@sqlrooms/duckdb 0.0.3 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/__tests__/arrow-utils.test.d.ts +2 -0
- package/dist/__tests__/arrow-utils.test.d.ts.map +1 -0
- package/dist/__tests__/arrow-utils.test.js +186 -0
- package/dist/__tests__/sql-from.test.d.ts +2 -0
- package/dist/__tests__/sql-from.test.d.ts.map +1 -0
- package/dist/__tests__/sql-from.test.js +70 -0
- package/dist/duckdb.d.ts.map +1 -1
- package/package.json +5 -6
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"arrow-utils.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/arrow-utils.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
import * as arrow from 'apache-arrow';
|
|
2
|
+
import { arrowTableToJson } from '../arrow-utils';
|
|
3
|
+
/// TODO: Revise tests for nested objects once https://github.com/apache/arrow/issues/33394 is fixed
|
|
4
|
+
describe('arrow-utils', () => {
|
|
5
|
+
describe('arrowTableToJson', () => {
|
|
6
|
+
it('should convert Arrow table to JSON array', () => {
|
|
7
|
+
// Create a simple Arrow table
|
|
8
|
+
const data = [
|
|
9
|
+
{ id: 1n, name: 'John', score: 95.5 },
|
|
10
|
+
{ id: 2n, name: 'Jane', score: 88.0 },
|
|
11
|
+
];
|
|
12
|
+
const table = arrow.tableFromJSON(data);
|
|
13
|
+
const result = arrowTableToJson(table);
|
|
14
|
+
const expected = [
|
|
15
|
+
{ id: 1, name: 'John', score: 95.5 },
|
|
16
|
+
{ id: 2, name: 'Jane', score: 88.0 },
|
|
17
|
+
];
|
|
18
|
+
expect(result).toEqual(expected);
|
|
19
|
+
});
|
|
20
|
+
it('should handle large BigInt values', () => {
|
|
21
|
+
const largeNumber = 9007199254740991n; // Number.MAX_SAFE_INTEGER
|
|
22
|
+
const data = [
|
|
23
|
+
{ id: largeNumber, value: 'test' },
|
|
24
|
+
{ id: largeNumber + 1n, value: 'test2' },
|
|
25
|
+
];
|
|
26
|
+
const table = arrow.tableFromJSON(data);
|
|
27
|
+
const result = arrowTableToJson(table);
|
|
28
|
+
const expected = [
|
|
29
|
+
{ id: 9007199254740991, value: 'test' },
|
|
30
|
+
{ id: '9007199254740992', value: 'test2' }, // Beyond MAX_SAFE_INTEGER, should be string
|
|
31
|
+
];
|
|
32
|
+
expect(result).toEqual(expected);
|
|
33
|
+
});
|
|
34
|
+
it('should handle timestamps and dates', () => {
|
|
35
|
+
const timestamp = new Date('2024-02-05T12:30:45.123Z');
|
|
36
|
+
const date = new Date('2024-02-05');
|
|
37
|
+
const data = [
|
|
38
|
+
{
|
|
39
|
+
id: 1,
|
|
40
|
+
timestamp: timestamp,
|
|
41
|
+
date: date,
|
|
42
|
+
},
|
|
43
|
+
];
|
|
44
|
+
const table = arrow.tableFromJSON(data);
|
|
45
|
+
const result = arrowTableToJson(table);
|
|
46
|
+
expect(result).toEqual([
|
|
47
|
+
{
|
|
48
|
+
id: 1,
|
|
49
|
+
timestamp: timestamp.getTime(),
|
|
50
|
+
date: date.getTime(),
|
|
51
|
+
},
|
|
52
|
+
]);
|
|
53
|
+
});
|
|
54
|
+
it('should handle nested objects (structs)', () => {
|
|
55
|
+
/// TODO: Revise tests for nested objects once https://github.com/apache/arrow/issues/33394 is fixed
|
|
56
|
+
// For now, we'll use JSON strings for nested objects as Arrow's JS API
|
|
57
|
+
// doesn't seem to have a straightforward way to create struct types
|
|
58
|
+
const data = [
|
|
59
|
+
{
|
|
60
|
+
id: 1,
|
|
61
|
+
user: JSON.stringify({
|
|
62
|
+
name: 'John',
|
|
63
|
+
address: {
|
|
64
|
+
city: 'New York',
|
|
65
|
+
country: 'USA',
|
|
66
|
+
},
|
|
67
|
+
}),
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
id: 2,
|
|
71
|
+
user: JSON.stringify({
|
|
72
|
+
name: 'Jane',
|
|
73
|
+
address: {
|
|
74
|
+
city: 'London',
|
|
75
|
+
country: 'UK',
|
|
76
|
+
},
|
|
77
|
+
}),
|
|
78
|
+
},
|
|
79
|
+
];
|
|
80
|
+
const table = arrow.tableFromJSON(data);
|
|
81
|
+
const result = arrowTableToJson(table);
|
|
82
|
+
// Parse the JSON strings back to objects for comparison
|
|
83
|
+
const parsedResult = result.map((row) => ({
|
|
84
|
+
...row,
|
|
85
|
+
user: JSON.parse(row.user),
|
|
86
|
+
}));
|
|
87
|
+
expect(parsedResult).toEqual([
|
|
88
|
+
{
|
|
89
|
+
id: 1,
|
|
90
|
+
user: {
|
|
91
|
+
name: 'John',
|
|
92
|
+
address: {
|
|
93
|
+
city: 'New York',
|
|
94
|
+
country: 'USA',
|
|
95
|
+
},
|
|
96
|
+
},
|
|
97
|
+
},
|
|
98
|
+
{
|
|
99
|
+
id: 2,
|
|
100
|
+
user: {
|
|
101
|
+
name: 'Jane',
|
|
102
|
+
address: {
|
|
103
|
+
city: 'London',
|
|
104
|
+
country: 'UK',
|
|
105
|
+
},
|
|
106
|
+
},
|
|
107
|
+
},
|
|
108
|
+
]);
|
|
109
|
+
});
|
|
110
|
+
it('should handle arrays', () => {
|
|
111
|
+
// For now, we'll use JSON strings for arrays as Arrow's JS API
|
|
112
|
+
// doesn't seem to have a straightforward way to create list types
|
|
113
|
+
const data = [
|
|
114
|
+
{
|
|
115
|
+
id: 1,
|
|
116
|
+
tags: JSON.stringify(['a', 'b']),
|
|
117
|
+
scores: JSON.stringify([1, 2, 3]),
|
|
118
|
+
},
|
|
119
|
+
];
|
|
120
|
+
const table = arrow.tableFromJSON(data);
|
|
121
|
+
const result = arrowTableToJson(table);
|
|
122
|
+
// Parse the JSON strings back to arrays for comparison
|
|
123
|
+
const parsedResult = result.map((row) => ({
|
|
124
|
+
...row,
|
|
125
|
+
tags: JSON.parse(row.tags),
|
|
126
|
+
scores: JSON.parse(row.scores),
|
|
127
|
+
}));
|
|
128
|
+
expect(parsedResult).toEqual([
|
|
129
|
+
{
|
|
130
|
+
id: 1,
|
|
131
|
+
tags: ['a', 'b'],
|
|
132
|
+
scores: [1, 2, 3],
|
|
133
|
+
},
|
|
134
|
+
]);
|
|
135
|
+
});
|
|
136
|
+
it('should handle combination of structs, BigInts, and timestamps', () => {
|
|
137
|
+
const timestamp = new Date('2024-02-05T12:30:45.123Z');
|
|
138
|
+
// const largeNumber = 9007199254740991n; // MAX_SAFE_INTEGER
|
|
139
|
+
const largeNumber = 1;
|
|
140
|
+
// Create data with JSON strings for complex structures
|
|
141
|
+
const data = [
|
|
142
|
+
{
|
|
143
|
+
id: largeNumber,
|
|
144
|
+
created_at: timestamp,
|
|
145
|
+
metadata: JSON.stringify({
|
|
146
|
+
user: {
|
|
147
|
+
id: largeNumber, // + 1n,
|
|
148
|
+
name: 'John',
|
|
149
|
+
last_login: new Date('2024-01-01T00:00:00Z').getTime(),
|
|
150
|
+
stats: {
|
|
151
|
+
score: 95.5,
|
|
152
|
+
rank: largeNumber, // + 2n,
|
|
153
|
+
},
|
|
154
|
+
},
|
|
155
|
+
tags: ['active', 'premium'],
|
|
156
|
+
}),
|
|
157
|
+
},
|
|
158
|
+
];
|
|
159
|
+
const table = arrow.tableFromJSON(data);
|
|
160
|
+
const result = arrowTableToJson(table);
|
|
161
|
+
// Parse the JSON strings back to objects for comparison
|
|
162
|
+
const parsedResult = result.map((row) => ({
|
|
163
|
+
...row,
|
|
164
|
+
metadata: JSON.parse(row.metadata),
|
|
165
|
+
}));
|
|
166
|
+
expect(parsedResult).toEqual([
|
|
167
|
+
{
|
|
168
|
+
id: 1,
|
|
169
|
+
created_at: timestamp.getTime(),
|
|
170
|
+
metadata: {
|
|
171
|
+
user: {
|
|
172
|
+
id: 1,
|
|
173
|
+
name: 'John',
|
|
174
|
+
last_login: new Date('2024-01-01T00:00:00Z').getTime(),
|
|
175
|
+
stats: {
|
|
176
|
+
score: 95.5,
|
|
177
|
+
rank: 1,
|
|
178
|
+
},
|
|
179
|
+
},
|
|
180
|
+
tags: ['active', 'premium'],
|
|
181
|
+
},
|
|
182
|
+
},
|
|
183
|
+
]);
|
|
184
|
+
});
|
|
185
|
+
});
|
|
186
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sql-from.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/sql-from.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { sqlFrom, literalToSQL } from '../sql-from';
|
|
2
|
+
describe('sql-from', () => {
|
|
3
|
+
describe('literalToSQL', () => {
|
|
4
|
+
it('should convert numbers correctly', () => {
|
|
5
|
+
expect(literalToSQL(42)).toBe('42');
|
|
6
|
+
expect(literalToSQL(3.14)).toBe('3.14');
|
|
7
|
+
expect(literalToSQL(Infinity)).toBe('NULL');
|
|
8
|
+
expect(literalToSQL(NaN)).toBe('NULL');
|
|
9
|
+
});
|
|
10
|
+
it('should convert strings correctly', () => {
|
|
11
|
+
expect(literalToSQL('hello')).toBe("'hello'");
|
|
12
|
+
expect(literalToSQL("O'Neil")).toBe("'O''Neil'"); // Escapes single quotes
|
|
13
|
+
});
|
|
14
|
+
it('should convert booleans correctly', () => {
|
|
15
|
+
expect(literalToSQL(true)).toBe('TRUE');
|
|
16
|
+
expect(literalToSQL(false)).toBe('FALSE');
|
|
17
|
+
});
|
|
18
|
+
it('should convert dates correctly', () => {
|
|
19
|
+
const date = new Date('2024-02-05');
|
|
20
|
+
expect(literalToSQL(date)).toMatch(/^DATE '\d{4}-\d{1,2}-\d{1,2}'$/);
|
|
21
|
+
const timestamp = new Date('2024-02-05T12:30:00Z');
|
|
22
|
+
expect(literalToSQL(timestamp)).toMatch(/^epoch_ms\(\d+\)$/);
|
|
23
|
+
});
|
|
24
|
+
it('should handle null and undefined', () => {
|
|
25
|
+
expect(literalToSQL(null)).toBe('NULL');
|
|
26
|
+
expect(literalToSQL(undefined)).toBe('NULL');
|
|
27
|
+
});
|
|
28
|
+
it('should convert RegExp to string', () => {
|
|
29
|
+
expect(literalToSQL(/test/)).toBe("'test'");
|
|
30
|
+
});
|
|
31
|
+
});
|
|
32
|
+
describe('sqlFrom', () => {
|
|
33
|
+
it('should create SQL query from array of objects', () => {
|
|
34
|
+
const data = [
|
|
35
|
+
{ id: 1, name: 'John' },
|
|
36
|
+
{ id: 2, name: 'Jane' },
|
|
37
|
+
];
|
|
38
|
+
const result = sqlFrom(data);
|
|
39
|
+
expect(result).toBe('(SELECT 1 AS "id", \'John\' AS "name") ' +
|
|
40
|
+
'UNION ALL ' +
|
|
41
|
+
'(SELECT 2 AS "id", \'Jane\' AS "name")');
|
|
42
|
+
});
|
|
43
|
+
it('should handle custom column mapping', () => {
|
|
44
|
+
const data = [
|
|
45
|
+
{ id: 1, firstName: 'John' },
|
|
46
|
+
{ id: 2, firstName: 'Jane' },
|
|
47
|
+
];
|
|
48
|
+
const result = sqlFrom(data, {
|
|
49
|
+
columns: { id: 'user_id', firstName: 'name' },
|
|
50
|
+
});
|
|
51
|
+
expect(result).toBe('(SELECT 1 AS "user_id", \'John\' AS "name") ' +
|
|
52
|
+
'UNION ALL ' +
|
|
53
|
+
'(SELECT 2 AS "user_id", \'Jane\' AS "name")');
|
|
54
|
+
});
|
|
55
|
+
it('should handle column subset selection', () => {
|
|
56
|
+
const data = [
|
|
57
|
+
{ id: 1, name: 'John', age: 30 },
|
|
58
|
+
{ id: 2, name: 'Jane', age: 25 },
|
|
59
|
+
];
|
|
60
|
+
const result = sqlFrom(data, { columns: ['id', 'name'] });
|
|
61
|
+
expect(result).toBe('(SELECT 1 AS "id", \'John\' AS "name") ' +
|
|
62
|
+
'UNION ALL ' +
|
|
63
|
+
'(SELECT 2 AS "id", \'Jane\' AS "name")');
|
|
64
|
+
});
|
|
65
|
+
it('should throw error for empty column set', () => {
|
|
66
|
+
const data = [];
|
|
67
|
+
expect(() => sqlFrom(data)).toThrow('Can not create table from empty column set.');
|
|
68
|
+
});
|
|
69
|
+
});
|
|
70
|
+
});
|
package/dist/duckdb.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"duckdb.d.ts","sourceRoot":"","sources":["../src/duckdb.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,cAAc,CAAC;AAGtC;;;;;GAKG;AACH,wBAAsB,oBAAoB,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM;;;GAU1E;AAED;;;;;;;GAOG;AACH,wBAAsB,4BAA4B,CAChD,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,MAAM,EACjB,IAAI,CAAC,EAAE;
|
|
1
|
+
{"version":3,"file":"duckdb.d.ts","sourceRoot":"","sources":["../src/duckdb.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,cAAc,CAAC;AAGtC;;;;;GAKG;AACH,wBAAsB,oBAAoB,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM;;;GAU1E;AAED;;;;;;;GAOG;AACH,wBAAsB,4BAA4B,CAChD,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,MAAM,EACjB,IAAI,CAAC,EAAE;IACL,IAAI,EAAE,OAAO,GAAG,MAAM,CAAC;CACxB,GACA,OAAO,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAC,CAAC,CAwBhD;AAED;;;;;;GAMG;AACH,wBAAsB,kBAAkB,CACtC,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,IAAI,GAAG,UAAU,GACtB,OAAO,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAC,CAAC,CAgBhD;AAED;;;;GAIG;AACH,wBAAsB,yBAAyB,CAC7C,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,KAAK,CAAC,KAAK,iBAIlB;AAED;;;;GAIG;AACH,wBAAsB,sBAAsB,CAC1C,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,iBAKhC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sqlrooms/duckdb",
|
|
3
|
-
"version": "0.0
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"main": "dist/index.js",
|
|
5
5
|
"types": "dist/index.d.ts",
|
|
6
6
|
"module": "dist/index.js",
|
|
@@ -13,18 +13,17 @@
|
|
|
13
13
|
"url": "https://github.com/sqlrooms/sqlrooms.git"
|
|
14
14
|
},
|
|
15
15
|
"files": [
|
|
16
|
-
"dist"
|
|
17
|
-
"!dist/__tests__"
|
|
16
|
+
"dist"
|
|
18
17
|
],
|
|
19
18
|
"publishConfig": {
|
|
20
19
|
"access": "public"
|
|
21
20
|
},
|
|
22
21
|
"dependencies": {
|
|
23
|
-
"@duckdb/duckdb-wasm": "^1.29.0",
|
|
22
|
+
"@duckdb/duckdb-wasm": "^1.29.1-dev68.0",
|
|
24
23
|
"apache-arrow": "^18.1.0"
|
|
25
24
|
},
|
|
26
25
|
"devDependencies": {
|
|
27
|
-
"@sqlrooms/jest-config": "0.0
|
|
26
|
+
"@sqlrooms/jest-config": "0.3.0",
|
|
28
27
|
"@types/jest": "^29.5.12",
|
|
29
28
|
"jest": "^29.7.0",
|
|
30
29
|
"ts-jest": "^29.1.2"
|
|
@@ -38,5 +37,5 @@
|
|
|
38
37
|
"test": "jest",
|
|
39
38
|
"test:watch": "jest --watch"
|
|
40
39
|
},
|
|
41
|
-
"gitHead": "
|
|
40
|
+
"gitHead": "8586d4dd135d46c9c03ea65baa5a822287a5f07b"
|
|
42
41
|
}
|