@sqlrooms/duckdb 0.0.3 → 0.1.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.
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=arrow-utils.test.d.ts.map
@@ -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,2 @@
1
+ export {};
2
+ //# sourceMappingURL=sql-from.test.d.ts.map
@@ -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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sqlrooms/duckdb",
3
- "version": "0.0.3",
3
+ "version": "0.1.0",
4
4
  "main": "dist/index.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "module": "dist/index.js",
@@ -13,8 +13,7 @@
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"
@@ -24,7 +23,7 @@
24
23
  "apache-arrow": "^18.1.0"
25
24
  },
26
25
  "devDependencies": {
27
- "@sqlrooms/jest-config": "0.0.3",
26
+ "@sqlrooms/jest-config": "0.1.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": "4269a3efdb5a903cb2498c126e9c36683b3bbae0"
40
+ "gitHead": "2d44f6636dbd53d18c32a422351e93caa182ada6"
42
41
  }