|
| 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