alasql 4.15.0 → 4.16.1
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/bin/alasql-cli.js +1 -1
- package/dist/alasql-worker.js +2 -2
- package/dist/alasql.fs.js +112 -31
- package/dist/alasql.js +112 -31
- package/dist/alasql.min.js +64 -64
- package/package.json +1 -1
package/bin/alasql-cli.js
CHANGED
package/dist/alasql-worker.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
//! AlaSQL v4.
|
|
1
|
+
//! AlaSQL v4.16.1 build: develop-ff717ec7 | © 2014-2025 Andrey Gershun & Mathias Wulff | License: MIT
|
|
2
2
|
/*
|
|
3
3
|
@module alasql
|
|
4
|
-
@version 4.
|
|
4
|
+
@version 4.16.1
|
|
5
5
|
|
|
6
6
|
AlaSQL - JavaScript SQL database
|
|
7
7
|
© 2014-2025 Andrey Gershun & Mathias Wulff
|
package/dist/alasql.fs.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
//! AlaSQL v4.
|
|
1
|
+
//! AlaSQL v4.16.1 build: develop-ff717ec7 | © 2014-2025 Andrey Gershun & Mathias Wulff | License: MIT
|
|
2
2
|
/*
|
|
3
3
|
@module alasql
|
|
4
|
-
@version 4.
|
|
4
|
+
@version 4.16.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.
|
|
145
|
-
alasql.build = 'develop-
|
|
144
|
+
alasql.version = '4.16.1';
|
|
145
|
+
alasql.build = 'develop-ff717ec7';
|
|
146
146
|
|
|
147
147
|
/**
|
|
148
148
|
Debug flag
|
|
@@ -4522,11 +4522,11 @@ var cloneDeep = (utils.cloneDeep = function cloneDeep(obj) {
|
|
|
4522
4522
|
return +obj;
|
|
4523
4523
|
}
|
|
4524
4524
|
|
|
4525
|
-
var temp = new obj.constructor(); // changed
|
|
4525
|
+
var temp = new (Object.prototype.hasOwnProperty.call(obj, 'constructor') ? Object : obj.constructor)(); // changed
|
|
4526
4526
|
|
|
4527
4527
|
for (var key in obj) {
|
|
4528
4528
|
if (obj.hasOwnProperty(key)) {
|
|
4529
|
-
temp[key] = cloneDeep(obj[key]);
|
|
4529
|
+
/* A "__proto__" key from parsed data is copied as data, never as the prototype */ if (key === '__proto__') { Object.defineProperty(temp, key, {value: cloneDeep(obj[key]), writable: true, enumerable: true, configurable: true}); } else { temp[key] = cloneDeep(obj[key]); }
|
|
4530
4530
|
}
|
|
4531
4531
|
}
|
|
4532
4532
|
return temp;
|
|
@@ -4598,7 +4598,7 @@ var extend = (utils.extend = function extend(a, b) {
|
|
|
4598
4598
|
a = a || {};
|
|
4599
4599
|
for (var key in b) {
|
|
4600
4600
|
if (b.hasOwnProperty(key)) {
|
|
4601
|
-
a[key] = b[key];
|
|
4601
|
+
/* A "__proto__" key from parsed data is copied as data, never as the prototype */ if (key === '__proto__') { Object.defineProperty(a, key, {value: b[key], writable: true, enumerable: true, configurable: true}); } else { a[key] = b[key]; }
|
|
4602
4602
|
}
|
|
4603
4603
|
}
|
|
4604
4604
|
return a;
|
|
@@ -8527,6 +8527,12 @@ yy.ExistsValue = class ExistsValue {
|
|
|
8527
8527
|
alasql.precompile = function (statement, databaseid, params) {
|
|
8528
8528
|
if (!statement) return;
|
|
8529
8529
|
statement.params = params;
|
|
8530
|
+
// For CREATE VIEW statements, move queries to the select object
|
|
8531
|
+
// so they can be compiled later when the view is first used
|
|
8532
|
+
if (statement.view && statement.select && statement.queries) {
|
|
8533
|
+
statement.select.queries = statement.queries;
|
|
8534
|
+
return;
|
|
8535
|
+
}
|
|
8530
8536
|
if (statement.queries) {
|
|
8531
8537
|
statement.queriesfn = statement.queries.map(function (q) {
|
|
8532
8538
|
var nq = q.compile(databaseid || statement.database.databaseid);
|
|
@@ -8615,7 +8621,12 @@ yy.Select.prototype.compileFrom = function (query) {
|
|
|
8615
8621
|
};
|
|
8616
8622
|
} else if (alasql.databases[source.databaseid].tables[source.tableid].view) {
|
|
8617
8623
|
source.datafn = (query, params, cb, idx, alasql) => {
|
|
8618
|
-
let
|
|
8624
|
+
let table = alasql.databases[source.databaseid].tables[source.tableid];
|
|
8625
|
+
// Lazily compile the view's select on first use
|
|
8626
|
+
if (!table.select && table.viewSelect) {
|
|
8627
|
+
table.select = table.viewSelect.compile(table.viewDatabaseid);
|
|
8628
|
+
}
|
|
8629
|
+
let res = table.select(params);
|
|
8619
8630
|
if (cb) res = cb(res, idx, query);
|
|
8620
8631
|
return res;
|
|
8621
8632
|
};
|
|
@@ -9331,7 +9342,7 @@ yy.Select.prototype.compileGroup = function (query) {
|
|
|
9331
9342
|
aft2 = '';
|
|
9332
9343
|
|
|
9333
9344
|
if (typeof query.groupStar !== 'undefined') {
|
|
9334
|
-
aft2 += "for(var f in p['" + query.groupStar + "']) {g[f]=p['" + query.groupStar + "'][f];};";
|
|
9345
|
+
aft2 += "for(var f in p['" + query.groupStar + "']) {if(/^__proto__$/.test(f))Object.defineProperty(g,f,{writable:true,enumerable:true,configurable:true});g[f]=p['" + query.groupStar + "'][f];};";
|
|
9335
9346
|
}
|
|
9336
9347
|
|
|
9337
9348
|
s += query.selectGroup
|
|
@@ -9793,7 +9804,7 @@ function compileSelectStar(query, aliases, joinstar) {
|
|
|
9793
9804
|
'var w=p["' + escapeq(alias) + '"];for(var k in w){r["' + escapeq(alias) + '_"+k]=w[k]};';
|
|
9794
9805
|
} else {
|
|
9795
9806
|
// Default overwrite mode
|
|
9796
|
-
sp += 'var w=p["' + escapeq(alias) + '"];for(var k in w){r[k]=w[k]};';
|
|
9807
|
+
sp += 'var w=p["' + escapeq(alias) + '"];for(var k in w){if(/^__proto__$/.test(k))Object.defineProperty(r,k,{writable:true,enumerable:true,configurable:true});r[k]=w[k]};';
|
|
9797
9808
|
}
|
|
9798
9809
|
|
|
9799
9810
|
query.dirtyColumns = true;
|
|
@@ -10232,10 +10243,10 @@ yy.Select.prototype.compileSelectGroup1 = function (query) {
|
|
|
10232
10243
|
self.columns.forEach(function (col) {
|
|
10233
10244
|
|
|
10234
10245
|
if (col instanceof yy.Column && col.columnid === '*') {
|
|
10235
|
-
// s += 'for(var k in g){r[k]=g[k]};';
|
|
10246
|
+
// s += 'for(var k in g){if(/^__proto__$/.test(k))Object.defineProperty(r,k,{writable:true,enumerable:true,configurable:true});r[k]=g[k]};';
|
|
10236
10247
|
// s += 'for(var k in this.query.groupColumns){r[k]=g[this.query.groupColumns[k]]};';
|
|
10237
10248
|
|
|
10238
|
-
s += 'for(var k in g) {r[k]=g[k]};';
|
|
10249
|
+
s += 'for(var k in g) {if(/^__proto__$/.test(k))Object.defineProperty(r,k,{writable:true,enumerable:true,configurable:true});r[k]=g[k]};';
|
|
10239
10250
|
return '';
|
|
10240
10251
|
|
|
10241
10252
|
} else {
|
|
@@ -11537,7 +11548,7 @@ yy.Over = class Over {
|
|
|
11537
11548
|
const allValues = this.right.map(value => value.value);
|
|
11538
11549
|
const allValuesStr = allValues.join(',');
|
|
11539
11550
|
alasql.sets[allValuesStr] = alasql.sets[allValuesStr] || new Set(allValues);
|
|
11540
|
-
s = `alasql.sets[
|
|
11551
|
+
s = `alasql.sets[${JSON.stringify(allValuesStr)}].has(alasql.utils.getValueOf(${leftJS()}))`;
|
|
11541
11552
|
}
|
|
11542
11553
|
} else {
|
|
11543
11554
|
s = `(${rightJS()}.indexOf(${leftJS()}) > -1)`;
|
|
@@ -11571,7 +11582,7 @@ yy.Over = class Over {
|
|
|
11571
11582
|
const allValues = this.right.map(value => value.value);
|
|
11572
11583
|
const allValuesStr = allValues.join(',');
|
|
11573
11584
|
alasql.sets[allValuesStr] = alasql.sets[allValuesStr] || new Set(allValues);
|
|
11574
|
-
s = `!alasql.sets[
|
|
11585
|
+
s = `!alasql.sets[${JSON.stringify(allValuesStr)}].has(alasql.utils.getValueOf(${leftJS()}))`;
|
|
11575
11586
|
}
|
|
11576
11587
|
} else {
|
|
11577
11588
|
s = `(${rightJS()}.indexOf(${leftJS()}) === -1)`;
|
|
@@ -11976,17 +11987,23 @@ yy.Over = class Over {
|
|
|
11976
11987
|
}
|
|
11977
11988
|
|
|
11978
11989
|
findAggregator(query) {
|
|
11979
|
-
|
|
11980
|
-
|
|
11981
|
-
if (!this.nick) {
|
|
11982
|
-
this.nick = colas;
|
|
11990
|
+
// Check if an identical aggregate already exists in selectGroup
|
|
11991
|
+
let existingAggr = query.selectGroup.find(agg => agg.toString() === this.toString());
|
|
11983
11992
|
|
|
11984
|
-
|
|
11985
|
-
|
|
11993
|
+
if (existingAggr) {
|
|
11994
|
+
// Reuse the existing aggregate's nick to share the same accumulator
|
|
11995
|
+
this.aggrNick = existingAggr.nick;
|
|
11996
|
+
} else {
|
|
11997
|
+
// New aggregate - assign nick and add to selectGroup
|
|
11998
|
+
if (!this.nick) {
|
|
11999
|
+
this.nick = escapeq(this.toString()) + ':' + query.selectGroup.length;
|
|
12000
|
+
if (!query.removeKeys.includes(this.nick)) {
|
|
12001
|
+
query.removeKeys.push(this.nick);
|
|
12002
|
+
}
|
|
11986
12003
|
}
|
|
12004
|
+
this.aggrNick = this.nick;
|
|
12005
|
+
query.selectGroup.push(this);
|
|
11987
12006
|
}
|
|
11988
|
-
|
|
11989
|
-
query.selectGroup.push(this);
|
|
11990
12007
|
}
|
|
11991
12008
|
|
|
11992
12009
|
toType() {
|
|
@@ -12006,7 +12023,8 @@ yy.Over = class Over {
|
|
|
12006
12023
|
}
|
|
12007
12024
|
|
|
12008
12025
|
toJS() {
|
|
12009
|
-
|
|
12026
|
+
// Use aggrNick for duplicate aggregates to share the same accumulator, otherwise use the unique nick
|
|
12027
|
+
var colas = this.aggrNick || this.nick;
|
|
12010
12028
|
if (colas === undefined) {
|
|
12011
12029
|
colas = escapeq(this.toString());
|
|
12012
12030
|
}
|
|
@@ -12506,8 +12524,20 @@ stdfn.CONCAT_WS = function () {
|
|
|
12506
12524
|
// Aggregator for joining strings
|
|
12507
12525
|
alasql.aggr.group_concat = alasql.aggr.GROUP_CONCAT = function (v, s, stage) {
|
|
12508
12526
|
if (stage === 1) {
|
|
12527
|
+
// Initialize: skip null values
|
|
12528
|
+
if (v === null || v === undefined) {
|
|
12529
|
+
return null;
|
|
12530
|
+
}
|
|
12509
12531
|
return '' + v;
|
|
12510
12532
|
} else if (stage === 2) {
|
|
12533
|
+
// Accumulate: skip null values
|
|
12534
|
+
if (v === null || v === undefined) {
|
|
12535
|
+
return s;
|
|
12536
|
+
}
|
|
12537
|
+
// If accumulator is null/undefined, start with current value
|
|
12538
|
+
if (s === null || s === undefined) {
|
|
12539
|
+
return '' + v;
|
|
12540
|
+
}
|
|
12511
12541
|
s += ',' + v;
|
|
12512
12542
|
return s;
|
|
12513
12543
|
}
|
|
@@ -13400,7 +13430,9 @@ yy.CreateTable.prototype.execute = function (databaseid, params, cb) {
|
|
|
13400
13430
|
//Used in 420from queryfn when table.view = true!
|
|
13401
13431
|
if (this.view && this.select) {
|
|
13402
13432
|
table.view = true;
|
|
13403
|
-
|
|
13433
|
+
// Store the uncompiled select statement and databaseid for lazy compilation
|
|
13434
|
+
table.viewSelect = this.select;
|
|
13435
|
+
table.viewDatabaseid = this.table.databaseid || databaseid;
|
|
13404
13436
|
}
|
|
13405
13437
|
|
|
13406
13438
|
if (db.engineid) {
|
|
@@ -13521,7 +13553,7 @@ yy.CreateTable.prototype.execute = function (databaseid, params, cb) {
|
|
|
13521
13553
|
|
|
13522
13554
|
table.update(
|
|
13523
13555
|
function (t) {
|
|
13524
|
-
for (var f in r) t[f] = r[f];
|
|
13556
|
+
for (var f in r) {if(/^__proto__$/.test(f))Object.defineProperty(t,f,{writable:true,enumerable:true,configurable:true});t[f] = r[f];}
|
|
13525
13557
|
},
|
|
13526
13558
|
table.data.indexOf(toreplace),
|
|
13527
13559
|
params
|
|
@@ -15188,6 +15220,14 @@ yy.Insert.prototype.compile = function (databaseid) {
|
|
|
15188
15220
|
throw "Table '" + tableid + "' could not be found";
|
|
15189
15221
|
}
|
|
15190
15222
|
|
|
15223
|
+
// Helper function to create error message for value/column count mismatch
|
|
15224
|
+
var createValueCountMismatchError = function (valueCount, columnCount, columnType) {
|
|
15225
|
+
return (
|
|
15226
|
+
`The number of values (${valueCount}) does not match the number of ${columnType} (${columnCount}). ` +
|
|
15227
|
+
'If using a subquery, use INSERT INTO ... SELECT instead of INSERT INTO ... VALUES (SELECT ...)'
|
|
15228
|
+
);
|
|
15229
|
+
};
|
|
15230
|
+
|
|
15191
15231
|
// Check, if this dirty flag is required
|
|
15192
15232
|
var s = '';
|
|
15193
15233
|
var sw = '';
|
|
@@ -15221,6 +15261,12 @@ yy.Insert.prototype.compile = function (databaseid) {
|
|
|
15221
15261
|
|
|
15222
15262
|
// s += '';
|
|
15223
15263
|
if (self.columns) {
|
|
15264
|
+
// Validate that we have the right number of values for the columns
|
|
15265
|
+
if (values.length !== self.columns.length) {
|
|
15266
|
+
throw new Error(
|
|
15267
|
+
createValueCountMismatchError(values.length, self.columns.length, 'columns')
|
|
15268
|
+
);
|
|
15269
|
+
}
|
|
15224
15270
|
self.columns.forEach(function (col, idx) {
|
|
15225
15271
|
|
|
15226
15272
|
// ss.push(col.columnid +':'+ self.values[idx].value.toString());
|
|
@@ -15253,6 +15299,12 @@ yy.Insert.prototype.compile = function (databaseid) {
|
|
|
15253
15299
|
// var table = db.tables[tableid];
|
|
15254
15300
|
|
|
15255
15301
|
if (Array.isArray(values) && table.columns && table.columns.length > 0) {
|
|
15302
|
+
// Validate that we have the right number of values for the table columns
|
|
15303
|
+
if (values.length !== table.columns.length) {
|
|
15304
|
+
throw new Error(
|
|
15305
|
+
createValueCountMismatchError(values.length, table.columns.length, 'table columns')
|
|
15306
|
+
);
|
|
15307
|
+
}
|
|
15256
15308
|
table.columns.forEach(function (col, idx) {
|
|
15257
15309
|
var q = "'" + col.columnid + "':";
|
|
15258
15310
|
// var val = values[idx].toJS();
|
|
@@ -15272,7 +15324,7 @@ yy.Insert.prototype.compile = function (databaseid) {
|
|
|
15272
15324
|
});
|
|
15273
15325
|
} else {
|
|
15274
15326
|
|
|
15275
|
-
// sw = 'var w='+JSONtoJS(values)+';for(var k in w){r[k]=w[k]};';
|
|
15327
|
+
// sw = 'var w='+JSONtoJS(values)+';for(var k in w){if(/^__proto__$/.test(k))Object.defineProperty(r,k,{writable:true,enumerable:true,configurable:true});r[k]=w[k]};';
|
|
15276
15328
|
sw = JSONtoJS(values);
|
|
15277
15329
|
}
|
|
15278
15330
|
}
|
|
@@ -15351,7 +15403,7 @@ yy.Insert.prototype.compile = function (databaseid) {
|
|
|
15351
15403
|
self.output.columns.forEach(function (col) {
|
|
15352
15404
|
if (col.columnid === '*') {
|
|
15353
15405
|
// For *, expand all properties
|
|
15354
|
-
s += 'for(var key in r){ outputRow[key] = r[key]; }';
|
|
15406
|
+
s += 'for(var key in r){ if(/^__proto__$/.test(key))Object.defineProperty(outputRow,key,{writable:true,enumerable:true,configurable:true});outputRow[key] = r[key]; }';
|
|
15355
15407
|
} else {
|
|
15356
15408
|
var colname = col.as || col.columnid;
|
|
15357
15409
|
// Direct property access for simple columns
|
|
@@ -15430,7 +15482,7 @@ yy.Insert.prototype.compile = function (databaseid) {
|
|
|
15430
15482
|
if (col.columnid === '*') {
|
|
15431
15483
|
// For *, expand all properties
|
|
15432
15484
|
for (var key in r) {
|
|
15433
|
-
outputRow[key] = r[key];
|
|
15485
|
+
if(/^__proto__$/.test(key))Object.defineProperty(outputRow,key,{writable:true,enumerable:true,configurable:true});outputRow[key] = r[key];
|
|
15434
15486
|
}
|
|
15435
15487
|
} else {
|
|
15436
15488
|
var colname = col.as || col.columnid;
|
|
@@ -15781,7 +15833,7 @@ yy.Delete.prototype.compile = function (databaseid) {
|
|
|
15781
15833
|
if (col.columnid === '*') {
|
|
15782
15834
|
// For *, expand all properties
|
|
15783
15835
|
for (var key in r) {
|
|
15784
|
-
outputRow[key] = r[key];
|
|
15836
|
+
if(/^__proto__$/.test(key))Object.defineProperty(outputRow,key,{writable:true,enumerable:true,configurable:true});outputRow[key] = r[key];
|
|
15785
15837
|
}
|
|
15786
15838
|
} else {
|
|
15787
15839
|
var colname = col.as || col.columnid;
|
|
@@ -15852,7 +15904,7 @@ yy.Delete.prototype.compile = function (databaseid) {
|
|
|
15852
15904
|
if (col.columnid === '*') {
|
|
15853
15905
|
// For *, expand all properties
|
|
15854
15906
|
for (var key in r) {
|
|
15855
|
-
outputRow[key] = r[key];
|
|
15907
|
+
if(/^__proto__$/.test(key))Object.defineProperty(outputRow,key,{writable:true,enumerable:true,configurable:true});outputRow[key] = r[key];
|
|
15856
15908
|
}
|
|
15857
15909
|
} else {
|
|
15858
15910
|
var colname = col.as || col.columnid;
|
|
@@ -16022,7 +16074,7 @@ yy.Update.prototype.compile = function (databaseid) {
|
|
|
16022
16074
|
if (col.columnid === '*') {
|
|
16023
16075
|
// For *, use INSERTED values
|
|
16024
16076
|
for (var key in inserted) {
|
|
16025
|
-
outputRow[key] = inserted[key];
|
|
16077
|
+
if(/^__proto__$/.test(key))Object.defineProperty(outputRow,key,{writable:true,enumerable:true,configurable:true});outputRow[key] = inserted[key];
|
|
16026
16078
|
}
|
|
16027
16079
|
} else {
|
|
16028
16080
|
var colname = col.as || col.columnid;
|
|
@@ -19587,6 +19639,35 @@ IDB.updateTable = function (databaseid, tableid, assignfn, wherefn, params, cb)
|
|
|
19587
19639
|
};
|
|
19588
19640
|
};
|
|
19589
19641
|
};
|
|
19642
|
+
|
|
19643
|
+
/**
|
|
19644
|
+
* Commit transaction for IndexedDB
|
|
19645
|
+
* Note: IndexedDB operations are auto-committed per operation
|
|
19646
|
+
* This method provides API compatibility
|
|
19647
|
+
*/
|
|
19648
|
+
IDB.commit = function (databaseid, cb) {
|
|
19649
|
+
// IndexedDB auto-commits each operation's transaction
|
|
19650
|
+
// No additional action needed
|
|
19651
|
+
return cb ? cb(1) : 1;
|
|
19652
|
+
};
|
|
19653
|
+
|
|
19654
|
+
/**
|
|
19655
|
+
* Begin transaction - alias to commit for IndexedDB
|
|
19656
|
+
* Similar to LOCALSTORAGE pattern
|
|
19657
|
+
*/
|
|
19658
|
+
IDB.begin = IDB.commit;
|
|
19659
|
+
|
|
19660
|
+
/**
|
|
19661
|
+
* Rollback transaction for IndexedDB
|
|
19662
|
+
* Note: IndexedDB operations are auto-committed per operation
|
|
19663
|
+
* Manual rollback not supported - operations cannot be undone
|
|
19664
|
+
*/
|
|
19665
|
+
IDB.rollback = function (databaseid, cb) {
|
|
19666
|
+
// IndexedDB auto-commits each operation
|
|
19667
|
+
// Cannot rollback already-committed operations
|
|
19668
|
+
// This provides API compatibility only
|
|
19669
|
+
return cb ? cb(1) : 1;
|
|
19670
|
+
};
|
|
19590
19671
|
//
|
|
19591
19672
|
// 91localstorage.js
|
|
19592
19673
|
// localStorage and DOM-Storage engine
|
package/dist/alasql.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
//! AlaSQL v4.
|
|
1
|
+
//! AlaSQL v4.16.1 build: develop-ff717ec7 | © 2014-2025 Andrey Gershun & Mathias Wulff | License: MIT
|
|
2
2
|
/*
|
|
3
3
|
@module alasql
|
|
4
|
-
@version 4.
|
|
4
|
+
@version 4.16.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.
|
|
145
|
-
alasql.build = 'develop-
|
|
144
|
+
alasql.version = '4.16.1';
|
|
145
|
+
alasql.build = 'develop-ff717ec7';
|
|
146
146
|
|
|
147
147
|
/**
|
|
148
148
|
Debug flag
|
|
@@ -4522,11 +4522,11 @@ var cloneDeep = (utils.cloneDeep = function cloneDeep(obj) {
|
|
|
4522
4522
|
return +obj;
|
|
4523
4523
|
}
|
|
4524
4524
|
|
|
4525
|
-
var temp = new obj.constructor(); // changed
|
|
4525
|
+
var temp = new (Object.prototype.hasOwnProperty.call(obj, 'constructor') ? Object : obj.constructor)(); // changed
|
|
4526
4526
|
|
|
4527
4527
|
for (var key in obj) {
|
|
4528
4528
|
if (obj.hasOwnProperty(key)) {
|
|
4529
|
-
temp[key] = cloneDeep(obj[key]);
|
|
4529
|
+
/* A "__proto__" key from parsed data is copied as data, never as the prototype */ if (key === '__proto__') { Object.defineProperty(temp, key, {value: cloneDeep(obj[key]), writable: true, enumerable: true, configurable: true}); } else { temp[key] = cloneDeep(obj[key]); }
|
|
4530
4530
|
}
|
|
4531
4531
|
}
|
|
4532
4532
|
return temp;
|
|
@@ -4598,7 +4598,7 @@ var extend = (utils.extend = function extend(a, b) {
|
|
|
4598
4598
|
a = a || {};
|
|
4599
4599
|
for (var key in b) {
|
|
4600
4600
|
if (b.hasOwnProperty(key)) {
|
|
4601
|
-
a[key] = b[key];
|
|
4601
|
+
/* A "__proto__" key from parsed data is copied as data, never as the prototype */ if (key === '__proto__') { Object.defineProperty(a, key, {value: b[key], writable: true, enumerable: true, configurable: true}); } else { a[key] = b[key]; }
|
|
4602
4602
|
}
|
|
4603
4603
|
}
|
|
4604
4604
|
return a;
|
|
@@ -8527,6 +8527,12 @@ yy.ExistsValue = class ExistsValue {
|
|
|
8527
8527
|
alasql.precompile = function (statement, databaseid, params) {
|
|
8528
8528
|
if (!statement) return;
|
|
8529
8529
|
statement.params = params;
|
|
8530
|
+
// For CREATE VIEW statements, move queries to the select object
|
|
8531
|
+
// so they can be compiled later when the view is first used
|
|
8532
|
+
if (statement.view && statement.select && statement.queries) {
|
|
8533
|
+
statement.select.queries = statement.queries;
|
|
8534
|
+
return;
|
|
8535
|
+
}
|
|
8530
8536
|
if (statement.queries) {
|
|
8531
8537
|
statement.queriesfn = statement.queries.map(function (q) {
|
|
8532
8538
|
var nq = q.compile(databaseid || statement.database.databaseid);
|
|
@@ -8615,7 +8621,12 @@ yy.Select.prototype.compileFrom = function (query) {
|
|
|
8615
8621
|
};
|
|
8616
8622
|
} else if (alasql.databases[source.databaseid].tables[source.tableid].view) {
|
|
8617
8623
|
source.datafn = (query, params, cb, idx, alasql) => {
|
|
8618
|
-
let
|
|
8624
|
+
let table = alasql.databases[source.databaseid].tables[source.tableid];
|
|
8625
|
+
// Lazily compile the view's select on first use
|
|
8626
|
+
if (!table.select && table.viewSelect) {
|
|
8627
|
+
table.select = table.viewSelect.compile(table.viewDatabaseid);
|
|
8628
|
+
}
|
|
8629
|
+
let res = table.select(params);
|
|
8619
8630
|
if (cb) res = cb(res, idx, query);
|
|
8620
8631
|
return res;
|
|
8621
8632
|
};
|
|
@@ -9331,7 +9342,7 @@ yy.Select.prototype.compileGroup = function (query) {
|
|
|
9331
9342
|
aft2 = '';
|
|
9332
9343
|
|
|
9333
9344
|
if (typeof query.groupStar !== 'undefined') {
|
|
9334
|
-
aft2 += "for(var f in p['" + query.groupStar + "']) {g[f]=p['" + query.groupStar + "'][f];};";
|
|
9345
|
+
aft2 += "for(var f in p['" + query.groupStar + "']) {if(/^__proto__$/.test(f))Object.defineProperty(g,f,{writable:true,enumerable:true,configurable:true});g[f]=p['" + query.groupStar + "'][f];};";
|
|
9335
9346
|
}
|
|
9336
9347
|
|
|
9337
9348
|
s += query.selectGroup
|
|
@@ -9793,7 +9804,7 @@ function compileSelectStar(query, aliases, joinstar) {
|
|
|
9793
9804
|
'var w=p["' + escapeq(alias) + '"];for(var k in w){r["' + escapeq(alias) + '_"+k]=w[k]};';
|
|
9794
9805
|
} else {
|
|
9795
9806
|
// Default overwrite mode
|
|
9796
|
-
sp += 'var w=p["' + escapeq(alias) + '"];for(var k in w){r[k]=w[k]};';
|
|
9807
|
+
sp += 'var w=p["' + escapeq(alias) + '"];for(var k in w){if(/^__proto__$/.test(k))Object.defineProperty(r,k,{writable:true,enumerable:true,configurable:true});r[k]=w[k]};';
|
|
9797
9808
|
}
|
|
9798
9809
|
|
|
9799
9810
|
query.dirtyColumns = true;
|
|
@@ -10232,10 +10243,10 @@ yy.Select.prototype.compileSelectGroup1 = function (query) {
|
|
|
10232
10243
|
self.columns.forEach(function (col) {
|
|
10233
10244
|
|
|
10234
10245
|
if (col instanceof yy.Column && col.columnid === '*') {
|
|
10235
|
-
// s += 'for(var k in g){r[k]=g[k]};';
|
|
10246
|
+
// s += 'for(var k in g){if(/^__proto__$/.test(k))Object.defineProperty(r,k,{writable:true,enumerable:true,configurable:true});r[k]=g[k]};';
|
|
10236
10247
|
// s += 'for(var k in this.query.groupColumns){r[k]=g[this.query.groupColumns[k]]};';
|
|
10237
10248
|
|
|
10238
|
-
s += 'for(var k in g) {r[k]=g[k]};';
|
|
10249
|
+
s += 'for(var k in g) {if(/^__proto__$/.test(k))Object.defineProperty(r,k,{writable:true,enumerable:true,configurable:true});r[k]=g[k]};';
|
|
10239
10250
|
return '';
|
|
10240
10251
|
|
|
10241
10252
|
} else {
|
|
@@ -11537,7 +11548,7 @@ yy.Over = class Over {
|
|
|
11537
11548
|
const allValues = this.right.map(value => value.value);
|
|
11538
11549
|
const allValuesStr = allValues.join(',');
|
|
11539
11550
|
alasql.sets[allValuesStr] = alasql.sets[allValuesStr] || new Set(allValues);
|
|
11540
|
-
s = `alasql.sets[
|
|
11551
|
+
s = `alasql.sets[${JSON.stringify(allValuesStr)}].has(alasql.utils.getValueOf(${leftJS()}))`;
|
|
11541
11552
|
}
|
|
11542
11553
|
} else {
|
|
11543
11554
|
s = `(${rightJS()}.indexOf(${leftJS()}) > -1)`;
|
|
@@ -11571,7 +11582,7 @@ yy.Over = class Over {
|
|
|
11571
11582
|
const allValues = this.right.map(value => value.value);
|
|
11572
11583
|
const allValuesStr = allValues.join(',');
|
|
11573
11584
|
alasql.sets[allValuesStr] = alasql.sets[allValuesStr] || new Set(allValues);
|
|
11574
|
-
s = `!alasql.sets[
|
|
11585
|
+
s = `!alasql.sets[${JSON.stringify(allValuesStr)}].has(alasql.utils.getValueOf(${leftJS()}))`;
|
|
11575
11586
|
}
|
|
11576
11587
|
} else {
|
|
11577
11588
|
s = `(${rightJS()}.indexOf(${leftJS()}) === -1)`;
|
|
@@ -11976,17 +11987,23 @@ yy.Over = class Over {
|
|
|
11976
11987
|
}
|
|
11977
11988
|
|
|
11978
11989
|
findAggregator(query) {
|
|
11979
|
-
|
|
11980
|
-
|
|
11981
|
-
if (!this.nick) {
|
|
11982
|
-
this.nick = colas;
|
|
11990
|
+
// Check if an identical aggregate already exists in selectGroup
|
|
11991
|
+
let existingAggr = query.selectGroup.find(agg => agg.toString() === this.toString());
|
|
11983
11992
|
|
|
11984
|
-
|
|
11985
|
-
|
|
11993
|
+
if (existingAggr) {
|
|
11994
|
+
// Reuse the existing aggregate's nick to share the same accumulator
|
|
11995
|
+
this.aggrNick = existingAggr.nick;
|
|
11996
|
+
} else {
|
|
11997
|
+
// New aggregate - assign nick and add to selectGroup
|
|
11998
|
+
if (!this.nick) {
|
|
11999
|
+
this.nick = escapeq(this.toString()) + ':' + query.selectGroup.length;
|
|
12000
|
+
if (!query.removeKeys.includes(this.nick)) {
|
|
12001
|
+
query.removeKeys.push(this.nick);
|
|
12002
|
+
}
|
|
11986
12003
|
}
|
|
12004
|
+
this.aggrNick = this.nick;
|
|
12005
|
+
query.selectGroup.push(this);
|
|
11987
12006
|
}
|
|
11988
|
-
|
|
11989
|
-
query.selectGroup.push(this);
|
|
11990
12007
|
}
|
|
11991
12008
|
|
|
11992
12009
|
toType() {
|
|
@@ -12006,7 +12023,8 @@ yy.Over = class Over {
|
|
|
12006
12023
|
}
|
|
12007
12024
|
|
|
12008
12025
|
toJS() {
|
|
12009
|
-
|
|
12026
|
+
// Use aggrNick for duplicate aggregates to share the same accumulator, otherwise use the unique nick
|
|
12027
|
+
var colas = this.aggrNick || this.nick;
|
|
12010
12028
|
if (colas === undefined) {
|
|
12011
12029
|
colas = escapeq(this.toString());
|
|
12012
12030
|
}
|
|
@@ -12506,8 +12524,20 @@ stdfn.CONCAT_WS = function () {
|
|
|
12506
12524
|
// Aggregator for joining strings
|
|
12507
12525
|
alasql.aggr.group_concat = alasql.aggr.GROUP_CONCAT = function (v, s, stage) {
|
|
12508
12526
|
if (stage === 1) {
|
|
12527
|
+
// Initialize: skip null values
|
|
12528
|
+
if (v === null || v === undefined) {
|
|
12529
|
+
return null;
|
|
12530
|
+
}
|
|
12509
12531
|
return '' + v;
|
|
12510
12532
|
} else if (stage === 2) {
|
|
12533
|
+
// Accumulate: skip null values
|
|
12534
|
+
if (v === null || v === undefined) {
|
|
12535
|
+
return s;
|
|
12536
|
+
}
|
|
12537
|
+
// If accumulator is null/undefined, start with current value
|
|
12538
|
+
if (s === null || s === undefined) {
|
|
12539
|
+
return '' + v;
|
|
12540
|
+
}
|
|
12511
12541
|
s += ',' + v;
|
|
12512
12542
|
return s;
|
|
12513
12543
|
}
|
|
@@ -13400,7 +13430,9 @@ yy.CreateTable.prototype.execute = function (databaseid, params, cb) {
|
|
|
13400
13430
|
//Used in 420from queryfn when table.view = true!
|
|
13401
13431
|
if (this.view && this.select) {
|
|
13402
13432
|
table.view = true;
|
|
13403
|
-
|
|
13433
|
+
// Store the uncompiled select statement and databaseid for lazy compilation
|
|
13434
|
+
table.viewSelect = this.select;
|
|
13435
|
+
table.viewDatabaseid = this.table.databaseid || databaseid;
|
|
13404
13436
|
}
|
|
13405
13437
|
|
|
13406
13438
|
if (db.engineid) {
|
|
@@ -13521,7 +13553,7 @@ yy.CreateTable.prototype.execute = function (databaseid, params, cb) {
|
|
|
13521
13553
|
|
|
13522
13554
|
table.update(
|
|
13523
13555
|
function (t) {
|
|
13524
|
-
for (var f in r) t[f] = r[f];
|
|
13556
|
+
for (var f in r) {if(/^__proto__$/.test(f))Object.defineProperty(t,f,{writable:true,enumerable:true,configurable:true});t[f] = r[f];}
|
|
13525
13557
|
},
|
|
13526
13558
|
table.data.indexOf(toreplace),
|
|
13527
13559
|
params
|
|
@@ -15188,6 +15220,14 @@ yy.Insert.prototype.compile = function (databaseid) {
|
|
|
15188
15220
|
throw "Table '" + tableid + "' could not be found";
|
|
15189
15221
|
}
|
|
15190
15222
|
|
|
15223
|
+
// Helper function to create error message for value/column count mismatch
|
|
15224
|
+
var createValueCountMismatchError = function (valueCount, columnCount, columnType) {
|
|
15225
|
+
return (
|
|
15226
|
+
`The number of values (${valueCount}) does not match the number of ${columnType} (${columnCount}). ` +
|
|
15227
|
+
'If using a subquery, use INSERT INTO ... SELECT instead of INSERT INTO ... VALUES (SELECT ...)'
|
|
15228
|
+
);
|
|
15229
|
+
};
|
|
15230
|
+
|
|
15191
15231
|
// Check, if this dirty flag is required
|
|
15192
15232
|
var s = '';
|
|
15193
15233
|
var sw = '';
|
|
@@ -15221,6 +15261,12 @@ yy.Insert.prototype.compile = function (databaseid) {
|
|
|
15221
15261
|
|
|
15222
15262
|
// s += '';
|
|
15223
15263
|
if (self.columns) {
|
|
15264
|
+
// Validate that we have the right number of values for the columns
|
|
15265
|
+
if (values.length !== self.columns.length) {
|
|
15266
|
+
throw new Error(
|
|
15267
|
+
createValueCountMismatchError(values.length, self.columns.length, 'columns')
|
|
15268
|
+
);
|
|
15269
|
+
}
|
|
15224
15270
|
self.columns.forEach(function (col, idx) {
|
|
15225
15271
|
|
|
15226
15272
|
// ss.push(col.columnid +':'+ self.values[idx].value.toString());
|
|
@@ -15253,6 +15299,12 @@ yy.Insert.prototype.compile = function (databaseid) {
|
|
|
15253
15299
|
// var table = db.tables[tableid];
|
|
15254
15300
|
|
|
15255
15301
|
if (Array.isArray(values) && table.columns && table.columns.length > 0) {
|
|
15302
|
+
// Validate that we have the right number of values for the table columns
|
|
15303
|
+
if (values.length !== table.columns.length) {
|
|
15304
|
+
throw new Error(
|
|
15305
|
+
createValueCountMismatchError(values.length, table.columns.length, 'table columns')
|
|
15306
|
+
);
|
|
15307
|
+
}
|
|
15256
15308
|
table.columns.forEach(function (col, idx) {
|
|
15257
15309
|
var q = "'" + col.columnid + "':";
|
|
15258
15310
|
// var val = values[idx].toJS();
|
|
@@ -15272,7 +15324,7 @@ yy.Insert.prototype.compile = function (databaseid) {
|
|
|
15272
15324
|
});
|
|
15273
15325
|
} else {
|
|
15274
15326
|
|
|
15275
|
-
// sw = 'var w='+JSONtoJS(values)+';for(var k in w){r[k]=w[k]};';
|
|
15327
|
+
// sw = 'var w='+JSONtoJS(values)+';for(var k in w){if(/^__proto__$/.test(k))Object.defineProperty(r,k,{writable:true,enumerable:true,configurable:true});r[k]=w[k]};';
|
|
15276
15328
|
sw = JSONtoJS(values);
|
|
15277
15329
|
}
|
|
15278
15330
|
}
|
|
@@ -15351,7 +15403,7 @@ yy.Insert.prototype.compile = function (databaseid) {
|
|
|
15351
15403
|
self.output.columns.forEach(function (col) {
|
|
15352
15404
|
if (col.columnid === '*') {
|
|
15353
15405
|
// For *, expand all properties
|
|
15354
|
-
s += 'for(var key in r){ outputRow[key] = r[key]; }';
|
|
15406
|
+
s += 'for(var key in r){ if(/^__proto__$/.test(key))Object.defineProperty(outputRow,key,{writable:true,enumerable:true,configurable:true});outputRow[key] = r[key]; }';
|
|
15355
15407
|
} else {
|
|
15356
15408
|
var colname = col.as || col.columnid;
|
|
15357
15409
|
// Direct property access for simple columns
|
|
@@ -15430,7 +15482,7 @@ yy.Insert.prototype.compile = function (databaseid) {
|
|
|
15430
15482
|
if (col.columnid === '*') {
|
|
15431
15483
|
// For *, expand all properties
|
|
15432
15484
|
for (var key in r) {
|
|
15433
|
-
outputRow[key] = r[key];
|
|
15485
|
+
if(/^__proto__$/.test(key))Object.defineProperty(outputRow,key,{writable:true,enumerable:true,configurable:true});outputRow[key] = r[key];
|
|
15434
15486
|
}
|
|
15435
15487
|
} else {
|
|
15436
15488
|
var colname = col.as || col.columnid;
|
|
@@ -15781,7 +15833,7 @@ yy.Delete.prototype.compile = function (databaseid) {
|
|
|
15781
15833
|
if (col.columnid === '*') {
|
|
15782
15834
|
// For *, expand all properties
|
|
15783
15835
|
for (var key in r) {
|
|
15784
|
-
outputRow[key] = r[key];
|
|
15836
|
+
if(/^__proto__$/.test(key))Object.defineProperty(outputRow,key,{writable:true,enumerable:true,configurable:true});outputRow[key] = r[key];
|
|
15785
15837
|
}
|
|
15786
15838
|
} else {
|
|
15787
15839
|
var colname = col.as || col.columnid;
|
|
@@ -15852,7 +15904,7 @@ yy.Delete.prototype.compile = function (databaseid) {
|
|
|
15852
15904
|
if (col.columnid === '*') {
|
|
15853
15905
|
// For *, expand all properties
|
|
15854
15906
|
for (var key in r) {
|
|
15855
|
-
outputRow[key] = r[key];
|
|
15907
|
+
if(/^__proto__$/.test(key))Object.defineProperty(outputRow,key,{writable:true,enumerable:true,configurable:true});outputRow[key] = r[key];
|
|
15856
15908
|
}
|
|
15857
15909
|
} else {
|
|
15858
15910
|
var colname = col.as || col.columnid;
|
|
@@ -16022,7 +16074,7 @@ yy.Update.prototype.compile = function (databaseid) {
|
|
|
16022
16074
|
if (col.columnid === '*') {
|
|
16023
16075
|
// For *, use INSERTED values
|
|
16024
16076
|
for (var key in inserted) {
|
|
16025
|
-
outputRow[key] = inserted[key];
|
|
16077
|
+
if(/^__proto__$/.test(key))Object.defineProperty(outputRow,key,{writable:true,enumerable:true,configurable:true});outputRow[key] = inserted[key];
|
|
16026
16078
|
}
|
|
16027
16079
|
} else {
|
|
16028
16080
|
var colname = col.as || col.columnid;
|
|
@@ -19587,6 +19639,35 @@ IDB.updateTable = function (databaseid, tableid, assignfn, wherefn, params, cb)
|
|
|
19587
19639
|
};
|
|
19588
19640
|
};
|
|
19589
19641
|
};
|
|
19642
|
+
|
|
19643
|
+
/**
|
|
19644
|
+
* Commit transaction for IndexedDB
|
|
19645
|
+
* Note: IndexedDB operations are auto-committed per operation
|
|
19646
|
+
* This method provides API compatibility
|
|
19647
|
+
*/
|
|
19648
|
+
IDB.commit = function (databaseid, cb) {
|
|
19649
|
+
// IndexedDB auto-commits each operation's transaction
|
|
19650
|
+
// No additional action needed
|
|
19651
|
+
return cb ? cb(1) : 1;
|
|
19652
|
+
};
|
|
19653
|
+
|
|
19654
|
+
/**
|
|
19655
|
+
* Begin transaction - alias to commit for IndexedDB
|
|
19656
|
+
* Similar to LOCALSTORAGE pattern
|
|
19657
|
+
*/
|
|
19658
|
+
IDB.begin = IDB.commit;
|
|
19659
|
+
|
|
19660
|
+
/**
|
|
19661
|
+
* Rollback transaction for IndexedDB
|
|
19662
|
+
* Note: IndexedDB operations are auto-committed per operation
|
|
19663
|
+
* Manual rollback not supported - operations cannot be undone
|
|
19664
|
+
*/
|
|
19665
|
+
IDB.rollback = function (databaseid, cb) {
|
|
19666
|
+
// IndexedDB auto-commits each operation
|
|
19667
|
+
// Cannot rollback already-committed operations
|
|
19668
|
+
// This provides API compatibility only
|
|
19669
|
+
return cb ? cb(1) : 1;
|
|
19670
|
+
};
|
|
19590
19671
|
//
|
|
19591
19672
|
// 91localstorage.js
|
|
19592
19673
|
// localStorage and DOM-Storage engine
|