UNPKG

drizzle-cube

Version:

Drizzle ORM-first semantic layer with Cube.js compatibility. Type-safe analytics and dashboards with SQL injection protection.

34 lines 415 kB
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const A=require("drizzle-orm");class we{preprocessCalculatedTemplate(e){return e}buildPattern(e,E){switch(e){case"contains":case"notContains":return`%${E}%`;case"startsWith":return`${E}%`;case"endsWith":return`%${E}`;default:return E}}parseISODuration(e){const E={years:0,months:0,days:0,hours:0,minutes:0,seconds:0},t=/^P(?:(\d+)Y)?(?:(\d+)M)?(?:(\d+)D)?(?:T(?:(\d+)H)?(?:(\d+)M)?(?:(\d+(?:\.\d+)?)S)?)?$/,T=e.match(t);if(!T)throw new Error(`Invalid ISO 8601 duration format: ${e}`);return E.years=parseInt(T[1]||"0",10),E.months=parseInt(T[2]||"0",10),E.days=parseInt(T[3]||"0",10),E.hours=parseInt(T[4]||"0",10),E.minutes=parseInt(T[5]||"0",10),E.seconds=parseFloat(T[6]||"0"),E}durationToSeconds(e){const E=this.parseISODuration(e);return E.years*365*24*60*60+E.months*30*24*60*60+E.days*24*60*60+E.hours*60*60+E.minutes*60+E.seconds}}class Rt extends we{getEngineType(){return"postgres"}supportsLateralJoins(){return!0}buildIntervalFromISO(e){const E=this.parseISODuration(e),t=[];E.years&&t.push(`${E.years} years`),E.months&&t.push(`${E.months} months`),E.days&&t.push(`${E.days} days`),E.hours&&t.push(`${E.hours} hours`),E.minutes&&t.push(`${E.minutes} minutes`),E.seconds&&t.push(`${E.seconds} seconds`);const T=t.join(" ")||"0 seconds";return A.sql`INTERVAL '${A.sql.raw(T)}'`}buildTimeDifferenceSeconds(e,E){return A.sql`EXTRACT(EPOCH FROM (${e} - ${E}))`}buildDateAddInterval(e,E){const t=this.buildIntervalFromISO(E);return A.sql`(${e} + ${t})`}buildConditionalAggregation(e,E,t){const T=e.toUpperCase();return e==="count"&&!E?A.sql`COUNT(*) FILTER (WHERE ${t})`:A.sql`${A.sql.raw(T)}(${E}) FILTER (WHERE ${t})`}buildTimeDimension(e,E){switch(e){case"year":return A.sql`DATE_TRUNC('year', ${E}::timestamp)`;case"quarter":return A.sql`DATE_TRUNC('quarter', ${E}::timestamp)`;case"month":return A.sql`DATE_TRUNC('month', ${E}::timestamp)`;case"week":return A.sql`DATE_TRUNC('week', ${E}::timestamp)`;case"day":return A.sql`DATE_TRUNC('day', ${E}::timestamp)::timestamp`;case"hour":return A.sql`DATE_TRUNC('hour', ${E}::timestamp)`;case"minute":return A.sql`DATE_TRUNC('minute', ${E}::timestamp)`;case"second":return A.sql`DATE_TRUNC('second', ${E}::timestamp)`;default:return E}}buildStringCondition(e,E,t){switch(E){case"contains":return A.sql`${e} ILIKE ${`%${t}%`}`;case"notContains":return A.sql`${e} NOT ILIKE ${`%${t}%`}`;case"startsWith":return A.sql`${e} ILIKE ${`${t}%`}`;case"endsWith":return A.sql`${e} ILIKE ${`%${t}`}`;case"like":return A.sql`${e} LIKE ${t}`;case"notLike":return A.sql`${e} NOT LIKE ${t}`;case"ilike":return A.sql`${e} ILIKE ${t}`;case"regex":return A.sql`${e} ~* ${t}`;case"notRegex":return A.sql`${e} !~* ${t}`;default:throw new Error(`Unsupported string operator: ${E}`)}}castToType(e,E){switch(E){case"timestamp":return A.sql`${e}::timestamp`;case"decimal":return A.sql`${e}::decimal`;case"integer":return A.sql`${e}::integer`;default:throw new Error(`Unsupported cast type: ${E}`)}}buildAvg(e){return A.sql`COALESCE(AVG(${e}), 0)`}buildCaseWhen(e,E){const t=e.map(T=>A.sql`WHEN ${T.when} THEN ${T.then}`).reduce((T,n)=>A.sql`${T} ${n}`);return E!==void 0?A.sql`CASE ${t} ELSE ${E} END`:A.sql`CASE ${t} END`}buildBooleanLiteral(e){return e?A.sql`TRUE`:A.sql`FALSE`}convertFilterValue(e){return e}prepareDateValue(e){return e}isTimestampInteger(){return!1}convertTimeDimensionResult(e){return e}getCapabilities(){return{supportsStddev:!0,supportsVariance:!0,supportsPercentile:!0,supportsWindowFunctions:!0,supportsFrameClause:!0,supportsLateralJoins:!0}}buildStddev(e,E=!1){const t=E?"STDDEV_SAMP":"STDDEV_POP";return A.sql`COALESCE(${A.sql.raw(t)}(${e}), 0)`}buildVariance(e,E=!1){const t=E?"VAR_SAMP":"VAR_POP";return A.sql`COALESCE(${A.sql.raw(t)}(${e}), 0)`}buildPercentile(e,E){const t=E/100;return A.sql`PERCENTILE_CONT(${t}) WITHIN GROUP (ORDER BY ${e})`}buildWindowFunction(e,E,t,T,n){const R=t&&t.length>0?A.sql`PARTITION BY ${A.sql.join(t,A.sql`, `)}`:A.sql``,r=T&&T.length>0?A.sql`ORDER BY ${A.sql.join(T.map(I=>I.direction==="desc"?A.sql`${I.field} DESC`:A.sql`${I.field} ASC`),A.sql`, `)}`:A.sql``;let S=A.sql``;if(n?.frame){const{type:I,start:a,end:o}=n.frame,l=I.toUpperCase(),C=a==="unbounded"?"UNBOUNDED PRECEDING":typeof a=="number"?`${a} PRECEDING`:"CURRENT ROW",u=o==="unbounded"?"UNBOUNDED FOLLOWING":o==="current"?"CURRENT ROW":typeof o=="number"?`${o} FOLLOWING`:"CURRENT ROW";S=A.sql`${A.sql.raw(l)} BETWEEN ${A.sql.raw(C)} AND ${A.sql.raw(u)}`}const i=[];t&&t.length>0&&i.push(R),T&&T.length>0&&i.push(r),n?.frame&&i.push(S);const N=i.length>0?A.sql.join(i,A.sql` `):A.sql``,O=A.sql`OVER (${N})`;switch(e){case"lag":return A.sql`LAG(${E}, ${n?.offset??1}${n?.defaultValue!==void 0?A.sql`, ${n.defaultValue}`:A.sql``}) ${O}`;case"lead":return A.sql`LEAD(${E}, ${n?.offset??1}${n?.defaultValue!==void 0?A.sql`, ${n.defaultValue}`:A.sql``}) ${O}`;case"rank":return A.sql`RANK() ${O}`;case"denseRank":return A.sql`DENSE_RANK() ${O}`;case"rowNumber":return A.sql`ROW_NUMBER() ${O}`;case"ntile":return A.sql`NTILE(${n?.nTile??4}) ${O}`;case"firstValue":return A.sql`FIRST_VALUE(${E}) ${O}`;case"lastValue":return A.sql`LAST_VALUE(${E}) ${O}`;case"movingAvg":return A.sql`AVG(${E}) ${O}`;case"movingSum":return A.sql`SUM(${E}) ${O}`;default:throw new Error(`Unsupported window function: ${e}`)}}}class GE extends we{getEngineType(){return"mysql"}supportsLateralJoins(){return!0}buildIntervalFromISO(e){const E=this.parseISODuration(e),t=[];E.years&&t.push(`${E.years} YEAR`),E.months&&t.push(`${E.months} MONTH`),E.days&&t.push(`${E.days} DAY`),E.hours&&t.push(`${E.hours} HOUR`),E.minutes&&t.push(`${E.minutes} MINUTE`),E.seconds&&t.push(`${E.seconds} SECOND`);const T=this.durationToSeconds(e);return A.sql`${T}`}buildTimeDifferenceSeconds(e,E){return A.sql`TIMESTAMPDIFF(SECOND, ${E}, ${e})`}buildDateAddInterval(e,E){const t=this.parseISODuration(E);let T=e;return t.years&&(T=A.sql`DATE_ADD(${T}, INTERVAL ${t.years} YEAR)`),t.months&&(T=A.sql`DATE_ADD(${T}, INTERVAL ${t.months} MONTH)`),t.days&&(T=A.sql`DATE_ADD(${T}, INTERVAL ${t.days} DAY)`),t.hours&&(T=A.sql`DATE_ADD(${T}, INTERVAL ${t.hours} HOUR)`),t.minutes&&(T=A.sql`DATE_ADD(${T}, INTERVAL ${t.minutes} MINUTE)`),t.seconds&&(T=A.sql`DATE_ADD(${T}, INTERVAL ${t.seconds} SECOND)`),T}buildConditionalAggregation(e,E,t){const T=e.toUpperCase();return e==="count"&&!E?A.sql`COUNT(CASE WHEN ${t} THEN 1 END)`:A.sql`${A.sql.raw(T)}(CASE WHEN ${t} THEN ${E} END)`}buildTimeDimension(e,E){const t={year:"%Y-01-01 00:00:00",quarter:"%Y-%q-01 00:00:00",month:"%Y-%m-01 00:00:00",week:"%Y-%u-01 00:00:00",day:"%Y-%m-%d 00:00:00",hour:"%Y-%m-%d %H:00:00",minute:"%Y-%m-%d %H:%i:00",second:"%Y-%m-%d %H:%i:%s"};switch(e){case"quarter":return A.sql`DATE_ADD(MAKEDATE(YEAR(${E}), 1), INTERVAL (QUARTER(${E}) - 1) * 3 MONTH)`;case"week":return A.sql`DATE_SUB(${E}, INTERVAL WEEKDAY(${E}) DAY)`;default:{const T=t[e];return T?A.sql`STR_TO_DATE(DATE_FORMAT(${E}, ${T}), '%Y-%m-%d %H:%i:%s')`:E}}}buildStringCondition(e,E,t){switch(E){case"contains":return A.sql`LOWER(${e}) LIKE ${`%${t.toLowerCase()}%`}`;case"notContains":return A.sql`LOWER(${e}) NOT LIKE ${`%${t.toLowerCase()}%`}`;case"startsWith":return A.sql`LOWER(${e}) LIKE ${`${t.toLowerCase()}%`}`;case"endsWith":return A.sql`LOWER(${e}) LIKE ${`%${t.toLowerCase()}`}`;case"like":return A.sql`${e} LIKE ${t}`;case"notLike":return A.sql`${e} NOT LIKE ${t}`;case"ilike":return A.sql`LOWER(${e}) LIKE ${t.toLowerCase()}`;case"regex":return A.sql`${e} REGEXP ${t}`;case"notRegex":return A.sql`${e} NOT REGEXP ${t}`;default:throw new Error(`Unsupported string operator: ${E}`)}}castToType(e,E){switch(E){case"timestamp":return A.sql`CAST(${e} AS DATETIME)`;case"decimal":return A.sql`CAST(${e} AS DECIMAL(10,2))`;case"integer":return A.sql`CAST(${e} AS SIGNED INTEGER)`;default:throw new Error(`Unsupported cast type: ${E}`)}}buildAvg(e){return A.sql`IFNULL(AVG(${e}), 0)`}buildCaseWhen(e,E){const t=e.map(T=>A.sql`WHEN ${T.when} THEN ${T.then}`).reduce((T,n)=>A.sql`${T} ${n}`);return E!==void 0?A.sql`CASE ${t} ELSE ${E} END`:A.sql`CASE ${t} END`}buildBooleanLiteral(e){return e?A.sql`TRUE`:A.sql`FALSE`}convertFilterValue(e){return e}prepareDateValue(e){return e}isTimestampInteger(){return!1}convertTimeDimensionResult(e){return e}getCapabilities(){return{supportsStddev:!0,supportsVariance:!0,supportsPercentile:!1,supportsWindowFunctions:!0,supportsFrameClause:!0,supportsLateralJoins:!0}}buildStddev(e,E=!1){const t=E?"STDDEV_SAMP":"STDDEV_POP";return A.sql`IFNULL(${A.sql.raw(t)}(${e}), 0)`}buildVariance(e,E=!1){const t=E?"VAR_SAMP":"VAR_POP";return A.sql`IFNULL(${A.sql.raw(t)}(${e}), 0)`}buildPercentile(e,E){return null}buildWindowFunction(e,E,t,T,n){const R=t&&t.length>0?A.sql`PARTITION BY ${A.sql.join(t,A.sql`, `)}`:A.sql``,r=T&&T.length>0?A.sql`ORDER BY ${A.sql.join(T.map(I=>I.direction==="desc"?A.sql`${I.field} DESC`:A.sql`${I.field} ASC`),A.sql`, `)}`:A.sql``;let S=A.sql``;if(n?.frame){const{type:I,start:a,end:o}=n.frame,l=I.toUpperCase(),C=a==="unbounded"?"UNBOUNDED PRECEDING":typeof a=="number"?`${a} PRECEDING`:"CURRENT ROW",u=o==="unbounded"?"UNBOUNDED FOLLOWING":o==="current"?"CURRENT ROW":typeof o=="number"?`${o} FOLLOWING`:"CURRENT ROW";S=A.sql`${A.sql.raw(l)} BETWEEN ${A.sql.raw(C)} AND ${A.sql.raw(u)}`}const i=[];t&&t.length>0&&i.push(R),T&&T.length>0&&i.push(r),n?.frame&&i.push(S);const N=i.length>0?A.sql.join(i,A.sql` `):A.sql``,O=A.sql`OVER (${N})`;switch(e){case"lag":return A.sql`LAG(${E}, ${n?.offset??1}${n?.defaultValue!==void 0?A.sql`, ${n.defaultValue}`:A.sql``}) ${O}`;case"lead":return A.sql`LEAD(${E}, ${n?.offset??1}${n?.defaultValue!==void 0?A.sql`, ${n.defaultValue}`:A.sql``}) ${O}`;case"rank":return A.sql`RANK() ${O}`;case"denseRank":return A.sql`DENSE_RANK() ${O}`;case"rowNumber":return A.sql`ROW_NUMBER() ${O}`;case"ntile":return A.sql`NTILE(${n?.nTile??4}) ${O}`;case"firstValue":return A.sql`FIRST_VALUE(${E}) ${O}`;case"lastValue":return A.sql`LAST_VALUE(${E}) ${O}`;case"movingAvg":return A.sql`AVG(${E}) ${O}`;case"movingSum":return A.sql`SUM(${E}) ${O}`;default:throw new Error(`Unsupported window function: ${e}`)}}}class At extends we{getEngineType(){return"sqlite"}supportsLateralJoins(){return!1}buildIntervalFromISO(e){const E=this.durationToSeconds(e);return A.sql`${E}`}buildTimeDifferenceSeconds(e,E){return A.sql`(${e} - ${E})`}buildDateAddInterval(e,E){const t=this.durationToSeconds(E);return A.sql`(${e} + ${t})`}buildConditionalAggregation(e,E,t){const T=e.toUpperCase();return e==="count"&&!E?A.sql`COUNT(CASE WHEN ${t} THEN 1 END)`:A.sql`${A.sql.raw(T)}(CASE WHEN ${t} THEN ${E} END)`}buildTimeDimension(e,E){switch(e){case"year":return A.sql`datetime(${E}, 'unixepoch', 'start of year')`;case"quarter":{const t=A.sql`datetime(${E}, 'unixepoch')`;return A.sql`datetime(${t}, 'start of year', '+' || (((CAST(strftime('%m', ${t}) AS INTEGER) - 1) / 3) * 3) || ' months')`}case"month":return A.sql`datetime(${E}, 'unixepoch', 'start of month')`;case"week":return A.sql`date(datetime(${E}, 'unixepoch'), 'weekday 1', '-6 days')`;case"day":return A.sql`datetime(${E}, 'unixepoch', 'start of day')`;case"hour":{const t=A.sql`datetime(${E}, 'unixepoch')`;return A.sql`datetime(strftime('%Y-%m-%d %H:00:00', ${t}))`}case"minute":{const t=A.sql`datetime(${E}, 'unixepoch')`;return A.sql`datetime(strftime('%Y-%m-%d %H:%M:00', ${t}))`}case"second":{const t=A.sql`datetime(${E}, 'unixepoch')`;return A.sql`datetime(strftime('%Y-%m-%d %H:%M:%S', ${t}))`}default:return A.sql`datetime(${E}, 'unixepoch')`}}buildStringCondition(e,E,t){switch(E){case"contains":return A.sql`LOWER(${e}) LIKE ${`%${t.toLowerCase()}%`}`;case"notContains":return A.sql`LOWER(${e}) NOT LIKE ${`%${t.toLowerCase()}%`}`;case"startsWith":return A.sql`LOWER(${e}) LIKE ${`${t.toLowerCase()}%`}`;case"endsWith":return A.sql`LOWER(${e}) LIKE ${`%${t.toLowerCase()}`}`;case"like":return A.sql`${e} LIKE ${t}`;case"notLike":return A.sql`${e} NOT LIKE ${t}`;case"ilike":return A.sql`LOWER(${e}) LIKE ${t.toLowerCase()}`;case"regex":return A.sql`${e} GLOB ${t}`;case"notRegex":return A.sql`${e} NOT GLOB ${t}`;default:throw new Error(`Unsupported string operator: ${E}`)}}castToType(e,E){switch(E){case"timestamp":return A.sql`datetime(${e} / 1000, 'unixepoch')`;case"decimal":return A.sql`CAST(${e} AS REAL)`;case"integer":return A.sql`CAST(${e} AS INTEGER)`;default:throw new Error(`Unsupported cast type: ${E}`)}}buildAvg(e){return A.sql`IFNULL(AVG(${e}), 0)`}buildCaseWhen(e,E){const t=e.map(T=>T.then&&typeof T.then=="object"&&(T.then.queryChunks||T.then._||T.then.sql)?A.sql`WHEN ${T.when} THEN ${A.sql.raw("(")}${T.then}${A.sql.raw(")")}`:A.sql`WHEN ${T.when} THEN ${T.then}`).reduce((T,n)=>A.sql`${T} ${n}`);return E!==void 0?E&&typeof E=="object"&&(E.queryChunks||E._||E.sql)?A.sql`CASE ${t} ELSE ${A.sql.raw("(")}${E}${A.sql.raw(")")} END`:A.sql`CASE ${t} ELSE ${E} END`:A.sql`CASE ${t} END`}buildBooleanLiteral(e){return e?A.sql`1`:A.sql`0`}preprocessCalculatedTemplate(e){const E=/(\{[^}]+\})\s*\/\s*/g;return e.replace(E,(t,T)=>`${T.replace(/\{([^}]+)\}/,"CAST({$1} AS REAL)")} / `)}convertFilterValue(e){return typeof e=="boolean"?e?1:0:e instanceof Date?e.getTime():Array.isArray(e)?e.map(E=>this.convertFilterValue(E)):e}prepareDateValue(e){if(!(e instanceof Date)){if(typeof e=="number")return e;if(typeof e=="string")return new Date(e).getTime();throw new Error(`prepareDateValue expects a Date object, got ${typeof e}`)}return e.getTime()}isTimestampInteger(){return!0}convertTimeDimensionResult(e){return e}getCapabilities(){return{supportsStddev:!1,supportsVariance:!1,supportsPercentile:!1,supportsWindowFunctions:!0,supportsFrameClause:!0,supportsLateralJoins:!1}}buildStddev(e,E=!1){return null}buildVariance(e,E=!1){return null}buildPercentile(e,E){return null}buildWindowFunction(e,E,t,T,n){const R=t&&t.length>0?A.sql`PARTITION BY ${A.sql.join(t,A.sql`, `)}`:A.sql``,r=T&&T.length>0?A.sql`ORDER BY ${A.sql.join(T.map(I=>I.direction==="desc"?A.sql`${I.field} DESC`:A.sql`${I.field} ASC`),A.sql`, `)}`:A.sql``;let S=A.sql``;if(n?.frame){const{type:I,start:a,end:o}=n.frame,l=I.toUpperCase(),C=a==="unbounded"?"UNBOUNDED PRECEDING":typeof a=="number"?`${a} PRECEDING`:"CURRENT ROW",u=o==="unbounded"?"UNBOUNDED FOLLOWING":o==="current"?"CURRENT ROW":typeof o=="number"?`${o} FOLLOWING`:"CURRENT ROW";S=A.sql`${A.sql.raw(l)} BETWEEN ${A.sql.raw(C)} AND ${A.sql.raw(u)}`}const i=[];t&&t.length>0&&i.push(R),T&&T.length>0&&i.push(r),n?.frame&&i.push(S);const N=i.length>0?A.sql.join(i,A.sql` `):A.sql``,O=A.sql`OVER (${N})`;switch(e){case"lag":return A.sql`LAG(${E}, ${n?.offset??1}${n?.defaultValue!==void 0?A.sql`, ${n.defaultValue}`:A.sql``}) ${O}`;case"lead":return A.sql`LEAD(${E}, ${n?.offset??1}${n?.defaultValue!==void 0?A.sql`, ${n.defaultValue}`:A.sql``}) ${O}`;case"rank":return A.sql`RANK() ${O}`;case"denseRank":return A.sql`DENSE_RANK() ${O}`;case"rowNumber":return A.sql`ROW_NUMBER() ${O}`;case"ntile":return A.sql`NTILE(${n?.nTile??4}) ${O}`;case"firstValue":return A.sql`FIRST_VALUE(${E}) ${O}`;case"lastValue":return A.sql`LAST_VALUE(${E}) ${O}`;case"movingAvg":return A.sql`AVG(${E}) ${O}`;case"movingSum":return A.sql`SUM(${E}) ${O}`;default:throw new Error(`Unsupported window function: ${e}`)}}}class rt extends GE{getEngineType(){return"singlestore"}}function it(s){switch(s){case"postgres":return new Rt;case"mysql":return new GE;case"sqlite":return new At;case"singlestore":return new rt;default:throw new Error(`Unsupported database engine: ${s}`)}}class ie{constructor(e,E,t){this.db=e,this.schema=E;const T=t||this.getEngineType();this.databaseAdapter=it(T)}databaseAdapter}function St(s,e){const E=[],t=[];let T=!1,n,R,r;const S=[];for(const N of s){const O=N.match(/Planning Time:\s*([\d.]+)\s*ms/i);if(O){n=parseFloat(O[1]);continue}const I=N.match(/Execution Time:\s*([\d.]+)\s*ms/i);if(I){R=parseFloat(I[1]);continue}const a=Nt(N);if(a){a.type.includes("Seq Scan")&&(T=!0),a.index&&t.push(a.index),E.length===0&&a.estimatedCost!==void 0&&(r=a.estimatedCost);const o=N.search(/\S/);for(;S.length>0&&S[S.length-1].indent>=o;)S.pop();if(S.length===0)E.push(a);else{const l=S[S.length-1].op;l.children||(l.children=[]),l.children.push(a)}S.push({indent:o,op:a})}}const i={database:"postgres",planningTime:n,executionTime:R,totalCost:r,hasSequentialScans:T,usedIndexes:[...new Set(t)]};return{operations:E,summary:i,raw:s.join(` `),sql:e}}function Nt(s){const e=s.replace(/^[\s->]+/,"").trim();if(!e)return null;const E=e.match(/^([A-Za-z][A-Za-z0-9 ]+?)(?:\s+using\s+(\S+))?(?:\s+on\s+(\S+))?(?:\s+\w+)?(?:\s+\(cost=([\d.]+)\.\.([\d.]+)\s+rows=(\d+)(?:\s+width=\d+)?\))?(?:\s+\(actual time=([\d.]+)\.\.([\d.]+)\s+rows=(\d+)\s+loops=(\d+)\))?/i);if(!E)return e.match(/^Filter:\s*(.+)$/i)||e.match(/^(Hash Cond|Join Filter|Index Cond):\s*(.+)$/i),null;const t=E[1].trim(),T=E[2]||void 0,n=E[3]||void 0,R=E[5]?parseFloat(E[5]):void 0,r=E[6]?parseInt(E[6],10):void 0,S=E[9]?parseInt(E[9],10):void 0,i={type:t,table:n,index:T,estimatedRows:r,estimatedCost:R};S!==void 0&&(i.actualRows=S);const N=s.match(/Filter:\s*(.+?)(?:\)|$)/i);return N&&(i.filter=N[1].trim()),i}class BE extends ie{async execute(e,E){if(e&&typeof e=="object"&&typeof e.execute=="function"){const T=await e.execute();return Array.isArray(T)?T.map(n=>this.convertNumericFields(n,E)):T}if(!this.db.execute)throw new Error("PostgreSQL database instance must have an execute method");const t=await this.db.execute(e);return Array.isArray(t)?t.map(T=>this.convertNumericFields(T,E)):t}convertNumericFields(e,E){if(!e||typeof e!="object")return e;const t={};for(const[T,n]of Object.entries(e))E&&E.includes(T)?t[T]=this.coerceToNumber(n):t[T]=n;return t}coerceToNumber(e){if(e==null||typeof e=="number")return e;if(typeof e=="bigint")return Number(e);if(e&&typeof e=="object"){if(typeof e.toString=="function"){const E=e.toString();if(/^-?\d+(\.\d+)?$/.test(E))return E.includes(".")?parseFloat(E):parseInt(E,10)}if(e.constructor?.name==="Numeric"||e.constructor?.name==="Decimal"||"digits"in e||"sign"in e){const E=e.toString();return parseFloat(E)}return e}if(typeof e=="string"){if(/^-?\d+(\.\d+)?$/.test(e))return e.includes(".")?parseFloat(e):parseInt(e,10);if(!isNaN(parseFloat(e))&&isFinite(parseFloat(e)))return parseFloat(e)}return e}getEngineType(){return"postgres"}async explainQuery(e,E,t){const T=t?.analyze?"EXPLAIN ANALYZE":"EXPLAIN";if(!this.db.execute)throw new Error("PostgreSQL database instance must have an execute method");const n=await this.db.execute(A.sql`${A.sql.raw(T)} ${A.sql.raw(e.replace(/\$(\d+)/g,(r,S)=>{const i=parseInt(S,10)-1,N=E[i];return N===null?"NULL":typeof N=="number"?String(N):typeof N=="boolean"?N?"TRUE":"FALSE":N instanceof Date?`'${N.toISOString()}'`:`'${String(N).replace(/'/g,"''")}'`}))}`),R=[];if(Array.isArray(n)){for(const r of n)if(r&&typeof r=="object"){const S=r["QUERY PLAN"]||r["query plan"]||r.queryplan;typeof S=="string"&&R.push(S)}}return St(R,{sql:e,params:E})}async getTableIndexes(e){if(!e||e.length===0)return[];if(!this.db.execute)throw new Error("PostgreSQL database instance must have an execute method");try{const E=e.map(T=>`'${T.toLowerCase()}'`).join(","),t=await this.db.execute(A.sql` SELECT t.relname as table_name, i.relname as index_name, array_to_string(array_agg(a.attname ORDER BY k.n), ',') as columns, ix.indisunique as is_unique, ix.indisprimary as is_primary FROM pg_index ix JOIN pg_class t ON t.oid = ix.indrelid JOIN pg_class i ON i.oid = ix.indexrelid JOIN pg_namespace n ON n.oid = t.relnamespace JOIN LATERAL unnest(ix.indkey) WITH ORDINALITY AS k(attnum, n) ON true JOIN pg_attribute a ON a.attrelid = t.oid AND a.attnum = k.attnum WHERE n.nspname = 'public' AND t.relname IN (${A.sql.raw(E)}) GROUP BY t.relname, i.relname, ix.indisunique, ix.indisprimary ORDER BY t.relname, i.relname `);return Array.isArray(t)?t.map(T=>({table_name:T.table_name,index_name:T.index_name,columns:T.columns.split(","),is_unique:T.is_unique,is_primary:T.is_primary})):[]}catch(E){return console.warn("Failed to get table indexes:",E),[]}}}function ge(s,e){return new BE(s,e,"postgres")}function Ot(s,e){const E=e?.toLowerCase()||"";switch(s.toLowerCase()){case"all":return"Seq Scan";case"index":return E.includes("using index")?"Index Only Scan":"Index Scan";case"range":return"Index Range Scan";case"ref":case"eq_ref":return"Index Lookup";case"const":case"system":return"Const Lookup";case"null":return"No Table";default:return`MySQL ${s}`}}function It(s,e){const E=[],t=[];let T=!1,n=0;for(const S of s){const i=Ot(S.type,S.Extra);S.type.toLowerCase()==="all"&&(T=!0),S.key&&t.push(S.key);const N={type:i,table:S.table||void 0,index:S.key||void 0,estimatedRows:S.rows,estimatedCost:S.rows};if(S.Extra){const O=[];S.Extra.includes("Using where")&&O.push("WHERE filter applied"),S.Extra.includes("Using filesort")&&O.push("Filesort required"),S.Extra.includes("Using temporary")&&O.push("Temporary table required"),S.Extra.includes("Using join buffer")&&O.push("Join buffer used"),O.length>0&&(N.details=O.join("; ")),N.filter=S.Extra}E.push(N),n+=S.rows}const R={database:"mysql",planningTime:void 0,executionTime:void 0,totalCost:n,hasSequentialScans:T,usedIndexes:[...new Set(t)]},r=["id select_type table type possible_keys key rows Extra",...s.map(S=>`${S.id} ${S.select_type} ${S.table||"NULL"} ${S.type} ${S.possible_keys||"NULL"} ${S.key||"NULL"} ${S.rows} ${S.Extra||""}`)];return{operations:E,summary:R,raw:r.join(` `),sql:e}}class ve extends ie{async execute(e,E){if(e&&typeof e=="object"&&typeof e.execute=="function"){const T=await e.execute();return Array.isArray(T)?T.map(n=>this.convertNumericFields(n,E)):T}if(!this.db.execute)throw new Error("MySQL database instance must have an execute method");const t=await this.db.execute(e);return Array.isArray(t)?t.map(T=>this.convertNumericFields(T,E)):t}convertNumericFields(e,E){if(!e||typeof e!="object")return e;const t={};for(const[T,n]of Object.entries(e))E&&E.includes(T)?t[T]=this.coerceToNumber(n):t[T]=n;return t}coerceToNumber(e){if(e==null||typeof e=="number")return e;if(typeof e=="string"){if(/^-?\d+(\.\d+)?$/.test(e))return e.includes(".")?parseFloat(e):parseInt(e,10);if(!isNaN(parseFloat(e))&&isFinite(parseFloat(e)))return parseFloat(e)}return e}getEngineType(){return"mysql"}async explainQuery(e,E,t){let T=e,n=0;T=T.replace(/\?/g,()=>{const i=E[n++];return i===null?"NULL":typeof i=="number"?String(i):typeof i=="boolean"?i?"1":"0":i instanceof Date?`'${i.toISOString().slice(0,19).replace("T"," ")}'`:`'${String(i).replace(/'/g,"''")}'`});const R=t?.analyze?"EXPLAIN ANALYZE":"EXPLAIN";if(!this.db.execute)throw new Error("MySQL database instance must have an execute method");const r=await this.db.execute(A.sql.raw(`${R} ${T}`)),S=[];if(Array.isArray(r))for(const i of r)i&&typeof i=="object"&&S.push({id:i.id||1,select_type:i.select_type||"SIMPLE",table:i.table||null,partitions:i.partitions||null,type:i.type||"ALL",possible_keys:i.possible_keys||null,key:i.key||null,key_len:i.key_len||null,ref:i.ref||null,rows:Number(i.rows)||0,filtered:Number(i.filtered)||100,Extra:i.Extra||null});return It(S,{sql:e,params:E})}async getTableIndexes(e){if(!e||e.length===0)return[];if(!this.db.execute)throw new Error("MySQL database instance must have an execute method");try{const E=e.map(T=>`'${T.toLowerCase()}'`).join(","),t=await this.db.execute(A.sql` SELECT TABLE_NAME as table_name, INDEX_NAME as index_name, GROUP_CONCAT(COLUMN_NAME ORDER BY SEQ_IN_INDEX) as columns, CASE WHEN NON_UNIQUE = 0 THEN TRUE ELSE FALSE END as is_unique, CASE WHEN INDEX_NAME = 'PRIMARY' THEN TRUE ELSE FALSE END as is_primary FROM INFORMATION_SCHEMA.STATISTICS WHERE TABLE_SCHEMA = DATABASE() AND LOWER(TABLE_NAME) IN (${A.sql.raw(E)}) GROUP BY TABLE_NAME, INDEX_NAME, NON_UNIQUE ORDER BY TABLE_NAME, INDEX_NAME `);return Array.isArray(t)?t.map(T=>({table_name:T.table_name,index_name:T.index_name,columns:T.columns.split(","),is_unique:!!T.is_unique,is_primary:!!T.is_primary})):[]}catch(E){return console.warn("Failed to get table indexes:",E),[]}}}function FE(s,e){return new ve(s,e,"mysql")}function at(s){const e=s.toLowerCase(),E=s.match(/^SCAN\s+(\S+)/i);if(E)return{type:"Seq Scan",table:E[1]};const t=s.match(/^SEARCH\s+(\S+)\s+USING\s+(?:COVERING\s+)?INDEX\s+(\S+)(?:\s+\((.+)\))?/i);if(t)return{type:"Index Scan",table:t[1],index:t[2],filter:t[3]};const T=s.match(/^SEARCH\s+(\S+)\s+USING\s+INTEGER\s+PRIMARY\s+KEY\s+\((.+)\)/i);if(T)return{type:"Primary Key Lookup",table:T[1],filter:T[2]};const n=s.match(/^SEARCH\s+(\S+)/i);return n?{type:"Search",table:n[1]}:e.includes("temp b-tree")?e.includes("order by")?{type:"Sort"}:e.includes("group by")?{type:"Group"}:e.includes("distinct")?{type:"Distinct"}:{type:"Temp B-Tree"}:e.includes("compound")?{type:"Compound Query"}:e.includes("subquery")?{type:"Subquery"}:e.includes("co-routine")?{type:"Coroutine"}:{type:s}}function ot(s,e){const E=[],t=[];let T=!1;const n=new Map;for(const S of s){const i=at(S.detail);i.type==="Seq Scan"&&(T=!0),i.index&&t.push(i.index);const N={type:i.type,table:i.table,index:i.index,filter:i.filter,details:S.detail};if(n.set(S.id,N),S.parent===0)E.push(N);else{const O=n.get(S.parent);O?(O.children||(O.children=[]),O.children.push(N)):E.push(N)}}const R={database:"sqlite",planningTime:void 0,executionTime:void 0,totalCost:void 0,hasSequentialScans:T,usedIndexes:[...new Set(t)]},r=["id parent detail",...s.map(S=>`${S.id} ${S.parent} ${S.detail}`)];return{operations:E,summary:R,raw:r.join(` `),sql:e}}class HE extends ie{async execute(e,E){if(e&&typeof e=="object"&&typeof e.execute=="function"){const t=await e.execute();return Array.isArray(t)?t.map(T=>this.convertNumericFields(T,E)):t}try{if(this.db.all){const t=this.db.all(e);return Array.isArray(t)?t.map(T=>this.convertNumericFields(T,E)):t}else{if(this.db.run)return this.db.run(e);throw new Error("SQLite database instance must have an all() or run() method")}}catch(t){throw new Error(`SQLite execution failed: ${t instanceof Error?t.message:"Unknown error"}`)}}convertNumericFields(e,E){if(!e||typeof e!="object")return e;const t={};for(const[T,n]of Object.entries(e))E&&E.includes(T)?t[T]=this.coerceToNumber(n):t[T]=n;return t}coerceToNumber(e){if(e==null||typeof e=="number")return e;if(typeof e=="string"){if(/^-?\d+(\.\d+)?$/.test(e))return e.includes(".")?parseFloat(e):parseInt(e,10);if(!isNaN(parseFloat(e))&&isFinite(parseFloat(e)))return parseFloat(e)}return e}getEngineType(){return"sqlite"}async explainQuery(e,E,t){let T=e,n=0;T=T.replace(/\?/g,()=>{const i=E[n++];return i===null?"NULL":typeof i=="number"?String(i):typeof i=="boolean"?i?"1":"0":i instanceof Date?`'${i.toISOString()}'`:`'${String(i).replace(/'/g,"''")}'`});const R=`EXPLAIN QUERY PLAN ${T}`;let r=[];if(this.db.all)r=this.db.all(A.sql.raw(R));else throw new Error("SQLite database instance must have an all() method for EXPLAIN");const S=[];if(Array.isArray(r))for(const i of r)i&&typeof i=="object"&&S.push({id:Number(i.id)||0,parent:Number(i.parent)||0,notused:Number(i.notused)||0,detail:String(i.detail||"")});return ot(S,{sql:e,params:E})}async getTableIndexes(e){if(!e||e.length===0)return[];if(!this.db.all)throw new Error("SQLite database instance must have an all() method");try{const E=[];for(const t of e){const T=this.db.all(A.sql.raw(`SELECT name, "unique", origin FROM pragma_index_list('${t.toLowerCase()}')`));if(Array.isArray(T))for(const n of T){const R=n.name,r=!!n.unique,S=n.origin,i=this.db.all(A.sql.raw(`SELECT name FROM pragma_index_info('${R}') ORDER BY seqno`)),N=[];if(Array.isArray(i))for(const O of i){const I=O.name;typeof I=="string"&&N.push(I)}E.push({table_name:t.toLowerCase(),index_name:R,columns:N,is_unique:r,is_primary:S==="pk"})}}return E}catch(E){return console.warn("Failed to get table indexes:",E),[]}}}function Ye(s,e){return new HE(s,e,"sqlite")}class Ct extends ve{getEngineType(){return"singlestore"}}function _t(s,e){return new Ct(s,e)}function ye(s,e,E){if(E)switch(E){case"postgres":return ge(s,e);case"mysql":return FE(s,e);case"sqlite":return Ye(s,e);case"singlestore":return _t(s,e)}if(s.all&&s.run)return Ye(s,e);if(s.execute)return ge(s,e);throw new Error("Unable to determine database engine type. Please specify engineType parameter.")}function k(s){return typeof s=="function"?s():s}function ne(s,e){if(e)return e;switch(s){case"belongsTo":return"inner";case"hasOne":return"left";case"hasMany":return"left";case"belongsToMany":return"left";default:return"left"}}function Ve(s){return s&&typeof s=="object"?A.sql`${A.sql`${s}`}`:s}function f(s,e){const E=typeof s=="function"?s(e):s;return Ve(E)}function Lt(s,e,E){return{...s,cubes:e,currentCube:E}}function lt(s,e){return{name:s,...e}}function ut(s,e){if(s.relationship!=="belongsToMany"||!s.through)throw new Error("expandBelongsToManyJoin can only be called on belongsToMany relationships with through configuration");const{table:E,sourceKey:t,targetKey:T,securitySql:n}=s.through,R=[];for(const N of t){const O=N.as||A.eq;R.push(O(N.source,N.target))}const r=[];for(const N of T){const O=N.as||A.eq;r.push(O(N.source,N.target))}let S;if(n){const N=n(e);S=Array.isArray(N)?N:[N]}const i=ne("belongsToMany",s.sqlJoinType);return{junctionJoins:[{joinType:i,table:E,condition:A.and(...R)},{joinType:i,table:E,condition:A.and(...r)}],junctionSecurityConditions:S}}function Re(s){if("and"in s)return`and:[${s.and.map(Re).sort().join(",")}]`;if("or"in s)return`or:[${s.or.map(Re).sort().join(",")}]`;const e=s,E=JSON.stringify(Array.isArray(e.values)?[...e.values].sort():e.values),t=e.dateRange?`:dr:${JSON.stringify(e.dateRange)}`:"";return`${e.member}:${e.operator}:${E}${t}`}function bE(s,e){return`timeDim:${s}:${JSON.stringify(e)}`}class je{cache=new Map;stats={hits:0,misses:0};getOrBuild(e,E){const t=this.cache.get(e);if(t!==void 0)return this.stats.hits++,t;const T=E();return T&&this.cache.set(e,T),this.stats.misses++,T}has(e){return this.cache.has(e)}get(e){const E=this.cache.get(e);return E!==void 0&&this.stats.hits++,E}preload(e){for(const{key:E,sql:t}of e)this.cache.has(E)||this.cache.set(E,t)}set(e,E){this.cache.set(e,E)}getStats(){return{...this.stats,cacheSize:this.cache.size}}clear(){this.cache.clear(),this.stats={hits:0,misses:0}}}function We(s){const e=[];for(const E of s)"and"in E&&E.and?e.push(...We(E.and)):"or"in E&&E.or?e.push(...We(E.or)):"member"in E&&e.push(E);return e}function gE(s,e,E={}){const t=E.keyPrefix??"drizzle-cube:",T=YE(s),n=$e(JSON.stringify(T));let R=`${t}query:${n}`;if(E.includeSecurityContext!==!1){const r=E.securityContextSerializer?E.securityContextSerializer(e):JSON.stringify(Ae(e)),S=$e(r);R+=`:ctx:${S}`}return R}function YE(s){return{measures:s.measures?[...s.measures].sort():void 0,dimensions:s.dimensions?[...s.dimensions].sort():void 0,filters:s.filters?X(s.filters):void 0,timeDimensions:s.timeDimensions?Pt(s.timeDimensions):void 0,limit:s.limit,offset:s.offset,order:s.order?Ae(s.order):void 0,fillMissingDatesValue:s.fillMissingDatesValue,funnel:s.funnel?ct(s.funnel):void 0,flow:s.flow?Dt(s.flow):void 0}}function ct(s){return{bindingKey:s.bindingKey,timeDimension:s.timeDimension,steps:s.steps.map(e=>{const E={name:e.name,filter:e.filter?Array.isArray(e.filter)?X(e.filter):X([e.filter])[0]:void 0,timeToConvert:e.timeToConvert};return"cube"in e&&e.cube&&(E.cube=e.cube),E}),includeTimeMetrics:s.includeTimeMetrics,globalTimeWindow:s.globalTimeWindow}}function Dt(s){return{bindingKey:s.bindingKey,timeDimension:s.timeDimension,eventDimension:s.eventDimension,startingStep:{name:s.startingStep.name,filter:s.startingStep.filter?Array.isArray(s.startingStep.filter)?X(s.startingStep.filter):X([s.startingStep.filter])[0]:void 0},stepsBefore:s.stepsBefore,stepsAfter:s.stepsAfter,entityLimit:s.entityLimit,outputMode:s.outputMode,joinStrategy:s.joinStrategy}}function X(s){return[...s].map(e=>{if("and"in e&&e.and)return{and:X(e.and)};if("or"in e&&e.or)return{or:X(e.or)};const E=e;return{...E,values:E.values?[...E.values].sort():E.values}}).sort((e,E)=>JSON.stringify(e).localeCompare(JSON.stringify(E)))}function Pt(s){return[...s].map(e=>({dimension:e.dimension,granularity:e.granularity,dateRange:e.dateRange,fillMissingDates:e.fillMissingDates,compareDateRange:e.compareDateRange?[...e.compareDateRange].sort((E,t)=>{const T=Array.isArray(E)?E.join("-"):E,n=Array.isArray(t)?t.join("-"):t;return T.localeCompare(n)}):void 0})).sort((e,E)=>e.dimension.localeCompare(E.dimension))}function Ae(s){return s===null||typeof s!="object"?s:Array.isArray(s)?s.map(Ae):Object.keys(s).sort().reduce((e,E)=>(e[E]=Ae(s[E]),e),{})}function $e(s){let e=2166136261;for(let E=0;E<s.length;E++)e^=s.charCodeAt(E),e=e*16777619>>>0;return e.toString(16).padStart(8,"0")}function dt(s,e){return`${e??"drizzle-cube:"}*${s}*`}class Se{constructor(e){this.databaseAdapter=e}buildTimeDimensionExpression(e,E,t){const T=f(e,t);return E?this.databaseAdapter.buildTimeDimension(E,T):T instanceof A.SQL?T:A.sql`${T}`}buildDateRangeCondition(e,E){if(!E)return null;if(Array.isArray(E)&&E.length>=2){const t=this.normalizeDate(E[0]);let T=this.normalizeDate(E[1]);if(!t||!T)return null;if(typeof E[1]=="string"&&/^\d{4}-\d{2}-\d{2}$/.test(E[1].trim())){const n=typeof T=="number"?new Date(T*(this.databaseAdapter.getEngineType()==="sqlite"?1e3:1)):new Date(T),R=new Date(n);R.setUTCHours(23,59,59,999),this.databaseAdapter.isTimestampInteger()?T=this.databaseAdapter.getEngineType()==="sqlite"?Math.floor(R.getTime()/1e3):R.getTime():T=R.toISOString()}return A.and(A.gte(e,t),A.lte(e,T))}if(typeof E=="string"){const t=this.parseRelativeDateRange(E);if(t){let N,O;return this.databaseAdapter.isTimestampInteger()?this.databaseAdapter.getEngineType()==="sqlite"?(N=Math.floor(t.start.getTime()/1e3),O=Math.floor(t.end.getTime()/1e3)):(N=t.start.getTime(),O=t.end.getTime()):(N=t.start.toISOString(),O=t.end.toISOString()),A.and(A.gte(e,N),A.lte(e,O))}const T=this.normalizeDate(E);if(!T)return null;const n=typeof T=="number"?new Date(T*(this.databaseAdapter.getEngineType()==="sqlite"?1e3:1)):new Date(T),R=new Date(n);R.setUTCHours(0,0,0,0);const r=new Date(n);r.setUTCHours(23,59,59,999);let S,i;return this.databaseAdapter.isTimestampInteger()?this.databaseAdapter.getEngineType()==="sqlite"?(S=Math.floor(R.getTime()/1e3),i=Math.floor(r.getTime()/1e3)):(S=R.getTime(),i=r.getTime()):(S=R.toISOString(),i=r.toISOString()),A.and(A.gte(e,S),A.lte(e,i))}return null}parseRelativeDateRange(e){const E=new Date,t=e.toLowerCase().trim(),T=E.getUTCFullYear(),n=E.getUTCMonth(),R=E.getUTCDate(),r=E.getUTCDay();if(t==="today"){const I=new Date(E);I.setUTCHours(0,0,0,0);const a=new Date(E);return a.setUTCHours(23,59,59,999),{start:I,end:a}}if(t==="yesterday"){const I=new Date(E);I.setUTCDate(R-1),I.setUTCHours(0,0,0,0);const a=new Date(E);return a.setUTCDate(R-1),a.setUTCHours(23,59,59,999),{start:I,end:a}}if(t==="this week"){const I=r===0?-6:1-r,a=new Date(E);a.setUTCDate(R+I),a.setUTCHours(0,0,0,0);const o=new Date(a);return o.setUTCDate(a.getUTCDate()+6),o.setUTCHours(23,59,59,999),{start:a,end:o}}if(t==="this month"){const I=new Date(Date.UTC(T,n,1,0,0,0,0)),a=new Date(Date.UTC(T,n+1,0,23,59,59,999));return{start:I,end:a}}if(t==="this quarter"){const I=Math.floor(n/3),a=new Date(Date.UTC(T,I*3,1,0,0,0,0)),o=new Date(Date.UTC(T,I*3+3,0,23,59,59,999));return{start:a,end:o}}if(t==="this year"){const I=new Date(Date.UTC(T,0,1,0,0,0,0)),a=new Date(Date.UTC(T,11,31,23,59,59,999));return{start:I,end:a}}const S=t.match(/^last\s+(\d+)\s+days?$/);if(S){const I=parseInt(S[1],10),a=new Date(E);a.setUTCDate(R-I+1),a.setUTCHours(0,0,0,0);const o=new Date(E);return o.setUTCHours(23,59,59,999),{start:a,end:o}}const i=t.match(/^last\s+(\d+)\s+weeks?$/);if(i){const a=parseInt(i[1],10)*7,o=new Date(E);o.setUTCDate(R-a+1),o.setUTCHours(0,0,0,0);const l=new Date(E);return l.setUTCHours(23,59,59,999),{start:o,end:l}}if(t==="last week"){const I=r===0?-13:-6-r,a=new Date(E);a.setUTCDate(R+I),a.setUTCHours(0,0,0,0);const o=new Date(a);return o.setUTCDate(a.getUTCDate()+6),o.setUTCHours(23,59,59,999),{start:a,end:o}}if(t==="last month"){const I=new Date(Date.UTC(T,n-1,1,0,0,0,0)),a=new Date(Date.UTC(T,n,0,23,59,59,999));return{start:I,end:a}}if(t==="last quarter"){const I=Math.floor(n/3),a=I===0?3:I-1,o=I===0?T-1:T,l=new Date(Date.UTC(o,a*3,1,0,0,0,0)),C=new Date(Date.UTC(o,a*3+3,0,23,59,59,999));return{start:l,end:C}}if(t==="last year"){const I=new Date(Date.UTC(T-1,0,1,0,0,0,0)),a=new Date(Date.UTC(T-1,11,31,23,59,59,999));return{start:I,end:a}}if(t==="last 12 months"){const I=new Date(Date.UTC(T,n-11,1,0,0,0,0)),a=new Date(E);return a.setUTCHours(23,59,59,999),{start:I,end:a}}const N=t.match(/^last\s+(\d+)\s+months?$/);if(N){const I=parseInt(N[1],10),a=new Date(Date.UTC(T,n-I+1,1,0,0,0,0)),o=new Date(E);return o.setUTCHours(23,59,59,999),{start:a,end:o}}const O=t.match(/^last\s+(\d+)\s+years?$/);if(O){const I=parseInt(O[1],10),a=new Date(Date.UTC(T-I,0,1,0,0,0,0)),o=new Date(E);return o.setUTCHours(23,59,59,999),{start:a,end:o}}return null}normalizeDate(e){if(!e)return null;if(e instanceof Date)return isNaN(e.getTime())?null:this.databaseAdapter.isTimestampInteger()?this.databaseAdapter.getEngineType()==="sqlite"?Math.floor(e.getTime()/1e3):e.getTime():e.toISOString();if(typeof e=="number"){const t=e<1e10?e*1e3:e,T=new Date(t);return isNaN(T.getTime())?null:this.databaseAdapter.isTimestampInteger()?this.databaseAdapter.getEngineType()==="sqlite"?Math.floor(t/1e3):t:T.toISOString()}if(typeof e=="string"){if(/^\d{4}-\d{2}-\d{2}$/.test(e.trim())){const T=new Date(e+"T00:00:00Z");return isNaN(T.getTime())?null:this.databaseAdapter.isTimestampInteger()?this.databaseAdapter.getEngineType()==="sqlite"?Math.floor(T.getTime()/1e3):T.getTime():T.toISOString()}const t=new Date(e);return isNaN(t.getTime())?null:this.databaseAdapter.isTimestampInteger()?this.databaseAdapter.getEngineType()==="sqlite"?Math.floor(t.getTime()/1e3):t.getTime():t.toISOString()}const E=new Date(e);return isNaN(E.getTime())?null:this.databaseAdapter.isTimestampInteger()?this.databaseAdapter.getEngineType()==="sqlite"?Math.floor(E.getTime()/1e3):E.getTime():E.toISOString()}}class Ke{constructor(e,E){this.databaseAdapter=e,this.dateTimeBuilder=E}buildFilterCondition(e,E,t,T,n){if(n!==void 0){if(E!=="inDateRange")throw new Error(`dateRange can only be used with 'inDateRange' operator, but got '${E}'. Use explicit date values in the 'values' array for other date operators.`);if(T&&T.type!=="time")throw new Error(`dateRange can only be used on time dimensions, but field '${T.name||"unknown"}' has type '${T.type}'`);return this.dateTimeBuilder.buildDateRangeCondition(e,n)}if(!t||t.length===0)return E==="equals"?this.databaseAdapter.buildBooleanLiteral(!1):null;const R=t.filter(S=>!(S==null||S===""||typeof S=="string"&&S.includes("\0"))).map(this.databaseAdapter.convertFilterValue);if(R.length===0&&!["set","notSet"].includes(E))return E==="equals"?this.databaseAdapter.buildBooleanLiteral(!1):null;const r=R[0];switch(E){case"equals":if(R.length>1){if(T?.type==="time"){const S=R.map(i=>this.dateTimeBuilder.normalizeDate(i)||i);return A.inArray(e,S)}return A.inArray(e,R)}else if(R.length===1){const S=T?.type==="time"&&this.dateTimeBuilder.normalizeDate(r)||r;return A.eq(e,S)}return this.databaseAdapter.buildBooleanLiteral(!1);case"notEquals":return R.length>1?A.notInArray(e,R):R.length===1?A.ne(e,r):null;case"contains":return this.databaseAdapter.buildStringCondition(e,"contains",r);case"notContains":return this.databaseAdapter.buildStringCondition(e,"notContains",r);case"startsWith":return this.databaseAdapter.buildStringCondition(e,"startsWith",r);case"endsWith":return this.databaseAdapter.buildStringCondition(e,"endsWith",r);case"gt":return A.gt(e,r);case"gte":return A.gte(e,r);case"lt":return A.lt(e,r);case"lte":return A.lte(e,r);case"set":return A.isNotNull(e);case"notSet":return A.isNull(e);case"inDateRange":if(R.length>=2){const S=this.dateTimeBuilder.normalizeDate(R[0]);let i=this.dateTimeBuilder.normalizeDate(R[1]);if(S&&i){const N=t[1];if(typeof N=="string"&&/^\d{4}-\d{2}-\d{2}$/.test(N.trim())){const O=typeof i=="number"?new Date(i*(this.databaseAdapter.getEngineType()==="sqlite"?1e3:1)):new Date(i),I=new Date(O);I.setUTCHours(23,59,59,999),this.databaseAdapter.isTimestampInteger()?i=this.databaseAdapter.getEngineType()==="sqlite"?Math.floor(I.getTime()/1e3):I.getTime():i=I.toISOString()}return A.and(A.gte(e,S),A.lte(e,i))}}return null;case"beforeDate":{const S=this.dateTimeBuilder.normalizeDate(r);return S?A.lt(e,S):null}case"afterDate":{const S=this.dateTimeBuilder.normalizeDate(r);return S?A.gt(e,S):null}case"between":return R.length>=2?A.and(A.gte(e,R[0]),A.lte(e,R[1])):null;case"notBetween":return R.length>=2?A.or(A.lt(e,R[0]),A.gt(e,R[1])):null;case"in":return R.length>0?A.inArray(e,R):null;case"notIn":return R.length>0?A.notInArray(e,R):null;case"like":return this.databaseAdapter.buildStringCondition(e,"like",r);case"notLike":return this.databaseAdapter.buildStringCondition(e,"notLike",r);case"ilike":return this.databaseAdapter.buildStringCondition(e,"ilike",r);case"regex":return this.databaseAdapter.buildStringCondition(e,"regex",r);case"notRegex":return this.databaseAdapter.buildStringCondition(e,"notRegex",r);case"isEmpty":return A.or(A.isNull(e),A.eq(e,""));case"isNotEmpty":return A.and(A.isNotNull(e),A.ne(e,""));case"arrayContains":return this.databaseAdapter.getEngineType()==="postgres"?A.arrayContains(e,R):null;case"arrayOverlaps":return this.databaseAdapter.getEngineType()==="postgres"?A.arrayOverlaps(e,R):null;case"arrayContained":return this.databaseAdapter.getEngineType()==="postgres"?A.arrayContained(e,R):null;default:return null}}buildLogicalFilter(e,E,t){if("and"in e&&e.and){const T=e.and.map(n=>this.buildSingleFilter(n,E,t)).filter(n=>n!==null);return T.length>0?T.length===1?T[0]:A.and(...T):null}if("or"in e&&e.or){const T=e.or.map(n=>this.buildSingleFilter(n,E,t)).filter(n=>n!==null);return T.length>0?T.length===1?T[0]:A.or(...T):null}return null}buildSingleFilter(e,E,t){if("and"in e||"or"in e)return this.buildLogicalFilter(e,E,t);const T=e,[n,R]=T.member.split("."),r=E.get(n);if(!r)return null;const S=r.dimensions?.[R];if(!S)return null;const i=f(S.sql,t);return this.buildFilterCondition(i,T.operator,T.values,S,T.dateRange)}}class ${dependencyGraph;cubes;constructor(e){this.cubes=e instanceof Map?e:new Map([[e.name,e]]),this.dependencyGraph=new Map}extractDependencies(e){const E=/\{([^}]+)\}/g,t=e.matchAll(E),T=[];for(const n of t){const R=n[1].trim();if(R.includes(".")){const[r,S]=R.split(".");T.push({measureName:R,cubeName:r.trim(),fieldName:S.trim()})}else T.push({measureName:R,cubeName:null,fieldName:R})}return T}buildGraph(e){for(const[E,t]of Object.entries(e.measures))if(t.type==="calculated"&&t.calculatedSql){const T=`${e.name}.${E}`,n=this.extractDependencies(t.calculatedSql),R=new Set;for(const r of n){const i=`${r.cubeName||e.name}.${r.fieldName}`;R.add(i)}this.dependencyGraph.set(T,{id:T,dependencies:R,inDegree:0})}this.calculateInDegrees()}buildGraphForMultipleCubes(e){for(const E of e.values())this.buildGraph(E)}calculateInDegrees(){for(const e of this.dependencyGraph.values())e.inDegree=0;for(const e of this.dependencyGraph.values())for(const E of e.dependencies){const t=this.dependencyGraph.get(E);t&&t.inDegree++}}topologicalSort(e){const E=new Map,t=[],T=[];for(const n of e){const R=this.dependencyGraph.get(n);R&&E.set(n,{id:R.id,dependencies:new Set(R.dependencies),inDegree:0})}for(const n of E.values()){let R=0;for(const r of n.dependencies)E.has(r)&&R++;n.inDegree=R}for(const[n,R]of E)R.inDegree===0&&t.push(n);for(;t.length>0;){const n=t.shift();T.push(n);for(const[R,r]of E)r.dependencies.has(n)&&(r.inDegree--,r.inDegree===0&&t.push(R))}if(T.length<E.size){const n=this.detectCycle();throw new Error(`Circular dependency detected in calculated measures: ${n?n.join(" -> "):"unknown cycle"}`)}return T}detectCycle(){const e=new Set,E=new Set,t=[];for(const T of this.dependencyGraph.keys())if(!e.has(T)){const n=this.dfs(T,e,E,t);if(n)return n}return null}dfs(e,E,t,T){E.add(e),t.add(e),T.push(e);const n=this.dependencyGraph.get(e);if(!n)return T.pop(),t.delete(e),null;for(const R of n.dependencies)if(E.has(R)){if(t.has(R)){const r=T.indexOf(R);return[...T.slice(r),R]}}else{const r=this.dfs(R,E,t,T);if(r)return r}return T.pop(),t.delete(e),null}getAllDependencies(e){const E=new Set,t=new Set,T=n=>{if(t.has(n))return;t.add(n);const R=this.dependencyGraph.get(n);if(R)for(const r of R.dependencies)E.add(r),T(r)};return T(e),E}validateDependencies(e){for(const[E,t]of Object.entries(e.measures))if(t.type==="calculated"&&t.calculatedSql){const T=this.extractDependencies(t.calculatedSql);for(const n of T){const R=n.cubeName||e.name,r=this.cubes.get(R);if(!r)throw new Error(`Calculated measure '${e.name}.${E}' references unknown cube '${R}'`);if(!r.measures[n.fieldName])throw new Error(`Calculated measure '${e.name}.${E}' references unknown measure '${n.measureName}'`);if(R===e.name&&n.fieldName===E)throw new Error(`Calculated measure '${e.name}.${E}' cannot reference itself`)}}}populateDependencies(e){for(const[,E]of Object.entries(e.measures))if(E.type==="calculated"&&E.calculatedSql&&!E.dependencies){const t=this.extractDependencies(E.calculatedSql);E.dependencies=t.map(T=>T.measureName)}}static isCalculatedMeasure(e){return e.type==="calculated"&&!!e.calculatedSql}}function Mt(s,e){const{cube:E,allCubes:t,resolvedMeasures:T}=e,n=xe(s),R=new Map;for(const O of n){const{originalRef:I,cubeName:a,fieldName:o}=O,l=a||E.name;if(!t.get(l))throw new Error(`Cannot substitute {${I}}: cube '${l}' not found`);const u=`${l}.${o}`,L=T.get(u);if(!L)throw new Error(`Cannot substitute {${I}}: measure '${u}' not resolved yet. Ensure measures are resolved in dependency order.`);const d=L(),P=A.sql`${d}`;R.set(I,P)}const r=[],S=[];let i=0;for(const O of n){const I=`{${O.originalRef}}`,a=s.indexOf(I,i);if(a>=0){r.push(s.substring(i,a));const o=R.get(O.originalRef);o&&S.push(o),i=a+I.length}}if(r.push(s.substring(i)),S.length===0)return A.sql.raw(s);const N=[];for(let O=0;O<r.length;O++)r[O]&&N.push(new A.StringChunk(r[O])),O<S.length&&N.push(S[O]);return A.sql.join(N,A.sql.raw(""))}function xe(s){const e=/\{([^}]+)\}/g,E=s.matchAll(e),t=[];for(const T of E){const n=T[1].trim();if(n.includes(".")){const[R,r]=n.split(".").map(S=>S.trim());t.push({originalRef:n,cubeName:R,fieldName:r})}else t.push({originalRef:n,cubeName:null,fieldName:n})}return t}function Ut(s){const e=[];let E=0;for(let R=0;R<s.length;R++)if(s[R]==="{")E++;else if(s[R]==="}"&&(E--,E<0)){e.push(`Unmatched closing brace at position ${R}`);break}E>0&&e.push("Unmatched opening brace in template"),/\{\s*\}/.test(s)&&e.push("Empty member reference {} found in template"),/\{[^}]*\{/.test(s)&&e.push("Nested braces are not allowed in member references");const n=xe(s);for(const R of n){const r=R.cubeName?`${R.cubeName}.${R.fieldName}`:R.fieldName;/^[a-zA-Z_][a-zA-Z0-9_.]*$/.test(r)||e.push(`Invalid member reference {${R.originalRef}}: must start with letter or underscore, and contain only letters, numbers, underscores, and dots`),r.split(".").length>2&&e.push(`Invalid member reference {${R.originalRef}}: only one dot allowed (Cube.measure format)`)}return{isValid:e.length===0,errors:e}}function Ie(s,e){const E=xe(s),t=new Set;for(const T of E){const R=`${T.cubeName||e}.${T.fieldName}`;t.add(R)}return Array.from(t)}class G{constructor(e){this.databaseAdapter=e}buildResolvedMeasures(e,E,t,T){const n=new Map,R=[],r=[],S=new Set(e),i=new $(E);for(const N of E.values())i.buildGraph(N);for(const N of e){const[O,I]=N.split("."),a=E.get(O);if(a&&a.measures&&a.measures[I]){const o=a.measures[I];if(G.isPostAggregationWindow(o)){const l=G.getWindowBaseMeasure(o,O);l&&S.add(l);continue}$.isCalculatedMeasure(o)?(r.push(N),Ie(o.calculatedSql,O).forEach(u=>S.add(u)),i.getAllDependencies(N).forEach(u=>{const[L,d]=u.split("."),P=E.get(L);if(P&&P.measures[d]){const U=P.measures[d];$.isCalculatedMeasure(U)&&Ie(U.calculatedSql,L).forEach(h=>S.add(h))}})):R.push(N)}}for(const N of S){const[O,I]=N.split("."),a=E.get(O);if(a&&a.measures&&a.measures[I]){const o=a.measures[I];if(G.isPostAggregationWindow(o))continue;$.isCalculatedMeasure(o)?r.includes(N)||r.push(N):R.includes(N)||R.push(N)}}for(const N of R){const[O,I]=N.split("."),a=E.get(O),o=a.measures[I];if(T){const l=T(N,o,a);n.set(N,()=>l)}else n.set(N,()=>this.buildMeasureExpression(o,t,a))}if(r.length>0){const N=i.topologicalSort(r);for(const O of N){const[I,a]=O.split("."),o=E.get(I),l=o.measures[a];n.set(O,()=>this.buildCalculatedMeasure(l,o,E,n,t))}}return n}buildCalculatedMeasure(e,E,t,T,n){if(!e.calculatedSql)throw new Error(`Calculated measure '${E.name}.${e.name}' missing calculatedSql property`);const R=this.databaseAdapter.preprocessCalculatedTemplate(e.calculatedSql);return Mt(R,{cube:E,allCubes:t,resolvedMeasures:T})}buildCTECalculatedMeasure(e,E,t,T,n){if(!e.calculatedSql)throw new Error(`Calculated measure '${E.name}.${e.name||"unknown"}' missing calculatedSql property`);const R=new Map,r=Ie(e.calculatedSql,E.name);for(const S of r){const[i,N]=S.split("."),O=T.get(i);if(O&&O.measures[N]){const I=O.measures[N];if(t.measures.includes(S)){const a=A.sql`${A.sql.identifier(t.cteAlias)}.${A.sql.identifier(N)}`;let o;switch(I.type){case"count":case"countDistinct":case"sum":o=A.sum(a);break;case"avg":o=this.databaseAdapter.buildAvg(a);break;case"min":o=A.min(a);break;case"max":o=A.max(a);break;case"number":o=A.sum(a);break;default:o=A.sum(a)}R.set(S,()=>o)}}}return this.buildCalculatedMeasure(e,E,T,R,n)}buildHavingMeasureExpression(e,E,t,T,n){if(n&&n.preAggregationCTEs){const R=n.preAggregationCTEs.find(r=>r.cube.name===e);if(R&&R.measures.includes(`${e}.${E}`))if(t.type==="calculated"&&t.calculatedSql){const r=n.primaryCube.name===e?n.primaryCube:n.joinCubes?.fin