Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 11 additions & 14 deletions .github/renovate.json5
Original file line number Diff line number Diff line change
@@ -1,18 +1,15 @@
{
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
"extends": [
"config:base"
],
"packageRules": [
$schema: "https://docs.renovatebot.com/renovate-schema.json",
extends: ["config:recommended"],
packageRules: [
{
"matchUpdateTypes": ["minor", "patch", "pin", "digest"],
"automerge": true
}
matchUpdateTypes: ["minor", "patch", "pin", "digest"],
automerge: true,
},
],
"automerge": true,
"automergeStrategy": "squash",
"dependencyDashboard": true,
"schedule": ["every weekend"],
"ignorePaths": ["modules/**"]

automerge: true,
automergeStrategy: "squash",
dependencyDashboard: true,
schedule: ["every weekend"],
ignorePaths: ["modules/**"],
}
6 changes: 3 additions & 3 deletions .github/workflows/codeql.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,14 +34,14 @@ jobs:
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8

- name: Initialize CodeQL
uses: github/codeql-action/init@4b675e451b3779918647db783e324bd9fd7f3932
uses: github/codeql-action/init@f67ec12472e1b361f5e1e2085f5e6f85a57e3cd6
with:
languages: ${{ matrix.language }}

- name: Autobuild
uses: github/codeql-action/autobuild@4b675e451b3779918647db783e324bd9fd7f3932
uses: github/codeql-action/autobuild@f67ec12472e1b361f5e1e2085f5e6f85a57e3cd6

- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@4b675e451b3779918647db783e324bd9fd7f3932
uses: github/codeql-action/analyze@f67ec12472e1b361f5e1e2085f5e6f85a57e3cd6
with:
category: '/language:${{ matrix.language }}'
2 changes: 1 addition & 1 deletion .github/workflows/scorecard.yml
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,6 @@ jobs:
# Upload the results to GitHub's code scanning dashboard (optional).
# Commenting out will disable upload of results to your repo's Code Scanning dashboard
- name: 'Upload to code-scanning'
uses: github/codeql-action/upload-sarif@1b168cd39490f61582a9beae412bb7057a6b2c4e # v4.31.8
uses: github/codeql-action/upload-sarif@5d4e8d1aca955e8d8589aabd499c5cae939e33c7 # v4.31.9
with:
sarif_file: results.sarif
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "alasql",
"description": "Use SQL to select and filter javascript data - including relational joins and search in nested objects (JSON). Export to and import from Excel and CSV",
"version": "4.14.0",
"version": "4.15.0",
"author": "Andrey Gershun <agershun@gmail.com>",
"contributors": [
"Mathias Wulff <m@rawu.dk>"
Expand Down Expand Up @@ -65,7 +65,7 @@
"blueimp-md5": "2.19.0",
"cmdmix": "2.2.2",
"dom-storage": "2.1.0",
"esbuild": "0.27.1",
"esbuild": "0.27.2",
"git-branch-is": "4.0.0",
"husky": "9.1.7",
"jison": "^0.4.18",
Expand Down
2 changes: 1 addition & 1 deletion src/15utility.js
Original file line number Diff line number Diff line change
Expand Up @@ -349,7 +349,7 @@ let loadFile = (utils.loadFile = function (path, asy, success, error) {
try {
data = fs.readFileSync(path);
} catch (e) {
error(err, null);
error(e, null);
return;
}

Expand Down
44 changes: 31 additions & 13 deletions src/35search.js
Original file line number Diff line number Diff line change
Expand Up @@ -690,20 +690,38 @@ yy.Search = class Search {
}

if (this.into) {
var a1, a2;
if (typeof this.into.args[0] !== 'undefined') {
a1 = new Function('params,alasql', 'var y;return ' + this.into.args[0].toJS())(
params,
alasql
);
}
if (typeof this.into.args[1] !== 'undefined') {
a2 = new Function('params,alasql', 'var y;return ' + this.into.args[1].toJS())(
params,
alasql
);
// Handle different INTO types
if (this.into instanceof yy.ParamValue) {
// INTO $variable or INTO ?
if (typeof this.into.param === 'string') {
// $variable syntax - replace the variable
params[this.into.param] = res;
} else {
// ? syntax - assign to parameter
params[this.into.param] = res;
}
if (cb) res = cb(res);
} else if (this.into instanceof yy.VarValue) {
// INTO @variable
alasql.vars[this.into.variable] = res;
if (cb) res = cb(res);
} else {
// INTO function (TXT(), JSON(), etc.)
var a1, a2;
if (typeof this.into.args[0] !== 'undefined') {
a1 = new Function('params,alasql', 'var y;return ' + this.into.args[0].toJS())(
params,
alasql
);
}
if (typeof this.into.args[1] !== 'undefined') {
a2 = new Function('params,alasql', 'var y;return ' + this.into.args[1].toJS())(
params,
alasql
);
}
res = alasql.into[this.into.funcid.toUpperCase()](a1, a2, res, [], cb);
}
res = alasql.into[this.into.funcid.toUpperCase()](a1, a2, res, [], cb);
} else {
if (stope.value && res.length > 0) {
res = res[0];
Expand Down
16 changes: 15 additions & 1 deletion src/40select.js
Original file line number Diff line number Diff line change
Expand Up @@ -344,8 +344,22 @@ yy.Select = class Select {
//
// Save data into parameters array
// like alasql('SELECT * INTO ? FROM ?',[outdata,srcdata]);
// or SELECT * INTO $variable FROM ?
//
query.intofns = `params[${JSON.stringify(this.into.param)}].push(r)`;
// Distinguish between ? (numeric param - push to array) and $variable (string param - replace array)
if (typeof this.into.param === 'string') {
// $variable syntax - replace the array
query.intoallfns = `
if(!params[${JSON.stringify(this.into.param)}]) params[${JSON.stringify(this.into.param)}]=[];
params[${JSON.stringify(this.into.param)}]=this.data;
res=this.data.length;
if(cb) res = cb(res);
return res;
`;
} else {
// ? syntax - push to existing array
query.intofns = `params[${JSON.stringify(this.into.param)}].push(r)`;
}
}

if (query.intofns) {
Expand Down
2 changes: 1 addition & 1 deletion src/50expression.js
Original file line number Diff line number Diff line change
Expand Up @@ -507,7 +507,7 @@
return '(' + declareRefs + ', ' + expr + ')';
}

return `(${declareRefs}, y.some(e => e == null) ? void 0 : ${expr})`;
return `(${declareRefs}, y.some(e => e == null || (typeof e === 'number' && isNaN(e))) ? void 0 : ${expr})`;
}
}

Expand Down
107 changes: 54 additions & 53 deletions src/60createtable.js
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ yy.CreateTable.prototype.execute = function (databaseid, params, cb) {
if (col.check) {
table.checks.push({
id: col.check.constrantid,
fn: new Function('r', 'var y;return ' + col.check.expression.toJS('r', '')),
fn: new Function('r,params,alasql', 'var y;return ' + col.check.expression.toJS('r', '')),
});
}

Expand Down Expand Up @@ -166,21 +166,25 @@ yy.CreateTable.prototype.execute = function (databaseid, params, cb) {
throw new Error('FOREIGN KEY allowed only to tables with PRIMARY KEYs');
}
}
// Store foreignkey property in column for later access
newcol.foreignkey = {
tableid: fk.tableid,
columnid: fk.columnid,
};
var fkfn = function (r) {
var rr = {};
if (typeof r[col.columnid] === 'undefined') {
return true;
}
rr[fk.columnid] = r[col.columnid];
var addr = fktable.pk.onrightfn(rr);
if (!fktable.uniqs[fktable.pk.hh][addr]) {
throw new Error(
'Foreign key "' + r[col.columnid] + '" not found in table "' + fk.tableid + '"'
);
var val = r[col.columnid];
// Only check foreign key if value is not null, undefined, or NaN
if (val != null && !(typeof val === 'number' && isNaN(val))) {
rr[fk.columnid] = val;
var addr = fktable.pk.onrightfn(rr);
if (!fktable.uniqs[fktable.pk.hh][addr]) {
throw new Error('Foreign key "' + val + '" not found in table "' + fk.tableid + '"');
}
}
return true;
};
table.checks.push({fn: fkfn});
table.checks.push({fn: fkfn, fk: true});
}

if (col.onupdate) {
Expand Down Expand Up @@ -211,8 +215,14 @@ yy.CreateTable.prototype.execute = function (databaseid, params, cb) {
pk.onrightfn = new Function('r', 'var y;return ' + pk.onrightfns);
pk.hh = hash(pk.onrightfns);
table.uniqs[pk.hh] = {};
// Mark columns with primarykey property
pk.columns.forEach(function (columnid) {
if (table.xcolumns[columnid]) {
table.xcolumns[columnid].primarykey = true;
}
});
} else if (con.type === 'CHECK') {
checkfn = new Function('r', 'var y;return ' + con.expression.toJS('r', ''));
checkfn = new Function('r,params,alasql', 'var y;return ' + con.expression.toJS('r', ''));
} else if (con.type === 'UNIQUE') {
var uk = {};
table.uk = table.uk || [];
Expand Down Expand Up @@ -243,13 +253,26 @@ yy.CreateTable.prototype.execute = function (databaseid, params, cb) {
throw new Error('Invalid foreign key on table ' + table.tableid);
}

// Mark columns with foreignkey property
fk.columns.forEach(function (columnid, i) {
if (table.xcolumns[columnid]) {
table.xcolumns[columnid].foreignkey = {
tableid: fk.tableid,
columnid: fk.fkcolumns[i],
constraintid: con.constraintid,
};
}
});

checkfn = function (r) {
var rr = {};

//Composite foreign keys
fk.fkcolumns.forEach(function (colFk, i) {
if (r[fk.columns[i]] != null) {
rr[colFk] = r[fk.columns[i]];
var val = r[fk.columns[i]];
// Only include non-null, non-undefined, non-NaN values
if (val != null && !(typeof val === 'number' && isNaN(val))) {
rr[colFk] = val;
}
});

Expand Down Expand Up @@ -332,10 +355,8 @@ yy.CreateTable.prototype.execute = function (databaseid, params, cb) {
for (var tr in table.beforeinsert) {
var trigger = table.beforeinsert[tr];
if (trigger) {
if (trigger.funcid) {
if (alasql.fn[trigger.funcid](r) === false) prevent = prevent || true;
} else if (trigger.statement) {
if (trigger.statement.execute(databaseid) === false) prevent = prevent || true;
if (alasql.executeTrigger(trigger, databaseid, r) === false) {
prevent = prevent || true;
}
}
}
Expand All @@ -347,11 +368,7 @@ yy.CreateTable.prototype.execute = function (databaseid, params, cb) {
escape = true;
trigger = table.insteadofinsert[tr];
if (trigger) {
if (trigger.funcid) {
alasql.fn[trigger.funcid](r);
} else if (trigger.statement) {
trigger.statement.execute(databaseid);
}
alasql.executeTrigger(trigger, databaseid, r);
}
}
if (escape) return;
Expand All @@ -371,7 +388,9 @@ yy.CreateTable.prototype.execute = function (databaseid, params, cb) {

if (table.checks && table.checks.length > 0) {
table.checks.forEach(function (check) {
if (!check.fn(r)) {
// In SQL, CHECK constraints treat NULL (undefined) as passing
// Only fail if the check explicitly returns false
if (check.fn(r, {}, alasql) === false) {
// if(orreplace) toreplace=true; else
throw new Error('Violation of CHECK constraint ' + (check.id || ''));
}
Expand Down Expand Up @@ -488,11 +507,7 @@ yy.CreateTable.prototype.execute = function (databaseid, params, cb) {
for (var tr in table.afterinsert) {
var trigger = table.afterinsert[tr];
if (trigger) {
if (trigger.funcid) {
alasql.fn[trigger.funcid](r);
} else if (trigger.statement) {
trigger.statement.execute(databaseid);
}
alasql.executeTrigger(trigger, databaseid, r);
}
}
alasql.inserted = oldinserted;
Expand All @@ -507,10 +522,8 @@ yy.CreateTable.prototype.execute = function (databaseid, params, cb) {
for (var tr in table.beforedelete) {
var trigger = table.beforedelete[tr];
if (trigger) {
if (trigger.funcid) {
if (alasql.fn[trigger.funcid](r) === false) prevent = prevent || true;
} else if (trigger.statement) {
if (trigger.statement.execute(databaseid) === false) prevent = prevent || true;
if (alasql.executeTrigger(trigger, databaseid, r) === false) {
prevent = prevent || true;
}
}
}
Expand All @@ -522,11 +535,7 @@ yy.CreateTable.prototype.execute = function (databaseid, params, cb) {
escape = true;
var trigger = table.insteadofdelete[tr];
if (trigger) {
if (trigger.funcid) {
alasql.fn[trigger.funcid](r);
} else if (trigger.statement) {
trigger.statement.execute(databaseid);
}
alasql.executeTrigger(trigger, databaseid, r);
}
}
if (escape) return;
Expand Down Expand Up @@ -613,10 +622,8 @@ yy.CreateTable.prototype.execute = function (databaseid, params, cb) {
for (var tr in table.beforeupdate) {
var trigger = table.beforeupdate[tr];
if (trigger) {
if (trigger.funcid) {
if (alasql.fn[trigger.funcid](this.data[i], r) === false) prevent = prevent || true;
} else if (trigger.statement) {
if (trigger.statement.execute(databaseid) === false) prevent = prevent || true;
if (alasql.executeTrigger(trigger, databaseid, this.data[i], r) === false) {
prevent = prevent || true;
}
}
}
Expand All @@ -628,19 +635,17 @@ yy.CreateTable.prototype.execute = function (databaseid, params, cb) {
escape = true;
var trigger = table.insteadofupdate[tr];
if (trigger) {
if (trigger.funcid) {
alasql.fn[trigger.funcid](this.data[i], r);
} else if (trigger.statement) {
trigger.statement.execute(databaseid);
}
alasql.executeTrigger(trigger, databaseid, this.data[i], r);
}
}
if (escape) return;

// PART 2 - POST CHECK
if (table.checks && table.checks.length > 0) {
table.checks.forEach(function (check) {
if (!check.fn(r)) {
// In SQL, CHECK constraints treat NULL (undefined) as passing
// Only fail if the check explicitly returns false
if (check.fn(r, params, alasql) === false) {
throw new Error('Violation of CHECK constraint ' + (check.id || ''));
}
});
Expand Down Expand Up @@ -685,11 +690,7 @@ yy.CreateTable.prototype.execute = function (databaseid, params, cb) {
for (var tr in table.afterupdate) {
var trigger = table.afterupdate[tr];
if (trigger) {
if (trigger.funcid) {
alasql.fn[trigger.funcid](this.data[i], r);
} else if (trigger.statement) {
trigger.statement.execute(databaseid);
}
alasql.executeTrigger(trigger, databaseid, this.data[i], r);
}
}
};
Expand Down
Loading
Loading