docs(duckdb-wasm|drizzle-duckdb-wasm): added documentations and descriptions
This commit is contained in:
@@ -41,42 +41,42 @@ export const users = pgTable('users', () => ({
|
||||
drizzle-kit generate
|
||||
```
|
||||
|
||||
```vue
|
||||
```html
|
||||
<!-- ./src/App.vue -->
|
||||
<script setup lang="ts">
|
||||
import type { DuckDBWasmDrizzleDatabase } from '@proj-airi/drizzle-duckdb-wasm'
|
||||
import type { DuckDBWasmDrizzleDatabase } from '@proj-airi/drizzle-duckdb-wasm'
|
||||
|
||||
import { drizzle } from '@proj-airi/drizzle-duckdb-wasm'
|
||||
import { getImportUrlBundles } from '@proj-airi/drizzle-duckdb-wasm/bundles/import-url-browser'
|
||||
import { useDebounceFn } from '@vueuse/core'
|
||||
import { serialize } from 'superjson'
|
||||
import { onMounted, onUnmounted, ref, watch } from 'vue'
|
||||
import { drizzle } from '@proj-airi/drizzle-duckdb-wasm'
|
||||
import { getImportUrlBundles } from '@proj-airi/drizzle-duckdb-wasm/bundles/import-url-browser'
|
||||
import { useDebounceFn } from '@vueuse/core'
|
||||
import { serialize } from 'superjson'
|
||||
import { onMounted, onUnmounted, ref, watch } from 'vue'
|
||||
|
||||
import * as schema from './db/schema'
|
||||
import { users } from './db/schema'
|
||||
import migration1 from './drizzle/0000_cute_kulan_gath.sql?raw'
|
||||
import * as schema from './db/schema'
|
||||
import { users } from './db/schema'
|
||||
import migration1 from './drizzle/0000_cute_kulan_gath.sql?raw'
|
||||
|
||||
const results = ref<any[]>([])
|
||||
const results = ref<any[]>([])
|
||||
|
||||
onMounted(async () => {
|
||||
// db.value = drizzle('duckdb-wasm://?bundles=import-url', { schema })
|
||||
// db.value = drizzle({ connection: { bundles: getImportUrlBundles() } }, { schema })
|
||||
onMounted(async () => {
|
||||
// db.value = drizzle('duckdb-wasm://?bundles=import-url', { schema })
|
||||
// db.value = drizzle({ connection: { bundles: getImportUrlBundles() } }, { schema })
|
||||
|
||||
await db.value?.execute(migration1)
|
||||
results.value = await db.value?.execute('SELECT count(*)::INTEGER as v FROM generate_series(0, 100) t(v)')
|
||||
console.log(results.value) // Output [{ v: 101 }]
|
||||
await db.value?.execute(migration1)
|
||||
results.value = await db.value?.execute('SELECT count(*)::INTEGER as v FROM generate_series(0, 100) t(v)')
|
||||
console.log(results.value) // Output [{ v: 101 }]
|
||||
|
||||
await db.value.insert(users).values({ id: '00000000-0000-0000-0000-000000000000' })
|
||||
const foundUsers = await db.value.select().from(users)
|
||||
console.log(foundUsers) // Output [{ id: '00000000-0000-0000-0000-000000000000' }]
|
||||
})
|
||||
await db.value.insert(users).values({ id: '00000000-0000-0000-0000-000000000000' })
|
||||
const foundUsers = await db.value.select().from(users)
|
||||
console.log(foundUsers) // Output [{ id: '00000000-0000-0000-0000-000000000000' }]
|
||||
})
|
||||
|
||||
onUnmounted(async () => {
|
||||
if (db.value) {
|
||||
const client = await db.value.$client
|
||||
await client.close()
|
||||
}
|
||||
})
|
||||
onUnmounted(async () => {
|
||||
if (db.value) {
|
||||
const client = await db.value.$client
|
||||
await client.close()
|
||||
}
|
||||
})
|
||||
</script>
|
||||
```
|
||||
|
||||
@@ -133,3 +133,7 @@ async function main() {
|
||||
await client.close()
|
||||
}
|
||||
```
|
||||
|
||||
## Footnotes
|
||||
|
||||
Check out [the package](https://github.com/moeru-ai/airi/tree/main/packages/duckdb-wasm/README.md) we made for easier call to `@duckdb/duckdb-wasm` as well!
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
import type { DuckDBWasmClient } from '@proj-airi/duckdb-wasm'
|
||||
import type { Schema, StructRow } from 'apache-arrow'
|
||||
import type { Assume, Logger, Query, RelationalSchemaConfig, TablesRelationalConfig } from 'drizzle-orm'
|
||||
import type { PgDialect, PgQueryResultHKT, PgTransactionConfig, PreparedQueryConfig, SelectedFieldsOrdered } from 'drizzle-orm/pg-core'
|
||||
|
||||
import { beginTransaction, mapColumnData, withSavepoint } from '@proj-airi/duckdb-wasm'
|
||||
import { beginTransaction, withSavepoint } from '@proj-airi/duckdb-wasm'
|
||||
import { entityKind, fillPlaceholders, NoopLogger } from 'drizzle-orm'
|
||||
import { PgPreparedQuery, PgSession, PgTransaction } from 'drizzle-orm/pg-core'
|
||||
|
||||
@@ -11,36 +10,6 @@ export type Row = Record<string, any>
|
||||
|
||||
export type RowList<T extends Row[]> = T
|
||||
|
||||
function toJSRepresentedRows<T extends { toArray: () => StructRow[], schema: Schema }>(results: T) {
|
||||
const rows = (results.toArray() as StructRow[] || []).map(item => item.toJSON()) || []
|
||||
|
||||
const jsRepresentedRows = rows.map((row) => {
|
||||
results.schema.fields.forEach((field) => {
|
||||
return row[field.name] = mapColumnData(row[field.name], field)
|
||||
})
|
||||
|
||||
return row
|
||||
})
|
||||
|
||||
return jsRepresentedRows
|
||||
}
|
||||
|
||||
async function callQuery(client: Promise<DuckDBWasmClient>, query: string, params: unknown[]) {
|
||||
const c = await client
|
||||
|
||||
if (!params || params.length === 0) {
|
||||
const results = await c.conn.query(query)
|
||||
return toJSRepresentedRows(results)
|
||||
}
|
||||
|
||||
const stmt = await c.conn.prepare(query)
|
||||
const results = await stmt.query(...params)
|
||||
const rows = toJSRepresentedRows(results)
|
||||
|
||||
stmt.close()
|
||||
return rows
|
||||
}
|
||||
|
||||
export class DuckDBWASMPreparedQuery<T extends PreparedQueryConfig> extends PgPreparedQuery<T> {
|
||||
static override readonly [entityKind]: string = 'DuckDBWasmPreparedQuery'
|
||||
|
||||
@@ -60,17 +29,21 @@ export class DuckDBWASMPreparedQuery<T extends PreparedQueryConfig> extends PgPr
|
||||
this.logger.logQuery(this.queryString, params)
|
||||
|
||||
const { fields, queryString: query, client, customResultMapper } = this
|
||||
const c = await client
|
||||
|
||||
if (!fields && !customResultMapper) {
|
||||
return callQuery(client, query, params)
|
||||
return c.query(query, params)
|
||||
}
|
||||
|
||||
return callQuery(client, query, params)
|
||||
return c.query(query, params)
|
||||
}
|
||||
|
||||
async all(placeholderValues: Record<string, unknown> | undefined = {}): Promise<T['all']> {
|
||||
const params = fillPlaceholders(this.params, placeholderValues)
|
||||
this.logger.logQuery(this.queryString, params)
|
||||
return callQuery(this.client, this.queryString, params)
|
||||
|
||||
const c = await this.client
|
||||
return c.query(this.queryString, params)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -116,7 +89,8 @@ export class DuckDBWasmSession<
|
||||
|
||||
async query(query: string, params: unknown[]): Promise<RowList<Row[]>> {
|
||||
this.logger.logQuery(query, params)
|
||||
return callQuery(this.client, query, params)
|
||||
const c = await this.client
|
||||
return c.query(query, params)
|
||||
}
|
||||
|
||||
async queryObjects<T extends Row>(
|
||||
@@ -124,7 +98,8 @@ export class DuckDBWasmSession<
|
||||
params: unknown[],
|
||||
): Promise<RowList<T[]>> {
|
||||
this.logger.logQuery(query, params)
|
||||
return callQuery(this.client, query, params) as Promise<RowList<T[]>>
|
||||
const c = await this.client
|
||||
return c.query(query, params) as Promise<RowList<T[]>>
|
||||
}
|
||||
|
||||
override transaction<T>(
|
||||
|
||||
@@ -17,25 +17,25 @@ npm i @proj-airi/duckdb-wasm -D
|
||||
|
||||
### Browser
|
||||
|
||||
```vue
|
||||
```html
|
||||
<script setup lang="ts">
|
||||
import type { DuckDBWasmClient } from '@proj-airi/duckdb-wasm'
|
||||
import type { DuckDBWasmClient } from '@proj-airi/duckdb-wasm'
|
||||
|
||||
import { connect, getEnvironment } from '@proj-airi/duckdb-wasm'
|
||||
import { getImportUrlBundles } from '@proj-airi/duckdb-wasm/bundles/import-url-browser'
|
||||
import { onMounted, onUnmounted, ref } from 'vue'
|
||||
import { connect, getEnvironment } from '@proj-airi/duckdb-wasm'
|
||||
import { getImportUrlBundles } from '@proj-airi/duckdb-wasm/bundles/import-url-browser'
|
||||
import { onMounted, onUnmounted, ref } from 'vue'
|
||||
|
||||
const db = ref<DuckDBWasmClient>()
|
||||
const db = ref<DuckDBWasmClient>()
|
||||
|
||||
onMounted(async () => {
|
||||
db.value = await connect({ bundles: getImportUrlBundles })
|
||||
const result = await db.value.conn.query('SELECT 1 + 1 AS res')
|
||||
console.log(result) // Output: [{ res: 2 }]
|
||||
})
|
||||
onMounted(async () => {
|
||||
db.value = await connect({ bundles: getImportUrlBundles })
|
||||
const result = await db.value.conn.query('SELECT 1 + 1 AS res')
|
||||
console.log(result) // Output: [{ res: 2 }]
|
||||
})
|
||||
|
||||
onUnmounted(() => {
|
||||
db.value?.close()
|
||||
})
|
||||
onUnmounted(() => {
|
||||
db.value?.close()
|
||||
})
|
||||
</script>
|
||||
```
|
||||
|
||||
@@ -62,3 +62,7 @@ async function main() {
|
||||
await close()
|
||||
}
|
||||
```
|
||||
|
||||
## Footnotes
|
||||
|
||||
Check out the [Drizzle ORM driver](https://github.com/moeru-ai/airi/blob/main/packages/drizzle-duckdb-wasm/README.md) we made for `@duckdb/duckdb-wasm` as welL!
|
||||
|
||||
@@ -36,6 +36,4 @@ export async function getEnvironment() {
|
||||
catch {
|
||||
return 'unknown'
|
||||
}
|
||||
|
||||
return 'unknown'
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import { AsyncDuckDB, ConsoleLogger, selectBundle, VoidLogger } from '@duckdb/du
|
||||
import { defu } from 'defu'
|
||||
|
||||
import { getEnvironment } from './common'
|
||||
import { mapStructRowData } from './format'
|
||||
|
||||
export type ConnectOptions = ConnectRequiredOptions & ConnectOptionalOptions
|
||||
|
||||
@@ -21,6 +22,7 @@ export interface DuckDBWasmClient {
|
||||
db: AsyncDuckDB
|
||||
conn: AsyncDuckDBConnection
|
||||
close: () => Promise<void>
|
||||
query: (string, params?: unknown[]) => Promise<Record<string, unknown>[]>
|
||||
}
|
||||
|
||||
export async function connect(options: ConnectOptions): Promise<DuckDBWasmClient> {
|
||||
@@ -79,6 +81,19 @@ export async function connect(options: ConnectOptions): Promise<DuckDBWasmClient
|
||||
worker,
|
||||
db,
|
||||
conn,
|
||||
query: async (query: string, params: unknown[] = []) => {
|
||||
if (!params || params.length === 0) {
|
||||
const results = await conn.query(query)
|
||||
return mapStructRowData(results)
|
||||
}
|
||||
|
||||
const stmt = await conn.prepare(query)
|
||||
const results = await stmt.query(...params)
|
||||
const rows = mapStructRowData(results)
|
||||
|
||||
stmt.close()
|
||||
return rows
|
||||
},
|
||||
close: async () => {
|
||||
await conn.close()
|
||||
await db.terminate()
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import type { TZDate } from '@date-fns/tz'
|
||||
import type { Field, StructRow } from 'apache-arrow'
|
||||
import type { Field, Schema, StructRow } from 'apache-arrow'
|
||||
import type { DataType } from './types'
|
||||
|
||||
import { TZDateMini } from '@date-fns/tz'
|
||||
@@ -605,3 +605,17 @@ export function mapColumnData<T = unknown>(x: DataType, field?: Field): T {
|
||||
|
||||
return String(x) as T
|
||||
}
|
||||
|
||||
export function mapStructRowData<T extends { toArray: () => StructRow[], schema: Schema }>(results: T) {
|
||||
const rows = (results.toArray() as StructRow[] || []).map(item => item.toJSON()) || []
|
||||
|
||||
const jsRepresentedRows = rows.map((row) => {
|
||||
results.schema.fields.forEach((field) => {
|
||||
return row[field.name] = mapColumnData(row[field.name], field)
|
||||
})
|
||||
|
||||
return row
|
||||
})
|
||||
|
||||
return jsRepresentedRows
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user