spice-js 2.7.14 → 2.7.15

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.
@@ -1290,34 +1290,42 @@ class SpiceModel {
1290
1290
  }
1291
1291
 
1292
1292
  extractNestings(string, localType) {
1293
- var returnVal = []; // First, extract loop variables and embedded arrays from ANY/EVERY expressions
1294
- // These should be EXCLUDED from join candidates
1293
+ var returnVal = []; // Extract loop variables from ANY/EVERY expressions
1294
+ // Loop variables (e.g., "vote" in "EVERY vote IN committee_votes") should be excluded
1295
+ // But the collection being iterated (e.g., "committee_votes") should be INCLUDED
1296
+ // if it's a joinable mapped property - buildJoinMetadata will filter non-joinables
1295
1297
 
1296
1298
  var anyEveryRegex = /(ANY|EVERY)\s+(\w+)\s+IN\s+`?(\w+)`?/gi;
1297
1299
  var anyEveryMatch;
1298
1300
  var loopVariables = new Set();
1299
- var embeddedArrayFields = new Set();
1301
+ var anyEveryCollections = new Set();
1300
1302
 
1301
1303
  while ((anyEveryMatch = anyEveryRegex.exec(string)) !== null) {
1302
- loopVariables.add(anyEveryMatch[2]); // e.g., "p"
1304
+ loopVariables.add(anyEveryMatch[2]); // e.g., "vote" - exclude from nestings
1303
1305
 
1304
- embeddedArrayFields.add(anyEveryMatch[3]); // e.g., "permissions"
1305
- } // Now extract dot notation patterns, but skip loop variables and embedded arrays
1306
+ anyEveryCollections.add(anyEveryMatch[3]); // e.g., "committee_votes" - include in nestings
1307
+ } // Now extract dot notation patterns, but skip loop variables
1306
1308
 
1307
1309
 
1308
1310
  var regex = /(`?\w+`?)\.(`?\w+`?)/g;
1309
1311
  var match;
1310
1312
 
1311
1313
  while ((match = regex.exec(string)) !== null) {
1312
- var first = match[1].replace(/`/g, ""); // Skip if it's the local type, a loop variable from ANY/EVERY, or an embedded array field
1314
+ var first = match[1].replace(/`/g, ""); // Skip if it's the local type or a loop variable from ANY/EVERY
1313
1315
 
1314
- if (first !== localType && !loopVariables.has(first) && !embeddedArrayFields.has(first)) {
1316
+ if (first !== localType && !loopVariables.has(first)) {
1315
1317
  returnVal.push(first);
1316
1318
  }
1317
- } // DO NOT add embedded array fields from ANY/EVERY expressions
1318
- // They iterate over document's embedded array, not join to another collection
1319
+ } // Add collections from ANY/EVERY expressions as potential nestings
1320
+ // buildJoinMetadata will filter out non-joinable ones (embedded arrays vs mapped collections)
1319
1321
 
1320
1322
 
1323
+ for (var collection of anyEveryCollections) {
1324
+ if (collection !== localType) {
1325
+ returnVal.push(collection);
1326
+ }
1327
+ }
1328
+
1321
1329
  return [...new Set(returnVal)];
1322
1330
  }
1323
1331
 
@@ -1460,6 +1468,11 @@ class SpiceModel {
1460
1468
 
1461
1469
  if (tableName === this.type && match) {
1462
1470
  return col;
1471
+ } // If column is already backtick-quoted, return as-is
1472
+
1473
+
1474
+ if (col.startsWith("`") && col.endsWith("`")) {
1475
+ return col;
1463
1476
  }
1464
1477
 
1465
1478
  return "`" + col + "`";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "spice-js",
3
- "version": "2.7.14",
3
+ "version": "2.7.15",
4
4
  "description": "spice",
5
5
  "main": "build/index.js",
6
6
  "repository": {
@@ -1110,32 +1110,39 @@ export default class SpiceModel {
1110
1110
  extractNestings(string, localType) {
1111
1111
  let returnVal = [];
1112
1112
 
1113
- // First, extract loop variables and embedded arrays from ANY/EVERY expressions
1114
- // These should be EXCLUDED from join candidates
1113
+ // Extract loop variables from ANY/EVERY expressions
1114
+ // Loop variables (e.g., "vote" in "EVERY vote IN committee_votes") should be excluded
1115
+ // But the collection being iterated (e.g., "committee_votes") should be INCLUDED
1116
+ // if it's a joinable mapped property - buildJoinMetadata will filter non-joinables
1115
1117
  let anyEveryRegex = /(ANY|EVERY)\s+(\w+)\s+IN\s+`?(\w+)`?/gi;
1116
1118
  let anyEveryMatch;
1117
1119
  const loopVariables = new Set();
1118
- const embeddedArrayFields = new Set();
1120
+ const anyEveryCollections = new Set();
1119
1121
 
1120
1122
  while ((anyEveryMatch = anyEveryRegex.exec(string)) !== null) {
1121
- loopVariables.add(anyEveryMatch[2]); // e.g., "p"
1122
- embeddedArrayFields.add(anyEveryMatch[3]); // e.g., "permissions"
1123
+ loopVariables.add(anyEveryMatch[2]); // e.g., "vote" - exclude from nestings
1124
+ anyEveryCollections.add(anyEveryMatch[3]); // e.g., "committee_votes" - include in nestings
1123
1125
  }
1124
1126
 
1125
- // Now extract dot notation patterns, but skip loop variables and embedded arrays
1127
+ // Now extract dot notation patterns, but skip loop variables
1126
1128
  let regex = /(`?\w+`?)\.(`?\w+`?)/g;
1127
1129
  let match;
1128
1130
 
1129
1131
  while ((match = regex.exec(string)) !== null) {
1130
1132
  let first = match[1].replace(/`/g, "");
1131
- // Skip if it's the local type, a loop variable from ANY/EVERY, or an embedded array field
1132
- if (first !== localType && !loopVariables.has(first) && !embeddedArrayFields.has(first)) {
1133
+ // Skip if it's the local type or a loop variable from ANY/EVERY
1134
+ if (first !== localType && !loopVariables.has(first)) {
1133
1135
  returnVal.push(first);
1134
1136
  }
1135
1137
  }
1136
1138
 
1137
- // DO NOT add embedded array fields from ANY/EVERY expressions
1138
- // They iterate over document's embedded array, not join to another collection
1139
+ // Add collections from ANY/EVERY expressions as potential nestings
1140
+ // buildJoinMetadata will filter out non-joinable ones (embedded arrays vs mapped collections)
1141
+ for (const collection of anyEveryCollections) {
1142
+ if (collection !== localType) {
1143
+ returnVal.push(collection);
1144
+ }
1145
+ }
1139
1146
 
1140
1147
  return [...new Set(returnVal)];
1141
1148
  }
@@ -1292,6 +1299,10 @@ export default class SpiceModel {
1292
1299
  return col;
1293
1300
  }
1294
1301
 
1302
+ // If column is already backtick-quoted, return as-is
1303
+ if (col.startsWith("`") && col.endsWith("`")) {
1304
+ return col;
1305
+ }
1295
1306
  return `\`${col}\``;
1296
1307
  });
1297
1308