@memberjunction/generic-database-provider 5.28.0 → 5.30.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.
@@ -187,6 +187,13 @@ export declare class QueryCompositionEngine {
187
187
  * `__tests__/skip-failure-regressions.test.ts` and `SKIP-QUERY-RENDERING-BUGS.md`.
188
188
  */
189
189
  private assembleCTEs;
190
+ /**
191
+ * Validates that no CTE body still contains an illegal top-level ORDER BY
192
+ * after stripping. Throws a diagnostic error with the dep name, category
193
+ * path, and specific reason — replacing the cryptic SQL Server error
194
+ * "The ORDER BY clause is invalid in views, inline functions...".
195
+ */
196
+ private validateCTEBodies;
190
197
  /**
191
198
  * Strips the surrounding bracket / quote characters from a CTE name so we
192
199
  * can compare names case-insensitively across quoting styles. `[Foo]`,
@@ -194,29 +201,22 @@ export declare class QueryCompositionEngine {
194
201
  */
195
202
  private canonicalCTEName;
196
203
  /**
197
- * Walks `innerCTEDefinitions` (each formatted as `Name AS (\nbody\n)` by
198
- * `extractCTEsViaRegex`/`extractCTEsViaAST`) and ensures every CTE name is
199
- * unique across the assembled WITH. When a collision is detected, the inner
200
- * CTE is renamed (`Name` → `Name__2`, `__3`, …) and the new name is
201
- * substituted everywhere the original was referenced — both in subsequent
202
- * inner CTE bodies (siblings can reference each other) and in the dep's
203
- * main SELECT.
204
+ * Deconflicts inner CTE names using a SymbolTable for name allocation.
205
+ * The SymbolTable guarantees uniqueness at registration time — name
206
+ * collisions become impossible by construction.
204
207
  *
205
- * NOTE (Phase 0 trade-off): reference rewriting is a word-boundary regex
206
- * over raw SQL. It does NOT skip string literals or comments. Real
207
- * dependencies' inner-CTE names are unlikely to appear as quoted text or
208
- * column aliases, so this is acceptable for the immediate fix; the
209
- * IR-based redesign (see plans/query-rendering-pipeline-redesign.md)
210
- * replaces this with a structured walk.
208
+ * Reference rewriting uses word-boundary regex over raw SQL. It does
209
+ * NOT skip string literals or comments — inner-CTE names are unlikely
210
+ * to appear as quoted text or column aliases in practice.
211
211
  */
212
- private deconflictInnerCTEs;
212
+ private deconflictInnerCTEsViaSymbolTable;
213
213
  /**
214
214
  * Replaces every reference to `oldName` (bare, [bracketed], or "quoted")
215
215
  * with bare `newName`. Case-insensitive. Word-boundary matched so
216
216
  * `MyAcronymBridge` is not affected by renaming `AcronymBridge`.
217
217
  *
218
218
  * Does not attempt to skip string literals or comments — see the note on
219
- * `deconflictInnerCTEs` for the trade-off rationale.
219
+ * `deconflictInnerCTEsViaSymbolTable` for the trade-off rationale.
220
220
  */
221
221
  private renameSQLIdentifier;
222
222
  /**
@@ -227,7 +227,7 @@ export declare class QueryCompositionEngine {
227
227
  * AST parsing fails (e.g. SQL contains Nunjucks template tokens).
228
228
  *
229
229
  * @param sql SQL starting with a WITH clause
230
- * @param platform Database platform, used to select the AST dialect
230
+ * @param dialect SQL dialect for AST parsing
231
231
  */
232
232
  private hoistInnerCTEs;
233
233
  /**
@@ -236,85 +236,20 @@ export declare class QueryCompositionEngine {
236
236
  * SQL Server disallows ORDER BY inside CTEs unless TOP, OFFSET, or FOR XML is present.
237
237
  * PostgreSQL allows ORDER BY in CTEs, so no stripping is needed there.
238
238
  *
239
- * Uses a 4-tier strategy:
240
- * 1. Fast exit — no ORDER keyword at all, or dialect allows ORDER BY in CTEs
241
- * 2. AST path — parse (with Nunjucks preprocessing if needed), check if ORDER BY is legal
242
- * (TOP/OFFSET/FOR XML via AST nodes), null out orderby if not, regenerate.
243
- * Handles window functions, UNION/EXCEPT, subqueries, string literals, and Nunjucks templates.
244
- * 3. Regex fallback — paren-depth heuristic for SQL the parser still can't handle
245
- * (e.g. STRING_AGG WITHIN GROUP)
246
- * 4. OFFSET 0 ROWS injection — last resort when both AST and regex fail to strip ORDER BY.
247
- * Injects OFFSET 0 ROWS after the ORDER BY clause to make it legal in CTEs.
248
- * This is semantically neutral (returns all rows starting from 0) but switches
249
- * SQL Server into paging mode internally, which may affect query plan shape.
250
- */
251
- private stripTrailingOrderBy;
252
- /**
253
- * Attempts to strip the top-level ORDER BY clause using AST parsing.
254
- * Tries direct parsing first, then MJPlaceholder-preprocessed parsing if the SQL
255
- * contains MJ template syntax. Handles UNION/EXCEPT by walking the _next chain.
256
- */
257
- private stripOrderByViaAST;
258
- /**
259
- * Core AST stripping: parse, analyze, and regenerate SQL without ORDER BY.
260
- */
261
- private tryASTStrip;
262
- /**
263
- * Walks the _next chain (UNION/EXCEPT/INTERSECT) to find the statement
264
- * that carries the ORDER BY clause.
265
- */
266
- private findOrderByStatement;
267
- /**
268
- * Nunjucks-aware ORDER BY stripping: preprocess templates into placeholder SQL,
269
- * parse with AST to confirm top-level ORDER BY exists, then use the position-aware
270
- * scanner on the original SQL to strip only the last top-level ORDER BY.
271
- */
272
- private tryNunjucksAwareStrip;
273
- /**
274
- * Checks AST properties to determine if ORDER BY is legal in a CTE context.
275
- */
276
- private isOrderByLegalInCTE;
277
- /**
278
- * Strips the last top-level ORDER BY clause using position-aware scanning.
279
- * Skips strings, comments, Nunjucks tags, and tracks paren depth.
280
- */
281
- private stripLastTopLevelOrderBy;
282
- /**
283
- * Finds character positions of all ORDER BY keywords at the outermost level
284
- * (paren depth 0, not inside strings, comments, or MJ template tokens).
239
+ * Delegates to the shared `AnalyzeTopLevelOrderBy` utility (orderByAnalyzer.ts)
240
+ * which implements a 2-tier strategy:
241
+ * Tier 1: AST parsing (with Nunjucks preprocessing if needed)
242
+ * Tier 2: MJLexer scanner with carried lexical state across token boundaries
285
243
  *
286
- * Uses MJLexer to skip MJ tokens ({{ }}, {% %}, {# #}), then scans only
287
- * SQL_TEXT segments for ORDER BY keywords while tracking paren depth and
288
- * respecting SQL string literals and comments.
244
+ * When both tiers fail to strip, falls back to OFFSET 0 ROWS injection as
245
+ * a last resort (semantically neutral but makes ORDER BY legal in CTEs).
289
246
  */
290
- private findTopLevelOrderByPositions;
291
- /**
292
- * Preprocesses Nunjucks templates into valid SQL for AST parsing.
293
- * Uses MJPlaceholderSubstitution for context-aware placeholder generation.
294
- */
295
- private preprocessNunjucks;
247
+ private stripTrailingOrderBy;
296
248
  /**
297
249
  * Injects OFFSET 0 ROWS after the last top-level ORDER BY clause to make it
298
- * legal in a CTE without changing the result set. Uses the position-aware scanner
299
- * to find the correct insertion point after the ORDER BY columns.
250
+ * legal in a CTE without changing the result set.
300
251
  */
301
252
  private injectOffset0Rows;
302
- /**
303
- * Position-aware fallback for stripping the last top-level ORDER BY clause.
304
- * Delegates to `stripLastTopLevelOrderBy`, which uses MJLexer to skip MJ
305
- * template tokens, then scans only SQL_TEXT segments while respecting paren
306
- * depth, single-quoted string literals, line comments (--), and block
307
- * comments (/* … *​/).
308
- *
309
- * The previous regex-only implementation matched any literal "ORDER BY" in
310
- * the SQL — including text inside leading block comments like
311
- * `/* No ORDER BY / TOP — composable. *​/` — and truncated the dep body
312
- * mid-comment, producing illegal SQL ("Incorrect syntax near '('").
313
- * Skip-Brain hit this against multiple AGRiP composition deps. See
314
- * `__tests__/skip-failure-regressions.test.ts` and
315
- * `SKIP-QUERY-RENDERING-BUGS.md` (Bug A) at the repo root.
316
- */
317
- private stripOrderByViaRegex;
318
253
  /**
319
254
  * Strips SQL comments from the input string so that composition tokens
320
255
  * inside comments are not treated as real references.
@@ -322,16 +257,6 @@ export declare class QueryCompositionEngine {
322
257
  * Preserves string literals (single-quoted) to avoid stripping inside them.
323
258
  */
324
259
  private stripSQLComments;
325
- /**
326
- * Escapes {{ and }} inside SQL comments so that Nunjucks doesn't try to parse them.
327
- * This is needed because dependency queries may carry comments containing
328
- * {{query:"..."}} examples or documentation that would otherwise cause
329
- * Nunjucks "expected variable end" errors.
330
- *
331
- * Only modifies content inside -- single-line and block comments.
332
- * Leaves string literals and normal SQL untouched.
333
- */
334
- escapeTemplateTokensInComments(sql: string): string;
335
260
  }
336
261
  export {};
337
262
  //# sourceMappingURL=queryCompositionEngine.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"queryCompositionEngine.d.ts","sourceRoot":"","sources":["../src/queryCompositionEngine.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"queryCompositionEngine.d.ts","sourceRoot":"","sources":["../src/queryCompositionEngine.ts"],"names":[],"mappings":"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"}