dzql 0.4.1 → 0.4.2
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/package.json +1 -1
- package/src/server/db.js +15 -40
- package/src/server/namespace.js +32 -8
package/package.json
CHANGED
package/src/server/db.js
CHANGED
|
@@ -173,50 +173,14 @@ export async function setupListeners(callback) {
|
|
|
173
173
|
}
|
|
174
174
|
}
|
|
175
175
|
|
|
176
|
-
//
|
|
177
|
-
let isCompiledMode = null;
|
|
178
|
-
|
|
179
|
-
// Auto-detect if we're in compiled or runtime mode
|
|
180
|
-
async function detectMode() {
|
|
181
|
-
if (isCompiledMode !== null) {
|
|
182
|
-
return isCompiledMode;
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
try {
|
|
186
|
-
// Check if dzql.generic_exec exists
|
|
187
|
-
const result = await sql`
|
|
188
|
-
SELECT 1 FROM pg_proc
|
|
189
|
-
WHERE proname = 'generic_exec'
|
|
190
|
-
AND pronamespace = (SELECT oid FROM pg_namespace WHERE nspname = 'dzql')
|
|
191
|
-
LIMIT 1
|
|
192
|
-
`;
|
|
193
|
-
isCompiledMode = result.length === 0; // If no results, it's compiled mode
|
|
194
|
-
dbLogger.trace(isCompiledMode ? 'Detected compiled mode' : 'Detected runtime mode');
|
|
195
|
-
} catch (error) {
|
|
196
|
-
// If there's an error checking, assume runtime mode
|
|
197
|
-
isCompiledMode = false;
|
|
198
|
-
dbLogger.trace('Error detecting mode, assuming runtime mode');
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
return isCompiledMode;
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
// DZQL Generic Operations
|
|
176
|
+
// DZQL Generic Operations - Try compiled functions first, fall back to generic_exec
|
|
205
177
|
export async function callDZQLOperation(operation, entity, args, userId) {
|
|
206
178
|
dbLogger.trace(`DZQL ${operation}.${entity} for user ${userId}`);
|
|
207
179
|
|
|
208
|
-
const
|
|
209
|
-
|
|
210
|
-
if (!compiled) {
|
|
211
|
-
// Runtime mode - use generic_exec
|
|
212
|
-
const result = await sql`
|
|
213
|
-
SELECT dzql.generic_exec(${operation}, ${entity}, ${args}, ${userId}) as result
|
|
214
|
-
`;
|
|
215
|
-
return result[0].result;
|
|
216
|
-
} else {
|
|
217
|
-
// Compiled mode - call compiled function directly
|
|
218
|
-
const compiledFunctionName = `${operation}_${entity}`;
|
|
180
|
+
const compiledFunctionName = `${operation}_${entity}`;
|
|
219
181
|
|
|
182
|
+
try {
|
|
183
|
+
// Try compiled function first
|
|
220
184
|
// Different operations have different signatures:
|
|
221
185
|
// - search: search_entity(p_user_id, p_filters, p_search, p_sort, p_page, p_limit)
|
|
222
186
|
// - get: get_entity(p_user_id, p_id, p_on_date)
|
|
@@ -259,6 +223,17 @@ export async function callDZQLOperation(operation, entity, args, userId) {
|
|
|
259
223
|
} else {
|
|
260
224
|
throw new Error(`Unknown operation: ${operation}`);
|
|
261
225
|
}
|
|
226
|
+
} catch (error) {
|
|
227
|
+
// If compiled function doesn't exist, fall back to generic_exec
|
|
228
|
+
if (error.message?.includes('does not exist') || error.code === '42883') {
|
|
229
|
+
dbLogger.trace(`Compiled function ${compiledFunctionName} not found, trying generic_exec`);
|
|
230
|
+
const result = await sql`
|
|
231
|
+
SELECT dzql.generic_exec(${operation}, ${entity}, ${args}, ${userId}) as result
|
|
232
|
+
`;
|
|
233
|
+
return result[0].result;
|
|
234
|
+
}
|
|
235
|
+
// Re-throw other errors
|
|
236
|
+
throw error;
|
|
262
237
|
}
|
|
263
238
|
}
|
|
264
239
|
|
package/src/server/namespace.js
CHANGED
|
@@ -9,9 +9,10 @@ import { sql, db } from "./db.js";
|
|
|
9
9
|
const DEFAULT_USER_ID = 1;
|
|
10
10
|
|
|
11
11
|
/**
|
|
12
|
-
* Discover available entities from dzql.entities table
|
|
12
|
+
* Discover available entities from dzql.entities table or compiled functions
|
|
13
13
|
*/
|
|
14
14
|
async function discoverEntities() {
|
|
15
|
+
// First try dzql.entities table (runtime mode)
|
|
15
16
|
const result = await sql`
|
|
16
17
|
SELECT table_name, label_field, searchable_fields
|
|
17
18
|
FROM dzql.entities
|
|
@@ -19,13 +20,36 @@ async function discoverEntities() {
|
|
|
19
20
|
`;
|
|
20
21
|
|
|
21
22
|
const entities = {};
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
entities
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
23
|
+
|
|
24
|
+
if (result.length > 0) {
|
|
25
|
+
// Runtime mode - use dzql.entities table
|
|
26
|
+
for (const row of result) {
|
|
27
|
+
const searchFields = row.searchable_fields?.join(", ") || "none";
|
|
28
|
+
entities[row.table_name] = {
|
|
29
|
+
label: row.label_field,
|
|
30
|
+
searchable: row.searchable_fields || [],
|
|
31
|
+
description: `Entity: ${row.table_name} (label: ${row.label_field}, searchable: ${searchFields})`,
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
} else {
|
|
35
|
+
// Compiled mode - discover from function names
|
|
36
|
+
const functions = await sql`
|
|
37
|
+
SELECT DISTINCT substring(proname from 'search_(.+)') as entity_name
|
|
38
|
+
FROM pg_proc
|
|
39
|
+
WHERE pronamespace = (SELECT oid FROM pg_namespace WHERE nspname = 'public')
|
|
40
|
+
AND proname LIKE 'search_%'
|
|
41
|
+
AND substring(proname from 'search_(.+)') IS NOT NULL
|
|
42
|
+
ORDER BY entity_name
|
|
43
|
+
`;
|
|
44
|
+
|
|
45
|
+
for (const row of functions) {
|
|
46
|
+
const entityName = row.entity_name;
|
|
47
|
+
entities[entityName] = {
|
|
48
|
+
label: 'id', // Default, since we can't know from functions alone
|
|
49
|
+
searchable: [],
|
|
50
|
+
description: `Entity: ${entityName} (compiled mode)`,
|
|
51
|
+
};
|
|
52
|
+
}
|
|
29
53
|
}
|
|
30
54
|
|
|
31
55
|
return entities;
|