SQL literal#176
Conversation
| cache: Map<SqlFragment | SqlVariant, unknown> | ||
| ): unknown { | ||
| let v: unknown; | ||
| if (dialect !== undefined && dialect in variant.variants) v = variant.variants[dialect]; |
There was a problem hiding this comment.
This addition of dialect !== undefined is for type safety more than runtime behavior.
|
|
||
| /** @see https://observablehq.com/@observablehq/database-client-specification#%C2%A71 */ | ||
| export type QueryResult = Record<string, any>[] & {schema: ColumnSchema[]; date: Date}; | ||
| export type QueryResult<T = Record<string, any>> = T[] & {schema: ColumnSchema[]; date: Date}; |
There was a problem hiding this comment.
Do we want to remove the date from here?
Also this type does not cover a resultset that would come back as an arrow table. Are we going to convert to arrow later, from the array of objects?
An idea could be to add a format="arrow" | "json" property on sql cells, that would default to JSON (the current format); if you pass "arrow" a database handler that has this capability creates arrow immediately; any other gets converted to arrow.
There was a problem hiding this comment.
This should go away entirely to be replaced with Arrow.Table.
| ) | ||
| ); | ||
| }); | ||
| test("chains a view into a recursive query (flight reachability)", () => { |
There was a problem hiding this comment.
| readonly name: string; | ||
| readonly options: QueryOptions; | ||
| sql(strings: readonly string[], ...params: QueryParam[]): Promise<QueryResult>; | ||
| readonly dialect?: SqlDialect; |
There was a problem hiding this comment.
TODO DatabaseClientImpl constructor needs to take a dialect.
There was a problem hiding this comment.
I've tried to implement this (together with binding to a database) in #177.
| return (await response.json().then(revive)) as QueryResult<T>; | ||
| } | ||
| async cachePath(strings: readonly string[], ...params: QueryParam[]): Promise<string> { | ||
| return `.observable/cache/${await nameHash(this.name)}-${await hash(strings, ...params)}.json`; |
There was a problem hiding this comment.
| return `.observable/cache/${await nameHash(this.name)}-${await hash(strings, ...params)}.json`; | |
| return `.observable/cache/${await nameHash(this.name)}-${await hash(strings, ...params)}.arrow`; |
There was a problem hiding this comment.
btw should we Promise.all these two awaits?
| async sql(strings: readonly string[], ...params: QueryParam[]): Promise<QueryResult> { | ||
| async sql<T = Record<string, any>>(strings: readonly string[], ...params: QueryParam[]): Promise<QueryResult<T>> { | ||
| const path = await this.cachePath(strings, ...params); | ||
| const response = await fetch(path); |
There was a problem hiding this comment.
This’ll need to be something like…
const [Arrow, response] = await Promise.all([import("https://cdn.jsdelivr.net/npm/apache-arrow@17.0.0/+esm"), fetch(path)]); // prettier-ignore
if (!response.ok) throw new Error(`failed to fetch: ${path}`);
return Arrow.tableFromIPC(response);
https://linear.app/observable/issue/DEV-1662/sql-fragments
To do
!assertions