UNPKG

drizzle-cube

Version:

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

2 lines 345 kB
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const S=require("drizzle-orm");class yE{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}}}class ze extends yE{getEngineType(){return"postgres"}buildTimeDimension(E,e){switch(E){case"year":return S.sql`DATE_TRUNC('year', ${e}::timestamp)`;case"quarter":return S.sql`DATE_TRUNC('quarter', ${e}::timestamp)`;case"month":return S.sql`DATE_TRUNC('month', ${e}::timestamp)`;case"week":return S.sql`DATE_TRUNC('week', ${e}::timestamp)`;case"day":return S.sql`DATE_TRUNC('day', ${e}::timestamp)::timestamp`;case"hour":return S.sql`DATE_TRUNC('hour', ${e}::timestamp)`;case"minute":return S.sql`DATE_TRUNC('minute', ${e}::timestamp)`;case"second":return S.sql`DATE_TRUNC('second', ${e}::timestamp)`;default:return e}}buildStringCondition(E,e,R){switch(e){case"contains":return S.sql`${E} ILIKE ${`%${R}%`}`;case"notContains":return S.sql`${E} NOT ILIKE ${`%${R}%`}`;case"startsWith":return S.sql`${E} ILIKE ${`${R}%`}`;case"endsWith":return S.sql`${E} ILIKE ${`%${R}`}`;case"like":return S.sql`${E} LIKE ${R}`;case"notLike":return S.sql`${E} NOT LIKE ${R}`;case"ilike":return S.sql`${E} ILIKE ${R}`;case"regex":return S.sql`${E} ~* ${R}`;case"notRegex":return S.sql`${E} !~* ${R}`;default:throw new Error(`Unsupported string operator: ${e}`)}}castToType(E,e){switch(e){case"timestamp":return S.sql`${E}::timestamp`;case"decimal":return S.sql`${E}::decimal`;case"integer":return S.sql`${E}::integer`;default:throw new Error(`Unsupported cast type: ${e}`)}}buildAvg(E){return S.sql`COALESCE(AVG(${E}), 0)`}buildCaseWhen(E,e){const R=E.map(A=>S.sql`WHEN ${A.when} THEN ${A.then}`).reduce((A,t)=>S.sql`${A} ${t}`);return e!==void 0?S.sql`CASE ${R} ELSE ${e} END`:S.sql`CASE ${R} END`}buildBooleanLiteral(E){return E?S.sql`TRUE`:S.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}}buildStddev(E,e=!1){const R=e?"STDDEV_SAMP":"STDDEV_POP";return S.sql`COALESCE(${S.sql.raw(R)}(${E}), 0)`}buildVariance(E,e=!1){const R=e?"VAR_SAMP":"VAR_POP";return S.sql`COALESCE(${S.sql.raw(R)}(${E}), 0)`}buildPercentile(E,e){const R=e/100;return S.sql`PERCENTILE_CONT(${R}) WITHIN GROUP (ORDER BY ${E})`}buildWindowFunction(E,e,R,A,t){const s=R&&R.length>0?S.sql`PARTITION BY ${S.sql.join(R,S.sql`, `)}`:S.sql``,N=A&&A.length>0?S.sql`ORDER BY ${S.sql.join(A.map(i=>i.direction==="desc"?S.sql`${i.field} DESC`:S.sql`${i.field} ASC`),S.sql`, `)}`:S.sql``;let r=S.sql``;if(t?.frame){const{type:i,start:C,end:a}=t.frame,_=i.toUpperCase(),P=C==="unbounded"?"UNBOUNDED PRECEDING":typeof C=="number"?`${C} PRECEDING`:"CURRENT ROW",c=a==="unbounded"?"UNBOUNDED FOLLOWING":a==="current"?"CURRENT ROW":typeof a=="number"?`${a} FOLLOWING`:"CURRENT ROW";r=S.sql`${S.sql.raw(_)} BETWEEN ${S.sql.raw(P)} AND ${S.sql.raw(c)}`}const O=[];R&&R.length>0&&O.push(s),A&&A.length>0&&O.push(N),t?.frame&&O.push(r);const n=O.length>0?S.sql.join(O,S.sql` `):S.sql``,I=S.sql`OVER (${n})`;switch(E){case"lag":return S.sql`LAG(${e}, ${t?.offset??1}${t?.defaultValue!==void 0?S.sql`, ${t.defaultValue}`:S.sql``}) ${I}`;case"lead":return S.sql`LEAD(${e}, ${t?.offset??1}${t?.defaultValue!==void 0?S.sql`, ${t.defaultValue}`:S.sql``}) ${I}`;case"rank":return S.sql`RANK() ${I}`;case"denseRank":return S.sql`DENSE_RANK() ${I}`;case"rowNumber":return S.sql`ROW_NUMBER() ${I}`;case"ntile":return S.sql`NTILE(${t?.nTile??4}) ${I}`;case"firstValue":return S.sql`FIRST_VALUE(${e}) ${I}`;case"lastValue":return S.sql`LAST_VALUE(${e}) ${I}`;case"movingAvg":return S.sql`AVG(${e}) ${I}`;case"movingSum":return S.sql`SUM(${e}) ${I}`;default:throw new Error(`Unsupported window function: ${E}`)}}}class me extends yE{getEngineType(){return"mysql"}buildTimeDimension(E,e){const R={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 S.sql`DATE_ADD(MAKEDATE(YEAR(${e}), 1), INTERVAL (QUARTER(${e}) - 1) * 3 MONTH)`;case"week":return S.sql`DATE_SUB(${e}, INTERVAL WEEKDAY(${e}) DAY)`;default:{const A=R[E];return A?S.sql`STR_TO_DATE(DATE_FORMAT(${e}, ${A}), '%Y-%m-%d %H:%i:%s')`:e}}}buildStringCondition(E,e,R){switch(e){case"contains":return S.sql`LOWER(${E}) LIKE ${`%${R.toLowerCase()}%`}`;case"notContains":return S.sql`LOWER(${E}) NOT LIKE ${`%${R.toLowerCase()}%`}`;case"startsWith":return S.sql`LOWER(${E}) LIKE ${`${R.toLowerCase()}%`}`;case"endsWith":return S.sql`LOWER(${E}) LIKE ${`%${R.toLowerCase()}`}`;case"like":return S.sql`${E} LIKE ${R}`;case"notLike":return S.sql`${E} NOT LIKE ${R}`;case"ilike":return S.sql`LOWER(${E}) LIKE ${R.toLowerCase()}`;case"regex":return S.sql`${E} REGEXP ${R}`;case"notRegex":return S.sql`${E} NOT REGEXP ${R}`;default:throw new Error(`Unsupported string operator: ${e}`)}}castToType(E,e){switch(e){case"timestamp":return S.sql`CAST(${E} AS DATETIME)`;case"decimal":return S.sql`CAST(${E} AS DECIMAL(10,2))`;case"integer":return S.sql`CAST(${E} AS SIGNED INTEGER)`;default:throw new Error(`Unsupported cast type: ${e}`)}}buildAvg(E){return S.sql`IFNULL(AVG(${E}), 0)`}buildCaseWhen(E,e){const R=E.map(A=>S.sql`WHEN ${A.when} THEN ${A.then}`).reduce((A,t)=>S.sql`${A} ${t}`);return e!==void 0?S.sql`CASE ${R} ELSE ${e} END`:S.sql`CASE ${R} END`}buildBooleanLiteral(E){return E?S.sql`TRUE`:S.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}}buildStddev(E,e=!1){const R=e?"STDDEV_SAMP":"STDDEV_POP";return S.sql`IFNULL(${S.sql.raw(R)}(${E}), 0)`}buildVariance(E,e=!1){const R=e?"VAR_SAMP":"VAR_POP";return S.sql`IFNULL(${S.sql.raw(R)}(${E}), 0)`}buildPercentile(E,e){return null}buildWindowFunction(E,e,R,A,t){const s=R&&R.length>0?S.sql`PARTITION BY ${S.sql.join(R,S.sql`, `)}`:S.sql``,N=A&&A.length>0?S.sql`ORDER BY ${S.sql.join(A.map(i=>i.direction==="desc"?S.sql`${i.field} DESC`:S.sql`${i.field} ASC`),S.sql`, `)}`:S.sql``;let r=S.sql``;if(t?.frame){const{type:i,start:C,end:a}=t.frame,_=i.toUpperCase(),P=C==="unbounded"?"UNBOUNDED PRECEDING":typeof C=="number"?`${C} PRECEDING`:"CURRENT ROW",c=a==="unbounded"?"UNBOUNDED FOLLOWING":a==="current"?"CURRENT ROW":typeof a=="number"?`${a} FOLLOWING`:"CURRENT ROW";r=S.sql`${S.sql.raw(_)} BETWEEN ${S.sql.raw(P)} AND ${S.sql.raw(c)}`}const O=[];R&&R.length>0&&O.push(s),A&&A.length>0&&O.push(N),t?.frame&&O.push(r);const n=O.length>0?S.sql.join(O,S.sql` `):S.sql``,I=S.sql`OVER (${n})`;switch(E){case"lag":return S.sql`LAG(${e}, ${t?.offset??1}${t?.defaultValue!==void 0?S.sql`, ${t.defaultValue}`:S.sql``}) ${I}`;case"lead":return S.sql`LEAD(${e}, ${t?.offset??1}${t?.defaultValue!==void 0?S.sql`, ${t.defaultValue}`:S.sql``}) ${I}`;case"rank":return S.sql`RANK() ${I}`;case"denseRank":return S.sql`DENSE_RANK() ${I}`;case"rowNumber":return S.sql`ROW_NUMBER() ${I}`;case"ntile":return S.sql`NTILE(${t?.nTile??4}) ${I}`;case"firstValue":return S.sql`FIRST_VALUE(${e}) ${I}`;case"lastValue":return S.sql`LAST_VALUE(${e}) ${I}`;case"movingAvg":return S.sql`AVG(${e}) ${I}`;case"movingSum":return S.sql`SUM(${e}) ${I}`;default:throw new Error(`Unsupported window function: ${E}`)}}}class ET extends yE{getEngineType(){return"sqlite"}buildTimeDimension(E,e){switch(E){case"year":return S.sql`datetime(${e}, 'unixepoch', 'start of year')`;case"quarter":{const R=S.sql`datetime(${e}, 'unixepoch')`;return S.sql`datetime(${R}, 'start of year', '+' || (((CAST(strftime('%m', ${R}) AS INTEGER) - 1) / 3) * 3) || ' months')`}case"month":return S.sql`datetime(${e}, 'unixepoch', 'start of month')`;case"week":return S.sql`date(datetime(${e}, 'unixepoch'), 'weekday 1', '-6 days')`;case"day":return S.sql`datetime(${e}, 'unixepoch', 'start of day')`;case"hour":{const R=S.sql`datetime(${e}, 'unixepoch')`;return S.sql`datetime(strftime('%Y-%m-%d %H:00:00', ${R}))`}case"minute":{const R=S.sql`datetime(${e}, 'unixepoch')`;return S.sql`datetime(strftime('%Y-%m-%d %H:%M:00', ${R}))`}case"second":{const R=S.sql`datetime(${e}, 'unixepoch')`;return S.sql`datetime(strftime('%Y-%m-%d %H:%M:%S', ${R}))`}default:return S.sql`datetime(${e}, 'unixepoch')`}}buildStringCondition(E,e,R){switch(e){case"contains":return S.sql`LOWER(${E}) LIKE ${`%${R.toLowerCase()}%`}`;case"notContains":return S.sql`LOWER(${E}) NOT LIKE ${`%${R.toLowerCase()}%`}`;case"startsWith":return S.sql`LOWER(${E}) LIKE ${`${R.toLowerCase()}%`}`;case"endsWith":return S.sql`LOWER(${E}) LIKE ${`%${R.toLowerCase()}`}`;case"like":return S.sql`${E} LIKE ${R}`;case"notLike":return S.sql`${E} NOT LIKE ${R}`;case"ilike":return S.sql`LOWER(${E}) LIKE ${R.toLowerCase()}`;case"regex":return S.sql`${E} GLOB ${R}`;case"notRegex":return S.sql`${E} NOT GLOB ${R}`;default:throw new Error(`Unsupported string operator: ${e}`)}}castToType(E,e){switch(e){case"timestamp":return S.sql`datetime(${E} / 1000, 'unixepoch')`;case"decimal":return S.sql`CAST(${E} AS REAL)`;case"integer":return S.sql`CAST(${E} AS INTEGER)`;default:throw new Error(`Unsupported cast type: ${e}`)}}buildAvg(E){return S.sql`IFNULL(AVG(${E}), 0)`}buildCaseWhen(E,e){const R=E.map(A=>A.then&&typeof A.then=="object"&&(A.then.queryChunks||A.then._||A.then.sql)?S.sql`WHEN ${A.when} THEN ${S.sql.raw("(")}${A.then}${S.sql.raw(")")}`:S.sql`WHEN ${A.when} THEN ${A.then}`).reduce((A,t)=>S.sql`${A} ${t}`);return e!==void 0?e&&typeof e=="object"&&(e.queryChunks||e._||e.sql)?S.sql`CASE ${R} ELSE ${S.sql.raw("(")}${e}${S.sql.raw(")")} END`:S.sql`CASE ${R} ELSE ${e} END`:S.sql`CASE ${R} END`}buildBooleanLiteral(E){return E?S.sql`1`:S.sql`0`}preprocessCalculatedTemplate(E){const e=/(\{[^}]+\})\s*\/\s*/g;return E.replace(e,(R,A)=>`${A.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}}buildStddev(E,e=!1){return null}buildVariance(E,e=!1){return null}buildPercentile(E,e){return null}buildWindowFunction(E,e,R,A,t){const s=R&&R.length>0?S.sql`PARTITION BY ${S.sql.join(R,S.sql`, `)}`:S.sql``,N=A&&A.length>0?S.sql`ORDER BY ${S.sql.join(A.map(i=>i.direction==="desc"?S.sql`${i.field} DESC`:S.sql`${i.field} ASC`),S.sql`, `)}`:S.sql``;let r=S.sql``;if(t?.frame){const{type:i,start:C,end:a}=t.frame,_=i.toUpperCase(),P=C==="unbounded"?"UNBOUNDED PRECEDING":typeof C=="number"?`${C} PRECEDING`:"CURRENT ROW",c=a==="unbounded"?"UNBOUNDED FOLLOWING":a==="current"?"CURRENT ROW":typeof a=="number"?`${a} FOLLOWING`:"CURRENT ROW";r=S.sql`${S.sql.raw(_)} BETWEEN ${S.sql.raw(P)} AND ${S.sql.raw(c)}`}const O=[];R&&R.length>0&&O.push(s),A&&A.length>0&&O.push(N),t?.frame&&O.push(r);const n=O.length>0?S.sql.join(O,S.sql` `):S.sql``,I=S.sql`OVER (${n})`;switch(E){case"lag":return S.sql`LAG(${e}, ${t?.offset??1}${t?.defaultValue!==void 0?S.sql`, ${t.defaultValue}`:S.sql``}) ${I}`;case"lead":return S.sql`LEAD(${e}, ${t?.offset??1}${t?.defaultValue!==void 0?S.sql`, ${t.defaultValue}`:S.sql``}) ${I}`;case"rank":return S.sql`RANK() ${I}`;case"denseRank":return S.sql`DENSE_RANK() ${I}`;case"rowNumber":return S.sql`ROW_NUMBER() ${I}`;case"ntile":return S.sql`NTILE(${t?.nTile??4}) ${I}`;case"firstValue":return S.sql`FIRST_VALUE(${e}) ${I}`;case"lastValue":return S.sql`LAST_VALUE(${e}) ${I}`;case"movingAvg":return S.sql`AVG(${e}) ${I}`;case"movingSum":return S.sql`SUM(${e}) ${I}`;default:throw new Error(`Unsupported window function: ${E}`)}}}class eT extends me{getEngineType(){return"singlestore"}}function TT(T){switch(T){case"postgres":return new ze;case"mysql":return new me;case"sqlite":return new ET;case"singlestore":return new eT;default:throw new Error(`Unsupported database engine: ${T}`)}}class sE{constructor(E,e,R){this.db=E,this.schema=e;const A=R||this.getEngineType();this.databaseAdapter=TT(A)}databaseAdapter}class pe extends sE{async execute(E,e){if(E&&typeof E=="object"&&typeof E.execute=="function"){const A=await E.execute();return Array.isArray(A)?A.map(t=>this.convertNumericFields(t,e)):A}if(!this.db.execute)throw new Error("PostgreSQL database instance must have an execute method");const R=await this.db.execute(E);return Array.isArray(R)?R.map(A=>this.convertNumericFields(A,e)):R}convertNumericFields(E,e){if(!E||typeof E!="object")return E;const R={};for(const[A,t]of Object.entries(E))e&&e.includes(A)?R[A]=this.coerceToNumber(t):R[A]=t;return R}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"}}function HE(T,E){return new pe(T,E,"postgres")}class XE extends sE{async execute(E,e){if(E&&typeof E=="object"&&typeof E.execute=="function"){const A=await E.execute();return Array.isArray(A)?A.map(t=>this.convertNumericFields(t,e)):A}if(!this.db.execute)throw new Error("MySQL database instance must have an execute method");const R=await this.db.execute(E);return Array.isArray(R)?R.map(A=>this.convertNumericFields(A,e)):R}convertNumericFields(E,e){if(!E||typeof E!="object")return E;const R={};for(const[A,t]of Object.entries(E))e&&e.includes(A)?R[A]=this.coerceToNumber(t):R[A]=t;return R}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"}}function Be(T,E){return new XE(T,E,"mysql")}class he extends sE{async execute(E,e){if(E&&typeof E=="object"&&typeof E.execute=="function"){const R=await E.execute();return Array.isArray(R)?R.map(A=>this.convertNumericFields(A,e)):R}try{if(this.db.all){const R=this.db.all(E);return Array.isArray(R)?R.map(A=>this.convertNumericFields(A,e)):R}else{if(this.db.run)return this.db.run(E);throw new Error("SQLite database instance must have an all() or run() method")}}catch(R){throw new Error(`SQLite execution failed: ${R instanceof Error?R.message:"Unknown error"}`)}}convertNumericFields(E,e){if(!E||typeof E!="object")return E;const R={};for(const[A,t]of Object.entries(E))e&&e.includes(A)?R[A]=this.coerceToNumber(t):R[A]=t;return R}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"}}function fE(T,E){return new he(T,E,"sqlite")}class RT extends XE{getEngineType(){return"singlestore"}}function AT(T,E){return new RT(T,E)}function FE(T,E,e){if(e)switch(e){case"postgres":return HE(T,E);case"mysql":return Be(T,E);case"sqlite":return fE(T,E);case"singlestore":return AT(T,E)}if(T.all&&T.run)return fE(T,E);if(T.execute)return HE(T,E);throw new Error("Unable to determine database engine type. Please specify engineType parameter.")}function q(T){return typeof T=="function"?T():T}function TE(T,E){if(E)return E;switch(T){case"belongsTo":return"inner";case"hasOne":return"left";case"hasMany":return"left";case"belongsToMany":return"left";default:return"left"}}function YE(T){return T&&typeof T=="object"?S.sql`${S.sql`${T}`}`:T}function F(T,E){const e=typeof T=="function"?T(E):T;return YE(e)}function tT(T,E,e){return{...T,cubes:E,currentCube:e}}function sT(T,E){return{name:T,...E}}function ST(T,E){if(T.relationship!=="belongsToMany"||!T.through)throw new Error("expandBelongsToManyJoin can only be called on belongsToMany relationships with through configuration");const{table:e,sourceKey:R,targetKey:A,securitySql:t}=T.through,s=[];for(const n of R){const I=n.as||S.eq;s.push(I(n.source,n.target))}const N=[];for(const n of A){const I=n.as||S.eq;N.push(I(n.source,n.target))}let r;if(t){const n=t(E);r=Array.isArray(n)?n:[n]}const O=TE("belongsToMany",T.sqlJoinType);return{junctionJoins:[{joinType:O,table:e,condition:S.and(...s)},{joinType:O,table:e,condition:S.and(...N)}],junctionSecurityConditions:r}}function RE(T){if("and"in T)return`and:[${T.and.map(RE).sort().join(",")}]`;if("or"in T)return`or:[${T.or.map(RE).sort().join(",")}]`;const E=T,e=JSON.stringify(Array.isArray(E.values)?[...E.values].sort():E.values),R=E.dateRange?`:dr:${JSON.stringify(E.dateRange)}`:"";return`${E.member}:${E.operator}:${e}${R}`}function He(T,E){return`timeDim:${T}:${JSON.stringify(E)}`}class JE{cache=new Map;stats={hits:0,misses:0};getOrBuild(E,e){const R=this.cache.get(E);if(R!==void 0)return this.stats.hits++,R;const A=e();return A&&this.cache.set(E,A),this.stats.misses++,A}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:R}of E)this.cache.has(e)||this.cache.set(e,R)}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 VE(T){const E=[];for(const e of T)"and"in e&&e.and?E.push(...VE(e.and)):"or"in e&&e.or?E.push(...VE(e.or)):"member"in e&&E.push(e);return E}function fe(T,E,e={}){const R=e.keyPrefix??"drizzle-cube:",A=Fe(T),t=gE(JSON.stringify(A));let s=`${R}query:${t}`;if(e.includeSecurityContext!==!1){const N=e.securityContextSerializer?e.securityContextSerializer(E):JSON.stringify(AE(E)),r=gE(N);s+=`:ctx:${r}`}return s}function Fe(T){return{measures:T.measures?[...T.measures].sort():void 0,dimensions:T.dimensions?[...T.dimensions].sort():void 0,filters:T.filters?bE(T.filters):void 0,timeDimensions:T.timeDimensions?NT(T.timeDimensions):void 0,limit:T.limit,offset:T.offset,order:T.order?AE(T.order):void 0,fillMissingDatesValue:T.fillMissingDatesValue}}function bE(T){return[...T].map(E=>{if("and"in E&&E.and)return{and:bE(E.and)};if("or"in E&&E.or)return{or:bE(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 NT(T){return[...T].map(E=>({dimension:E.dimension,granularity:E.granularity,dateRange:E.dateRange,fillMissingDates:E.fillMissingDates,compareDateRange:E.compareDateRange?[...E.compareDateRange].sort((e,R)=>{const A=Array.isArray(e)?e.join("-"):e,t=Array.isArray(R)?R.join("-"):R;return A.localeCompare(t)}):void 0})).sort((E,e)=>E.dimension.localeCompare(e.dimension))}function AE(T){return T===null||typeof T!="object"?T:Array.isArray(T)?T.map(AE):Object.keys(T).sort().reduce((E,e)=>(E[e]=AE(T[e]),E),{})}function gE(T){let E=2166136261;for(let e=0;e<T.length;e++)E^=T.charCodeAt(e),E=E*16777619>>>0;return E.toString(16).padStart(8,"0")}function OT(T,E){return`${E??"drizzle-cube:"}*${T}*`}class Ye{constructor(E){this.databaseAdapter=E}buildTimeDimensionExpression(E,e,R){const A=F(E,R);return e?this.databaseAdapter.buildTimeDimension(e,A):A instanceof S.SQL?A:S.sql`${A}`}buildDateRangeCondition(E,e){if(!e)return null;if(Array.isArray(e)&&e.length>=2){const R=this.normalizeDate(e[0]);let A=this.normalizeDate(e[1]);if(!R||!A)return null;if(typeof e[1]=="string"&&/^\d{4}-\d{2}-\d{2}$/.test(e[1].trim())){const t=typeof A=="number"?new Date(A*(this.databaseAdapter.getEngineType()==="sqlite"?1e3:1)):new Date(A),s=new Date(t);s.setUTCHours(23,59,59,999),this.databaseAdapter.isTimestampInteger()?A=this.databaseAdapter.getEngineType()==="sqlite"?Math.floor(s.getTime()/1e3):s.getTime():A=s.toISOString()}return S.and(S.gte(E,R),S.lte(E,A))}if(typeof e=="string"){const R=this.parseRelativeDateRange(e);if(R){let n,I;return this.databaseAdapter.isTimestampInteger()?this.databaseAdapter.getEngineType()==="sqlite"?(n=Math.floor(R.start.getTime()/1e3),I=Math.floor(R.end.getTime()/1e3)):(n=R.start.getTime(),I=R.end.getTime()):(n=R.start.toISOString(),I=R.end.toISOString()),S.and(S.gte(E,n),S.lte(E,I))}const A=this.normalizeDate(e);if(!A)return null;const t=typeof A=="number"?new Date(A*(this.databaseAdapter.getEngineType()==="sqlite"?1e3:1)):new Date(A),s=new Date(t);s.setUTCHours(0,0,0,0);const N=new Date(t);N.setUTCHours(23,59,59,999);let r,O;return this.databaseAdapter.isTimestampInteger()?this.databaseAdapter.getEngineType()==="sqlite"?(r=Math.floor(s.getTime()/1e3),O=Math.floor(N.getTime()/1e3)):(r=s.getTime(),O=N.getTime()):(r=s.toISOString(),O=N.toISOString()),S.and(S.gte(E,r),S.lte(E,O))}return null}parseRelativeDateRange(E){const e=new Date,R=E.toLowerCase().trim(),A=e.getUTCFullYear(),t=e.getUTCMonth(),s=e.getUTCDate(),N=e.getUTCDay();if(R==="today"){const i=new Date(e);i.setUTCHours(0,0,0,0);const C=new Date(e);return C.setUTCHours(23,59,59,999),{start:i,end:C}}if(R==="yesterday"){const i=new Date(e);i.setUTCDate(s-1),i.setUTCHours(0,0,0,0);const C=new Date(e);return C.setUTCDate(s-1),C.setUTCHours(23,59,59,999),{start:i,end:C}}if(R==="this week"){const i=N===0?-6:1-N,C=new Date(e);C.setUTCDate(s+i),C.setUTCHours(0,0,0,0);const a=new Date(C);return a.setUTCDate(C.getUTCDate()+6),a.setUTCHours(23,59,59,999),{start:C,end:a}}if(R==="this month"){const i=new Date(Date.UTC(A,t,1,0,0,0,0)),C=new Date(Date.UTC(A,t+1,0,23,59,59,999));return{start:i,end:C}}if(R==="this quarter"){const i=Math.floor(t/3),C=new Date(Date.UTC(A,i*3,1,0,0,0,0)),a=new Date(Date.UTC(A,i*3+3,0,23,59,59,999));return{start:C,end:a}}if(R==="this year"){const i=new Date(Date.UTC(A,0,1,0,0,0,0)),C=new Date(Date.UTC(A,11,31,23,59,59,999));return{start:i,end:C}}const r=R.match(/^last\s+(\d+)\s+days?$/);if(r){const i=parseInt(r[1],10),C=new Date(e);C.setUTCDate(s-i+1),C.setUTCHours(0,0,0,0);const a=new Date(e);return a.setUTCHours(23,59,59,999),{start:C,end:a}}const O=R.match(/^last\s+(\d+)\s+weeks?$/);if(O){const C=parseInt(O[1],10)*7,a=new Date(e);a.setUTCDate(s-C+1),a.setUTCHours(0,0,0,0);const _=new Date(e);return _.setUTCHours(23,59,59,999),{start:a,end:_}}if(R==="last week"){const i=N===0?-13:-6-N,C=new Date(e);C.setUTCDate(s+i),C.setUTCHours(0,0,0,0);const a=new Date(C);return a.setUTCDate(C.getUTCDate()+6),a.setUTCHours(23,59,59,999),{start:C,end:a}}if(R==="last month"){const i=new Date(Date.UTC(A,t-1,1,0,0,0,0)),C=new Date(Date.UTC(A,t,0,23,59,59,999));return{start:i,end:C}}if(R==="last quarter"){const i=Math.floor(t/3),C=i===0?3:i-1,a=i===0?A-1:A,_=new Date(Date.UTC(a,C*3,1,0,0,0,0)),P=new Date(Date.UTC(a,C*3+3,0,23,59,59,999));return{start:_,end:P}}if(R==="last year"){const i=new Date(Date.UTC(A-1,0,1,0,0,0,0)),C=new Date(Date.UTC(A-1,11,31,23,59,59,999));return{start:i,end:C}}if(R==="last 12 months"){const i=new Date(Date.UTC(A,t-11,1,0,0,0,0)),C=new Date(e);return C.setUTCHours(23,59,59,999),{start:i,end:C}}const n=R.match(/^last\s+(\d+)\s+months?$/);if(n){const i=parseInt(n[1],10),C=new Date(Date.UTC(A,t-i+1,1,0,0,0,0)),a=new Date(e);return a.setUTCHours(23,59,59,999),{start:C,end:a}}const I=R.match(/^last\s+(\d+)\s+years?$/);if(I){const i=parseInt(I[1],10),C=new Date(Date.UTC(A-i,0,1,0,0,0,0)),a=new Date(e);return a.setUTCHours(23,59,59,999),{start:C,end:a}}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 R=E<1e10?E*1e3:E,A=new Date(R);return isNaN(A.getTime())?null:this.databaseAdapter.isTimestampInteger()?this.databaseAdapter.getEngineType()==="sqlite"?Math.floor(R/1e3):R:A.toISOString()}if(typeof E=="string"){if(/^\d{4}-\d{2}-\d{2}$/.test(E.trim())){const A=new Date(E+"T00:00:00Z");return isNaN(A.getTime())?null:this.databaseAdapter.isTimestampInteger()?this.databaseAdapter.getEngineType()==="sqlite"?Math.floor(A.getTime()/1e3):A.getTime():A.toISOString()}const R=new Date(E);return isNaN(R.getTime())?null:this.databaseAdapter.isTimestampInteger()?this.databaseAdapter.getEngineType()==="sqlite"?Math.floor(R.getTime()/1e3):R.getTime():R.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 IT{constructor(E,e){this.databaseAdapter=E,this.dateTimeBuilder=e}buildFilterCondition(E,e,R,A,t){if(t!==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(A&&A.type!=="time")throw new Error(`dateRange can only be used on time dimensions, but field '${A.name||"unknown"}' has type '${A.type}'`);return this.dateTimeBuilder.buildDateRangeCondition(E,t)}if(!R||R.length===0)return e==="equals"?this.databaseAdapter.buildBooleanLiteral(!1):null;const s=R.filter(r=>!(r==null||r===""||typeof r=="string"&&r.includes("\0"))).map(this.databaseAdapter.convertFilterValue);if(s.length===0&&!["set","notSet"].includes(e))return e==="equals"?this.databaseAdapter.buildBooleanLiteral(!1):null;const N=s[0];switch(e){case"equals":if(s.length>1){if(A?.type==="time"){const r=s.map(O=>this.dateTimeBuilder.normalizeDate(O)||O);return S.inArray(E,r)}return S.inArray(E,s)}else if(s.length===1){const r=A?.type==="time"&&this.dateTimeBuilder.normalizeDate(N)||N;return S.eq(E,r)}return this.databaseAdapter.buildBooleanLiteral(!1);case"notEquals":return s.length>1?S.notInArray(E,s):s.length===1?S.ne(E,N):null;case"contains":return this.databaseAdapter.buildStringCondition(E,"contains",N);case"notContains":return this.databaseAdapter.buildStringCondition(E,"notContains",N);case"startsWith":return this.databaseAdapter.buildStringCondition(E,"startsWith",N);case"endsWith":return this.databaseAdapter.buildStringCondition(E,"endsWith",N);case"gt":return S.gt(E,N);case"gte":return S.gte(E,N);case"lt":return S.lt(E,N);case"lte":return S.lte(E,N);case"set":return S.isNotNull(E);case"notSet":return S.isNull(E);case"inDateRange":if(s.length>=2){const r=this.dateTimeBuilder.normalizeDate(s[0]);let O=this.dateTimeBuilder.normalizeDate(s[1]);if(r&&O){const n=R[1];if(typeof n=="string"&&/^\d{4}-\d{2}-\d{2}$/.test(n.trim())){const I=typeof O=="number"?new Date(O*(this.databaseAdapter.getEngineType()==="sqlite"?1e3:1)):new Date(O),i=new Date(I);i.setUTCHours(23,59,59,999),this.databaseAdapter.isTimestampInteger()?O=this.databaseAdapter.getEngineType()==="sqlite"?Math.floor(i.getTime()/1e3):i.getTime():O=i.toISOString()}return S.and(S.gte(E,r),S.lte(E,O))}}return null;case"beforeDate":{const r=this.dateTimeBuilder.normalizeDate(N);return r?S.lt(E,r):null}case"afterDate":{const r=this.dateTimeBuilder.normalizeDate(N);return r?S.gt(E,r):null}case"between":return s.length>=2?S.and(S.gte(E,s[0]),S.lte(E,s[1])):null;case"notBetween":return s.length>=2?S.or(S.lt(E,s[0]),S.gt(E,s[1])):null;case"in":return s.length>0?S.inArray(E,s):null;case"notIn":return s.length>0?S.notInArray(E,s):null;case"like":return this.databaseAdapter.buildStringCondition(E,"like",N);case"notLike":return this.databaseAdapter.buildStringCondition(E,"notLike",N);case"ilike":return this.databaseAdapter.buildStringCondition(E,"ilike",N);case"regex":return this.databaseAdapter.buildStringCondition(E,"regex",N);case"notRegex":return this.databaseAdapter.buildStringCondition(E,"notRegex",N);case"isEmpty":return S.or(S.isNull(E),S.eq(E,""));case"isNotEmpty":return S.and(S.isNotNull(E),S.ne(E,""));case"arrayContains":return this.databaseAdapter.getEngineType()==="postgres"?S.arrayContains(E,s):null;case"arrayOverlaps":return this.databaseAdapter.getEngineType()==="postgres"?S.arrayOverlaps(E,s):null;case"arrayContained":return this.databaseAdapter.getEngineType()==="postgres"?S.arrayContained(E,s):null;default:return null}}buildLogicalFilter(E,e,R){if("and"in E&&E.and){const A=E.and.map(t=>this.buildSingleFilter(t,e,R)).filter(t=>t!==null);return A.length>0?A.length===1?A[0]:S.and(...A):null}if("or"in E&&E.or){const A=E.or.map(t=>this.buildSingleFilter(t,e,R)).filter(t=>t!==null);return A.length>0?A.length===1?A[0]:S.or(...A):null}return null}buildSingleFilter(E,e,R){if("and"in E||"or"in E)return this.buildLogicalFilter(E,e,R);const A=E,[t,s]=A.member.split("."),N=e.get(t);if(!N)return null;const r=N.dimensions?.[s];if(!r)return null;const O=F(r.sql,R);return this.buildFilterCondition(O,A.operator,A.values,r,A.dateRange)}}class y{dependencyGraph;cubes;constructor(E){this.cubes=E instanceof Map?E:new Map([[E.name,E]]),this.dependencyGraph=new Map}extractDependencies(E){const e=/\{([^}]+)\}/g,R=E.matchAll(e),A=[];for(const t of R){const s=t[1].trim();if(s.includes(".")){const[N,r]=s.split(".");A.push({measureName:s,cubeName:N.trim(),fieldName:r.trim()})}else A.push({measureName:s,cubeName:null,fieldName:s})}return A}buildGraph(E){for(const[e,R]of Object.entries(E.measures))if(R.type==="calculated"&&R.calculatedSql){const A=`${E.name}.${e}`,t=this.extractDependencies(R.calculatedSql),s=new Set;for(const N of t){const O=`${N.cubeName||E.name}.${N.fieldName}`;s.add(O)}this.dependencyGraph.set(A,{id:A,dependencies:s,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 R=this.dependencyGraph.get(e);R&&R.inDegree++}}topologicalSort(E){const e=new Map,R=[],A=[];for(const t of E){const s=this.dependencyGraph.get(t);s&&e.set(t,{id:s.id,dependencies:new Set(s.dependencies),inDegree:0})}for(const t of e.values()){let s=0;for(const N of t.dependencies)e.has(N)&&s++;t.inDegree=s}for(const[t,s]of e)s.inDegree===0&&R.push(t);for(;R.length>0;){const t=R.shift();A.push(t);for(const[s,N]of e)N.dependencies.has(t)&&(N.inDegree--,N.inDegree===0&&R.push(s))}if(A.length<e.size){const t=this.detectCycle();throw new Error(`Circular dependency detected in calculated measures: ${t?t.join(" -> "):"unknown cycle"}`)}return A}detectCycle(){const E=new Set,e=new Set,R=[];for(const A of this.dependencyGraph.keys())if(!E.has(A)){const t=this.dfs(A,E,e,R);if(t)return t}return null}dfs(E,e,R,A){e.add(E),R.add(E),A.push(E);const t=this.dependencyGraph.get(E);if(!t)return A.pop(),R.delete(E),null;for(const s of t.dependencies)if(e.has(s)){if(R.has(s)){const N=A.indexOf(s);return[...A.slice(N),s]}}else{const N=this.dfs(s,e,R,A);if(N)return N}return A.pop(),R.delete(E),null}getAllDependencies(E){const e=new Set,R=new Set,A=t=>{if(R.has(t))return;R.add(t);const s=this.dependencyGraph.get(t);if(s)for(const N of s.dependencies)e.add(N),A(N)};return A(E),e}validateDependencies(E){for(const[e,R]of Object.entries(E.measures))if(R.type==="calculated"&&R.calculatedSql){const A=this.extractDependencies(R.calculatedSql);for(const t of A){const s=t.cubeName||E.name,N=this.cubes.get(s);if(!N)throw new Error(`Calculated measure '${E.name}.${e}' references unknown cube '${s}'`);if(!N.measures[t.fieldName])throw new Error(`Calculated measure '${E.name}.${e}' references unknown measure '${t.measureName}'`);if(s===E.name&&t.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 R=this.extractDependencies(e.calculatedSql);e.dependencies=R.map(A=>A.measureName)}}static isCalculatedMeasure(E){return E.type==="calculated"&&!!E.calculatedSql}}function nT(T,E){const{cube:e,allCubes:R,resolvedMeasures:A}=E,t=$E(T),s=new Map;for(const I of t){const{originalRef:i,cubeName:C,fieldName:a}=I,_=C||e.name;if(!R.get(_))throw new Error(`Cannot substitute {${i}}: cube '${_}' not found`);const c=`${_}.${a}`,o=A.get(c);if(!o)throw new Error(`Cannot substitute {${i}}: measure '${c}' not resolved yet. Ensure measures are resolved in dependency order.`);const U=o(),M=S.sql`${U}`;s.set(i,M)}const N=[],r=[];let O=0;for(const I of t){const i=`{${I.originalRef}}`,C=T.indexOf(i,O);if(C>=0){N.push(T.substring(O,C));const a=s.get(I.originalRef);a&&r.push(a),O=C+i.length}}if(N.push(T.substring(O)),r.length===0)return S.sql.raw(T);const n=[];for(let I=0;I<N.length;I++)N[I]&&n.push(new S.StringChunk(N[I])),I<r.length&&n.push(r[I]);return S.sql.join(n,S.sql.raw(""))}function $E(T){const E=/\{([^}]+)\}/g,e=T.matchAll(E),R=[];for(const A of e){const t=A[1].trim();if(t.includes(".")){const[s,N]=t.split(".").map(r=>r.trim());R.push({originalRef:t,cubeName:s,fieldName:N})}else R.push({originalRef:t,cubeName:null,fieldName:t})}return R}function rT(T){const E=[];let e=0;for(let s=0;s<T.length;s++)if(T[s]==="{")e++;else if(T[s]==="}"&&(e--,e<0)){E.push(`Unmatched closing brace at position ${s}`);break}e>0&&E.push("Unmatched opening brace in template"),/\{\s*\}/.test(T)&&E.push("Empty member reference {} found in template"),/\{[^}]*\{/.test(T)&&E.push("Nested braces are not allowed in member references");const t=$E(T);for(const s of t){const N=s.cubeName?`${s.cubeName}.${s.fieldName}`:s.fieldName;/^[a-zA-Z_][a-zA-Z0-9_.]*$/.test(N)||E.push(`Invalid member reference {${s.originalRef}}: must start with letter or underscore, and contain only letters, numbers, underscores, and dots`),N.split(".").length>2&&E.push(`Invalid member reference {${s.originalRef}}: only one dot allowed (Cube.measure format)`)}return{isValid:E.length===0,errors:E}}function OE(T,E){const e=$E(T),R=new Set;for(const A of e){const s=`${A.cubeName||E}.${A.fieldName}`;R.add(s)}return Array.from(R)}class B{constructor(E){this.databaseAdapter=E}buildResolvedMeasures(E,e,R,A){const t=new Map,s=[],N=[],r=new Set(E),O=new y(e);for(const n of e.values())O.buildGraph(n);for(const n of E){const[I,i]=n.split("."),C=e.get(I);if(C&&C.measures&&C.measures[i]){const a=C.measures[i];if(B.isPostAggregationWindow(a)){const _=B.getWindowBaseMeasure(a,I);_&&r.add(_);continue}y.isCalculatedMeasure(a)?(N.push(n),OE(a.calculatedSql,I).forEach(c=>r.add(c)),O.getAllDependencies(n).forEach(c=>{const[o,U]=c.split("."),M=e.get(o);if(M&&M.measures[U]){const d=M.measures[U];y.isCalculatedMeasure(d)&&OE(d.calculatedSql,o).forEach(p=>r.add(p))}})):s.push(n)}}for(const n of r){const[I,i]=n.split("."),C=e.get(I);if(C&&C.measures&&C.measures[i]){const a=C.measures[i];if(B.isPostAggregationWindow(a))continue;y.isCalculatedMeasure(a)?N.includes(n)||N.push(n):s.includes(n)||s.push(n)}}for(const n of s){const[I,i]=n.split("."),C=e.get(I),a=C.measures[i];if(A){const _=A(n,a,C);t.set(n,()=>_)}else t.set(n,()=>this.buildMeasureExpression(a,R,C))}if(N.length>0){const n=O.topologicalSort(N);for(const I of n){const[i,C]=I.split("."),a=e.get(i),_=a.measures[C];t.set(I,()=>this.buildCalculatedMeasure(_,a,e,t,R))}}return t}buildCalculatedMeasure(E,e,R,A,t){if(!E.calculatedSql)throw new Error(`Calculated measure '${e.name}.${E.name}' missing calculatedSql property`);const s=this.databaseAdapter.preprocessCalculatedTemplate(E.calculatedSql);return nT(s,{cube:e,allCubes:R,resolvedMeasures:A})}buildCTECalculatedMeasure(E,e,R,A,t){if(!E.calculatedSql)throw new Error(`Calculated measure '${e.name}.${E.name||"unknown"}' missing calculatedSql property`);const s=new Map,N=OE(E.calculatedSql,e.name);for(const r of N){const[O,n]=r.split("."),I=A.get(O);if(I&&I.measures[n]){const i=I.measures[n];if(R.measures.includes(r)){const C=S.sql`${S.sql.identifier(R.cteAlias)}.${S.sql.identifier(n)}`;let a;switch(i.type){case"count":case"countDistinct":case"sum":a=S.sum(C);break;case"avg":a=this.databaseAdapter.buildAvg(C);break;case"min":a=S.min(C);break;case"max":a=S.max(C);break;case"number":a=S.sum(C);break;default:a=S.sum(C)}s.set(r,()=>a)}}}return this.buildCalculatedMeasure(E,e,A,s,t)}buildHavingMeasureExpression(E,e,R,A,t){if(t&&t.preAggregationCTEs){const s=t.preAggregationCTEs.find(N=>N.cube.name===E);if(s&&s.measures.includes(`${E}.${e}`))if(R.type==="calculated"&&R.calculatedSql){const N=t.primaryCube.name===E?t.primaryCube:t.joinCubes?.find(O=>O.cube.name===E)?.cube;if(!N)throw new Error(`Cube ${E} not found in query plan`);const r=new Map([[t.primaryCube.name,t.primaryCube]]);if(t.joinCubes)for(const O of t.joinCubes)r.set(O.cube.name,O.cube);return this.buildCTECalculatedMeasure(R,N,s,r,A)}else{const N=S.sql`${S.sql.identifier(s.cteAlias)}.${S.sql.identifier(e)}`;switch(R.type){case"count":case"countDistinct":case"sum":return S.sum(N);case"avg":return this.databaseAdapter.buildAvg(N);case"min":return S.min(N);case"max":return S.max(N);case"number":return S.sum(N);default:return S.sum(N)}}}return this.buildMeasureExpression(R,A)}buildMeasureExpression(E,e,R){if(E.type==="calculated")throw new Error(`Cannot build calculated measure '${E.name}' directly. Use buildCalculatedMeasure instead.`);if(B.isPostAggregationWindow(E))throw new Error(`Post-aggregation window measure '${E.name}' should be built via buildPostAggregationWindowExpression, not buildMeasureExpression.`);if(!E.sql)throw new Error(`Measure '${E.name}' of type '${E.type}' is missing required 'sql' property. Only calculated measures and post-aggregation window functions can omit 'sql'.`);let A=F(E.sql,e);if(E.filters&&E.filters.length>0){const t=E.filters.map(s=>{const N=s(e);return N?S.sql`(${N})`:void 0}).filter(Boolean);if(t.length>0){const s=t.length===1?t[0]:S.and(...t);A=this.databaseAdapter.buildCaseWhen([{when:s,then:A}])}}switch(E.type){case"count":return S.count(A);case"countDistinct":return S.countDistinct(A);case"sum":return S.sum(A);case"avg":return this.databaseAdapter.buildAvg(A);case"min":return S.min(A);case"max":return S.max(A);case"number":return A;case"stddev":case"stddevSamp":{const t=E.type==="stddevSamp"||E.statisticalConfig?.useSample,s=this.databaseAdapter.buildStddev(A,t);return s===null?(console.warn(`[drizzle-cube] ${E.type} not supported on ${this.databaseAdapter.getEngineType()}, returning NULL`),S.sql`MAX(NULL)`):s}case"variance":case"varianceSamp":{const t=E.type==="varianceSamp"||E.statisticalConfig?.useSample,s=this.databaseAdapter.buildVariance(A,t);return s===null?(console.warn(`[drizzle-cube] ${E.type} not supported on ${this.databaseAdapter.getEngineType()}, returning NULL`),S.sql`MAX(NULL)`):s}case"percentile":case"median":case"p95":case"p99":{let t;switch(E.type){case"median":t=50;break;case"p95":t=95;break;case"p99":t=99;break;default:t=E.statisticalConfig?.percentile??50}const s=this.databaseAdapter.buildPercentile(A,t);return s===null?(console.warn(`[drizzle-cube] ${E.type} not supported on ${this.databaseAdapter.getEngineType()}, returning NULL`),S.sql`MAX(NULL)`):s}case"lag":case"lead":case"rank":case"denseRank":case"rowNumber":case"ntile":case"firstValue":case"lastValue":case"movingAvg":case"movingSum":{const t=E.windowConfig||{};let s;if(t.partitionBy&&t.partitionBy.length>0&&R){const O=t.partitionBy.map(n=>{const I=n.includes(".")?n.split(".")[1]:n,i=R.dimensions?.[I];return i?F(i.sql,e):(console.warn(`[drizzle-cube] Window function partition dimension '${n}' not found in cube '${R.name}'`),null)}).filter(n=>n!==null);O.length>0&&(s=O)}let N;if(t.orderBy&&t.orderBy.length>0&&R){const O=t.orderBy.map(n=>{const I=n.field.includes(".")?n.field.split(".")[1]:n.field,i=R.dimensions?.[I];if(i)return{field:F(i.sql,e),direction:n.direction};const C=R.measures?.[I];return C&&C.sql?{field:F(C.sql,e),direction:n.direction}:(console.warn(`[drizzle-cube] Window function order field '${n.field}' not found in cube '${R.name}'`),null)}).filter(n=>n!==null);O.length>0&&(N=O)}const r=this.databaseAdapter.buildWindowFunction(E.type,["rank","denseRank","rowNumber"].includes(E.type)?null:A,s,N,{offset:t.offset,defaultValue:t.defaultValue,nTile:t.nTile,frame:t.frame});return r===null?(console.warn(`[drizzle-cube] ${E.type} not supported on ${this.databaseAdapter.getEngineType()}, returning NULL`),S.sql`NULL`):r}default:return S.count(A)}}static WINDOW_FUNCTION_TYPES=["lag","lead","rank","denseRank","rowNumber","ntile","firstValue","lastValue","movingAvg","movingSum"];static isWindowFunction(E){return B.WINDOW_FUNCTION_TYPES.includes(E)}static categorizeMeasures(E,e){const R=[],A=[];for(const t of E){const[s,N]=t.split("."),r=e.get(s);if(r?.measures?.[N]){const O=r.measures[N];B.isWindowFunction(O.type)?R.push(t):A.push(t)}}return{windowMeasures:R,aggregateMeasures:A}}static hasWindowFunctions(E,e){const{windowMeasures:R}=B.categorizeMeasures(E,e);return R.length>0}static isPostAggregationWindow(E){return B.isWindowFunction(E.type)&&E.windowConfig?.measure!==void 0}static getWindowBaseMeasure(E,e){if(!E.windowConfig?.measure)return null;const R=E.windowConfig.measure;return R.includes(".")?R:`${e}.${R}`}static getDefaultWindowOperation(E){switch(E){case"lag":case"lead":return"difference";default:return"raw"}}static categorizeForPostAggregation(E,e){const R=[],A=[],t=new Set;for(const s of E){const[N,r]=s.split("."),O=e.get(N);if(O?.measures?.[r]){const n=O.measures[r];if(B.isPostAggregationWindow(n)){A.push(s);const I=B.getWindowBaseMeasure(n,N);I&&t.add(I)}else B.isWindowFunction(n.type)||R.push(s)}}return{aggregateMeasures:R,postAggWindowMeasures:A,requiredBaseMeasures:t}}static hasPostAggregationWindows(E,e){const{postAggWindowMeasures:R}=B.categorizeForPostAggregation(E,e);return R.length>0}}class iT{constructor(E){this.dateTimeBuilder=E}isWindowFunctionType(E){return["lag","lead","rank","denseRank","rowNumber","ntile","firstValue","lastValue","movingAvg","movingSum"].includes(E)}isAggregateFunctionType(E){return["count","countDistinct","sum","avg","min","max","stddev","stddevSamp","variance","varianceSamp","median","p95","p99","percentile","number"].includes(E)}buildGroupByFields(E,e,R,A){const t=[],s=E instanceof Map?E:new Map([[E.name,E]]);let N=!1;for(const r of e.measures||[]){const[O,n]=r.split("."),I=s.get(O);if(I&&I.measures&&I.measures[n]){const i=I.measures[n];if(this.isAggregateFunctionType(i.type)||i.type==="calculated"){N=!0;break}if(B.isPostAggregationWindow(i)){const C=B.getWindowBaseMeasure(i,O);if(C){const[a,_]=C.split("."),c=s.get(a)?.measures?.[_];if(c&&this.isAggregateFunctionType(c.type)){N=!0;break}}}}}if(!N)return[];if(e.dimensions)for(const r of e.dimensions){const[O,n]=r.split("."),I=s.get(O);if(I&&I.dimensions&&I.dimensions[n])if(A?.preAggregationCTEs?.some(C=>C.cube.name===O)){const C=A.preAggregationCTEs.find(_=>_.cube.name===O),a=C.joinKeys.find(_=>_.targetColumn===n);if(a&&a.sourceColumnObj)t.push(a.sourceColumnObj);else{const _=S.sql`${S.sql.identifier(C.cteAlias)}.${S.sql.identifier(n)}`;t.push(_)}}else{const C=I.dimensions[n],a=F(C.sql,R);t.push(a)}}if(e.timeDimensions)for(const r of e.timeDimensions){const[O,n]=r.dimension.split("."),I=s.get(O);if(I&&I.dimensions&&I.dimensions[n])if(A?.preAggregationCTEs?.some(C=>C.cube.name===O)){const C=A.preAggregationCTEs.find(_=>_.cube.name===O),a=C.joinKeys.find(_=>_.targetColumn===n);if(a&&a.sourceColumnObj){const _=this.dateTimeBuilder.buildTimeDimensionExpression(a.sourceColumnObj,r.granularity,R);t.push(_)}else{const _=S.sql`${S.sql.identifier(C.cteAlias)}.${S.sql.identifier(n)}`;t.push(_)}}else{const C=I.dimensions[n],a=this.dateTimeBuilder.buildTimeDimensionExpression(C.sql,r.granularity,R);t.push(a)}}return t}}class Ve{dateTimeBuilder;filterBuilder;groupByBuilder;measureBuilder;constructor(E){this.dateTimeBuilder=new Ye(E),this.filterBuilder=new IT(E,this.dateTimeBuilder),this.groupByBuilder=new iT(this.dateTimeBuilder),this.measureBuilder=new B(E)}buildResolvedMeasures(E,e,R,A){return this.measureBuilder.buildResolvedMeasures(E,e,R,A)}buildSelections(E,e,R){const A={},t=E instanceof Map?E:new Map([[E.name,E]]);if(e.dimensions)for(const s of e.dimensions){const[N,r]=s.split("."),O=t.get(N);if(O&&O.dimensions&&O.dimensions[r]){const n=O.dimensions[r],I=F(n.sql,R);A[s]=S.sql`${I}`.as(s)}}if(e.measures){const s=this.buildResolvedMeasures(e.measures,t,R);for(const N of e.measures){const r=s.get(N);if(r){const O=r();A[N]=S.sql`${O}`.as(N)}}}if(e.timeDimensions)for(const s of e.timeDimensions){const[N,r]=s.dimension.split("."),O=t.get(N);if(O&&O.dimensions&&O.dimensions[r]){const n=O.dimensions[r],I=this.buildTimeDimensionExpression(n.sql,s.granularity,R);A[s.dimension]=S.sql`${I}`.as(s.dimension)}}return Object.keys(A).length===0&&(A.count=S.count()),A}buildCalculatedMeasure(E,e,R,A,t){return this.measureBuilder.buildCalculatedMeasure(E,e,R,A,t)}buildCTECalculatedMeasure(E,e,R,A,t){return this.measureBuilder.buildCTECalculatedMeasure(E,e,R,A,t)}buildHavingMeasureExpression(E,e,R,A,t){return this.measureBuilder.buildHavingMeasureExpression(E,e,R,A,t)}buildMeasureExpression(E,e,R){return this.measureBuilder.buildMeasureExpression(E,e,R)}buildTimeDimensionExpression(E,e,R){return this.dateTimeBuilder.buildTimeDimensionExpression(E,e,R)}buildWhereConditions(E,e,R,A,t){const s=[],N=E instanceof Map?E:new Map([[E.name,E]]),r=new Set;if(e.filters&&e.filters.length>0)for(const O of e.filters){if(t&&"member"in O){const[I]=O.member.split(".");if(N.has(I)&&t.has(I)&&!r.has(I)){const C=t.get(I);s.push(...C),r.add(I);continue}else if(r.has(I))continue}const n=this.processFilter(O,N,R,"where",A);n&&s.push(n)}if(e.timeDimensions)for(const O of e.timeDimensions){const[n,I]=O.dimension.split("."),i=N.get(n);if(i&&i.dimensions[I]&&O.dateRange){if(A?.preAggregationCTEs&&A.preAggregationCTEs.some(c=>c.cube.name===n))continue;if(R.filterCache){const P=He(O.dimension,O.dateRange),c=R.filterCache.get(P);if(c){s.push(c);continue}}const C=i.dimensions[I],a=F(C.sql,R),_=this.buildDateRangeCondition(a,O.dateRange);_&&s.push(_)}}return s}buildHavingConditions(E,e,R,A){const t=[],s=E instanceof Map?E:new Map([[E.name,E]]);if(e.filters&&e.filters.length>0)for(const N of e.filters){const r=this.processFilter(N,s,R,"having",A);r&&t.push(r)}return t}processFilter(E,e,R,A,t){if("and"in E||"or"in E){const C=E;if(C.and){const a=C.and.map(_=>this.processFilter(_,e,R,A,t)).filter(_=>_!==null);return a.length>0?S.and(...a):null}if(C.or){const a=C.or.map(_=>this.processFilter(_,e,R,A,t)).filter(_=>_!==null);return a.length>0?S.or(...a):null}}const s=E,[N,r]=s.member.split("."),O=e.get(N);if(!O)return null;const n=O.dimensions[r],I=O.measures[r],i=n||I;if(!i)return null;if(A==="where"&&n){if(t?.preAggregationCTEs&&t.preAggregationCTEs.some(P=>P.cube.name===N))return null;const C=["arrayContains","arrayOverlaps","arrayContained"].includes(s.operator);if(!C&&R.filterCache){const _=RE(E),P=R.filterCache.get(_);if(P)return P}const a=C?typeof n.sql=="function"?n.sql(R):n.sql:F(n.sql,R);return this.buildFilterCondition(a,s.operator,s.values,i,s.dateRange)}else{if(A==="where"&&I)return null;if(A==="having"&&I){const C=this.buildHavingMeasureExpression(N,r,I,R,t);return this.buildFilterCondition(C,s.operator,s.values,i,s.dateRange)}}return null}buildFilterCondition(E,e,R,A,t){return this.filterBuilder.buildFilterCondition(E,e,R,A,t)}buildDateRangeCondition(E,e){return this.dateTimeBuilder.buildDateRangeCondition(E,e)}buildGroupByFields(E,e,R,A){return this.groupByBuilder.buildGroupByFields(E,e,R,A)}buildOrderBy(E,e){const R=[],A=e||[...E.measures||[],...E.dimensions||[],...E.timeDimensions?.map(t=>t.dimension)||[]];if(E.order&&Object.keys(E.order).length>0)for(const[t,s]of Object.entries(E.order)){if(!A.includes(t))throw new Error(`Cannot order by '${t}': field is not selected in the query`);const N=s==="desc"?S.desc(S.sql.identifier(t)):S.asc(S.sql.identifier(t));R.push(N)}if(E.timeDimensions&&E.timeDimensions.length>0){const t=new Set(Object.keys(E.order||{})),s=[...E.timeDimensions].sort((N,r)=>N.dimension.localeCompare(r.dimension));for(const N of s)t.has(N.dimension)||R.push(S.asc(S.sql.identifier(N.dimension)))}return R}collectNumericFields(E,e){const R=[],A=E instanceof Map?E:new Map([[E.name,E]]);if(e.measures&&R.push(...e.measures),e.dimensions)for(const t of e.dimensions){const[s,N]=t.split("."),r=A.get(s);if(r){const O=r.dimensions[N];O&&O.type==="number"&&R.push(t)}}return R}applyLimitAndOffset(E,e){let R=e.limit;e.offset!==void 0&&e.offset>0&&R===void 0&&(R=50);let A=E;if(R!==void 0){if(R<0)throw new Error("Limit must be non-negative");A=A.limit(R)}if(e.offset!==void 0){if(e.offset<0)throw new Error("Offset must be non-negative");A=A.offset(e.offset)}return A}buildFilterConditionPublic(E,e,R,A,t){return this.buildFilterCondition(E,e,R,A,t)}buildLogicalFilter(E,e,R){return this.filterBuilder.buildLogicalFilter(E,e,R)}}class CT{cubes;connectivityCache=new Map;constructor(E){this.cubes=E}findPath(E,e,R=new Set){if(E===e)return[];const A=this.getCacheKey(E,e,R),t=this.getFromCache(A);if(t!==void 0)return t;const s=[{cube:E,path:[]}],N=new Set([E,...R]);for(;s.length>0;){const{cube:r,path:O}=s.shift(),n=this.cubes.get(r);if(n?.joins)for(const[,I]of Object.entries(n.joins)){const C=q(I.targetCube).name;if(N.has(C))continue;const a=[...O,{fromCube:r,toCube:C,joinDef:I}];if(C===e)return this.setInCache(A,a),a;N.add(C),s.push({cube:C,path:a})}}return this.setInCache(A,null),null}canReachAll(E,e){const R=e.filter(A=>A!==E);for(const A of R){const t=this.findPath(E,A,new Set);if(!t||t.length===0)return!1}return!0}build