|
| 1 | +import {getArrowTableSchema} from "./arrow.mjs"; |
1 | 2 | import {arrow9 as arrow, duckdb} from "./dependencies.mjs"; |
2 | 3 | import {FileAttachment} from "./fileAttachment.mjs"; |
3 | 4 |
|
@@ -42,22 +43,17 @@ export class DuckDBClient { |
42 | 43 |
|
43 | 44 | async queryStream(query, params) { |
44 | 45 | const connection = await this._db.connect(); |
45 | | - let reader, schema, batch; |
| 46 | + let reader, batch; |
46 | 47 | try { |
47 | 48 | reader = await connection.send(query, params); |
48 | 49 | batch = await reader.next(); |
49 | 50 | if (batch.done) throw new Error("missing first batch"); |
50 | | - schema = batch.value.schema; |
51 | 51 | } catch (error) { |
52 | 52 | await connection.close(); |
53 | 53 | throw error; |
54 | 54 | } |
55 | 55 | return { |
56 | | - schema: schema.fields.map(({name, type}) => ({ |
57 | | - name, |
58 | | - type: getType(String(type)), |
59 | | - databaseType: String(type) |
60 | | - })), |
| 56 | + schema: getArrowTableSchema(batch.value), |
61 | 57 | async *readRows() { |
62 | 58 | try { |
63 | 59 | while (!batch.done) { |
@@ -113,13 +109,12 @@ export class DuckDBClient { |
113 | 109 |
|
114 | 110 | async describeColumns({table} = {}) { |
115 | 111 | const columns = await this.query(`DESCRIBE ${table}`); |
116 | | - return columns.map(({column_name, column_type}) => { |
117 | | - return { |
118 | | - name: column_name, |
119 | | - type: getType(column_type), |
120 | | - databaseType: column_type |
121 | | - }; |
122 | | - }); |
| 112 | + return columns.map(({column_name, column_type, null: nullable}) => ({ |
| 113 | + name: column_name, |
| 114 | + type: getDuckDBType(column_type), |
| 115 | + nullable: nullable !== "NO", |
| 116 | + databaseType: column_type |
| 117 | + })); |
123 | 118 | } |
124 | 119 |
|
125 | 120 | static async of(sources = {}, config = {}) { |
@@ -227,67 +222,37 @@ async function loadArrow() { |
227 | 222 | return await import(`${cdn}${arrow.resolve()}`); |
228 | 223 | } |
229 | 224 |
|
230 | | -function getType(type) { |
231 | | - switch (type.toLowerCase()) { |
232 | | - case "bigint": |
233 | | - case "int8": |
234 | | - case "long": |
| 225 | +// https://duckdb.org/docs/sql/data_types/overview |
| 226 | +function getDuckDBType(type) { |
| 227 | + switch (type) { |
| 228 | + case "BIGINT": |
| 229 | + case "HUGEINT": |
| 230 | + case "UBIGINT": |
235 | 231 | return "bigint"; |
236 | | - |
237 | | - case "double": |
238 | | - case "float8": |
239 | | - case "numeric": |
240 | | - case "decimal": |
241 | | - case "decimal(s, p)": |
242 | | - case "real": |
243 | | - case "float4": |
244 | | - case "float": |
245 | | - case "float32": |
246 | | - case "float64": |
| 232 | + case "DOUBLE": |
| 233 | + case "REAL": |
247 | 234 | return "number"; |
248 | | - |
249 | | - case "hugeint": |
250 | | - case "integer": |
251 | | - case "smallint": |
252 | | - case "tinyint": |
253 | | - case "ubigint": |
254 | | - case "uinteger": |
255 | | - case "usmallint": |
256 | | - case "utinyint": |
257 | | - case "int4": |
258 | | - case "int": |
259 | | - case "signed": |
260 | | - case "int2": |
261 | | - case "short": |
262 | | - case "int1": |
263 | | - case "int64": |
264 | | - case "int32": |
| 235 | + case "INTEGER": |
| 236 | + case "SMALLINT": |
| 237 | + case "TINYINT": |
| 238 | + case "USMALLINT": |
| 239 | + case "UINTEGER": |
| 240 | + case "UTINYINT": |
265 | 241 | return "integer"; |
266 | | - |
267 | | - case "boolean": |
268 | | - case "bool": |
269 | | - case "logical": |
| 242 | + case "BOOLEAN": |
270 | 243 | return "boolean"; |
271 | | - |
272 | | - case "date": |
273 | | - case "interval": // date or time delta |
274 | | - case "time": |
275 | | - case "timestamp": |
276 | | - case "timestamp with time zone": |
277 | | - case "datetime": |
278 | | - case "timestamptz": |
279 | | - case "date64<millisecond>": |
| 244 | + case "DATE": |
| 245 | + case "TIMESTAMP": |
| 246 | + case "TIMESTAMP WITH TIME ZONE": |
280 | 247 | return "date"; |
281 | | - |
282 | | - case "uuid": |
283 | | - case "varchar": |
284 | | - case "char": |
285 | | - case "bpchar": |
286 | | - case "text": |
287 | | - case "string": |
288 | | - case "utf8": // this type is unlisted in the `types`, but is returned by the db as `column_type`... |
| 248 | + case "VARCHAR": |
| 249 | + case "UUID": |
289 | 250 | return "string"; |
| 251 | + // case "BLOB": |
| 252 | + // case "INTERVAL": |
| 253 | + // case "TIME": |
290 | 254 | default: |
| 255 | + if (/^DECIMAL\(/.test(type)) return "integer"; |
291 | 256 | return "other"; |
292 | 257 | } |
293 | 258 | } |
0 commit comments