@memberjunction/generic-database-provider 5.22.0 → 5.23.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.
@@ -13,20 +13,25 @@ export interface PagingWrappedSQL {
13
13
  PageSize: number;
14
14
  }
15
15
  /**
16
- * Handles server-side pagination for query SQL by wrapping resolved SQL in CTEs
17
- * and applying platform-specific OFFSET/FETCH or LIMIT/OFFSET clauses.
16
+ * Handles server-side pagination for query SQL by applying platform-specific
17
+ * paging clauses.
18
18
  *
19
- * Uses a two-tier strategy:
20
- * 1. **AST path** — parse SQL via node-sql-parser, extract ORDER BY and TOP from
21
- * the AST, reconstruct clean SQL via sqlify. Handles CTEs, subqueries, UNION,
22
- * and complex expressions correctly without string heuristics.
23
- * 2. **Regex fallback** — for SQL that node-sql-parser cannot handle (e.g.,
24
- * STRING_AGG WITHIN GROUP, certain FOR XML patterns), falls back to the
25
- * original string-based approach with paren-depth tracking.
19
+ * **Data SQL** — appends OFFSET/FETCH (SQL Server) or LIMIT/OFFSET (PostgreSQL)
20
+ * directly to the original SQL. The query is not wrapped in a CTE, so all column
21
+ * scopes, ORDER BY references, and table aliases remain valid. TOP is stripped on
22
+ * SQL Server since it conflicts with OFFSET.
23
+ *
24
+ * **Count SQL** — wraps the original SQL (minus ORDER BY) in a CTE and produces
25
+ * `SELECT COUNT(*) AS TotalRowCount FROM [__count]`. ORDER BY is irrelevant for
26
+ * counting and must be removed since SQL Server forbids it in CTEs without TOP.
27
+ *
28
+ * This approach eliminates the need for ORDER BY remapping (mapping column
29
+ * references from the inner query scope to the outer CTE scope), which was the
30
+ * primary source of paging bugs.
26
31
  */
27
32
  export declare class QueryPagingEngine {
28
33
  /**
29
- * Wraps resolved SQL with CTE-based paging for server-side pagination.
34
+ * Produces paged DataSQL and CountSQL from resolved query SQL.
30
35
  *
31
36
  * @param resolvedSQL The fully-resolved SQL (after composition + Nunjucks)
32
37
  * @param startRow 0-based row offset
@@ -39,49 +44,78 @@ export declare class QueryPagingEngine {
39
44
  * Determines whether the given params indicate paging should be applied.
40
45
  */
41
46
  static ShouldPage(startRow: number | undefined, maxRows: number | undefined): boolean;
42
- private static wrapViaAST;
43
47
  /**
44
- * Remaps ORDER BY terms to projected column names using AST comparison.
48
+ * Builds the paged data SQL by appending OFFSET/FETCH or LIMIT/OFFSET
49
+ * directly to the original SQL.
45
50
  *
46
- * For each ORDER BY expression, checks the SELECT column list for a match:
47
- * 1. If the SELECT column has an AS alias, use the alias
48
- * 2. If the SELECT column is a bare column_ref, use the column name
49
- * 3. If the ORDER BY is a simple column_ref, strip the table qualifier
51
+ * - Strips TOP on SQL Server (TOP and OFFSET are mutually exclusive)
52
+ * - Ensures ORDER BY exists (SQL Server requires it for OFFSET/FETCH;
53
+ * PostgreSQL requires it for deterministic LIMIT/OFFSET)
54
+ * - Appends the platform-specific paging clause
55
+ */
56
+ private static buildDataSQL;
57
+ /**
58
+ * Strips a TOP clause from the outermost SELECT statement.
59
+ * Handles `TOP N` and `TOP (N)`, with or without DISTINCT.
60
+ * Does not affect TOP in subqueries or CTEs.
61
+ */
62
+ private static stripTopFromMainSelect;
63
+ /**
64
+ * Builds the count SQL by wrapping the original query (minus ORDER BY)
65
+ * in a CTE and selecting COUNT(*).
50
66
  *
51
- * This is more robust than string-based remapping because it works directly
52
- * with the parsed AST structure — no regex needed for quoting or prefix stripping.
67
+ * Uses a two-tier approach:
68
+ * 1. **AST path** — parse SQL, strip ORDER BY via AST, reconstruct
69
+ * 2. **Regex fallback** — use SQLParser.ExtractCTEs + regex ORDER BY removal
53
70
  */
54
- private static remapOrderByViaAST;
71
+ private static buildCountSQL;
55
72
  /**
56
- * Resolves an ORDER BY expression to its projected column name by matching
57
- * against the SELECT column list at the AST level.
73
+ * AST-based count SQL: parse entire SQL, extract CTEs, strip ORDER BY and
74
+ * TOP from the main SELECT, then assemble all CTEs + __count as siblings
75
+ * in a flat WITH chain.
58
76
  */
59
- private static resolveOrderByExpr;
77
+ private static buildCountSQLViaAST;
60
78
  /**
61
- * Compares two AST expression nodes for structural equality.
62
- * Handles column_ref (with table qualifier matching), aggregates, and functions.
79
+ * Extracts CTE definitions from an AST statement, producing quoted
80
+ * `[name] AS (...)` strings for each CTE.
63
81
  */
64
- private static astExprsMatch;
65
82
  private static extractCTEsFromAST;
83
+ /**
84
+ * Regex-based count SQL: use SQLParser.ExtractCTEs for robust CTE splitting,
85
+ * then regex to strip ORDER BY from the main SELECT, wrap in count CTE.
86
+ */
87
+ private static buildCountSQLViaRegex;
88
+ /**
89
+ * Wraps cleaned SQL (no ORDER BY) in a CTE for counting.
90
+ */
91
+ private static assembleCountSQL;
66
92
  private static findOrderByStatement;
67
- private static wrapViaRegex;
68
- static splitCTEAndSelect(sql: string): {
69
- ctePrefix: string;
70
- mainSelect: string;
71
- };
93
+ /**
94
+ * Checks if the SQL has a top-level ORDER BY clause (not inside subqueries/CTEs).
95
+ */
96
+ private static hasTopLevelOrderBy;
97
+ /**
98
+ * Extracts the top-level ORDER BY clause from SQL, ignoring ORDER BY
99
+ * inside subqueries (tracked via paren depth).
100
+ */
72
101
  static extractOrderBy(sql: string): {
73
102
  sqlWithoutOrder: string;
74
103
  orderByClause: string | null;
75
104
  };
105
+ /**
106
+ * Strips a TOP N or TOP (N) clause from the beginning of a SELECT statement.
107
+ */
76
108
  static stripTopClause(sql: string): {
77
109
  sql: string;
78
110
  topRemoved: boolean;
79
111
  };
112
+ /**
113
+ * ExtractCTEs returns CTE definitions with unquoted names (e.g. `myName AS (...)`).
114
+ * We need to apply platform-specific identifier quoting to the CTE name.
115
+ */
116
+ private static quoteCteName;
80
117
  private static quoteIdentifier;
81
118
  private static buildPagingClause;
82
- static remapOrderByToProjectedNames(orderByClause: string, selectSQL: string): string;
83
- private static buildSelectAliasMap;
84
- private static splitAtTopLevelCommas;
85
119
  private static defaultOrderBy;
86
120
  }
87
121
  //# sourceMappingURL=queryPagingEngine.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"queryPagingEngine.d.ts","sourceRoot":"","sources":["../src/queryPagingEngine.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAGxD;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC7B,2CAA2C;IAC3C,OAAO,EAAE,MAAM,CAAC;IAChB,4DAA4D;IAC5D,QAAQ,EAAE,MAAM,CAAC;IACjB,mDAAmD;IACnD,MAAM,EAAE,MAAM,CAAC;IACf,4CAA4C;IAC5C,QAAQ,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;;;;;;GAWG;AACH,qBAAa,iBAAiB;IAE1B;;;;;;;;OAQG;IACH,MAAM,CAAC,cAAc,CACjB,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,gBAAgB,GAC3B,gBAAgB;IAYnB;;OAEG;IACH,MAAM,CAAC,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,EAAE,OAAO,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO;IAQrF,OAAO,CAAC,MAAM,CAAC,UAAU;IAuDzB;;;;;;;;;;OAUG;IACH,OAAO,CAAC,MAAM,CAAC,kBAAkB;IA6BjC;;;OAGG;IACH,OAAO,CAAC,MAAM,CAAC,kBAAkB;IA2BjC;;;OAGG;IACH,OAAO,CAAC,MAAM,CAAC,aAAa;IA2B5B,OAAO,CAAC,MAAM,CAAC,kBAAkB;IAcjC,OAAO,CAAC,MAAM,CAAC,oBAAoB;IAUnC,OAAO,CAAC,MAAM,CAAC,YAAY;IA8B3B,MAAM,CAAC,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE;IAgDhF,MAAM,CAAC,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG;QAAE,eAAe,EAAE,MAAM,CAAC;QAAC,aAAa,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE;IA4B7F,MAAM,CAAC,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,OAAO,CAAA;KAAE;IAWxE,OAAO,CAAC,MAAM,CAAC,eAAe;IAI9B,OAAO,CAAC,MAAM,CAAC,iBAAiB;IAMhC,MAAM,CAAC,4BAA4B,CAAC,aAAa,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM;IAoCrF,OAAO,CAAC,MAAM,CAAC,mBAAmB;IAsClC,OAAO,CAAC,MAAM,CAAC,qBAAqB;IAcpC,OAAO,CAAC,MAAM,CAAC,cAAc;CAGhC"}
1
+ {"version":3,"file":"queryPagingEngine.d.ts","sourceRoot":"","sources":["../src/queryPagingEngine.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAGxD;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC7B,2CAA2C;IAC3C,OAAO,EAAE,MAAM,CAAC;IAChB,4DAA4D;IAC5D,QAAQ,EAAE,MAAM,CAAC;IACjB,mDAAmD;IACnD,MAAM,EAAE,MAAM,CAAC;IACf,4CAA4C;IAC5C,QAAQ,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,qBAAa,iBAAiB;IAE1B;;;;;;;;OAQG;IACH,MAAM,CAAC,cAAc,CACjB,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,gBAAgB,GAC3B,gBAAgB;IAUnB;;OAEG;IACH,MAAM,CAAC,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,EAAE,OAAO,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO;IAQrF;;;;;;;;OAQG;IACH,OAAO,CAAC,MAAM,CAAC,YAAY;IA0B3B;;;;OAIG;IACH,OAAO,CAAC,MAAM,CAAC,sBAAsB;IA0BrC;;;;;;;OAOG;IACH,OAAO,CAAC,MAAM,CAAC,aAAa;IAS5B;;;;OAIG;IACH,OAAO,CAAC,MAAM,CAAC,mBAAmB;IAoClC;;;OAGG;IACH,OAAO,CAAC,MAAM,CAAC,kBAAkB;IAcjC;;;OAGG;IACH,OAAO,CAAC,MAAM,CAAC,qBAAqB;IAoBpC;;OAEG;IACH,OAAO,CAAC,MAAM,CAAC,gBAAgB;IAS/B,OAAO,CAAC,MAAM,CAAC,oBAAoB;IAUnC;;OAEG;IACH,OAAO,CAAC,MAAM,CAAC,kBAAkB;IAIjC;;;OAGG;IACH,MAAM,CAAC,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG;QAAE,eAAe,EAAE,MAAM,CAAC;QAAC,aAAa,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE;IA4B7F;;OAEG;IACH,MAAM,CAAC,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,OAAO,CAAA;KAAE;IAOxE;;;OAGG;IACH,OAAO,CAAC,MAAM,CAAC,YAAY;IAe3B,OAAO,CAAC,MAAM,CAAC,eAAe;IAI9B,OAAO,CAAC,MAAM,CAAC,iBAAiB;IAMhC,OAAO,CAAC,MAAM,CAAC,cAAc;CAGhC"}
@@ -1,19 +1,24 @@
1
1
  import { SQLParser } from '@memberjunction/sql-parser';
2
2
  /**
3
- * Handles server-side pagination for query SQL by wrapping resolved SQL in CTEs
4
- * and applying platform-specific OFFSET/FETCH or LIMIT/OFFSET clauses.
3
+ * Handles server-side pagination for query SQL by applying platform-specific
4
+ * paging clauses.
5
5
  *
6
- * Uses a two-tier strategy:
7
- * 1. **AST path** — parse SQL via node-sql-parser, extract ORDER BY and TOP from
8
- * the AST, reconstruct clean SQL via sqlify. Handles CTEs, subqueries, UNION,
9
- * and complex expressions correctly without string heuristics.
10
- * 2. **Regex fallback** — for SQL that node-sql-parser cannot handle (e.g.,
11
- * STRING_AGG WITHIN GROUP, certain FOR XML patterns), falls back to the
12
- * original string-based approach with paren-depth tracking.
6
+ * **Data SQL** — appends OFFSET/FETCH (SQL Server) or LIMIT/OFFSET (PostgreSQL)
7
+ * directly to the original SQL. The query is not wrapped in a CTE, so all column
8
+ * scopes, ORDER BY references, and table aliases remain valid. TOP is stripped on
9
+ * SQL Server since it conflicts with OFFSET.
10
+ *
11
+ * **Count SQL** — wraps the original SQL (minus ORDER BY) in a CTE and produces
12
+ * `SELECT COUNT(*) AS TotalRowCount FROM [__count]`. ORDER BY is irrelevant for
13
+ * counting and must be removed since SQL Server forbids it in CTEs without TOP.
14
+ *
15
+ * This approach eliminates the need for ORDER BY remapping (mapping column
16
+ * references from the inner query scope to the outer CTE scope), which was the
17
+ * primary source of paging bugs.
13
18
  */
14
19
  export class QueryPagingEngine {
15
20
  /**
16
- * Wraps resolved SQL with CTE-based paging for server-side pagination.
21
+ * Produces paged DataSQL and CountSQL from resolved query SQL.
17
22
  *
18
23
  * @param resolvedSQL The fully-resolved SQL (after composition + Nunjucks)
19
24
  * @param startRow 0-based row offset
@@ -22,14 +27,11 @@ export class QueryPagingEngine {
22
27
  * @returns DataSQL for paged results and CountSQL for total row count
23
28
  */
24
29
  static WrapWithPaging(resolvedSQL, startRow, maxRows, platform) {
25
- // Strip trailing semicolons — they break CTE wrapping and OFFSET/FETCH clauses
30
+ // Strip trailing semicolons — they break OFFSET/FETCH and CTE wrapping
26
31
  const cleanedSQL = resolvedSQL.trimEnd().replace(/;\s*$/, '');
27
- // Tier 1: AST-based paging (robust, handles CTEs/subqueries/UNION correctly)
28
- const astResult = QueryPagingEngine.wrapViaAST(cleanedSQL, startRow, maxRows, platform);
29
- if (astResult)
30
- return astResult;
31
- // Tier 2: Regex-based fallback for SQL the parser can't handle
32
- return QueryPagingEngine.wrapViaRegex(cleanedSQL, startRow, maxRows, platform);
32
+ const dataSQL = QueryPagingEngine.buildDataSQL(cleanedSQL, startRow, maxRows, platform);
33
+ const countSQL = QueryPagingEngine.buildCountSQL(cleanedSQL, platform);
34
+ return { DataSQL: dataSQL, CountSQL: countSQL, Offset: startRow, PageSize: maxRows };
33
35
  }
34
36
  /**
35
37
  * Determines whether the given params indicate paging should be applied.
@@ -38,9 +40,83 @@ export class QueryPagingEngine {
38
40
  return maxRows != null && maxRows > 0 && startRow != null && startRow >= 0;
39
41
  }
40
42
  // ════════════════════════════════════════════════════════════════════
41
- // AST-based paging (primary path)
43
+ // Data SQL — append paging clause directly to original SQL
44
+ // ════════════════════════════════════════════════════════════════════
45
+ /**
46
+ * Builds the paged data SQL by appending OFFSET/FETCH or LIMIT/OFFSET
47
+ * directly to the original SQL.
48
+ *
49
+ * - Strips TOP on SQL Server (TOP and OFFSET are mutually exclusive)
50
+ * - Ensures ORDER BY exists (SQL Server requires it for OFFSET/FETCH;
51
+ * PostgreSQL requires it for deterministic LIMIT/OFFSET)
52
+ * - Appends the platform-specific paging clause
53
+ */
54
+ static buildDataSQL(sql, startRow, maxRows, platform) {
55
+ let dataSQL = sql;
56
+ // Strip TOP clause on SQL Server — it conflicts with OFFSET/FETCH.
57
+ // Must operate on the main SELECT, not on subqueries or CTEs.
58
+ if (platform === 'sqlserver') {
59
+ dataSQL = QueryPagingEngine.stripTopFromMainSelect(dataSQL);
60
+ }
61
+ // Ensure there's an ORDER BY — required for OFFSET/FETCH on SQL Server,
62
+ // and strongly recommended for deterministic LIMIT/OFFSET on PostgreSQL.
63
+ if (!QueryPagingEngine.hasTopLevelOrderBy(dataSQL)) {
64
+ const defaultOrder = QueryPagingEngine.defaultOrderBy(platform);
65
+ dataSQL = `${dataSQL}\nORDER BY ${defaultOrder}`;
66
+ }
67
+ // Append paging clause
68
+ const pagingClause = QueryPagingEngine.buildPagingClause(startRow, maxRows, platform);
69
+ return `${dataSQL}\n${pagingClause}`;
70
+ }
71
+ /**
72
+ * Strips a TOP clause from the outermost SELECT statement.
73
+ * Handles `TOP N` and `TOP (N)`, with or without DISTINCT.
74
+ * Does not affect TOP in subqueries or CTEs.
75
+ */
76
+ static stripTopFromMainSelect(sql) {
77
+ // Find the main SELECT — it's either the first token, or follows the
78
+ // last CTE closing paren. Use ExtractCTEs to find the main statement.
79
+ const parserDialect = 'TransactSQL';
80
+ const extraction = SQLParser.ExtractCTEs(sql, parserDialect);
81
+ if (extraction) {
82
+ // SQL has CTEs — strip TOP only from the main statement
83
+ const { sql: cleanMain, topRemoved } = QueryPagingEngine.stripTopClause(extraction.MainStatement);
84
+ if (topRemoved) {
85
+ // Reassemble: WITH ... <CTEs> ... <cleanMain>
86
+ const ctePrefix = sql.substring(0, sql.length - extraction.MainStatement.length).trimEnd();
87
+ return `${ctePrefix}\n${cleanMain}`;
88
+ }
89
+ return sql;
90
+ }
91
+ // No CTEs — strip TOP from the SQL directly
92
+ const { sql: cleanSQL } = QueryPagingEngine.stripTopClause(sql);
93
+ return cleanSQL;
94
+ }
95
+ // ════════════════════════════════════════════════════════════════════
96
+ // Count SQL — wrap in CTE, strip ORDER BY, SELECT COUNT(*)
42
97
  // ════════════════════════════════════════════════════════════════════
43
- static wrapViaAST(sql, startRow, maxRows, platform) {
98
+ /**
99
+ * Builds the count SQL by wrapping the original query (minus ORDER BY)
100
+ * in a CTE and selecting COUNT(*).
101
+ *
102
+ * Uses a two-tier approach:
103
+ * 1. **AST path** — parse SQL, strip ORDER BY via AST, reconstruct
104
+ * 2. **Regex fallback** — use SQLParser.ExtractCTEs + regex ORDER BY removal
105
+ */
106
+ static buildCountSQL(sql, platform) {
107
+ // Tier 1: Try full AST — cleanest approach
108
+ const astResult = QueryPagingEngine.buildCountSQLViaAST(sql, platform);
109
+ if (astResult)
110
+ return astResult;
111
+ // Tier 2: Hybrid — SQLParser.ExtractCTEs + regex ORDER BY stripping
112
+ return QueryPagingEngine.buildCountSQLViaRegex(sql, platform);
113
+ }
114
+ /**
115
+ * AST-based count SQL: parse entire SQL, extract CTEs, strip ORDER BY and
116
+ * TOP from the main SELECT, then assemble all CTEs + __count as siblings
117
+ * in a flat WITH chain.
118
+ */
119
+ static buildCountSQLViaAST(sql, platform) {
44
120
  const parserDialect = platform === 'postgresql' ? 'PostgresQL' : 'TransactSQL';
45
121
  try {
46
122
  const ast = SQLParser.ParseSQL(sql, parserDialect);
@@ -49,126 +125,32 @@ export class QueryPagingEngine {
49
125
  const stmt = (Array.isArray(ast) ? ast[0] : ast);
50
126
  if (!stmt)
51
127
  return null;
52
- // Extract CTEs via AST
53
- const cteDefs = QueryPagingEngine.extractCTEsFromAST(stmt, parserDialect, platform);
54
- // Extract ORDER BY and remap to projected column names via AST.
55
- // The outer query is SELECT * FROM [__paged], so table aliases from the
56
- // inner query don't exist. We match ORDER BY expressions against SELECT
57
- // columns to find the projected name (AS alias or bare column name).
128
+ // Extract existing CTEs as sibling definitions
129
+ const existingCTEDefs = QueryPagingEngine.extractCTEsFromAST(stmt, parserDialect, platform);
130
+ // Strip ORDER BY (not needed for counting, illegal in CTEs without TOP)
58
131
  const orderByStmt = QueryPagingEngine.findOrderByStatement(stmt);
59
- const selectColumns = (stmt.columns && Array.isArray(stmt.columns))
60
- ? stmt.columns
61
- : [];
62
- const remappedOrderBy = QueryPagingEngine.remapOrderByViaAST(orderByStmt, selectColumns, parserDialect);
63
132
  if (orderByStmt?.orderby) {
64
133
  orderByStmt.orderby = null;
65
134
  }
66
- // Strip TOP
135
+ // Strip TOP — we want the full count
67
136
  if (stmt.top)
68
137
  stmt.top = null;
69
- // Get main SELECT without CTEs or ORDER BY
138
+ // Reconstruct only the main SELECT (without CTEs)
70
139
  stmt.with = null;
71
140
  const mainSelectSQL = SQLParser.SqlifyAST(stmt, parserDialect);
72
- // Assemble paged query (skip string-based remapping — already done via AST)
73
- const pagingCTEName = QueryPagingEngine.quoteIdentifier('__paged', platform);
74
- const allCTEs = [...cteDefs, `${pagingCTEName} AS (\n${mainSelectSQL}\n)`];
75
- const cteChain = `WITH ${allCTEs.join(',\n')}`;
76
- const outerOrderBy = remappedOrderBy || QueryPagingEngine.defaultOrderBy(platform);
77
- const pagingClause = QueryPagingEngine.buildPagingClause(startRow, maxRows, platform);
78
- const dataSQL = `${cteChain}\nSELECT * FROM ${pagingCTEName}\nORDER BY ${outerOrderBy}\n${pagingClause}`;
79
- const countSQL = `${cteChain}\nSELECT COUNT(*) AS TotalRowCount FROM ${pagingCTEName}`;
80
- return { DataSQL: dataSQL, CountSQL: countSQL, Offset: startRow, PageSize: maxRows };
141
+ // Assemble: all existing CTEs + __count as siblings in a single WITH
142
+ const countCTEName = QueryPagingEngine.quoteIdentifier('__count', platform);
143
+ const allCTEs = [...existingCTEDefs, `${countCTEName} AS (\n${mainSelectSQL}\n)`];
144
+ return `WITH ${allCTEs.join(',\n')}\nSELECT COUNT(*) AS TotalRowCount FROM ${countCTEName}`;
81
145
  }
82
146
  catch {
83
147
  return null;
84
148
  }
85
149
  }
86
150
  /**
87
- * Remaps ORDER BY terms to projected column names using AST comparison.
88
- *
89
- * For each ORDER BY expression, checks the SELECT column list for a match:
90
- * 1. If the SELECT column has an AS alias, use the alias
91
- * 2. If the SELECT column is a bare column_ref, use the column name
92
- * 3. If the ORDER BY is a simple column_ref, strip the table qualifier
93
- *
94
- * This is more robust than string-based remapping because it works directly
95
- * with the parsed AST structure — no regex needed for quoting or prefix stripping.
96
- */
97
- static remapOrderByViaAST(orderByStmt, selectColumns, parserDialect) {
98
- if (!orderByStmt?.orderby || !Array.isArray(orderByStmt.orderby))
99
- return null;
100
- const orderByTerms = orderByStmt.orderby;
101
- const remappedTerms = orderByTerms.map(orderTerm => {
102
- const direction = orderTerm.type === 'DESC' ? ' DESC' : '';
103
- const projectedName = QueryPagingEngine.resolveOrderByExpr(orderTerm.expr, selectColumns);
104
- if (projectedName) {
105
- return projectedName + direction;
106
- }
107
- // Fallback: if it's a simple column_ref, strip the table qualifier
108
- if (orderTerm.expr.type === 'column_ref') {
109
- return orderTerm.expr.column + direction;
110
- }
111
- // Last resort: convert via ExprToSQL (will have correct quoting at least)
112
- return SQLParser.ExprToSQL(orderTerm.expr, parserDialect) + direction;
113
- });
114
- return remappedTerms.join(', ');
115
- }
116
- /**
117
- * Resolves an ORDER BY expression to its projected column name by matching
118
- * against the SELECT column list at the AST level.
119
- */
120
- static resolveOrderByExpr(orderExpr, selectColumns) {
121
- for (const col of selectColumns) {
122
- if (!col.expr)
123
- continue;
124
- // Check if the ORDER BY expression matches this SELECT column's expression
125
- if (QueryPagingEngine.astExprsMatch(orderExpr, col.expr)) {
126
- // If the column has an AS alias, use it
127
- if (col.as)
128
- return col.as;
129
- // If it's a bare column_ref, use the column name
130
- if (col.expr.type === 'column_ref')
131
- return col.expr.column;
132
- }
133
- // Also check: ORDER BY references a column by name that matches an AS alias
134
- if (orderExpr.type === 'column_ref' && col.as) {
135
- const orderCol = orderExpr.column;
136
- if (orderCol.toLowerCase() === col.as.toLowerCase()) {
137
- return col.as;
138
- }
139
- }
140
- }
141
- return null;
142
- }
143
- /**
144
- * Compares two AST expression nodes for structural equality.
145
- * Handles column_ref (with table qualifier matching), aggregates, and functions.
151
+ * Extracts CTE definitions from an AST statement, producing quoted
152
+ * `[name] AS (...)` strings for each CTE.
146
153
  */
147
- static astExprsMatch(a, b) {
148
- if (!a || !b)
149
- return false;
150
- if (a.type !== b.type)
151
- return false;
152
- // column_ref: match by column name (ignore table qualifier — the whole point
153
- // of remapping is that table qualifiers don't exist in the outer query)
154
- if (a.type === 'column_ref') {
155
- return a.column?.toLowerCase() === b.column?.toLowerCase() &&
156
- a.table?.toLowerCase() === b.table?.toLowerCase();
157
- }
158
- // For aggregate functions (COUNT, SUM, etc.), compare name and args
159
- if (a.type === 'aggr_func') {
160
- if (a.name !== b.name)
161
- return false;
162
- return JSON.stringify(a.args) === JSON.stringify(b.args);
163
- }
164
- // For regular functions, compare name and args
165
- if (a.type === 'function') {
166
- return JSON.stringify(a.name) === JSON.stringify(b.name) &&
167
- JSON.stringify(a.args) === JSON.stringify(b.args);
168
- }
169
- // Generic fallback: JSON deep equality (works for simple expressions)
170
- return JSON.stringify(a) === JSON.stringify(b);
171
- }
172
154
  static extractCTEsFromAST(stmt, parserDialect, platform) {
173
155
  const ctes = stmt.with || [];
174
156
  return ctes.map(cte => {
@@ -178,6 +160,35 @@ export class QueryPagingEngine {
178
160
  return `${quotedName} AS (\n${bodySQL}\n)`;
179
161
  });
180
162
  }
163
+ /**
164
+ * Regex-based count SQL: use SQLParser.ExtractCTEs for robust CTE splitting,
165
+ * then regex to strip ORDER BY from the main SELECT, wrap in count CTE.
166
+ */
167
+ static buildCountSQLViaRegex(sql, platform) {
168
+ const parserDialect = platform === 'postgresql' ? 'PostgresQL' : 'TransactSQL';
169
+ const extraction = SQLParser.ExtractCTEs(sql, parserDialect);
170
+ if (extraction) {
171
+ // Strip ORDER BY from the main SELECT only
172
+ const { sqlWithoutOrder } = QueryPagingEngine.extractOrderBy(extraction.MainStatement);
173
+ const quotedCTEDefs = extraction.CTEDefinitions.map(def => QueryPagingEngine.quoteCteName(def, platform));
174
+ const countCTEName = QueryPagingEngine.quoteIdentifier('__count', platform);
175
+ const allCTEs = [...quotedCTEDefs, `${countCTEName} AS (\n${sqlWithoutOrder}\n)`];
176
+ return `WITH ${allCTEs.join(',\n')}\nSELECT COUNT(*) AS TotalRowCount FROM ${countCTEName}`;
177
+ }
178
+ // No CTEs — strip ORDER BY and wrap the whole SQL
179
+ const { sqlWithoutOrder } = QueryPagingEngine.extractOrderBy(sql);
180
+ return QueryPagingEngine.assembleCountSQL(sqlWithoutOrder, platform);
181
+ }
182
+ /**
183
+ * Wraps cleaned SQL (no ORDER BY) in a CTE for counting.
184
+ */
185
+ static assembleCountSQL(cleanSQL, platform) {
186
+ const countCTEName = QueryPagingEngine.quoteIdentifier('__count', platform);
187
+ return `WITH ${countCTEName} AS (\n${cleanSQL}\n)\nSELECT COUNT(*) AS TotalRowCount FROM ${countCTEName}`;
188
+ }
189
+ // ════════════════════════════════════════════════════════════════════
190
+ // AST helpers
191
+ // ════════════════════════════════════════════════════════════════════
181
192
  static findOrderByStatement(stmt) {
182
193
  if (stmt.orderby)
183
194
  return stmt;
@@ -186,76 +197,18 @@ export class QueryPagingEngine {
186
197
  return null;
187
198
  }
188
199
  // ════════════════════════════════════════════════════════════════════
189
- // Regex-based paging (fallback)
190
- // ════════════════════════════════════════════════════════════════════
191
- static wrapViaRegex(sql, startRow, maxRows, platform) {
192
- const { ctePrefix, mainSelect } = QueryPagingEngine.splitCTEAndSelect(sql);
193
- const { sqlWithoutOrder, orderByClause } = QueryPagingEngine.extractOrderBy(mainSelect);
194
- const { sql: cleanSelect } = QueryPagingEngine.stripTopClause(sqlWithoutOrder);
195
- const pagingCTEName = QueryPagingEngine.quoteIdentifier('__paged', platform);
196
- const existingCTEs = ctePrefix ? ctePrefix + ',\n' : 'WITH ';
197
- const cteChain = `${existingCTEs}${pagingCTEName} AS (\n${cleanSelect}\n)`;
198
- const rawOrderBy = orderByClause || QueryPagingEngine.defaultOrderBy(platform);
199
- const outerOrderBy = orderByClause
200
- ? QueryPagingEngine.remapOrderByToProjectedNames(rawOrderBy, cleanSelect)
201
- : rawOrderBy;
202
- const pagingClause = QueryPagingEngine.buildPagingClause(startRow, maxRows, platform);
203
- const dataSQL = `${cteChain}\nSELECT * FROM ${pagingCTEName}\nORDER BY ${outerOrderBy}\n${pagingClause}`;
204
- const countSQL = `${cteChain}\nSELECT COUNT(*) AS TotalRowCount FROM ${pagingCTEName}`;
205
- return { DataSQL: dataSQL, CountSQL: countSQL, Offset: startRow, PageSize: maxRows };
206
- }
207
- // ════════════════════════════════════════════════════════════════════
208
- // Regex helpers (used by fallback path)
200
+ // SQL analysis helpers
209
201
  // ════════════════════════════════════════════════════════════════════
210
- static splitCTEAndSelect(sql) {
211
- const trimmed = sql.trim();
212
- if (!/^WITH\s/i.test(trimmed)) {
213
- return { ctePrefix: '', mainSelect: trimmed };
214
- }
215
- let depth = 0;
216
- let lastCTEEnd = -1;
217
- let i = 0;
218
- const withMatch = trimmed.match(/^WITH\s+/i);
219
- if (!withMatch)
220
- return { ctePrefix: '', mainSelect: trimmed };
221
- i = withMatch[0].length;
222
- while (i < trimmed.length) {
223
- const ch = trimmed[i];
224
- if (ch === '(') {
225
- depth++;
226
- }
227
- else if (ch === ')') {
228
- depth--;
229
- if (depth === 0) {
230
- lastCTEEnd = i;
231
- const rest = trimmed.substring(i + 1).trimStart();
232
- if (rest.startsWith(',')) {
233
- i = trimmed.indexOf(',', i + 1) + 1;
234
- continue;
235
- }
236
- break;
237
- }
238
- }
239
- else if (ch === "'" && depth > 0) {
240
- i++;
241
- while (i < trimmed.length && trimmed[i] !== "'") {
242
- if (trimmed[i] === "'" && i + 1 < trimmed.length && trimmed[i + 1] === "'") {
243
- i += 2;
244
- }
245
- else {
246
- i++;
247
- }
248
- }
249
- }
250
- i++;
251
- }
252
- if (lastCTEEnd === -1)
253
- return { ctePrefix: '', mainSelect: trimmed };
254
- return {
255
- ctePrefix: trimmed.substring(0, lastCTEEnd + 1).trim(),
256
- mainSelect: trimmed.substring(lastCTEEnd + 1).trim(),
257
- };
202
+ /**
203
+ * Checks if the SQL has a top-level ORDER BY clause (not inside subqueries/CTEs).
204
+ */
205
+ static hasTopLevelOrderBy(sql) {
206
+ return QueryPagingEngine.extractOrderBy(sql).orderByClause !== null;
258
207
  }
208
+ /**
209
+ * Extracts the top-level ORDER BY clause from SQL, ignoring ORDER BY
210
+ * inside subqueries (tracked via paren depth).
211
+ */
259
212
  static extractOrderBy(sql) {
260
213
  const upperSQL = sql.toUpperCase();
261
214
  let depth = 0;
@@ -282,6 +235,9 @@ export class QueryPagingEngine {
282
235
  sqlWithoutOrder: sql.substring(0, lastOrderByPos).trim(),
283
236
  };
284
237
  }
238
+ /**
239
+ * Strips a TOP N or TOP (N) clause from the beginning of a SELECT statement.
240
+ */
285
241
  static stripTopClause(sql) {
286
242
  const topRegex = /^(SELECT\s+(?:DISTINCT\s+)?)TOP\s+(?:\(\s*\d+\s*\)|\d+)\s+/i;
287
243
  const match = sql.match(topRegex);
@@ -289,8 +245,22 @@ export class QueryPagingEngine {
289
245
  return { sql, topRemoved: false };
290
246
  return { sql: match[1] + sql.substring(match[0].length), topRemoved: true };
291
247
  }
248
+ /**
249
+ * ExtractCTEs returns CTE definitions with unquoted names (e.g. `myName AS (...)`).
250
+ * We need to apply platform-specific identifier quoting to the CTE name.
251
+ */
252
+ static quoteCteName(cteDefinition, platform) {
253
+ const match = cteDefinition.match(/^(\[([^\]]+)\]|"([^"]+)"|([A-Za-z_]\w*))\s+AS\s*\(/i);
254
+ if (!match)
255
+ return cteDefinition;
256
+ const bareName = match[2] ?? match[3] ?? match[4];
257
+ if (!bareName)
258
+ return cteDefinition;
259
+ const quotedName = QueryPagingEngine.quoteIdentifier(bareName, platform);
260
+ return quotedName + cteDefinition.substring(match[1].length);
261
+ }
292
262
  // ════════════════════════════════════════════════════════════════════
293
- // Shared helpers
263
+ // Platform helpers
294
264
  // ════════════════════════════════════════════════════════════════════
295
265
  static quoteIdentifier(name, platform) {
296
266
  return platform === 'postgresql' ? `"${name}"` : `[${name}]`;
@@ -300,98 +270,6 @@ export class QueryPagingEngine {
300
270
  ? `LIMIT ${maxRows} OFFSET ${startRow}`
301
271
  : `OFFSET ${startRow} ROWS FETCH NEXT ${maxRows} ROWS ONLY`;
302
272
  }
303
- static remapOrderByToProjectedNames(orderByClause, selectSQL) {
304
- const aliasMap = QueryPagingEngine.buildSelectAliasMap(selectSQL);
305
- const terms = QueryPagingEngine.splitAtTopLevelCommas(orderByClause);
306
- const remapped = terms.map(term => {
307
- const trimmed = term.trim();
308
- const dirMatch = trimmed.match(/\s+(ASC|DESC)(\s+NULLS\s+(FIRST|LAST))?\s*$/i);
309
- const expr = dirMatch ? trimmed.substring(0, dirMatch.index).trim() : trimmed;
310
- const direction = dirMatch ? dirMatch[0] : '';
311
- // Strip bracket/backtick/double-quote quoting for normalized matching.
312
- // The AST path produces [bracket]-quoted identifiers, while the alias map
313
- // may use either quoted or unquoted forms.
314
- const unquoted = expr.replace(/\[([^\]]+)\]/g, '$1').replace(/`([^`]+)`/g, '$1').replace(/"([^"]+)"/g, '$1');
315
- const normalizedExpr = unquoted.replace(/\s+/g, ' ').trim();
316
- // 1. Try exact match against SELECT expressions
317
- const exactMatch = aliasMap.get(normalizedExpr.toUpperCase());
318
- if (exactMatch)
319
- return exactMatch + direction;
320
- // 2. Strip table alias prefixes (handles both quoted and unquoted)
321
- const stripped = normalizedExpr.replace(/\b[a-zA-Z_]\w*\./g, '');
322
- const strippedMatch = aliasMap.get(stripped.toUpperCase());
323
- if (strippedMatch)
324
- return strippedMatch + direction;
325
- // 3. Simple table.column — return just the column name
326
- const dotMatch = normalizedExpr.match(/^[a-zA-Z_]\w*\.([a-zA-Z_]\w*)$/);
327
- if (dotMatch)
328
- return dotMatch[1] + direction;
329
- // 4. Fallback: return stripped expression
330
- return stripped + direction;
331
- });
332
- return remapped.join(', ');
333
- }
334
- static buildSelectAliasMap(selectSQL) {
335
- const map = new Map();
336
- const stripped = selectSQL.replace(/^(\s*(--[^\n]*\n|\/\*[\s\S]*?\*\/))*\s*/i, '');
337
- const selectMatch = stripped.match(/^SELECT\s+(?:DISTINCT\s+)?/i);
338
- if (!selectMatch)
339
- return map;
340
- const afterSelect = stripped.substring(selectMatch[0].length);
341
- const upperAfter = afterSelect.toUpperCase();
342
- let depth = 0;
343
- let fromPos = -1;
344
- for (let i = 0; i < afterSelect.length; i++) {
345
- const ch = afterSelect[i];
346
- if (ch === '(')
347
- depth++;
348
- else if (ch === ')')
349
- depth--;
350
- else if (depth === 0 && i + 5 <= afterSelect.length) {
351
- if (upperAfter.substring(i, i + 5) === 'FROM ' || upperAfter.substring(i, i + 5) === 'FROM\n' || upperAfter.substring(i, i + 5) === 'FROM\t') {
352
- if (i === 0 || /\s/.test(afterSelect[i - 1])) {
353
- fromPos = i;
354
- break;
355
- }
356
- }
357
- }
358
- }
359
- const columnList = fromPos === -1 ? afterSelect : afterSelect.substring(0, fromPos);
360
- for (const item of QueryPagingEngine.splitAtTopLevelCommas(columnList)) {
361
- const trimmedItem = item.trim();
362
- if (!trimmedItem)
363
- continue;
364
- const asMatch = trimmedItem.match(/\s+AS\s+(\[?\w+\]?)\s*$/i);
365
- if (asMatch) {
366
- const exprPart = trimmedItem.substring(0, asMatch.index).trim();
367
- const alias = asMatch[1].replace(/[[\]]/g, '');
368
- const normalizedExpr = exprPart.replace(/\s+/g, ' ').toUpperCase();
369
- map.set(normalizedExpr, alias);
370
- const strippedExpr = normalizedExpr.replace(/\b[A-Z_]\w*\./g, '');
371
- if (strippedExpr !== normalizedExpr)
372
- map.set(strippedExpr, alias);
373
- }
374
- }
375
- return map;
376
- }
377
- static splitAtTopLevelCommas(sql) {
378
- const parts = [];
379
- let depth = 0;
380
- let start = 0;
381
- for (let i = 0; i < sql.length; i++) {
382
- const ch = sql[i];
383
- if (ch === '(')
384
- depth++;
385
- else if (ch === ')')
386
- depth--;
387
- else if (ch === ',' && depth === 0) {
388
- parts.push(sql.substring(start, i));
389
- start = i + 1;
390
- }
391
- }
392
- parts.push(sql.substring(start));
393
- return parts;
394
- }
395
273
  static defaultOrderBy(platform) {
396
274
  return platform === 'postgresql' ? '1' : '(SELECT NULL)';
397
275
  }
@@ -1 +1 @@
1
- {"version":3,"file":"queryPagingEngine.js","sourceRoot":"","sources":["../src/queryPagingEngine.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"queryPagingEngine.js","sourceRoot":"","sources":["../src/queryPagingEngine.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@memberjunction/generic-database-provider",
3
3
  "type": "module",
4
- "version": "5.22.0",
4
+ "version": "5.23.0",
5
5
  "description": "Shared database provider logic for MemberJunction — intermediate base class between DatabaseProviderBase and platform-specific providers",
6
6
  "main": "dist/index.js",
7
7
  "types": "dist/index.d.ts",
@@ -22,17 +22,17 @@
22
22
  "vitest": "^3.1.1"
23
23
  },
24
24
  "dependencies": {
25
- "@memberjunction/actions": "5.22.0",
26
- "@memberjunction/actions-base": "5.22.0",
27
- "@memberjunction/aiengine": "5.22.0",
28
- "@memberjunction/core": "5.22.0",
29
- "@memberjunction/core-entities": "5.22.0",
30
- "@memberjunction/encryption": "5.22.0",
31
- "@memberjunction/global": "5.22.0",
32
- "@memberjunction/query-processor": "5.22.0",
33
- "@memberjunction/sql-dialect": "5.22.0",
34
- "@memberjunction/sql-parser": "5.22.0",
35
- "@memberjunction/queue": "5.22.0",
25
+ "@memberjunction/actions": "5.23.0",
26
+ "@memberjunction/actions-base": "5.23.0",
27
+ "@memberjunction/aiengine": "5.23.0",
28
+ "@memberjunction/core": "5.23.0",
29
+ "@memberjunction/core-entities": "5.23.0",
30
+ "@memberjunction/encryption": "5.23.0",
31
+ "@memberjunction/global": "5.23.0",
32
+ "@memberjunction/query-processor": "5.23.0",
33
+ "@memberjunction/sql-dialect": "5.23.0",
34
+ "@memberjunction/sql-parser": "5.23.0",
35
+ "@memberjunction/queue": "5.23.0",
36
36
  "sql-formatter": "^15.7.0",
37
37
  "uuid": "^13.0.0"
38
38
  },