alasql 4.19.0 → 4.20.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.
@@ -1,7 +1,7 @@
1
- //! AlaSQL v4.18.0 build: develop-ddadb7a5 | © 2014-2025 Andrey Gershun & Mathias Wulff | License: MIT
1
+ //! AlaSQL v4.19.1 build: develop-cfae681d | © 2014-2025 Andrey Gershun & Mathias Wulff | License: MIT
2
2
  /*
3
3
  @module alasql
4
- @version 4.18.0
4
+ @version 4.19.1
5
5
 
6
6
  AlaSQL - JavaScript SQL database
7
7
  © 2014-2025 Andrey Gershun & Mathias Wulff
package/dist/alasql.d.ts CHANGED
@@ -4,11 +4,11 @@ declare module 'alasql' {
4
4
  import * as xlsx from 'xlsx';
5
5
 
6
6
  // Callback with error-first convention and optional data
7
- interface AlaSQLCallback<T = unknown> {
7
+ export interface AlaSQLCallback<T = unknown> {
8
8
  (err: Error | null, data?: T): void;
9
9
  }
10
10
 
11
- interface AlaSQLOptions {
11
+ export interface AlaSQLOptions {
12
12
  errorlog: boolean;
13
13
  valueof: boolean;
14
14
  dropifnotexists: boolean; // drop database in any case
@@ -35,21 +35,21 @@ declare module 'alasql' {
35
35
  }
36
36
 
37
37
  // compiled Statement
38
- interface AlaSQLStatement {
38
+ export interface AlaSQLStatement {
39
39
  <T = unknown>(params?: any, cb?: AlaSQLCallback<T>, scope?: unknown): T;
40
40
  }
41
41
 
42
- type AlaSQLDefaultColumns = {[columnName: string]: string};
42
+ export type AlaSQLDefaultColumns = {[columnName: string]: string};
43
43
 
44
44
  /**
45
45
  * Base parsed expression node.
46
46
  * Node shapes below are part of the public parser AST surface and follow semver.
47
47
  */
48
- interface AlaSQLExpression {
48
+ export interface AlaSQLExpression {
49
49
  toJS(context: string, tableid: string | number, defcols: AlaSQLDefaultColumns | null): string;
50
50
  }
51
51
 
52
- interface Op extends AlaSQLExpression {
52
+ export interface Op extends AlaSQLExpression {
53
53
  left: ExpressionNode;
54
54
  op: string;
55
55
  right?: ExpressionNode;
@@ -57,71 +57,72 @@ declare module 'alasql' {
57
57
  right2?: ExpressionNode;
58
58
  }
59
59
 
60
- interface Column extends AlaSQLExpression {
60
+ export interface Column extends AlaSQLExpression {
61
61
  columnid: string;
62
62
  tableid?: string;
63
63
  databaseid?: string;
64
64
  }
65
65
 
66
- interface ParamValue extends AlaSQLExpression {
66
+ export interface ParamValue extends AlaSQLExpression {
67
67
  param: string | number;
68
68
  }
69
69
 
70
- interface NumValue extends AlaSQLExpression {
70
+ export interface NumValue extends AlaSQLExpression {
71
71
  value: number;
72
72
  }
73
73
 
74
- interface StringValue extends AlaSQLExpression {
74
+ export interface StringValue extends AlaSQLExpression {
75
75
  value: string;
76
76
  }
77
77
 
78
- interface LogicValue extends AlaSQLExpression {
78
+ export interface LogicValue extends AlaSQLExpression {
79
79
  value: boolean;
80
80
  }
81
81
 
82
- interface UniOp extends AlaSQLExpression {
82
+ export interface UniOp extends AlaSQLExpression {
83
83
  op: string | null;
84
84
  right: ExpressionNode;
85
85
  }
86
86
 
87
- type ExpressionNode = Op | Column | ParamValue | NumValue | StringValue | LogicValue | UniOp;
87
+ export type ExpressionNode =
88
+ Op | Column | ParamValue | NumValue | StringValue | LogicValue | UniOp;
88
89
 
89
- interface ExpressionWrapper extends AlaSQLExpression {
90
+ export interface ExpressionWrapper extends AlaSQLExpression {
90
91
  expression: ExpressionNode;
91
92
  reduced?: boolean;
92
93
  }
93
94
 
94
- interface Statement {
95
+ export interface Statement {
95
96
  compile(databaseid: string): AlaSQLStatement;
96
97
  where?: ExpressionWrapper;
97
98
  [key: string]: unknown;
98
99
  }
99
100
 
100
101
  // abstract Syntax Tree
101
- interface AlaSQLAST {
102
+ export interface AlaSQLAST {
102
103
  statements: Statement[];
103
104
  compile(databaseid: string): AlaSQLStatement;
104
105
  }
105
106
 
106
107
  // see https://github.com/alasql/alasql/wiki/User%20Defined%20Functions
107
- interface userDefinedFunction {
108
+ export interface userDefinedFunction {
108
109
  (...x: unknown[]): unknown;
109
110
  }
110
111
 
111
- interface userDefinedFunctionLookUp {
112
+ export interface userDefinedFunctionLookUp {
112
113
  [x: string]: userDefinedFunction;
113
114
  }
114
115
 
115
116
  // see https://github.com/alasql/alasql/wiki/User%20Defined%20Functions
116
- interface userAggregator {
117
+ export interface userAggregator {
117
118
  (value: unknown, accumulator: unknown, stage: number): unknown;
118
119
  }
119
120
 
120
- interface userAggregatorLookUp {
121
+ export interface userAggregatorLookUp {
121
122
  [x: string]: userAggregator;
122
123
  }
123
124
 
124
- interface userFromFunction {
125
+ export interface userFromFunction {
125
126
  (
126
127
  dataReference: unknown,
127
128
  options: unknown,
@@ -131,7 +132,7 @@ declare module 'alasql' {
131
132
  ): void;
132
133
  }
133
134
 
134
- interface userFromFunctionLookUp {
135
+ export interface userFromFunctionLookUp {
135
136
  [x: string]: userFromFunction;
136
137
  }
137
138
 
@@ -140,7 +141,7 @@ declare module 'alasql' {
140
141
  *
141
142
  * @interface database
142
143
  */
143
- interface database {
144
+ export interface database {
144
145
  /**
145
146
  * The database ID.
146
147
  *
@@ -163,7 +164,7 @@ declare module 'alasql' {
163
164
  *
164
165
  * @interface table
165
166
  */
166
- interface table {
167
+ export interface table {
167
168
  /**
168
169
  * The array of data stored in the table which can be queried
169
170
  *
@@ -178,7 +179,7 @@ declare module 'alasql' {
178
179
  *
179
180
  * @interface databaseLookUp
180
181
  */
181
- interface databaseLookUp {
182
+ export interface databaseLookUp {
182
183
  [databaseName: string]: database;
183
184
  }
184
185
 
@@ -187,11 +188,11 @@ declare module 'alasql' {
187
188
  *
188
189
  * @interface tableLookUp
189
190
  */
190
- interface tableLookUp {
191
+ export interface tableLookUp {
191
192
  [tableName: string]: table;
192
193
  }
193
194
 
194
- interface Database {
195
+ export interface Database {
195
196
  new (databaseid?: string): Database;
196
197
  databaseid: string;
197
198
  dbversion: number;
@@ -209,7 +210,7 @@ declare module 'alasql' {
209
210
  autoval(tablename: string, colname: string, getNext: boolean): unknown;
210
211
  }
211
212
 
212
- interface AlaSQL {
213
+ export interface AlaSQL {
213
214
  options: AlaSQLOptions;
214
215
  error: Error;
215
216
  <T = unknown>(sql: string, params?: any, cb?: AlaSQLCallback<T>, scope?: unknown): T;
package/dist/alasql.fs.js CHANGED
@@ -1,7 +1,7 @@
1
- //! AlaSQL v4.18.0 build: develop-ddadb7a5 | © 2014-2025 Andrey Gershun & Mathias Wulff | License: MIT
1
+ //! AlaSQL v4.19.1 build: develop-cfae681d | © 2014-2025 Andrey Gershun & Mathias Wulff | License: MIT
2
2
  /*
3
3
  @module alasql
4
- @version 4.18.0
4
+ @version 4.19.1
5
5
 
6
6
  AlaSQL - JavaScript SQL database
7
7
  © 2014-2025 Andrey Gershun & Mathias Wulff
@@ -141,8 +141,8 @@ SOFTWARE.
141
141
  Current version of alasql
142
142
  @constant {string}
143
143
  */
144
- alasql.version = '4.18.0';
145
- alasql.build = 'develop-ddadb7a5';
144
+ alasql.version = '4.19.1';
145
+ alasql.build = 'develop-cfae681d';
146
146
 
147
147
  /**
148
148
  Debug flag
@@ -8601,7 +8601,11 @@ yy.Select = class Select {
8601
8601
  return referencesExternal(subquery.where) || referencesExternal(subquery.columns);
8602
8602
  };
8603
8603
 
8604
- query.queriesfn = this.queries.map(function (q, idx) {
8604
+ // Compile each subquery. Nested scalar subqueries such as
8605
+ // SELECT (SELECT (SELECT 1 AS c) AS b) AS a share one statement-level
8606
+ // queries list (see #1025), so every compiled subquery must be able to
8607
+ // resolve queriesidx against the same queriesfn array at runtime.
8608
+ query.queriesfn = this.queries.map(function (q) {
8605
8609
  var nq = q.compile(query.database.databaseid);
8606
8610
  nq.query.modifier = 'RECORDSET';
8607
8611
 
@@ -8609,8 +8613,8 @@ yy.Select = class Select {
8609
8613
  nq.query.isCorrelated = isCorrelated(q, query);
8610
8614
 
8611
8615
  // If the nested query has its own queries, ensure they're compiled too
8612
- // This handles nested subqueries properly
8613
- if (q.queries && q.queries.length > 0) {
8616
+ // (e.g. IN/ALL/ANY subqueries that captured a nested queries list)
8617
+ if (q.queries && q.queries.length > 0 && !nq.query.queriesfn) {
8614
8618
  nq.query.queriesfn = q.queries.map(function (qq) {
8615
8619
  var nnq = qq.compile(query.database.databaseid);
8616
8620
  nnq.query.modifier = 'RECORDSET';
@@ -8620,15 +8624,20 @@ yy.Select = class Select {
8620
8624
  return nq;
8621
8625
  });
8622
8626
 
8623
- // Subquery indices (queriesidx) are assigned against the statement-level
8624
- // queries list, so a subquery that references another subquery
8625
- // (e.g. a scalar subquery nested inside a subquery's WHERE clause)
8626
- // needs access to the same compiled list
8627
- query.queriesfn.forEach(function (nq) {
8628
- if (!nq.query.queriesfn) {
8629
- nq.query.queriesfn = query.queriesfn;
8630
- }
8631
- });
8627
+ // Share compiled subquery functions down the tree. Without this,
8628
+ // multi-level scalar subqueries fail with
8629
+ // "Cannot read properties of undefined (reading '0')" when the
8630
+ // inner select expression evaluates this.queriesfn[queriesidx-1].
8631
+ (function shareQueriesfn(queriesfn) {
8632
+ if (!queriesfn) return;
8633
+ queriesfn.forEach(function (nq) {
8634
+ if (!nq.query.queriesfn) {
8635
+ nq.query.queriesfn = queriesfn;
8636
+ } else if (nq.query.queriesfn !== queriesfn) {
8637
+ shareQueriesfn(nq.query.queriesfn);
8638
+ }
8639
+ });
8640
+ })(query.queriesfn);
8632
8641
  }
8633
8642
  };
8634
8643
 
@@ -15455,40 +15464,61 @@ function mapColumnsToNames(data, sourceColumns, targetColumns) {
15455
15464
 
15456
15465
  yy.WithSelect.prototype.execute = function (databaseid, params, cb) {
15457
15466
  var self = this;
15458
- // Create temporary tables
15459
15467
  var savedTables = [];
15460
- self.withs.forEach(function (w) {
15468
+
15469
+ // Restore tables shadowed by the temporary CTE tables
15470
+ function restoreTables() {
15471
+ self.withs.forEach(function (w, idx) {
15472
+ if (savedTables[idx]) alasql.databases[databaseid].tables[w.name] = savedTables[idx];
15473
+ else delete alasql.databases[databaseid].tables[w.name];
15474
+ });
15475
+ }
15476
+
15477
+ // Create temporary tables one after another. Each non-recursive CTE is
15478
+ // executed with a callback, so sources that load data asynchronously
15479
+ // (like CSV() or XLSX() reading a file) are fully loaded before the
15480
+ // next CTE or the main select reads the temporary table.
15481
+ function executeWith(idx) {
15482
+ if (idx >= self.withs.length) {
15483
+ return self.select.execute(databaseid, params, function (data, err) {
15484
+ restoreTables();
15485
+ if (cb) data = cb(data, err);
15486
+ return data;
15487
+ });
15488
+ }
15489
+
15490
+ var w = self.withs[idx];
15461
15491
  savedTables.push(alasql.databases[databaseid].tables[w.name]);
15462
15492
 
15463
15493
  if (w.recursive) {
15464
15494
  // Execute recursive CTE
15465
15495
  executeRecursiveCTE(w, databaseid, params);
15466
- } else {
15467
- // Non-recursive CTE - original behavior
15468
- var tb = (alasql.databases[databaseid].tables[w.name] = new Table({
15469
- tableid: w.name,
15470
- }));
15471
- tb.data = w.select.execute(databaseid, params);
15496
+ return executeWith(idx + 1);
15497
+ }
15498
+
15499
+ // Non-recursive CTE
15500
+ var tb = (alasql.databases[databaseid].tables[w.name] = new Table({
15501
+ tableid: w.name,
15502
+ }));
15503
+ // The statement returns its own result, so keep the result of the rest
15504
+ // of the chain (available right away when all sources are synchronous)
15505
+ var res;
15506
+ w.select.execute(databaseid, params, function (data, err) {
15507
+ if (err) {
15508
+ restoreTables();
15509
+ if (cb) return cb(null, err);
15510
+ throw err;
15511
+ }
15512
+ tb.data = data;
15472
15513
  if (w.columns) {
15473
15514
  tb.data = renameColumns(tb.data, w.columns);
15474
15515
  }
15475
- }
15476
- });
15477
-
15478
- var res = 1;
15479
- res = this.select.execute(databaseid, params, function (data) {
15480
- // Clear temporary tables
15481
- // setTimeout(function(){
15482
- self.withs.forEach(function (w, idx) {
15483
- if (savedTables[idx]) alasql.databases[databaseid].tables[w.name] = savedTables[idx];
15484
- else delete alasql.databases[databaseid].tables[w.name];
15516
+ res = executeWith(idx + 1);
15485
15517
  });
15486
- // },0);
15518
+ return res;
15519
+ }
15487
15520
 
15488
- if (cb) data = cb(data);
15489
- return data;
15490
- });
15491
- return res;
15521
+ return executeWith(0);
15492
15522
  };
15493
15523
 
15494
15524
  /*
@@ -16525,6 +16555,7 @@ yy.Update.prototype.compile = function (databaseid) {
16525
16555
 
16526
16556
  var statement = function (params, cb) {
16527
16557
  var db = alasql.databases[databaseid];
16558
+ self.params = params;
16528
16559
 
16529
16560
  if (db.engineid && alasql.engines[db.engineid].updateTable) {
16530
16561
 
package/dist/alasql.js CHANGED
@@ -1,7 +1,7 @@
1
- //! AlaSQL v4.18.0 build: develop-ddadb7a5 | © 2014-2025 Andrey Gershun & Mathias Wulff | License: MIT
1
+ //! AlaSQL v4.19.1 build: develop-cfae681d | © 2014-2025 Andrey Gershun & Mathias Wulff | License: MIT
2
2
  /*
3
3
  @module alasql
4
- @version 4.18.0
4
+ @version 4.19.1
5
5
 
6
6
  AlaSQL - JavaScript SQL database
7
7
  © 2014-2025 Andrey Gershun & Mathias Wulff
@@ -141,8 +141,8 @@ SOFTWARE.
141
141
  Current version of alasql
142
142
  @constant {string}
143
143
  */
144
- alasql.version = '4.18.0';
145
- alasql.build = 'develop-ddadb7a5';
144
+ alasql.version = '4.19.1';
145
+ alasql.build = 'develop-cfae681d';
146
146
 
147
147
  /**
148
148
  Debug flag
@@ -8601,7 +8601,11 @@ yy.Select = class Select {
8601
8601
  return referencesExternal(subquery.where) || referencesExternal(subquery.columns);
8602
8602
  };
8603
8603
 
8604
- query.queriesfn = this.queries.map(function (q, idx) {
8604
+ // Compile each subquery. Nested scalar subqueries such as
8605
+ // SELECT (SELECT (SELECT 1 AS c) AS b) AS a share one statement-level
8606
+ // queries list (see #1025), so every compiled subquery must be able to
8607
+ // resolve queriesidx against the same queriesfn array at runtime.
8608
+ query.queriesfn = this.queries.map(function (q) {
8605
8609
  var nq = q.compile(query.database.databaseid);
8606
8610
  nq.query.modifier = 'RECORDSET';
8607
8611
 
@@ -8609,8 +8613,8 @@ yy.Select = class Select {
8609
8613
  nq.query.isCorrelated = isCorrelated(q, query);
8610
8614
 
8611
8615
  // If the nested query has its own queries, ensure they're compiled too
8612
- // This handles nested subqueries properly
8613
- if (q.queries && q.queries.length > 0) {
8616
+ // (e.g. IN/ALL/ANY subqueries that captured a nested queries list)
8617
+ if (q.queries && q.queries.length > 0 && !nq.query.queriesfn) {
8614
8618
  nq.query.queriesfn = q.queries.map(function (qq) {
8615
8619
  var nnq = qq.compile(query.database.databaseid);
8616
8620
  nnq.query.modifier = 'RECORDSET';
@@ -8620,15 +8624,20 @@ yy.Select = class Select {
8620
8624
  return nq;
8621
8625
  });
8622
8626
 
8623
- // Subquery indices (queriesidx) are assigned against the statement-level
8624
- // queries list, so a subquery that references another subquery
8625
- // (e.g. a scalar subquery nested inside a subquery's WHERE clause)
8626
- // needs access to the same compiled list
8627
- query.queriesfn.forEach(function (nq) {
8628
- if (!nq.query.queriesfn) {
8629
- nq.query.queriesfn = query.queriesfn;
8630
- }
8631
- });
8627
+ // Share compiled subquery functions down the tree. Without this,
8628
+ // multi-level scalar subqueries fail with
8629
+ // "Cannot read properties of undefined (reading '0')" when the
8630
+ // inner select expression evaluates this.queriesfn[queriesidx-1].
8631
+ (function shareQueriesfn(queriesfn) {
8632
+ if (!queriesfn) return;
8633
+ queriesfn.forEach(function (nq) {
8634
+ if (!nq.query.queriesfn) {
8635
+ nq.query.queriesfn = queriesfn;
8636
+ } else if (nq.query.queriesfn !== queriesfn) {
8637
+ shareQueriesfn(nq.query.queriesfn);
8638
+ }
8639
+ });
8640
+ })(query.queriesfn);
8632
8641
  }
8633
8642
  };
8634
8643
 
@@ -15455,40 +15464,61 @@ function mapColumnsToNames(data, sourceColumns, targetColumns) {
15455
15464
 
15456
15465
  yy.WithSelect.prototype.execute = function (databaseid, params, cb) {
15457
15466
  var self = this;
15458
- // Create temporary tables
15459
15467
  var savedTables = [];
15460
- self.withs.forEach(function (w) {
15468
+
15469
+ // Restore tables shadowed by the temporary CTE tables
15470
+ function restoreTables() {
15471
+ self.withs.forEach(function (w, idx) {
15472
+ if (savedTables[idx]) alasql.databases[databaseid].tables[w.name] = savedTables[idx];
15473
+ else delete alasql.databases[databaseid].tables[w.name];
15474
+ });
15475
+ }
15476
+
15477
+ // Create temporary tables one after another. Each non-recursive CTE is
15478
+ // executed with a callback, so sources that load data asynchronously
15479
+ // (like CSV() or XLSX() reading a file) are fully loaded before the
15480
+ // next CTE or the main select reads the temporary table.
15481
+ function executeWith(idx) {
15482
+ if (idx >= self.withs.length) {
15483
+ return self.select.execute(databaseid, params, function (data, err) {
15484
+ restoreTables();
15485
+ if (cb) data = cb(data, err);
15486
+ return data;
15487
+ });
15488
+ }
15489
+
15490
+ var w = self.withs[idx];
15461
15491
  savedTables.push(alasql.databases[databaseid].tables[w.name]);
15462
15492
 
15463
15493
  if (w.recursive) {
15464
15494
  // Execute recursive CTE
15465
15495
  executeRecursiveCTE(w, databaseid, params);
15466
- } else {
15467
- // Non-recursive CTE - original behavior
15468
- var tb = (alasql.databases[databaseid].tables[w.name] = new Table({
15469
- tableid: w.name,
15470
- }));
15471
- tb.data = w.select.execute(databaseid, params);
15496
+ return executeWith(idx + 1);
15497
+ }
15498
+
15499
+ // Non-recursive CTE
15500
+ var tb = (alasql.databases[databaseid].tables[w.name] = new Table({
15501
+ tableid: w.name,
15502
+ }));
15503
+ // The statement returns its own result, so keep the result of the rest
15504
+ // of the chain (available right away when all sources are synchronous)
15505
+ var res;
15506
+ w.select.execute(databaseid, params, function (data, err) {
15507
+ if (err) {
15508
+ restoreTables();
15509
+ if (cb) return cb(null, err);
15510
+ throw err;
15511
+ }
15512
+ tb.data = data;
15472
15513
  if (w.columns) {
15473
15514
  tb.data = renameColumns(tb.data, w.columns);
15474
15515
  }
15475
- }
15476
- });
15477
-
15478
- var res = 1;
15479
- res = this.select.execute(databaseid, params, function (data) {
15480
- // Clear temporary tables
15481
- // setTimeout(function(){
15482
- self.withs.forEach(function (w, idx) {
15483
- if (savedTables[idx]) alasql.databases[databaseid].tables[w.name] = savedTables[idx];
15484
- else delete alasql.databases[databaseid].tables[w.name];
15516
+ res = executeWith(idx + 1);
15485
15517
  });
15486
- // },0);
15518
+ return res;
15519
+ }
15487
15520
 
15488
- if (cb) data = cb(data);
15489
- return data;
15490
- });
15491
- return res;
15521
+ return executeWith(0);
15492
15522
  };
15493
15523
 
15494
15524
  /*
@@ -16525,6 +16555,7 @@ yy.Update.prototype.compile = function (databaseid) {
16525
16555
 
16526
16556
  var statement = function (params, cb) {
16527
16557
  var db = alasql.databases[databaseid];
16558
+ self.params = params;
16528
16559
 
16529
16560
  if (db.engineid && alasql.engines[db.engineid].updateTable) {
16530
16561