From 0745298257c781e2f4202e6ddec8078bb8e06096 Mon Sep 17 00:00:00 2001 From: jasinco Date: Fri, 25 Apr 2025 11:45:55 +0800 Subject: [PATCH] postgres_cursor add --- bun.lockb | Bin 38103 -> 38474 bytes justfile | 4 ++ package.json | 1 + src/app/page.tsx | 3 +- src/app/post.tsx | 60 ++++++++++++------------- src/db.ts | 112 ++++++++++++++++++++++++++-------------------- tools/gen_fake.ts | 15 +++++++ tools/post_db.ts | 13 ++++++ tsconfig.json | 5 ++- 9 files changed, 131 insertions(+), 82 deletions(-) mode change 100644 => 100755 bun.lockb create mode 100644 justfile create mode 100644 tools/gen_fake.ts create mode 100644 tools/post_db.ts diff --git a/bun.lockb b/bun.lockb old mode 100644 new mode 100755 index fababebaf53c4a54ea9c358c85098a8b994543fd..dc222f17e3f920d34404b82647568c307130e19e GIT binary patch delta 5424 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 delta 5129 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 G@P7hRe&iYe diff --git a/justfile b/justfile new file mode 100644 index 0000000..693ee5b --- /dev/null +++ b/justfile @@ -0,0 +1,4 @@ +fake: + POSTGRES_URL="postgres://test:test@192.168.50.14:5432/posts" bun run ./tools/gen_fake.ts +fetch_post: + POSTGRES_URL="postgres://test:test@192.168.50.14:5432/posts" bun run ./tools/post_db.ts diff --git a/package.json b/package.json index 3b19ef7..39569f4 100644 --- a/package.json +++ b/package.json @@ -9,6 +9,7 @@ "lint": "next lint" }, "dependencies": { + "@faker-js/faker": "^9.7.0", "bun-types": "^1.2.9", "next": "15.3.0", "react": "^19.0.0", diff --git a/src/app/page.tsx b/src/app/page.tsx index 25af71e..6cb854d 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -1,4 +1,3 @@ -import { retrieve_post } from "@/db"; export default function Home() { @@ -8,7 +7,7 @@ export default function Home() {

匿名中工

- +
); diff --git a/src/app/post.tsx b/src/app/post.tsx index 4f0ea0f..3b43cfd 100644 --- a/src/app/post.tsx +++ b/src/app/post.tsx @@ -1,35 +1,35 @@ import { Suspense } from "react"; import Image from "next/image"; -import { Attachment } from "@/db"; +import { Attachment, MultiMediaType } from "@/db"; export default function Post(post_content: string, attachments: Attachment[]) { - let images = []; - let videos = []; - attachments.forEach(attachment => { - if (attachment.type.type == "video") { - attachment.urls.forEach(url => { - videos.push( - 加載中

}> - -
- ) - }) - }else if (attachment.type.type="image"){ - attachment.urls.forEach(url => { - images.push(Uploaded) - }) - } - }) - return (
-
- {post_content} -
-
-
-
-
) -} \ No newline at end of file + let images = []; + let videos = []; + attachments.forEach(attachment => { + if (attachment.type == MultiMediaType.video) { + attachment.urls.forEach(url => { + videos.push( + 加載中

}> + +
+ ) + }) + } else if (attachment.type == MultiMediaType.image) { + attachment.urls.forEach(url => { + images.push(Uploaded) + }) + } + }) + return (
+
+ {post_content} +
+
+
+
+
) +} diff --git a/src/db.ts b/src/db.ts index a31fb47..af1b730 100644 --- a/src/db.ts +++ b/src/db.ts @@ -1,57 +1,73 @@ -import { main } from "bun"; -import { sql } from "bun"; -import { MIMEType } from "util" +import { env, ReservedSQL, sql } from 'bun' +import { MIMEType } from 'util'; + +export enum MultiMediaType { + video, image +} export interface Attachment { - type: MIMEType; - urls: string[]; -} + urls: string[], + type: MultiMediaType +}; + export interface Post { - content: string, + post: string, + post_time: string, hash: string, + attachments: Attachment[], +} +interface SQLPostCast { + hash: string, post: string, post_time: string, images: number[] +}; +const SQLPostCast2Post = (obj: SQLPostCast) => { + let x: Post = + { + post: obj.post, + hash: obj.hash, + post_time: obj.post_time, + attachments: [] + }; + if (obj.images && obj.images.length > 0) { + x.attachments.push( + { + type: MultiMediaType.image, urls: obj.images.map(img => { + return `/img/${obj.hash}_${img}` + }) + } + ) + } + return x } -export async function setup_func() { - const rows = await sql` - CREATE OR REPLACE FUNCTION fetch_post( - OUT p_text VARCHAR(1000), - OUT p_hash CHAR(32), - OUT p_date TIMESTAMP, - OUT p_pics INT[] - ) - RETURNS SETOF RECORD AS - $$ - DECLARE - post_cursor CURSOR FOR - SELECT content, hash, date - FROM posts; - post_record RECORD; - BEGIN - -- Open cursor - OPEN post_cursor; - - -- Fetch rows and return - LOOP - FETCH NEXT FROM post_cursor INTO post_record; - EXIT WHEN NOT FOUND; - - p_text = post_record.content; - p_date = post_record.date; - p_hash = post_record.hash; - RETURN NEXT; - END LOOP; - - -- Close cursor - CLOSE post_cursor; - END; - $$ - LANGUAGE PLPGSQL;`; +export interface Cursor { + hash: string, + post_time: string, } -/* retrieve the latest post with posts table */ -export async function retrieve_post(offset: Number) { - const res = await sql`SELECT * FROM fetch_post();` - console.log(res) + +export class PostFetcher { + conn: Promise; + constructor() { + this.conn = sql.reserve(); + } + async init() { + await this.conn.then(async e => { + await e`DECLARE post_ptr CURSOR WITH HOLD FOR SELECT niming.posts.*, niming.images.file_sequence + AS images FROM niming.posts + LEFT JOIN niming.images ON niming.images.hash=niming.posts.hash ORDER BY niming.posts.post_time DESC, niming.posts.hash ASC` + }).catch(err => { + console.log(err); + }) + } + + async postgres_fetch() { + let x: SQLPostCast[] = [] + if (this.conn) { + x = await (await this.conn)`FETCH 10 IN post_ptr`; + } + return x.map(e => { + return SQLPostCast2Post(e) + }) + } } -setup_func() -retrieve_post(0) \ No newline at end of file + diff --git a/tools/gen_fake.ts b/tools/gen_fake.ts new file mode 100644 index 0000000..61af1d6 --- /dev/null +++ b/tools/gen_fake.ts @@ -0,0 +1,15 @@ +import { CryptoHasher, sql } from "bun"; +import { retrieve_post, setup_func } from "@/db"; +import { faker } from '@faker-js/faker'; + +for (let i = 0; i < 100; i++) { + + let text = faker.string.alpha(20); + let hash = new CryptoHasher("sha256") + hash.update(text) + hash.update(Date.now().toString()) + let dg = hash.digest("hex") + console.log(dg) + const _ = await sql`INSERT INTO niming.posts (hash, post,post_time) VALUES (${dg},${text}, now())` +} + diff --git a/tools/post_db.ts b/tools/post_db.ts new file mode 100644 index 0000000..d33303a --- /dev/null +++ b/tools/post_db.ts @@ -0,0 +1,13 @@ +import { PostFetcher, Post } from "@/db" +import { sql } from "bun"; + +let x: Post[] = []; +const fetcher = new PostFetcher(); +await fetcher.init() + +for (let i = 0; i < 10; i++) { + x = await fetcher.postgres_fetch() + + console.log(x) + +} diff --git a/tsconfig.json b/tsconfig.json index c133409..3f26a4b 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -8,7 +8,7 @@ "noEmit": true, "esModuleInterop": true, "module": "esnext", - "moduleResolution": "bundler", + "moduleResolution": "Bundler", "resolveJsonModule": true, "isolatedModules": true, "jsx": "preserve", @@ -20,7 +20,8 @@ ], "paths": { "@/*": ["./src/*"] - } + }, + "types":["bun-types"] }, "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"], "exclude": ["node_modules"]