@carbonorm/carbonnode 6.0.19 → 6.1.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.
Files changed (89) hide show
  1. package/README.md +46 -1
  2. package/dist/constants/C6Constants.d.ts +342 -338
  3. package/dist/executors/SqlExecutor.d.ts +8 -0
  4. package/dist/index.cjs.js +751 -272
  5. package/dist/index.cjs.js.map +1 -1
  6. package/dist/index.d.ts +1 -0
  7. package/dist/index.esm.js +744 -273
  8. package/dist/index.esm.js.map +1 -1
  9. package/dist/orm/builders/AggregateBuilder.d.ts +5 -1
  10. package/dist/orm/builders/ConditionBuilder.d.ts +2 -3
  11. package/dist/orm/builders/ExpressionSerializer.d.ts +22 -0
  12. package/dist/orm/builders/PaginationBuilder.d.ts +4 -6
  13. package/dist/orm/queryHelpers.d.ts +12 -1
  14. package/dist/types/mysqlTypes.d.ts +6 -1
  15. package/dist/types/ormInterfaces.d.ts +7 -5
  16. package/dist/utils/cacheManager.d.ts +3 -2
  17. package/package.json +2 -2
  18. package/scripts/assets/handlebars/C6.test.ts.handlebars +4 -4
  19. package/src/__tests__/cacheManager.test.ts +28 -0
  20. package/src/__tests__/expressServer.e2e.test.ts +26 -17
  21. package/src/__tests__/httpExecutorSingular.e2e.test.ts +53 -14
  22. package/src/__tests__/normalizeSingularRequest.test.ts +26 -8
  23. package/src/__tests__/sakila-db/C6.js +1 -1
  24. package/src/__tests__/sakila-db/C6.mysqldump.json +1 -1
  25. package/src/__tests__/sakila-db/C6.mysqldump.sql +1 -1
  26. package/src/__tests__/sakila-db/C6.sqlAllowList.json +1 -1
  27. package/src/__tests__/sakila-db/C6.test.ts +4 -4
  28. package/src/__tests__/sakila-db/C6.ts +1 -1
  29. package/src/__tests__/sakila-db/sqlResponses/C6.actor.post.json +11 -4
  30. package/src/__tests__/sakila-db/sqlResponses/C6.actor.post.latest.json +3 -3
  31. package/src/__tests__/sakila-db/sqlResponses/C6.actor.put.json +1 -1
  32. package/src/__tests__/sakila-db/sqlResponses/C6.actor.put.lookup.json +3 -3
  33. package/src/__tests__/sakila-db/sqlResponses/C6.address.post.json +26 -7
  34. package/src/__tests__/sakila-db/sqlResponses/C6.address.post.latest.json +5 -5
  35. package/src/__tests__/sakila-db/sqlResponses/C6.address.put.json +1 -1
  36. package/src/__tests__/sakila-db/sqlResponses/C6.address.put.lookup.json +5 -5
  37. package/src/__tests__/sakila-db/sqlResponses/C6.category.post.json +9 -3
  38. package/src/__tests__/sakila-db/sqlResponses/C6.category.post.latest.json +2 -2
  39. package/src/__tests__/sakila-db/sqlResponses/C6.category.put.json +1 -1
  40. package/src/__tests__/sakila-db/sqlResponses/C6.category.put.lookup.json +2 -2
  41. package/src/__tests__/sakila-db/sqlResponses/C6.city.post.json +10 -3
  42. package/src/__tests__/sakila-db/sqlResponses/C6.city.post.latest.json +2 -2
  43. package/src/__tests__/sakila-db/sqlResponses/C6.city.put.json +1 -1
  44. package/src/__tests__/sakila-db/sqlResponses/C6.city.put.lookup.json +2 -2
  45. package/src/__tests__/sakila-db/sqlResponses/C6.country.post.json +9 -3
  46. package/src/__tests__/sakila-db/sqlResponses/C6.country.post.latest.json +2 -2
  47. package/src/__tests__/sakila-db/sqlResponses/C6.country.put.json +1 -1
  48. package/src/__tests__/sakila-db/sqlResponses/C6.country.put.lookup.json +2 -2
  49. package/src/__tests__/sakila-db/sqlResponses/C6.customer.post.json +18 -6
  50. package/src/__tests__/sakila-db/sqlResponses/C6.customer.post.latest.json +5 -5
  51. package/src/__tests__/sakila-db/sqlResponses/C6.customer.put.json +1 -1
  52. package/src/__tests__/sakila-db/sqlResponses/C6.customer.put.lookup.json +5 -5
  53. package/src/__tests__/sakila-db/sqlResponses/C6.film.post.json +18 -3
  54. package/src/__tests__/sakila-db/sqlResponses/C6.film.post.latest.json +2 -2
  55. package/src/__tests__/sakila-db/sqlResponses/C6.film.put.json +1 -1
  56. package/src/__tests__/sakila-db/sqlResponses/C6.film.put.lookup.json +2 -2
  57. package/src/__tests__/sakila-db/sqlResponses/C6.inventory.post.json +9 -2
  58. package/src/__tests__/sakila-db/sqlResponses/C6.inventory.post.latest.json +1 -1
  59. package/src/__tests__/sakila-db/sqlResponses/C6.inventory.put.json +1 -1
  60. package/src/__tests__/sakila-db/sqlResponses/C6.inventory.put.lookup.json +1 -1
  61. package/src/__tests__/sakila-db/sqlResponses/C6.language.post.json +9 -3
  62. package/src/__tests__/sakila-db/sqlResponses/C6.language.post.latest.json +2 -2
  63. package/src/__tests__/sakila-db/sqlResponses/C6.language.put.json +1 -1
  64. package/src/__tests__/sakila-db/sqlResponses/C6.language.put.lookup.json +2 -2
  65. package/src/__tests__/sakila-db/sqlResponses/C6.payment.post.json +13 -3
  66. package/src/__tests__/sakila-db/sqlResponses/C6.payment.post.latest.json +2 -2
  67. package/src/__tests__/sakila-db/sqlResponses/C6.payment.put.lookup.json +2 -2
  68. package/src/__tests__/sakila-db/sqlResponses/C6.rental.join.json +10 -10
  69. package/src/__tests__/sakila-db/sqlResponses/C6.rental.post.json +14 -4
  70. package/src/__tests__/sakila-db/sqlResponses/C6.rental.post.latest.json +3 -3
  71. package/src/__tests__/sakila-db/sqlResponses/C6.rental.put.json +1 -1
  72. package/src/__tests__/sakila-db/sqlResponses/C6.rental.put.lookup.json +3 -3
  73. package/src/__tests__/sqlBuilders.complex.test.ts +62 -74
  74. package/src/__tests__/sqlBuilders.expressions.test.ts +58 -30
  75. package/src/__tests__/sqlBuilders.test.ts +68 -4
  76. package/src/__tests__/sqlExecutorPostUuid.test.ts +185 -0
  77. package/src/constants/C6Constants.ts +3 -1
  78. package/src/executors/HttpExecutor.ts +35 -6
  79. package/src/executors/SqlExecutor.ts +232 -4
  80. package/src/index.ts +1 -0
  81. package/src/orm/builders/AggregateBuilder.ts +67 -106
  82. package/src/orm/builders/ConditionBuilder.ts +69 -93
  83. package/src/orm/builders/ExpressionSerializer.ts +275 -0
  84. package/src/orm/builders/PaginationBuilder.ts +24 -34
  85. package/src/orm/queryHelpers.ts +29 -0
  86. package/src/types/mysqlTypes.ts +130 -9
  87. package/src/types/ormInterfaces.ts +7 -7
  88. package/src/utils/cacheManager.ts +6 -4
  89. package/src/utils/normalizeSingularRequest.ts +11 -4
@@ -1,12 +1,18 @@
1
1
  {
2
2
  "affected": 1,
3
3
  "insertId": 7,
4
- "rest": [],
4
+ "rest": [
5
+ {
6
+ "name": "name_1771106835139",
7
+ "last_update": "2026-02-14 22:07:15",
8
+ "language_id": 7
9
+ }
10
+ ],
5
11
  "sql": {
6
12
  "sql": "INSERT INTO `language` (\n `name`, `last_update`\n ) VALUES\n (?, ?)",
7
13
  "values": [
8
- "name_1770945558829",
9
- "2026-02-13 01:19:18"
14
+ "name_1771106835139",
15
+ "2026-02-14 22:07:15"
10
16
  ]
11
17
  }
12
18
  }
@@ -2,8 +2,8 @@
2
2
  "rest": [
3
3
  {
4
4
  "language_id": 7,
5
- "name": "name_1770945558829",
6
- "last_update": "2026-02-13T01:19:18.000Z"
5
+ "name": "name_1771106835139",
6
+ "last_update": "2026-02-14T22:07:15.000Z"
7
7
  }
8
8
  ],
9
9
  "sql": {
@@ -5,7 +5,7 @@
5
5
  "sql": {
6
6
  "sql": "UPDATE `language` SET `name` = ? WHERE (language.language_id) = ?",
7
7
  "values": [
8
- "name_updated_1770945",
8
+ "name_updated_1771106",
9
9
  7
10
10
  ]
11
11
  }
@@ -2,8 +2,8 @@
2
2
  "rest": [
3
3
  {
4
4
  "language_id": 7,
5
- "name": "name_updated_1770945",
6
- "last_update": "2026-02-13T01:19:18.000Z"
5
+ "name": "name_updated_1771106",
6
+ "last_update": "2026-02-14T22:07:15.000Z"
7
7
  }
8
8
  ],
9
9
  "sql": {
@@ -1,7 +1,17 @@
1
1
  {
2
2
  "affected": 1,
3
3
  "insertId": 16050,
4
- "rest": [],
4
+ "rest": [
5
+ {
6
+ "customer_id": 2,
7
+ "staff_id": 1,
8
+ "rental_id": 1,
9
+ "amount": 1,
10
+ "payment_date": "2026-02-14 22:07:15",
11
+ "last_update": "2026-02-14 22:07:15",
12
+ "payment_id": 16050
13
+ }
14
+ ],
5
15
  "sql": {
6
16
  "sql": "INSERT INTO `payment` (\n `customer_id`, `staff_id`, `rental_id`, `amount`, `payment_date`, `last_update`\n ) VALUES\n (?, ?, ?, ?, ?, ?)",
7
17
  "values": [
@@ -9,8 +19,8 @@
9
19
  1,
10
20
  1,
11
21
  1,
12
- "2026-02-13 01:19:18",
13
- "2026-02-13 01:19:18"
22
+ "2026-02-14 22:07:15",
23
+ "2026-02-14 22:07:15"
14
24
  ]
15
25
  }
16
26
  }
@@ -6,8 +6,8 @@
6
6
  "staff_id": 1,
7
7
  "rental_id": 1,
8
8
  "amount": "1.00",
9
- "payment_date": "2026-02-13T01:19:18.000Z",
10
- "last_update": "2026-02-13T01:19:18.000Z"
9
+ "payment_date": "2026-02-14T22:07:15.000Z",
10
+ "last_update": "2026-02-14T22:07:15.000Z"
11
11
  }
12
12
  ],
13
13
  "sql": {
@@ -6,8 +6,8 @@
6
6
  "staff_id": 1,
7
7
  "rental_id": 1,
8
8
  "amount": "1.00",
9
- "payment_date": "2026-02-13T01:19:18.000Z",
10
- "last_update": "2026-02-13T01:19:18.000Z"
9
+ "payment_date": "2026-02-14T22:07:15.000Z",
10
+ "last_update": "2026-02-14T22:07:15.000Z"
11
11
  }
12
12
  ],
13
13
  "sql": {
@@ -1,18 +1,18 @@
1
1
  {
2
2
  "rest": [
3
3
  {
4
- "rental_id": 1,
5
- "rental_date": "2005-05-24T22:53:30.000Z",
6
- "inventory_id": 367,
7
- "customer_id": 130,
8
- "return_date": "2005-05-26T22:04:30.000Z",
9
- "staff_id": 1,
4
+ "rental_id": 76,
5
+ "rental_date": "2005-05-25T11:30:37.000Z",
6
+ "inventory_id": 3021,
7
+ "customer_id": 1,
8
+ "return_date": "2005-06-03T12:00:37.000Z",
9
+ "staff_id": 2,
10
10
  "last_update": "2006-02-15T04:57:20.000Z",
11
11
  "store_id": 1,
12
- "first_name": "CHARLOTTE",
13
- "last_name": "HUNTER",
14
- "email": "CHARLOTTE.HUNTER@sakilacustomer.org",
15
- "address_id": 134,
12
+ "first_name": "MARY",
13
+ "last_name": "SMITH",
14
+ "email": "MARY.SMITH@sakilacustomer.org",
15
+ "address_id": 5,
16
16
  "active": 1,
17
17
  "create_date": "2006-02-14T22:04:36.000Z"
18
18
  }
@@ -1,16 +1,26 @@
1
1
  {
2
2
  "affected": 1,
3
3
  "insertId": 16050,
4
- "rest": [],
4
+ "rest": [
5
+ {
6
+ "rental_date": "2026-02-14 22:07:15",
7
+ "inventory_id": 1,
8
+ "customer_id": 1,
9
+ "return_date": "2026-02-14 22:07:15",
10
+ "staff_id": 1,
11
+ "last_update": "2026-02-14 22:07:15",
12
+ "rental_id": 16050
13
+ }
14
+ ],
5
15
  "sql": {
6
16
  "sql": "INSERT INTO `rental` (\n `rental_date`, `inventory_id`, `customer_id`, `return_date`, `staff_id`, `last_update`\n ) VALUES\n (?, ?, ?, ?, ?, ?)",
7
17
  "values": [
8
- "2026-02-13 01:19:18",
18
+ "2026-02-14 22:07:15",
9
19
  1,
10
20
  1,
11
- "2026-02-13 01:19:18",
21
+ "2026-02-14 22:07:15",
12
22
  1,
13
- "2026-02-13 01:19:18"
23
+ "2026-02-14 22:07:15"
14
24
  ]
15
25
  }
16
26
  }
@@ -2,12 +2,12 @@
2
2
  "rest": [
3
3
  {
4
4
  "rental_id": 16050,
5
- "rental_date": "2026-02-13T01:19:18.000Z",
5
+ "rental_date": "2026-02-14T22:07:15.000Z",
6
6
  "inventory_id": 1,
7
7
  "customer_id": 1,
8
- "return_date": "2026-02-13T01:19:18.000Z",
8
+ "return_date": "2026-02-14T22:07:15.000Z",
9
9
  "staff_id": 1,
10
- "last_update": "2026-02-13T01:19:18.000Z"
10
+ "last_update": "2026-02-14T22:07:15.000Z"
11
11
  }
12
12
  ],
13
13
  "sql": {
@@ -5,7 +5,7 @@
5
5
  "sql": {
6
6
  "sql": "UPDATE `rental` SET `rental_date` = ? WHERE (rental.rental_id) = ?",
7
7
  "values": [
8
- "2026-02-13 01:19:18",
8
+ "2026-02-14 22:07:15",
9
9
  16050
10
10
  ]
11
11
  }
@@ -2,12 +2,12 @@
2
2
  "rest": [
3
3
  {
4
4
  "rental_id": 16050,
5
- "rental_date": "2026-02-13T01:19:18.000Z",
5
+ "rental_date": "2026-02-14T22:07:15.000Z",
6
6
  "inventory_id": 1,
7
7
  "customer_id": 1,
8
- "return_date": "2026-02-13T01:19:18.000Z",
8
+ "return_date": "2026-02-14T22:07:15.000Z",
9
9
  "staff_id": 1,
10
- "last_update": "2026-02-13T01:19:18.000Z"
10
+ "last_update": "2026-02-14T22:07:15.000Z"
11
11
  }
12
12
  ],
13
13
  "sql": {
@@ -38,7 +38,7 @@ describe('SQL Builders - Complex SELECTs', () => {
38
38
  SELECT: ['actor.actor_id', 'actor.first_name'],
39
39
  WHERE: {
40
40
  // AND root with one direct condition
41
- 'actor.first_name': [C6C.LIKE, 'A%'],
41
+ 'actor.first_name': [C6C.LIKE, [C6C.LIT, 'A%']],
42
42
  // OR group #1
43
43
  0: {
44
44
  'actor.actor_id': [C6C.IN, [1, 2, 3]]
@@ -52,7 +52,7 @@ describe('SQL Builders - Complex SELECTs', () => {
52
52
  'actor.last_name': [C6C.IS, null]
53
53
  },
54
54
  // AND with NOT IN
55
- 'actor.last_name': [C6C.NOT_IN, ['SMITH', 'DOE']]
55
+ 'actor.last_name': [C6C.NOT_IN, [[C6C.LIT, 'SMITH'], [C6C.LIT, 'DOE']]]
56
56
  }
57
57
  } as any, false);
58
58
 
@@ -108,10 +108,10 @@ describe('SQL Builders - Complex SELECTs', () => {
108
108
  SELECT: ['actor.actor_id', 'actor.first_name'],
109
109
  WHERE: { 'actor.actor_id': [C6C.GREATER_THAN, 10] },
110
110
  PAGINATION: {
111
- [C6C.ORDER]: {
112
- 'actor.last_name': 'ASC',
113
- 'actor.first_name': 'DESC'
114
- },
111
+ [C6C.ORDER]: [
112
+ ['actor.last_name', 'ASC'],
113
+ ['actor.first_name', 'DESC'],
114
+ ],
115
115
  [C6C.LIMIT]: 10,
116
116
  [C6C.PAGE]: 3
117
117
  }
@@ -128,7 +128,7 @@ describe('SQL Builders - Complex SELECTs', () => {
128
128
  const config = buildTestConfig();
129
129
 
130
130
  const qb = new SelectQueryBuilder(config as any, {
131
- SELECT: [[C6C.DISTINCT, 'actor.first_name'], [C6C.COUNT, 'actor.actor_id', C6C.AS, 'cnt']],
131
+ SELECT: [[C6C.DISTINCT, 'actor.first_name'], [C6C.AS, [C6C.COUNT, 'actor.actor_id'], 'cnt']],
132
132
  GROUP_BY: 'actor.first_name',
133
133
  HAVING: { 'cnt': [C6C.GREATER_THAN, 1] }
134
134
  } as any, false);
@@ -148,7 +148,7 @@ describe('SQL Builders - Complex SELECTs', () => {
148
148
  const qb = new SelectQueryBuilder(config as any, {
149
149
  SELECT: ['actor.actor_id'],
150
150
  WHERE: {
151
- 'actor.first_name': [C6C.MATCH_AGAINST, ['alpha beta', 'BOOLEAN']]
151
+ 'actor.first_name': [C6C.MATCH_AGAINST, [[C6C.LIT, 'alpha beta'], 'BOOLEAN']]
152
152
  }
153
153
  } as any, false);
154
154
 
@@ -225,19 +225,21 @@ describe('SQL Builders - Complex SELECTs', () => {
225
225
  [C6C.WHERE]: {
226
226
  [Property_Units.UNIT_ID]: [C6C.NOT_EQUAL, unitIdParam],
227
227
  [Parcel_Sales.SALE_PRICE]: [C6C.NOT_EQUAL, 0],
228
- [Parcel_Sales.SALE_TYPE]: { [C6C.IN]: ALLOWED_SALE_TYPES },
228
+ [Parcel_Sales.SALE_TYPE]: { [C6C.IN]: ALLOWED_SALE_TYPES.map((saleType) => [C6C.LIT, saleType]) },
229
229
  0: parsedDateRanges.map(({ start, end }) => ({
230
- [Parcel_Sales.SALE_DATE]: [C6C.BETWEEN, [start, end]],
230
+ [Parcel_Sales.SALE_DATE]: [C6C.BETWEEN, [[C6C.LIT, start], [C6C.LIT, end]]],
231
231
  })),
232
232
  },
233
233
  [C6C.PAGINATION]: {
234
234
  [C6C.LIMIT]: 200,
235
- [C6C.ORDER]: {
236
- [C6C.ST_DISTANCE_SPHERE]: [
235
+ [C6C.ORDER]: [[
236
+ [
237
+ C6C.ST_DISTANCE_SPHERE,
237
238
  Property_Units.LOCATION,
238
239
  F(Property_Units.LOCATION, 'pu_target'),
239
240
  ],
240
- },
241
+ C6C.ASC,
242
+ ]],
241
243
  },
242
244
  } as any, false);
243
245
 
@@ -250,7 +252,7 @@ describe('SQL Builders - Complex SELECTs', () => {
250
252
  expect(sql).toMatch(/INNER JOIN \(\s+SELECT property_units\.location/);
251
253
  expect(sql).toContain('WHERE (property_units.unit_id) <> ?');
252
254
  expect(sql).toContain('AND (parcel_sales.sale_price) <> ?');
253
- expect(sql).toContain('ORDER BY ST_Distance_Sphere(property_units.location, pu_target.location)');
255
+ expect(sql).toContain('ORDER BY ST_DISTANCE_SPHERE(property_units.location, pu_target.location) ASC');
254
256
  expect(sql.trim().endsWith('LIMIT 200')).toBe(true);
255
257
 
256
258
  expect(params).toEqual([
@@ -314,17 +316,15 @@ describe('SQL Builders - Complex SELECTs', () => {
314
316
  [C6C.SELECT]: [Property_Units.UNIT_ID],
315
317
  [C6C.PAGINATION]: {
316
318
  [C6C.LIMIT]: 200,
317
- [C6C.ORDER]: {
318
- [C6C.ST_DISTANCE_SPHERE]: [
319
- Property_Units.LOCATION,
320
- [C6C.ST_POINT, ['-104.8967729', '39.3976764']],
321
- ],
322
- },
319
+ [C6C.ORDER]: [[
320
+ [C6C.ST_DISTANCE_SPHERE, Property_Units.LOCATION, [C6C.ST_POINT, -104.8967729, 39.3976764]],
321
+ C6C.ASC,
322
+ ]],
323
323
  },
324
324
  } as any, false);
325
325
 
326
326
  const { sql } = qb.build(Property_Units.TABLE_NAME);
327
- expect(sql).toContain('ORDER BY ST_Distance_Sphere(property_units.location, ST_POINT(-104.8967729, 39.3976764))');
327
+ expect(sql).toContain('ORDER BY ST_DISTANCE_SPHERE(property_units.location, ST_POINT(-104.8967729, 39.3976764)) ASC');
328
328
  });
329
329
 
330
330
  it('orders by distance to ST_SRID(ST_Point(lng, lat), 4326)', () => {
@@ -334,17 +334,15 @@ describe('SQL Builders - Complex SELECTs', () => {
334
334
  [C6C.SELECT]: [Property_Units.UNIT_ID],
335
335
  [C6C.PAGINATION]: {
336
336
  [C6C.LIMIT]: 50,
337
- [C6C.ORDER]: {
338
- [C6C.ST_DISTANCE_SPHERE]: [
339
- Property_Units.LOCATION,
340
- [C6C.ST_SRID, [C6C.ST_POINT, [10, 20]], 4326],
341
- ],
342
- },
337
+ [C6C.ORDER]: [[
338
+ [C6C.ST_DISTANCE_SPHERE, Property_Units.LOCATION, [C6C.ST_SRID, [C6C.ST_POINT, 10, 20], 4326]],
339
+ C6C.ASC,
340
+ ]],
343
341
  },
344
342
  } as any, false);
345
343
 
346
344
  const { sql } = qb.build(Property_Units.TABLE_NAME);
347
- expect(sql).toContain('ORDER BY ST_Distance_Sphere(property_units.location, ST_SRID(ST_POINT(10, 20), 4326))');
345
+ expect(sql).toContain('ORDER BY ST_DISTANCE_SPHERE(property_units.location, ST_SRID(ST_POINT(10, 20), 4326)) ASC');
348
346
  });
349
347
 
350
348
  it('orders by distance using placeholders via PARAM inside nested ST_Point', () => {
@@ -354,17 +352,15 @@ describe('SQL Builders - Complex SELECTs', () => {
354
352
  [C6C.SELECT]: [Property_Units.UNIT_ID],
355
353
  [C6C.PAGINATION]: {
356
354
  [C6C.LIMIT]: 25,
357
- [C6C.ORDER]: {
358
- [C6C.ST_DISTANCE_SPHERE]: [
359
- Property_Units.LOCATION,
360
- [C6C.ST_SRID, [C6C.ST_POINT, [[C6C.PARAM, 10], [C6C.PARAM, 20]]], 4326],
361
- ],
362
- },
355
+ [C6C.ORDER]: [[
356
+ [C6C.ST_DISTANCE_SPHERE, Property_Units.LOCATION, [C6C.ST_SRID, [C6C.ST_POINT, [C6C.PARAM, 10], [C6C.PARAM, 20]], 4326]],
357
+ C6C.ASC,
358
+ ]],
363
359
  },
364
360
  } as any, false);
365
361
 
366
362
  const { sql, params } = qb.build(Property_Units.TABLE_NAME);
367
- expect(sql).toContain('ORDER BY ST_Distance_Sphere(property_units.location, ST_SRID(ST_POINT(?, ?), 4326))');
363
+ expect(sql).toContain('ORDER BY ST_DISTANCE_SPHERE(property_units.location, ST_SRID(ST_POINT(?, ?), 4326)) ASC');
368
364
  expect(params.slice(-2)).toEqual([10, 20]);
369
365
  });
370
366
 
@@ -375,12 +371,10 @@ describe('SQL Builders - Complex SELECTs', () => {
375
371
  [C6C.SELECT]: [Property_Units.UNIT_ID],
376
372
  [C6C.PAGINATION]: {
377
373
  [C6C.LIMIT]: 25,
378
- [C6C.ORDER]: {
379
- [C6C.ST_DISTANCE_SPHERE]: [
380
- Property_Units.LOCATION,
381
- [C6C.ST_SRID, [C6C.ST_POINT, [[C6C.PARAM, 10], [C6C.PARAM, 20]]], 4326],
382
- ],
383
- },
374
+ [C6C.ORDER]: [[
375
+ [C6C.ST_DISTANCE_SPHERE, Property_Units.LOCATION, [C6C.ST_SRID, [C6C.ST_POINT, [C6C.PARAM, 10], [C6C.PARAM, 20]], 4326]],
376
+ C6C.ASC,
377
+ ]],
384
378
  },
385
379
  } as any, true);
386
380
 
@@ -396,17 +390,15 @@ describe('SQL Builders - Complex SELECTs', () => {
396
390
  [C6C.SELECT]: [Property_Units.UNIT_ID],
397
391
  [C6C.PAGINATION]: {
398
392
  [C6C.LIMIT]: 10,
399
- [C6C.ORDER]: {
400
- [C6C.ST_DISTANCE_SPHERE]: [
401
- Property_Units.LOCATION,
402
- [C6C.ST_GEOMFROMTEXT, [[C6C.PARAM, 'POINT(-104.8967729 39.3976764)'], 4326]],
403
- ],
404
- },
393
+ [C6C.ORDER]: [[
394
+ [C6C.ST_DISTANCE_SPHERE, Property_Units.LOCATION, [C6C.ST_GEOMFROMTEXT, [C6C.PARAM, 'POINT(-104.8967729 39.3976764)'], 4326]],
395
+ C6C.ASC,
396
+ ]],
405
397
  },
406
398
  } as any, false);
407
399
 
408
400
  const { sql, params } = qb.build(Property_Units.TABLE_NAME);
409
- expect(sql).toContain('ORDER BY ST_Distance_Sphere(property_units.location, ST_GEOMFROMTEXT(?, 4326))');
401
+ expect(sql).toContain('ORDER BY ST_DISTANCE_SPHERE(property_units.location, ST_GEOMFROMTEXT(?, 4326)) ASC');
410
402
  expect(params.slice(-1)[0]).toBe('POINT(-104.8967729 39.3976764)');
411
403
  });
412
404
 
@@ -417,20 +409,16 @@ describe('SQL Builders - Complex SELECTs', () => {
417
409
  [C6C.SELECT]: [Property_Units.UNIT_ID],
418
410
  [C6C.PAGINATION]: {
419
411
  [C6C.LIMIT]: 10,
420
- [C6C.ORDER]: {
421
- [C6C.ST_DISTANCE_SPHERE]: [
422
- Property_Units.LOCATION,
423
- [C6C.ST_GEOMFROMTEXT, ['POINT(-104.8967729 39.3976764)', 4326]],
424
- ],
425
- },
412
+ [C6C.ORDER]: [[
413
+ [C6C.ST_DISTANCE_SPHERE, Property_Units.LOCATION, [C6C.ST_GEOMFROMTEXT, [C6C.LIT, 'POINT(-104.8967729 39.3976764)'], 4326]],
414
+ C6C.ASC,
415
+ ]],
426
416
  },
427
417
  } as any, false);
428
418
 
429
419
  const { sql, params } = qb.build(Property_Units.TABLE_NAME);
430
- expect(sql).toContain(
431
- "ORDER BY ST_Distance_Sphere(property_units.location, ST_GEOMFROMTEXT('POINT(-104.8967729 39.3976764)', 4326))",
432
- );
433
- expect(params).not.toContain('POINT(-104.8967729 39.3976764)');
420
+ expect(sql).toContain('ORDER BY ST_DISTANCE_SPHERE(property_units.location, ST_GEOMFROMTEXT(?, 4326))');
421
+ expect(params).toContain('POINT(-104.8967729 39.3976764)');
434
422
  });
435
423
 
436
424
  it('leaves normal table joins unaffected', () => {
@@ -455,16 +443,14 @@ describe('SQL Builders - Complex SELECTs', () => {
455
443
  const qb = new SelectQueryBuilder(config as any, {
456
444
  [C6C.SELECT]: [
457
445
  Property_Units.UNIT_ID,
458
- [
446
+ [C6C.AS, [
459
447
  C6C.SUBSELECT,
460
448
  {
461
449
  [C6C.SELECT]: [[C6C.COUNT, Parcel_Sales.PARCEL_ID]],
462
450
  [C6C.FROM]: Parcel_Sales.TABLE_NAME,
463
451
  [C6C.WHERE]: { [Parcel_Sales.SALE_PRICE]: [C6C.GREATER_THAN, 0] },
464
452
  },
465
- C6C.AS,
466
- 'sale_count',
467
- ],
453
+ ], 'sale_count'],
468
454
  ],
469
455
  [C6C.WHERE]: {
470
456
  [Property_Units.UNIT_ID]: [
@@ -491,7 +477,7 @@ describe('SQL Builders - Complex SELECTs', () => {
491
477
  it('serializes spatial filtering with FORCE INDEX and correlated EXISTS subqueries', () => {
492
478
  const config = buildParcelConfig();
493
479
  const polygon = 'POLYGON((39.5185659 -105.0142915, 39.5401859 -105.0142915, 39.5401859 -104.9862115, 39.5185659 -104.9862115, 39.5185659 -105.0142915))';
494
- const point = [C6C.ST_GEOMFROMTEXT, ['POINT(39.5293759 -105.0002515)', 4326]];
480
+ const point = [C6C.ST_GEOMFROMTEXT, [C6C.LIT, 'POINT(39.5293759 -105.0002515)'], 4326];
495
481
  const unitId = Buffer.from('11F0615D24861BE1ADD40AFFCF6A1F27', 'hex');
496
482
  const countyId = Buffer.from('11F012CFF561A29DBB0E0AFFF25F1747', 'hex');
497
483
 
@@ -504,7 +490,7 @@ describe('SQL Builders - Complex SELECTs', () => {
504
490
  [Property_Units.UNIT_ID]: [C6C.NOT_EQUAL, unitId],
505
491
  [Property_Units.COUNTY_ID]: countyId,
506
492
  [C6C.MBRCONTAINS]: [
507
- [C6C.ST_GEOMFROMTEXT, [polygon, 4326]],
493
+ [C6C.ST_GEOMFROMTEXT, [C6C.LIT, polygon], 4326],
508
494
  Property_Units.LOCATION,
509
495
  ],
510
496
  [C6C.LESS_THAN_OR_EQUAL_TO]: [
@@ -532,7 +518,7 @@ describe('SQL Builders - Complex SELECTs', () => {
532
518
  [C6C.SELECT]: [Parcel_Sales.PARCEL_ID],
533
519
  [C6C.FROM]: Parcel_Sales.TABLE_NAME,
534
520
  [C6C.WHERE]: {
535
- [Parcel_Sales.SALE_DATE]: [C6C.BETWEEN, ['2023-01-01', '2024-06-30']],
521
+ [Parcel_Sales.SALE_DATE]: [C6C.BETWEEN, [[C6C.LIT, '2023-01-01'], [C6C.LIT, '2024-06-30']]],
536
522
  [Parcel_Sales.SALE_PRICE]: [C6C.NOT_EQUAL, 0],
537
523
  },
538
524
  },
@@ -542,26 +528,28 @@ describe('SQL Builders - Complex SELECTs', () => {
542
528
  },
543
529
  [C6C.PAGINATION]: {
544
530
  [C6C.LIMIT]: 100,
545
- [C6C.ORDER]: {
546
- [C6C.ST_DISTANCE_SPHERE]: [Property_Units.LOCATION, point],
547
- },
531
+ [C6C.ORDER]: [
532
+ [[C6C.ST_DISTANCE_SPHERE, Property_Units.LOCATION, point], C6C.ASC],
533
+ ],
548
534
  },
549
535
  } as any, false);
550
536
 
551
537
  const { sql, params } = qb.build(Property_Units.TABLE_NAME);
552
538
 
553
539
  expect(sql).toContain('FORCE INDEX (`idx_county_id`, `idx_property_units_location`)');
554
- expect(sql).toMatch(/MBRCONTAINS\(ST_GEOMFROMTEXT\('POLYGON\(\(39\.5185659 -105\.0142915, 39\.5401859 -105\.0142915, 39\.5401859 -104\.9862115, 39\.5185659 -104\.9862115, 39\.5185659 -105\.0142915\)\)', 4326\), property_units\.location\)/);
555
- expect(sql).toMatch(/ST_DISTANCE_SPHERE\(property_units\.location, ST_GEOMFROMTEXT\('POINT\(39\.5293759 -105\.0002515\)', 4326\)\) <= \?/);
540
+ expect(sql).toMatch(/MBRCONTAINS\(ST_GEOMFROMTEXT\(\?, 4326\), property_units\.location\)/);
541
+ expect(sql).toMatch(/ST_DISTANCE_SPHERE\(property_units\.location, ST_GEOMFROMTEXT\(\?, 4326\)\) <= \?/);
556
542
  expect(sql).toMatch(/\(parcel_building_details\.parcel_id\) = property_units\.parcel_id/);
557
543
  expect(sql).toMatch(/\(parcel_sales\.parcel_id\) = property_units\.parcel_id/);
558
- expect(sql).toMatch(/ORDER BY ST[_]Distance[_]Sphere\(property_units\.location, ST_GEOMFROMTEXT\('POINT\(39\.5293759 -105\.0002515\)', 4326\)\)/i);
544
+ expect(sql).toMatch(/ORDER BY ST[_]DISTANCE[_]SPHERE\(property_units\.location, ST_GEOMFROMTEXT\(\?, 4326\)\) ASC/i);
559
545
 
560
- expect(params).toHaveLength(10);
546
+ expect(params).toHaveLength(13);
561
547
  expect(params[0]).toEqual(unitId);
562
548
  expect(params[1]).toEqual(countyId);
549
+ expect(params[2]).toEqual(polygon);
550
+ expect(params[3]).toEqual('POINT(39.5293759 -105.0002515)');
563
551
  expect(params).toContain(1200);
564
- expect(params.slice(3, 7)).toEqual([1988, 2008, 1876.5, 3127.5]);
565
- expect(params.slice(7)).toEqual(['2023-01-01', '2024-06-30', 0]);
552
+ expect(params.slice(5, 9)).toEqual([1988, 2008, 1876.5, 3127.5]);
553
+ expect(params.slice(9)).toEqual(['2023-01-01', '2024-06-30', 0, 'POINT(39.5293759 -105.0002515)']);
566
554
  });
567
555
  });