From 46fa92d475bbe1ff166eb5dc2c9667f653d94e67 Mon Sep 17 00:00:00 2001 From: "Visal .In" Date: Sat, 6 Apr 2024 08:07:27 +0700 Subject: [PATCH] feat: add big number support for local connection (#78) --- src/app/client/[[...driver]]/page-client.tsx | 2 +- .../client/s/[[...driver]]/page-client.tsx | 2 +- src/components/query-result-table.tsx | 52 ++++++++++++++----- src/drivers/base-driver.ts | 4 ++ src/drivers/remote-driver.ts | 4 ++ src/drivers/rqlite-driver.ts | 4 ++ src/drivers/turso-driver.tsx | 9 +++- 7 files changed, 62 insertions(+), 15 deletions(-) diff --git a/src/app/client/[[...driver]]/page-client.tsx b/src/app/client/[[...driver]]/page-client.tsx index 563304ce..d2ffea31 100644 --- a/src/app/client/[[...driver]]/page-client.tsx +++ b/src/app/client/[[...driver]]/page-client.tsx @@ -21,7 +21,7 @@ export default function ClientPageBody() { if (config.driver === "rqlite") { return new RqliteDriver(config.url, config.username, config.password); } - return new TursoDriver(config.url, config.token as string); + return new TursoDriver(config.url, config.token as string, true); }, []); const config = useMemo(() => { diff --git a/src/app/client/s/[[...driver]]/page-client.tsx b/src/app/client/s/[[...driver]]/page-client.tsx index ebce2ba4..4eabdebb 100644 --- a/src/app/client/s/[[...driver]]/page-client.tsx +++ b/src/app/client/s/[[...driver]]/page-client.tsx @@ -29,7 +29,7 @@ export default function ClientPageBody() { ); } - return new TursoDriver(conn.config.url, conn.config.token); + return new TursoDriver(conn.config.url, conn.config.token, true); }, [conn]); if (!driver || !conn) { diff --git a/src/components/query-result-table.tsx b/src/components/query-result-table.tsx index 72394b57..c28db6a4 100644 --- a/src/components/query-result-table.tsx +++ b/src/components/query-result-table.tsx @@ -34,6 +34,8 @@ import { } from "./ui/dropdown-menu"; import { triggerSelectFiles, uploadFile } from "@/lib/file-upload"; import { toast } from "sonner"; +import { useDatabaseDriver } from "@/context/DatabaseDriverProvider"; +import BigNumberCell from "./table-cell/BigNumberCell"; interface ResultTableProps { data: OptimizeTableState; @@ -91,6 +93,7 @@ export default function ResultTable({ }: ResultTableProps) { const [stickyHeaderIndex, setStickHeaderIndex] = useState(); const { openBlockEditor } = useBlockEditor(); + const { databaseDriver } = useDatabaseDriver(); const renderHeader = useCallback( (header: OptimizeTableHeaderWithIndexProps) => { @@ -99,7 +102,7 @@ export default function ResultTable({ { setStickHeaderIndex( - header.index === stickyHeaderIndex ? undefined : header.index, + header.index === stickyHeaderIndex ? undefined : header.index ); }} > @@ -132,7 +135,7 @@ export default function ResultTable({ ); }, - [stickyHeaderIndex, tableName, onSortColumnChange], + [stickyHeaderIndex, tableName, onSortColumnChange] ); const renderCell = useCallback( @@ -161,10 +164,7 @@ export default function ResultTable({ }} /> ); - } else if ( - header.dataType === TableColumnDataType.REAL || - header.dataType === TableColumnDataType.INTEGER - ) { + } else if (header.dataType === TableColumnDataType.REAL) { return ( ); + } else if (header.dataType === TableColumnDataType.INTEGER) { + if (databaseDriver.supportBigInt()) { + return ( + } + focus={isFocus} + isChanged={state.hasCellChange(y, x)} + onChange={(newValue) => { + state.changeValue(y, x, newValue); + }} + /> + ); + } else { + return ( + } + focus={isFocus} + isChanged={state.hasCellChange(y, x)} + onChange={(newValue) => { + state.changeValue(y, x, newValue); + }} + /> + ); + } } return ; }, - [], + [databaseDriver] ); const onHeaderContextMenu = useCallback((e: React.MouseEvent) => { @@ -339,7 +367,7 @@ export default function ResultTable({ onClick: () => { if (state.getSelectedRowCount() > 0) { window.navigator.clipboard.writeText( - exportRowsToExcel(state.getSelectedRowsArray()), + exportRowsToExcel(state.getSelectedRowsArray()) ); } }, @@ -356,8 +384,8 @@ export default function ResultTable({ exportRowsToSqlInsert( tableName ?? "UnknownTable", headers, - state.getSelectedRowsArray(), - ), + state.getSelectedRowsArray() + ) ); } }, @@ -381,7 +409,7 @@ export default function ResultTable({ }, ])(event); }, - [data, tableName, copyCallback, pasteCallback, openBlockEditor], + [data, tableName, copyCallback, pasteCallback, openBlockEditor] ); const onKeyDown = useCallback( @@ -435,7 +463,7 @@ export default function ResultTable({ e.preventDefault(); }, - [copyCallback, pasteCallback], + [copyCallback, pasteCallback] ); return ( diff --git a/src/drivers/base-driver.ts b/src/drivers/base-driver.ts index 35ac78a8..a9267669 100644 --- a/src/drivers/base-driver.ts +++ b/src/drivers/base-driver.ts @@ -134,6 +134,10 @@ export interface DatabaseTableOperationReslt { } export abstract class BaseDriver { + // Flags + abstract supportBigInt(): boolean; + + // Methods abstract close(): void; abstract query(stmt: InStatement): Promise; diff --git a/src/drivers/remote-driver.ts b/src/drivers/remote-driver.ts index b876094e..6f59602a 100644 --- a/src/drivers/remote-driver.ts +++ b/src/drivers/remote-driver.ts @@ -25,6 +25,10 @@ export default class RemoteDriver implements BaseDriver { this.authToken = authToken; } + supportBigInt(): boolean { + return false; + } + protected async request(body: RequestOperationBody) { const r = await fetch(`/api/ops/${this.id}`, { method: "POST", diff --git a/src/drivers/rqlite-driver.ts b/src/drivers/rqlite-driver.ts index 366d3269..1df53b6d 100644 --- a/src/drivers/rqlite-driver.ts +++ b/src/drivers/rqlite-driver.ts @@ -95,6 +95,10 @@ export default class RqliteDriver extends SqliteLikeBaseDriver { return json.results.map(transformRawResult); } + supportBigInt(): boolean { + return false; + } + async query(stmt: InStatement): Promise { return (await this.transaction([stmt]))[0]; } diff --git a/src/drivers/turso-driver.tsx b/src/drivers/turso-driver.tsx index de720d00..1f7fbd4d 100644 --- a/src/drivers/turso-driver.tsx +++ b/src/drivers/turso-driver.tsx @@ -41,18 +41,25 @@ export default class TursoDriver extends SqliteLikeBaseDriver { protected client: Client; protected endpoint: string = ""; protected authToken = ""; + protected bigInt = false; - constructor(url: string, authToken: string) { + constructor(url: string, authToken: string, bigInt: boolean = false) { super(); this.endpoint = url; this.authToken = authToken; + this.bigInt = bigInt; this.client = createClient({ url: this.endpoint, authToken: this.authToken, + intMode: bigInt ? "bigint" : "number", }); } + supportBigInt(): boolean { + return this.bigInt; + } + async query(stmt: InStatement) { const stream = this.client; const r = await stream.execute(stmt);