@effectuate/cubejs-mongosql-driver 1.0.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.
@@ -0,0 +1,551 @@
1
+ "use strict";
2
+ /**
3
+ * MongoSqlQuery — Cube SQL dialect for MongoSQL.
4
+ *
5
+ * See SPEC.md FR-2 and ARCHITECTURE.md §4.1. Reference:
6
+ * https://www.mongodb.com/docs/sql-interface/language-reference/
7
+ *
8
+ * T12a scope: STATIC SYNTAX — identifier quoting, type names, timestamp
9
+ * casts, timezone passthrough, NULL/param tokens.
10
+ * T12b scope: DATE ARITHMETIC, INTERVALS, time-series generation,
11
+ * date-truncation, dateBin, unixTimestampSql.
12
+ *
13
+ * MongoSQL date-function audit (verified against mongosql v1.8.5 source —
14
+ * `mongosql/src/ast/definitions.rs` `FunctionName::try_from` and
15
+ * `algebrize_date_function`, plus `ast/rewrites/test.rs`):
16
+ *
17
+ * | Function | Signature | Notes |
18
+ * |----------------|--------------------------------------------------------|--------------------------------------------------------------------|
19
+ * | DATEADD | DATEADD(<date_part>, <numeric>, <date>) | TIMESTAMPADD is an alias. |
20
+ * | DATEDIFF | DATEDIFF(<date_part>, <start>, <end>[, <start_of_week>]) | Returns LONG. TIMESTAMPDIFF is an alias. |
21
+ * | DATETRUNC | DATETRUNC(<date_part>, <date>[, <start_of_week>]) | TIMESTAMPTRUNC is an alias. |
22
+ * | EXTRACT | EXTRACT(<date_part> FROM <date>) | Supports YEAR/MONTH/WEEK/DAY/HOUR/MINUTE/SECOND/MILLISECOND/... |
23
+ * | YEAR/MONTH/... | YEAR(d), MONTH(d), ... — rewritten to EXTRACT | All datepart helpers map to EXTRACT. |
24
+ * | CURRENT_TIMESTAMP | CURRENT_TIMESTAMP[(<precision>)] | SQL-92 keyword. Replaces NOW(). |
25
+ *
26
+ * <date_part> for DATEADD / DATEDIFF / DATETRUNC must be one of:
27
+ * YEAR | QUARTER | MONTH | WEEK | DAY | HOUR | MINUTE | SECOND | MILLISECOND
28
+ * (mongosql `DatePart` enum; `IsoWeek`/`DayOfYear` are EXTRACT-only and
29
+ * panic for date-functions per `algebrize_date_function`.)
30
+ *
31
+ * NOT available in MongoSQL (called out so future maintainers don't try):
32
+ * - `INTERVAL '1 day'` literals — REJECTED by parser.
33
+ * - `EXTRACT(EPOCH FROM ...)` — EPOCH is not a `DatePart`.
34
+ * - `AT TIME ZONE` / `CONVERT_TZ` — no SQL-level timezone function.
35
+ * - `VALUES (...)` table constructors — no parser support.
36
+ * - `WITH RECURSIVE` / `generate_series` — no recursive CTEs.
37
+ * For each gap, see the override below for the closest viable substitute.
38
+ *
39
+ * BaseQuery method-list audit (against
40
+ * `node_modules/@cubejs-backend/schema-compiler/dist/src/adapter/BaseQuery.js`,
41
+ * cross-checked against `MysqlQuery.js` and `PostgresQuery.js`):
42
+ *
43
+ * | BaseQuery method | T12a/b action | Why |
44
+ * |-------------------------------------------|-------------------|---------------------------------------------------------------------|
45
+ * | escapeColumnName(name) | OVERRIDE (T12a) | Default emits double-quoted ident; MongoSQL uses backticks. |
46
+ * | quoteIdentifier(name) | ADD (alias) (T12a)| Not on BaseQuery, but task spec + driver doc-comment expect it. |
47
+ * | autoPrefixWithCubeName(c, sql, isExpr) | OVERRIDE (T19a) | mongosql v1.8.5 rejects `<alias>.<col>` outside JOIN scope (3008). |
48
+ * | timeStampCast(value) | OVERRIDE (T12a) | Base emits `value::timestamptz` (Postgres). Mongosql has no `::`. |
49
+ * | dateTimeCast(value) | OVERRIDE (T12a) | Base emits `value::timestamp` (Postgres) — invalid in MongoSQL. |
50
+ * | timeStampParam(td) | INHERIT | Default delegates to timeStampCast — fine once we override that. |
51
+ * | timestampFormat() | INHERIT | ISO-8601 default matches mongosql's accepted CAST literal form. |
52
+ * | castToString(sql) | OVERRIDE (T12a) | Base emits `CAST(.. as TEXT)`; MongoSQL spells it `STRING`. |
53
+ * | convertTz(field) | OVERRIDE (T12a) | MongoSQL has no AT TIME ZONE / CONVERT_TZ. UTC-only passthrough. |
54
+ * | inDbTimeZone(date) | INHERIT | Pure JS — converts JS-side; no SQL emitted. |
55
+ * | nowTimestampSql() | OVERRIDE (T12a) | Base emits `NOW()`; MongoSQL spells it `CURRENT_TIMESTAMP`. |
56
+ * | unixTimestampSql() | OVERRIDE (T12b) | Base uses EXTRACT(EPOCH ...) — not in MongoSQL. Use DATEDIFF. |
57
+ * | concatStringsSql(strings) | INHERIT | Default uses `||` template; MongoSQL accepts `||` for concat. |
58
+ * | sqlTemplates() | OVERRIDE (T12a) | Patch quotes/identifiers + types.* to MongoSQL spellings. |
59
+ * | timeGroupedColumn(g, dim) | OVERRIDE (T12b) | Use DATETRUNC. Week pinned to 'sunday' for determinism. |
60
+ * | dateBin(interval, source, origin) | OVERRIDE (T12b) | DATEADD(unit, FLOOR(DATEDIFF/N)*N, origin) — no INTERVAL literals. |
61
+ * | subtractInterval / addInterval | OVERRIDE (T12b) | DATEADD with positive/negative numeric. Compound = chained calls. |
62
+ * | intervalString(interval) | OVERRIDE (T12b) | Quote-and-pass; no INTERVAL keyword. Used only in error/diag paths. |
63
+ * | seriesSql(td) | OVERRIDE (T12b) | UNION ALL of literal rows (MysqlQuery pattern, CAST not TIMESTAMP). |
64
+ * | newFilter(f) | OVERRIDE (Gap 4) | Return MongoSqlFilter — rewrites ILIKE (unsupported) to LOWER+LIKE. |
65
+ * | newParamAllocator(p) | INHERIT | Default `?` placeholder works for MongoSQL. |
66
+ * | escapeColumnName-driven preAggTableName | INHERIT | Inherited tableName logic produces backtick-safe identifiers. |
67
+ *
68
+ * Anything not in this table is BaseQuery default behaviour and is either
69
+ * (a) provably valid MongoSQL or (b) routed through the overrides above.
70
+ */
71
+ Object.defineProperty(exports, "__esModule", { value: true });
72
+ exports.MongoSqlFilter = exports.MongoSqlQuery = void 0;
73
+ const schema_compiler_1 = require("@cubejs-backend/schema-compiler");
74
+ /**
75
+ * Inlined re-implementation of `@cubejs-backend/shared`'s `parseSqlInterval`.
76
+ * The shared package isn't a direct dep (only transitive via schema-compiler),
77
+ * and the function is a 10-line string-split — inlining avoids pulling in
78
+ * the entire shared package and keeps the dialect's resolver-friendly.
79
+ *
80
+ * Source pattern (matches shared@1.6.44 `dist/src/time.js::parseSqlInterval`):
81
+ * "1 year 6 months" -> { year: 1, month: 6 }
82
+ * Negative values are supported.
83
+ */
84
+ function parseSqlInterval(intervalStr) {
85
+ const out = {};
86
+ const parts = intervalStr.trim().split(/\s+/);
87
+ for (let i = 0; i < parts.length; i += 2) {
88
+ const value = parseInt(parts[i], 10);
89
+ const unit = (parts[i + 1] ?? '').toLowerCase();
90
+ if (!unit || Number.isNaN(value)) {
91
+ throw new Error(`Cannot parse interval segment "${parts[i]} ${parts[i + 1] ?? ''}" in "${intervalStr}"`);
92
+ }
93
+ const singular = unit.endsWith('s') ? unit.slice(0, -1) : unit;
94
+ out[singular] = value;
95
+ }
96
+ return out;
97
+ }
98
+ /**
99
+ * Map from Cube's lowercase granularity names to MongoSQL's documented
100
+ * `DatePart` tokens (uppercase). Matches PostgresQuery's `GRANULARITY_TO_INTERVAL`
101
+ * spirit but uses MongoSQL's spellings.
102
+ */
103
+ const GRANULARITY_TO_DATE_PART = Object.freeze({
104
+ second: 'SECOND',
105
+ minute: 'MINUTE',
106
+ hour: 'HOUR',
107
+ day: 'DAY',
108
+ week: 'WEEK',
109
+ month: 'MONTH',
110
+ quarter: 'QUARTER',
111
+ year: 'YEAR',
112
+ });
113
+ /**
114
+ * Map from `parseSqlInterval` keys (singular, lowercase) to MongoSQL DATEADD
115
+ * date-part tokens. Includes `millisecond` because mongosql DATEADD supports
116
+ * MILLISECOND (per `DatePart` enum).
117
+ */
118
+ const INTERVAL_UNIT_TO_DATE_PART = Object.freeze({
119
+ millisecond: 'MILLISECOND',
120
+ second: 'SECOND',
121
+ minute: 'MINUTE',
122
+ hour: 'HOUR',
123
+ day: 'DAY',
124
+ week: 'WEEK',
125
+ month: 'MONTH',
126
+ quarter: 'QUARTER',
127
+ year: 'YEAR',
128
+ });
129
+ /**
130
+ * Cube SQL-dialect adapter that emits MongoSQL-compatible SQL.
131
+ *
132
+ * Instantiated by `MongoSqlDriver.dialectClass()`. Cube calls into this for
133
+ * every measure/dimension/timeDimension SQL fragment.
134
+ */
135
+ class MongoSqlQuery extends schema_compiler_1.BaseQuery {
136
+ /**
137
+ * Identifier quoting — MongoSQL uses backticks.
138
+ * Reference: https://www.mongodb.com/docs/sql-interface/language-reference/identifiers/
139
+ *
140
+ * BaseQuery's actual identifier-quoting hook is `escapeColumnName`; we
141
+ * also expose `quoteIdentifier` as an alias because it's the conventional
142
+ * name and the driver's audit comment refers to it.
143
+ */
144
+ escapeColumnName(name) {
145
+ return `\`${name.replace(/`/g, '``')}\``;
146
+ }
147
+ quoteIdentifier(identifier) {
148
+ return this.escapeColumnName(identifier);
149
+ }
150
+ /**
151
+ * Suppress the cube-alias prefix on bare column references when the query
152
+ * has only one cube in scope.
153
+ *
154
+ * Background (T19 discovery): mongosql v1.8.5's algebrizer rejects qualified
155
+ * `<table_alias>.<col>` references in projections when only one collection
156
+ * is in scope — Error 3008 "Field `orders` in the `SELECT` clause at the 0
157
+ * scope level not found". Cube's BaseQuery emits `${cubeAlias}.${sql}` for
158
+ * every dimension that is a bare identifier (see BaseQuery.js:2508
159
+ * `autoPrefixWithCubeName`), which makes every realistic Cube query against
160
+ * a single cube fail translation.
161
+ *
162
+ * Strategy:
163
+ * - Single-cube query (`this.join.joins.length === 0`): drop the prefix
164
+ * — emit a bare column reference (`SELECT email FROM users`).
165
+ * - Multi-cube / JOIN: keep the prefix (`SELECT users.email`) — mongosql
166
+ * accepts qualified refs in JOIN scope (verified end-to-end in
167
+ * tests/integration/basic-queries.test.ts).
168
+ * - `this.join` may be `null` during pre-build / collect-cube-names paths
169
+ * before `prebuildJoin` runs; treat that as "not enough info, keep
170
+ * BaseQuery's behaviour" so we don't drop a prefix Cube actually needed.
171
+ * - `isMemberExpr` (member-expression SQL) bypasses the prefix entirely
172
+ * in BaseQuery; keep that semantics for forward compat.
173
+ *
174
+ * The conditional fall-through to `super` keeps every other code path
175
+ * (non-bare expressions like `LOWER(email)` already escape the regex match
176
+ * and are returned verbatim by the base implementation) unchanged.
177
+ */
178
+ autoPrefixWithCubeName(cubeName, sql, isMemberExpr = false) {
179
+ // Single-cube projection: mongosql rejects `<alias>.<col>`. Strip the
180
+ // alias prefix only when (a) we'd otherwise emit it (bare identifier,
181
+ // not a member-expression) and (b) the query truly has no joins.
182
+ const join = this
183
+ .join;
184
+ if (join &&
185
+ Array.isArray(join.joins) &&
186
+ join.joins.length === 0 &&
187
+ !isMemberExpr &&
188
+ /^[_a-zA-Z][_a-zA-Z0-9]*$/.test(sql)) {
189
+ return sql;
190
+ }
191
+ return super.autoPrefixWithCubeName(cubeName, sql, isMemberExpr);
192
+ }
193
+ /**
194
+ * GROUP BY by column alias instead of positional `1, 2, ...`.
195
+ * mongosql v1.8.5's algebrizer rejects positional refs in GROUP BY
196
+ * (and the failure mode misreports as Error 3008 "Field <col> in the
197
+ * SELECT clause not found"). Mirrors the ClickHouseQuery pattern.
198
+ */
199
+ groupByClause() {
200
+ if (this.ungrouped) {
201
+ return '';
202
+ }
203
+ const aliases = this.dimensionAliasNames();
204
+ return aliases.length ? ` GROUP BY ${aliases.join(', ')}` : '';
205
+ }
206
+ /**
207
+ * ORDER BY by column alias instead of positional `1, 2, ...`.
208
+ * Same constraint as `groupByClause` — mongosql requires named refs.
209
+ */
210
+ orderHashToString(hash) {
211
+ if (!hash?.id) {
212
+ return null;
213
+ }
214
+ const fieldAlias = this.getFieldAlias(hash.id);
215
+ if (fieldAlias === null) {
216
+ return null;
217
+ }
218
+ const direction = hash.desc ? 'DESC' : 'ASC';
219
+ return `${fieldAlias} ${direction}`;
220
+ }
221
+ /**
222
+ * Timestamp literal cast — CRITICAL DISCOVERY (T07): MongoSQL does NOT
223
+ * accept the SQL-92 `TIMESTAMP 'literal'` form. Use `CAST('...' AS TIMESTAMP)`.
224
+ * Reference: https://www.mongodb.com/docs/sql-interface/language-reference/data-types/
225
+ * (and crates/native/src/translate.rs::date_filter_emits_match_referencing_created_at)
226
+ */
227
+ timeStampCast(value) {
228
+ return `CAST(${value} AS TIMESTAMP)`;
229
+ }
230
+ /**
231
+ * datetime cast — MongoSQL has only `TIMESTAMP` (no separate `DATETIME` /
232
+ * `DATE` types), so `dateTimeCast` and `timeStampCast` produce the same SQL.
233
+ * SPEC FR-2 explicitly substitutes `TIMESTAMP` for `DATE`.
234
+ */
235
+ dateTimeCast(value) {
236
+ return `CAST(${value} AS TIMESTAMP)`;
237
+ }
238
+ /**
239
+ * String cast — MongoSQL's string type is spelt `STRING`, not the SQL-92
240
+ * `TEXT` (BaseQuery's default) or MySQL's `CHAR`.
241
+ * Reference: https://www.mongodb.com/docs/sql-interface/language-reference/data-types/
242
+ */
243
+ castToString(sql) {
244
+ return `CAST(${sql} AS STRING)`;
245
+ }
246
+ /**
247
+ * Generic typed cast helper. MongoSQL accepts the standard CAST grammar;
248
+ * the *type name* must be one of MongoSQL's documented type tokens
249
+ * (BOOL, INT, LONG, DOUBLE, DECIMAL, STRING, TIMESTAMP, ARRAY, DOCUMENT).
250
+ */
251
+ castSqlType(value, type) {
252
+ return `CAST(${value} AS ${type})`;
253
+ }
254
+ /**
255
+ * Timezone conversion — MongoSQL has no `AT TIME ZONE` or `CONVERT_TZ`
256
+ * function (verified against the v1.8.5 grammar). Data is stored in UTC
257
+ * (BSON DateTime), and `inDbTimeZone()` (inherited) shifts JS-side
258
+ * timestamp parameters. For SQL-emitted field references we passthrough —
259
+ * correct for UTC data and matching "no conversion" semantics.
260
+ *
261
+ * Revisit if MongoSQL adds a timezone-aware function form, or if T14
262
+ * integration shows non-UTC dimensions break.
263
+ */
264
+ convertTz(field) {
265
+ return field;
266
+ }
267
+ /**
268
+ * NOW() equivalent. MongoSQL's documented form for the current time is
269
+ * `CURRENT_TIMESTAMP` (SQL-92 keyword), not MySQL/Postgres `NOW()`.
270
+ */
271
+ nowTimestampSql() {
272
+ return 'CURRENT_TIMESTAMP';
273
+ }
274
+ /**
275
+ * Seconds since the Unix epoch. BaseQuery default uses
276
+ * `EXTRACT(EPOCH FROM NOW())`, but MongoSQL's `EXTRACT` does NOT support
277
+ * the `EPOCH` date-part (only YEAR/MONTH/WEEK/DAY/HOUR/MINUTE/SECOND/
278
+ * MILLISECOND/DAYOFYEAR/DAYOFWEEK/ISOWEEK/ISOWEEKDAY — see
279
+ * `algebrize_extract` in mongosql/src/algebrizer/definitions.rs).
280
+ *
281
+ * Use `DATEDIFF(SECOND, '1970-01-01T00:00:00Z', CURRENT_TIMESTAMP)`
282
+ * instead. Returns LONG (mongosql `$dateDiff`).
283
+ */
284
+ unixTimestampSql() {
285
+ return `DATEDIFF(SECOND, ${this.timeStampCast("'1970-01-01T00:00:00Z'")}, ${this.nowTimestampSql()})`;
286
+ }
287
+ /**
288
+ * Parse a Cube/Postgres-style interval string ("1 day", "2 weeks",
289
+ * "1 year 6 months") into an ordered list of MongoSQL DATEADD components.
290
+ *
291
+ * Cube emits compound intervals for partition ranges and granularity
292
+ * offsets. MongoSQL's DATEADD takes a single `<date_part>`, so we apply
293
+ * each component as a chained DATEADD call (see `addInterval` /
294
+ * `subtractInterval`). Order is preserved from `parseSqlInterval` so the
295
+ * outermost DATEADD is the *last* component (matches semantics: applying
296
+ * `(YEAR, 1)` then `(MONTH, 6)` is equivalent to "1 year 6 months").
297
+ *
298
+ * Public for unit-testing the bridge in isolation; not on BaseQuery.
299
+ */
300
+ intervalUnitsForMongo(interval) {
301
+ const parsed = parseSqlInterval(interval);
302
+ const components = [];
303
+ for (const [unit, value] of Object.entries(parsed)) {
304
+ const datePart = INTERVAL_UNIT_TO_DATE_PART[unit];
305
+ if (!datePart) {
306
+ throw new Error(`MongoSQL DATEADD does not support interval unit "${unit}" (from "${interval}")`);
307
+ }
308
+ components.push({ value, unit: datePart });
309
+ }
310
+ if (components.length === 0) {
311
+ throw new Error(`Cannot parse interval "${interval}" — produced no components`);
312
+ }
313
+ return components;
314
+ }
315
+ /**
316
+ * Add a Cube interval to a date expression. Compound intervals
317
+ * ("1 year 6 months") are emitted as chained DATEADD calls.
318
+ *
319
+ * MongoSQL has no `INTERVAL '...'` literal. The base implementation emits
320
+ * `${date} + interval '...'` which the parser rejects.
321
+ */
322
+ addInterval(date, interval) {
323
+ return this.applyIntervalChain(date, this.intervalUnitsForMongo(interval), 1);
324
+ }
325
+ /**
326
+ * Subtract a Cube interval from a date expression. Implemented as DATEADD
327
+ * with negated values (so `subtractInterval('d', '1 month')` becomes
328
+ * `DATEADD(MONTH, -1, d)`). Compound intervals chain the same way as
329
+ * `addInterval`.
330
+ */
331
+ subtractInterval(date, interval) {
332
+ return this.applyIntervalChain(date, this.intervalUnitsForMongo(interval), -1);
333
+ }
334
+ applyIntervalChain(date, components, sign) {
335
+ return components.reduce((acc, { value, unit }) => `DATEADD(${unit}, ${sign * value}, ${acc})`, date);
336
+ }
337
+ /**
338
+ * Printable interval string. MongoSQL has no INTERVAL literal so this is
339
+ * not safe to splice into emitted SQL — kept for diagnostic / error
340
+ * messages and for any BaseQuery code path we haven't audited yet (a
341
+ * future grep for `'1 day'` in SQL output would surface a regression).
342
+ */
343
+ intervalString(interval) {
344
+ return `'${interval}'`;
345
+ }
346
+ /**
347
+ * Truncate a timestamp to a granularity boundary. MongoSQL's documented
348
+ * form is `DATETRUNC(<unit>, <date>[, <start_of_week>])`. For week we pin
349
+ * `'sunday'` explicitly: mongosql's `ScalarFunctionsRewritePass` defaults
350
+ * a missing third arg to `'sunday'` (per ast/rewrites/test.rs::
351
+ * `timestamp_trunc`), but Cube's tests should not depend on that
352
+ * implicit default — a future mongosql release could change it.
353
+ */
354
+ timeGroupedColumn(granularity, dimension) {
355
+ const datePart = GRANULARITY_TO_DATE_PART[granularity];
356
+ if (!datePart) {
357
+ throw new Error(`MongoSQL dialect does not support granularity "${granularity}"`);
358
+ }
359
+ if (granularity === 'week') {
360
+ return `DATETRUNC(${datePart}, ${dimension}, 'sunday')`;
361
+ }
362
+ return `DATETRUNC(${datePart}, ${dimension})`;
363
+ }
364
+ /**
365
+ * Bucket `source` into intervals starting from `origin`. Cube uses this
366
+ * for custom (non-natural) granularities like "5 minutes" or "10 days".
367
+ *
368
+ * MongoSQL has no INTERVAL literal, so PostgresQuery's
369
+ * `'origin'::ts + INTERVAL N * FLOOR(EXTRACT(EPOCH ...))` form doesn't
370
+ * port. Instead we use the DATEADD/DATEDIFF identity:
371
+ *
372
+ * floor((source - origin) / interval) * interval + origin
373
+ *
374
+ * which becomes:
375
+ *
376
+ * DATEADD(unit, FLOOR(DATEDIFF(unit, origin, source) / N) * N, origin)
377
+ *
378
+ * Year and quarter intervals are normalised to MONTH (1 year = 12 months,
379
+ * 1 quarter = 3 months) so arithmetic doesn't depend on leap-day-aware
380
+ * second math. Every other unit (week / day / hour / minute / second /
381
+ * millisecond) is used as-is — DATEDIFF/DATEADD operate in the unit's
382
+ * native granularity which is the most precise viable choice.
383
+ *
384
+ * NOTE: only single-component intervals are supported here (matches
385
+ * Cube's custom-granularity inputs which are always one unit). Compound
386
+ * dateBin intervals would need a different strategy.
387
+ */
388
+ dateBin(interval, source, origin) {
389
+ const components = this.intervalUnitsForMongo(interval);
390
+ if (components.length !== 1) {
391
+ throw new Error(`MongoSQL dateBin requires a single-unit interval; got "${interval}"`);
392
+ }
393
+ const [{ value, unit }] = components;
394
+ // Normalise year/quarter to MONTH so the unit aligns with calendar
395
+ // boundaries; everything else uses its native unit for max precision.
396
+ const usedUnit = unit === 'YEAR' || unit === 'QUARTER' ? 'MONTH' : unit;
397
+ const stride = unit === 'YEAR' ? value * 12 : unit === 'QUARTER' ? value * 3 : value;
398
+ const originExpr = this.dateTimeCast(`'${origin}'`);
399
+ return `DATEADD(${usedUnit}, FLOOR(DATEDIFF(${usedUnit}, ${originExpr}, ${source}) / ${stride}) * ${stride}, ${originExpr})`;
400
+ }
401
+ /**
402
+ * Generate the date-series SQL Cube uses for time-bucketed pre-aggregations.
403
+ * MongoSQL has no `VALUES (...)`, no recursive CTE, and no `generate_series`,
404
+ * so we emit a UNION ALL of literal-row SELECTs (MysqlQuery's strategy)
405
+ * and CAST in the outer projection. Identical row count to MysqlQuery's
406
+ * version; the difference is `CAST(... AS TIMESTAMP)` instead of
407
+ * MySQL-specific `TIMESTAMP(...)`.
408
+ *
409
+ * NOTE: emits N rows for an N-row series. For very large partition ranges
410
+ * Cube can pre-compute the row set in JS — there's no in-DB way to grow
411
+ * the series without recursive CTEs, which v1.8.5 doesn't support.
412
+ */
413
+ seriesSql(timeDimension) {
414
+ const rows = timeDimension.timeSeries();
415
+ const union = rows
416
+ .map((row) => {
417
+ const [from, to] = row;
418
+ return `SELECT '${from}' f, '${to}' t`;
419
+ })
420
+ .join(' UNION ALL ');
421
+ const dateFrom = this.escapeColumnName('date_from');
422
+ const dateTo = this.escapeColumnName('date_to');
423
+ return `SELECT CAST(dates.f AS TIMESTAMP) AS ${dateFrom}, CAST(dates.t AS TIMESTAMP) AS ${dateTo} FROM (${union}) ${this.asSyntaxTable} dates`;
424
+ }
425
+ /**
426
+ * Override Cube's filter class for every filter on a MongoSQL query.
427
+ *
428
+ * Background (Gap 4 discovery): Cube's default `BaseFilter.likeIgnoreCase`
429
+ * emits `<col> [NOT] ILIKE <pattern>` for `contains`, `notContains`,
430
+ * `startsWith`, `notStartsWith`, `endsWith`, `notEndsWith`. mongosql
431
+ * v1.8.5's grammar does NOT include the `ILIKE` keyword (verified
432
+ * empirically against atlas-local — the parser reports
433
+ * `Error 2001: Unrecognized token ILIKE, expected: BETWEEN` /
434
+ * `expected COMMA, RIGHT_PAREN`). mongosql DOES support the standard
435
+ * SQL-92 `LIKE` keyword.
436
+ *
437
+ * Strategy: subclass BaseFilter and override `likeIgnoreCase` to
438
+ * emit `LOWER(<col>) LIKE LOWER(<pattern>)` instead of
439
+ * `<col> ILIKE <pattern>`. Wrapping both sides in `LOWER(...)`
440
+ * preserves case-insensitive semantics; mongosql's `LOWER` is the
441
+ * standard SQL function and round-trips strings unchanged for ASCII
442
+ * content. We do NOT use `ESCAPE` clauses here because Cube's
443
+ * `escapeWildcardChars` pre-escapes `%` and `_` with `\` and SQL's
444
+ * default LIKE escape character IS `\` per the SQL standard (mongosql
445
+ * v1.8.5 follows this).
446
+ *
447
+ * **Non-ASCII / Unicode caveat.** This override is ASCII-aware case
448
+ * folding only. mongosql v1.8.5 does not expose `COLLATE` at the SQL
449
+ * surface, so case-folding non-ASCII characters (e.g. the German
450
+ * sharp-s `ß` → `ss`, Turkish dotless-i, etc.) is NOT performed. For
451
+ * pure-Latin inputs (the dominant Cube use case) this is correct.
452
+ * For locale-sensitive case-insensitive search, use MongoDB's
453
+ * collation feature outside the SQL surface or pre-normalise data.
454
+ */
455
+ newFilter(filter) {
456
+ return new MongoSqlFilter(this, filter);
457
+ }
458
+ /**
459
+ * Patch the SQL templates that drive the rest of BaseQuery's builders.
460
+ * Mirrors MysqlQuery.sqlTemplates()'s pattern of `super` + targeted
461
+ * overrides.
462
+ *
463
+ * T12b additions: remove the `expressions.interval` template (BaseQuery's
464
+ * default emits `INTERVAL '<x>'` — invalid MongoSQL) so any caller that
465
+ * tries to render an interval literal surfaces an error rather than
466
+ * silently emitting unparseable SQL. The arithmetic-emitting paths
467
+ * (subtractInterval/addInterval/dateBin) don't go through this template.
468
+ * Also drop `statements.generated_time_series_*` for the same reason —
469
+ * those are recursive-CTE forms that mongosql doesn't accept.
470
+ */
471
+ sqlTemplates() {
472
+ const templates = super.sqlTemplates();
473
+ // Identifier quoting at the template layer (used by Cube's SQL planner).
474
+ templates.quotes.identifiers = '`';
475
+ templates.quotes.escape = '``';
476
+ // Type names — MongoSQL's spellings per the Language Reference.
477
+ // https://www.mongodb.com/docs/sql-interface/language-reference/data-types/
478
+ templates.types.string = 'STRING';
479
+ templates.types.boolean = 'BOOL';
480
+ templates.types.tinyint = 'INT';
481
+ templates.types.smallint = 'INT';
482
+ templates.types.integer = 'INT';
483
+ templates.types.bigint = 'LONG';
484
+ templates.types.float = 'DOUBLE';
485
+ templates.types.double = 'DOUBLE';
486
+ templates.types.decimal = 'DECIMAL';
487
+ templates.types.timestamp = 'TIMESTAMP';
488
+ // MongoSQL has no `DATE` / `TIME` / `INTERVAL` / `BINARY`; map to closest
489
+ // representable type or delete to surface an error if Cube ever asks.
490
+ templates.types.date = 'TIMESTAMP';
491
+ templates.types.time = 'TIMESTAMP';
492
+ delete templates.types.interval;
493
+ delete templates.types.binary;
494
+ // Drop INTERVAL-literal and recursive-CTE forms — mongosql v1.8.5
495
+ // rejects both. Anything that would have used these now routes through
496
+ // our typed overrides (addInterval/subtractInterval/seriesSql) or
497
+ // surfaces a clear missing-template error.
498
+ if (templates.expressions) {
499
+ delete templates.expressions.interval;
500
+ }
501
+ if (templates.statements) {
502
+ delete templates.statements.generated_time_series_select;
503
+ delete templates.statements.generated_time_series_with_cte_range_source;
504
+ }
505
+ return templates;
506
+ }
507
+ }
508
+ exports.MongoSqlQuery = MongoSqlQuery;
509
+ /**
510
+ * Filter override for MongoSQL — rewrites `ILIKE` to `LOWER(...) LIKE LOWER(...)`.
511
+ *
512
+ * See `MongoSqlQuery.newFilter` for the rationale. Exported so unit tests
513
+ * can exercise `likeIgnoreCase` in isolation without instantiating the
514
+ * whole query stack.
515
+ */
516
+ class MongoSqlFilter extends schema_compiler_1.BaseFilter {
517
+ /**
518
+ * Emit `LOWER(<col>) [NOT] LIKE LOWER(<wrapped-param>)` for mongosql.
519
+ *
520
+ * Layout mirrors BaseFilter.likeIgnoreCase:
521
+ * - `type === 'contains'`: wrap pattern with `'%' || ... || '%'`
522
+ * - `type === 'starts'`: suffix with `|| '%'` only (no prefix)
523
+ * - `type === 'ends'`: prefix with `'%' ||` only (no suffix)
524
+ *
525
+ * Cube's BaseFilter passes type as 'contains' / 'starts' / 'ends'
526
+ * (NOT the camelized operator — see BaseFilter.likeOr where `type`
527
+ * is hardcoded to one of those three values).
528
+ *
529
+ * `allocateParam` returns Cube's `?` placeholder; the driver's
530
+ * `substituteParameters` inlines literals before sending to mongosql.
531
+ */
532
+ likeIgnoreCase(column, not, param, type) {
533
+ const p = !type || type === 'contains' || type === 'ends' ? "'%' || " : '';
534
+ const s = !type || type === 'contains' || type === 'starts' ? " || '%'" : '';
535
+ // Wrap the param-allocated placeholder in LOWER so the parser sees
536
+ // `LOWER(<col>) [NOT] LIKE LOWER('%' || ? || '%')`. mongosql's LOWER
537
+ // accepts the concatenated string expression as input.
538
+ //
539
+ // **Performance.** `LOWER(<col>)` is non-sargable — it prevents
540
+ // MongoDB from using any B-tree index on `<col>`. For high-volume
541
+ // case-insensitive search consider EITHER (a) materialising a
542
+ // lowercase shadow column at ingestion time and indexing that, OR
543
+ // (b) using MongoDB's collation feature outside the SQL surface
544
+ // (mongosql v1.8.5 does not expose `COLLATE`).
545
+ const wrapped = `${p}${this.allocateParam(param)}${s}`;
546
+ const direction = not ? ' NOT' : '';
547
+ return `LOWER(${column})${direction} LIKE LOWER(${wrapped})`;
548
+ }
549
+ }
550
+ exports.MongoSqlFilter = MongoSqlFilter;
551
+ //# sourceMappingURL=MongoSqlQuery.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MongoSqlQuery.js","sourceRoot":"","sources":["../src/MongoSqlQuery.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,29 @@
1
+ /** Subset of `process.env` we depend on. */
2
+ export type EnvLike = NodeJS.ProcessEnv;
3
+ /** Result of resolving env vars + overrides into a connection-string + driver options. */
4
+ export interface ResolvedUriConfig {
5
+ /** Final URI to hand to the Rust client. Always contains all env-driven params. */
6
+ uri: string;
7
+ /**
8
+ * Effective per-query timeout in milliseconds (drives the aggregation
9
+ * pipeline's `maxTimeMS`). Resolved precedence:
10
+ * 1. `override.queryTimeoutMs` (constructor arg)
11
+ * 2. `CUBEJS_DB_QUERY_TIMEOUT` (Cube-standard, duration-aware)
12
+ * 3. `CUBEJS_MONGOSQL_QUERY_TIMEOUT_MS` (legacy, bare number)
13
+ * Undefined if none set; the native side then uses its built-in default.
14
+ */
15
+ queryTimeoutMs: number | undefined;
16
+ }
17
+ /**
18
+ * Resolve `(uri, queryTimeoutMs)` from constructor overrides + env.
19
+ *
20
+ * Throws `MONGOSQL_CONFIG_INVALID` when:
21
+ * - neither explicit uri / `CUBEJS_DB_URL` / `CUBEJS_DB_URI` is set
22
+ * AND `CUBEJS_DB_HOST` is also unset;
23
+ * - a duration env var is malformed (e.g. `"forever"`);
24
+ * - a numeric env var fails to parse.
25
+ */
26
+ export declare function resolveUriConfig(overrideUri: string | undefined, env: EnvLike): ResolvedUriConfig;
27
+ /** Same as `parseDurationToMillisString` but returns the integer directly. Throws on malformed input. */
28
+ export declare function parseDurationToMillis(raw: string, envVarName: string): number;
29
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAyEA,4CAA4C;AAC5C,MAAM,MAAM,OAAO,GAAG,MAAM,CAAC,UAAU,CAAC;AAExC,0FAA0F;AAC1F,MAAM,WAAW,iBAAiB;IAChC,mFAAmF;IACnF,GAAG,EAAE,MAAM,CAAC;IACZ;;;;;;;OAOG;IACH,cAAc,EAAE,MAAM,GAAG,SAAS,CAAC;CACpC;AA+CD;;;;;;;;GAQG;AACH,wBAAgB,gBAAgB,CAAC,WAAW,EAAE,MAAM,GAAG,SAAS,EAAE,GAAG,EAAE,OAAO,GAAG,iBAAiB,CAiBjG;AAsLD,yGAAyG;AACzG,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,CAQ7E"}