leangraph 1.1.4 → 1.1.8
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/auth.d.ts.map +1 -1
- package/dist/auth.js +3 -6
- package/dist/auth.js.map +1 -1
- package/dist/db.d.ts +3 -1
- package/dist/db.d.ts.map +1 -1
- package/dist/db.js +38 -7
- package/dist/db.js.map +1 -1
- package/dist/executor.d.ts +1 -0
- package/dist/executor.d.ts.map +1 -1
- package/dist/executor.js +48 -36
- package/dist/executor.js.map +1 -1
- package/dist/parser.d.ts +2 -0
- package/dist/parser.d.ts.map +1 -1
- package/dist/parser.js +32 -12
- package/dist/parser.js.map +1 -1
- package/dist/routes.d.ts +1 -3
- package/dist/routes.d.ts.map +1 -1
- package/dist/routes.js +147 -102
- package/dist/routes.js.map +1 -1
- package/dist/translator.d.ts.map +1 -1
- package/dist/translator.js +105 -92
- package/dist/translator.js.map +1 -1
- package/package.json +3 -3
package/dist/executor.js
CHANGED
|
@@ -1,4 +1,11 @@
|
|
|
1
1
|
// Query Executor - Full pipeline: Cypher → Parse → Translate → Execute → Format
|
|
2
|
+
/**
|
|
3
|
+
* Escape a string for safe interpolation inside a SQL string literal.
|
|
4
|
+
* Prevents SQL injection via backtick-quoted Cypher identifiers.
|
|
5
|
+
*/
|
|
6
|
+
function escSqlStr(s) {
|
|
7
|
+
return (s || "").replace(/'/g, "''");
|
|
8
|
+
}
|
|
2
9
|
import { parse, } from "./parser.js";
|
|
3
10
|
import { Translator } from "./translator.js";
|
|
4
11
|
import { HybridExecutor } from "./engine/hybrid-executor.js";
|
|
@@ -215,15 +222,20 @@ export class Executor {
|
|
|
215
222
|
if (flags.hasWith || flags.hasReturn) {
|
|
216
223
|
this.validateOrderByVariables(parseResult.query, params);
|
|
217
224
|
}
|
|
225
|
+
// Maximum number of results to return (security limit)
|
|
226
|
+
const MAX_RESULTS_LIMIT = 10000;
|
|
218
227
|
// Helper to return successful result
|
|
219
228
|
const makeResult = (data) => {
|
|
220
229
|
const endTime = performance.now();
|
|
230
|
+
const truncated = data.length > MAX_RESULTS_LIMIT;
|
|
231
|
+
const limitedData = truncated ? data.slice(0, MAX_RESULTS_LIMIT) : data;
|
|
221
232
|
return {
|
|
222
233
|
success: true,
|
|
223
|
-
data,
|
|
234
|
+
data: limitedData,
|
|
224
235
|
meta: {
|
|
225
|
-
count:
|
|
236
|
+
count: limitedData.length,
|
|
226
237
|
time_ms: Math.round((endTime - startTime) * 100) / 100,
|
|
238
|
+
truncated,
|
|
227
239
|
},
|
|
228
240
|
};
|
|
229
241
|
};
|
|
@@ -1850,7 +1862,7 @@ export class Executor {
|
|
|
1850
1862
|
}
|
|
1851
1863
|
// Property conditions
|
|
1852
1864
|
for (const [key, value] of Object.entries(props)) {
|
|
1853
|
-
conditions.push(`json_extract(properties, '$.${key}') = ?`);
|
|
1865
|
+
conditions.push(`json_extract(properties, '$.${escSqlStr(key)}') = ?`);
|
|
1854
1866
|
conditionParams.push(value);
|
|
1855
1867
|
}
|
|
1856
1868
|
// Find existing nodes
|
|
@@ -1927,11 +1939,11 @@ export class Executor {
|
|
|
1927
1939
|
for (const [key, value] of Object.entries(edgeProps)) {
|
|
1928
1940
|
if (Array.isArray(value) || (typeof value === "object" && value !== null)) {
|
|
1929
1941
|
// For arrays and objects, compare JSON representations
|
|
1930
|
-
propConditions += ` AND json_extract(properties, '$.${key}') = json(?)`;
|
|
1942
|
+
propConditions += ` AND json_extract(properties, '$.${escSqlStr(key)}') = json(?)`;
|
|
1931
1943
|
propParams.push(JSON.stringify(value));
|
|
1932
1944
|
}
|
|
1933
1945
|
else {
|
|
1934
|
-
propConditions += ` AND json_extract(properties, '$.${key}') = ?`;
|
|
1946
|
+
propConditions += ` AND json_extract(properties, '$.${escSqlStr(key)}') = ?`;
|
|
1935
1947
|
propParams.push(value);
|
|
1936
1948
|
}
|
|
1937
1949
|
}
|
|
@@ -3248,7 +3260,7 @@ export class Executor {
|
|
|
3248
3260
|
continue;
|
|
3249
3261
|
if (assignment.property && assignment.value) {
|
|
3250
3262
|
const value = this.evaluateExpressionInRow(assignment.value, row, params);
|
|
3251
|
-
this.db.execute(`UPDATE nodes SET properties = json_set(properties, '$.${assignment.property}', json(?)) WHERE id = ?`, [JSON.stringify(value), nodeId]);
|
|
3263
|
+
this.db.execute(`UPDATE nodes SET properties = json_set(properties, '$.${escSqlStr(assignment.property)}', json(?)) WHERE id = ?`, [JSON.stringify(value), nodeId]);
|
|
3252
3264
|
// Invalidate cache after UPDATE
|
|
3253
3265
|
this.invalidatePropertyCache(nodeId);
|
|
3254
3266
|
}
|
|
@@ -3308,12 +3320,12 @@ export class Executor {
|
|
|
3308
3320
|
// Not valid JSON, treat as node ID
|
|
3309
3321
|
}
|
|
3310
3322
|
// Try as node ID
|
|
3311
|
-
let result = this.db.execute(`SELECT json_extract(properties, '$.${expr.property}') as value FROM nodes WHERE id = ?`, [varValue]);
|
|
3323
|
+
let result = this.db.execute(`SELECT json_extract(properties, '$.${escSqlStr(expr.property)}') as value FROM nodes WHERE id = ?`, [varValue]);
|
|
3312
3324
|
if (result.rows.length > 0) {
|
|
3313
3325
|
return this.deepParseJson(result.rows[0].value);
|
|
3314
3326
|
}
|
|
3315
3327
|
// Try edges
|
|
3316
|
-
result = this.db.execute(`SELECT json_extract(properties, '$.${expr.property}') as value FROM edges WHERE id = ?`, [varValue]);
|
|
3328
|
+
result = this.db.execute(`SELECT json_extract(properties, '$.${escSqlStr(expr.property)}') as value FROM edges WHERE id = ?`, [varValue]);
|
|
3317
3329
|
if (result.rows.length > 0) {
|
|
3318
3330
|
return this.deepParseJson(result.rows[0].value);
|
|
3319
3331
|
}
|
|
@@ -4725,7 +4737,7 @@ export class Executor {
|
|
|
4725
4737
|
whereParams.push(nodePattern.label, nodePattern.label, nodePattern.label);
|
|
4726
4738
|
}
|
|
4727
4739
|
for (const [key, value] of Object.entries(props)) {
|
|
4728
|
-
whereConditions.push(`json_extract(properties, '$.${key}') = ?`);
|
|
4740
|
+
whereConditions.push(`json_extract(properties, '$.${escSqlStr(key)}') = ?`);
|
|
4729
4741
|
whereParams.push(value);
|
|
4730
4742
|
}
|
|
4731
4743
|
const existsQuery = whereConditions.length > 0
|
|
@@ -6277,7 +6289,7 @@ export class Executor {
|
|
|
6277
6289
|
conditionParams.push(...labelCondition.params);
|
|
6278
6290
|
}
|
|
6279
6291
|
for (const [key, value] of Object.entries(matchProps)) {
|
|
6280
|
-
conditions.push(`json_extract(properties, '$.${key}') = ?`);
|
|
6292
|
+
conditions.push(`json_extract(properties, '$.${escSqlStr(key)}') = ?`);
|
|
6281
6293
|
conditionParams.push(value);
|
|
6282
6294
|
}
|
|
6283
6295
|
const sql = conditions.length > 0
|
|
@@ -6362,7 +6374,7 @@ export class Executor {
|
|
|
6362
6374
|
conditionParams.push(...labelCondition.params);
|
|
6363
6375
|
}
|
|
6364
6376
|
for (const [key, value] of Object.entries(matchProps)) {
|
|
6365
|
-
conditions.push(`json_extract(properties, '$.${key}') = ?`);
|
|
6377
|
+
conditions.push(`json_extract(properties, '$.${escSqlStr(key)}') = ?`);
|
|
6366
6378
|
conditionParams.push(value);
|
|
6367
6379
|
}
|
|
6368
6380
|
// Try to find existing node
|
|
@@ -6403,7 +6415,7 @@ export class Executor {
|
|
|
6403
6415
|
if (!assignment.value || !assignment.property)
|
|
6404
6416
|
continue;
|
|
6405
6417
|
const value = this.evaluateExpressionWithMatchedNodes(assignment.value, params, matchedNodes);
|
|
6406
|
-
this.db.execute(`UPDATE nodes SET properties = json_set(properties, '$.${assignment.property}', json(?)) WHERE id = ?`, [JSON.stringify(value), nodeId]);
|
|
6418
|
+
this.db.execute(`UPDATE nodes SET properties = json_set(properties, '$.${escSqlStr(assignment.property)}', json(?)) WHERE id = ?`, [JSON.stringify(value), nodeId]);
|
|
6407
6419
|
// Invalidate cache after UPDATE
|
|
6408
6420
|
this.invalidatePropertyCache(nodeId);
|
|
6409
6421
|
}
|
|
@@ -6454,7 +6466,7 @@ export class Executor {
|
|
|
6454
6466
|
if (!assignment.value || !assignment.property)
|
|
6455
6467
|
continue;
|
|
6456
6468
|
const value = this.evaluateExpressionWithMatchedNodes(assignment.value, params, matchedNodes);
|
|
6457
|
-
this.db.execute(`UPDATE edges SET properties = json_set(properties, '$.${assignment.property}', json(?)) WHERE id = ?`, [JSON.stringify(value), edgeId]);
|
|
6469
|
+
this.db.execute(`UPDATE edges SET properties = json_set(properties, '$.${escSqlStr(assignment.property)}', json(?)) WHERE id = ?`, [JSON.stringify(value), edgeId]);
|
|
6458
6470
|
}
|
|
6459
6471
|
}
|
|
6460
6472
|
}
|
|
@@ -6738,7 +6750,7 @@ export class Executor {
|
|
|
6738
6750
|
conditionParams.push(...labelCondition.params);
|
|
6739
6751
|
}
|
|
6740
6752
|
for (const [key, value] of Object.entries(matchProps)) {
|
|
6741
|
-
conditions.push(`json_extract(properties, '$.${key}') = ?`);
|
|
6753
|
+
conditions.push(`json_extract(properties, '$.${escSqlStr(key)}') = ?`);
|
|
6742
6754
|
conditionParams.push(value);
|
|
6743
6755
|
}
|
|
6744
6756
|
const findSql = conditions.length > 0
|
|
@@ -6844,7 +6856,7 @@ export class Executor {
|
|
|
6844
6856
|
conditionParams.push(...labelCondition.params);
|
|
6845
6857
|
}
|
|
6846
6858
|
for (const [key, value] of Object.entries(matchProps)) {
|
|
6847
|
-
conditions.push(`json_extract(properties, '$.${key}') = ?`);
|
|
6859
|
+
conditions.push(`json_extract(properties, '$.${escSqlStr(key)}') = ?`);
|
|
6848
6860
|
conditionParams.push(value);
|
|
6849
6861
|
}
|
|
6850
6862
|
// Try to find existing node
|
|
@@ -6903,7 +6915,7 @@ export class Executor {
|
|
|
6903
6915
|
if (!assignment.value || !assignment.property)
|
|
6904
6916
|
continue;
|
|
6905
6917
|
const value = this.evaluateExpressionWithMatchedNodes(assignment.value, params, matchedNodes);
|
|
6906
|
-
this.db.execute(`UPDATE nodes SET properties = json_set(properties, '$.${assignment.property}', json(?)) WHERE id = ?`, [JSON.stringify(value), nodeId]);
|
|
6918
|
+
this.db.execute(`UPDATE nodes SET properties = json_set(properties, '$.${escSqlStr(assignment.property)}', json(?)) WHERE id = ?`, [JSON.stringify(value), nodeId]);
|
|
6907
6919
|
// Invalidate cache after UPDATE
|
|
6908
6920
|
this.invalidatePropertyCache(nodeId);
|
|
6909
6921
|
}
|
|
@@ -6986,7 +6998,7 @@ export class Executor {
|
|
|
6986
6998
|
findEdgeParams.push(edgeType);
|
|
6987
6999
|
}
|
|
6988
7000
|
for (const [key, value] of Object.entries(edgeProps)) {
|
|
6989
|
-
findEdgeConditions.push(`json_extract(properties, '$.${key}') = ?`);
|
|
7001
|
+
findEdgeConditions.push(`json_extract(properties, '$.${escSqlStr(key)}') = ?`);
|
|
6990
7002
|
findEdgeParams.push(value);
|
|
6991
7003
|
}
|
|
6992
7004
|
const findEdgeSql = `SELECT id, type, source_id, target_id, properties FROM edges WHERE ${findEdgeConditions.join(" AND ")}`;
|
|
@@ -7025,7 +7037,7 @@ export class Executor {
|
|
|
7025
7037
|
// Check if assignment is for the edge variable
|
|
7026
7038
|
if (pattern.edge.variable && assignment.variable === pattern.edge.variable) {
|
|
7027
7039
|
const value = this.evaluateExpression(assignment.value, params);
|
|
7028
|
-
this.db.execute(`UPDATE edges SET properties = json_set(properties, '$.${assignment.property}', json(?)) WHERE id = ?`, [JSON.stringify(value), edgeId]);
|
|
7040
|
+
this.db.execute(`UPDATE edges SET properties = json_set(properties, '$.${escSqlStr(assignment.property)}', json(?)) WHERE id = ?`, [JSON.stringify(value), edgeId]);
|
|
7029
7041
|
}
|
|
7030
7042
|
}
|
|
7031
7043
|
}
|
|
@@ -7170,7 +7182,7 @@ export class Executor {
|
|
|
7170
7182
|
conditionParams.push(...labelCondition.params);
|
|
7171
7183
|
}
|
|
7172
7184
|
for (const [key, value] of Object.entries(matchProps)) {
|
|
7173
|
-
conditions.push(`json_extract(properties, '$.${key}') = ?`);
|
|
7185
|
+
conditions.push(`json_extract(properties, '$.${escSqlStr(key)}') = ?`);
|
|
7174
7186
|
conditionParams.push(value);
|
|
7175
7187
|
}
|
|
7176
7188
|
// Try to find existing node
|
|
@@ -7249,7 +7261,7 @@ export class Executor {
|
|
|
7249
7261
|
const value = assignment.value.type === "property" || assignment.value.type === "binary"
|
|
7250
7262
|
? this.evaluateExpressionWithContext(assignment.value, params, resolvedIds)
|
|
7251
7263
|
: this.evaluateExpression(assignment.value, params);
|
|
7252
|
-
this.db.execute(`UPDATE nodes SET properties = json_set(properties, '$.${assignment.property}', json(?)) WHERE id = ?`, [JSON.stringify(value), nodeId]);
|
|
7264
|
+
this.db.execute(`UPDATE nodes SET properties = json_set(properties, '$.${escSqlStr(assignment.property)}', json(?)) WHERE id = ?`, [JSON.stringify(value), nodeId]);
|
|
7253
7265
|
// Invalidate cache after UPDATE
|
|
7254
7266
|
this.invalidatePropertyCache(nodeId);
|
|
7255
7267
|
}
|
|
@@ -7337,7 +7349,7 @@ export class Executor {
|
|
|
7337
7349
|
}
|
|
7338
7350
|
// Add edge property conditions if any
|
|
7339
7351
|
for (const [key, value] of Object.entries(edgeProps)) {
|
|
7340
|
-
findEdgeConditions.push(`json_extract(properties, '$.${key}') = ?`);
|
|
7352
|
+
findEdgeConditions.push(`json_extract(properties, '$.${escSqlStr(key)}') = ?`);
|
|
7341
7353
|
findEdgeParams.push(value);
|
|
7342
7354
|
}
|
|
7343
7355
|
const findEdgeSql = `SELECT id, type, source_id, target_id, properties FROM edges WHERE ${findEdgeConditions.join(" AND ")}`;
|
|
@@ -7360,7 +7372,7 @@ export class Executor {
|
|
|
7360
7372
|
continue;
|
|
7361
7373
|
const value = this.evaluateExpression(assignment.value, params);
|
|
7362
7374
|
// Update target node with ON CREATE SET
|
|
7363
|
-
this.db.execute(`UPDATE nodes SET properties = json_set(properties, '$.${assignment.property}', json(?)) WHERE id = ?`, [JSON.stringify(value), targetNodeId]);
|
|
7375
|
+
this.db.execute(`UPDATE nodes SET properties = json_set(properties, '$.${escSqlStr(assignment.property)}', json(?)) WHERE id = ?`, [JSON.stringify(value), targetNodeId]);
|
|
7364
7376
|
// Invalidate cache after UPDATE
|
|
7365
7377
|
this.invalidatePropertyCache(targetNodeId);
|
|
7366
7378
|
}
|
|
@@ -7379,7 +7391,7 @@ export class Executor {
|
|
|
7379
7391
|
continue;
|
|
7380
7392
|
const value = this.evaluateExpression(assignment.value, params);
|
|
7381
7393
|
// Update target node with ON MATCH SET
|
|
7382
|
-
this.db.execute(`UPDATE nodes SET properties = json_set(properties, '$.${assignment.property}', json(?)) WHERE id = ?`, [JSON.stringify(value), targetNodeId]);
|
|
7394
|
+
this.db.execute(`UPDATE nodes SET properties = json_set(properties, '$.${escSqlStr(assignment.property)}', json(?)) WHERE id = ?`, [JSON.stringify(value), targetNodeId]);
|
|
7383
7395
|
// Invalidate cache after UPDATE
|
|
7384
7396
|
this.invalidatePropertyCache(targetNodeId);
|
|
7385
7397
|
}
|
|
@@ -7430,7 +7442,7 @@ export class Executor {
|
|
|
7430
7442
|
conditionParams.push(...labelCondition.params);
|
|
7431
7443
|
}
|
|
7432
7444
|
for (const [key, value] of Object.entries(props)) {
|
|
7433
|
-
conditions.push(`json_extract(properties, '$.${key}') = ?`);
|
|
7445
|
+
conditions.push(`json_extract(properties, '$.${escSqlStr(key)}') = ?`);
|
|
7434
7446
|
conditionParams.push(value);
|
|
7435
7447
|
}
|
|
7436
7448
|
// If we have conditions, try to find existing node
|
|
@@ -7912,7 +7924,7 @@ export class Executor {
|
|
|
7912
7924
|
if (assignment.property) {
|
|
7913
7925
|
// SET n.prop = value
|
|
7914
7926
|
const propName = assignment.property;
|
|
7915
|
-
const sql = `UPDATE ${table} SET properties = json_set(properties, '$.${propName}', json(?)) WHERE id = ?`;
|
|
7927
|
+
const sql = `UPDATE ${table} SET properties = json_set(properties, '$.${escSqlStr(propName)}', json(?)) WHERE id = ?`;
|
|
7916
7928
|
this.db.execute(sql, [JSON.stringify(newValue), nodeId]);
|
|
7917
7929
|
// Update the row object so subsequent iterations see the new value
|
|
7918
7930
|
target[propName] = newValue;
|
|
@@ -8939,13 +8951,13 @@ export class Executor {
|
|
|
8939
8951
|
const nodeId = resolvedIds[variable];
|
|
8940
8952
|
if (nodeId) {
|
|
8941
8953
|
// Try nodes first
|
|
8942
|
-
const nodeResult = this.db.execute(`SELECT json_extract(properties, '$.${property}') as value FROM nodes WHERE id = ?`, [nodeId]);
|
|
8954
|
+
const nodeResult = this.db.execute(`SELECT json_extract(properties, '$.${escSqlStr(property)}') as value FROM nodes WHERE id = ?`, [nodeId]);
|
|
8943
8955
|
if (nodeResult.rows.length > 0) {
|
|
8944
8956
|
resultRow[alias] = this.deepParseJson(nodeResult.rows[0].value);
|
|
8945
8957
|
}
|
|
8946
8958
|
else {
|
|
8947
8959
|
// Try edges
|
|
8948
|
-
const edgeResult = this.db.execute(`SELECT json_extract(properties, '$.${property}') as value FROM edges WHERE id = ?`, [nodeId]);
|
|
8960
|
+
const edgeResult = this.db.execute(`SELECT json_extract(properties, '$.${escSqlStr(property)}') as value FROM edges WHERE id = ?`, [nodeId]);
|
|
8949
8961
|
if (edgeResult.rows.length > 0) {
|
|
8950
8962
|
resultRow[alias] = this.deepParseJson(edgeResult.rows[0].value);
|
|
8951
8963
|
}
|
|
@@ -9043,7 +9055,7 @@ export class Executor {
|
|
|
9043
9055
|
const nodeId = resolvedIds[arg.variable];
|
|
9044
9056
|
if (nodeId) {
|
|
9045
9057
|
// Try nodes first
|
|
9046
|
-
const nodeResult = this.db.execute(`SELECT json_extract(properties, '$.${arg.property}') as value FROM nodes WHERE id = ?`, [nodeId]);
|
|
9058
|
+
const nodeResult = this.db.execute(`SELECT json_extract(properties, '$.${escSqlStr(arg.property)}') as value FROM nodes WHERE id = ?`, [nodeId]);
|
|
9047
9059
|
if (nodeResult.rows.length > 0) {
|
|
9048
9060
|
const value = this.deepParseJson(nodeResult.rows[0].value);
|
|
9049
9061
|
if (Array.isArray(value)) {
|
|
@@ -9058,7 +9070,7 @@ export class Executor {
|
|
|
9058
9070
|
}
|
|
9059
9071
|
else {
|
|
9060
9072
|
// Try edges
|
|
9061
|
-
const edgeResult = this.db.execute(`SELECT json_extract(properties, '$.${arg.property}') as value FROM edges WHERE id = ?`, [nodeId]);
|
|
9073
|
+
const edgeResult = this.db.execute(`SELECT json_extract(properties, '$.${escSqlStr(arg.property)}') as value FROM edges WHERE id = ?`, [nodeId]);
|
|
9062
9074
|
if (edgeResult.rows.length > 0) {
|
|
9063
9075
|
const value = this.deepParseJson(edgeResult.rows[0].value);
|
|
9064
9076
|
if (Array.isArray(value)) {
|
|
@@ -9157,7 +9169,7 @@ export class Executor {
|
|
|
9157
9169
|
}
|
|
9158
9170
|
if (nullKeys.length > 0) {
|
|
9159
9171
|
// Need to merge non-null props and remove null keys
|
|
9160
|
-
const removePaths = nullKeys.map(k => `'$.${k}'`).join(', ');
|
|
9172
|
+
const removePaths = nullKeys.map(k => `'$.${escSqlStr(k)}'`).join(', ');
|
|
9161
9173
|
const nodeResult = this.db.execute(`UPDATE nodes SET properties = json_remove(json_patch(properties, ?), ${removePaths}) WHERE id = ?`, [JSON.stringify(nonNullProps), nodeId]);
|
|
9162
9174
|
if (nodeResult.changes === 0) {
|
|
9163
9175
|
this.db.execute(`UPDATE edges SET properties = json_remove(json_patch(properties, ?), ${removePaths}) WHERE id = ?`, [JSON.stringify(nonNullProps), nodeId]);
|
|
@@ -9184,19 +9196,19 @@ export class Executor {
|
|
|
9184
9196
|
: this.evaluateExpression(assignment.value, params);
|
|
9185
9197
|
// If value is null, remove the property instead of setting it to null
|
|
9186
9198
|
if (value === null) {
|
|
9187
|
-
const nodeResult = this.db.execute(`UPDATE nodes SET properties = json_remove(properties, '$.${assignment.property}') WHERE id = ?`, [nodeId]);
|
|
9199
|
+
const nodeResult = this.db.execute(`UPDATE nodes SET properties = json_remove(properties, '$.${escSqlStr(assignment.property)}') WHERE id = ?`, [nodeId]);
|
|
9188
9200
|
if (nodeResult.changes === 0) {
|
|
9189
|
-
this.db.execute(`UPDATE edges SET properties = json_remove(properties, '$.${assignment.property}') WHERE id = ?`, [nodeId]);
|
|
9201
|
+
this.db.execute(`UPDATE edges SET properties = json_remove(properties, '$.${escSqlStr(assignment.property)}') WHERE id = ?`, [nodeId]);
|
|
9190
9202
|
}
|
|
9191
9203
|
}
|
|
9192
9204
|
else {
|
|
9193
9205
|
// Update the property using json_set
|
|
9194
9206
|
// We need to determine if it's a node or edge - for now assume node
|
|
9195
9207
|
// Try nodes first, then edges
|
|
9196
|
-
const nodeResult = this.db.execute(`UPDATE nodes SET properties = json_set(properties, '$.${assignment.property}', json(?)) WHERE id = ?`, [JSON.stringify(value), nodeId]);
|
|
9208
|
+
const nodeResult = this.db.execute(`UPDATE nodes SET properties = json_set(properties, '$.${escSqlStr(assignment.property)}', json(?)) WHERE id = ?`, [JSON.stringify(value), nodeId]);
|
|
9197
9209
|
if (nodeResult.changes === 0) {
|
|
9198
9210
|
// Try edges
|
|
9199
|
-
this.db.execute(`UPDATE edges SET properties = json_set(properties, '$.${assignment.property}', json(?)) WHERE id = ?`, [JSON.stringify(value), nodeId]);
|
|
9211
|
+
this.db.execute(`UPDATE edges SET properties = json_set(properties, '$.${escSqlStr(assignment.property)}', json(?)) WHERE id = ?`, [JSON.stringify(value), nodeId]);
|
|
9200
9212
|
}
|
|
9201
9213
|
}
|
|
9202
9214
|
// Invalidate cache after UPDATE
|
|
@@ -9317,7 +9329,7 @@ export class Executor {
|
|
|
9317
9329
|
throw new Error(`Unknown variable: ${varName}`);
|
|
9318
9330
|
}
|
|
9319
9331
|
// Try nodes first
|
|
9320
|
-
const nodeResult = this.db.execute(`SELECT json_extract(properties, '$.${propName}') AS value FROM nodes WHERE id = ?`, [entityId]);
|
|
9332
|
+
const nodeResult = this.db.execute(`SELECT json_extract(properties, '$.${escSqlStr(propName)}') AS value FROM nodes WHERE id = ?`, [entityId]);
|
|
9321
9333
|
if (nodeResult.rows.length > 0) {
|
|
9322
9334
|
const value = nodeResult.rows[0].value;
|
|
9323
9335
|
// json_extract returns JSON-encoded strings for arrays/objects
|
|
@@ -9333,7 +9345,7 @@ export class Executor {
|
|
|
9333
9345
|
return value;
|
|
9334
9346
|
}
|
|
9335
9347
|
// Try edges
|
|
9336
|
-
const edgeResult = this.db.execute(`SELECT json_extract(properties, '$.${propName}') AS value FROM edges WHERE id = ?`, [entityId]);
|
|
9348
|
+
const edgeResult = this.db.execute(`SELECT json_extract(properties, '$.${escSqlStr(propName)}') AS value FROM edges WHERE id = ?`, [entityId]);
|
|
9337
9349
|
if (edgeResult.rows.length > 0) {
|
|
9338
9350
|
const value = edgeResult.rows[0].value;
|
|
9339
9351
|
if (typeof value === "string" && (value.startsWith("[") || value.startsWith("{"))) {
|