masterrecord 0.2.36 → 0.3.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/.claude/settings.local.json +20 -1
- package/Entity/entityModel.js +6 -0
- package/Entity/entityTrackerModel.js +20 -3
- package/Entity/fieldTransformer.js +266 -0
- package/Migrations/migrationMySQLQuery.js +145 -1
- package/Migrations/migrationPostgresQuery.js +402 -0
- package/Migrations/migrationSQLiteQuery.js +145 -1
- package/Migrations/schema.js +131 -28
- package/QueryLanguage/queryMethods.js +193 -15
- package/QueryLanguage/queryParameters.js +136 -0
- package/QueryLanguage/queryScript.js +13 -4
- package/SQLLiteEngine.js +331 -20
- package/context.js +91 -14
- package/docs/INCLUDES_CLARIFICATION.md +202 -0
- package/docs/METHODS_REFERENCE.md +184 -0
- package/docs/MIGRATIONS_GUIDE.md +699 -0
- package/docs/POSTGRESQL_SETUP.md +415 -0
- package/examples/jsonArrayTransformer.js +215 -0
- package/mySQLEngine.js +273 -17
- package/package.json +3 -3
- package/postgresEngine.js +600 -483
- package/postgresSyncConnect.js +209 -0
- package/readme.md +1046 -416
- package/test/anyCommaStringTest.js +237 -0
- package/test/anyMethodTest.js +176 -0
- package/test/findByIdTest.js +227 -0
- package/test/includesFeatureTest.js +183 -0
- package/test/includesTransformTest.js +110 -0
- package/test/newMethodTest.js +330 -0
- package/test/newMethodUnitTest.js +320 -0
- package/test/parameterizedPlaceholderTest.js +159 -0
- package/test/postgresEngineTest.js +463 -0
- package/test/postgresIntegrationTest.js +381 -0
- package/test/securityTest.js +268 -0
- package/test/singleDollarPlaceholderTest.js +238 -0
- package/test/transformerTest.js +287 -0
- package/test/verifyFindById.js +169 -0
- package/test/verifyNewMethod.js +191 -0
|
@@ -0,0 +1,463 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PostgreSQL Engine Test
|
|
3
|
+
*
|
|
4
|
+
* Tests the postgresEngine.js implementation including all bug fixes:
|
|
5
|
+
* - Placeholder detection in buildWhere and buildAnd
|
|
6
|
+
* - Parameterized query generation
|
|
7
|
+
* - $1, $2, $3... placeholder format
|
|
8
|
+
* - RETURNING clause for INSERT
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
const postgresEngine = require('../postgresEngine');
|
|
12
|
+
|
|
13
|
+
console.log("╔════════════════════════════════════════════════════════════════╗");
|
|
14
|
+
console.log("║ PostgreSQL Engine Unit Tests ║");
|
|
15
|
+
console.log("╚════════════════════════════════════════════════════════════════╝\n");
|
|
16
|
+
|
|
17
|
+
let passed = 0;
|
|
18
|
+
let failed = 0;
|
|
19
|
+
|
|
20
|
+
// Mock entity for testing
|
|
21
|
+
const TEST_ENTITY = {
|
|
22
|
+
__name: 'User',
|
|
23
|
+
id: { type: 'integer', primary: true, auto: true },
|
|
24
|
+
name: { type: 'string', nullable: false },
|
|
25
|
+
email: { type: 'string', nullable: false },
|
|
26
|
+
age: { type: 'integer', nullable: true },
|
|
27
|
+
status: { type: 'string', nullable: true }
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
// Test 1: Engine Initialization
|
|
31
|
+
console.log("📝 Test 1: Engine Instance Creation");
|
|
32
|
+
console.log("──────────────────────────────────────────────────");
|
|
33
|
+
|
|
34
|
+
try {
|
|
35
|
+
const engine = new postgresEngine();
|
|
36
|
+
|
|
37
|
+
if (engine) {
|
|
38
|
+
console.log(" ✓ Engine instance created");
|
|
39
|
+
console.log(` ✓ Database type: ${engine.dbType}`);
|
|
40
|
+
passed++;
|
|
41
|
+
} else {
|
|
42
|
+
console.log(" ✗ Failed to create engine");
|
|
43
|
+
failed++;
|
|
44
|
+
}
|
|
45
|
+
} catch (err) {
|
|
46
|
+
console.log(` ✗ Error: ${err.message}`);
|
|
47
|
+
failed++;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// Test 2: Placeholder Detection in buildWhere
|
|
51
|
+
console.log("\n📝 Test 2: Placeholder Detection in buildWhere");
|
|
52
|
+
console.log("──────────────────────────────────────────────────");
|
|
53
|
+
|
|
54
|
+
try {
|
|
55
|
+
const engine = new postgresEngine();
|
|
56
|
+
|
|
57
|
+
// Mock query with $1 placeholder
|
|
58
|
+
const mockQuery = {
|
|
59
|
+
where: {
|
|
60
|
+
User: {
|
|
61
|
+
query: {
|
|
62
|
+
expressions: [
|
|
63
|
+
{ field: 'name', func: '=', arg: '$1' }
|
|
64
|
+
],
|
|
65
|
+
fields: ['name']
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
},
|
|
69
|
+
parentName: 'User',
|
|
70
|
+
entityMap: [{ name: 'User', entity: 'User' }]
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
const whereClause = engine.buildWhere(mockQuery, TEST_ENTITY);
|
|
74
|
+
|
|
75
|
+
// Should NOT quote $1 placeholder
|
|
76
|
+
if (whereClause.includes('$1') && !whereClause.includes("'$1'")) {
|
|
77
|
+
console.log(" ✓ $1 placeholder not quoted");
|
|
78
|
+
console.log(` ✓ Generated: ${whereClause}`);
|
|
79
|
+
passed++;
|
|
80
|
+
} else {
|
|
81
|
+
console.log(` ✗ Placeholder incorrectly handled: ${whereClause}`);
|
|
82
|
+
failed++;
|
|
83
|
+
}
|
|
84
|
+
} catch (err) {
|
|
85
|
+
console.log(` ✗ Error: ${err.message}`);
|
|
86
|
+
failed++;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// Test 3: String Values Should Be Quoted
|
|
90
|
+
console.log("\n📝 Test 3: Non-Placeholder Values Should Be Quoted");
|
|
91
|
+
console.log("──────────────────────────────────────────────────");
|
|
92
|
+
|
|
93
|
+
try {
|
|
94
|
+
const engine = new postgresEngine();
|
|
95
|
+
|
|
96
|
+
const mockQuery = {
|
|
97
|
+
where: {
|
|
98
|
+
User: {
|
|
99
|
+
query: {
|
|
100
|
+
expressions: [
|
|
101
|
+
{ field: 'status', func: '=', arg: 'active' }
|
|
102
|
+
],
|
|
103
|
+
fields: ['status']
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
},
|
|
107
|
+
parentName: 'User',
|
|
108
|
+
entityMap: [{ name: 'User', entity: 'User' }]
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
const whereClause = engine.buildWhere(mockQuery, TEST_ENTITY);
|
|
112
|
+
|
|
113
|
+
// Should quote literal string 'active'
|
|
114
|
+
if (whereClause.includes("'active'")) {
|
|
115
|
+
console.log(" ✓ Literal string correctly quoted");
|
|
116
|
+
console.log(` ✓ Generated: ${whereClause}`);
|
|
117
|
+
passed++;
|
|
118
|
+
} else {
|
|
119
|
+
console.log(` ✗ String not quoted: ${whereClause}`);
|
|
120
|
+
failed++;
|
|
121
|
+
}
|
|
122
|
+
} catch (err) {
|
|
123
|
+
console.log(` ✗ Error: ${err.message}`);
|
|
124
|
+
failed++;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// Test 4: Placeholder Detection in buildAnd
|
|
128
|
+
console.log("\n📝 Test 4: Placeholder Detection in buildAnd");
|
|
129
|
+
console.log("──────────────────────────────────────────────────");
|
|
130
|
+
|
|
131
|
+
try {
|
|
132
|
+
const engine = new postgresEngine();
|
|
133
|
+
|
|
134
|
+
const mockQuery = {
|
|
135
|
+
and: {
|
|
136
|
+
and1: {
|
|
137
|
+
User: {
|
|
138
|
+
query: {
|
|
139
|
+
expressions: [
|
|
140
|
+
{ field: 'age', func: '>', arg: '$2' }
|
|
141
|
+
],
|
|
142
|
+
fields: ['age']
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
},
|
|
147
|
+
parentName: 'User',
|
|
148
|
+
entityMap: [{ name: 'User', entity: 'User' }]
|
|
149
|
+
};
|
|
150
|
+
|
|
151
|
+
const andClause = engine.buildAnd(mockQuery, TEST_ENTITY);
|
|
152
|
+
|
|
153
|
+
// Should NOT quote $2 placeholder
|
|
154
|
+
if (andClause.includes('$2') && !andClause.includes("'$2'")) {
|
|
155
|
+
console.log(" ✓ $2 placeholder in AND clause not quoted");
|
|
156
|
+
console.log(` ✓ Generated: ${andClause}`);
|
|
157
|
+
passed++;
|
|
158
|
+
} else {
|
|
159
|
+
console.log(` ✗ AND clause placeholder incorrectly handled: ${andClause}`);
|
|
160
|
+
failed++;
|
|
161
|
+
}
|
|
162
|
+
} catch (err) {
|
|
163
|
+
console.log(` ✗ Error: ${err.message}`);
|
|
164
|
+
failed++;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
// Test 5: NULL Handling in WHERE
|
|
168
|
+
console.log("\n📝 Test 5: NULL Handling in WHERE Clause");
|
|
169
|
+
console.log("──────────────────────────────────────────────────");
|
|
170
|
+
|
|
171
|
+
try {
|
|
172
|
+
const engine = new postgresEngine();
|
|
173
|
+
|
|
174
|
+
const mockQuery = {
|
|
175
|
+
where: {
|
|
176
|
+
User: {
|
|
177
|
+
query: {
|
|
178
|
+
expressions: [
|
|
179
|
+
{ field: 'status', func: '=', arg: 'null' }
|
|
180
|
+
],
|
|
181
|
+
fields: ['status']
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
},
|
|
185
|
+
parentName: 'User',
|
|
186
|
+
entityMap: [{ name: 'User', entity: 'User' }]
|
|
187
|
+
};
|
|
188
|
+
|
|
189
|
+
const whereClause = engine.buildWhere(mockQuery, TEST_ENTITY);
|
|
190
|
+
|
|
191
|
+
// Should convert = to IS for NULL
|
|
192
|
+
if (whereClause.includes('IS null')) {
|
|
193
|
+
console.log(" ✓ NULL comparison uses IS instead of =");
|
|
194
|
+
console.log(` ✓ Generated: ${whereClause}`);
|
|
195
|
+
passed++;
|
|
196
|
+
} else {
|
|
197
|
+
console.log(` ✗ NULL not handled correctly: ${whereClause}`);
|
|
198
|
+
failed++;
|
|
199
|
+
}
|
|
200
|
+
} catch (err) {
|
|
201
|
+
console.log(` ✗ Error: ${err.message}`);
|
|
202
|
+
failed++;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
// Test 6: Build Complete Query
|
|
206
|
+
console.log("\n📝 Test 6: Complete Query Building");
|
|
207
|
+
console.log("──────────────────────────────────────────────────");
|
|
208
|
+
|
|
209
|
+
try {
|
|
210
|
+
const engine = new postgresEngine();
|
|
211
|
+
|
|
212
|
+
const mockQuery = {
|
|
213
|
+
where: {
|
|
214
|
+
User: {
|
|
215
|
+
query: {
|
|
216
|
+
expressions: [
|
|
217
|
+
{ field: 'name', func: '=', arg: '$1' }
|
|
218
|
+
],
|
|
219
|
+
fields: ['name']
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
},
|
|
223
|
+
parentName: 'User',
|
|
224
|
+
entityMap: [{ name: 'User', entity: 'User' }],
|
|
225
|
+
parameters: {
|
|
226
|
+
getParams: () => ['John Doe']
|
|
227
|
+
}
|
|
228
|
+
};
|
|
229
|
+
|
|
230
|
+
const queryObj = engine.buildQuery(mockQuery, TEST_ENTITY);
|
|
231
|
+
|
|
232
|
+
if (queryObj.query && queryObj.params) {
|
|
233
|
+
console.log(" ✓ Query object generated");
|
|
234
|
+
console.log(` ✓ SQL: ${queryObj.query.substring(0, 80)}...`);
|
|
235
|
+
console.log(` ✓ Params: [${queryObj.params.join(', ')}]`);
|
|
236
|
+
|
|
237
|
+
if (queryObj.query.includes('$1') && queryObj.params.length === 1) {
|
|
238
|
+
console.log(" ✓ Placeholder and params match");
|
|
239
|
+
passed++;
|
|
240
|
+
} else {
|
|
241
|
+
console.log(" ✗ Placeholder/params mismatch");
|
|
242
|
+
failed++;
|
|
243
|
+
}
|
|
244
|
+
} else {
|
|
245
|
+
console.log(" ✗ Query object incomplete");
|
|
246
|
+
failed++;
|
|
247
|
+
}
|
|
248
|
+
} catch (err) {
|
|
249
|
+
console.log(` ✗ Error: ${err.message}`);
|
|
250
|
+
failed++;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
// Test 7: INSERT Object with $1, $2, $3 Placeholders
|
|
254
|
+
console.log("\n📝 Test 7: INSERT with $1, $2, $3... Placeholders");
|
|
255
|
+
console.log("──────────────────────────────────────────────────");
|
|
256
|
+
|
|
257
|
+
try {
|
|
258
|
+
const engine = new postgresEngine();
|
|
259
|
+
|
|
260
|
+
const mockFields = {
|
|
261
|
+
name: 'Jane Smith',
|
|
262
|
+
email: 'jane@example.com',
|
|
263
|
+
age: 25,
|
|
264
|
+
__entity: TEST_ENTITY
|
|
265
|
+
};
|
|
266
|
+
|
|
267
|
+
const insertObj = engine._buildSQLInsertObjectParameterized(mockFields, TEST_ENTITY);
|
|
268
|
+
|
|
269
|
+
if (insertObj && insertObj !== -1) {
|
|
270
|
+
console.log(" ✓ INSERT object generated");
|
|
271
|
+
console.log(` ✓ Table: ${insertObj.tableName}`);
|
|
272
|
+
console.log(` ✓ Columns: ${insertObj.columns}`);
|
|
273
|
+
console.log(` ✓ Placeholders: ${insertObj.placeholders}`);
|
|
274
|
+
console.log(` ✓ Params count: ${insertObj.params.length}`);
|
|
275
|
+
|
|
276
|
+
// Verify PostgreSQL placeholder format ($1, $2, $3...)
|
|
277
|
+
if (insertObj.placeholders.includes('$1') && insertObj.placeholders.includes('$2')) {
|
|
278
|
+
console.log(" ✓ Uses PostgreSQL $1, $2, $3... format");
|
|
279
|
+
passed++;
|
|
280
|
+
} else {
|
|
281
|
+
console.log(` ✗ Wrong placeholder format: ${insertObj.placeholders}`);
|
|
282
|
+
failed++;
|
|
283
|
+
}
|
|
284
|
+
} else {
|
|
285
|
+
console.log(" ✗ INSERT object generation failed");
|
|
286
|
+
failed++;
|
|
287
|
+
}
|
|
288
|
+
} catch (err) {
|
|
289
|
+
console.log(` ✗ Error: ${err.message}`);
|
|
290
|
+
failed++;
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
// Test 8: LIMIT and OFFSET
|
|
294
|
+
console.log("\n📝 Test 8: LIMIT and OFFSET (OFFSET syntax)");
|
|
295
|
+
console.log("──────────────────────────────────────────────────");
|
|
296
|
+
|
|
297
|
+
try {
|
|
298
|
+
const engine = new postgresEngine();
|
|
299
|
+
|
|
300
|
+
const limitQuery = { take: 10 };
|
|
301
|
+
const limitClause = engine.buildLimit(limitQuery);
|
|
302
|
+
|
|
303
|
+
const skipQuery = { skip: 20 };
|
|
304
|
+
const skipClause = engine.buildSkip(skipQuery);
|
|
305
|
+
|
|
306
|
+
if (limitClause === 'LIMIT 10' && skipClause === 'OFFSET 20') {
|
|
307
|
+
console.log(" ✓ LIMIT clause: LIMIT 10");
|
|
308
|
+
console.log(" ✓ SKIP clause: OFFSET 20");
|
|
309
|
+
console.log(" ✓ PostgreSQL pagination syntax correct");
|
|
310
|
+
passed++;
|
|
311
|
+
} else {
|
|
312
|
+
console.log(` ✗ Wrong pagination syntax`);
|
|
313
|
+
console.log(` ✗ LIMIT: ${limitClause}, SKIP: ${skipClause}`);
|
|
314
|
+
failed++;
|
|
315
|
+
}
|
|
316
|
+
} catch (err) {
|
|
317
|
+
console.log(` ✗ Error: ${err.message}`);
|
|
318
|
+
failed++;
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
// Test 9: ORDER BY
|
|
322
|
+
console.log("\n📝 Test 9: ORDER BY Clause");
|
|
323
|
+
console.log("──────────────────────────────────────────────────");
|
|
324
|
+
|
|
325
|
+
try {
|
|
326
|
+
const engine = new postgresEngine();
|
|
327
|
+
|
|
328
|
+
const ascQuery = {
|
|
329
|
+
orderBy: 'name',
|
|
330
|
+
parentName: 'User',
|
|
331
|
+
entityMap: [{ name: 'User', entity: 'User' }]
|
|
332
|
+
};
|
|
333
|
+
|
|
334
|
+
const descQuery = {
|
|
335
|
+
orderByDescending: 'created_at',
|
|
336
|
+
parentName: 'User',
|
|
337
|
+
entityMap: [{ name: 'User', entity: 'User' }]
|
|
338
|
+
};
|
|
339
|
+
|
|
340
|
+
const ascClause = engine.buildOrderBy(ascQuery);
|
|
341
|
+
const descClause = engine.buildOrderBy(descQuery);
|
|
342
|
+
|
|
343
|
+
if (ascClause.includes('ORDER BY') && ascClause.includes('ASC') &&
|
|
344
|
+
descClause.includes('ORDER BY') && descClause.includes('DESC')) {
|
|
345
|
+
console.log(" ✓ ORDER BY ASC: " + ascClause);
|
|
346
|
+
console.log(" ✓ ORDER BY DESC: " + descClause);
|
|
347
|
+
passed++;
|
|
348
|
+
} else {
|
|
349
|
+
console.log(` ✗ ORDER BY clauses incorrect`);
|
|
350
|
+
failed++;
|
|
351
|
+
}
|
|
352
|
+
} catch (err) {
|
|
353
|
+
console.log(` ✗ Error: ${err.message}`);
|
|
354
|
+
failed++;
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
// Test 10: Field Type Validation
|
|
358
|
+
console.log("\n📝 Test 10: Field Type Validation and Coercion");
|
|
359
|
+
console.log("──────────────────────────────────────────────────");
|
|
360
|
+
|
|
361
|
+
try {
|
|
362
|
+
const engine = new postgresEngine();
|
|
363
|
+
|
|
364
|
+
// Test integer coercion
|
|
365
|
+
const intField = { type: 'integer', nullable: false };
|
|
366
|
+
const intValue = engine._validateAndCoerceFieldType('25', intField, 'User', 'age');
|
|
367
|
+
|
|
368
|
+
// Test string coercion
|
|
369
|
+
const strField = { type: 'string', nullable: false };
|
|
370
|
+
const strValue = engine._validateAndCoerceFieldType(123, strField, 'User', 'name');
|
|
371
|
+
|
|
372
|
+
// Test boolean coercion
|
|
373
|
+
const boolField = { type: 'boolean', nullable: false };
|
|
374
|
+
const boolValue = engine._validateAndCoerceFieldType(1, boolField, 'User', 'active');
|
|
375
|
+
|
|
376
|
+
if (typeof intValue === 'number' && intValue === 25 &&
|
|
377
|
+
typeof strValue === 'string' && strValue === '123' &&
|
|
378
|
+
typeof boolValue === 'boolean' && boolValue === true) {
|
|
379
|
+
console.log(" ✓ Integer coercion: '25' → 25");
|
|
380
|
+
console.log(" ✓ String coercion: 123 → '123'");
|
|
381
|
+
console.log(" ✓ Boolean coercion: 1 → true");
|
|
382
|
+
passed++;
|
|
383
|
+
} else {
|
|
384
|
+
console.log(" ✗ Type coercion failed");
|
|
385
|
+
failed++;
|
|
386
|
+
}
|
|
387
|
+
} catch (err) {
|
|
388
|
+
console.log(` ✗ Error: ${err.message}`);
|
|
389
|
+
failed++;
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
// Test 11: Nullable Field Validation
|
|
393
|
+
console.log("\n📝 Test 11: Nullable Field Validation");
|
|
394
|
+
console.log("──────────────────────────────────────────────────");
|
|
395
|
+
|
|
396
|
+
try {
|
|
397
|
+
const engine = new postgresEngine();
|
|
398
|
+
|
|
399
|
+
// Test nullable field accepts null
|
|
400
|
+
const nullableField = { type: 'integer', nullable: true };
|
|
401
|
+
const nullValue = engine._validateAndCoerceFieldType(null, nullableField, 'User', 'age');
|
|
402
|
+
|
|
403
|
+
// Test non-nullable field rejects null
|
|
404
|
+
const nonNullableField = { type: 'string', nullable: false };
|
|
405
|
+
let caughtError = false;
|
|
406
|
+
|
|
407
|
+
try {
|
|
408
|
+
engine._validateAndCoerceFieldType(null, nonNullableField, 'User', 'name');
|
|
409
|
+
} catch (err) {
|
|
410
|
+
if (err.message.includes('cannot be null')) {
|
|
411
|
+
caughtError = true;
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
if (nullValue === null && caughtError) {
|
|
416
|
+
console.log(" ✓ Nullable field accepts null");
|
|
417
|
+
console.log(" ✓ Non-nullable field rejects null");
|
|
418
|
+
passed++;
|
|
419
|
+
} else {
|
|
420
|
+
console.log(" ✗ Nullable validation failed");
|
|
421
|
+
failed++;
|
|
422
|
+
}
|
|
423
|
+
} catch (err) {
|
|
424
|
+
console.log(` ✗ Error: ${err.message}`);
|
|
425
|
+
failed++;
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
// Summary
|
|
429
|
+
console.log("\n\n╔════════════════════════════════════════════════════════════════╗");
|
|
430
|
+
console.log("║ Test Summary ║");
|
|
431
|
+
console.log("╚════════════════════════════════════════════════════════════════╝");
|
|
432
|
+
|
|
433
|
+
const total = passed + failed;
|
|
434
|
+
const successRate = total > 0 ? Math.round((passed/total)*100) : 0;
|
|
435
|
+
|
|
436
|
+
console.log(`\n Total Tests: ${total}`);
|
|
437
|
+
console.log(` ✅ Passed: ${passed}`);
|
|
438
|
+
console.log(` ❌ Failed: ${failed}`);
|
|
439
|
+
console.log(` Success Rate: ${successRate}%\n`);
|
|
440
|
+
|
|
441
|
+
if (failed === 0) {
|
|
442
|
+
console.log("🎉 All PostgreSQL engine tests passed!");
|
|
443
|
+
console.log("\n✨ PostgreSQL Engine Implementation Verified!");
|
|
444
|
+
console.log("\n📖 Verified Features:");
|
|
445
|
+
console.log(" ✓ $1, $2, $3... placeholder generation");
|
|
446
|
+
console.log(" ✓ Placeholder detection (doesn't quote placeholders)");
|
|
447
|
+
console.log(" ✓ Literal value quoting");
|
|
448
|
+
console.log(" ✓ NULL handling (= converts to IS)");
|
|
449
|
+
console.log(" ✓ WHERE clause building");
|
|
450
|
+
console.log(" ✓ AND clause building");
|
|
451
|
+
console.log(" ✓ Complete query building");
|
|
452
|
+
console.log(" ✓ INSERT object with PostgreSQL placeholders");
|
|
453
|
+
console.log(" ✓ LIMIT/OFFSET pagination");
|
|
454
|
+
console.log(" ✓ ORDER BY ASC/DESC");
|
|
455
|
+
console.log(" ✓ Field type validation and coercion");
|
|
456
|
+
console.log(" ✓ Nullable field validation");
|
|
457
|
+
console.log("\n✅ All session bug fixes properly implemented!\n");
|
|
458
|
+
process.exit(0);
|
|
459
|
+
} else {
|
|
460
|
+
console.log("⚠️ Some engine tests failed.");
|
|
461
|
+
console.log(" Review the postgresEngine.js implementation.\n");
|
|
462
|
+
process.exit(1);
|
|
463
|
+
}
|