@objectql/core 3.0.1 → 4.0.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/CHANGELOG.md +17 -3
- package/README.md +31 -9
- package/dist/ai-agent.d.ts +4 -3
- package/dist/ai-agent.js +10 -3
- package/dist/ai-agent.js.map +1 -1
- package/dist/app.d.ts +29 -6
- package/dist/app.js +117 -58
- package/dist/app.js.map +1 -1
- package/dist/formula-engine.d.ts +7 -0
- package/dist/formula-engine.js +9 -2
- package/dist/formula-engine.js.map +1 -1
- package/dist/formula-plugin.d.ts +52 -0
- package/dist/formula-plugin.js +107 -0
- package/dist/formula-plugin.js.map +1 -0
- package/dist/index.d.ts +16 -3
- package/dist/index.js +14 -3
- package/dist/index.js.map +1 -1
- package/dist/plugin.d.ts +89 -0
- package/dist/plugin.js +136 -0
- package/dist/plugin.js.map +1 -0
- package/dist/query/filter-translator.d.ts +39 -0
- package/dist/query/filter-translator.js +135 -0
- package/dist/query/filter-translator.js.map +1 -0
- package/dist/query/index.d.ts +22 -0
- package/dist/query/index.js +39 -0
- package/dist/query/index.js.map +1 -0
- package/dist/query/query-analyzer.d.ts +188 -0
- package/dist/query/query-analyzer.js +349 -0
- package/dist/query/query-analyzer.js.map +1 -0
- package/dist/query/query-builder.d.ts +29 -0
- package/dist/query/query-builder.js +71 -0
- package/dist/query/query-builder.js.map +1 -0
- package/dist/query/query-service.d.ts +152 -0
- package/dist/query/query-service.js +268 -0
- package/dist/query/query-service.js.map +1 -0
- package/dist/repository.d.ts +23 -2
- package/dist/repository.js +81 -14
- package/dist/repository.js.map +1 -1
- package/dist/util.d.ts +7 -0
- package/dist/util.js +18 -3
- package/dist/util.js.map +1 -1
- package/dist/validator-plugin.d.ts +56 -0
- package/dist/validator-plugin.js +106 -0
- package/dist/validator-plugin.js.map +1 -0
- package/dist/validator.d.ts +7 -0
- package/dist/validator.js +10 -8
- package/dist/validator.js.map +1 -1
- package/jest.config.js +16 -0
- package/package.json +7 -5
- package/src/ai-agent.ts +8 -0
- package/src/app.ts +136 -72
- package/src/formula-engine.ts +8 -0
- package/src/formula-plugin.ts +141 -0
- package/src/index.ts +28 -3
- package/src/plugin.ts +224 -0
- package/src/query/filter-translator.ts +148 -0
- package/src/query/index.ts +24 -0
- package/src/query/query-analyzer.ts +537 -0
- package/src/query/query-builder.ts +81 -0
- package/src/query/query-service.ts +393 -0
- package/src/repository.ts +101 -18
- package/src/util.ts +19 -3
- package/src/validator-plugin.ts +140 -0
- package/src/validator.ts +12 -5
- package/test/__mocks__/@objectstack/runtime.ts +255 -0
- package/test/app.test.ts +23 -35
- package/test/filter-syntax.test.ts +233 -0
- package/test/formula-engine.test.ts +8 -0
- package/test/formula-integration.test.ts +8 -0
- package/test/formula-plugin.test.ts +197 -0
- package/test/introspection.test.ts +8 -0
- package/test/mock-driver.ts +8 -0
- package/test/plugin-integration.test.ts +213 -0
- package/test/repository-validation.test.ts +8 -0
- package/test/repository.test.ts +8 -0
- package/test/util.test.ts +9 -1
- package/test/utils.ts +8 -0
- package/test/validator-plugin.test.ts +126 -0
- package/test/validator.test.ts +8 -0
- package/tsconfig.json +8 -0
- package/tsconfig.tsbuildinfo +1 -1
- package/dist/action.d.ts +0 -7
- package/dist/action.js +0 -23
- package/dist/action.js.map +0 -1
- package/dist/hook.d.ts +0 -8
- package/dist/hook.js +0 -25
- package/dist/hook.js.map +0 -1
- package/dist/object.d.ts +0 -3
- package/dist/object.js +0 -28
- package/dist/object.js.map +0 -1
- package/src/action.ts +0 -40
- package/src/hook.ts +0 -42
- package/src/object.ts +0 -26
- package/test/action.test.ts +0 -276
- package/test/hook.test.ts +0 -343
- package/test/object.test.ts +0 -183
|
@@ -0,0 +1,349 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* ObjectQL Query Analyzer
|
|
4
|
+
* Copyright (c) 2026-present ObjectStack Inc.
|
|
5
|
+
*
|
|
6
|
+
* This source code is licensed under the MIT license found in the
|
|
7
|
+
* LICENSE file in the root directory of this source tree.
|
|
8
|
+
*/
|
|
9
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
+
exports.QueryAnalyzer = void 0;
|
|
11
|
+
/**
|
|
12
|
+
* Query Analyzer
|
|
13
|
+
*
|
|
14
|
+
* Provides query performance analysis and profiling capabilities.
|
|
15
|
+
* This class helps developers optimize queries by:
|
|
16
|
+
* - Analyzing query plans
|
|
17
|
+
* - Profiling execution performance
|
|
18
|
+
* - Tracking statistics
|
|
19
|
+
* - Providing optimization suggestions
|
|
20
|
+
*/
|
|
21
|
+
class QueryAnalyzer {
|
|
22
|
+
constructor(queryService, metadata) {
|
|
23
|
+
this.queryService = queryService;
|
|
24
|
+
this.metadata = metadata;
|
|
25
|
+
this.stats = {
|
|
26
|
+
totalQueries: 0,
|
|
27
|
+
avgExecutionTime: 0,
|
|
28
|
+
slowestQuery: 0,
|
|
29
|
+
fastestQuery: Number.MAX_VALUE,
|
|
30
|
+
byObject: {},
|
|
31
|
+
slowQueries: []
|
|
32
|
+
};
|
|
33
|
+
this.executionTimes = [];
|
|
34
|
+
this.MAX_SLOW_QUERIES = 10;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Analyze a query and generate an execution plan
|
|
38
|
+
*
|
|
39
|
+
* @param objectName - The object to query
|
|
40
|
+
* @param query - The unified query
|
|
41
|
+
* @returns Query plan with optimization suggestions
|
|
42
|
+
*/
|
|
43
|
+
async explain(objectName, query) {
|
|
44
|
+
const schema = this.getSchema(objectName);
|
|
45
|
+
// Build the QueryAST (without executing)
|
|
46
|
+
const ast = {
|
|
47
|
+
object: objectName,
|
|
48
|
+
filters: query.filters, // FilterCondition is compatible with FilterNode
|
|
49
|
+
sort: query.sort, // Will be converted to SortNode[] format
|
|
50
|
+
top: query.limit, // Changed from limit to top (QueryAST uses 'top')
|
|
51
|
+
skip: query.skip,
|
|
52
|
+
fields: query.fields
|
|
53
|
+
};
|
|
54
|
+
// Analyze filters for index usage
|
|
55
|
+
const indexes = this.findApplicableIndexes(schema, query);
|
|
56
|
+
// Detect potential issues
|
|
57
|
+
const warnings = this.analyzeWarnings(schema, query);
|
|
58
|
+
// Generate suggestions
|
|
59
|
+
const suggestions = this.generateSuggestions(schema, query, indexes);
|
|
60
|
+
// Calculate complexity
|
|
61
|
+
const complexity = this.calculateComplexity(query);
|
|
62
|
+
// Try to estimate rows (basic heuristic)
|
|
63
|
+
const estimatedRows = this.estimateRows(schema, query);
|
|
64
|
+
return {
|
|
65
|
+
ast,
|
|
66
|
+
estimatedRows,
|
|
67
|
+
indexes,
|
|
68
|
+
warnings,
|
|
69
|
+
suggestions,
|
|
70
|
+
complexity
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Profile a query execution
|
|
75
|
+
*
|
|
76
|
+
* @param objectName - The object to query
|
|
77
|
+
* @param query - The unified query
|
|
78
|
+
* @param options - Query execution options
|
|
79
|
+
* @returns Profile result with execution statistics
|
|
80
|
+
*/
|
|
81
|
+
async profile(objectName, query, options = {}) {
|
|
82
|
+
var _a, _b;
|
|
83
|
+
// Get the query plan first
|
|
84
|
+
const plan = await this.explain(objectName, query);
|
|
85
|
+
// Execute with profiling enabled
|
|
86
|
+
const result = await this.queryService.find(objectName, query, {
|
|
87
|
+
...options,
|
|
88
|
+
profile: true
|
|
89
|
+
});
|
|
90
|
+
const executionTime = ((_a = result.profile) === null || _a === void 0 ? void 0 : _a.executionTime) || 0;
|
|
91
|
+
const rowsReturned = result.value.length;
|
|
92
|
+
const rowsScanned = ((_b = result.profile) === null || _b === void 0 ? void 0 : _b.rowsScanned) || rowsReturned;
|
|
93
|
+
// Calculate efficiency
|
|
94
|
+
const efficiency = rowsScanned > 0 ? rowsReturned / rowsScanned : 0;
|
|
95
|
+
// Determine if index was used (heuristic)
|
|
96
|
+
const indexUsed = plan.indexes.length > 0 && efficiency > 0.5;
|
|
97
|
+
// Update statistics
|
|
98
|
+
this.recordExecution(objectName, executionTime, query);
|
|
99
|
+
return {
|
|
100
|
+
executionTime,
|
|
101
|
+
rowsScanned,
|
|
102
|
+
rowsReturned,
|
|
103
|
+
indexUsed,
|
|
104
|
+
plan,
|
|
105
|
+
efficiency
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Get aggregated query statistics
|
|
110
|
+
*
|
|
111
|
+
* @returns Current query statistics
|
|
112
|
+
*/
|
|
113
|
+
getStatistics() {
|
|
114
|
+
return { ...this.stats };
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Reset statistics
|
|
118
|
+
*/
|
|
119
|
+
resetStatistics() {
|
|
120
|
+
this.stats = {
|
|
121
|
+
totalQueries: 0,
|
|
122
|
+
avgExecutionTime: 0,
|
|
123
|
+
slowestQuery: 0,
|
|
124
|
+
fastestQuery: Number.MAX_VALUE,
|
|
125
|
+
byObject: {},
|
|
126
|
+
slowQueries: []
|
|
127
|
+
};
|
|
128
|
+
this.executionTimes = [];
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Get schema for an object
|
|
132
|
+
* @private
|
|
133
|
+
*/
|
|
134
|
+
getSchema(objectName) {
|
|
135
|
+
const obj = this.metadata.get('object', objectName);
|
|
136
|
+
if (!obj) {
|
|
137
|
+
throw new Error(`Object '${objectName}' not found`);
|
|
138
|
+
}
|
|
139
|
+
return obj;
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Find indexes that could be used for the query
|
|
143
|
+
* @private
|
|
144
|
+
*/
|
|
145
|
+
findApplicableIndexes(schema, query) {
|
|
146
|
+
const indexes = [];
|
|
147
|
+
if (!schema.indexes || !query.filters) {
|
|
148
|
+
return indexes;
|
|
149
|
+
}
|
|
150
|
+
// Extract fields used in filters
|
|
151
|
+
const filterFields = new Set();
|
|
152
|
+
// FilterCondition is an object-based filter (e.g., { field: value } or { field: { $eq: value } })
|
|
153
|
+
// We need to extract field names from the filter object
|
|
154
|
+
const extractFieldsFromFilter = (filter) => {
|
|
155
|
+
if (!filter || typeof filter !== 'object')
|
|
156
|
+
return;
|
|
157
|
+
for (const key of Object.keys(filter)) {
|
|
158
|
+
// Skip logical operators
|
|
159
|
+
if (key.startsWith('$')) {
|
|
160
|
+
// Logical operators contain nested filters
|
|
161
|
+
if (key === '$and' || key === '$or') {
|
|
162
|
+
const nested = filter[key];
|
|
163
|
+
if (Array.isArray(nested)) {
|
|
164
|
+
nested.forEach(extractFieldsFromFilter);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
continue;
|
|
168
|
+
}
|
|
169
|
+
// This is a field name
|
|
170
|
+
filterFields.add(key);
|
|
171
|
+
}
|
|
172
|
+
};
|
|
173
|
+
extractFieldsFromFilter(query.filters);
|
|
174
|
+
// Check which indexes could be used
|
|
175
|
+
const indexesArray = Array.isArray(schema.indexes) ? schema.indexes : Object.values(schema.indexes || {});
|
|
176
|
+
for (const index of indexesArray) {
|
|
177
|
+
const indexFields = Array.isArray(index.fields)
|
|
178
|
+
? index.fields
|
|
179
|
+
: [index.fields];
|
|
180
|
+
// Simple heuristic: index is applicable if first field is in filter
|
|
181
|
+
if (indexFields.length > 0 && filterFields.has(indexFields[0])) {
|
|
182
|
+
const indexName = index.name || indexFields.join('_');
|
|
183
|
+
indexes.push(indexName);
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
return indexes;
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* Analyze query for potential issues
|
|
190
|
+
* @private
|
|
191
|
+
*/
|
|
192
|
+
analyzeWarnings(schema, query) {
|
|
193
|
+
const warnings = [];
|
|
194
|
+
// Warning: No filters (full table scan)
|
|
195
|
+
if (!query.filters || query.filters.length === 0) {
|
|
196
|
+
warnings.push('No filters specified - this will scan all records');
|
|
197
|
+
}
|
|
198
|
+
// Warning: No limit on potentially large dataset
|
|
199
|
+
if (!query.limit) {
|
|
200
|
+
warnings.push('No limit specified - consider adding pagination');
|
|
201
|
+
}
|
|
202
|
+
// Warning: Selecting all fields
|
|
203
|
+
if (!query.fields || query.fields.length === 0) {
|
|
204
|
+
const fieldCount = Object.keys(schema.fields || {}).length;
|
|
205
|
+
if (fieldCount > 10) {
|
|
206
|
+
warnings.push(`Selecting all ${fieldCount} fields - consider selecting only needed fields`);
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
// Warning: Complex filters without indexes
|
|
210
|
+
if (query.filters && query.filters.length > 5) {
|
|
211
|
+
const indexes = this.findApplicableIndexes(schema, query);
|
|
212
|
+
if (indexes.length === 0) {
|
|
213
|
+
warnings.push('Complex filters without matching indexes - consider adding indexes');
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
return warnings;
|
|
217
|
+
}
|
|
218
|
+
/**
|
|
219
|
+
* Generate optimization suggestions
|
|
220
|
+
* @private
|
|
221
|
+
*/
|
|
222
|
+
generateSuggestions(schema, query, indexes) {
|
|
223
|
+
const suggestions = [];
|
|
224
|
+
// Suggest adding limit
|
|
225
|
+
if (!query.limit) {
|
|
226
|
+
suggestions.push('Add a limit clause to restrict result set size');
|
|
227
|
+
}
|
|
228
|
+
// Suggest adding indexes
|
|
229
|
+
if (query.filters && query.filters.length > 0 && indexes.length === 0) {
|
|
230
|
+
const filterFields = query.filters
|
|
231
|
+
.filter((f) => Array.isArray(f) && f.length >= 1)
|
|
232
|
+
.map((f) => String(f[0]));
|
|
233
|
+
if (filterFields.length > 0) {
|
|
234
|
+
suggestions.push(`Consider adding an index on: ${filterFields.join(', ')}`);
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
// Suggest field selection
|
|
238
|
+
if (!query.fields || query.fields.length === 0) {
|
|
239
|
+
suggestions.push('Select only required fields to reduce data transfer');
|
|
240
|
+
}
|
|
241
|
+
// Suggest composite index for multiple filters
|
|
242
|
+
if (query.filters && query.filters.length > 1 && indexes.length < 2) {
|
|
243
|
+
const filterFields = query.filters
|
|
244
|
+
.filter((f) => Array.isArray(f) && f.length >= 1)
|
|
245
|
+
.map((f) => String(f[0]))
|
|
246
|
+
.slice(0, 3); // Top 3 fields
|
|
247
|
+
if (filterFields.length > 1) {
|
|
248
|
+
suggestions.push(`Consider a composite index on: (${filterFields.join(', ')})`);
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
return suggestions;
|
|
252
|
+
}
|
|
253
|
+
/**
|
|
254
|
+
* Calculate query complexity score (0-100)
|
|
255
|
+
* @private
|
|
256
|
+
*/
|
|
257
|
+
calculateComplexity(query) {
|
|
258
|
+
let complexity = 0;
|
|
259
|
+
// Base complexity
|
|
260
|
+
complexity += 10;
|
|
261
|
+
// Filters add complexity
|
|
262
|
+
if (query.filters) {
|
|
263
|
+
complexity += query.filters.length * 5;
|
|
264
|
+
// Nested filters (OR conditions) add more
|
|
265
|
+
const hasNestedFilters = query.filters.some((f) => Array.isArray(f) && Array.isArray(f[0]));
|
|
266
|
+
if (hasNestedFilters) {
|
|
267
|
+
complexity += 15;
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
// Sorting adds complexity
|
|
271
|
+
if (query.sort && query.sort.length > 0) {
|
|
272
|
+
complexity += query.sort.length * 3;
|
|
273
|
+
}
|
|
274
|
+
// Field selection reduces complexity slightly
|
|
275
|
+
if (query.fields && query.fields.length > 0 && query.fields.length < 10) {
|
|
276
|
+
complexity -= 5;
|
|
277
|
+
}
|
|
278
|
+
// Pagination reduces complexity
|
|
279
|
+
if (query.limit) {
|
|
280
|
+
complexity -= 5;
|
|
281
|
+
}
|
|
282
|
+
// Cap at 100
|
|
283
|
+
return Math.min(Math.max(complexity, 0), 100);
|
|
284
|
+
}
|
|
285
|
+
/**
|
|
286
|
+
* Estimate number of rows (very rough heuristic)
|
|
287
|
+
* @private
|
|
288
|
+
*/
|
|
289
|
+
estimateRows(schema, query) {
|
|
290
|
+
// This is a placeholder - real implementation would need statistics
|
|
291
|
+
// from the database (row count, index selectivity, etc.)
|
|
292
|
+
// Default to unknown
|
|
293
|
+
if (!query.filters || query.filters.length === 0) {
|
|
294
|
+
return -1; // Unknown, full scan
|
|
295
|
+
}
|
|
296
|
+
// Very rough estimate based on filter count
|
|
297
|
+
const baseEstimate = 1000;
|
|
298
|
+
const filterReduction = Math.pow(0.5, query.filters.length);
|
|
299
|
+
const estimated = Math.floor(baseEstimate * filterReduction);
|
|
300
|
+
// Apply limit if present
|
|
301
|
+
if (query.limit) {
|
|
302
|
+
return Math.min(estimated, query.limit);
|
|
303
|
+
}
|
|
304
|
+
return estimated;
|
|
305
|
+
}
|
|
306
|
+
/**
|
|
307
|
+
* Record a query execution for statistics
|
|
308
|
+
* @private
|
|
309
|
+
*/
|
|
310
|
+
recordExecution(objectName, executionTime, query) {
|
|
311
|
+
// Update totals
|
|
312
|
+
this.stats.totalQueries++;
|
|
313
|
+
this.executionTimes.push(executionTime);
|
|
314
|
+
// Update average
|
|
315
|
+
this.stats.avgExecutionTime =
|
|
316
|
+
this.executionTimes.reduce((sum, t) => sum + t, 0) / this.executionTimes.length;
|
|
317
|
+
// Update min/max
|
|
318
|
+
this.stats.slowestQuery = Math.max(this.stats.slowestQuery, executionTime);
|
|
319
|
+
this.stats.fastestQuery = Math.min(this.stats.fastestQuery, executionTime);
|
|
320
|
+
// Update per-object stats
|
|
321
|
+
if (!this.stats.byObject[objectName]) {
|
|
322
|
+
this.stats.byObject[objectName] = { count: 0, avgTime: 0 };
|
|
323
|
+
}
|
|
324
|
+
const objStats = this.stats.byObject[objectName];
|
|
325
|
+
objStats.count++;
|
|
326
|
+
objStats.avgTime = ((objStats.avgTime * (objStats.count - 1)) + executionTime) / objStats.count;
|
|
327
|
+
// Track slow queries
|
|
328
|
+
if (this.stats.slowQueries.length < this.MAX_SLOW_QUERIES) {
|
|
329
|
+
this.stats.slowQueries.push({
|
|
330
|
+
objectName,
|
|
331
|
+
executionTime,
|
|
332
|
+
query,
|
|
333
|
+
timestamp: new Date()
|
|
334
|
+
});
|
|
335
|
+
this.stats.slowQueries.sort((a, b) => b.executionTime - a.executionTime);
|
|
336
|
+
}
|
|
337
|
+
else if (executionTime > this.stats.slowQueries[this.MAX_SLOW_QUERIES - 1].executionTime) {
|
|
338
|
+
this.stats.slowQueries[this.MAX_SLOW_QUERIES - 1] = {
|
|
339
|
+
objectName,
|
|
340
|
+
executionTime,
|
|
341
|
+
query,
|
|
342
|
+
timestamp: new Date()
|
|
343
|
+
};
|
|
344
|
+
this.stats.slowQueries.sort((a, b) => b.executionTime - a.executionTime);
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
exports.QueryAnalyzer = QueryAnalyzer;
|
|
349
|
+
//# sourceMappingURL=query-analyzer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"query-analyzer.js","sourceRoot":"","sources":["../../src/query/query-analyzer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ObjectQL
|
|
3
|
+
* Copyright (c) 2026-present ObjectStack Inc.
|
|
4
|
+
*
|
|
5
|
+
* This source code is licensed under the MIT license found in the
|
|
6
|
+
* LICENSE file in the root directory of this source tree.
|
|
7
|
+
*/
|
|
8
|
+
import type { UnifiedQuery } from '@objectql/types';
|
|
9
|
+
import { Data } from '@objectstack/spec';
|
|
10
|
+
type QueryAST = Data.QueryAST;
|
|
11
|
+
/**
|
|
12
|
+
* Query Builder
|
|
13
|
+
*
|
|
14
|
+
* Builds ObjectStack QueryAST from ObjectQL UnifiedQuery.
|
|
15
|
+
* This is the central query construction module for ObjectQL.
|
|
16
|
+
*/
|
|
17
|
+
export declare class QueryBuilder {
|
|
18
|
+
private filterTranslator;
|
|
19
|
+
constructor();
|
|
20
|
+
/**
|
|
21
|
+
* Build a QueryAST from a UnifiedQuery
|
|
22
|
+
*
|
|
23
|
+
* @param objectName - Target object name
|
|
24
|
+
* @param query - ObjectQL UnifiedQuery
|
|
25
|
+
* @returns ObjectStack QueryAST
|
|
26
|
+
*/
|
|
27
|
+
build(objectName: string, query: UnifiedQuery): QueryAST;
|
|
28
|
+
}
|
|
29
|
+
export {};
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* ObjectQL
|
|
4
|
+
* Copyright (c) 2026-present ObjectStack Inc.
|
|
5
|
+
*
|
|
6
|
+
* This source code is licensed under the MIT license found in the
|
|
7
|
+
* LICENSE file in the root directory of this source tree.
|
|
8
|
+
*/
|
|
9
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
+
exports.QueryBuilder = void 0;
|
|
11
|
+
const filter_translator_1 = require("./filter-translator");
|
|
12
|
+
/**
|
|
13
|
+
* Query Builder
|
|
14
|
+
*
|
|
15
|
+
* Builds ObjectStack QueryAST from ObjectQL UnifiedQuery.
|
|
16
|
+
* This is the central query construction module for ObjectQL.
|
|
17
|
+
*/
|
|
18
|
+
class QueryBuilder {
|
|
19
|
+
constructor() {
|
|
20
|
+
this.filterTranslator = new filter_translator_1.FilterTranslator();
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Build a QueryAST from a UnifiedQuery
|
|
24
|
+
*
|
|
25
|
+
* @param objectName - Target object name
|
|
26
|
+
* @param query - ObjectQL UnifiedQuery
|
|
27
|
+
* @returns ObjectStack QueryAST
|
|
28
|
+
*/
|
|
29
|
+
build(objectName, query) {
|
|
30
|
+
const ast = {
|
|
31
|
+
object: objectName,
|
|
32
|
+
};
|
|
33
|
+
// Map fields
|
|
34
|
+
if (query.fields) {
|
|
35
|
+
ast.fields = query.fields;
|
|
36
|
+
}
|
|
37
|
+
// Map filters using FilterTranslator
|
|
38
|
+
if (query.filters) {
|
|
39
|
+
ast.filters = this.filterTranslator.translate(query.filters);
|
|
40
|
+
}
|
|
41
|
+
// Map sort
|
|
42
|
+
if (query.sort) {
|
|
43
|
+
ast.sort = query.sort.map(([field, order]) => ({
|
|
44
|
+
field,
|
|
45
|
+
order: order
|
|
46
|
+
}));
|
|
47
|
+
}
|
|
48
|
+
// Map pagination
|
|
49
|
+
if (query.limit !== undefined) {
|
|
50
|
+
ast.top = query.limit;
|
|
51
|
+
}
|
|
52
|
+
if (query.skip !== undefined) {
|
|
53
|
+
ast.skip = query.skip;
|
|
54
|
+
}
|
|
55
|
+
// Map groupBy
|
|
56
|
+
if (query.groupBy) {
|
|
57
|
+
ast.groupBy = query.groupBy;
|
|
58
|
+
}
|
|
59
|
+
// Map aggregations
|
|
60
|
+
if (query.aggregate) {
|
|
61
|
+
ast.aggregations = query.aggregate.map(agg => ({
|
|
62
|
+
function: agg.func,
|
|
63
|
+
field: agg.field,
|
|
64
|
+
alias: agg.alias || `${agg.func}_${agg.field}`
|
|
65
|
+
}));
|
|
66
|
+
}
|
|
67
|
+
return ast;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
exports.QueryBuilder = QueryBuilder;
|
|
71
|
+
//# sourceMappingURL=query-builder.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"query-builder.js","sourceRoot":"","sources":["../../src/query/query-builder.ts"],"names":[],"mappings":";AAAA;;;;;;GAMG;;;AAKH,2DAAuD;AAEvD;;;;;GAKG;AACH,MAAa,YAAY;IAGrB;QACI,IAAI,CAAC,gBAAgB,GAAG,IAAI,oCAAgB,EAAE,CAAC;IACnD,CAAC;IAED;;;;;;OAMG;IACH,KAAK,CAAC,UAAkB,EAAE,KAAmB;QACzC,MAAM,GAAG,GAAa;YAClB,MAAM,EAAE,UAAU;SACrB,CAAC;QAEF,aAAa;QACb,IAAI,KAAK,CAAC,MAAM,EAAE,CAAC;YACf,GAAG,CAAC,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC;QAC9B,CAAC;QAED,qCAAqC;QACrC,IAAI,KAAK,CAAC,OAAO,EAAE,CAAC;YAChB,GAAG,CAAC,OAAO,GAAG,IAAI,CAAC,gBAAgB,CAAC,SAAS,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QACjE,CAAC;QAED,WAAW;QACX,IAAI,KAAK,CAAC,IAAI,EAAE,CAAC;YACb,GAAG,CAAC,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,CAAC;gBAC3C,KAAK;gBACL,KAAK,EAAE,KAAuB;aACjC,CAAC,CAAC,CAAC;QACR,CAAC;QAED,iBAAiB;QACjB,IAAI,KAAK,CAAC,KAAK,KAAK,SAAS,EAAE,CAAC;YAC5B,GAAG,CAAC,GAAG,GAAG,KAAK,CAAC,KAAK,CAAC;QAC1B,CAAC;QACD,IAAI,KAAK,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;YAC3B,GAAG,CAAC,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC;QAC1B,CAAC;QAED,cAAc;QACd,IAAI,KAAK,CAAC,OAAO,EAAE,CAAC;YAChB,GAAG,CAAC,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC;QAChC,CAAC;QAED,mBAAmB;QACnB,IAAI,KAAK,CAAC,SAAS,EAAE,CAAC;YAClB,GAAG,CAAC,YAAY,GAAG,KAAK,CAAC,SAAS,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;gBAC3C,QAAQ,EAAE,GAAG,CAAC,IAAW;gBACzB,KAAK,EAAE,GAAG,CAAC,KAAK;gBAChB,KAAK,EAAE,GAAG,CAAC,KAAK,IAAI,GAAG,GAAG,CAAC,IAAI,IAAI,GAAG,CAAC,KAAK,EAAE;aACjD,CAAC,CAAC,CAAC;QACR,CAAC;QAED,OAAO,GAAG,CAAC;IACf,CAAC;CACJ;AA7DD,oCA6DC"}
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ObjectQL Query Service
|
|
3
|
+
* Copyright (c) 2026-present ObjectStack Inc.
|
|
4
|
+
*
|
|
5
|
+
* This source code is licensed under the MIT license found in the
|
|
6
|
+
* LICENSE file in the root directory of this source tree.
|
|
7
|
+
*/
|
|
8
|
+
import type { Driver, UnifiedQuery, Filter, MetadataRegistry } from '@objectql/types';
|
|
9
|
+
import { Data } from '@objectstack/spec';
|
|
10
|
+
type QueryAST = Data.QueryAST;
|
|
11
|
+
/**
|
|
12
|
+
* Options for query execution
|
|
13
|
+
*/
|
|
14
|
+
export interface QueryOptions {
|
|
15
|
+
/**
|
|
16
|
+
* Transaction handle for transactional queries
|
|
17
|
+
*/
|
|
18
|
+
transaction?: any;
|
|
19
|
+
/**
|
|
20
|
+
* Skip validation (for system operations)
|
|
21
|
+
*/
|
|
22
|
+
skipValidation?: boolean;
|
|
23
|
+
/**
|
|
24
|
+
* Include profiling information
|
|
25
|
+
*/
|
|
26
|
+
profile?: boolean;
|
|
27
|
+
/**
|
|
28
|
+
* Custom driver options
|
|
29
|
+
*/
|
|
30
|
+
driverOptions?: Record<string, unknown>;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Result of a query execution with optional profiling data
|
|
34
|
+
*/
|
|
35
|
+
export interface QueryResult<T = any> {
|
|
36
|
+
/**
|
|
37
|
+
* The query results
|
|
38
|
+
*/
|
|
39
|
+
value: T;
|
|
40
|
+
/**
|
|
41
|
+
* Total count (for paginated queries)
|
|
42
|
+
*/
|
|
43
|
+
count?: number;
|
|
44
|
+
/**
|
|
45
|
+
* Profiling information (if profile option was enabled)
|
|
46
|
+
*/
|
|
47
|
+
profile?: QueryProfile;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Profiling information for a query
|
|
51
|
+
*/
|
|
52
|
+
export interface QueryProfile {
|
|
53
|
+
/**
|
|
54
|
+
* Execution time in milliseconds
|
|
55
|
+
*/
|
|
56
|
+
executionTime: number;
|
|
57
|
+
/**
|
|
58
|
+
* Number of rows scanned
|
|
59
|
+
*/
|
|
60
|
+
rowsScanned?: number;
|
|
61
|
+
/**
|
|
62
|
+
* Whether an index was used
|
|
63
|
+
*/
|
|
64
|
+
indexUsed?: boolean;
|
|
65
|
+
/**
|
|
66
|
+
* The generated QueryAST
|
|
67
|
+
*/
|
|
68
|
+
ast?: QueryAST;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Query Service
|
|
72
|
+
*
|
|
73
|
+
* Handles all query execution logic, separating query concerns from
|
|
74
|
+
* the repository pattern. This service is responsible for:
|
|
75
|
+
* - Building QueryAST from UnifiedQuery
|
|
76
|
+
* - Executing queries via drivers
|
|
77
|
+
* - Optional query profiling and analysis
|
|
78
|
+
*
|
|
79
|
+
* The QueryService is registered as a service in the ObjectQLPlugin
|
|
80
|
+
* and can be used by Repository for all read operations.
|
|
81
|
+
*/
|
|
82
|
+
export declare class QueryService {
|
|
83
|
+
private datasources;
|
|
84
|
+
private metadata;
|
|
85
|
+
private queryBuilder;
|
|
86
|
+
constructor(datasources: Record<string, Driver>, metadata: MetadataRegistry);
|
|
87
|
+
/**
|
|
88
|
+
* Get the driver for a specific object
|
|
89
|
+
* @private
|
|
90
|
+
*/
|
|
91
|
+
private getDriver;
|
|
92
|
+
/**
|
|
93
|
+
* Get the schema for an object
|
|
94
|
+
* @private
|
|
95
|
+
*/
|
|
96
|
+
private getSchema;
|
|
97
|
+
/**
|
|
98
|
+
* Build QueryAST from UnifiedQuery
|
|
99
|
+
* @private
|
|
100
|
+
*/
|
|
101
|
+
private buildQueryAST;
|
|
102
|
+
/**
|
|
103
|
+
* Execute a find query
|
|
104
|
+
*
|
|
105
|
+
* @param objectName - The object to query
|
|
106
|
+
* @param query - The unified query
|
|
107
|
+
* @param options - Query execution options
|
|
108
|
+
* @returns Array of matching records
|
|
109
|
+
*/
|
|
110
|
+
find(objectName: string, query?: UnifiedQuery, options?: QueryOptions): Promise<QueryResult<any[]>>;
|
|
111
|
+
/**
|
|
112
|
+
* Execute a findOne query by ID
|
|
113
|
+
*
|
|
114
|
+
* @param objectName - The object to query
|
|
115
|
+
* @param id - The record ID
|
|
116
|
+
* @param options - Query execution options
|
|
117
|
+
* @returns The matching record or undefined
|
|
118
|
+
*/
|
|
119
|
+
findOne(objectName: string, id: string | number, options?: QueryOptions): Promise<QueryResult<any>>;
|
|
120
|
+
/**
|
|
121
|
+
* Execute a count query
|
|
122
|
+
*
|
|
123
|
+
* @param objectName - The object to query
|
|
124
|
+
* @param filters - Optional filters
|
|
125
|
+
* @param options - Query execution options
|
|
126
|
+
* @returns Count of matching records
|
|
127
|
+
*/
|
|
128
|
+
count(objectName: string, filters?: Filter[], options?: QueryOptions): Promise<QueryResult<number>>;
|
|
129
|
+
/**
|
|
130
|
+
* Execute an aggregate query
|
|
131
|
+
*
|
|
132
|
+
* @param objectName - The object to query
|
|
133
|
+
* @param query - The aggregation query using UnifiedQuery format
|
|
134
|
+
* @param options - Query execution options
|
|
135
|
+
* @returns Aggregation results
|
|
136
|
+
*/
|
|
137
|
+
aggregate(objectName: string, query: UnifiedQuery, options?: QueryOptions): Promise<QueryResult<any[]>>;
|
|
138
|
+
/**
|
|
139
|
+
* Execute a direct SQL/query passthrough
|
|
140
|
+
*
|
|
141
|
+
* This bypasses ObjectQL's query builder and executes raw queries.
|
|
142
|
+
* Use with caution as it bypasses security and validation.
|
|
143
|
+
*
|
|
144
|
+
* @param objectName - The object (determines which datasource to use)
|
|
145
|
+
* @param queryString - Raw query string (SQL, MongoDB query, etc.)
|
|
146
|
+
* @param params - Query parameters (for parameterized queries)
|
|
147
|
+
* @param options - Query execution options
|
|
148
|
+
* @returns Query results
|
|
149
|
+
*/
|
|
150
|
+
directQuery(objectName: string, queryString: string, params?: any[], options?: QueryOptions): Promise<QueryResult<any>>;
|
|
151
|
+
}
|
|
152
|
+
export {};
|