drizzle-cube 0.4.0 → 0.4.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (26) hide show
  1. package/dist/adapters/express/index.cjs +1 -1
  2. package/dist/adapters/express/index.js +1 -1
  3. package/dist/adapters/fastify/index.cjs +1 -1
  4. package/dist/adapters/fastify/index.js +1 -1
  5. package/dist/adapters/hono/index.cjs +1 -1
  6. package/dist/adapters/hono/index.js +1 -1
  7. package/dist/adapters/{mcp-transport-Bbz3qrIy.js → mcp-transport-Dmolep14.js} +31 -26
  8. package/dist/adapters/{mcp-transport-CXF4E5QJ.cjs → mcp-transport-h__yKJm9.cjs} +3 -3
  9. package/dist/adapters/nextjs/index.cjs +1 -1
  10. package/dist/adapters/nextjs/index.js +1 -1
  11. package/dist/client/chunks/{DashboardEditModal-Bv7e3Q7O.js → DashboardEditModal-D6TDeTBa.js} +1947 -1980
  12. package/dist/client/chunks/DashboardEditModal-D6TDeTBa.js.map +1 -0
  13. package/dist/client/chunks/{analysis-builder-BfH-w92z.js → analysis-builder-CIuNLos1.js} +101 -101
  14. package/dist/client/chunks/{analysis-builder-BfH-w92z.js.map → analysis-builder-CIuNLos1.js.map} +1 -1
  15. package/dist/client/chunks/{analysis-builder-shared-DsbdRCzz.js → analysis-builder-shared-gky0SKQH.js} +160 -159
  16. package/dist/client/chunks/analysis-builder-shared-gky0SKQH.js.map +1 -0
  17. package/dist/client/components/PortletAnalysisModal.d.ts +2 -2
  18. package/dist/client/components.js +1 -1
  19. package/dist/client/index.js +2 -2
  20. package/dist/client/utils/filterUtils.d.ts +6 -0
  21. package/dist/client-bundle-stats.html +1 -1
  22. package/dist/server/index.cjs +31 -31
  23. package/dist/server/index.js +1512 -1507
  24. package/package.json +1 -1
  25. package/dist/client/chunks/DashboardEditModal-Bv7e3Q7O.js.map +0 -1
  26. package/dist/client/chunks/analysis-builder-shared-DsbdRCzz.js.map +0 -1
@@ -1,4 +1,4 @@
1
- "use strict";const Y=require("./utils.cjs"),x=Symbol.for("drizzle:entityKind");function I(d,e){if(!d||typeof d!="object")return!1;if(d instanceof e)return!0;if(!Object.prototype.hasOwnProperty.call(e,x))throw new Error(`Class "${e.name??"<unknown>"}" doesn't look like a Drizzle entity. If this is incorrect and the class is provided by Drizzle, please report this as a bug.`);let t=Object.getPrototypeOf(d).constructor;if(t)for(;t;){if(x in t&&t[x]===e[x])return!0;t=Object.getPrototypeOf(t)}return!1}class se{constructor(e,t){this.table=e,this.config=t,this.name=t.name,this.keyAsName=t.keyAsName,this.notNull=t.notNull,this.default=t.default,this.defaultFn=t.defaultFn,this.onUpdateFn=t.onUpdateFn,this.hasDefault=t.hasDefault,this.primary=t.primaryKey,this.isUnique=t.isUnique,this.uniqueName=t.uniqueName,this.uniqueType=t.uniqueType,this.dataType=t.dataType,this.columnType=t.columnType,this.generated=t.generated,this.generatedIdentity=t.generatedIdentity}static[x]="Column";name;keyAsName;primary;notNull;default;defaultFn;onUpdateFn;hasDefault;isUnique;uniqueName;uniqueType;dataType;columnType;enumValues=void 0;generated=void 0;generatedIdentity=void 0;config;mapFromDriverValue(e){return e}mapToDriverValue(e){return e}shouldDisableInsert(){return this.config.generated!==void 0&&this.config.generated.type!=="byDefault"}}const Ce=Symbol.for("drizzle:Name"),Pe=Symbol.for("drizzle:isPgEnum");function Ct(d){return!!d&&typeof d=="function"&&Pe in d&&d[Pe]===!0}class nt{static[x]="Subquery";constructor(e,t,n,i=!1,s=[]){this._={brand:"Subquery",sql:e,selectedFields:t,alias:n,isWith:i,usedTables:s}}}const wt={startActiveSpan(d,e){return e()}},ie=Symbol.for("drizzle:ViewBaseConfig"),we=Symbol.for("drizzle:Schema"),Be=Symbol.for("drizzle:Columns"),ke=Symbol.for("drizzle:ExtraConfigColumns"),$e=Symbol.for("drizzle:OriginalName"),Te=Symbol.for("drizzle:BaseName"),ce=Symbol.for("drizzle:IsAlias"),xe=Symbol.for("drizzle:ExtraConfigBuilder"),$t=Symbol.for("drizzle:IsDrizzleTable");class Q{static[x]="Table";static Symbol={Name:Ce,Schema:we,OriginalName:$e,Columns:Be,ExtraConfigColumns:ke,BaseName:Te,IsAlias:ce,ExtraConfigBuilder:xe};[Ce];[$e];[we];[Be];[ke];[Te];[ce]=!1;[$t]=!0;[xe]=void 0;constructor(e,t,n){this[Ce]=this[$e]=e,this[we]=t,this[Te]=n}}function it(d){return d!=null&&typeof d.getSQL=="function"}function Tt(d){const e={sql:"",params:[]};for(const t of d)e.sql+=t.sql,e.params.push(...t.params),t.typings?.length&&(e.typings||(e.typings=[]),e.typings.push(...t.typings));return e}class P{static[x]="StringChunk";value;constructor(e){this.value=Array.isArray(e)?e:[e]}getSQL(){return new O([this])}}class O{constructor(e){this.queryChunks=e;for(const t of e)if(I(t,Q)){const n=t[Q.Symbol.Schema];this.usedTables.push(n===void 0?t[Q.Symbol.Name]:n+"."+t[Q.Symbol.Name])}}static[x]="SQL";decoder=st;shouldInlineParams=!1;usedTables=[];append(e){return this.queryChunks.push(...e.queryChunks),this}toQuery(e){return wt.startActiveSpan("drizzle.buildSQL",t=>{const n=this.buildQueryFromSourceParams(this.queryChunks,e);return t?.setAttributes({"drizzle.query.text":n.sql,"drizzle.query.params":JSON.stringify(n.params)}),n})}buildQueryFromSourceParams(e,t){const n=Object.assign({},t,{inlineParams:t.inlineParams||this.shouldInlineParams,paramStartIndex:t.paramStartIndex||{value:0}}),{casing:i,escapeName:s,escapeParam:o,prepareTyping:a,inlineParams:u,paramStartIndex:c}=n;return Tt(e.map(l=>{if(I(l,P))return{sql:l.value.join(""),params:[]};if(I(l,_e))return{sql:s(l.value),params:[]};if(l===void 0)return{sql:"",params:[]};if(Array.isArray(l)){const m=[new P("(")];for(const[p,f]of l.entries())m.push(f),p<l.length-1&&m.push(new P(", "));return m.push(new P(")")),this.buildQueryFromSourceParams(m,n)}if(I(l,O))return this.buildQueryFromSourceParams(l.queryChunks,{...n,inlineParams:u||l.shouldInlineParams});if(I(l,Q)){const m=l[Q.Symbol.Schema],p=l[Q.Symbol.Name];return{sql:m===void 0||l[ce]?s(p):s(m)+"."+s(p),params:[]}}if(I(l,se)){const m=i.getColumnCasing(l);if(t.invokeSource==="indexes")return{sql:s(m),params:[]};const p=l.table[Q.Symbol.Schema];return{sql:l.table[ce]||p===void 0?s(l.table[Q.Symbol.Name])+"."+s(m):s(p)+"."+s(l.table[Q.Symbol.Name])+"."+s(m),params:[]}}if(I(l,ot)){const m=l[ie].schema,p=l[ie].name;return{sql:m===void 0||l[ie].isAlias?s(p):s(m)+"."+s(p),params:[]}}if(I(l,de)){if(I(l.value,me))return{sql:o(c.value++,l),params:[l],typings:["none"]};const m=l.value===null?null:l.encoder.mapToDriverValue(l.value);if(I(m,O))return this.buildQueryFromSourceParams([m],n);if(u)return{sql:this.mapInlineParam(m,n),params:[]};let p=["none"];return a&&(p=[a(l.encoder)]),{sql:o(c.value++,m),params:[m],typings:p}}return I(l,me)?{sql:o(c.value++,l),params:[l],typings:["none"]}:I(l,O.Aliased)&&l.fieldAlias!==void 0?{sql:s(l.fieldAlias),params:[]}:I(l,nt)?l._.isWith?{sql:s(l._.alias),params:[]}:this.buildQueryFromSourceParams([new P("("),l._.sql,new P(") "),new _e(l._.alias)],n):Ct(l)?l.schema?{sql:s(l.schema)+"."+s(l.enumName),params:[]}:{sql:s(l.enumName),params:[]}:it(l)?l.shouldOmitSQLParens?.()?this.buildQueryFromSourceParams([l.getSQL()],n):this.buildQueryFromSourceParams([new P("("),l.getSQL(),new P(")")],n):u?{sql:this.mapInlineParam(l,n),params:[]}:{sql:o(c.value++,l),params:[l],typings:["none"]}}))}mapInlineParam(e,{escapeString:t}){if(e===null)return"null";if(typeof e=="number"||typeof e=="boolean")return e.toString();if(typeof e=="string")return t(e);if(typeof e=="object"){const n=e.toString();return t(n==="[object Object]"?JSON.stringify(e):n)}throw new Error("Unexpected param value: "+e)}getSQL(){return this}as(e){return e===void 0?this:new O.Aliased(this,e)}mapWith(e){return this.decoder=typeof e=="function"?{mapFromDriverValue:e}:e,this}inlineParams(){return this.shouldInlineParams=!0,this}if(e){return e?this:void 0}}class _e{constructor(e){this.value=e}static[x]="Name";brand;getSQL(){return new O([this])}}function Et(d){return typeof d=="object"&&d!==null&&"mapToDriverValue"in d&&typeof d.mapToDriverValue=="function"}const st={mapFromDriverValue:d=>d},rt={mapToDriverValue:d=>d};({...st,...rt});class de{constructor(e,t=rt){this.value=e,this.encoder=t}static[x]="Param";brand;getSQL(){return new O([this])}}function r(d,...e){const t=[];(e.length>0||d.length>0&&d[0]!=="")&&t.push(new P(d[0]));for(const[n,i]of e.entries())t.push(i,new P(d[n+1]));return new O(t)}(d=>{function e(){return new O([])}d.empty=e;function t(u){return new O(u)}d.fromList=t;function n(u){return new O([new P(u)])}d.raw=n;function i(u,c){const l=[];for(const[m,p]of u.entries())m>0&&c!==void 0&&l.push(c),l.push(p);return new O(l)}d.join=i;function s(u){return new _e(u)}d.identifier=s;function o(u){return new me(u)}d.placeholder=o;function a(u,c){return new de(u,c)}d.param=a})(r||(r={}));(d=>{class e{constructor(n,i){this.sql=n,this.fieldAlias=i}static[x]="SQL.Aliased";isSelectionField=!1;getSQL(){return this.sql}clone(){return new e(this.sql,this.fieldAlias)}}d.Aliased=e})(O||(O={}));class me{constructor(e){this.name=e}static[x]="Placeholder";getSQL(){return new O([this])}}const St=Symbol.for("drizzle:IsDrizzleView");class ot{static[x]="View";[ie];[St]=!0;constructor({name:e,schema:t,selectedFields:n,query:i}){this[ie]={name:e,originalName:e,schema:t,selectedFields:n,query:i,isExisting:!i,isAlias:!1}}getSQL(){return new O([this])}}se.prototype.getSQL=function(){return new O([this])};Q.prototype.getSQL=function(){return new O([this])};nt.prototype.getSQL=function(){return new O([this])};function B(d,e){return Et(e)&&!it(d)&&!I(d,de)&&!I(d,me)&&!I(d,se)&&!I(d,Q)&&!I(d,ot)?new de(d,e):d}const k=(d,e)=>r`${d} = ${B(e,d)}`,Ue=(d,e)=>r`${d} <> ${B(e,d)}`;function A(...d){const e=d.filter(t=>t!==void 0);if(e.length!==0)return e.length===1?new O(e):new O([new P("("),r.join(e,new P(" and ")),new P(")")])}function oe(...d){const e=d.filter(t=>t!==void 0);if(e.length!==0)return e.length===1?new O(e):new O([new P("("),r.join(e,new P(" or ")),new P(")")])}const Ee=(d,e)=>r`${d} > ${B(e,d)}`,ee=(d,e)=>r`${d} >= ${B(e,d)}`,Se=(d,e)=>r`${d} < ${B(e,d)}`,te=(d,e)=>r`${d} <= ${B(e,d)}`;function De(d,e){return Array.isArray(e)?e.length===0?r`false`:r`${d} in ${e.map(t=>B(t,d))}`:r`${d} in ${B(e,d)}`}function Qe(d,e){return Array.isArray(e)?e.length===0?r`true`:r`${d} not in ${e.map(t=>B(t,d))}`:r`${d} not in ${B(e,d)}`}function Ke(d){return r`${d} is null`}function We(d){return r`${d} is not null`}function Dt(d,e){if(Array.isArray(e)){if(e.length===0)throw new Error("arrayContains requires at least one value");const t=r`${B(e,d)}`;return r`${d} @> ${t}`}return r`${d} @> ${B(e,d)}`}function Nt(d,e){if(Array.isArray(e)){if(e.length===0)throw new Error("arrayContained requires at least one value");const t=r`${B(e,d)}`;return r`${d} <@ ${t}`}return r`${d} <@ ${B(e,d)}`}function At(d,e){if(Array.isArray(e)){if(e.length===0)throw new Error("arrayOverlaps requires at least one value");const t=r`${B(e,d)}`;return r`${d} && ${t}`}return r`${d} && ${B(e,d)}`}function Je(d){return r`${d} asc`}function _t(d){return r`${d} desc`}function ve(d){return r`count(${d||r.raw("*")})`.mapWith(Number)}function vt(d){return r`count(distinct ${d})`.mapWith(Number)}function z(d){return r`sum(${d})`.mapWith(String)}function H(d){return r`max(${d})`.mapWith(I(d,se)?d:String)}function ae(d){return r`min(${d})`.mapWith(I(d,se)?d:String)}class he{preprocessCalculatedTemplate(e){return e}buildPattern(e,t){switch(e){case"contains":case"notContains":return`%${t}%`;case"startsWith":return`${t}%`;case"endsWith":return`%${t}`;default:return t}}parseISODuration(e){const t={years:0,months:0,days:0,hours:0,minutes:0,seconds:0},n=/^P(?:(\d+)Y)?(?:(\d+)M)?(?:(\d+)D)?(?:T(?:(\d+)H)?(?:(\d+)M)?(?:(\d+(?:\.\d+)?)S)?)?$/,i=e.match(n);if(!i)throw new Error(`Invalid ISO 8601 duration format: ${e}`);return t.years=parseInt(i[1]||"0",10),t.months=parseInt(i[2]||"0",10),t.days=parseInt(i[3]||"0",10),t.hours=parseInt(i[4]||"0",10),t.minutes=parseInt(i[5]||"0",10),t.seconds=parseFloat(i[6]||"0"),t}durationToSeconds(e){const t=this.parseISODuration(e);return t.years*365*24*60*60+t.months*30*24*60*60+t.days*24*60*60+t.hours*60*60+t.minutes*60+t.seconds}}class Rt extends he{getEngineType(){return"postgres"}supportsLateralJoins(){return!0}buildIntervalFromISO(e){const t=this.parseISODuration(e),n=[];t.years&&n.push(`${t.years} years`),t.months&&n.push(`${t.months} months`),t.days&&n.push(`${t.days} days`),t.hours&&n.push(`${t.hours} hours`),t.minutes&&n.push(`${t.minutes} minutes`),t.seconds&&n.push(`${t.seconds} seconds`);const i=n.join(" ")||"0 seconds";return r`INTERVAL '${r.raw(i)}'`}buildTimeDifferenceSeconds(e,t){return r`EXTRACT(EPOCH FROM (${e} - ${t}))`}buildDateAddInterval(e,t){const n=this.buildIntervalFromISO(t);return r`(${e} + ${n})`}buildConditionalAggregation(e,t,n){const i=e.toUpperCase();return e==="count"&&!t?r`COUNT(*) FILTER (WHERE ${n})`:r`${r.raw(i)}(${t}) FILTER (WHERE ${n})`}buildDateDiffPeriods(e,t,n){switch(n){case"day":return r`(${t}::date - ${e}::date)`;case"week":return r`FLOOR((${t}::date - ${e}::date) / 7)`;case"month":return r`(EXTRACT(YEAR FROM AGE(${t}::timestamp, ${e}::timestamp)) * 12 + EXTRACT(MONTH FROM AGE(${t}::timestamp, ${e}::timestamp)))::integer`;default:throw new Error(`Unsupported date diff unit: ${n}`)}}buildPeriodSeriesSubquery(e){return r`(SELECT generate_series(0, ${e}) as period_number) p`}buildTimeDimension(e,t){switch(e){case"year":return r`DATE_TRUNC('year', ${t}::timestamp)`;case"quarter":return r`DATE_TRUNC('quarter', ${t}::timestamp)`;case"month":return r`DATE_TRUNC('month', ${t}::timestamp)`;case"week":return r`DATE_TRUNC('week', ${t}::timestamp)`;case"day":return r`DATE_TRUNC('day', ${t}::timestamp)::timestamp`;case"hour":return r`DATE_TRUNC('hour', ${t}::timestamp)`;case"minute":return r`DATE_TRUNC('minute', ${t}::timestamp)`;case"second":return r`DATE_TRUNC('second', ${t}::timestamp)`;default:return t}}buildStringCondition(e,t,n){switch(t){case"contains":return r`${e} ILIKE ${`%${n}%`}`;case"notContains":return r`${e} NOT ILIKE ${`%${n}%`}`;case"startsWith":return r`${e} ILIKE ${`${n}%`}`;case"endsWith":return r`${e} ILIKE ${`%${n}`}`;case"like":return r`${e} LIKE ${n}`;case"notLike":return r`${e} NOT LIKE ${n}`;case"ilike":return r`${e} ILIKE ${n}`;case"regex":return r`${e} ~* ${n}`;case"notRegex":return r`${e} !~* ${n}`;default:throw new Error(`Unsupported string operator: ${t}`)}}castToType(e,t){switch(t){case"timestamp":return r`${e}::timestamp`;case"decimal":return r`${e}::decimal`;case"integer":return r`${e}::integer`;default:throw new Error(`Unsupported cast type: ${t}`)}}buildAvg(e){return r`COALESCE(AVG(${e}), 0)`}buildCaseWhen(e,t){const n=e.map(i=>r`WHEN ${i.when} THEN ${i.then}`).reduce((i,s)=>r`${i} ${s}`);return t!==void 0?r`CASE ${n} ELSE ${t} END`:r`CASE ${n} END`}buildBooleanLiteral(e){return e?r`TRUE`:r`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,supportsPercentileSubqueries:!0}}buildStddev(e,t=!1){const n=t?"STDDEV_SAMP":"STDDEV_POP";return r`COALESCE(${r.raw(n)}(${e}), 0)`}buildVariance(e,t=!1){const n=t?"VAR_SAMP":"VAR_POP";return r`COALESCE(${r.raw(n)}(${e}), 0)`}buildPercentile(e,t){const n=t/100;return r`PERCENTILE_CONT(${n}) WITHIN GROUP (ORDER BY ${e})`}buildWindowFunction(e,t,n,i,s){const o=n&&n.length>0?r`PARTITION BY ${r.join(n,r`, `)}`:r``,a=i&&i.length>0?r`ORDER BY ${r.join(i.map(p=>p.direction==="desc"?r`${p.field} DESC`:r`${p.field} ASC`),r`, `)}`:r``;let u=r``;if(s?.frame){const{type:p,start:f,end:h}=s.frame,g=p.toUpperCase(),y=f==="unbounded"?"UNBOUNDED PRECEDING":typeof f=="number"?`${f} PRECEDING`:"CURRENT ROW",b=h==="unbounded"?"UNBOUNDED FOLLOWING":h==="current"?"CURRENT ROW":typeof h=="number"?`${h} FOLLOWING`:"CURRENT ROW";u=r`${r.raw(g)} BETWEEN ${r.raw(y)} AND ${r.raw(b)}`}const c=[];n&&n.length>0&&c.push(o),i&&i.length>0&&c.push(a),s?.frame&&c.push(u);const l=c.length>0?r.join(c,r` `):r``,m=r`OVER (${l})`;switch(e){case"lag":return r`LAG(${t}, ${s?.offset??1}${s?.defaultValue!==void 0?r`, ${s.defaultValue}`:r``}) ${m}`;case"lead":return r`LEAD(${t}, ${s?.offset??1}${s?.defaultValue!==void 0?r`, ${s.defaultValue}`:r``}) ${m}`;case"rank":return r`RANK() ${m}`;case"denseRank":return r`DENSE_RANK() ${m}`;case"rowNumber":return r`ROW_NUMBER() ${m}`;case"ntile":return r`NTILE(${s?.nTile??4}) ${m}`;case"firstValue":return r`FIRST_VALUE(${t}) ${m}`;case"lastValue":return r`LAST_VALUE(${t}) ${m}`;case"movingAvg":return r`AVG(${t}) ${m}`;case"movingSum":return r`SUM(${t}) ${m}`;default:throw new Error(`Unsupported window function: ${e}`)}}}class at extends he{getEngineType(){return"mysql"}supportsLateralJoins(){return!0}buildIntervalFromISO(e){const t=this.parseISODuration(e),n=[];t.years&&n.push(`${t.years} YEAR`),t.months&&n.push(`${t.months} MONTH`),t.days&&n.push(`${t.days} DAY`),t.hours&&n.push(`${t.hours} HOUR`),t.minutes&&n.push(`${t.minutes} MINUTE`),t.seconds&&n.push(`${t.seconds} SECOND`);const i=this.durationToSeconds(e);return r`${i}`}buildTimeDifferenceSeconds(e,t){return r`TIMESTAMPDIFF(SECOND, ${t}, ${e})`}buildDateAddInterval(e,t){const n=this.parseISODuration(t);let i=e;return n.years&&(i=r`DATE_ADD(${i}, INTERVAL ${n.years} YEAR)`),n.months&&(i=r`DATE_ADD(${i}, INTERVAL ${n.months} MONTH)`),n.days&&(i=r`DATE_ADD(${i}, INTERVAL ${n.days} DAY)`),n.hours&&(i=r`DATE_ADD(${i}, INTERVAL ${n.hours} HOUR)`),n.minutes&&(i=r`DATE_ADD(${i}, INTERVAL ${n.minutes} MINUTE)`),n.seconds&&(i=r`DATE_ADD(${i}, INTERVAL ${n.seconds} SECOND)`),i}buildConditionalAggregation(e,t,n){const i=e.toUpperCase();return e==="count"&&!t?r`COUNT(CASE WHEN ${n} THEN 1 END)`:r`${r.raw(i)}(CASE WHEN ${n} THEN ${t} END)`}buildDateDiffPeriods(e,t,n){const i=n.toUpperCase();return r`TIMESTAMPDIFF(${r.raw(i)}, ${e}, ${t})`}buildPeriodSeriesSubquery(e){return r`(
1
+ "use strict";const Y=require("./utils.cjs"),x=Symbol.for("drizzle:entityKind");function I(d,e){if(!d||typeof d!="object")return!1;if(d instanceof e)return!0;if(!Object.prototype.hasOwnProperty.call(e,x))throw new Error(`Class "${e.name??"<unknown>"}" doesn't look like a Drizzle entity. If this is incorrect and the class is provided by Drizzle, please report this as a bug.`);let t=Object.getPrototypeOf(d).constructor;if(t)for(;t;){if(x in t&&t[x]===e[x])return!0;t=Object.getPrototypeOf(t)}return!1}class se{constructor(e,t){this.table=e,this.config=t,this.name=t.name,this.keyAsName=t.keyAsName,this.notNull=t.notNull,this.default=t.default,this.defaultFn=t.defaultFn,this.onUpdateFn=t.onUpdateFn,this.hasDefault=t.hasDefault,this.primary=t.primaryKey,this.isUnique=t.isUnique,this.uniqueName=t.uniqueName,this.uniqueType=t.uniqueType,this.dataType=t.dataType,this.columnType=t.columnType,this.generated=t.generated,this.generatedIdentity=t.generatedIdentity}static[x]="Column";name;keyAsName;primary;notNull;default;defaultFn;onUpdateFn;hasDefault;isUnique;uniqueName;uniqueType;dataType;columnType;enumValues=void 0;generated=void 0;generatedIdentity=void 0;config;mapFromDriverValue(e){return e}mapToDriverValue(e){return e}shouldDisableInsert(){return this.config.generated!==void 0&&this.config.generated.type!=="byDefault"}}const Ce=Symbol.for("drizzle:Name"),Pe=Symbol.for("drizzle:isPgEnum");function Ct(d){return!!d&&typeof d=="function"&&Pe in d&&d[Pe]===!0}class nt{static[x]="Subquery";constructor(e,t,n,i=!1,s=[]){this._={brand:"Subquery",sql:e,selectedFields:t,alias:n,isWith:i,usedTables:s}}}const wt={startActiveSpan(d,e){return e()}},ie=Symbol.for("drizzle:ViewBaseConfig"),we=Symbol.for("drizzle:Schema"),Be=Symbol.for("drizzle:Columns"),ke=Symbol.for("drizzle:ExtraConfigColumns"),$e=Symbol.for("drizzle:OriginalName"),Te=Symbol.for("drizzle:BaseName"),ce=Symbol.for("drizzle:IsAlias"),xe=Symbol.for("drizzle:ExtraConfigBuilder"),$t=Symbol.for("drizzle:IsDrizzleTable");class Q{static[x]="Table";static Symbol={Name:Ce,Schema:we,OriginalName:$e,Columns:Be,ExtraConfigColumns:ke,BaseName:Te,IsAlias:ce,ExtraConfigBuilder:xe};[Ce];[$e];[we];[Be];[ke];[Te];[ce]=!1;[$t]=!0;[xe]=void 0;constructor(e,t,n){this[Ce]=this[$e]=e,this[we]=t,this[Te]=n}}function it(d){return d!=null&&typeof d.getSQL=="function"}function Tt(d){const e={sql:"",params:[]};for(const t of d)e.sql+=t.sql,e.params.push(...t.params),t.typings?.length&&(e.typings||(e.typings=[]),e.typings.push(...t.typings));return e}class P{static[x]="StringChunk";value;constructor(e){this.value=Array.isArray(e)?e:[e]}getSQL(){return new O([this])}}class O{constructor(e){this.queryChunks=e;for(const t of e)if(I(t,Q)){const n=t[Q.Symbol.Schema];this.usedTables.push(n===void 0?t[Q.Symbol.Name]:n+"."+t[Q.Symbol.Name])}}static[x]="SQL";decoder=st;shouldInlineParams=!1;usedTables=[];append(e){return this.queryChunks.push(...e.queryChunks),this}toQuery(e){return wt.startActiveSpan("drizzle.buildSQL",t=>{const n=this.buildQueryFromSourceParams(this.queryChunks,e);return t?.setAttributes({"drizzle.query.text":n.sql,"drizzle.query.params":JSON.stringify(n.params)}),n})}buildQueryFromSourceParams(e,t){const n=Object.assign({},t,{inlineParams:t.inlineParams||this.shouldInlineParams,paramStartIndex:t.paramStartIndex||{value:0}}),{casing:i,escapeName:s,escapeParam:o,prepareTyping:a,inlineParams:u,paramStartIndex:c}=n;return Tt(e.map(l=>{if(I(l,P))return{sql:l.value.join(""),params:[]};if(I(l,_e))return{sql:s(l.value),params:[]};if(l===void 0)return{sql:"",params:[]};if(Array.isArray(l)){const m=[new P("(")];for(const[p,f]of l.entries())m.push(f),p<l.length-1&&m.push(new P(", "));return m.push(new P(")")),this.buildQueryFromSourceParams(m,n)}if(I(l,O))return this.buildQueryFromSourceParams(l.queryChunks,{...n,inlineParams:u||l.shouldInlineParams});if(I(l,Q)){const m=l[Q.Symbol.Schema],p=l[Q.Symbol.Name];return{sql:m===void 0||l[ce]?s(p):s(m)+"."+s(p),params:[]}}if(I(l,se)){const m=i.getColumnCasing(l);if(t.invokeSource==="indexes")return{sql:s(m),params:[]};const p=l.table[Q.Symbol.Schema];return{sql:l.table[ce]||p===void 0?s(l.table[Q.Symbol.Name])+"."+s(m):s(p)+"."+s(l.table[Q.Symbol.Name])+"."+s(m),params:[]}}if(I(l,ot)){const m=l[ie].schema,p=l[ie].name;return{sql:m===void 0||l[ie].isAlias?s(p):s(m)+"."+s(p),params:[]}}if(I(l,de)){if(I(l.value,me))return{sql:o(c.value++,l),params:[l],typings:["none"]};const m=l.value===null?null:l.encoder.mapToDriverValue(l.value);if(I(m,O))return this.buildQueryFromSourceParams([m],n);if(u)return{sql:this.mapInlineParam(m,n),params:[]};let p=["none"];return a&&(p=[a(l.encoder)]),{sql:o(c.value++,m),params:[m],typings:p}}return I(l,me)?{sql:o(c.value++,l),params:[l],typings:["none"]}:I(l,O.Aliased)&&l.fieldAlias!==void 0?{sql:s(l.fieldAlias),params:[]}:I(l,nt)?l._.isWith?{sql:s(l._.alias),params:[]}:this.buildQueryFromSourceParams([new P("("),l._.sql,new P(") "),new _e(l._.alias)],n):Ct(l)?l.schema?{sql:s(l.schema)+"."+s(l.enumName),params:[]}:{sql:s(l.enumName),params:[]}:it(l)?l.shouldOmitSQLParens?.()?this.buildQueryFromSourceParams([l.getSQL()],n):this.buildQueryFromSourceParams([new P("("),l.getSQL(),new P(")")],n):u?{sql:this.mapInlineParam(l,n),params:[]}:{sql:o(c.value++,l),params:[l],typings:["none"]}}))}mapInlineParam(e,{escapeString:t}){if(e===null)return"null";if(typeof e=="number"||typeof e=="boolean")return e.toString();if(typeof e=="string")return t(e);if(typeof e=="object"){const n=e.toString();return t(n==="[object Object]"?JSON.stringify(e):n)}throw new Error("Unexpected param value: "+e)}getSQL(){return this}as(e){return e===void 0?this:new O.Aliased(this,e)}mapWith(e){return this.decoder=typeof e=="function"?{mapFromDriverValue:e}:e,this}inlineParams(){return this.shouldInlineParams=!0,this}if(e){return e?this:void 0}}class _e{constructor(e){this.value=e}static[x]="Name";brand;getSQL(){return new O([this])}}function Et(d){return typeof d=="object"&&d!==null&&"mapToDriverValue"in d&&typeof d.mapToDriverValue=="function"}const st={mapFromDriverValue:d=>d},rt={mapToDriverValue:d=>d};({...st,...rt});class de{constructor(e,t=rt){this.value=e,this.encoder=t}static[x]="Param";brand;getSQL(){return new O([this])}}function r(d,...e){const t=[];(e.length>0||d.length>0&&d[0]!=="")&&t.push(new P(d[0]));for(const[n,i]of e.entries())t.push(i,new P(d[n+1]));return new O(t)}(d=>{function e(){return new O([])}d.empty=e;function t(u){return new O(u)}d.fromList=t;function n(u){return new O([new P(u)])}d.raw=n;function i(u,c){const l=[];for(const[m,p]of u.entries())m>0&&c!==void 0&&l.push(c),l.push(p);return new O(l)}d.join=i;function s(u){return new _e(u)}d.identifier=s;function o(u){return new me(u)}d.placeholder=o;function a(u,c){return new de(u,c)}d.param=a})(r||(r={}));(d=>{class e{constructor(n,i){this.sql=n,this.fieldAlias=i}static[x]="SQL.Aliased";isSelectionField=!1;getSQL(){return this.sql}clone(){return new e(this.sql,this.fieldAlias)}}d.Aliased=e})(O||(O={}));class me{constructor(e){this.name=e}static[x]="Placeholder";getSQL(){return new O([this])}}const St=Symbol.for("drizzle:IsDrizzleView");class ot{static[x]="View";[ie];[St]=!0;constructor({name:e,schema:t,selectedFields:n,query:i}){this[ie]={name:e,originalName:e,schema:t,selectedFields:n,query:i,isExisting:!i,isAlias:!1}}getSQL(){return new O([this])}}se.prototype.getSQL=function(){return new O([this])};Q.prototype.getSQL=function(){return new O([this])};nt.prototype.getSQL=function(){return new O([this])};function B(d,e){return Et(e)&&!it(d)&&!I(d,de)&&!I(d,me)&&!I(d,se)&&!I(d,Q)&&!I(d,ot)?new de(d,e):d}const k=(d,e)=>r`${d} = ${B(e,d)}`,Ue=(d,e)=>r`${d} <> ${B(e,d)}`;function A(...d){const e=d.filter(t=>t!==void 0);if(e.length!==0)return e.length===1?new O(e):new O([new P("("),r.join(e,new P(" and ")),new P(")")])}function oe(...d){const e=d.filter(t=>t!==void 0);if(e.length!==0)return e.length===1?new O(e):new O([new P("("),r.join(e,new P(" or ")),new P(")")])}const Ee=(d,e)=>r`${d} > ${B(e,d)}`,ee=(d,e)=>r`${d} >= ${B(e,d)}`,Se=(d,e)=>r`${d} < ${B(e,d)}`,te=(d,e)=>r`${d} <= ${B(e,d)}`;function De(d,e){return Array.isArray(e)?e.length===0?r`false`:r`${d} in ${e.map(t=>B(t,d))}`:r`${d} in ${B(e,d)}`}function Qe(d,e){return Array.isArray(e)?e.length===0?r`true`:r`${d} not in ${e.map(t=>B(t,d))}`:r`${d} not in ${B(e,d)}`}function Ke(d){return r`${d} is null`}function We(d){return r`${d} is not null`}function Dt(d,e){if(Array.isArray(e)){if(e.length===0)throw new Error("arrayContains requires at least one value");const t=r`${B(e,d)}`;return r`${d} @> ${t}`}return r`${d} @> ${B(e,d)}`}function Nt(d,e){if(Array.isArray(e)){if(e.length===0)throw new Error("arrayContained requires at least one value");const t=r`${B(e,d)}`;return r`${d} <@ ${t}`}return r`${d} <@ ${B(e,d)}`}function At(d,e){if(Array.isArray(e)){if(e.length===0)throw new Error("arrayOverlaps requires at least one value");const t=r`${B(e,d)}`;return r`${d} && ${t}`}return r`${d} && ${B(e,d)}`}function Je(d){return r`${d} asc`}function _t(d){return r`${d} desc`}function ve(d){return r`count(${d||r.raw("*")})`.mapWith(Number)}function vt(d){return r`count(distinct ${d})`.mapWith(Number)}function V(d){return r`sum(${d})`.mapWith(String)}function H(d){return r`max(${d})`.mapWith(I(d,se)?d:String)}function ae(d){return r`min(${d})`.mapWith(I(d,se)?d:String)}class he{preprocessCalculatedTemplate(e){return e}buildPattern(e,t){switch(e){case"contains":case"notContains":return`%${t}%`;case"startsWith":return`${t}%`;case"endsWith":return`%${t}`;default:return t}}parseISODuration(e){const t={years:0,months:0,days:0,hours:0,minutes:0,seconds:0},n=/^P(?:(\d+)Y)?(?:(\d+)M)?(?:(\d+)D)?(?:T(?:(\d+)H)?(?:(\d+)M)?(?:(\d+(?:\.\d+)?)S)?)?$/,i=e.match(n);if(!i)throw new Error(`Invalid ISO 8601 duration format: ${e}`);return t.years=parseInt(i[1]||"0",10),t.months=parseInt(i[2]||"0",10),t.days=parseInt(i[3]||"0",10),t.hours=parseInt(i[4]||"0",10),t.minutes=parseInt(i[5]||"0",10),t.seconds=parseFloat(i[6]||"0"),t}durationToSeconds(e){const t=this.parseISODuration(e);return t.years*365*24*60*60+t.months*30*24*60*60+t.days*24*60*60+t.hours*60*60+t.minutes*60+t.seconds}}class Rt extends he{getEngineType(){return"postgres"}supportsLateralJoins(){return!0}buildIntervalFromISO(e){const t=this.parseISODuration(e),n=[];t.years&&n.push(`${t.years} years`),t.months&&n.push(`${t.months} months`),t.days&&n.push(`${t.days} days`),t.hours&&n.push(`${t.hours} hours`),t.minutes&&n.push(`${t.minutes} minutes`),t.seconds&&n.push(`${t.seconds} seconds`);const i=n.join(" ")||"0 seconds";return r`INTERVAL '${r.raw(i)}'`}buildTimeDifferenceSeconds(e,t){return r`EXTRACT(EPOCH FROM (${e} - ${t}))`}buildDateAddInterval(e,t){const n=this.buildIntervalFromISO(t);return r`(${e} + ${n})`}buildConditionalAggregation(e,t,n){const i=e.toUpperCase();return e==="count"&&!t?r`COUNT(*) FILTER (WHERE ${n})`:r`${r.raw(i)}(${t}) FILTER (WHERE ${n})`}buildDateDiffPeriods(e,t,n){switch(n){case"day":return r`(${t}::date - ${e}::date)`;case"week":return r`FLOOR((${t}::date - ${e}::date) / 7)`;case"month":return r`(EXTRACT(YEAR FROM AGE(${t}::timestamp, ${e}::timestamp)) * 12 + EXTRACT(MONTH FROM AGE(${t}::timestamp, ${e}::timestamp)))::integer`;default:throw new Error(`Unsupported date diff unit: ${n}`)}}buildPeriodSeriesSubquery(e){return r`(SELECT generate_series(0, ${e}) as period_number) p`}buildTimeDimension(e,t){switch(e){case"year":return r`DATE_TRUNC('year', ${t}::timestamp)`;case"quarter":return r`DATE_TRUNC('quarter', ${t}::timestamp)`;case"month":return r`DATE_TRUNC('month', ${t}::timestamp)`;case"week":return r`DATE_TRUNC('week', ${t}::timestamp)`;case"day":return r`DATE_TRUNC('day', ${t}::timestamp)::timestamp`;case"hour":return r`DATE_TRUNC('hour', ${t}::timestamp)`;case"minute":return r`DATE_TRUNC('minute', ${t}::timestamp)`;case"second":return r`DATE_TRUNC('second', ${t}::timestamp)`;default:return t}}buildStringCondition(e,t,n){switch(t){case"contains":return r`${e} ILIKE ${`%${n}%`}`;case"notContains":return r`${e} NOT ILIKE ${`%${n}%`}`;case"startsWith":return r`${e} ILIKE ${`${n}%`}`;case"endsWith":return r`${e} ILIKE ${`%${n}`}`;case"like":return r`${e} LIKE ${n}`;case"notLike":return r`${e} NOT LIKE ${n}`;case"ilike":return r`${e} ILIKE ${n}`;case"regex":return r`${e} ~* ${n}`;case"notRegex":return r`${e} !~* ${n}`;default:throw new Error(`Unsupported string operator: ${t}`)}}castToType(e,t){switch(t){case"timestamp":return r`${e}::timestamp`;case"decimal":return r`${e}::decimal`;case"integer":return r`${e}::integer`;default:throw new Error(`Unsupported cast type: ${t}`)}}buildAvg(e){return r`COALESCE(AVG(${e}), 0)`}buildCaseWhen(e,t){const n=e.map(i=>r`WHEN ${i.when} THEN ${i.then}`).reduce((i,s)=>r`${i} ${s}`);return t!==void 0?r`CASE ${n} ELSE ${t} END`:r`CASE ${n} END`}buildBooleanLiteral(e){return e?r`TRUE`:r`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,supportsPercentileSubqueries:!0}}buildStddev(e,t=!1){const n=t?"STDDEV_SAMP":"STDDEV_POP";return r`COALESCE(${r.raw(n)}(${e}), 0)`}buildVariance(e,t=!1){const n=t?"VAR_SAMP":"VAR_POP";return r`COALESCE(${r.raw(n)}(${e}), 0)`}buildPercentile(e,t){const n=t/100;return r`PERCENTILE_CONT(${n}) WITHIN GROUP (ORDER BY ${e})`}buildWindowFunction(e,t,n,i,s){const o=n&&n.length>0?r`PARTITION BY ${r.join(n,r`, `)}`:r``,a=i&&i.length>0?r`ORDER BY ${r.join(i.map(p=>p.direction==="desc"?r`${p.field} DESC`:r`${p.field} ASC`),r`, `)}`:r``;let u=r``;if(s?.frame){const{type:p,start:f,end:h}=s.frame,g=p.toUpperCase(),y=f==="unbounded"?"UNBOUNDED PRECEDING":typeof f=="number"?`${f} PRECEDING`:"CURRENT ROW",b=h==="unbounded"?"UNBOUNDED FOLLOWING":h==="current"?"CURRENT ROW":typeof h=="number"?`${h} FOLLOWING`:"CURRENT ROW";u=r`${r.raw(g)} BETWEEN ${r.raw(y)} AND ${r.raw(b)}`}const c=[];n&&n.length>0&&c.push(o),i&&i.length>0&&c.push(a),s?.frame&&c.push(u);const l=c.length>0?r.join(c,r` `):r``,m=r`OVER (${l})`;switch(e){case"lag":return r`LAG(${t}, ${s?.offset??1}${s?.defaultValue!==void 0?r`, ${s.defaultValue}`:r``}) ${m}`;case"lead":return r`LEAD(${t}, ${s?.offset??1}${s?.defaultValue!==void 0?r`, ${s.defaultValue}`:r``}) ${m}`;case"rank":return r`RANK() ${m}`;case"denseRank":return r`DENSE_RANK() ${m}`;case"rowNumber":return r`ROW_NUMBER() ${m}`;case"ntile":return r`NTILE(${s?.nTile??4}) ${m}`;case"firstValue":return r`FIRST_VALUE(${t}) ${m}`;case"lastValue":return r`LAST_VALUE(${t}) ${m}`;case"movingAvg":return r`AVG(${t}) ${m}`;case"movingSum":return r`SUM(${t}) ${m}`;default:throw new Error(`Unsupported window function: ${e}`)}}}class at extends he{getEngineType(){return"mysql"}supportsLateralJoins(){return!0}buildIntervalFromISO(e){const t=this.parseISODuration(e),n=[];t.years&&n.push(`${t.years} YEAR`),t.months&&n.push(`${t.months} MONTH`),t.days&&n.push(`${t.days} DAY`),t.hours&&n.push(`${t.hours} HOUR`),t.minutes&&n.push(`${t.minutes} MINUTE`),t.seconds&&n.push(`${t.seconds} SECOND`);const i=this.durationToSeconds(e);return r`${i}`}buildTimeDifferenceSeconds(e,t){return r`TIMESTAMPDIFF(SECOND, ${t}, ${e})`}buildDateAddInterval(e,t){const n=this.parseISODuration(t);let i=e;return n.years&&(i=r`DATE_ADD(${i}, INTERVAL ${n.years} YEAR)`),n.months&&(i=r`DATE_ADD(${i}, INTERVAL ${n.months} MONTH)`),n.days&&(i=r`DATE_ADD(${i}, INTERVAL ${n.days} DAY)`),n.hours&&(i=r`DATE_ADD(${i}, INTERVAL ${n.hours} HOUR)`),n.minutes&&(i=r`DATE_ADD(${i}, INTERVAL ${n.minutes} MINUTE)`),n.seconds&&(i=r`DATE_ADD(${i}, INTERVAL ${n.seconds} SECOND)`),i}buildConditionalAggregation(e,t,n){const i=e.toUpperCase();return e==="count"&&!t?r`COUNT(CASE WHEN ${n} THEN 1 END)`:r`${r.raw(i)}(CASE WHEN ${n} THEN ${t} END)`}buildDateDiffPeriods(e,t,n){const i=n.toUpperCase();return r`TIMESTAMPDIFF(${r.raw(i)}, ${e}, ${t})`}buildPeriodSeriesSubquery(e){return r`(
2
2
  WITH RECURSIVE periods(period_number) AS (
3
3
  SELECT 0
4
4
  UNION ALL
@@ -57,7 +57,7 @@
57
57
  WHERE LOWER(table_name) IN (${r.raw(t)})
58
58
  GROUP BY table_name, index_name, is_unique, is_primary
59
59
  ORDER BY table_name, index_name
60
- `);return Array.isArray(n)?n.map(i=>({table_name:i.table_name,index_name:i.index_name,columns:typeof i.columns=="string"?i.columns.split(","):[],is_unique:!!i.is_unique,is_primary:!!i.is_primary})):[]}catch(t){return console.warn("Failed to get table indexes:",t),[]}}}function Ht(d,e){return new Gt(d,e,"duckdb")}function Ve(d,e,t){if(t)switch(t){case"postgres":return ze(d,e);case"mysql":return xt(d,e);case"sqlite":return qe(d,e);case"singlestore":return Jt(d,e);case"duckdb":return Ht(d,e)}if(d.all&&d.run)return qe(d,e);if(d.execute)return ze(d,e);throw new Error("Unable to determine database engine type. Please specify engineType parameter.")}function q(d){return typeof d=="function"?d():d}function Re(d,e){if(e)return e;switch(d){case"belongsTo":return"inner";case"hasOne":return"left";case"hasMany":return"left";case"belongsToMany":return"left";default:return"left"}}function Fe(d){return d&&typeof d=="object"?r`${r`${d}`}`:d}function R(d,e){const t=typeof d=="function"?d(e):d;return Fe(t)}function Yt(d,e){if(d.relationship!=="belongsToMany"||!d.through)throw new Error("expandBelongsToManyJoin can only be called on belongsToMany relationships with through configuration");const{table:t,sourceKey:n,targetKey:i,securitySql:s}=d.through,o=[];for(const l of n){const m=l.as||k;o.push(m(l.source,l.target))}const a=[];for(const l of i){const m=l.as||k;a.push(m(l.source,l.target))}let u;if(s){const l=s(e);u=Array.isArray(l)?l:[l]}const c=Re("belongsToMany",d.sqlJoinType);return{junctionJoins:[{joinType:c,table:t,condition:A(...o)},{joinType:c,table:t,condition:A(...a)}],junctionSecurityConditions:u}}function fe(d){if("and"in d)return`and:[${d.and.map(fe).sort().join(",")}]`;if("or"in d)return`or:[${d.or.map(fe).sort().join(",")}]`;const e=d,t=JSON.stringify(Array.isArray(e.values)?[...e.values].sort():e.values),n=e.dateRange?`:dr:${JSON.stringify(e.dateRange)}`:"";return`${e.member}:${e.operator}:${t}${n}`}function lt(d,e){return`timeDim:${d}:${JSON.stringify(e)}`}class ne{cache=new Map;stats={hits:0,misses:0};getOrBuild(e,t){const n=this.cache.get(e);if(n!==void 0)return this.stats.hits++,n;const i=t();return i&&this.cache.set(e,i),this.stats.misses++,i}has(e){return this.cache.has(e)}get(e){const t=this.cache.get(e);return t!==void 0&&this.stats.hits++,t}preload(e){for(const{key:t,sql:n}of e)this.cache.has(t)||this.cache.set(t,n)}set(e,t){this.cache.set(e,t)}getStats(){return{...this.stats,cacheSize:this.cache.size}}clear(){this.cache.clear(),this.stats={hits:0,misses:0}}}function Me(d){const e=[];for(const t of d)"and"in t&&t.and?e.push(...Me(t.and)):"or"in t&&t.or?e.push(...Me(t.or)):"member"in t&&e.push(t);return e}function Xt(d,e,t={}){const n=t.keyPrefix??"drizzle-cube:",i=Zt(d),s=Ge(JSON.stringify(i));let o=`${n}query:${s}`;if(t.includeSecurityContext!==!1){const a=t.securityContextSerializer?t.securityContextSerializer(e):JSON.stringify(pe(e)),u=Ge(a);o+=`:ctx:${u}`}return o}function Zt(d){return{measures:d.measures?[...d.measures].sort():void 0,dimensions:d.dimensions?[...d.dimensions].sort():void 0,filters:d.filters?K(d.filters):void 0,timeDimensions:d.timeDimensions?sn(d.timeDimensions):void 0,limit:d.limit,offset:d.offset,order:d.order?pe(d.order):void 0,fillMissingDatesValue:d.fillMissingDatesValue,funnel:d.funnel?en(d.funnel):void 0,flow:d.flow?tn(d.flow):void 0,retention:d.retention?nn(d.retention):void 0}}function en(d){return{bindingKey:d.bindingKey,timeDimension:d.timeDimension,steps:d.steps.map(e=>{const t={name:e.name,filter:e.filter?Array.isArray(e.filter)?K(e.filter):K([e.filter])[0]:void 0,timeToConvert:e.timeToConvert};return"cube"in e&&e.cube&&(t.cube=e.cube),t}),includeTimeMetrics:d.includeTimeMetrics,globalTimeWindow:d.globalTimeWindow}}function tn(d){return{bindingKey:d.bindingKey,timeDimension:d.timeDimension,eventDimension:d.eventDimension,startingStep:{name:d.startingStep.name,filter:d.startingStep.filter?Array.isArray(d.startingStep.filter)?K(d.startingStep.filter):K([d.startingStep.filter])[0]:void 0},stepsBefore:d.stepsBefore,stepsAfter:d.stepsAfter,entityLimit:d.entityLimit,outputMode:d.outputMode,joinStrategy:d.joinStrategy}}function nn(d){return{timeDimension:d.timeDimension,bindingKey:d.bindingKey,dateRange:d.dateRange,granularity:d.granularity,periods:d.periods,retentionType:d.retentionType,cohortFilters:d.cohortFilters?Array.isArray(d.cohortFilters)?K(d.cohortFilters):K([d.cohortFilters])[0]:void 0,activityFilters:d.activityFilters?Array.isArray(d.activityFilters)?K(d.activityFilters):K([d.activityFilters])[0]:void 0,breakdownDimensions:d.breakdownDimensions}}function K(d){return[...d].map(e=>{if("and"in e&&e.and)return{and:K(e.and)};if("or"in e&&e.or)return{or:K(e.or)};const t=e;return{...t,values:t.values?[...t.values].sort():t.values}}).sort((e,t)=>JSON.stringify(e).localeCompare(JSON.stringify(t)))}function sn(d){return[...d].map(e=>({dimension:e.dimension,granularity:e.granularity,dateRange:e.dateRange,fillMissingDates:e.fillMissingDates,compareDateRange:e.compareDateRange?[...e.compareDateRange].sort((t,n)=>{const i=Array.isArray(t)?t.join("-"):t,s=Array.isArray(n)?n.join("-"):n;return i.localeCompare(s)}):void 0})).sort((e,t)=>e.dimension.localeCompare(t.dimension))}function pe(d){return d===null||typeof d!="object"?d:Array.isArray(d)?d.map(pe):Object.keys(d).sort().reduce((e,t)=>(e[t]=pe(d[t]),e),{})}function Ge(d){let e=2166136261;for(let t=0;t<d.length;t++)e^=d.charCodeAt(t),e=e*16777619>>>0;return e.toString(16).padStart(8,"0")}class re{constructor(e){this.databaseAdapter=e}buildTimeDimensionExpression(e,t,n){const i=R(e,n);return t?this.databaseAdapter.buildTimeDimension(t,i):i instanceof O?i:r`${i}`}buildDateRangeCondition(e,t){if(!t)return null;if(Array.isArray(t)&&t.length>=2){const n=this.normalizeDate(t[0]);let i=this.normalizeDate(t[1]);if(!n||!i)return null;if(typeof t[1]=="string"&&/^\d{4}-\d{2}-\d{2}$/.test(t[1].trim())){const s=typeof i=="number"?new Date(i*(this.databaseAdapter.getEngineType()==="sqlite"?1e3:1)):new Date(i),o=new Date(s);o.setUTCHours(23,59,59,999),this.databaseAdapter.isTimestampInteger()?i=this.databaseAdapter.getEngineType()==="sqlite"?Math.floor(o.getTime()/1e3):o.getTime():i=o.toISOString()}return A(ee(e,n),te(e,i))}if(typeof t=="string"){const n=this.parseRelativeDateRange(t);if(n){let l,m;return this.databaseAdapter.isTimestampInteger()?this.databaseAdapter.getEngineType()==="sqlite"?(l=Math.floor(n.start.getTime()/1e3),m=Math.floor(n.end.getTime()/1e3)):(l=n.start.getTime(),m=n.end.getTime()):(l=n.start.toISOString(),m=n.end.toISOString()),A(ee(e,l),te(e,m))}const i=this.normalizeDate(t);if(!i)return null;const s=typeof i=="number"?new Date(i*(this.databaseAdapter.getEngineType()==="sqlite"?1e3:1)):new Date(i),o=new Date(s);o.setUTCHours(0,0,0,0);const a=new Date(s);a.setUTCHours(23,59,59,999);let u,c;return this.databaseAdapter.isTimestampInteger()?this.databaseAdapter.getEngineType()==="sqlite"?(u=Math.floor(o.getTime()/1e3),c=Math.floor(a.getTime()/1e3)):(u=o.getTime(),c=a.getTime()):(u=o.toISOString(),c=a.toISOString()),A(ee(e,u),te(e,c))}return null}parseRelativeDateRange(e){const t=new Date,n=e.toLowerCase().trim(),i=t.getUTCFullYear(),s=t.getUTCMonth(),o=t.getUTCDate(),a=t.getUTCDay();if(n==="today"){const p=new Date(t);p.setUTCHours(0,0,0,0);const f=new Date(t);return f.setUTCHours(23,59,59,999),{start:p,end:f}}if(n==="yesterday"){const p=new Date(t);p.setUTCDate(o-1),p.setUTCHours(0,0,0,0);const f=new Date(t);return f.setUTCDate(o-1),f.setUTCHours(23,59,59,999),{start:p,end:f}}if(n==="this week"){const p=a===0?-6:1-a,f=new Date(t);f.setUTCDate(o+p),f.setUTCHours(0,0,0,0);const h=new Date(f);return h.setUTCDate(f.getUTCDate()+6),h.setUTCHours(23,59,59,999),{start:f,end:h}}if(n==="this month"){const p=new Date(Date.UTC(i,s,1,0,0,0,0)),f=new Date(Date.UTC(i,s+1,0,23,59,59,999));return{start:p,end:f}}if(n==="this quarter"){const p=Math.floor(s/3),f=new Date(Date.UTC(i,p*3,1,0,0,0,0)),h=new Date(Date.UTC(i,p*3+3,0,23,59,59,999));return{start:f,end:h}}if(n==="this year"){const p=new Date(Date.UTC(i,0,1,0,0,0,0)),f=new Date(Date.UTC(i,11,31,23,59,59,999));return{start:p,end:f}}const u=n.match(/^last\s+(\d+)\s+days?$/);if(u){const p=parseInt(u[1],10),f=new Date(t);f.setUTCDate(o-p+1),f.setUTCHours(0,0,0,0);const h=new Date(t);return h.setUTCHours(23,59,59,999),{start:f,end:h}}const c=n.match(/^last\s+(\d+)\s+weeks?$/);if(c){const f=parseInt(c[1],10)*7,h=new Date(t);h.setUTCDate(o-f+1),h.setUTCHours(0,0,0,0);const g=new Date(t);return g.setUTCHours(23,59,59,999),{start:h,end:g}}if(n==="last week"){const p=a===0?-13:-6-a,f=new Date(t);f.setUTCDate(o+p),f.setUTCHours(0,0,0,0);const h=new Date(f);return h.setUTCDate(f.getUTCDate()+6),h.setUTCHours(23,59,59,999),{start:f,end:h}}if(n==="last month"){const p=new Date(Date.UTC(i,s-1,1,0,0,0,0)),f=new Date(Date.UTC(i,s,0,23,59,59,999));return{start:p,end:f}}if(n==="last quarter"){const p=Math.floor(s/3),f=p===0?3:p-1,h=p===0?i-1:i,g=new Date(Date.UTC(h,f*3,1,0,0,0,0)),y=new Date(Date.UTC(h,f*3+3,0,23,59,59,999));return{start:g,end:y}}if(n==="last year"){const p=new Date(Date.UTC(i-1,0,1,0,0,0,0)),f=new Date(Date.UTC(i-1,11,31,23,59,59,999));return{start:p,end:f}}if(n==="last 12 months"){const p=new Date(Date.UTC(i,s-11,1,0,0,0,0)),f=new Date(t);return f.setUTCHours(23,59,59,999),{start:p,end:f}}const l=n.match(/^last\s+(\d+)\s+months?$/);if(l){const p=parseInt(l[1],10),f=new Date(Date.UTC(i,s-p+1,1,0,0,0,0)),h=new Date(t);return h.setUTCHours(23,59,59,999),{start:f,end:h}}const m=n.match(/^last\s+(\d+)\s+years?$/);if(m){const p=parseInt(m[1],10),f=new Date(Date.UTC(i-p,0,1,0,0,0,0)),h=new Date(t);return h.setUTCHours(23,59,59,999),{start:f,end:h}}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 n=e<1e10?e*1e3:e,i=new Date(n);return isNaN(i.getTime())?null:this.databaseAdapter.isTimestampInteger()?this.databaseAdapter.getEngineType()==="sqlite"?Math.floor(n/1e3):n:i.toISOString()}if(typeof e=="string"){if(/^\d{4}-\d{2}-\d{2}$/.test(e.trim())){const i=new Date(e+"T00:00:00Z");return isNaN(i.getTime())?null:this.databaseAdapter.isTimestampInteger()?this.databaseAdapter.getEngineType()==="sqlite"?Math.floor(i.getTime()/1e3):i.getTime():i.toISOString()}const n=new Date(e);return isNaN(n.getTime())?null:this.databaseAdapter.isTimestampInteger()?this.databaseAdapter.getEngineType()==="sqlite"?Math.floor(n.getTime()/1e3):n.getTime():n.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()}}class be{constructor(e,t){this.databaseAdapter=e,this.dateTimeBuilder=t}buildFilterCondition(e,t,n,i,s){if(s!==void 0){if(t!=="inDateRange")throw new Error(`dateRange can only be used with 'inDateRange' operator, but got '${t}'. Use explicit date values in the 'values' array for other date operators.`);if(i&&i.type!=="time")throw new Error(`dateRange can only be used on time dimensions, but field '${i.name||"unknown"}' has type '${i.type}'`);return this.dateTimeBuilder.buildDateRangeCondition(e,s)}if(!n||n.length===0)return t==="equals"?this.databaseAdapter.buildBooleanLiteral(!1):null;const o=n.filter(u=>!(u==null||u===""||typeof u=="string"&&u.includes("\0"))).map(this.databaseAdapter.convertFilterValue);if(o.length===0&&!["set","notSet"].includes(t))return t==="equals"?this.databaseAdapter.buildBooleanLiteral(!1):null;const a=o[0];switch(t){case"equals":if(o.length>1){if(i?.type==="time"){const u=o.map(c=>this.dateTimeBuilder.normalizeDate(c)||c);return De(e,u)}return De(e,o)}else if(o.length===1){const u=i?.type==="time"&&this.dateTimeBuilder.normalizeDate(a)||a;return k(e,u)}return this.databaseAdapter.buildBooleanLiteral(!1);case"notEquals":return o.length>1?Qe(e,o):o.length===1?Ue(e,a):null;case"contains":return this.databaseAdapter.buildStringCondition(e,"contains",a);case"notContains":return this.databaseAdapter.buildStringCondition(e,"notContains",a);case"startsWith":return this.databaseAdapter.buildStringCondition(e,"startsWith",a);case"endsWith":return this.databaseAdapter.buildStringCondition(e,"endsWith",a);case"gt":return Ee(e,a);case"gte":return ee(e,a);case"lt":return Se(e,a);case"lte":return te(e,a);case"set":return We(e);case"notSet":return Ke(e);case"inDateRange":if(o.length>=2){const u=this.dateTimeBuilder.normalizeDate(o[0]);let c=this.dateTimeBuilder.normalizeDate(o[1]);if(u&&c){const l=n[1];if(typeof l=="string"&&/^\d{4}-\d{2}-\d{2}$/.test(l.trim())){const m=typeof c=="number"?new Date(c*(this.databaseAdapter.getEngineType()==="sqlite"?1e3:1)):new Date(c),p=new Date(m);p.setUTCHours(23,59,59,999),this.databaseAdapter.isTimestampInteger()?c=this.databaseAdapter.getEngineType()==="sqlite"?Math.floor(p.getTime()/1e3):p.getTime():c=p.toISOString()}return A(ee(e,u),te(e,c))}}return null;case"beforeDate":{const u=this.dateTimeBuilder.normalizeDate(a);return u?Se(e,u):null}case"afterDate":{const u=this.dateTimeBuilder.normalizeDate(a);return u?Ee(e,u):null}case"between":return o.length>=2?A(ee(e,o[0]),te(e,o[1])):null;case"notBetween":return o.length>=2?oe(Se(e,o[0]),Ee(e,o[1])):null;case"in":return o.length>0?De(e,o):null;case"notIn":return o.length>0?Qe(e,o):null;case"like":return this.databaseAdapter.buildStringCondition(e,"like",a);case"notLike":return this.databaseAdapter.buildStringCondition(e,"notLike",a);case"ilike":return this.databaseAdapter.buildStringCondition(e,"ilike",a);case"regex":return this.databaseAdapter.buildStringCondition(e,"regex",a);case"notRegex":return this.databaseAdapter.buildStringCondition(e,"notRegex",a);case"isEmpty":return oe(Ke(e),k(e,""));case"isNotEmpty":return A(We(e),Ue(e,""));case"arrayContains":return this.databaseAdapter.getEngineType()==="postgres"?Dt(e,o):null;case"arrayOverlaps":return this.databaseAdapter.getEngineType()==="postgres"?At(e,o):null;case"arrayContained":return this.databaseAdapter.getEngineType()==="postgres"?Nt(e,o):null;default:return null}}buildLogicalFilter(e,t,n){if("and"in e&&e.and){const i=e.and.map(s=>this.buildSingleFilter(s,t,n)).filter(s=>s!==null);return i.length>0?i.length===1?i[0]:A(...i):null}if("or"in e&&e.or){const i=e.or.map(s=>this.buildSingleFilter(s,t,n)).filter(s=>s!==null);return i.length>0?i.length===1?i[0]:oe(...i):null}return null}buildSingleFilter(e,t,n){if("and"in e||"or"in e)return this.buildLogicalFilter(e,t,n);const i=e,[s,o]=i.member.split("."),a=t.get(s);if(!a)return null;const u=a.dimensions?.[o];if(!u)return null;const c=R(u.sql,n);return this.buildFilterCondition(c,i.operator,i.values,u,i.dateRange)}}class X{dependencyGraph;cubes;constructor(e){this.cubes=e instanceof Map?e:new Map([[e.name,e]]),this.dependencyGraph=new Map}extractDependencies(e){const t=/\{([^}]+)\}/g,n=e.matchAll(t),i=[];for(const s of n){const o=s[1].trim();if(o.includes(".")){const[a,u]=o.split(".");i.push({measureName:o,cubeName:a.trim(),fieldName:u.trim()})}else i.push({measureName:o,cubeName:null,fieldName:o})}return i}buildGraph(e){for(const[t,n]of Object.entries(e.measures))if(n.type==="calculated"&&n.calculatedSql){const i=`${e.name}.${t}`,s=this.extractDependencies(n.calculatedSql),o=new Set;for(const a of s){const c=`${a.cubeName||e.name}.${a.fieldName}`;o.add(c)}this.dependencyGraph.set(i,{id:i,dependencies:o,inDegree:0})}this.calculateInDegrees()}buildGraphForMultipleCubes(e){for(const t of e.values())this.buildGraph(t)}calculateInDegrees(){for(const e of this.dependencyGraph.values())e.inDegree=0;for(const e of this.dependencyGraph.values())for(const t of e.dependencies){const n=this.dependencyGraph.get(t);n&&n.inDegree++}}topologicalSort(e){const t=new Map,n=[],i=[];for(const s of e){const o=this.dependencyGraph.get(s);o&&t.set(s,{id:o.id,dependencies:new Set(o.dependencies),inDegree:0})}for(const s of t.values()){let o=0;for(const a of s.dependencies)t.has(a)&&o++;s.inDegree=o}for(const[s,o]of t)o.inDegree===0&&n.push(s);for(;n.length>0;){const s=n.shift();i.push(s);for(const[o,a]of t)a.dependencies.has(s)&&(a.inDegree--,a.inDegree===0&&n.push(o))}if(i.length<t.size){const s=this.detectCycle();throw new Error(`Circular dependency detected in calculated measures: ${s?s.join(" -> "):"unknown cycle"}`)}return i}detectCycle(){const e=new Set,t=new Set,n=[];for(const i of this.dependencyGraph.keys())if(!e.has(i)){const s=this.dfs(i,e,t,n);if(s)return s}return null}dfs(e,t,n,i){t.add(e),n.add(e),i.push(e);const s=this.dependencyGraph.get(e);if(!s)return i.pop(),n.delete(e),null;for(const o of s.dependencies)if(t.has(o)){if(n.has(o)){const a=i.indexOf(o);return[...i.slice(a),o]}}else{const a=this.dfs(o,t,n,i);if(a)return a}return i.pop(),n.delete(e),null}getAllDependencies(e){const t=new Set,n=new Set,i=s=>{if(n.has(s))return;n.add(s);const o=this.dependencyGraph.get(s);if(o)for(const a of o.dependencies)t.add(a),i(a)};return i(e),t}validateDependencies(e){for(const[t,n]of Object.entries(e.measures))if(n.type==="calculated"&&n.calculatedSql){const i=this.extractDependencies(n.calculatedSql);for(const s of i){const o=s.cubeName||e.name,a=this.cubes.get(o);if(!a)throw new Error(`Calculated measure '${e.name}.${t}' references unknown cube '${o}'`);if(!a.measures[s.fieldName])throw new Error(`Calculated measure '${e.name}.${t}' references unknown measure '${s.measureName}'`);if(o===e.name&&s.fieldName===t)throw new Error(`Calculated measure '${e.name}.${t}' cannot reference itself`)}}}populateDependencies(e){for(const[,t]of Object.entries(e.measures))if(t.type==="calculated"&&t.calculatedSql&&!t.dependencies){const n=this.extractDependencies(t.calculatedSql);t.dependencies=n.map(i=>i.measureName)}}static isCalculatedMeasure(e){return e.type==="calculated"&&!!e.calculatedSql}}function rn(d,e){const{cube:t,allCubes:n,resolvedMeasures:i}=e,s=Oe(d),o=new Map;for(const m of s){const{originalRef:p,cubeName:f,fieldName:h}=m,g=f||t.name;if(!n.get(g))throw new Error(`Cannot substitute {${p}}: cube '${g}' not found`);const b=`${g}.${h}`,w=i.get(b);if(!w)throw new Error(`Cannot substitute {${p}}: measure '${b}' not resolved yet. Ensure measures are resolved in dependency order.`);const $=w(),S=r`${$}`;o.set(p,S)}const a=[],u=[];let c=0;for(const m of s){const p=`{${m.originalRef}}`,f=d.indexOf(p,c);if(f>=0){a.push(d.substring(c,f));const h=o.get(m.originalRef);h&&u.push(h),c=f+p.length}}if(a.push(d.substring(c)),u.length===0)return r.raw(d);const l=[];for(let m=0;m<a.length;m++)a[m]&&l.push(new P(a[m])),m<u.length&&l.push(u[m]);return r.join(l,r.raw(""))}function Oe(d){const e=/\{([^}]+)\}/g,t=d.matchAll(e),n=[];for(const i of t){const s=i[1].trim();if(s.includes(".")){const[o,a]=s.split(".").map(u=>u.trim());n.push({originalRef:s,cubeName:o,fieldName:a})}else n.push({originalRef:s,cubeName:null,fieldName:s})}return n}function on(d){const e=[];let t=0;for(let o=0;o<d.length;o++)if(d[o]==="{")t++;else if(d[o]==="}"&&(t--,t<0)){e.push(`Unmatched closing brace at position ${o}`);break}t>0&&e.push("Unmatched opening brace in template"),/\{\s*\}/.test(d)&&e.push("Empty member reference {} found in template"),/\{[^}]*\{/.test(d)&&e.push("Nested braces are not allowed in member references");const s=Oe(d);for(const o of s){const a=o.cubeName?`${o.cubeName}.${o.fieldName}`:o.fieldName;/^[a-zA-Z_][a-zA-Z0-9_.]*$/.test(a)||e.push(`Invalid member reference {${o.originalRef}}: must start with letter or underscore, and contain only letters, numbers, underscores, and dots`),a.split(".").length>2&&e.push(`Invalid member reference {${o.originalRef}}: only one dot allowed (Cube.measure format)`)}return{isValid:e.length===0,errors:e}}function Ne(d,e){const t=Oe(d),n=new Set;for(const i of t){const o=`${i.cubeName||e}.${i.fieldName}`;n.add(o)}return Array.from(n)}class L{constructor(e){this.databaseAdapter=e}buildResolvedMeasures(e,t,n,i){const s=new Map,o=[],a=[],u=new Set(e),c=new X(t);for(const l of t.values())c.buildGraph(l);for(const l of e){const[m,p]=l.split("."),f=t.get(m);if(f&&f.measures&&f.measures[p]){const h=f.measures[p];if(L.isPostAggregationWindow(h)){const g=L.getWindowBaseMeasure(h,m);g&&u.add(g);continue}X.isCalculatedMeasure(h)?(a.push(l),Ne(h.calculatedSql,m).forEach(b=>u.add(b)),c.getAllDependencies(l).forEach(b=>{const[w,$]=b.split("."),S=t.get(w);if(S&&S.measures[$]){const C=S.measures[$];X.isCalculatedMeasure(C)&&Ne(C.calculatedSql,w).forEach(D=>u.add(D))}})):o.push(l)}}for(const l of u){const[m,p]=l.split("."),f=t.get(m);if(f&&f.measures&&f.measures[p]){const h=f.measures[p];if(L.isPostAggregationWindow(h))continue;X.isCalculatedMeasure(h)?a.includes(l)||a.push(l):o.includes(l)||o.push(l)}}for(const l of o){const[m,p]=l.split("."),f=t.get(m),h=f.measures[p];if(i){const g=i(l,h,f);s.set(l,()=>g)}else s.set(l,()=>this.buildMeasureExpression(h,n,f))}if(a.length>0){const l=c.topologicalSort(a);for(const m of l){const[p,f]=m.split("."),h=t.get(p),g=h.measures[f];s.set(m,()=>this.buildCalculatedMeasure(g,h,t,s,n))}}return s}buildCalculatedMeasure(e,t,n,i,s){if(!e.calculatedSql)throw new Error(`Calculated measure '${t.name}.${e.name}' missing calculatedSql property`);const o=this.databaseAdapter.preprocessCalculatedTemplate(e.calculatedSql);return rn(o,{cube:t,allCubes:n,resolvedMeasures:i})}buildCTECalculatedMeasure(e,t,n,i,s){if(!e.calculatedSql)throw new Error(`Calculated measure '${t.name}.${e.name||"unknown"}' missing calculatedSql property`);const o=new Map,a=Ne(e.calculatedSql,t.name);for(const u of a){const[c,l]=u.split("."),m=i.get(c);if(m&&m.measures[l]){const p=m.measures[l];if(n.measures.includes(u)){const f=r`${r.identifier(n.cteAlias)}.${r.identifier(l)}`;let h;switch(p.type){case"count":case"countDistinct":case"sum":h=z(f);break;case"avg":h=this.databaseAdapter.buildAvg(f);break;case"min":h=ae(f);break;case"max":h=H(f);break;case"number":h=z(f);break;default:h=z(f)}o.set(u,()=>h)}}}return this.buildCalculatedMeasure(e,t,i,o,s)}buildHavingMeasureExpression(e,t,n,i,s){if(s&&s.preAggregationCTEs){const o=s.preAggregationCTEs.find(a=>a.cube.name===e);if(o&&o.measures.includes(`${e}.${t}`))if(n.type==="calculated"&&n.calculatedSql){const a=s.primaryCube.name===e?s.primaryCube:s.joinCubes?.find(c=>c.cube.name===e)?.cube;if(!a)throw new Error(`Cube ${e} not found in query plan`);const u=new Map([[s.primaryCube.name,s.primaryCube]]);if(s.joinCubes)for(const c of s.joinCubes)u.set(c.cube.name,c.cube);return this.buildCTECalculatedMeasure(n,a,o,u,i)}else{const a=r`${r.identifier(o.cteAlias)}.${r.identifier(t)}`;switch(n.type){case"count":case"countDistinct":case"sum":return z(a);case"avg":return this.databaseAdapter.buildAvg(a);case"min":return ae(a);case"max":return H(a);case"number":return z(a);default:return z(a)}}}return this.buildMeasureExpression(n,i)}buildMeasureExpression(e,t,n){if(e.type==="calculated")throw new Error(`Cannot build calculated measure '${e.name}' directly. Use buildCalculatedMeasure instead.`);if(L.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 i=R(e.sql,t);if(e.filters&&e.filters.length>0){const s=e.filters.map(o=>{const a=o(t);return a?r`(${a})`:void 0}).filter(Boolean);if(s.length>0){const o=s.length===1?s[0]:A(...s);i=this.databaseAdapter.buildCaseWhen([{when:o,then:i}])}}switch(e.type){case"count":return ve(i);case"countDistinct":return vt(i);case"sum":return z(i);case"avg":return this.databaseAdapter.buildAvg(i);case"min":return ae(i);case"max":return H(i);case"number":return i;case"stddev":case"stddevSamp":{const s=e.type==="stddevSamp"||e.statisticalConfig?.useSample,o=this.databaseAdapter.buildStddev(i,s);return o===null?(console.warn(`[drizzle-cube] ${e.type} not supported on ${this.databaseAdapter.getEngineType()}, returning NULL`),r`MAX(NULL)`):o}case"variance":case"varianceSamp":{const s=e.type==="varianceSamp"||e.statisticalConfig?.useSample,o=this.databaseAdapter.buildVariance(i,s);return o===null?(console.warn(`[drizzle-cube] ${e.type} not supported on ${this.databaseAdapter.getEngineType()}, returning NULL`),r`MAX(NULL)`):o}case"percentile":case"median":case"p95":case"p99":{let s;switch(e.type){case"median":s=50;break;case"p95":s=95;break;case"p99":s=99;break;default:s=e.statisticalConfig?.percentile??50}const o=this.databaseAdapter.buildPercentile(i,s);return o===null?(console.warn(`[drizzle-cube] ${e.type} not supported on ${this.databaseAdapter.getEngineType()}, returning NULL`),r`MAX(NULL)`):o}case"lag":case"lead":case"rank":case"denseRank":case"rowNumber":case"ntile":case"firstValue":case"lastValue":case"movingAvg":case"movingSum":{const s=e.windowConfig||{};let o;if(s.partitionBy&&s.partitionBy.length>0&&n){const c=s.partitionBy.map(l=>{const m=l.includes(".")?l.split(".")[1]:l,p=n.dimensions?.[m];return p?R(p.sql,t):(console.warn(`[drizzle-cube] Window function partition dimension '${l}' not found in cube '${n.name}'`),null)}).filter(l=>l!==null);c.length>0&&(o=c)}let a;if(s.orderBy&&s.orderBy.length>0&&n){const c=s.orderBy.map(l=>{const m=l.field.includes(".")?l.field.split(".")[1]:l.field,p=n.dimensions?.[m];if(p)return{field:R(p.sql,t),direction:l.direction};const f=n.measures?.[m];return f&&f.sql?{field:R(f.sql,t),direction:l.direction}:(console.warn(`[drizzle-cube] Window function order field '${l.field}' not found in cube '${n.name}'`),null)}).filter(l=>l!==null);c.length>0&&(a=c)}const u=this.databaseAdapter.buildWindowFunction(e.type,["rank","denseRank","rowNumber"].includes(e.type)?null:i,o,a,{offset:s.offset,defaultValue:s.defaultValue,nTile:s.nTile,frame:s.frame});return u===null?(console.warn(`[drizzle-cube] ${e.type} not supported on ${this.databaseAdapter.getEngineType()}, returning NULL`),r`NULL`):u}default:return ve(i)}}static WINDOW_FUNCTION_TYPES=["lag","lead","rank","denseRank","rowNumber","ntile","firstValue","lastValue","movingAvg","movingSum"];static isWindowFunction(e){return L.WINDOW_FUNCTION_TYPES.includes(e)}static categorizeMeasures(e,t){const n=[],i=[];for(const s of e){const[o,a]=s.split("."),u=t.get(o);if(u?.measures?.[a]){const c=u.measures[a];L.isWindowFunction(c.type)?n.push(s):i.push(s)}}return{windowMeasures:n,aggregateMeasures:i}}static hasWindowFunctions(e,t){const{windowMeasures:n}=L.categorizeMeasures(e,t);return n.length>0}static isPostAggregationWindow(e){return L.isWindowFunction(e.type)&&e.windowConfig?.measure!==void 0}static getWindowBaseMeasure(e,t){if(!e.windowConfig?.measure)return null;const n=e.windowConfig.measure;return n.includes(".")?n:`${t}.${n}`}static getDefaultWindowOperation(e){switch(e){case"lag":case"lead":return"difference";default:return"raw"}}static categorizeForPostAggregation(e,t){const n=[],i=[],s=new Set;for(const o of e){const[a,u]=o.split("."),c=t.get(a);if(c?.measures?.[u]){const l=c.measures[u];if(L.isPostAggregationWindow(l)){i.push(o);const m=L.getWindowBaseMeasure(l,a);m&&s.add(m)}else L.isWindowFunction(l.type)||n.push(o)}}return{aggregateMeasures:n,postAggWindowMeasures:i,requiredBaseMeasures:s}}static hasPostAggregationWindows(e,t){const{postAggWindowMeasures:n}=L.categorizeForPostAggregation(e,t);return n.length>0}}class an{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,t,n,i){const s=[],o=e instanceof Map?e:new Map([[e.name,e]]),a=t.dimensions&&t.dimensions.length>0||t.timeDimensions&&t.timeDimensions.length>0,u=t.measures&&t.measures.length>0,c=a&&!u;let l=!1;for(const m of t.measures||[]){const[p,f]=m.split("."),h=o.get(p);if(h&&h.measures&&h.measures[f]){const g=h.measures[f];if(this.isAggregateFunctionType(g.type)||g.type==="calculated"){l=!0;break}if(L.isPostAggregationWindow(g)){const y=L.getWindowBaseMeasure(g,p);if(y){const[b,w]=y.split("."),S=o.get(b)?.measures?.[w];if(S&&this.isAggregateFunctionType(S.type)){l=!0;break}}}}}if(!l&&!c)return[];if(t.dimensions)for(const m of t.dimensions){const[p,f]=m.split("."),h=o.get(p);if(h&&h.dimensions&&h.dimensions[f]){const g=i?.preAggregationCTEs?.find(y=>y.cube.name===p);if(g){const y=g.joinKeys.find(b=>b.targetColumn===f);if(y&&y.sourceColumnObj)s.push(y.sourceColumnObj);else{const b=r`${r.identifier(g.cteAlias)}.${r.identifier(f)}`;s.push(b)}}else{const y=h.dimensions[f],b=R(y.sql,n);s.push(b)}}}if(t.timeDimensions)for(const m of t.timeDimensions){const[p,f]=m.dimension.split("."),h=o.get(p);if(h&&h.dimensions&&h.dimensions[f]){const g=i?.preAggregationCTEs?.find(y=>y.cube.name===p);if(g){const y=g.joinKeys.find(b=>b.targetColumn===f);if(y&&y.sourceColumnObj){const b=this.dateTimeBuilder.buildTimeDimensionExpression(y.sourceColumnObj,m.granularity,n);s.push(b)}else{const b=r`${r.identifier(g.cteAlias)}.${r.identifier(f)}`;s.push(b)}}else{const y=h.dimensions[f],b=this.dateTimeBuilder.buildTimeDimensionExpression(y.sql,m.granularity,n);s.push(b)}}}return s}}class un{dateTimeBuilder;filterBuilder;groupByBuilder;measureBuilder;constructor(e){this.dateTimeBuilder=new re(e),this.filterBuilder=new be(e,this.dateTimeBuilder),this.groupByBuilder=new an(this.dateTimeBuilder),this.measureBuilder=new L(e)}buildResolvedMeasures(e,t,n,i){return this.measureBuilder.buildResolvedMeasures(e,t,n,i)}buildSelections(e,t,n){const i={},s=e instanceof Map?e:new Map([[e.name,e]]);if(t.dimensions)for(const o of t.dimensions){const[a,u]=o.split("."),c=s.get(a);if(c&&c.dimensions&&c.dimensions[u]){const l=c.dimensions[u],m=R(l.sql,n);i[o]=r`${m}`.as(o)}}if(t.measures){const o=this.buildResolvedMeasures(t.measures,s,n);for(const a of t.measures){const u=o.get(a);if(u){const c=u();i[a]=r`${c}`.as(a)}}}if(t.timeDimensions)for(const o of t.timeDimensions){const[a,u]=o.dimension.split("."),c=s.get(a);if(c&&c.dimensions&&c.dimensions[u]){const l=c.dimensions[u],m=this.buildTimeDimensionExpression(l.sql,o.granularity,n);i[o.dimension]=r`${m}`.as(o.dimension)}}return Object.keys(i).length===0&&(i.count=ve()),i}buildCalculatedMeasure(e,t,n,i,s){return this.measureBuilder.buildCalculatedMeasure(e,t,n,i,s)}buildCTECalculatedMeasure(e,t,n,i,s){return this.measureBuilder.buildCTECalculatedMeasure(e,t,n,i,s)}buildHavingMeasureExpression(e,t,n,i,s){return this.measureBuilder.buildHavingMeasureExpression(e,t,n,i,s)}buildMeasureExpression(e,t,n){return this.measureBuilder.buildMeasureExpression(e,t,n)}buildTimeDimensionExpression(e,t,n){return this.dateTimeBuilder.buildTimeDimensionExpression(e,t,n)}buildWhereConditions(e,t,n,i,s){const o=[],a=e instanceof Map?e:new Map([[e.name,e]]),u=new Set;if(t.filters&&t.filters.length>0)for(const c of t.filters){if(s&&"member"in c){const[m]=c.member.split(".");if(a.has(m)&&s.has(m)&&!u.has(m)){const f=s.get(m);o.push(...f),u.add(m);continue}else if(u.has(m))continue}const l=this.processFilter(c,a,n,"where",i);l&&o.push(l)}if(t.timeDimensions)for(const c of t.timeDimensions){const[l,m]=c.dimension.split("."),p=a.get(l);if(p&&p.dimensions[m]&&c.dateRange){if(i?.preAggregationCTEs&&i.preAggregationCTEs.some(b=>b.cube.name===l))continue;if(n.filterCache){const y=lt(c.dimension,c.dateRange),b=n.filterCache.get(y);if(b){o.push(b);continue}}const f=p.dimensions[m],h=R(f.sql,n),g=this.buildDateRangeCondition(h,c.dateRange);g&&o.push(g)}}return o}buildHavingConditions(e,t,n,i){const s=[],o=e instanceof Map?e:new Map([[e.name,e]]);if(t.filters&&t.filters.length>0)for(const a of t.filters){const u=this.processFilter(a,o,n,"having",i);u&&s.push(u)}return s}processFilter(e,t,n,i,s){if("and"in e||"or"in e){const f=e;if(f.and){const h=f.and.map(g=>this.processFilter(g,t,n,i,s)).filter(g=>g!==null);return h.length>0?A(...h):null}if(f.or){const h=f.or.map(g=>this.processFilter(g,t,n,i,s)).filter(g=>g!==null);return h.length>0?oe(...h):null}}const o=e,[a,u]=o.member.split("."),c=t.get(a);if(!c)return null;const l=c.dimensions[u],m=c.measures[u],p=l||m;if(!p)return null;if(i==="where"&&l){if(s?.preAggregationCTEs&&s.preAggregationCTEs.some(y=>y.cube.name===a))return null;const f=["arrayContains","arrayOverlaps","arrayContained"].includes(o.operator);if(!f&&n.filterCache){const g=fe(e),y=n.filterCache.get(g);if(y)return y}const h=f?typeof l.sql=="function"?l.sql(n):l.sql:R(l.sql,n);return this.buildFilterCondition(h,o.operator,o.values,p,o.dateRange)}else{if(i==="where"&&m)return null;if(i==="having"&&m){const f=this.buildHavingMeasureExpression(a,u,m,n,s);return this.buildFilterCondition(f,o.operator,o.values,p,o.dateRange)}}return null}buildFilterCondition(e,t,n,i,s){return this.filterBuilder.buildFilterCondition(e,t,n,i,s)}buildDateRangeCondition(e,t){return this.dateTimeBuilder.buildDateRangeCondition(e,t)}buildGroupByFields(e,t,n,i){return this.groupByBuilder.buildGroupByFields(e,t,n,i)}buildOrderBy(e,t){const n=[],i=t||[...e.measures||[],...e.dimensions||[],...e.timeDimensions?.map(s=>s.dimension)||[]];if(e.order&&Object.keys(e.order).length>0)for(const[s,o]of Object.entries(e.order)){if(!i.includes(s))throw new Error(`Cannot order by '${s}': field is not selected in the query`);const a=o==="desc"?_t(r.identifier(s)):Je(r.identifier(s));n.push(a)}if(e.timeDimensions&&e.timeDimensions.length>0){const s=new Set(Object.keys(e.order||{})),o=[...e.timeDimensions].sort((a,u)=>a.dimension.localeCompare(u.dimension));for(const a of o)s.has(a.dimension)||n.push(Je(r.identifier(a.dimension)))}return n}collectNumericFields(e,t){const n=[],i=e instanceof Map?e:new Map([[e.name,e]]);if(t.measures&&n.push(...t.measures),t.dimensions)for(const s of t.dimensions){const[o,a]=s.split("."),u=i.get(o);if(u){const c=u.dimensions[a];c&&c.type==="number"&&n.push(s)}}return n}applyLimitAndOffset(e,t){let n=t.limit;t.offset!==void 0&&t.offset>0&&n===void 0&&(n=50);let i=e;if(n!==void 0){if(n<0)throw new Error("Limit must be non-negative");i=i.limit(n)}if(t.offset!==void 0){if(t.offset<0)throw new Error("Offset must be non-negative");i=i.offset(t.offset)}return i}buildFilterConditionPublic(e,t,n,i,s){return this.buildFilterCondition(e,t,n,i,s)}buildLogicalFilter(e,t,n){return this.filterBuilder.buildLogicalFilter(e,t,n)}}class ue{cubes;connectivityCache=new Map;constructor(e){this.cubes=e}findPath(e,t,n=new Set){if(e===t)return[];const i=this.getCacheKey(e,t,n),s=this.getFromCache(i);if(s!==void 0)return s;const o=[{cube:e,path:[]}],a=new Set([e,...n]);for(;o.length>0;){const{cube:u,path:c}=o.shift(),l=this.cubes.get(u);if(l?.joins)for(const[,m]of Object.entries(l.joins)){const f=q(m.targetCube).name;if(a.has(f))continue;const h=[...c,{fromCube:u,toCube:f,joinDef:m}];if(f===t)return this.setInCache(i,h),h;a.add(f),o.push({cube:f,path:h})}}return this.setInCache(i,null),null}findPathPreferring(e,t,n,i=new Set){return this.findPathPreferringDetailed(e,t,n,i).selectedPath}findPathPreferringDetailed(e,t,n,i=new Set){const s=this.findAllPaths(e,t,new Set);if(s.length===0){const a=this.findPath(e,t,i),u=a?[{path:a,score:0,usesPreferredJoin:!1,preferredCubesInPath:0,usesProcessed:a.some(c=>i.has(c.toCube)),scoreBreakdown:{preferredJoinBonus:0,preferredCubeBonus:0,lengthPenalty:0}}]:[];return{strategy:"fallbackShortest",preferredCubes:Array.from(n).sort(),selectedIndex:a?0:-1,candidates:u,selectedPath:a}}const o=s.map(a=>{let u=0;const c=a.some((h,g)=>h.joinDef.preferredFor?.includes(t)&&g===0);c&&(u=10);const l=a.filter(h=>n.has(h.toCube)).length,m=l,p=a.length-1,f=u+m-p;return{path:a,score:f,usesPreferredJoin:c,preferredCubesInPath:l,usesProcessed:a.some(h=>i.has(h.toCube)),scoreBreakdown:{preferredJoinBonus:u,preferredCubeBonus:m,lengthPenalty:p}}});return o.sort((a,u)=>u.score!==a.score?u.score-a.score:a.usesProcessed!==u.usesProcessed?a.usesProcessed?-1:1:a.path.length-u.path.length),{strategy:"preferred",preferredCubes:Array.from(n).sort(),selectedIndex:o.length>0?0:-1,candidates:o,selectedPath:o[0]?.path??null}}findAllPaths(e,t,n,i=4){if(e===t)return[[]];const s=[],o=[{cube:e,path:[],visited:new Set([e,...n])}];for(;o.length>0;){const{cube:a,path:u,visited:c}=o.shift();if(u.length>=i)continue;const l=this.cubes.get(a);if(l?.joins)for(const[,m]of Object.entries(l.joins)){const f=q(m.targetCube).name;if(c.has(f))continue;const h=[...u,{fromCube:a,toCube:f,joinDef:m}];if(f===t)s.push(h);else{const g=new Set(c);g.add(f),o.push({cube:f,path:h,visited:g})}}}return s}canReachAll(e,t){const n=t.filter(i=>i!==e);for(const i of n){const s=this.findPath(e,i,new Set);if(!s||s.length===0)return!1}return!0}buildJoinCondition(e,t,n){const i=[];for(const s of e.on){const o=t?r`${r.identifier(t)}.${r.identifier(s.source.name)}`:Fe(s.source),a=n?r`${r.identifier(n)}.${r.identifier(s.target.name)}`:Fe(s.target),u=s.as||k;i.push(u(o,a))}return A(...i)}getReachableCubes(e){const t=new Set([e]),n=[e];for(;n.length>0;){const i=n.shift(),s=this.cubes.get(i);if(s?.joins)for(const[,o]of Object.entries(s.joins)){const u=q(o.targetCube).name;t.has(u)||(t.add(u),n.push(u))}}return t}getCacheKey(e,t,n){const i=Array.from(n).sort().join(",");return`${e}:${t}:${i}`}getFromCache(e){const t=this.connectivityCache.get(e);if(t)return t.path}setInCache(e,t){this.connectivityCache.set(e,{path:t})}}class ln{resolverCache=new WeakMap;getResolver(e){let t=this.resolverCache.get(e);return t||(t=new ue(e),this.resolverCache.set(e,t)),t}analyzeCubeUsage(e){const t=new Set;if(e.measures)for(const n of e.measures){const[i]=n.split(".");t.add(i)}if(e.dimensions)for(const n of e.dimensions){const[i]=n.split(".");t.add(i)}if(e.timeDimensions)for(const n of e.timeDimensions){const[i]=n.dimension.split(".");t.add(i)}if(e.filters)for(const n of e.filters)this.extractCubeNamesFromFilter(n,t);if(e.order)for(const n of Object.keys(e.order)){const[i]=n.split(".");i&&t.add(i)}return t}collectPathHintCubes(e){return this.analyzeCubeUsage(e)}extractCubeNamesFromFilter(e,t){if("and"in e||"or"in e){const n=e.and||e.or||[];for(const i of n)this.extractCubeNamesFromFilter(i,t);return}if("member"in e){const[n]=e.member.split(".");n&&t.add(n)}}extractMeasuresFromFilters(e,t){const n=[];if(!e.filters)return n;for(const i of e.filters)this.extractMeasuresFromFilter(i,t,n);return n}extractMeasuresFromFilter(e,t,n){if("and"in e||"or"in e){const i=e.and||e.or||[];for(const s of i)this.extractMeasuresFromFilter(s,t,n);return}if("member"in e){const i=e.member,[s,o]=i.split(".");s===t.name&&t.measures&&t.measures[o]&&n.push(i)}}choosePrimaryCube(e,t,n){return e.length===1?e[0]:n?this.analyzePrimaryCubeSelection(e,t,n).selectedCube:[...e].sort()[0]}analyzePrimaryCube(e,t,n){return this.analyzePrimaryCubeSelection(e,t,n)}analyzeJoinPathForTarget(e,t,n,i){return this.analyzeJoinPath(e,t,n,i)}buildJoinPlanForPrimary(e,t,n,i,s){return this.buildJoinPlan(e,t,n,i,s)}buildPreAggregationCTEs(e,t,n,i,s){return this.planPreAggregationCTEs(e,t,n,i,s)}buildWarnings(e,t){return this.generateWarnings(e,t)}buildJoinPlan(e,t,n,i,s){const o=this.getResolver(e),a=[],u=new Set([t.name]),c=new Set;if(s.measures)for(const f of s.measures){const[h]=f.split(".");c.add(h)}const l=this.collectPathHintCubes(s),m=new Set;for(const f of c){if(f===t.name)continue;this.findHasManyJoinDef(t,f)&&m.add(f)}const p=n.filter(f=>f!==t.name);for(const f of p){if(u.has(f))continue;const h=new Set([...u].filter(y=>!m.has(y))),g=o.findPathPreferring(t.name,f,l,h);if(!g||g.length===0)throw new Error(`No join path found from '${t.name}' to '${f}'`);for(const{fromCube:y,toCube:b,joinDef:w}of g){if(u.has(b))continue;const $=e.get(b);if(!$)throw new Error(`Cube '${b}' not found`);if(w.relationship==="belongsToMany"&&w.through){const S=Yt(w,i.securityContext);a.push({cube:$,alias:`${b.toLowerCase()}_cube`,joinType:S.junctionJoins[1].joinType,joinCondition:S.junctionJoins[1].condition,relationship:"belongsToMany",junctionTable:{table:w.through.table,alias:`junction_${b.toLowerCase()}`,joinType:S.junctionJoins[0].joinType,joinCondition:S.junctionJoins[0].condition,securitySql:w.through.securitySql,sourceCubeName:y}})}else{const S=o.buildJoinCondition(w,null,null),C=Re(w.relationship,w.sqlJoinType);a.push({cube:$,alias:`${b.toLowerCase()}_cube`,joinType:C,joinCondition:S,relationship:w.relationship})}u.add(b)}}return a}planPreAggregationCTEs(e,t,n,i,s){const o=[];if(!i.measures||i.measures.length===0)return o;const a=this.computeCTEReasons(t,n,i);if(a.size===0)return o;for(const u of n){const c=a.get(u.cube.name);if(!c)continue;const l=u.cube,m=u.alias,p=i.measures.filter(D=>D.startsWith(l.name+".")),f=this.extractMeasuresFromFilters(i,l),h=[...new Set([...p,...f])];if(h.length===0)continue;const g=this.analyzeJoinPathToPrimary(e,t,l.name,s,i);let y,b;if(g?.hasIntermediateHasMany&&g.intermediateJoins.length>0)y=g.correctJoinKeys,b=g.intermediateJoins;else{const N=(g?.path&&g.path.length>0?(()=>{const M=g.path[g.path.length-1],v=e.get(M.fromCube);return v?{sourceCube:v,joinDef:M.joinDef}:null})():null)??this.findJoinInfoForCube(e,t,l.name);if(!N)continue;N.joinDef.relationship==="belongsToMany"&&N.joinDef.through?N.sourceCube?.name===t.name&&!("reversed"in N&&N.reversed)?y=N.joinDef.through.targetKey.map(v=>({sourceColumn:v.source.name,targetColumn:v.target.name,sourceColumnObj:v.source,targetColumnObj:v.target})):y=N.joinDef.through.sourceKey.map(v=>({sourceColumn:v.target.name,targetColumn:v.source.name,sourceColumnObj:v.target,targetColumnObj:v.source})):y="reversed"in N&&N.reversed?N.joinDef.on.map(v=>({sourceColumn:v.target.name,targetColumn:v.source.name,sourceColumnObj:v.target,targetColumnObj:v.source})):N.joinDef.on.map(v=>({sourceColumn:v.source.name,targetColumn:v.target.name,sourceColumnObj:v.source,targetColumnObj:v.target})),b=void 0}const w=this.findPropagatingFilters(i,l,e),$=new Map([[l.name,l]]),{aggregateMeasures:S,requiredBaseMeasures:C}=L.categorizeForPostAggregation(h,$),T=[...new Set([...S,...Array.from(C).filter(D=>D.startsWith(l.name+"."))])];if(T.length>0){const D=this.expandCalculatedMeasureDependencies(l,T),N=this.findDownstreamJoinKeys(l,i,e);o.push({cube:l,alias:m,cteAlias:`${l.name.toLowerCase()}_agg`,joinKeys:y,measures:D,propagatingFilters:w.length>0?w:void 0,downstreamJoinKeys:N.length>0?N:void 0,intermediateJoins:b&&b.length>0?b:void 0,cteType:"aggregate",cteReason:c})}}return o}findJoinInfoToCube(e,t){for(const[,n]of e)if(n.name!==t&&n.joins){for(const[,i]of Object.entries(n.joins))if(q(i.targetCube).name===t)return{sourceCube:n,joinDef:i}}return null}analyzeJoinPathToPrimary(e,t,n,i,s){const o=this.getResolver(e),a=this.collectPathHintCubes(s),u=a.size>0?o.findPathPreferring(t.name,n,a,new Set):o.findPath(t.name,n);if(!u||u.length===0)return null;const c=u.map(g=>({fromCube:g.fromCube,toCube:g.toCube,joinDef:g.joinDef}));if(!c.slice(0,-1).some(g=>g.joinDef.relationship==="hasMany"))return{path:c,hasIntermediateHasMany:!1,intermediateJoins:[],correctJoinKeys:[]};const p=[];for(let g=0;g<c.length-1;g++){const y=c[g],b=c[g+1],w=e.get(y.toCube);if(!w)continue;const S=w.sql(i).where,C=b.joinDef.on[0]?.source,T=y.joinDef.on[0]?.target;p.push({cube:w,joinDef:b.joinDef,securityFilter:S,primaryJoinColumn:T,cteJoinColumn:C})}const h=c[0].joinDef.on.map(g=>({sourceColumn:g.source.name,targetColumn:g.target.name,sourceColumnObj:g.source,targetColumnObj:g.target}));return{path:c,hasIntermediateHasMany:!0,intermediateJoins:p,correctJoinKeys:h}}computeCTEReasons(e,t,n){const i=new Map,s=new Set,o=new Set,a=new Set;if(n.measures)for(const u of n.measures){const[c]=u.split(".");a.add(c)}for(const u of t)u.relationship==="hasMany"||u.relationship==="belongsToMany"?s.add(u.cube.name):u.relationship==="belongsTo"&&a.has(u.cube.name)&&o.add(u.cube.name);if(s.size===0&&o.size===0)return i;for(const u of t)a.has(u.cube.name)&&(s.has(u.cube.name)?i.set(u.cube.name,"hasMany"):(o.has(u.cube.name)||s.size>0)&&i.set(u.cube.name,"fanOutPrevention"));return i}findJoinInfoForCube(e,t,n){if(t.joins){for(const[,s]of Object.entries(t.joins))if(q(s.targetCube).name===n)return{sourceCube:t,joinDef:s}}const i=e.get(n);if(i?.joins){for(const[,s]of Object.entries(i.joins))if(q(s.targetCube).name===t.name)return{sourceCube:i,joinDef:s,reversed:!0}}for(const[,s]of e)if(!(s.name===t.name||s.name===n)&&s.joins){for(const[,o]of Object.entries(s.joins))if(q(o.targetCube).name===n)return{sourceCube:s,joinDef:o}}return null}findDownstreamJoinKeys(e,t,n){const i=[],s=new Set;if(t.dimensions)for(const o of t.dimensions){const[a]=o.split(".");a!==e.name&&s.add(a)}if(t.timeDimensions)for(const o of t.timeDimensions){const[a]=o.dimension.split(".");a!==e.name&&s.add(a)}if(e.joins)for(const[,o]of Object.entries(e.joins)){const u=q(o.targetCube).name;if(s.has(u)){let c;o.relationship==="belongsToMany"&&o.through?c=o.through.sourceKey.map(l=>({sourceColumn:l.source.name,targetColumn:l.target.name,sourceColumnObj:l.source,targetColumnObj:l.target})):c=o.on.map(l=>({sourceColumn:l.source.name,targetColumn:l.target.name,sourceColumnObj:l.source,targetColumnObj:l.target})),i.push({targetCubeName:u,joinKeys:c})}}return i}expandCalculatedMeasureDependencies(e,t){const n=new Set,i=[...t];for(;i.length>0;){const s=i.pop();if(n.has(s))continue;n.add(s);const[,o]=s.split(".");if(!e.measures||!e.measures[o])continue;const a=e.measures[o];if(a.type==="calculated"&&a.calculatedSql){const u=this.extractDependenciesFromTemplate(a.calculatedSql,e.name);for(const c of u)n.has(c)||i.push(c)}}return Array.from(n)}extractDependenciesFromTemplate(e,t){const n=/\{([^}]+)\}/g,i=e.matchAll(n),s=[];for(const o of i){const a=o[1].trim();a.includes(".")?s.push(a):s.push(`${t}.${a}`)}return s}findHasManyJoinDef(e,t){if(!e.joins)return null;for(const[,n]of Object.entries(e.joins))if(q(n.targetCube).name===t&&n.relationship==="hasMany")return n;return null}findPropagatingFilters(e,t,n){const i=[];if(!e.filters)return i;const s=new Set;if(this.extractFilterCubeNamesToSet(e.filters,s),e.timeDimensions){for(const o of e.timeDimensions)if(o.dateRange){const[a]=o.dimension.split(".");a&&s.add(a)}}for(const o of s){if(o===t.name)continue;const a=n.get(o);if(a?.joins){for(const[,u]of Object.entries(a.joins))if(q(u.targetCube).name===t.name&&u.relationship==="hasMany"){const l=this.extractFiltersForCube(e.filters,o),m=this.extractTimeDimensionFiltersForCube(e,o),p=[...l,...m];p.length>0&&u.on.length>0&&i.push({sourceCube:a,filters:p,joinConditions:u.on.map(f=>({source:f.source,target:f.target}))})}}}return i}extractFilterCubeNamesToSet(e,t){for(const n of e){if("and"in n||"or"in n){const i=n.and||n.or||[];this.extractFilterCubeNamesToSet(i,t);continue}if("member"in n){const[i]=n.member.split(".");i&&t.add(i)}}}extractFiltersForCube(e,t){const n=[];for(const i of e){if("and"in i){const s=this.extractFiltersForCube(i.and||[],t);s.length>0&&n.push({and:s});continue}if("or"in i){const s=i.or||[];if(this.allFiltersFromCube(s,t)){const a=this.extractFiltersForCube(s,t);a.length>0&&n.push({or:a})}continue}if("member"in i){const[s]=i.member.split(".");s===t&&n.push(i)}}return n}allFiltersFromCube(e,t){for(const n of e){if("and"in n){if(!this.allFiltersFromCube(n.and||[],t))return!1;continue}if("or"in n){if(!this.allFiltersFromCube(n.or||[],t))return!1;continue}if("member"in n){const[i]=n.member.split(".");if(i!==t)return!1}}return!0}extractTimeDimensionFiltersForCube(e,t){const n=[];if(!e.timeDimensions)return n;for(const i of e.timeDimensions){const[s]=i.dimension.split(".");s===t&&i.dateRange&&n.push({member:i.dimension,operator:"inDateRange",values:Array.isArray(i.dateRange)?i.dateRange:[i.dateRange]})}return n}analyzePrimaryCubeSelection(e,t,n){if(e.length===1)return{selectedCube:e[0],reason:"single_cube",explanation:"Only one cube is used in this query"};const i=[],s=(t.dimensions||[]).map(l=>l.split(".")[0]),o=new Map;for(const l of s)o.set(l,(o.get(l)||0)+1);const a=this.getResolver(n);for(const l of e){const m=n.get(l),p=o.get(l)||0,f=m?.joins?Object.keys(m.joins).length:0,h=a.canReachAll(l,e);i.push({cubeName:l,dimensionCount:p,joinCount:f,canReachAll:h})}if(t.dimensions&&t.dimensions.length>0){const l=Math.max(...i.map(m=>m.dimensionCount));if(l>0){const m=i.filter(p=>p.dimensionCount===l).sort((p,f)=>p.cubeName.localeCompare(f.cubeName));for(const p of m)if(p.canReachAll)return{selectedCube:p.cubeName,reason:"most_dimensions",explanation:`Selected because it has ${p.dimensionCount} dimension${p.dimensionCount!==1?"s":""} in the query (defines the analytical grain)`,candidates:i}}}const u=i.filter(l=>l.canReachAll);if(u.length>0){const l=Math.max(...u.map(p=>p.joinCount)),m=u.filter(p=>p.joinCount===l).sort((p,f)=>p.cubeName.localeCompare(f.cubeName))[0];return{selectedCube:m.cubeName,reason:"most_connected",explanation:`Selected because it has ${m.joinCount} join relationship${m.joinCount!==1?"s":""} and can reach all other cubes`,candidates:i}}return{selectedCube:[...e].sort()[0],reason:"alphabetical_fallback",explanation:"Selected alphabetically as fallback (no cube could reach all others)",candidates:i}}analyzeJoinPath(e,t,n,i){const s=this.getResolver(e),o=i?this.collectPathHintCubes(i):new Set,a=o.size>0?s.findPathPreferringDetailed(t,n,o):null,u=a?.selectedPath??s.findPath(t,n),c=[t];if(u)for(const m of u)c.push(m.toCube);if(!u||u.length===0)return{targetCube:n,pathFound:!1,error:`No join path found from '${t}' to '${n}'. Ensure the target cube has a relationship defined (belongsTo, hasOne, hasMany, or belongsToMany).`,visitedCubes:c,selection:this.buildJoinPathSelectionAnalysis(a)};const l=this.convertInternalPathToJoinPathSteps(u);return{targetCube:n,pathFound:!0,path:l,pathLength:l.length,visitedCubes:c,selection:this.buildJoinPathSelectionAnalysis(a)}}convertInternalPathToJoinPathSteps(e){return e.map(t=>{const n=Re(t.joinDef.relationship,t.joinDef.sqlJoinType),i=t.joinDef.on.map(o=>({sourceColumn:o.source.name,targetColumn:o.target.name})),s={fromCube:t.fromCube,toCube:t.toCube,relationship:t.joinDef.relationship,joinType:n,joinColumns:i};if(t.joinDef.relationship==="belongsToMany"&&t.joinDef.through){const o=t.joinDef.through;s.junctionTable={tableName:o.table[Symbol.for("drizzle:Name")]||"junction_table",sourceColumns:o.sourceKey.map(a=>a.target.name),targetColumns:o.targetKey.map(a=>a.source.name)}}return s})}buildJoinPathSelectionAnalysis(e){if(!e)return{strategy:"shortest"};const t=e.candidates.map((n,i)=>this.mapPreferredCandidate(n,i+1));return{strategy:e.strategy,preferredCubes:e.preferredCubes,selectedRank:e.selectedIndex>=0?e.selectedIndex+1:void 0,selectedScore:e.selectedIndex>=0?e.candidates[e.selectedIndex]?.score:void 0,candidates:t}}mapPreferredCandidate(e,t){return{rank:t,score:e.score,usesPreferredJoin:e.usesPreferredJoin,preferredCubesInPath:e.preferredCubesInPath,usesProcessed:e.usesProcessed,scoreBreakdown:e.scoreBreakdown,path:this.convertInternalPathToJoinPathSteps(e.path)}}generateWarnings(e,t){const n=[],i=this.checkFanOutNoDimensions(e,t);return i&&n.push(i),n}checkFanOutNoDimensions(e,t){if(!t||t.length===0||!e.measures||e.measures.length===0)return null;const n=new Set;for(const o of e.measures){const[a]=o.split(".");n.add(a)}if(n.size<2)return null;const i=e.dimensions&&e.dimensions.length>0,s=e.timeDimensions?.some(o=>o.granularity);return i||s?null:{code:"FAN_OUT_NO_DIMENSIONS",message:"Query combines measures from multiple cubes with hasMany relationships but has no dimensions. Results are aggregated at the join key level, which may produce unexpected totals.",severity:"warning",cubes:[...n].sort(),measures:e.measures,suggestion:"Add a dimension to see per-group breakdowns, or add a time dimension with granularity."}}}class cn{constructor(e){this.queryBuilder=e}buildPreAggregationCTE(e,t,n,i,s){const o=e.cube,a=o.sql(n),u=e.intermediateJoins&&e.intermediateJoins.length>0,c={};if(u&&e.intermediateJoins){const T=e.intermediateJoins[0].primaryJoinColumn;if(T){const D=T.name;c[D]=T}}else for(const C of e.joinKeys)if(C.targetColumnObj){c[C.targetColumn]=C.targetColumnObj;for(const[T,D]of Object.entries(o.dimensions||{}))D.sql===C.targetColumnObj&&T!==C.targetColumn&&(c[T]=r`${C.targetColumnObj}`.as(T))}if(e.downstreamJoinKeys)for(const C of e.downstreamJoinKeys)for(const T of C.joinKeys)T.sourceColumnObj&&(c[T.sourceColumn]=T.sourceColumnObj);const l=o.name,m=new Map([[l,o]]),p=this.queryBuilder.buildResolvedMeasures(e.measures,m,n);for(const C of e.measures){const[,T]=C.split("."),D=p.get(C);if(D){const N=D();c[T]=r`${N}`.as(T)}}if(t.dimensions)for(const C of t.dimensions){const[T,D]=C.split(".");if(T===l&&o.dimensions&&o.dimensions[D]){const N=o.dimensions[D],M=this.queryBuilder.buildMeasureExpression({sql:N.sql,type:"number"},n);c[D]=r`${M}`.as(D)}}if(t.timeDimensions)for(const C of t.timeDimensions){const[T,D]=C.dimension.split(".");if(T===l&&o.dimensions&&o.dimensions[D]){const N=o.dimensions[D],M=this.queryBuilder.buildTimeDimensionExpression(N.sql,C.granularity,n);c[D]=r`${M}`.as(D)}}if(Object.keys(c).length===0)return null;let f=n.db.select(c).from(a.from);if(u&&e.intermediateJoins){const C=[...e.intermediateJoins].reverse();for(const T of C){const D=T.cube.sql(n),M=[k(T.cteJoinColumn,T.joinDef.on[0]?.target)];T.securityFilter&&M.push(T.securityFilter),f=f.leftJoin(D.from,A(...M))}}const h=i?{...i,preAggregationCTEs:i.preAggregationCTEs?.filter(C=>C.cube.name!==o.name)}:void 0,g=this.queryBuilder.buildWhereConditions(o,t,n,h,s),y=[];if(t.timeDimensions)for(const C of t.timeDimensions){const[T,D]=C.dimension.split(".");if(T===l&&o.dimensions&&o.dimensions[D]&&C.dateRange){const N=o.dimensions[D],M=this.queryBuilder.buildMeasureExpression({sql:N.sql,type:"number"},n),v=this.queryBuilder.buildDateRangeCondition(M,C.dateRange);v&&y.push(v)}}if(t.filters){for(const C of t.filters)if(!("and"in C)&&!("or"in C)&&"member"in C&&"operator"in C){const T=C,[D,N]=T.member.split(".");if(D===l&&o.dimensions&&o.dimensions[N]){const M=o.dimensions[N];if(T.operator==="inDateRange"){const v=this.queryBuilder.buildMeasureExpression({sql:M.sql,type:"number"},n),U=this.queryBuilder.buildDateRangeCondition(v,T.values);U&&y.push(U)}}}}if(e.propagatingFilters&&e.propagatingFilters.length>0)for(const C of e.propagatingFilters){const T=this.buildPropagatingFilterSubquery(C,n);T&&y.push(T)}const b=[];if(a.where&&b.push(a.where),b.push(...g,...y),b.length>0){const C=b.length===1?b[0]:A(...b);f=f.where(C)}const w=[],$=new Set,S=C=>{const T=C?.name||(typeof C=="string"?C:null);T&&!$.has(T)?($.add(T),w.push(C)):T||w.push(C)};if(u&&e.intermediateJoins){const C=e.intermediateJoins[0];C.primaryJoinColumn&&S(C.primaryJoinColumn)}else for(const C of e.joinKeys)C.targetColumnObj&&S(C.targetColumnObj);if(e.downstreamJoinKeys)for(const C of e.downstreamJoinKeys)for(const T of C.joinKeys)T.sourceColumnObj&&S(T.sourceColumnObj);if(t.dimensions)for(const C of t.dimensions){const[T,D]=C.split(".");if(T===l&&o.dimensions&&o.dimensions[D]){const N=o.dimensions[D],M=R(N.sql,n);w.push(M)}}if(t.timeDimensions)for(const C of t.timeDimensions){const[T,D]=C.dimension.split(".");if(T===l&&o.dimensions&&o.dimensions[D]){const N=o.dimensions[D],M=this.queryBuilder.buildTimeDimensionExpression(N.sql,C.granularity,n);w.push(M)}}return w.length>0&&(f=f.groupBy(...w)),n.db.$with(e.cteAlias).as(f)}buildCTEJoinCondition(e,t,n){const i=n.preAggregationCTEs?.find(o=>o.cube.name===e.cube.name);if(!i)throw new Error(`CTE info not found for cube ${e.cube.name}`);const s=[];if(i.intermediateJoins&&i.intermediateJoins.length>0){const o=i.intermediateJoins[0],a=this.resolveCTEJoinSourceColumn(i.joinKeys[0],i,n),u=r`${r.identifier(t)}.${r.identifier(o.primaryJoinColumn.name)}`;s.push(k(a,u))}else for(const o of i.joinKeys){const a=this.resolveCTEJoinSourceColumn(o,i,n),u=r`${r.identifier(t)}.${r.identifier(o.targetColumn)}`;s.push(k(a,u))}return s.length===1?s[0]:A(...s)}resolveCTEJoinSourceColumn(e,t,n){if(!e)throw new Error(`Missing join key while building CTE join condition for '${t.cube.name}'`);const i=e.sourceColumnObj||r.identifier(e.sourceColumn);if(!e.sourceColumnObj||!n.preAggregationCTEs)return i;for(const s of n.preAggregationCTEs)if(s.cube.name!==t.cube.name){for(const[o,a]of Object.entries(s.cube.dimensions||{}))if(typeof a.sql!="function"&&a.sql===e.sourceColumnObj)return r`${r.identifier(s.cteAlias)}.${r.identifier(o)}`}return i}buildPropagatingFilterSubquery(e,t){const n=e.sourceCube,i=n.sql(t),s=[];if(i.where&&s.push(i.where),e.preBuiltFilterSQL)s.push(e.preBuiltFilterSQL);else{const u={filters:e.filters},c=new Map([[n.name,n]]),l=this.queryBuilder.buildWhereConditions(c,u,t);s.push(...l)}if(s.length===0)return null;const o=s.length===1?s[0]:A(...s),a=e.joinConditions;if(a.length===1){const{source:u,target:c}=a[0],l=t.db.select({pk:u}).from(i.from).where(o);return r`${c} IN ${l}`}else{const u=a.map(m=>k(m.source,m.target)),c=A(...u,o),l=t.db.select({one:r`1`}).from(i.from).where(c);return r`EXISTS ${l}`}}}function dn(d,e,t){const n=[];let i=He(new Date(d),t);const s=He(new Date(e),t),o=1e4;for(;i<=s&&n.length<o;)n.push(new Date(i)),i=mn(i,t);return n}function He(d,e){const t=new Date(d);switch(e){case"second":t.setUTCMilliseconds(0);break;case"minute":t.setUTCSeconds(0,0);break;case"hour":t.setUTCMinutes(0,0,0);break;case"day":t.setUTCHours(0,0,0,0);break;case"week":{const n=t.getUTCDay(),i=n===0?6:n-1;t.setUTCDate(t.getUTCDate()-i),t.setUTCHours(0,0,0,0);break}case"month":t.setUTCDate(1),t.setUTCHours(0,0,0,0);break;case"quarter":{const n=Math.floor(t.getUTCMonth()/3)*3;t.setUTCMonth(n,1),t.setUTCHours(0,0,0,0);break}case"year":t.setUTCMonth(0,1),t.setUTCHours(0,0,0,0);break}return t}function mn(d,e){const t=new Date(d);switch(e){case"second":t.setUTCSeconds(t.getUTCSeconds()+1);break;case"minute":t.setUTCMinutes(t.getUTCMinutes()+1);break;case"hour":t.setUTCHours(t.getUTCHours()+1);break;case"day":t.setUTCDate(t.getUTCDate()+1);break;case"week":t.setUTCDate(t.getUTCDate()+7);break;case"month":t.setUTCMonth(t.getUTCMonth()+1);break;case"quarter":t.setUTCMonth(t.getUTCMonth()+3);break;case"year":t.setUTCFullYear(t.getUTCFullYear()+1);break}return t}function fn(d){if(d instanceof Date)return d.toISOString();if(typeof d=="string"){const e=new Date(d);if(!isNaN(e.getTime()))return e.toISOString()}return String(d)}function pn(d,e){return e.length===0?"__all__":e.map(t=>String(d[t]??"")).join("|||")}function hn(d,e){const{timeDimensionKey:t,granularity:n,dateRange:i,fillValue:s,measures:o,dimensions:a}=e,u=dn(i[0],i[1],n);if(u.length===0)return d;const c=new Map;for(const m of d){const p=pn(m,a),f=fn(m[t]);c.has(p)||c.set(p,new Map),c.get(p).set(f,m)}c.size===0&&a.length===0&&c.set("__all__",new Map);const l=[];for(const[m,p]of c){const f=p.size>0?p.values().next().value:null;for(const h of u){const g=h.toISOString(),y=p.get(g);if(y)l.push(y);else{const b={[t]:g};if(f)for(const w of a)b[w]=f[w];for(const w of o)b[w]=s;l.push(b)}}}return l}function gn(d){if(!d)return null;if(Array.isArray(d)){if(d.length<2)return null;const t=new Date(d[0]),n=new Date(d[1]);return isNaN(t.getTime())||isNaN(n.getTime())?null:[t,n]}const e=new Date(d);return isNaN(e.getTime())?null:[e,e]}function Ye(d,e,t){if(!e.timeDimensions||e.timeDimensions.length===0)return d;const n=e.timeDimensions.filter(u=>{const c=u.fillMissingDates!==!1,l=u.granularity&&u.dateRange;return c&&l});if(n.length===0)return d;const i=e.fillMissingDatesValue===void 0?0:e.fillMissingDatesValue,s=new Set(e.timeDimensions.map(u=>u.dimension)),o=(e.dimensions||[]).filter(u=>!s.has(u));let a=d;for(const u of n){const c=gn(u.dateRange);if(!c)continue;const l={timeDimensionKey:u.dimension,granularity:u.granularity,dateRange:c,fillValue:i,measures:t,dimensions:o};a=hn(a,l)}return a}class bn{dateTimeBuilder;constructor(e){this.dateTimeBuilder=new re(e)}hasComparison(e){return e.timeDimensions?.some(t=>t.compareDateRange&&t.compareDateRange.length>=2)??!1}getComparisonTimeDimension(e){return e.timeDimensions?.find(t=>t.compareDateRange&&t.compareDateRange.length>=2)}normalizePeriods(e){const t=[];for(let n=0;n<e.length;n++){const i=e[n];let s,o,a;if(typeof i=="string"){const u=this.dateTimeBuilder.parseRelativeDateRange(i);if(u)s=u.start,o=u.end,a=i;else{const c=new Date(i);if(!isNaN(c.getTime()))s=new Date(c),s.setUTCHours(0,0,0,0),o=new Date(c),o.setUTCHours(23,59,59,999),a=i;else continue}}else{if(s=new Date(i[0]),o=new Date(i[1]),isNaN(s.getTime())||isNaN(o.getTime()))continue;/^\d{4}-\d{2}-\d{2}$/.test(i[1])&&o.setUTCHours(23,59,59,999),a=`${i[0]} - ${i[1]}`}t.push({start:s,end:o,label:a,index:n})}return t}createPeriodQuery(e,t){return{...e,timeDimensions:e.timeDimensions?.map(n=>n.compareDateRange?{...n,dateRange:[t.start.toISOString(),t.end.toISOString()],compareDateRange:void 0}:n)}}calculatePeriodDayIndex(e,t,n){const i=typeof e=="string"?new Date(e):e,s=t.getTime(),o=i.getTime();switch(n){case"second":return Math.floor((o-s)/1e3);case"minute":return Math.floor((o-s)/(1e3*60));case"hour":return Math.floor((o-s)/(1e3*60*60));case"day":return Math.floor((o-s)/(1e3*60*60*24));case"week":return Math.floor((o-s)/(1e3*60*60*24*7));case"month":{const a=t.getUTCFullYear(),u=t.getUTCMonth(),c=i.getUTCFullYear(),l=i.getUTCMonth();return(c-a)*12+(l-u)}case"quarter":{const a=t.getUTCFullYear(),u=Math.floor(t.getUTCMonth()/3),c=i.getUTCFullYear(),l=Math.floor(i.getUTCMonth()/3);return(c-a)*4+(l-u)}case"year":return i.getUTCFullYear()-t.getUTCFullYear();default:return Math.floor((o-s)/(1e3*60*60*24))}}addPeriodMetadata(e,t,n,i){return e.map(s=>{const o=s[n];let a=0;if(o){const u=typeof o=="string"?new Date(o):o instanceof Date?o:null;u&&!isNaN(u.getTime())&&(a=this.calculatePeriodDayIndex(u,t.start,i))}return{...s,__period:t.label,__periodIndex:t.index,__periodDayIndex:a}})}mergeComparisonResults(e,t,n){const i=[];let s={measures:{},dimensions:{},segments:{},timeDimensions:{}};const o=e.map(u=>u.period);for(const{result:u,period:c}of e){const l=this.addPeriodMetadata(u.data,c,t.dimension,n);i.push(...l),s={measures:{...s.measures,...u.annotation.measures},dimensions:{...s.dimensions,...u.annotation.dimensions},segments:{...s.segments,...u.annotation.segments},timeDimensions:{...s.timeDimensions,...u.annotation.timeDimensions}}}const a={ranges:o.map(u=>[u.start.toISOString().split("T")[0],u.end.toISOString().split("T")[0]]),labels:o.map(u=>u.label),timeDimension:t.dimension,granularity:n};return{data:i,annotation:{...s,periods:a}}}sortComparisonResults(e,t){return[...e].sort((n,i)=>{const s=n.__periodIndex-i.__periodIndex;if(s!==0)return s;const o=n[t],a=i[t];return typeof o=="string"&&typeof a=="string"?new Date(o).getTime()-new Date(a).getTime():0})}}class yn{constructor(e){this.databaseAdapter=e,this.dateTimeBuilder=new re(e),this.filterBuilder=new be(e,this.dateTimeBuilder)}filterBuilder;dateTimeBuilder;hasFunnel(e){return e.funnel!==void 0&&e.funnel.steps.length>=2}validateConfig(e,t){const n=[];if(e.steps.length<2&&n.push("Funnel must have at least 2 steps"),typeof e.bindingKey=="string"){const[i,s]=e.bindingKey.split(".");if(!i||!s)n.push(`Invalid binding key format: ${e.bindingKey}. Expected 'CubeName.dimensionName'`);else{const o=t.get(i);o?o.dimensions?.[s]||n.push(`Binding key dimension not found: ${s} in cube ${i}`):n.push(`Binding key cube not found: ${i}`)}}else if(Array.isArray(e.bindingKey))for(const i of e.bindingKey){const s=t.get(i.cube);if(!s)n.push(`Binding key mapping cube not found: ${i.cube}`);else{const[,o]=i.dimension.split(".");s.dimensions?.[o]||n.push(`Binding key dimension not found: ${o} in cube ${i.cube}`)}}if(typeof e.timeDimension=="string"){const[i,s]=e.timeDimension.split(".");if(!i||!s)n.push(`Invalid time dimension format: ${e.timeDimension}. Expected 'CubeName.dimensionName'`);else{const o=t.get(i);o?o.dimensions?.[s]||n.push(`Time dimension not found: ${s} in cube ${i}`):n.push(`Time dimension cube not found: ${i}`)}}for(let i=0;i<e.steps.length;i++){const s=e.steps[i];if(s.name||n.push(`Step ${i} must have a name`),"cube"in s&&s.cube&&(t.get(s.cube)||n.push(`Step ${i} cube not found: ${s.cube}`)),s.filter){let o;"cube"in s&&s.cube?o=s.cube:typeof e.bindingKey=="string"&&([o]=e.bindingKey.split("."));const a=o?new ue(t):null,u=Array.isArray(s.filter)?s.filter:[s.filter];for(const c of u)if("member"in c){const[l,m]=c.member.split("."),p=t.get(l);if(!p)n.push(`Step ${i} filter cube not found: ${l}`);else if(p.dimensions?.[m]||(p.measures?.[m]?n.push(`Step ${i} filter '${l}.${m}' is a measure. Funnel step filters only support dimensions, not measures.`):n.push(`Step ${i} filter member not found: ${m} in cube ${l}`)),o&&l!==o&&a){const f=a.findPath(o,l);(!f||f.length===0)&&n.push(`Step ${i} filter '${l}.${m}' requires a join from '${o}' but no join path was found. Define a join relationship between these cubes.`)}}}s.timeToConvert&&i>0&&(/^P(?:\d+Y)?(?:\d+M)?(?:\d+D)?(?:T(?:\d+H)?(?:\d+M)?(?:\d+(?:\.\d+)?S)?)?$/.test(s.timeToConvert)||n.push(`Step ${i} timeToConvert must be ISO 8601 duration format: ${s.timeToConvert}`))}return{isValid:n.length===0,errors:n}}buildFunnelQuery(e,t,n){const i=this.resolveSteps(e,t,n),s=[];for(let c=0;c<i.length;c++){const l=c>0?s[c-1]:void 0;s.push(this.buildStepCTE(i[c],n,l))}const o=this.buildFunnelResultsCTE(s,i,e,n),a=this.buildAggregationCTE(o,s,i,e,n),u=[...s,o,a];return n.db.with(...u).select().from(a)}transformResult(e,t){if(!e||e.length===0)return[];const n=e[0],i=[],s=Number(n.step_0_count)||0;for(let o=0;o<t.steps.length;o++){const a=t.steps[o],u=Number(n[`step_${o}_count`])||0,c=o>0&&Number(n[`step_${o-1}_count`])||0,l={step:a.name,stepIndex:o,count:u,conversionRate:o===0?null:c>0?u/c:0,cumulativeConversionRate:s>0?u/s:0};t.includeTimeMetrics&&o>0&&(l.avgSecondsToConvert=n[`step_${o}_avg_seconds`]!==null?Number(n[`step_${o}_avg_seconds`]):null,l.minSecondsToConvert=n[`step_${o}_min_seconds`]!==null?Number(n[`step_${o}_min_seconds`]):null,l.maxSecondsToConvert=n[`step_${o}_max_seconds`]!==null?Number(n[`step_${o}_max_seconds`]):null,n[`step_${o}_median_seconds`]!==void 0&&(l.medianSecondsToConvert=n[`step_${o}_median_seconds`]!==null?Number(n[`step_${o}_median_seconds`]):null),n[`step_${o}_p90_seconds`]!==void 0&&(l.p90SecondsToConvert=n[`step_${o}_p90_seconds`]!==null?Number(n[`step_${o}_p90_seconds`]):null)),i.push(l)}return i}extractFilterCubeNames(e){const t=new Set;if(!e.filter)return t;const n=Array.isArray(e.filter)?e.filter:[e.filter],i=s=>{if("and"in s&&s.and)for(const o of s.and)i(o);else if("or"in s&&s.or)for(const o of s.or)i(o);else if("type"in s&&"filters"in s){const o=s;for(const a of o.filters||[])i(a)}else if("member"in s){const[o]=s.member.split(".");t.add(o)}};for(const s of n)i(s);return t}resolveSteps(e,t,n){const i=new ue(t);return e.steps.map((s,o)=>{const a=this.resolveCubeForStep(s,e,t),u=this.resolveBindingKey(e,a,n),c=this.resolveTimeDimension(e,a,n),l=this.buildStepFilters(s,a,t,n),m=this.extractFilterCubeNames(s),p=[];for(const f of m)if(f!==a.name){const h=t.get(f);if(h){const g=i.findPath(a.name,f);g&&g.length>0&&p.push({cube:h,joinPath:g})}}return{name:s.name,index:o,cube:a,bindingKeyExpr:u,timeExpr:c,filterConditions:l,timeToConvert:s.timeToConvert,joinedCubes:p}})}resolveCubeForStep(e,t,n){if("cube"in e&&e.cube){const i=n.get(e.cube);if(!i)throw new Error(`Cube not found for step: ${e.cube}`);return i}if(typeof t.bindingKey=="string"){const[i]=t.bindingKey.split("."),s=n.get(i);if(!s)throw new Error(`Cube not found for binding key: ${t.bindingKey}`);return s}throw new Error("Cannot resolve cube for step - multi-cube funnel requires cube specification in each step")}resolveBindingKey(e,t,n){if(typeof e.bindingKey=="string"){const[,a]=e.bindingKey.split("."),u=t.dimensions?.[a];if(!u)throw new Error(`Binding key dimension not found: ${e.bindingKey}`);return R(u.sql,n)}const i=e.bindingKey.find(a=>a.cube===t.name);if(!i)throw new Error(`No binding key mapping found for cube: ${t.name}`);const[,s]=i.dimension.split("."),o=t.dimensions?.[s];if(!o)throw new Error(`Binding key dimension not found: ${i.dimension}`);return R(o.sql,n)}resolveTimeDimension(e,t,n){if(typeof e.timeDimension=="string"){const[,a]=e.timeDimension.split("."),u=t.dimensions?.[a];if(!u)throw new Error(`Time dimension not found: ${e.timeDimension}`);return R(u.sql,n)}const i=e.timeDimension.find(a=>a.cube===t.name);if(!i)throw new Error(`No time dimension mapping found for cube: ${t.name}`);const[,s]=i.dimension.split("."),o=t.dimensions?.[s];if(!o)throw new Error(`Time dimension not found: ${i.dimension}`);return R(o.sql,n)}buildStepFilters(e,t,n,i){if(!e.filter)return[];const s=Array.isArray(e.filter)?e.filter:[e.filter],o=[];for(const a of s){const u=this.buildFilterCondition(a,t,n,i);u&&o.push(u)}return o}buildFilterCondition(e,t,n,i){const s="and"in e||"or"in e,o="type"in e&&"filters"in e&&(e.type==="and"||e.type==="or");if(s||o){const g=[];let y;if(o){const b=e;y=b.type==="and";for(const w of b.filters||[]){const $=this.buildFilterCondition(w,t,n,i);$&&g.push($)}}else{const b=e;y="and"in b&&!!b.and;const w=b.and||b.or||[];for(const $ of w){const S=this.buildFilterCondition($,t,n,i);S&&g.push(S)}}return g.length===0?null:g.length===1?g[0]:y?A(...g):r`(${r.join(g,r` OR `)})`}const a=e,[u,c]=a.member.split("."),l=a.dateRange!==void 0;if(a.operator!=="set"&&a.operator!=="notSet"&&!l&&(!a.values||a.values.length===0||a.values[0]===void 0||a.values[0]===""))return null;const p=n.get(u);if(!p)return null;if(u!==t.name){const y=new ue(n).findPath(t.name,u);if(!y||y.length===0)return console.warn(`Funnel filter: Cannot filter by '${u}.${c}' in step using '${t.name}'. No join path found. Filter will be skipped.`),null}const f=p.dimensions?.[c];if(!f)return null;const h=R(f.sql,i);return this.filterBuilder.buildFilterCondition(h,a.operator,a.values||[],f,a.dateRange)}buildStepCTE(e,t,n){return e.index===0?this.buildFirstStepCTE(e,t):this.buildSubsequentStepCTE(e,t,n)}buildFirstStepCTE(e,t){const n=`step_${e.index}`,i=e.cube.sql(t),s=[];i.where&&s.push(i.where),s.push(...e.filterConditions);let o=t.db.select({binding_key:r`${e.bindingKeyExpr}`.as("binding_key"),step_time:r`MIN(${e.timeExpr})`.as("step_time")}).from(i.from);if(o=this.addCrossJoinsToQuery(o,e,t,s),s.length>0){const a=s.length===1?s[0]:A(...s);o=o.where(a)}return o=o.groupBy(e.bindingKeyExpr),t.db.$with(n).as(o)}buildSubsequentStepCTE(e,t,n){const i=`step_${e.index}`,s=`step_${e.index-1}`,o=e.cube.sql(t),a=[];o.where&&a.push(o.where),a.push(...e.filterConditions);const u=r`${r.identifier(s)}.step_time`;let c=r`${e.timeExpr} > ${u}`;if(e.timeToConvert){const m=this.databaseAdapter.buildDateAddInterval(u,e.timeToConvert);c=r`${c} AND ${e.timeExpr} <= ${m}`}a.push(c);let l=t.db.select({binding_key:r`${e.bindingKeyExpr}`.as("binding_key"),step_time:r`MIN(${e.timeExpr})`.as("step_time")}).from(o.from).innerJoin(n,r`${e.bindingKeyExpr} = ${r.identifier(s)}.binding_key`);if(l=this.addCrossJoinsToQuery(l,e,t,a),a.length>0){const m=a.length===1?a[0]:A(...a);l=l.where(m)}return l=l.groupBy(e.bindingKeyExpr),t.db.$with(i).as(l)}addCrossJoinsToQuery(e,t,n,i){if(t.joinedCubes.length===0)return e;for(const s of t.joinedCubes)for(const o of s.joinPath){const a=o.joinDef,u=[];for(const p of a.on)p.as?u.push(p.as(p.source,p.target)):u.push(k(p.source,p.target));const c=u.length===1?u[0]:A(...u),m=s.cube.sql(n);e=e.leftJoin(m.from,c),m.where&&i.push(m.where)}return e}buildFunnelResultsCTE(e,t,n,i){const s={binding_key:r`s0.binding_key`,step_0_time:r`s0.step_time`};for(let l=1;l<t.length;l++)s[`step_${l}_time`]=r`s${r.raw(String(l))}.step_time`;let o=r`${r.identifier("step_0")} s0`;for(let l=1;l<t.length;l++)o=r`${o}
60
+ `);return Array.isArray(n)?n.map(i=>({table_name:i.table_name,index_name:i.index_name,columns:typeof i.columns=="string"?i.columns.split(","):[],is_unique:!!i.is_unique,is_primary:!!i.is_primary})):[]}catch(t){return console.warn("Failed to get table indexes:",t),[]}}}function Ht(d,e){return new Gt(d,e,"duckdb")}function Ve(d,e,t){if(t)switch(t){case"postgres":return ze(d,e);case"mysql":return xt(d,e);case"sqlite":return qe(d,e);case"singlestore":return Jt(d,e);case"duckdb":return Ht(d,e)}if(d.all&&d.run)return qe(d,e);if(d.execute)return ze(d,e);throw new Error("Unable to determine database engine type. Please specify engineType parameter.")}function z(d){return typeof d=="function"?d():d}function Re(d,e){if(e)return e;switch(d){case"belongsTo":return"inner";case"hasOne":return"left";case"hasMany":return"left";case"belongsToMany":return"left";default:return"left"}}function Fe(d){return d&&typeof d=="object"?r`${r`${d}`}`:d}function R(d,e){const t=typeof d=="function"?d(e):d;return Fe(t)}function Yt(d,e){if(d.relationship!=="belongsToMany"||!d.through)throw new Error("expandBelongsToManyJoin can only be called on belongsToMany relationships with through configuration");const{table:t,sourceKey:n,targetKey:i,securitySql:s}=d.through,o=[];for(const l of n){const m=l.as||k;o.push(m(l.source,l.target))}const a=[];for(const l of i){const m=l.as||k;a.push(m(l.source,l.target))}let u;if(s){const l=s(e);u=Array.isArray(l)?l:[l]}const c=Re("belongsToMany",d.sqlJoinType);return{junctionJoins:[{joinType:c,table:t,condition:A(...o)},{joinType:c,table:t,condition:A(...a)}],junctionSecurityConditions:u}}function fe(d){if("and"in d)return`and:[${d.and.map(fe).sort().join(",")}]`;if("or"in d)return`or:[${d.or.map(fe).sort().join(",")}]`;const e=d,t=JSON.stringify(Array.isArray(e.values)?[...e.values].sort():e.values),n=e.dateRange?`:dr:${JSON.stringify(e.dateRange)}`:"";return`${e.member}:${e.operator}:${t}${n}`}function lt(d,e){return`timeDim:${d}:${JSON.stringify(e)}`}class ne{cache=new Map;stats={hits:0,misses:0};getOrBuild(e,t){const n=this.cache.get(e);if(n!==void 0)return this.stats.hits++,n;const i=t();return i&&this.cache.set(e,i),this.stats.misses++,i}has(e){return this.cache.has(e)}get(e){const t=this.cache.get(e);return t!==void 0&&this.stats.hits++,t}preload(e){for(const{key:t,sql:n}of e)this.cache.has(t)||this.cache.set(t,n)}set(e,t){this.cache.set(e,t)}getStats(){return{...this.stats,cacheSize:this.cache.size}}clear(){this.cache.clear(),this.stats={hits:0,misses:0}}}function Me(d){const e=[];for(const t of d)"and"in t&&t.and?e.push(...Me(t.and)):"or"in t&&t.or?e.push(...Me(t.or)):"member"in t&&e.push(t);return e}function Xt(d,e,t={}){const n=t.keyPrefix??"drizzle-cube:",i=Zt(d),s=Ge(JSON.stringify(i));let o=`${n}query:${s}`;if(t.includeSecurityContext!==!1){const a=t.securityContextSerializer?t.securityContextSerializer(e):JSON.stringify(pe(e)),u=Ge(a);o+=`:ctx:${u}`}return o}function Zt(d){return{measures:d.measures?[...d.measures].sort():void 0,dimensions:d.dimensions?[...d.dimensions].sort():void 0,filters:d.filters?K(d.filters):void 0,timeDimensions:d.timeDimensions?sn(d.timeDimensions):void 0,limit:d.limit,offset:d.offset,order:d.order?pe(d.order):void 0,fillMissingDatesValue:d.fillMissingDatesValue,funnel:d.funnel?en(d.funnel):void 0,flow:d.flow?tn(d.flow):void 0,retention:d.retention?nn(d.retention):void 0}}function en(d){return{bindingKey:d.bindingKey,timeDimension:d.timeDimension,steps:d.steps.map(e=>{const t={name:e.name,filter:e.filter?Array.isArray(e.filter)?K(e.filter):K([e.filter])[0]:void 0,timeToConvert:e.timeToConvert};return"cube"in e&&e.cube&&(t.cube=e.cube),t}),includeTimeMetrics:d.includeTimeMetrics,globalTimeWindow:d.globalTimeWindow}}function tn(d){return{bindingKey:d.bindingKey,timeDimension:d.timeDimension,eventDimension:d.eventDimension,startingStep:{name:d.startingStep.name,filter:d.startingStep.filter?Array.isArray(d.startingStep.filter)?K(d.startingStep.filter):K([d.startingStep.filter])[0]:void 0},stepsBefore:d.stepsBefore,stepsAfter:d.stepsAfter,entityLimit:d.entityLimit,outputMode:d.outputMode,joinStrategy:d.joinStrategy}}function nn(d){return{timeDimension:d.timeDimension,bindingKey:d.bindingKey,dateRange:d.dateRange,granularity:d.granularity,periods:d.periods,retentionType:d.retentionType,cohortFilters:d.cohortFilters?Array.isArray(d.cohortFilters)?K(d.cohortFilters):K([d.cohortFilters])[0]:void 0,activityFilters:d.activityFilters?Array.isArray(d.activityFilters)?K(d.activityFilters):K([d.activityFilters])[0]:void 0,breakdownDimensions:d.breakdownDimensions}}function K(d){return[...d].map(e=>{if("and"in e&&e.and)return{and:K(e.and)};if("or"in e&&e.or)return{or:K(e.or)};const t=e;return{...t,values:t.values?[...t.values].sort():t.values}}).sort((e,t)=>JSON.stringify(e).localeCompare(JSON.stringify(t)))}function sn(d){return[...d].map(e=>({dimension:e.dimension,granularity:e.granularity,dateRange:e.dateRange,fillMissingDates:e.fillMissingDates,compareDateRange:e.compareDateRange?[...e.compareDateRange].sort((t,n)=>{const i=Array.isArray(t)?t.join("-"):t,s=Array.isArray(n)?n.join("-"):n;return i.localeCompare(s)}):void 0})).sort((e,t)=>e.dimension.localeCompare(t.dimension))}function pe(d){return d===null||typeof d!="object"?d:Array.isArray(d)?d.map(pe):Object.keys(d).sort().reduce((e,t)=>(e[t]=pe(d[t]),e),{})}function Ge(d){let e=2166136261;for(let t=0;t<d.length;t++)e^=d.charCodeAt(t),e=e*16777619>>>0;return e.toString(16).padStart(8,"0")}class re{constructor(e){this.databaseAdapter=e}buildTimeDimensionExpression(e,t,n){const i=R(e,n);return t?this.databaseAdapter.buildTimeDimension(t,i):i instanceof O?i:r`${i}`}buildDateRangeCondition(e,t){if(!t)return null;if(Array.isArray(t)&&t.length>=2){const n=this.normalizeDate(t[0]);let i=this.normalizeDate(t[1]);if(!n||!i)return null;if(typeof t[1]=="string"&&/^\d{4}-\d{2}-\d{2}$/.test(t[1].trim())){const s=typeof i=="number"?new Date(i*(this.databaseAdapter.getEngineType()==="sqlite"?1e3:1)):new Date(i),o=new Date(s);o.setUTCHours(23,59,59,999),this.databaseAdapter.isTimestampInteger()?i=this.databaseAdapter.getEngineType()==="sqlite"?Math.floor(o.getTime()/1e3):o.getTime():i=o.toISOString()}return A(ee(e,n),te(e,i))}if(typeof t=="string"){const n=this.parseRelativeDateRange(t);if(n){let l,m;return this.databaseAdapter.isTimestampInteger()?this.databaseAdapter.getEngineType()==="sqlite"?(l=Math.floor(n.start.getTime()/1e3),m=Math.floor(n.end.getTime()/1e3)):(l=n.start.getTime(),m=n.end.getTime()):(l=n.start.toISOString(),m=n.end.toISOString()),A(ee(e,l),te(e,m))}const i=this.normalizeDate(t);if(!i)return null;const s=typeof i=="number"?new Date(i*(this.databaseAdapter.getEngineType()==="sqlite"?1e3:1)):new Date(i),o=new Date(s);o.setUTCHours(0,0,0,0);const a=new Date(s);a.setUTCHours(23,59,59,999);let u,c;return this.databaseAdapter.isTimestampInteger()?this.databaseAdapter.getEngineType()==="sqlite"?(u=Math.floor(o.getTime()/1e3),c=Math.floor(a.getTime()/1e3)):(u=o.getTime(),c=a.getTime()):(u=o.toISOString(),c=a.toISOString()),A(ee(e,u),te(e,c))}return null}parseRelativeDateRange(e){const t=new Date,n=e.toLowerCase().trim(),i=t.getUTCFullYear(),s=t.getUTCMonth(),o=t.getUTCDate(),a=t.getUTCDay();if(n==="today"){const p=new Date(t);p.setUTCHours(0,0,0,0);const f=new Date(t);return f.setUTCHours(23,59,59,999),{start:p,end:f}}if(n==="yesterday"){const p=new Date(t);p.setUTCDate(o-1),p.setUTCHours(0,0,0,0);const f=new Date(t);return f.setUTCDate(o-1),f.setUTCHours(23,59,59,999),{start:p,end:f}}if(n==="this week"){const p=a===0?-6:1-a,f=new Date(t);f.setUTCDate(o+p),f.setUTCHours(0,0,0,0);const h=new Date(f);return h.setUTCDate(f.getUTCDate()+6),h.setUTCHours(23,59,59,999),{start:f,end:h}}if(n==="this month"){const p=new Date(Date.UTC(i,s,1,0,0,0,0)),f=new Date(Date.UTC(i,s+1,0,23,59,59,999));return{start:p,end:f}}if(n==="this quarter"){const p=Math.floor(s/3),f=new Date(Date.UTC(i,p*3,1,0,0,0,0)),h=new Date(Date.UTC(i,p*3+3,0,23,59,59,999));return{start:f,end:h}}if(n==="this year"){const p=new Date(Date.UTC(i,0,1,0,0,0,0)),f=new Date(Date.UTC(i,11,31,23,59,59,999));return{start:p,end:f}}const u=n.match(/^last\s+(\d+)\s+days?$/);if(u){const p=parseInt(u[1],10),f=new Date(t);f.setUTCDate(o-p+1),f.setUTCHours(0,0,0,0);const h=new Date(t);return h.setUTCHours(23,59,59,999),{start:f,end:h}}const c=n.match(/^last\s+(\d+)\s+weeks?$/);if(c){const f=parseInt(c[1],10)*7,h=new Date(t);h.setUTCDate(o-f+1),h.setUTCHours(0,0,0,0);const g=new Date(t);return g.setUTCHours(23,59,59,999),{start:h,end:g}}if(n==="last week"){const p=a===0?-13:-6-a,f=new Date(t);f.setUTCDate(o+p),f.setUTCHours(0,0,0,0);const h=new Date(f);return h.setUTCDate(f.getUTCDate()+6),h.setUTCHours(23,59,59,999),{start:f,end:h}}if(n==="last month"){const p=new Date(Date.UTC(i,s-1,1,0,0,0,0)),f=new Date(Date.UTC(i,s,0,23,59,59,999));return{start:p,end:f}}if(n==="last quarter"){const p=Math.floor(s/3),f=p===0?3:p-1,h=p===0?i-1:i,g=new Date(Date.UTC(h,f*3,1,0,0,0,0)),y=new Date(Date.UTC(h,f*3+3,0,23,59,59,999));return{start:g,end:y}}if(n==="last year"){const p=new Date(Date.UTC(i-1,0,1,0,0,0,0)),f=new Date(Date.UTC(i-1,11,31,23,59,59,999));return{start:p,end:f}}if(n==="last 12 months"){const p=new Date(Date.UTC(i,s-11,1,0,0,0,0)),f=new Date(t);return f.setUTCHours(23,59,59,999),{start:p,end:f}}const l=n.match(/^last\s+(\d+)\s+months?$/);if(l){const p=parseInt(l[1],10),f=new Date(Date.UTC(i,s-p+1,1,0,0,0,0)),h=new Date(t);return h.setUTCHours(23,59,59,999),{start:f,end:h}}const m=n.match(/^last\s+(\d+)\s+years?$/);if(m){const p=parseInt(m[1],10),f=new Date(Date.UTC(i-p,0,1,0,0,0,0)),h=new Date(t);return h.setUTCHours(23,59,59,999),{start:f,end:h}}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 n=e<1e10?e*1e3:e,i=new Date(n);return isNaN(i.getTime())?null:this.databaseAdapter.isTimestampInteger()?this.databaseAdapter.getEngineType()==="sqlite"?Math.floor(n/1e3):n:i.toISOString()}if(typeof e=="string"){if(/^\d{4}-\d{2}-\d{2}$/.test(e.trim())){const i=new Date(e+"T00:00:00Z");return isNaN(i.getTime())?null:this.databaseAdapter.isTimestampInteger()?this.databaseAdapter.getEngineType()==="sqlite"?Math.floor(i.getTime()/1e3):i.getTime():i.toISOString()}const n=new Date(e);return isNaN(n.getTime())?null:this.databaseAdapter.isTimestampInteger()?this.databaseAdapter.getEngineType()==="sqlite"?Math.floor(n.getTime()/1e3):n.getTime():n.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()}}class be{constructor(e,t){this.databaseAdapter=e,this.dateTimeBuilder=t}buildFilterCondition(e,t,n,i,s){if(s!==void 0){if(t!=="inDateRange")throw new Error(`dateRange can only be used with 'inDateRange' operator, but got '${t}'. Use explicit date values in the 'values' array for other date operators.`);if(i&&i.type!=="time")throw new Error(`dateRange can only be used on time dimensions, but field '${i.name||"unknown"}' has type '${i.type}'`);return this.dateTimeBuilder.buildDateRangeCondition(e,s)}if(!n||n.length===0)return t==="equals"?this.databaseAdapter.buildBooleanLiteral(!1):null;const o=n.filter(u=>!(u==null||u===""||typeof u=="string"&&u.includes("\0"))).map(this.databaseAdapter.convertFilterValue);if(o.length===0&&!["set","notSet"].includes(t))return t==="equals"?this.databaseAdapter.buildBooleanLiteral(!1):null;const a=o[0];switch(t){case"equals":if(o.length>1){if(i?.type==="time"){const u=o.map(c=>this.dateTimeBuilder.normalizeDate(c)||c);return De(e,u)}return De(e,o)}else if(o.length===1){const u=i?.type==="time"&&this.dateTimeBuilder.normalizeDate(a)||a;return k(e,u)}return this.databaseAdapter.buildBooleanLiteral(!1);case"notEquals":return o.length>1?Qe(e,o):o.length===1?Ue(e,a):null;case"contains":return this.databaseAdapter.buildStringCondition(e,"contains",a);case"notContains":return this.databaseAdapter.buildStringCondition(e,"notContains",a);case"startsWith":return this.databaseAdapter.buildStringCondition(e,"startsWith",a);case"endsWith":return this.databaseAdapter.buildStringCondition(e,"endsWith",a);case"gt":return Ee(e,a);case"gte":return ee(e,a);case"lt":return Se(e,a);case"lte":return te(e,a);case"set":return We(e);case"notSet":return Ke(e);case"inDateRange":if(o.length>=2){const u=this.dateTimeBuilder.normalizeDate(o[0]);let c=this.dateTimeBuilder.normalizeDate(o[1]);if(u&&c){const l=n[1];if(typeof l=="string"&&/^\d{4}-\d{2}-\d{2}$/.test(l.trim())){const m=typeof c=="number"?new Date(c*(this.databaseAdapter.getEngineType()==="sqlite"?1e3:1)):new Date(c),p=new Date(m);p.setUTCHours(23,59,59,999),this.databaseAdapter.isTimestampInteger()?c=this.databaseAdapter.getEngineType()==="sqlite"?Math.floor(p.getTime()/1e3):p.getTime():c=p.toISOString()}return A(ee(e,u),te(e,c))}}return null;case"beforeDate":{const u=this.dateTimeBuilder.normalizeDate(a);return u?Se(e,u):null}case"afterDate":{const u=this.dateTimeBuilder.normalizeDate(a);return u?Ee(e,u):null}case"between":return o.length>=2?A(ee(e,o[0]),te(e,o[1])):null;case"notBetween":return o.length>=2?oe(Se(e,o[0]),Ee(e,o[1])):null;case"in":return o.length>0?De(e,o):null;case"notIn":return o.length>0?Qe(e,o):null;case"like":return this.databaseAdapter.buildStringCondition(e,"like",a);case"notLike":return this.databaseAdapter.buildStringCondition(e,"notLike",a);case"ilike":return this.databaseAdapter.buildStringCondition(e,"ilike",a);case"regex":return this.databaseAdapter.buildStringCondition(e,"regex",a);case"notRegex":return this.databaseAdapter.buildStringCondition(e,"notRegex",a);case"isEmpty":return oe(Ke(e),k(e,""));case"isNotEmpty":return A(We(e),Ue(e,""));case"arrayContains":return this.databaseAdapter.getEngineType()==="postgres"?Dt(e,o):null;case"arrayOverlaps":return this.databaseAdapter.getEngineType()==="postgres"?At(e,o):null;case"arrayContained":return this.databaseAdapter.getEngineType()==="postgres"?Nt(e,o):null;default:return null}}buildLogicalFilter(e,t,n){if("and"in e&&e.and){const i=e.and.map(s=>this.buildSingleFilter(s,t,n)).filter(s=>s!==null);return i.length>0?i.length===1?i[0]:A(...i):null}if("or"in e&&e.or){const i=e.or.map(s=>this.buildSingleFilter(s,t,n)).filter(s=>s!==null);return i.length>0?i.length===1?i[0]:oe(...i):null}return null}buildSingleFilter(e,t,n){if("and"in e||"or"in e)return this.buildLogicalFilter(e,t,n);const i=e,[s,o]=i.member.split("."),a=t.get(s);if(!a)return null;const u=a.dimensions?.[o];if(!u)return null;const c=R(u.sql,n);return this.buildFilterCondition(c,i.operator,i.values,u,i.dateRange)}}class X{dependencyGraph;cubes;constructor(e){this.cubes=e instanceof Map?e:new Map([[e.name,e]]),this.dependencyGraph=new Map}extractDependencies(e){const t=/\{([^}]+)\}/g,n=e.matchAll(t),i=[];for(const s of n){const o=s[1].trim();if(o.includes(".")){const[a,u]=o.split(".");i.push({measureName:o,cubeName:a.trim(),fieldName:u.trim()})}else i.push({measureName:o,cubeName:null,fieldName:o})}return i}buildGraph(e){for(const[t,n]of Object.entries(e.measures))if(n.type==="calculated"&&n.calculatedSql){const i=`${e.name}.${t}`,s=this.extractDependencies(n.calculatedSql),o=new Set;for(const a of s){const c=`${a.cubeName||e.name}.${a.fieldName}`;o.add(c)}this.dependencyGraph.set(i,{id:i,dependencies:o,inDegree:0})}this.calculateInDegrees()}buildGraphForMultipleCubes(e){for(const t of e.values())this.buildGraph(t)}calculateInDegrees(){for(const e of this.dependencyGraph.values())e.inDegree=0;for(const e of this.dependencyGraph.values())for(const t of e.dependencies){const n=this.dependencyGraph.get(t);n&&n.inDegree++}}topologicalSort(e){const t=new Map,n=[],i=[];for(const s of e){const o=this.dependencyGraph.get(s);o&&t.set(s,{id:o.id,dependencies:new Set(o.dependencies),inDegree:0})}for(const s of t.values()){let o=0;for(const a of s.dependencies)t.has(a)&&o++;s.inDegree=o}for(const[s,o]of t)o.inDegree===0&&n.push(s);for(;n.length>0;){const s=n.shift();i.push(s);for(const[o,a]of t)a.dependencies.has(s)&&(a.inDegree--,a.inDegree===0&&n.push(o))}if(i.length<t.size){const s=this.detectCycle();throw new Error(`Circular dependency detected in calculated measures: ${s?s.join(" -> "):"unknown cycle"}`)}return i}detectCycle(){const e=new Set,t=new Set,n=[];for(const i of this.dependencyGraph.keys())if(!e.has(i)){const s=this.dfs(i,e,t,n);if(s)return s}return null}dfs(e,t,n,i){t.add(e),n.add(e),i.push(e);const s=this.dependencyGraph.get(e);if(!s)return i.pop(),n.delete(e),null;for(const o of s.dependencies)if(t.has(o)){if(n.has(o)){const a=i.indexOf(o);return[...i.slice(a),o]}}else{const a=this.dfs(o,t,n,i);if(a)return a}return i.pop(),n.delete(e),null}getAllDependencies(e){const t=new Set,n=new Set,i=s=>{if(n.has(s))return;n.add(s);const o=this.dependencyGraph.get(s);if(o)for(const a of o.dependencies)t.add(a),i(a)};return i(e),t}validateDependencies(e){for(const[t,n]of Object.entries(e.measures))if(n.type==="calculated"&&n.calculatedSql){const i=this.extractDependencies(n.calculatedSql);for(const s of i){const o=s.cubeName||e.name,a=this.cubes.get(o);if(!a)throw new Error(`Calculated measure '${e.name}.${t}' references unknown cube '${o}'`);if(!a.measures[s.fieldName])throw new Error(`Calculated measure '${e.name}.${t}' references unknown measure '${s.measureName}'`);if(o===e.name&&s.fieldName===t)throw new Error(`Calculated measure '${e.name}.${t}' cannot reference itself`)}}}populateDependencies(e){for(const[,t]of Object.entries(e.measures))if(t.type==="calculated"&&t.calculatedSql&&!t.dependencies){const n=this.extractDependencies(t.calculatedSql);t.dependencies=n.map(i=>i.measureName)}}static isCalculatedMeasure(e){return e.type==="calculated"&&!!e.calculatedSql}}function rn(d,e){const{cube:t,allCubes:n,resolvedMeasures:i}=e,s=Oe(d),o=new Map;for(const m of s){const{originalRef:p,cubeName:f,fieldName:h}=m,g=f||t.name;if(!n.get(g))throw new Error(`Cannot substitute {${p}}: cube '${g}' not found`);const b=`${g}.${h}`,w=i.get(b);if(!w)throw new Error(`Cannot substitute {${p}}: measure '${b}' not resolved yet. Ensure measures are resolved in dependency order.`);const $=w(),S=r`${$}`;o.set(p,S)}const a=[],u=[];let c=0;for(const m of s){const p=`{${m.originalRef}}`,f=d.indexOf(p,c);if(f>=0){a.push(d.substring(c,f));const h=o.get(m.originalRef);h&&u.push(h),c=f+p.length}}if(a.push(d.substring(c)),u.length===0)return r.raw(d);const l=[];for(let m=0;m<a.length;m++)a[m]&&l.push(new P(a[m])),m<u.length&&l.push(u[m]);return r.join(l,r.raw(""))}function Oe(d){const e=/\{([^}]+)\}/g,t=d.matchAll(e),n=[];for(const i of t){const s=i[1].trim();if(s.includes(".")){const[o,a]=s.split(".").map(u=>u.trim());n.push({originalRef:s,cubeName:o,fieldName:a})}else n.push({originalRef:s,cubeName:null,fieldName:s})}return n}function on(d){const e=[];let t=0;for(let o=0;o<d.length;o++)if(d[o]==="{")t++;else if(d[o]==="}"&&(t--,t<0)){e.push(`Unmatched closing brace at position ${o}`);break}t>0&&e.push("Unmatched opening brace in template"),/\{\s*\}/.test(d)&&e.push("Empty member reference {} found in template"),/\{[^}]*\{/.test(d)&&e.push("Nested braces are not allowed in member references");const s=Oe(d);for(const o of s){const a=o.cubeName?`${o.cubeName}.${o.fieldName}`:o.fieldName;/^[a-zA-Z_][a-zA-Z0-9_.]*$/.test(a)||e.push(`Invalid member reference {${o.originalRef}}: must start with letter or underscore, and contain only letters, numbers, underscores, and dots`),a.split(".").length>2&&e.push(`Invalid member reference {${o.originalRef}}: only one dot allowed (Cube.measure format)`)}return{isValid:e.length===0,errors:e}}function Ne(d,e){const t=Oe(d),n=new Set;for(const i of t){const o=`${i.cubeName||e}.${i.fieldName}`;n.add(o)}return Array.from(n)}class L{constructor(e){this.databaseAdapter=e}buildResolvedMeasures(e,t,n,i){const s=new Map,o=[],a=[],u=new Set(e),c=new X(t);for(const l of t.values())c.buildGraph(l);for(const l of e){const[m,p]=l.split("."),f=t.get(m);if(f&&f.measures&&f.measures[p]){const h=f.measures[p];if(L.isPostAggregationWindow(h)){const g=L.getWindowBaseMeasure(h,m);g&&u.add(g);continue}X.isCalculatedMeasure(h)?(a.push(l),Ne(h.calculatedSql,m).forEach(b=>u.add(b)),c.getAllDependencies(l).forEach(b=>{const[w,$]=b.split("."),S=t.get(w);if(S&&S.measures[$]){const C=S.measures[$];X.isCalculatedMeasure(C)&&Ne(C.calculatedSql,w).forEach(D=>u.add(D))}})):o.push(l)}}for(const l of u){const[m,p]=l.split("."),f=t.get(m);if(f&&f.measures&&f.measures[p]){const h=f.measures[p];if(L.isPostAggregationWindow(h))continue;X.isCalculatedMeasure(h)?a.includes(l)||a.push(l):o.includes(l)||o.push(l)}}for(const l of o){const[m,p]=l.split("."),f=t.get(m),h=f.measures[p];if(i){const g=i(l,h,f);s.set(l,()=>g)}else s.set(l,()=>this.buildMeasureExpression(h,n,f))}if(a.length>0){const l=c.topologicalSort(a);for(const m of l){const[p,f]=m.split("."),h=t.get(p),g=h.measures[f];s.set(m,()=>this.buildCalculatedMeasure(g,h,t,s,n))}}return s}buildCalculatedMeasure(e,t,n,i,s){if(!e.calculatedSql)throw new Error(`Calculated measure '${t.name}.${e.name}' missing calculatedSql property`);const o=this.databaseAdapter.preprocessCalculatedTemplate(e.calculatedSql);return rn(o,{cube:t,allCubes:n,resolvedMeasures:i})}buildCTECalculatedMeasure(e,t,n,i,s){if(!e.calculatedSql)throw new Error(`Calculated measure '${t.name}.${e.name||"unknown"}' missing calculatedSql property`);const o=new Map,a=Ne(e.calculatedSql,t.name);for(const u of a){const[c,l]=u.split("."),m=i.get(c);if(m&&m.measures[l]){const p=m.measures[l];if(n.measures.includes(u)){const f=r`${r.identifier(n.cteAlias)}.${r.identifier(l)}`;let h;switch(p.type){case"count":case"countDistinct":case"sum":h=V(f);break;case"avg":h=this.databaseAdapter.buildAvg(f);break;case"min":h=ae(f);break;case"max":h=H(f);break;case"number":h=V(f);break;default:h=V(f)}o.set(u,()=>h)}}}return this.buildCalculatedMeasure(e,t,i,o,s)}buildHavingMeasureExpression(e,t,n,i,s){if(s&&s.preAggregationCTEs){const o=s.preAggregationCTEs.find(a=>a.cube.name===e);if(o&&o.measures.includes(`${e}.${t}`))if(n.type==="calculated"&&n.calculatedSql){const a=s.primaryCube.name===e?s.primaryCube:s.joinCubes?.find(c=>c.cube.name===e)?.cube;if(!a)throw new Error(`Cube ${e} not found in query plan`);const u=new Map([[s.primaryCube.name,s.primaryCube]]);if(s.joinCubes)for(const c of s.joinCubes)u.set(c.cube.name,c.cube);return this.buildCTECalculatedMeasure(n,a,o,u,i)}else{const a=r`${r.identifier(o.cteAlias)}.${r.identifier(t)}`;switch(n.type){case"count":case"countDistinct":case"sum":return V(a);case"avg":return this.databaseAdapter.buildAvg(a);case"min":return ae(a);case"max":return H(a);case"number":return V(a);default:return V(a)}}}return this.buildMeasureExpression(n,i)}buildMeasureExpression(e,t,n){if(e.type==="calculated")throw new Error(`Cannot build calculated measure '${e.name}' directly. Use buildCalculatedMeasure instead.`);if(L.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 i=R(e.sql,t);if(e.filters&&e.filters.length>0){const s=e.filters.map(o=>{const a=o(t);return a?r`(${a})`:void 0}).filter(Boolean);if(s.length>0){const o=s.length===1?s[0]:A(...s);i=this.databaseAdapter.buildCaseWhen([{when:o,then:i}])}}switch(e.type){case"count":return ve(i);case"countDistinct":return vt(i);case"sum":return V(i);case"avg":return this.databaseAdapter.buildAvg(i);case"min":return ae(i);case"max":return H(i);case"number":return i;case"stddev":case"stddevSamp":{const s=e.type==="stddevSamp"||e.statisticalConfig?.useSample,o=this.databaseAdapter.buildStddev(i,s);return o===null?(console.warn(`[drizzle-cube] ${e.type} not supported on ${this.databaseAdapter.getEngineType()}, returning NULL`),r`MAX(NULL)`):o}case"variance":case"varianceSamp":{const s=e.type==="varianceSamp"||e.statisticalConfig?.useSample,o=this.databaseAdapter.buildVariance(i,s);return o===null?(console.warn(`[drizzle-cube] ${e.type} not supported on ${this.databaseAdapter.getEngineType()}, returning NULL`),r`MAX(NULL)`):o}case"percentile":case"median":case"p95":case"p99":{let s;switch(e.type){case"median":s=50;break;case"p95":s=95;break;case"p99":s=99;break;default:s=e.statisticalConfig?.percentile??50}const o=this.databaseAdapter.buildPercentile(i,s);return o===null?(console.warn(`[drizzle-cube] ${e.type} not supported on ${this.databaseAdapter.getEngineType()}, returning NULL`),r`MAX(NULL)`):o}case"lag":case"lead":case"rank":case"denseRank":case"rowNumber":case"ntile":case"firstValue":case"lastValue":case"movingAvg":case"movingSum":{const s=e.windowConfig||{};let o;if(s.partitionBy&&s.partitionBy.length>0&&n){const c=s.partitionBy.map(l=>{const m=l.includes(".")?l.split(".")[1]:l,p=n.dimensions?.[m];return p?R(p.sql,t):(console.warn(`[drizzle-cube] Window function partition dimension '${l}' not found in cube '${n.name}'`),null)}).filter(l=>l!==null);c.length>0&&(o=c)}let a;if(s.orderBy&&s.orderBy.length>0&&n){const c=s.orderBy.map(l=>{const m=l.field.includes(".")?l.field.split(".")[1]:l.field,p=n.dimensions?.[m];if(p)return{field:R(p.sql,t),direction:l.direction};const f=n.measures?.[m];return f&&f.sql?{field:R(f.sql,t),direction:l.direction}:(console.warn(`[drizzle-cube] Window function order field '${l.field}' not found in cube '${n.name}'`),null)}).filter(l=>l!==null);c.length>0&&(a=c)}const u=this.databaseAdapter.buildWindowFunction(e.type,["rank","denseRank","rowNumber"].includes(e.type)?null:i,o,a,{offset:s.offset,defaultValue:s.defaultValue,nTile:s.nTile,frame:s.frame});return u===null?(console.warn(`[drizzle-cube] ${e.type} not supported on ${this.databaseAdapter.getEngineType()}, returning NULL`),r`NULL`):u}default:return ve(i)}}static WINDOW_FUNCTION_TYPES=["lag","lead","rank","denseRank","rowNumber","ntile","firstValue","lastValue","movingAvg","movingSum"];static isWindowFunction(e){return L.WINDOW_FUNCTION_TYPES.includes(e)}static categorizeMeasures(e,t){const n=[],i=[];for(const s of e){const[o,a]=s.split("."),u=t.get(o);if(u?.measures?.[a]){const c=u.measures[a];L.isWindowFunction(c.type)?n.push(s):i.push(s)}}return{windowMeasures:n,aggregateMeasures:i}}static hasWindowFunctions(e,t){const{windowMeasures:n}=L.categorizeMeasures(e,t);return n.length>0}static isPostAggregationWindow(e){return L.isWindowFunction(e.type)&&e.windowConfig?.measure!==void 0}static getWindowBaseMeasure(e,t){if(!e.windowConfig?.measure)return null;const n=e.windowConfig.measure;return n.includes(".")?n:`${t}.${n}`}static getDefaultWindowOperation(e){switch(e){case"lag":case"lead":return"difference";default:return"raw"}}static categorizeForPostAggregation(e,t){const n=[],i=[],s=new Set;for(const o of e){const[a,u]=o.split("."),c=t.get(a);if(c?.measures?.[u]){const l=c.measures[u];if(L.isPostAggregationWindow(l)){i.push(o);const m=L.getWindowBaseMeasure(l,a);m&&s.add(m)}else L.isWindowFunction(l.type)||n.push(o)}}return{aggregateMeasures:n,postAggWindowMeasures:i,requiredBaseMeasures:s}}static hasPostAggregationWindows(e,t){const{postAggWindowMeasures:n}=L.categorizeForPostAggregation(e,t);return n.length>0}}class an{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,t,n,i){const s=[],o=e instanceof Map?e:new Map([[e.name,e]]),a=t.dimensions&&t.dimensions.length>0||t.timeDimensions&&t.timeDimensions.length>0,u=t.measures&&t.measures.length>0,c=a&&!u;let l=!1;for(const m of t.measures||[]){const[p,f]=m.split("."),h=o.get(p);if(h&&h.measures&&h.measures[f]){const g=h.measures[f];if(this.isAggregateFunctionType(g.type)||g.type==="calculated"){l=!0;break}if(L.isPostAggregationWindow(g)){const y=L.getWindowBaseMeasure(g,p);if(y){const[b,w]=y.split("."),S=o.get(b)?.measures?.[w];if(S&&this.isAggregateFunctionType(S.type)){l=!0;break}}}}}if(!l&&!c)return[];if(t.dimensions)for(const m of t.dimensions){const[p,f]=m.split("."),h=o.get(p);if(h&&h.dimensions&&h.dimensions[f]){const g=i?.preAggregationCTEs?.find(y=>y.cube.name===p);if(g){const y=g.joinKeys.find(b=>b.targetColumn===f);if(y&&y.sourceColumnObj)s.push(y.sourceColumnObj);else{const b=r`${r.identifier(g.cteAlias)}.${r.identifier(f)}`;s.push(b)}}else{const y=h.dimensions[f],b=R(y.sql,n);s.push(b)}}}if(t.timeDimensions)for(const m of t.timeDimensions){const[p,f]=m.dimension.split("."),h=o.get(p);if(h&&h.dimensions&&h.dimensions[f]){const g=i?.preAggregationCTEs?.find(y=>y.cube.name===p);if(g){const y=g.joinKeys.find(b=>b.targetColumn===f);if(y&&y.sourceColumnObj){const b=this.dateTimeBuilder.buildTimeDimensionExpression(y.sourceColumnObj,m.granularity,n);s.push(b)}else{const b=r`${r.identifier(g.cteAlias)}.${r.identifier(f)}`;s.push(b)}}else{const y=h.dimensions[f],b=this.dateTimeBuilder.buildTimeDimensionExpression(y.sql,m.granularity,n);s.push(b)}}}return s}}class un{dateTimeBuilder;filterBuilder;groupByBuilder;measureBuilder;constructor(e){this.dateTimeBuilder=new re(e),this.filterBuilder=new be(e,this.dateTimeBuilder),this.groupByBuilder=new an(this.dateTimeBuilder),this.measureBuilder=new L(e)}buildResolvedMeasures(e,t,n,i){return this.measureBuilder.buildResolvedMeasures(e,t,n,i)}buildSelections(e,t,n){const i={},s=e instanceof Map?e:new Map([[e.name,e]]);if(t.dimensions)for(const o of t.dimensions){const[a,u]=o.split("."),c=s.get(a);if(c&&c.dimensions&&c.dimensions[u]){const l=c.dimensions[u],m=R(l.sql,n);i[o]=r`${m}`.as(o)}}if(t.measures){const o=this.buildResolvedMeasures(t.measures,s,n);for(const a of t.measures){const u=o.get(a);if(u){const c=u();i[a]=r`${c}`.as(a)}}}if(t.timeDimensions)for(const o of t.timeDimensions){const[a,u]=o.dimension.split("."),c=s.get(a);if(c&&c.dimensions&&c.dimensions[u]){const l=c.dimensions[u],m=this.buildTimeDimensionExpression(l.sql,o.granularity,n);i[o.dimension]=r`${m}`.as(o.dimension)}}return Object.keys(i).length===0&&(i.count=ve()),i}buildCalculatedMeasure(e,t,n,i,s){return this.measureBuilder.buildCalculatedMeasure(e,t,n,i,s)}buildCTECalculatedMeasure(e,t,n,i,s){return this.measureBuilder.buildCTECalculatedMeasure(e,t,n,i,s)}buildHavingMeasureExpression(e,t,n,i,s){return this.measureBuilder.buildHavingMeasureExpression(e,t,n,i,s)}buildMeasureExpression(e,t,n){return this.measureBuilder.buildMeasureExpression(e,t,n)}buildTimeDimensionExpression(e,t,n){return this.dateTimeBuilder.buildTimeDimensionExpression(e,t,n)}buildWhereConditions(e,t,n,i,s){const o=[],a=e instanceof Map?e:new Map([[e.name,e]]),u=new Set;if(t.filters&&t.filters.length>0)for(const c of t.filters){if(s&&"member"in c){const[m]=c.member.split(".");if(a.has(m)&&s.has(m)&&!u.has(m)){const f=s.get(m);o.push(...f),u.add(m);continue}else if(u.has(m))continue}const l=this.processFilter(c,a,n,"where",i);l&&o.push(l)}if(t.timeDimensions)for(const c of t.timeDimensions){const[l,m]=c.dimension.split("."),p=a.get(l);if(p&&p.dimensions[m]&&c.dateRange){if(i?.preAggregationCTEs&&i.preAggregationCTEs.some(b=>b.cube.name===l))continue;if(n.filterCache){const y=lt(c.dimension,c.dateRange),b=n.filterCache.get(y);if(b){o.push(b);continue}}const f=p.dimensions[m],h=R(f.sql,n),g=this.buildDateRangeCondition(h,c.dateRange);g&&o.push(g)}}return o}buildHavingConditions(e,t,n,i){const s=[],o=e instanceof Map?e:new Map([[e.name,e]]);if(t.filters&&t.filters.length>0)for(const a of t.filters){const u=this.processFilter(a,o,n,"having",i);u&&s.push(u)}return s}processFilter(e,t,n,i,s){if("and"in e||"or"in e){const f=e;if(f.and){const h=f.and.map(g=>this.processFilter(g,t,n,i,s)).filter(g=>g!==null);return h.length>0?A(...h):null}if(f.or){const h=f.or.map(g=>this.processFilter(g,t,n,i,s)).filter(g=>g!==null);return h.length>0?oe(...h):null}}const o=e,[a,u]=o.member.split("."),c=t.get(a);if(!c)return null;const l=c.dimensions[u],m=c.measures[u],p=l||m;if(!p)return null;if(i==="where"&&l){if(s?.preAggregationCTEs&&s.preAggregationCTEs.some(y=>y.cube.name===a))return null;const f=["arrayContains","arrayOverlaps","arrayContained"].includes(o.operator);if(!f&&n.filterCache){const g=fe(e),y=n.filterCache.get(g);if(y)return y}const h=f?typeof l.sql=="function"?l.sql(n):l.sql:R(l.sql,n);return this.buildFilterCondition(h,o.operator,o.values,p,o.dateRange)}else{if(i==="where"&&m)return null;if(i==="having"&&m){const f=this.buildHavingMeasureExpression(a,u,m,n,s);return this.buildFilterCondition(f,o.operator,o.values,p,o.dateRange)}}return null}buildFilterCondition(e,t,n,i,s){return this.filterBuilder.buildFilterCondition(e,t,n,i,s)}buildDateRangeCondition(e,t){return this.dateTimeBuilder.buildDateRangeCondition(e,t)}buildGroupByFields(e,t,n,i){return this.groupByBuilder.buildGroupByFields(e,t,n,i)}buildOrderBy(e,t){const n=[],i=t||[...e.measures||[],...e.dimensions||[],...e.timeDimensions?.map(s=>s.dimension)||[]];if(e.order&&Object.keys(e.order).length>0)for(const[s,o]of Object.entries(e.order)){if(!i.includes(s))throw new Error(`Cannot order by '${s}': field is not selected in the query`);const a=o==="desc"?_t(r.identifier(s)):Je(r.identifier(s));n.push(a)}if(e.timeDimensions&&e.timeDimensions.length>0){const s=new Set(Object.keys(e.order||{})),o=[...e.timeDimensions].sort((a,u)=>a.dimension.localeCompare(u.dimension));for(const a of o)s.has(a.dimension)||n.push(Je(r.identifier(a.dimension)))}return n}collectNumericFields(e,t){const n=[],i=e instanceof Map?e:new Map([[e.name,e]]);if(t.measures&&n.push(...t.measures),t.dimensions)for(const s of t.dimensions){const[o,a]=s.split("."),u=i.get(o);if(u){const c=u.dimensions[a];c&&c.type==="number"&&n.push(s)}}return n}applyLimitAndOffset(e,t){let n=t.limit;t.offset!==void 0&&t.offset>0&&n===void 0&&(n=50);let i=e;if(n!==void 0){if(n<0)throw new Error("Limit must be non-negative");i=i.limit(n)}if(t.offset!==void 0){if(t.offset<0)throw new Error("Offset must be non-negative");i=i.offset(t.offset)}return i}buildFilterConditionPublic(e,t,n,i,s){return this.buildFilterCondition(e,t,n,i,s)}buildLogicalFilter(e,t,n){return this.filterBuilder.buildLogicalFilter(e,t,n)}}class ue{cubes;connectivityCache=new Map;constructor(e){this.cubes=e}findPath(e,t,n=new Set){if(e===t)return[];const i=this.getCacheKey(e,t,n),s=this.getFromCache(i);if(s!==void 0)return s;const o=[{cube:e,path:[]}],a=new Set([e,...n]);for(;o.length>0;){const{cube:u,path:c}=o.shift(),l=this.cubes.get(u);if(l?.joins)for(const[,m]of Object.entries(l.joins)){const f=z(m.targetCube).name;if(a.has(f))continue;const h=[...c,{fromCube:u,toCube:f,joinDef:m}];if(f===t)return this.setInCache(i,h),h;a.add(f),o.push({cube:f,path:h})}}return this.setInCache(i,null),null}findPathPreferring(e,t,n,i=new Set){return this.findPathPreferringDetailed(e,t,n,i).selectedPath}findPathPreferringDetailed(e,t,n,i=new Set){const s=this.findAllPaths(e,t,new Set);if(s.length===0){const a=this.findPath(e,t,i),u=a?[{path:a,score:0,usesPreferredJoin:!1,preferredCubesInPath:0,usesProcessed:a.some(c=>i.has(c.toCube)),scoreBreakdown:{preferredJoinBonus:0,preferredCubeBonus:0,lengthPenalty:0}}]:[];return{strategy:"fallbackShortest",preferredCubes:Array.from(n).sort(),selectedIndex:a?0:-1,candidates:u,selectedPath:a}}const o=s.map(a=>{let u=0;const c=a.some((h,g)=>h.joinDef.preferredFor?.includes(t)&&g===0);c&&(u=10);const l=a.filter(h=>n.has(h.toCube)).length,m=l,p=a.length-1,f=u+m-p;return{path:a,score:f,usesPreferredJoin:c,preferredCubesInPath:l,usesProcessed:a.some(h=>i.has(h.toCube)),scoreBreakdown:{preferredJoinBonus:u,preferredCubeBonus:m,lengthPenalty:p}}});return o.sort((a,u)=>u.score!==a.score?u.score-a.score:a.usesProcessed!==u.usesProcessed?a.usesProcessed?-1:1:a.path.length-u.path.length),{strategy:"preferred",preferredCubes:Array.from(n).sort(),selectedIndex:o.length>0?0:-1,candidates:o,selectedPath:o[0]?.path??null}}findAllPaths(e,t,n,i=4){if(e===t)return[[]];const s=[],o=[{cube:e,path:[],visited:new Set([e,...n])}];for(;o.length>0;){const{cube:a,path:u,visited:c}=o.shift();if(u.length>=i)continue;const l=this.cubes.get(a);if(l?.joins)for(const[,m]of Object.entries(l.joins)){const f=z(m.targetCube).name;if(c.has(f))continue;const h=[...u,{fromCube:a,toCube:f,joinDef:m}];if(f===t)s.push(h);else{const g=new Set(c);g.add(f),o.push({cube:f,path:h,visited:g})}}}return s}canReachAll(e,t){const n=t.filter(i=>i!==e);for(const i of n){const s=this.findPath(e,i,new Set);if(!s||s.length===0)return!1}return!0}buildJoinCondition(e,t,n){const i=[];for(const s of e.on){const o=t?r`${r.identifier(t)}.${r.identifier(s.source.name)}`:Fe(s.source),a=n?r`${r.identifier(n)}.${r.identifier(s.target.name)}`:Fe(s.target),u=s.as||k;i.push(u(o,a))}return A(...i)}getReachableCubes(e){const t=new Set([e]),n=[e];for(;n.length>0;){const i=n.shift(),s=this.cubes.get(i);if(s?.joins)for(const[,o]of Object.entries(s.joins)){const u=z(o.targetCube).name;t.has(u)||(t.add(u),n.push(u))}}return t}getCacheKey(e,t,n){const i=Array.from(n).sort().join(",");return`${e}:${t}:${i}`}getFromCache(e){const t=this.connectivityCache.get(e);if(t)return t.path}setInCache(e,t){this.connectivityCache.set(e,{path:t})}}class ln{resolverCache=new WeakMap;getResolver(e){let t=this.resolverCache.get(e);return t||(t=new ue(e),this.resolverCache.set(e,t)),t}analyzeCubeUsage(e){const t=new Set;if(e.measures)for(const n of e.measures){const[i]=n.split(".");t.add(i)}if(e.dimensions)for(const n of e.dimensions){const[i]=n.split(".");t.add(i)}if(e.timeDimensions)for(const n of e.timeDimensions){const[i]=n.dimension.split(".");t.add(i)}if(e.filters)for(const n of e.filters)this.extractCubeNamesFromFilter(n,t);if(e.order)for(const n of Object.keys(e.order)){const[i]=n.split(".");i&&t.add(i)}return t}collectPathHintCubes(e){return this.analyzeCubeUsage(e)}extractCubeNamesFromFilter(e,t){if("and"in e||"or"in e){const n=e.and||e.or||[];for(const i of n)this.extractCubeNamesFromFilter(i,t);return}if("member"in e){const[n]=e.member.split(".");n&&t.add(n)}}extractMeasuresFromFilters(e,t){const n=[];if(!e.filters)return n;for(const i of e.filters)this.extractMeasuresFromFilter(i,t,n);return n}extractMeasuresFromFilter(e,t,n){if("and"in e||"or"in e){const i=e.and||e.or||[];for(const s of i)this.extractMeasuresFromFilter(s,t,n);return}if("member"in e){const i=e.member,[s,o]=i.split(".");s===t.name&&t.measures&&t.measures[o]&&n.push(i)}}choosePrimaryCube(e,t,n){return e.length===1?e[0]:n?this.analyzePrimaryCubeSelection(e,t,n).selectedCube:[...e].sort()[0]}analyzePrimaryCube(e,t,n){return this.analyzePrimaryCubeSelection(e,t,n)}analyzeJoinPathForTarget(e,t,n,i){return this.analyzeJoinPath(e,t,n,i)}buildJoinPlanForPrimary(e,t,n,i,s){return this.buildJoinPlan(e,t,n,i,s)}buildPreAggregationCTEs(e,t,n,i,s){return this.planPreAggregationCTEs(e,t,n,i,s)}buildWarnings(e,t){return this.generateWarnings(e,t)}buildJoinPlan(e,t,n,i,s){const o=this.getResolver(e),a=[],u=new Set([t.name]),c=new Set;if(s.measures)for(const f of s.measures){const[h]=f.split(".");c.add(h)}const l=this.collectPathHintCubes(s),m=new Set;for(const f of c){if(f===t.name)continue;this.findHasManyJoinDef(t,f)&&m.add(f)}const p=n.filter(f=>f!==t.name);for(const f of p){if(u.has(f))continue;const h=new Set([...u].filter(y=>!m.has(y))),g=o.findPathPreferring(t.name,f,l,h);if(!g||g.length===0)throw new Error(`No join path found from '${t.name}' to '${f}'`);for(const{fromCube:y,toCube:b,joinDef:w}of g){if(u.has(b))continue;const $=e.get(b);if(!$)throw new Error(`Cube '${b}' not found`);if(w.relationship==="belongsToMany"&&w.through){const S=Yt(w,i.securityContext);a.push({cube:$,alias:`${b.toLowerCase()}_cube`,joinType:S.junctionJoins[1].joinType,joinCondition:S.junctionJoins[1].condition,relationship:"belongsToMany",junctionTable:{table:w.through.table,alias:`junction_${b.toLowerCase()}`,joinType:S.junctionJoins[0].joinType,joinCondition:S.junctionJoins[0].condition,securitySql:w.through.securitySql,sourceCubeName:y}})}else{const S=o.buildJoinCondition(w,null,null),C=Re(w.relationship,w.sqlJoinType);a.push({cube:$,alias:`${b.toLowerCase()}_cube`,joinType:C,joinCondition:S,relationship:w.relationship})}u.add(b)}}return a}planPreAggregationCTEs(e,t,n,i,s){const o=[];if(!i.measures||i.measures.length===0)return o;const a=this.computeCTEReasons(t,n,i);if(a.size===0)return o;for(const u of n){const c=a.get(u.cube.name);if(!c)continue;const l=u.cube,m=u.alias,p=i.measures.filter(D=>D.startsWith(l.name+".")),f=this.extractMeasuresFromFilters(i,l),h=[...new Set([...p,...f])];if(h.length===0)continue;const g=this.analyzeJoinPathToPrimary(e,t,l.name,s,i);let y,b;if(g?.hasIntermediateHasMany&&g.intermediateJoins.length>0)y=g.correctJoinKeys,b=g.intermediateJoins;else{const N=(g?.path&&g.path.length>0?(()=>{const M=g.path[g.path.length-1],v=e.get(M.fromCube);return v?{sourceCube:v,joinDef:M.joinDef}:null})():null)??this.findJoinInfoForCube(e,t,l.name);if(!N)continue;N.joinDef.relationship==="belongsToMany"&&N.joinDef.through?N.sourceCube?.name===t.name&&!("reversed"in N&&N.reversed)?y=N.joinDef.through.targetKey.map(v=>({sourceColumn:v.source.name,targetColumn:v.target.name,sourceColumnObj:v.source,targetColumnObj:v.target})):y=N.joinDef.through.sourceKey.map(v=>({sourceColumn:v.target.name,targetColumn:v.source.name,sourceColumnObj:v.target,targetColumnObj:v.source})):y="reversed"in N&&N.reversed?N.joinDef.on.map(v=>({sourceColumn:v.target.name,targetColumn:v.source.name,sourceColumnObj:v.target,targetColumnObj:v.source})):N.joinDef.on.map(v=>({sourceColumn:v.source.name,targetColumn:v.target.name,sourceColumnObj:v.source,targetColumnObj:v.target})),b=void 0}const w=this.findPropagatingFilters(i,l,e),$=new Map([[l.name,l]]),{aggregateMeasures:S,requiredBaseMeasures:C}=L.categorizeForPostAggregation(h,$),T=[...new Set([...S,...Array.from(C).filter(D=>D.startsWith(l.name+"."))])];if(T.length>0){const D=this.expandCalculatedMeasureDependencies(l,T),N=this.findDownstreamJoinKeys(l,i,e);o.push({cube:l,alias:m,cteAlias:`${l.name.toLowerCase()}_agg`,joinKeys:y,measures:D,propagatingFilters:w.length>0?w:void 0,downstreamJoinKeys:N.length>0?N:void 0,intermediateJoins:b&&b.length>0?b:void 0,cteType:"aggregate",cteReason:c})}}return o}findJoinInfoToCube(e,t){for(const[,n]of e)if(n.name!==t&&n.joins){for(const[,i]of Object.entries(n.joins))if(z(i.targetCube).name===t)return{sourceCube:n,joinDef:i}}return null}analyzeJoinPathToPrimary(e,t,n,i,s){const o=this.getResolver(e),a=this.collectPathHintCubes(s),u=a.size>0?o.findPathPreferring(t.name,n,a,new Set):o.findPath(t.name,n);if(!u||u.length===0)return null;const c=u.map(g=>({fromCube:g.fromCube,toCube:g.toCube,joinDef:g.joinDef}));if(!c.slice(0,-1).some(g=>g.joinDef.relationship==="hasMany"))return{path:c,hasIntermediateHasMany:!1,intermediateJoins:[],correctJoinKeys:[]};const p=[];for(let g=0;g<c.length-1;g++){const y=c[g],b=c[g+1],w=e.get(y.toCube);if(!w)continue;const S=w.sql(i).where,C=b.joinDef.on[0]?.source,T=y.joinDef.on[0]?.target;p.push({cube:w,joinDef:b.joinDef,securityFilter:S,primaryJoinColumn:T,cteJoinColumn:C})}const h=c[0].joinDef.on.map(g=>({sourceColumn:g.source.name,targetColumn:g.target.name,sourceColumnObj:g.source,targetColumnObj:g.target}));return{path:c,hasIntermediateHasMany:!0,intermediateJoins:p,correctJoinKeys:h}}computeCTEReasons(e,t,n){const i=new Map,s=new Set,o=new Set,a=new Set;if(n.measures)for(const u of n.measures){const[c]=u.split(".");a.add(c)}for(const u of t)u.relationship==="hasMany"||u.relationship==="belongsToMany"?s.add(u.cube.name):u.relationship==="belongsTo"&&a.has(u.cube.name)&&o.add(u.cube.name);if(s.size===0&&o.size===0)return i;for(const u of t)a.has(u.cube.name)&&(s.has(u.cube.name)?i.set(u.cube.name,"hasMany"):(o.has(u.cube.name)||s.size>0)&&i.set(u.cube.name,"fanOutPrevention"));return i}findJoinInfoForCube(e,t,n){if(t.joins){for(const[,s]of Object.entries(t.joins))if(z(s.targetCube).name===n)return{sourceCube:t,joinDef:s}}const i=e.get(n);if(i?.joins){for(const[,s]of Object.entries(i.joins))if(z(s.targetCube).name===t.name)return{sourceCube:i,joinDef:s,reversed:!0}}for(const[,s]of e)if(!(s.name===t.name||s.name===n)&&s.joins){for(const[,o]of Object.entries(s.joins))if(z(o.targetCube).name===n)return{sourceCube:s,joinDef:o}}return null}findDownstreamJoinKeys(e,t,n){const i=[],s=new Set;if(t.dimensions)for(const o of t.dimensions){const[a]=o.split(".");a!==e.name&&s.add(a)}if(t.timeDimensions)for(const o of t.timeDimensions){const[a]=o.dimension.split(".");a!==e.name&&s.add(a)}if(t.filters){for(const o of t.filters)this.extractCubeNamesFromFilter(o,s);s.delete(e.name)}if(e.joins)for(const[,o]of Object.entries(e.joins)){const u=z(o.targetCube).name;if(s.has(u)){let c;o.relationship==="belongsToMany"&&o.through?c=o.through.sourceKey.map(l=>({sourceColumn:l.source.name,targetColumn:l.target.name,sourceColumnObj:l.source,targetColumnObj:l.target})):c=o.on.map(l=>({sourceColumn:l.source.name,targetColumn:l.target.name,sourceColumnObj:l.source,targetColumnObj:l.target})),i.push({targetCubeName:u,joinKeys:c})}}return i}expandCalculatedMeasureDependencies(e,t){const n=new Set,i=[...t];for(;i.length>0;){const s=i.pop();if(n.has(s))continue;n.add(s);const[,o]=s.split(".");if(!e.measures||!e.measures[o])continue;const a=e.measures[o];if(a.type==="calculated"&&a.calculatedSql){const u=this.extractDependenciesFromTemplate(a.calculatedSql,e.name);for(const c of u)n.has(c)||i.push(c)}}return Array.from(n)}extractDependenciesFromTemplate(e,t){const n=/\{([^}]+)\}/g,i=e.matchAll(n),s=[];for(const o of i){const a=o[1].trim();a.includes(".")?s.push(a):s.push(`${t}.${a}`)}return s}findHasManyJoinDef(e,t){if(!e.joins)return null;for(const[,n]of Object.entries(e.joins))if(z(n.targetCube).name===t&&n.relationship==="hasMany")return n;return null}findPropagatingFilters(e,t,n){const i=[];if(!e.filters)return i;const s=new Set;if(this.extractFilterCubeNamesToSet(e.filters,s),e.timeDimensions){for(const o of e.timeDimensions)if(o.dateRange){const[a]=o.dimension.split(".");a&&s.add(a)}}for(const o of s){if(o===t.name)continue;const a=n.get(o);if(a?.joins){for(const[,u]of Object.entries(a.joins))if(z(u.targetCube).name===t.name&&u.relationship==="hasMany"){const l=this.extractFiltersForCube(e.filters,o),m=this.extractTimeDimensionFiltersForCube(e,o),p=[...l,...m];p.length>0&&u.on.length>0&&i.push({sourceCube:a,filters:p,joinConditions:u.on.map(f=>({source:f.source,target:f.target}))})}}}return i}extractFilterCubeNamesToSet(e,t){for(const n of e){if("and"in n||"or"in n){const i=n.and||n.or||[];this.extractFilterCubeNamesToSet(i,t);continue}if("member"in n){const[i]=n.member.split(".");i&&t.add(i)}}}extractFiltersForCube(e,t){const n=[];for(const i of e){if("and"in i){const s=this.extractFiltersForCube(i.and||[],t);s.length>0&&n.push({and:s});continue}if("or"in i){const s=i.or||[];if(this.allFiltersFromCube(s,t)){const a=this.extractFiltersForCube(s,t);a.length>0&&n.push({or:a})}continue}if("member"in i){const[s]=i.member.split(".");s===t&&n.push(i)}}return n}allFiltersFromCube(e,t){for(const n of e){if("and"in n){if(!this.allFiltersFromCube(n.and||[],t))return!1;continue}if("or"in n){if(!this.allFiltersFromCube(n.or||[],t))return!1;continue}if("member"in n){const[i]=n.member.split(".");if(i!==t)return!1}}return!0}extractTimeDimensionFiltersForCube(e,t){const n=[];if(!e.timeDimensions)return n;for(const i of e.timeDimensions){const[s]=i.dimension.split(".");s===t&&i.dateRange&&n.push({member:i.dimension,operator:"inDateRange",values:Array.isArray(i.dateRange)?i.dateRange:[i.dateRange]})}return n}analyzePrimaryCubeSelection(e,t,n){if(e.length===1)return{selectedCube:e[0],reason:"single_cube",explanation:"Only one cube is used in this query"};const i=[],s=(t.dimensions||[]).map(l=>l.split(".")[0]),o=new Map;for(const l of s)o.set(l,(o.get(l)||0)+1);const a=this.getResolver(n);for(const l of e){const m=n.get(l),p=o.get(l)||0,f=m?.joins?Object.keys(m.joins).length:0,h=a.canReachAll(l,e);i.push({cubeName:l,dimensionCount:p,joinCount:f,canReachAll:h})}if(t.dimensions&&t.dimensions.length>0){const l=Math.max(...i.map(m=>m.dimensionCount));if(l>0){const m=i.filter(p=>p.dimensionCount===l).sort((p,f)=>p.cubeName.localeCompare(f.cubeName));for(const p of m)if(p.canReachAll)return{selectedCube:p.cubeName,reason:"most_dimensions",explanation:`Selected because it has ${p.dimensionCount} dimension${p.dimensionCount!==1?"s":""} in the query (defines the analytical grain)`,candidates:i}}}const u=i.filter(l=>l.canReachAll);if(u.length>0){const l=Math.max(...u.map(p=>p.joinCount)),m=u.filter(p=>p.joinCount===l).sort((p,f)=>p.cubeName.localeCompare(f.cubeName))[0];return{selectedCube:m.cubeName,reason:"most_connected",explanation:`Selected because it has ${m.joinCount} join relationship${m.joinCount!==1?"s":""} and can reach all other cubes`,candidates:i}}return{selectedCube:[...e].sort()[0],reason:"alphabetical_fallback",explanation:"Selected alphabetically as fallback (no cube could reach all others)",candidates:i}}analyzeJoinPath(e,t,n,i){const s=this.getResolver(e),o=i?this.collectPathHintCubes(i):new Set,a=o.size>0?s.findPathPreferringDetailed(t,n,o):null,u=a?.selectedPath??s.findPath(t,n),c=[t];if(u)for(const m of u)c.push(m.toCube);if(!u||u.length===0)return{targetCube:n,pathFound:!1,error:`No join path found from '${t}' to '${n}'. Ensure the target cube has a relationship defined (belongsTo, hasOne, hasMany, or belongsToMany).`,visitedCubes:c,selection:this.buildJoinPathSelectionAnalysis(a)};const l=this.convertInternalPathToJoinPathSteps(u);return{targetCube:n,pathFound:!0,path:l,pathLength:l.length,visitedCubes:c,selection:this.buildJoinPathSelectionAnalysis(a)}}convertInternalPathToJoinPathSteps(e){return e.map(t=>{const n=Re(t.joinDef.relationship,t.joinDef.sqlJoinType),i=t.joinDef.on.map(o=>({sourceColumn:o.source.name,targetColumn:o.target.name})),s={fromCube:t.fromCube,toCube:t.toCube,relationship:t.joinDef.relationship,joinType:n,joinColumns:i};if(t.joinDef.relationship==="belongsToMany"&&t.joinDef.through){const o=t.joinDef.through;s.junctionTable={tableName:o.table[Symbol.for("drizzle:Name")]||"junction_table",sourceColumns:o.sourceKey.map(a=>a.target.name),targetColumns:o.targetKey.map(a=>a.source.name)}}return s})}buildJoinPathSelectionAnalysis(e){if(!e)return{strategy:"shortest"};const t=e.candidates.map((n,i)=>this.mapPreferredCandidate(n,i+1));return{strategy:e.strategy,preferredCubes:e.preferredCubes,selectedRank:e.selectedIndex>=0?e.selectedIndex+1:void 0,selectedScore:e.selectedIndex>=0?e.candidates[e.selectedIndex]?.score:void 0,candidates:t}}mapPreferredCandidate(e,t){return{rank:t,score:e.score,usesPreferredJoin:e.usesPreferredJoin,preferredCubesInPath:e.preferredCubesInPath,usesProcessed:e.usesProcessed,scoreBreakdown:e.scoreBreakdown,path:this.convertInternalPathToJoinPathSteps(e.path)}}generateWarnings(e,t){const n=[],i=this.checkFanOutNoDimensions(e,t);return i&&n.push(i),n}checkFanOutNoDimensions(e,t){if(!t||t.length===0||!e.measures||e.measures.length===0)return null;const n=new Set;for(const o of e.measures){const[a]=o.split(".");n.add(a)}if(n.size<2)return null;const i=e.dimensions&&e.dimensions.length>0,s=e.timeDimensions?.some(o=>o.granularity);return i||s?null:{code:"FAN_OUT_NO_DIMENSIONS",message:"Query combines measures from multiple cubes with hasMany relationships but has no dimensions. Results are aggregated at the join key level, which may produce unexpected totals.",severity:"warning",cubes:[...n].sort(),measures:e.measures,suggestion:"Add a dimension to see per-group breakdowns, or add a time dimension with granularity."}}}class cn{constructor(e){this.queryBuilder=e}buildPreAggregationCTE(e,t,n,i,s){const o=e.cube,a=o.sql(n),u=e.intermediateJoins&&e.intermediateJoins.length>0,c={};if(u&&e.intermediateJoins){const T=e.intermediateJoins[0].primaryJoinColumn;if(T){const D=T.name;c[D]=T}}else for(const C of e.joinKeys)if(C.targetColumnObj){c[C.targetColumn]=C.targetColumnObj;for(const[T,D]of Object.entries(o.dimensions||{}))D.sql===C.targetColumnObj&&T!==C.targetColumn&&(c[T]=r`${C.targetColumnObj}`.as(T))}if(e.downstreamJoinKeys)for(const C of e.downstreamJoinKeys)for(const T of C.joinKeys)T.sourceColumnObj&&(c[T.sourceColumn]=T.sourceColumnObj);const l=o.name,m=new Map([[l,o]]),p=this.queryBuilder.buildResolvedMeasures(e.measures,m,n);for(const C of e.measures){const[,T]=C.split("."),D=p.get(C);if(D){const N=D();c[T]=r`${N}`.as(T)}}if(t.dimensions)for(const C of t.dimensions){const[T,D]=C.split(".");if(T===l&&o.dimensions&&o.dimensions[D]){const N=o.dimensions[D],M=this.queryBuilder.buildMeasureExpression({sql:N.sql,type:"number"},n);c[D]=r`${M}`.as(D)}}if(t.timeDimensions)for(const C of t.timeDimensions){const[T,D]=C.dimension.split(".");if(T===l&&o.dimensions&&o.dimensions[D]){const N=o.dimensions[D],M=this.queryBuilder.buildTimeDimensionExpression(N.sql,C.granularity,n);c[D]=r`${M}`.as(D)}}if(Object.keys(c).length===0)return null;let f=n.db.select(c).from(a.from);if(u&&e.intermediateJoins){const C=[...e.intermediateJoins].reverse();for(const T of C){const D=T.cube.sql(n),M=[k(T.cteJoinColumn,T.joinDef.on[0]?.target)];T.securityFilter&&M.push(T.securityFilter),f=f.leftJoin(D.from,A(...M))}}const h=i?{...i,preAggregationCTEs:i.preAggregationCTEs?.filter(C=>C.cube.name!==o.name)}:void 0,g=this.queryBuilder.buildWhereConditions(o,t,n,h,s),y=[];if(t.timeDimensions)for(const C of t.timeDimensions){const[T,D]=C.dimension.split(".");if(T===l&&o.dimensions&&o.dimensions[D]&&C.dateRange){const N=o.dimensions[D],M=this.queryBuilder.buildMeasureExpression({sql:N.sql,type:"number"},n),v=this.queryBuilder.buildDateRangeCondition(M,C.dateRange);v&&y.push(v)}}if(t.filters){for(const C of t.filters)if(!("and"in C)&&!("or"in C)&&"member"in C&&"operator"in C){const T=C,[D,N]=T.member.split(".");if(D===l&&o.dimensions&&o.dimensions[N]){const M=o.dimensions[N];if(T.operator==="inDateRange"){const v=this.queryBuilder.buildMeasureExpression({sql:M.sql,type:"number"},n),U=this.queryBuilder.buildDateRangeCondition(v,T.values);U&&y.push(U)}}}}if(e.propagatingFilters&&e.propagatingFilters.length>0)for(const C of e.propagatingFilters){const T=this.buildPropagatingFilterSubquery(C,n);T&&y.push(T)}const b=[];if(a.where&&b.push(a.where),b.push(...g,...y),b.length>0){const C=b.length===1?b[0]:A(...b);f=f.where(C)}const w=[],$=new Set,S=C=>{const T=C?.name||(typeof C=="string"?C:null);T&&!$.has(T)?($.add(T),w.push(C)):T||w.push(C)};if(u&&e.intermediateJoins){const C=e.intermediateJoins[0];C.primaryJoinColumn&&S(C.primaryJoinColumn)}else for(const C of e.joinKeys)C.targetColumnObj&&S(C.targetColumnObj);if(e.downstreamJoinKeys)for(const C of e.downstreamJoinKeys)for(const T of C.joinKeys)T.sourceColumnObj&&S(T.sourceColumnObj);if(t.dimensions)for(const C of t.dimensions){const[T,D]=C.split(".");if(T===l&&o.dimensions&&o.dimensions[D]){const N=o.dimensions[D],M=R(N.sql,n);w.push(M)}}if(t.timeDimensions)for(const C of t.timeDimensions){const[T,D]=C.dimension.split(".");if(T===l&&o.dimensions&&o.dimensions[D]){const N=o.dimensions[D],M=this.queryBuilder.buildTimeDimensionExpression(N.sql,C.granularity,n);w.push(M)}}return w.length>0&&(f=f.groupBy(...w)),n.db.$with(e.cteAlias).as(f)}buildCTEJoinCondition(e,t,n){const i=n.preAggregationCTEs?.find(o=>o.cube.name===e.cube.name);if(!i)throw new Error(`CTE info not found for cube ${e.cube.name}`);const s=[];if(i.intermediateJoins&&i.intermediateJoins.length>0){const o=i.intermediateJoins[0],a=this.resolveCTEJoinSourceColumn(i.joinKeys[0],i,n),u=r`${r.identifier(t)}.${r.identifier(o.primaryJoinColumn.name)}`;s.push(k(a,u))}else for(const o of i.joinKeys){const a=this.resolveCTEJoinSourceColumn(o,i,n),u=r`${r.identifier(t)}.${r.identifier(o.targetColumn)}`;s.push(k(a,u))}return s.length===1?s[0]:A(...s)}resolveCTEJoinSourceColumn(e,t,n){if(!e)throw new Error(`Missing join key while building CTE join condition for '${t.cube.name}'`);const i=e.sourceColumnObj||r.identifier(e.sourceColumn);if(!e.sourceColumnObj||!n.preAggregationCTEs)return i;for(const s of n.preAggregationCTEs)if(s.cube.name!==t.cube.name){for(const[o,a]of Object.entries(s.cube.dimensions||{}))if(typeof a.sql!="function"&&a.sql===e.sourceColumnObj)return r`${r.identifier(s.cteAlias)}.${r.identifier(o)}`}return i}buildPropagatingFilterSubquery(e,t){const n=e.sourceCube,i=n.sql(t),s=[];if(i.where&&s.push(i.where),e.preBuiltFilterSQL)s.push(e.preBuiltFilterSQL);else{const u={filters:e.filters},c=new Map([[n.name,n]]),l=this.queryBuilder.buildWhereConditions(c,u,t);s.push(...l)}if(s.length===0)return null;const o=s.length===1?s[0]:A(...s),a=e.joinConditions;if(a.length===1){const{source:u,target:c}=a[0],l=t.db.select({pk:u}).from(i.from).where(o);return r`${c} IN ${l}`}else{const u=a.map(m=>k(m.source,m.target)),c=A(...u,o),l=t.db.select({one:r`1`}).from(i.from).where(c);return r`EXISTS ${l}`}}}function dn(d,e,t){const n=[];let i=He(new Date(d),t);const s=He(new Date(e),t),o=1e4;for(;i<=s&&n.length<o;)n.push(new Date(i)),i=mn(i,t);return n}function He(d,e){const t=new Date(d);switch(e){case"second":t.setUTCMilliseconds(0);break;case"minute":t.setUTCSeconds(0,0);break;case"hour":t.setUTCMinutes(0,0,0);break;case"day":t.setUTCHours(0,0,0,0);break;case"week":{const n=t.getUTCDay(),i=n===0?6:n-1;t.setUTCDate(t.getUTCDate()-i),t.setUTCHours(0,0,0,0);break}case"month":t.setUTCDate(1),t.setUTCHours(0,0,0,0);break;case"quarter":{const n=Math.floor(t.getUTCMonth()/3)*3;t.setUTCMonth(n,1),t.setUTCHours(0,0,0,0);break}case"year":t.setUTCMonth(0,1),t.setUTCHours(0,0,0,0);break}return t}function mn(d,e){const t=new Date(d);switch(e){case"second":t.setUTCSeconds(t.getUTCSeconds()+1);break;case"minute":t.setUTCMinutes(t.getUTCMinutes()+1);break;case"hour":t.setUTCHours(t.getUTCHours()+1);break;case"day":t.setUTCDate(t.getUTCDate()+1);break;case"week":t.setUTCDate(t.getUTCDate()+7);break;case"month":t.setUTCMonth(t.getUTCMonth()+1);break;case"quarter":t.setUTCMonth(t.getUTCMonth()+3);break;case"year":t.setUTCFullYear(t.getUTCFullYear()+1);break}return t}function fn(d){if(d instanceof Date)return d.toISOString();if(typeof d=="string"){const e=new Date(d);if(!isNaN(e.getTime()))return e.toISOString()}return String(d)}function pn(d,e){return e.length===0?"__all__":e.map(t=>String(d[t]??"")).join("|||")}function hn(d,e){const{timeDimensionKey:t,granularity:n,dateRange:i,fillValue:s,measures:o,dimensions:a}=e,u=dn(i[0],i[1],n);if(u.length===0)return d;const c=new Map;for(const m of d){const p=pn(m,a),f=fn(m[t]);c.has(p)||c.set(p,new Map),c.get(p).set(f,m)}c.size===0&&a.length===0&&c.set("__all__",new Map);const l=[];for(const[m,p]of c){const f=p.size>0?p.values().next().value:null;for(const h of u){const g=h.toISOString(),y=p.get(g);if(y)l.push(y);else{const b={[t]:g};if(f)for(const w of a)b[w]=f[w];for(const w of o)b[w]=s;l.push(b)}}}return l}function gn(d){if(!d)return null;if(Array.isArray(d)){if(d.length<2)return null;const t=new Date(d[0]),n=new Date(d[1]);return isNaN(t.getTime())||isNaN(n.getTime())?null:[t,n]}const e=new Date(d);return isNaN(e.getTime())?null:[e,e]}function Ye(d,e,t){if(!e.timeDimensions||e.timeDimensions.length===0)return d;const n=e.timeDimensions.filter(u=>{const c=u.fillMissingDates!==!1,l=u.granularity&&u.dateRange;return c&&l});if(n.length===0)return d;const i=e.fillMissingDatesValue===void 0?0:e.fillMissingDatesValue,s=new Set(e.timeDimensions.map(u=>u.dimension)),o=(e.dimensions||[]).filter(u=>!s.has(u));let a=d;for(const u of n){const c=gn(u.dateRange);if(!c)continue;const l={timeDimensionKey:u.dimension,granularity:u.granularity,dateRange:c,fillValue:i,measures:t,dimensions:o};a=hn(a,l)}return a}class bn{dateTimeBuilder;constructor(e){this.dateTimeBuilder=new re(e)}hasComparison(e){return e.timeDimensions?.some(t=>t.compareDateRange&&t.compareDateRange.length>=2)??!1}getComparisonTimeDimension(e){return e.timeDimensions?.find(t=>t.compareDateRange&&t.compareDateRange.length>=2)}normalizePeriods(e){const t=[];for(let n=0;n<e.length;n++){const i=e[n];let s,o,a;if(typeof i=="string"){const u=this.dateTimeBuilder.parseRelativeDateRange(i);if(u)s=u.start,o=u.end,a=i;else{const c=new Date(i);if(!isNaN(c.getTime()))s=new Date(c),s.setUTCHours(0,0,0,0),o=new Date(c),o.setUTCHours(23,59,59,999),a=i;else continue}}else{if(s=new Date(i[0]),o=new Date(i[1]),isNaN(s.getTime())||isNaN(o.getTime()))continue;/^\d{4}-\d{2}-\d{2}$/.test(i[1])&&o.setUTCHours(23,59,59,999),a=`${i[0]} - ${i[1]}`}t.push({start:s,end:o,label:a,index:n})}return t}createPeriodQuery(e,t){return{...e,timeDimensions:e.timeDimensions?.map(n=>n.compareDateRange?{...n,dateRange:[t.start.toISOString(),t.end.toISOString()],compareDateRange:void 0}:n)}}calculatePeriodDayIndex(e,t,n){const i=typeof e=="string"?new Date(e):e,s=t.getTime(),o=i.getTime();switch(n){case"second":return Math.floor((o-s)/1e3);case"minute":return Math.floor((o-s)/(1e3*60));case"hour":return Math.floor((o-s)/(1e3*60*60));case"day":return Math.floor((o-s)/(1e3*60*60*24));case"week":return Math.floor((o-s)/(1e3*60*60*24*7));case"month":{const a=t.getUTCFullYear(),u=t.getUTCMonth(),c=i.getUTCFullYear(),l=i.getUTCMonth();return(c-a)*12+(l-u)}case"quarter":{const a=t.getUTCFullYear(),u=Math.floor(t.getUTCMonth()/3),c=i.getUTCFullYear(),l=Math.floor(i.getUTCMonth()/3);return(c-a)*4+(l-u)}case"year":return i.getUTCFullYear()-t.getUTCFullYear();default:return Math.floor((o-s)/(1e3*60*60*24))}}addPeriodMetadata(e,t,n,i){return e.map(s=>{const o=s[n];let a=0;if(o){const u=typeof o=="string"?new Date(o):o instanceof Date?o:null;u&&!isNaN(u.getTime())&&(a=this.calculatePeriodDayIndex(u,t.start,i))}return{...s,__period:t.label,__periodIndex:t.index,__periodDayIndex:a}})}mergeComparisonResults(e,t,n){const i=[];let s={measures:{},dimensions:{},segments:{},timeDimensions:{}};const o=e.map(u=>u.period);for(const{result:u,period:c}of e){const l=this.addPeriodMetadata(u.data,c,t.dimension,n);i.push(...l),s={measures:{...s.measures,...u.annotation.measures},dimensions:{...s.dimensions,...u.annotation.dimensions},segments:{...s.segments,...u.annotation.segments},timeDimensions:{...s.timeDimensions,...u.annotation.timeDimensions}}}const a={ranges:o.map(u=>[u.start.toISOString().split("T")[0],u.end.toISOString().split("T")[0]]),labels:o.map(u=>u.label),timeDimension:t.dimension,granularity:n};return{data:i,annotation:{...s,periods:a}}}sortComparisonResults(e,t){return[...e].sort((n,i)=>{const s=n.__periodIndex-i.__periodIndex;if(s!==0)return s;const o=n[t],a=i[t];return typeof o=="string"&&typeof a=="string"?new Date(o).getTime()-new Date(a).getTime():0})}}class yn{constructor(e){this.databaseAdapter=e,this.dateTimeBuilder=new re(e),this.filterBuilder=new be(e,this.dateTimeBuilder)}filterBuilder;dateTimeBuilder;hasFunnel(e){return e.funnel!==void 0&&e.funnel.steps.length>=2}validateConfig(e,t){const n=[];if(e.steps.length<2&&n.push("Funnel must have at least 2 steps"),typeof e.bindingKey=="string"){const[i,s]=e.bindingKey.split(".");if(!i||!s)n.push(`Invalid binding key format: ${e.bindingKey}. Expected 'CubeName.dimensionName'`);else{const o=t.get(i);o?o.dimensions?.[s]||n.push(`Binding key dimension not found: ${s} in cube ${i}`):n.push(`Binding key cube not found: ${i}`)}}else if(Array.isArray(e.bindingKey))for(const i of e.bindingKey){const s=t.get(i.cube);if(!s)n.push(`Binding key mapping cube not found: ${i.cube}`);else{const[,o]=i.dimension.split(".");s.dimensions?.[o]||n.push(`Binding key dimension not found: ${o} in cube ${i.cube}`)}}if(typeof e.timeDimension=="string"){const[i,s]=e.timeDimension.split(".");if(!i||!s)n.push(`Invalid time dimension format: ${e.timeDimension}. Expected 'CubeName.dimensionName'`);else{const o=t.get(i);o?o.dimensions?.[s]||n.push(`Time dimension not found: ${s} in cube ${i}`):n.push(`Time dimension cube not found: ${i}`)}}for(let i=0;i<e.steps.length;i++){const s=e.steps[i];if(s.name||n.push(`Step ${i} must have a name`),"cube"in s&&s.cube&&(t.get(s.cube)||n.push(`Step ${i} cube not found: ${s.cube}`)),s.filter){let o;"cube"in s&&s.cube?o=s.cube:typeof e.bindingKey=="string"&&([o]=e.bindingKey.split("."));const a=o?new ue(t):null,u=Array.isArray(s.filter)?s.filter:[s.filter];for(const c of u)if("member"in c){const[l,m]=c.member.split("."),p=t.get(l);if(!p)n.push(`Step ${i} filter cube not found: ${l}`);else if(p.dimensions?.[m]||(p.measures?.[m]?n.push(`Step ${i} filter '${l}.${m}' is a measure. Funnel step filters only support dimensions, not measures.`):n.push(`Step ${i} filter member not found: ${m} in cube ${l}`)),o&&l!==o&&a){const f=a.findPath(o,l);(!f||f.length===0)&&n.push(`Step ${i} filter '${l}.${m}' requires a join from '${o}' but no join path was found. Define a join relationship between these cubes.`)}}}s.timeToConvert&&i>0&&(/^P(?:\d+Y)?(?:\d+M)?(?:\d+D)?(?:T(?:\d+H)?(?:\d+M)?(?:\d+(?:\.\d+)?S)?)?$/.test(s.timeToConvert)||n.push(`Step ${i} timeToConvert must be ISO 8601 duration format: ${s.timeToConvert}`))}return{isValid:n.length===0,errors:n}}buildFunnelQuery(e,t,n){const i=this.resolveSteps(e,t,n),s=[];for(let c=0;c<i.length;c++){const l=c>0?s[c-1]:void 0;s.push(this.buildStepCTE(i[c],n,l))}const o=this.buildFunnelResultsCTE(s,i,e,n),a=this.buildAggregationCTE(o,s,i,e,n),u=[...s,o,a];return n.db.with(...u).select().from(a)}transformResult(e,t){if(!e||e.length===0)return[];const n=e[0],i=[],s=Number(n.step_0_count)||0;for(let o=0;o<t.steps.length;o++){const a=t.steps[o],u=Number(n[`step_${o}_count`])||0,c=o>0&&Number(n[`step_${o-1}_count`])||0,l={step:a.name,stepIndex:o,count:u,conversionRate:o===0?null:c>0?u/c:0,cumulativeConversionRate:s>0?u/s:0};t.includeTimeMetrics&&o>0&&(l.avgSecondsToConvert=n[`step_${o}_avg_seconds`]!==null?Number(n[`step_${o}_avg_seconds`]):null,l.minSecondsToConvert=n[`step_${o}_min_seconds`]!==null?Number(n[`step_${o}_min_seconds`]):null,l.maxSecondsToConvert=n[`step_${o}_max_seconds`]!==null?Number(n[`step_${o}_max_seconds`]):null,n[`step_${o}_median_seconds`]!==void 0&&(l.medianSecondsToConvert=n[`step_${o}_median_seconds`]!==null?Number(n[`step_${o}_median_seconds`]):null),n[`step_${o}_p90_seconds`]!==void 0&&(l.p90SecondsToConvert=n[`step_${o}_p90_seconds`]!==null?Number(n[`step_${o}_p90_seconds`]):null)),i.push(l)}return i}extractFilterCubeNames(e){const t=new Set;if(!e.filter)return t;const n=Array.isArray(e.filter)?e.filter:[e.filter],i=s=>{if("and"in s&&s.and)for(const o of s.and)i(o);else if("or"in s&&s.or)for(const o of s.or)i(o);else if("type"in s&&"filters"in s){const o=s;for(const a of o.filters||[])i(a)}else if("member"in s){const[o]=s.member.split(".");t.add(o)}};for(const s of n)i(s);return t}resolveSteps(e,t,n){const i=new ue(t);return e.steps.map((s,o)=>{const a=this.resolveCubeForStep(s,e,t),u=this.resolveBindingKey(e,a,n),c=this.resolveTimeDimension(e,a,n),l=this.buildStepFilters(s,a,t,n),m=this.extractFilterCubeNames(s),p=[];for(const f of m)if(f!==a.name){const h=t.get(f);if(h){const g=i.findPath(a.name,f);g&&g.length>0&&p.push({cube:h,joinPath:g})}}return{name:s.name,index:o,cube:a,bindingKeyExpr:u,timeExpr:c,filterConditions:l,timeToConvert:s.timeToConvert,joinedCubes:p}})}resolveCubeForStep(e,t,n){if("cube"in e&&e.cube){const i=n.get(e.cube);if(!i)throw new Error(`Cube not found for step: ${e.cube}`);return i}if(typeof t.bindingKey=="string"){const[i]=t.bindingKey.split("."),s=n.get(i);if(!s)throw new Error(`Cube not found for binding key: ${t.bindingKey}`);return s}throw new Error("Cannot resolve cube for step - multi-cube funnel requires cube specification in each step")}resolveBindingKey(e,t,n){if(typeof e.bindingKey=="string"){const[,a]=e.bindingKey.split("."),u=t.dimensions?.[a];if(!u)throw new Error(`Binding key dimension not found: ${e.bindingKey}`);return R(u.sql,n)}const i=e.bindingKey.find(a=>a.cube===t.name);if(!i)throw new Error(`No binding key mapping found for cube: ${t.name}`);const[,s]=i.dimension.split("."),o=t.dimensions?.[s];if(!o)throw new Error(`Binding key dimension not found: ${i.dimension}`);return R(o.sql,n)}resolveTimeDimension(e,t,n){if(typeof e.timeDimension=="string"){const[,a]=e.timeDimension.split("."),u=t.dimensions?.[a];if(!u)throw new Error(`Time dimension not found: ${e.timeDimension}`);return R(u.sql,n)}const i=e.timeDimension.find(a=>a.cube===t.name);if(!i)throw new Error(`No time dimension mapping found for cube: ${t.name}`);const[,s]=i.dimension.split("."),o=t.dimensions?.[s];if(!o)throw new Error(`Time dimension not found: ${i.dimension}`);return R(o.sql,n)}buildStepFilters(e,t,n,i){if(!e.filter)return[];const s=Array.isArray(e.filter)?e.filter:[e.filter],o=[];for(const a of s){const u=this.buildFilterCondition(a,t,n,i);u&&o.push(u)}return o}buildFilterCondition(e,t,n,i){const s="and"in e||"or"in e,o="type"in e&&"filters"in e&&(e.type==="and"||e.type==="or");if(s||o){const g=[];let y;if(o){const b=e;y=b.type==="and";for(const w of b.filters||[]){const $=this.buildFilterCondition(w,t,n,i);$&&g.push($)}}else{const b=e;y="and"in b&&!!b.and;const w=b.and||b.or||[];for(const $ of w){const S=this.buildFilterCondition($,t,n,i);S&&g.push(S)}}return g.length===0?null:g.length===1?g[0]:y?A(...g):r`(${r.join(g,r` OR `)})`}const a=e,[u,c]=a.member.split("."),l=a.dateRange!==void 0;if(a.operator!=="set"&&a.operator!=="notSet"&&!l&&(!a.values||a.values.length===0||a.values[0]===void 0||a.values[0]===""))return null;const p=n.get(u);if(!p)return null;if(u!==t.name){const y=new ue(n).findPath(t.name,u);if(!y||y.length===0)return console.warn(`Funnel filter: Cannot filter by '${u}.${c}' in step using '${t.name}'. No join path found. Filter will be skipped.`),null}const f=p.dimensions?.[c];if(!f)return null;const h=R(f.sql,i);return this.filterBuilder.buildFilterCondition(h,a.operator,a.values||[],f,a.dateRange)}buildStepCTE(e,t,n){return e.index===0?this.buildFirstStepCTE(e,t):this.buildSubsequentStepCTE(e,t,n)}buildFirstStepCTE(e,t){const n=`step_${e.index}`,i=e.cube.sql(t),s=[];i.where&&s.push(i.where),s.push(...e.filterConditions);let o=t.db.select({binding_key:r`${e.bindingKeyExpr}`.as("binding_key"),step_time:r`MIN(${e.timeExpr})`.as("step_time")}).from(i.from);if(o=this.addCrossJoinsToQuery(o,e,t,s),s.length>0){const a=s.length===1?s[0]:A(...s);o=o.where(a)}return o=o.groupBy(e.bindingKeyExpr),t.db.$with(n).as(o)}buildSubsequentStepCTE(e,t,n){const i=`step_${e.index}`,s=`step_${e.index-1}`,o=e.cube.sql(t),a=[];o.where&&a.push(o.where),a.push(...e.filterConditions);const u=r`${r.identifier(s)}.step_time`;let c=r`${e.timeExpr} > ${u}`;if(e.timeToConvert){const m=this.databaseAdapter.buildDateAddInterval(u,e.timeToConvert);c=r`${c} AND ${e.timeExpr} <= ${m}`}a.push(c);let l=t.db.select({binding_key:r`${e.bindingKeyExpr}`.as("binding_key"),step_time:r`MIN(${e.timeExpr})`.as("step_time")}).from(o.from).innerJoin(n,r`${e.bindingKeyExpr} = ${r.identifier(s)}.binding_key`);if(l=this.addCrossJoinsToQuery(l,e,t,a),a.length>0){const m=a.length===1?a[0]:A(...a);l=l.where(m)}return l=l.groupBy(e.bindingKeyExpr),t.db.$with(i).as(l)}addCrossJoinsToQuery(e,t,n,i){if(t.joinedCubes.length===0)return e;for(const s of t.joinedCubes)for(const o of s.joinPath){const a=o.joinDef,u=[];for(const p of a.on)p.as?u.push(p.as(p.source,p.target)):u.push(k(p.source,p.target));const c=u.length===1?u[0]:A(...u),m=s.cube.sql(n);e=e.leftJoin(m.from,c),m.where&&i.push(m.where)}return e}buildFunnelResultsCTE(e,t,n,i){const s={binding_key:r`s0.binding_key`,step_0_time:r`s0.step_time`};for(let l=1;l<t.length;l++)s[`step_${l}_time`]=r`s${r.raw(String(l))}.step_time`;let o=r`${r.identifier("step_0")} s0`;for(let l=1;l<t.length;l++)o=r`${o}
61
61
  LEFT JOIN ${r.identifier(`step_${l}`)} s${r.raw(String(l))} ON s0.binding_key = s${r.raw(String(l))}.binding_key`;const a=Object.entries(s).map(([l,m])=>r`${m} AS ${r.identifier(l)}`),u=r`SELECT ${r.join(a,r`, `)} FROM ${o}`,c={binding_key:r`binding_key`.as("binding_key"),step_0_time:r`step_0_time`.as("step_0_time")};for(let l=1;l<t.length;l++)c[`step_${l}_time`]=r`${r.identifier(`step_${l}_time`)}`.as(`step_${l}_time`);return i.db.$with("funnel_joined").as(i.db.select(c).from(r`(${u}) as _inner`))}buildAggregationCTE(e,t,n,i,s){const o={};o.step_0_count=r`COUNT(*)`.as("step_0_count");for(let u=1;u<n.length;u++)o[`step_${u}_count`]=r`COUNT(${r.identifier(`step_${u}_time`)})`.as(`step_${u}_count`);if(i.includeTimeMetrics)for(let u=1;u<n.length;u++){const c=r.identifier(`step_${u}_time`),l=r.identifier(`step_${u-1}_time`),m=this.databaseAdapter.buildTimeDifferenceSeconds(r`${c}`,r`${l}`),p=r`${c} IS NOT NULL`;o[`step_${u}_avg_seconds`]=this.databaseAdapter.buildConditionalAggregation("avg",m,p).as(`step_${u}_avg_seconds`),o[`step_${u}_min_seconds`]=this.databaseAdapter.buildConditionalAggregation("min",m,p).as(`step_${u}_min_seconds`),o[`step_${u}_max_seconds`]=this.databaseAdapter.buildConditionalAggregation("max",m,p).as(`step_${u}_max_seconds`);const f=this.databaseAdapter.getCapabilities(),h=this.databaseAdapter.buildPercentile(m,50);h&&f.supportsPercentileSubqueries&&(o[`step_${u}_median_seconds`]=r`(SELECT ${h} FROM ${r.identifier("funnel_joined")} WHERE ${c} IS NOT NULL)`.as(`step_${u}_median_seconds`));const g=this.databaseAdapter.buildPercentile(m,90);g&&f.supportsPercentileSubqueries&&(o[`step_${u}_p90_seconds`]=r`(SELECT ${g} FROM ${r.identifier("funnel_joined")} WHERE ${c} IS NOT NULL)`.as(`step_${u}_p90_seconds`))}const a=s.db.select(o).from(e);return s.db.$with("funnel_metrics").as(a)}}class Cn{filterBuilder;dateTimeBuilder;databaseAdapter;constructor(e){this.databaseAdapter=e,this.dateTimeBuilder=new re(e),this.filterBuilder=new be(e,this.dateTimeBuilder)}hasFlow(e){return e.flow!==void 0&&e.flow.startingStep!==void 0&&e.flow.eventDimension!==void 0}validateConfig(e,t){const n=[],i=[],s=this.databaseAdapter.getEngineType(),o=this.databaseAdapter.supportsLateralJoins();if(s==="sqlite")return n.push("Flow queries are not supported on SQLite. Use PostgreSQL or MySQL for flow analysis."),{isValid:!1,errors:n,warnings:i};if(typeof e.bindingKey=="string"){const[a,u]=e.bindingKey.split(".");if(!a||!u)n.push(`Invalid binding key format: ${e.bindingKey}. Expected 'CubeName.dimensionName'`);else{const c=t.get(a);c?c.dimensions?.[u]||n.push(`Binding key dimension not found: ${u} in cube ${a}`):n.push(`Binding key cube not found: ${a}`)}}else if(Array.isArray(e.bindingKey))for(const a of e.bindingKey){const u=t.get(a.cube);if(!u)n.push(`Binding key mapping cube not found: ${a.cube}`);else{const[,c]=a.dimension.split(".");u.dimensions?.[c]||n.push(`Binding key dimension not found: ${c} in cube ${a.cube}`)}}if(typeof e.timeDimension=="string"){const[a,u]=e.timeDimension.split(".");if(!a||!u)n.push(`Invalid time dimension format: ${e.timeDimension}. Expected 'CubeName.dimensionName'`);else{const c=t.get(a);c?c.dimensions?.[u]||n.push(`Time dimension not found: ${u} in cube ${a}`):n.push(`Time dimension cube not found: ${a}`)}}if(e.eventDimension){const[a,u]=e.eventDimension.split(".");if(!a||!u)n.push(`Invalid event dimension format: ${e.eventDimension}. Expected 'CubeName.dimensionName'`);else{const c=t.get(a);c?c.dimensions?.[u]||n.push(`Event dimension not found: ${u} in cube ${a}`):n.push(`Event dimension cube not found: ${a}`)}}else n.push("Event dimension is required for flow analysis");return e.startingStep?(e.startingStep.filter||n.push("Starting step must have at least one filter"),e.startingStep.name||i.push("Starting step has no name - using default")):n.push("Starting step is required for flow analysis"),(e.stepsBefore<0||e.stepsBefore>5)&&n.push(`stepsBefore must be between 0 and 5, got: ${e.stepsBefore}`),(e.stepsAfter<0||e.stepsAfter>5)&&n.push(`stepsAfter must be between 0 and 5, got: ${e.stepsAfter}`),(e.stepsBefore>=4||e.stepsAfter>=4)&&i.push("High step depth (4-5) may impact query performance on large datasets"),e.joinStrategy&&!["auto","lateral","window"].includes(e.joinStrategy)?n.push(`Invalid joinStrategy: ${e.joinStrategy}`):e.joinStrategy==="lateral"&&!o&&n.push("Lateral joins are not supported on this database"),{isValid:n.length===0,errors:n,warnings:i}}buildFlowQuery(e,t,n){if(this.databaseAdapter.getEngineType()==="sqlite")throw new Error("Flow queries are not supported on SQLite. Use PostgreSQL or MySQL for flow analysis.");const s=this.databaseAdapter.supportsLateralJoins(),o=e.joinStrategy??"auto",a=o==="lateral"||o==="auto"&&s;if(o==="lateral"&&!s)throw new Error("Lateral joins are not supported on this database");const u={...e,stepsBefore:e.outputMode==="sunburst"?0:e.stepsBefore},c=this.resolveFlowConfig(u,t,n),l=[],m=this.buildStartingEntitiesCTE(u,c,n);l.push(m);const p=a?this.buildBeforeCTEsLateral(u,c,n):this.buildBeforeCTEsWindow(u,c,n);l.push(...p);const f=a?this.buildAfterCTEsLateral(u,c,n):this.buildAfterCTEsWindow(u,c,n);l.push(...f);const h=this.buildNodesAggregationCTE(u,n);l.push(h);const g=this.buildLinksAggregationCTE(u,n);l.push(g);const y=this.buildFinalResultCTE(n);return l.push(y),n.db.with(...l).select().from(y)}transformResult(e){if(!e||e.length===0)return{nodes:[],links:[]};const t=[],n=[];for(const i of e){const s=i.record_type;s==="node"?t.push({id:String(i.id),name:String(i.name),layer:Number(i.layer),value:Number(i.value)}):s==="link"&&n.push({source:String(i.source_id),target:String(i.target_id),value:Number(i.value)})}return t.sort((i,s)=>i.layer-s.layer),{nodes:t,links:n}}resolveFlowConfig(e,t,n){const i=this.resolveCube(e,t),s=i.sql(n);return{cube:i,cubeBase:s,bindingKeyExpr:this.resolveBindingKey(e,i,n),timeExpr:this.resolveTimeDimension(e,i,n),eventExpr:this.resolveEventDimension(e,i,n),startingStepFilters:this.buildStartingStepFilters(e,i,n)}}resolveCube(e,t){let n;if(typeof e.bindingKey=="string")[n]=e.bindingKey.split(".");else if(Array.isArray(e.bindingKey)&&e.bindingKey.length>0)n=e.bindingKey[0].cube;else throw new Error("Cannot resolve cube for flow query");const i=t.get(n);if(!i)throw new Error(`Cube not found: ${n}`);return i}resolveBindingKey(e,t,n){if(typeof e.bindingKey=="string"){const[,a]=e.bindingKey.split("."),u=t.dimensions?.[a];if(!u)throw new Error(`Binding key dimension not found: ${e.bindingKey}`);return R(u.sql,n)}const i=e.bindingKey.find(a=>a.cube===t.name);if(!i)throw new Error(`No binding key mapping found for cube: ${t.name}`);const[,s]=i.dimension.split("."),o=t.dimensions?.[s];if(!o)throw new Error(`Binding key dimension not found: ${i.dimension}`);return R(o.sql,n)}resolveTimeDimension(e,t,n){if(typeof e.timeDimension=="string"){const[,a]=e.timeDimension.split("."),u=t.dimensions?.[a];if(!u)throw new Error(`Time dimension not found: ${e.timeDimension}`);return R(u.sql,n)}const i=e.timeDimension.find(a=>a.cube===t.name);if(!i)throw new Error(`No time dimension mapping found for cube: ${t.name}`);const[,s]=i.dimension.split("."),o=t.dimensions?.[s];if(!o)throw new Error(`Time dimension not found: ${i.dimension}`);return R(o.sql,n)}resolveEventDimension(e,t,n){const[,i]=e.eventDimension.split("."),s=t.dimensions?.[i];if(!s)throw new Error(`Event dimension not found: ${e.eventDimension}`);return R(s.sql,n)}buildStartingStepFilters(e,t,n){if(!e.startingStep.filter)return[];const i=Array.isArray(e.startingStep.filter)?e.startingStep.filter:[e.startingStep.filter],s=[];for(const o of i){const a=this.buildFilterCondition(o,t,n);a&&s.push(a)}return s}buildFilterCondition(e,t,n){if("and"in e||"or"in e){const u=e,c=[],l=u.and||u.or||[];for(const m of l){const p=this.buildFilterCondition(m,t,n);p&&c.push(p)}return c.length===0?null:c.length===1?c[0]:"and"in e?A(...c):r`(${r.join(c,r` OR `)})`}if("type"in e&&"filters"in e){const u=e,c=[];for(const l of u.filters||[]){const m=this.buildFilterCondition(l,t,n);m&&c.push(m)}return c.length===0?null:c.length===1?c[0]:u.type==="and"?A(...c):r`(${r.join(c,r` OR `)})`}const i=e,[,s]=i.member.split("."),o=t.dimensions?.[s];if(!o)return null;const a=R(o.sql,n);return this.filterBuilder.buildFilterCondition(a,i.operator,i.values||[],o,i.dateRange)}buildStartingEntitiesCTE(e,t,n){const{cubeBase:i,bindingKeyExpr:s,timeExpr:o,eventExpr:a,startingStepFilters:u}=t,c=[];i.where&&c.push(i.where),c.push(...u);let l=n.db.select({binding_key:r`${s}`.as("binding_key"),start_time:r`MIN(${o})`.as("start_time"),event_type:r`${a}`.as("event_type"),event_path:r`${a}`.as("event_path")}).from(i.from);if(c.length>0){const m=c.length===1?c[0]:A(...c);l=l.where(m)}return l=l.groupBy(s,a),e.entityLimit&&(l=l.limit(e.entityLimit)),n.db.$with("starting_entities").as(l)}buildBeforeCTEsLateral(e,t,n){const{cubeBase:i,bindingKeyExpr:s,timeExpr:o,eventExpr:a}=t,u=[],c=e.outputMode==="sunburst";for(let l=1;l<=e.stepsBefore;l++){const m=l===1?"starting_entities":`before_step_${l-1}`,p=l===1?"start_time":"step_time",f=`before_step_${l}`,h=[];i.where&&h.push(i.where),h.push(r`${s} = ${r.identifier(m)}.binding_key`,r`${o} < ${r.identifier(m)}.${r.identifier(p)}`);const g=h.length===1?h[0]:A(...h),y=c?r`${a} || ${"→"} || ${r.identifier(m)}.event_path`:r`${a}`,b=n.db.select({binding_key:r`${s}`.as("binding_key"),step_time:r`${o}`.as("step_time"),event_type:r`${a}`.as("event_type"),event_path:y.as("event_path")}).from(i.from).where(g).orderBy(r`${o} DESC`).limit(1),w=n.db.$with(f).as(n.db.select({binding_key:r`e.binding_key`.as("binding_key"),step_time:r`e.step_time`.as("step_time"),event_type:r`e.event_type`.as("event_type"),event_path:r`e.event_path`.as("event_path")}).from(r`${r.identifier(m)}`).crossJoinLateral(b.as("e")));u.push(w)}return u}buildAfterCTEsLateral(e,t,n){const{cubeBase:i,bindingKeyExpr:s,timeExpr:o,eventExpr:a}=t,u=[],c=e.outputMode==="sunburst";for(let l=1;l<=e.stepsAfter;l++){const m=l===1?"starting_entities":`after_step_${l-1}`,p=l===1?"start_time":"step_time",f=`after_step_${l}`,h=[];i.where&&h.push(i.where),h.push(r`${s} = ${r.identifier(m)}.binding_key`,r`${o} > ${r.identifier(m)}.${r.identifier(p)}`);const g=h.length===1?h[0]:A(...h),y=c?r`${r.identifier(m)}.event_path || ${"→"} || ${a}`:r`${a}`,b=n.db.select({binding_key:r`${s}`.as("binding_key"),step_time:r`${o}`.as("step_time"),event_type:r`${a}`.as("event_type"),event_path:y.as("event_path")}).from(i.from).where(g).orderBy(r`${o} ASC`).limit(1),w=n.db.$with(f).as(n.db.select({binding_key:r`e.binding_key`.as("binding_key"),step_time:r`e.step_time`.as("step_time"),event_type:r`e.event_type`.as("event_type"),event_path:r`e.event_path`.as("event_path")}).from(r`${r.identifier(m)}`).crossJoinLateral(b.as("e")));u.push(w)}return u}buildBeforeCTEsWindow(e,t,n){const{cubeBase:i,bindingKeyExpr:s,timeExpr:o,eventExpr:a}=t,u=[],c=e.outputMode==="sunburst";for(let l=1;l<=e.stepsBefore;l++){const m=l===1?"starting_entities":`before_step_${l-1}`,p=l===1?"start_time":"step_time",f=`before_step_${l}`,h=[];i.where&&h.push(i.where),h.push(r`${o} < ${r.identifier(m)}.${r.identifier(p)}`);const g=h.length===1?h[0]:A(...h),y=c?r`${a} || ${"→"} || ${r.identifier(m)}.event_path`:r`${a}`,b=n.db.select({binding_key:r`${s}`.as("binding_key"),step_time:r`${o}`.as("step_time"),event_type:r`${a}`.as("event_type"),event_path:y.as("event_path"),rn:r`ROW_NUMBER() OVER (PARTITION BY ${s} ORDER BY ${o} DESC)`.as("rn")}).from(i.from).innerJoin(r`${r.identifier(m)}`,r`${s} = ${r.identifier(m)}.binding_key`).where(g),w=n.db.select({binding_key:r`binding_key`.as("binding_key"),step_time:r`step_time`.as("step_time"),event_type:r`event_type`.as("event_type"),event_path:r`event_path`.as("event_path")}).from(b.as("ranked")).where(r`rn = 1`);u.push(n.db.$with(f).as(w))}return u}buildAfterCTEsWindow(e,t,n){const{cubeBase:i,bindingKeyExpr:s,timeExpr:o,eventExpr:a}=t,u=[],c=e.outputMode==="sunburst";for(let l=1;l<=e.stepsAfter;l++){const m=l===1?"starting_entities":`after_step_${l-1}`,p=l===1?"start_time":"step_time",f=`after_step_${l}`,h=[];i.where&&h.push(i.where),h.push(r`${o} > ${r.identifier(m)}.${r.identifier(p)}`);const g=h.length===1?h[0]:A(...h),y=c?r`${r.identifier(m)}.event_path || ${"→"} || ${a}`:r`${a}`,b=n.db.select({binding_key:r`${s}`.as("binding_key"),step_time:r`${o}`.as("step_time"),event_type:r`${a}`.as("event_type"),event_path:y.as("event_path"),rn:r`ROW_NUMBER() OVER (PARTITION BY ${s} ORDER BY ${o} ASC)`.as("rn")}).from(i.from).innerJoin(r`${r.identifier(m)}`,r`${s} = ${r.identifier(m)}.binding_key`).where(g),w=n.db.select({binding_key:r`binding_key`.as("binding_key"),step_time:r`step_time`.as("step_time"),event_type:r`event_type`.as("event_type"),event_path:r`event_path`.as("event_path")}).from(b.as("ranked")).where(r`rn = 1`);u.push(n.db.$with(f).as(w))}return u}buildNodesAggregationCTE(e,t){const n=[],i=e.outputMode==="sunburst";for(let a=e.stepsBefore;a>=1;a--){const u=-a,c=`before_step_${a}`;i?n.push(r`
62
62
  SELECT
63
63
  ${r.raw(`'before_${a}_'`)} || event_path AS node_id,
@@ -191,7 +191,7 @@
191
191
  FROM activity_periods
192
192
  WHERE period_number >= 0 AND period_number <= ${e.periods}
193
193
  GROUP BY binding_key${r.raw(s)}
194
- )`,a=this.databaseAdapter.buildPeriodSeriesSubquery(e.periods),u={period_number:r`p.period_number`.as("period_number"),retained_users:r`COUNT(DISTINCT CASE WHEN ump.max_period >= p.period_number THEN ump.binding_key END)`.as("retained_users")},c=[r`p.period_number`];for(let l=0;l<n;l++)u[`breakdown_${l}`]=r.raw(`ump.breakdown_${l}`).as(`breakdown_${l}`),c.push(r.raw(`ump.breakdown_${l}`));return t.db.select(u).from(r`${o} ump`).crossJoin(a).groupBy(...c)}buildPeriodNumberExpression(e,t,n){return this.databaseAdapter.buildDateDiffPeriods(e,t,n)}extractDimensionName(e){const t=e.split(".");return t.length>1?t[1]:t[0]}}class $n{constructor(e){this.queryPlanner=e}plan(e,t,n){return this.planWithAnalysis(e,t,n).plan}planWithAnalysis(e,t,n){const i=Array.from(this.queryPlanner.analyzeCubeUsage(t));if(i.length===0)throw new Error("No cubes found in query");const s=this.queryPlanner.analyzePrimaryCube(i,t,e),o=s.selectedCube,a=e.get(o);if(!a)throw new Error(`Primary cube '${o}' not found`);const c=i.filter(C=>C!==o).map(C=>this.queryPlanner.analyzeJoinPathForTarget(e,o,C,t)),l=i.length>1?this.queryPlanner.buildJoinPlanForPrimary(e,a,i,n,t):[],m=i.length>1?this.queryPlanner.buildPreAggregationCTEs(e,a,l,t,n)??[]:[],p=this.queryPlanner.buildWarnings(t,m),f=this.buildSourceFromPhases(a,l,m,e,t,n),h=f.source,g=this.buildQueryNode(h,t,e,p),y=this.buildPreAggregationAnalysis(m),b=new Map;for(const C of i){const T=e.get(C);T&&b.set(C,T)}const w=L.hasPostAggregationWindows(t.measures??[],b),$=[...c.filter(C=>!C.pathFound&&C.error).map(C=>C.error),...p.map(C=>C.message)],S={timestamp:new Date().toISOString(),cubeCount:i.length,cubesInvolved:[...i].sort(),primaryCube:s,joinPaths:c,preAggregations:y,querySummary:{queryType:m.length>0?"multi_cube_cte":i.length>1?"multi_cube_join":"single_cube",measureStrategy:f.strategy,joinCount:l.length,cteCount:m.length,hasPreAggregation:m.length>0,hasWindowFunctions:w},warnings:$.length>0?$:void 0,planningTrace:{steps:[{phase:"cube_usage",decision:`Identified ${i.length} cube${i.length===1?"":"s"} from query members`,details:{cubesInvolved:[...i].sort()}},{phase:"primary_cube_selection",decision:`Selected '${s.selectedCube}' as primary cube (${s.reason})`,details:{selectedCube:s.selectedCube,reason:s.reason,candidates:s.candidates?.map(C=>C.cubeName)}},{phase:"join_planning",decision:`Planned ${l.length} join${l.length===1?"":"s"}`,details:{joinCount:l.length,joinTargets:l.map(C=>C.cube.name),pathSelection:c.map(C=>({targetCube:C.targetCube,strategy:C.selection?.strategy,selectedRank:C.selection?.selectedRank,selectedScore:C.selection?.selectedScore}))}},{phase:"cte_planning",decision:`Planned ${m.length} pre-aggregation CTE${m.length===1?"":"s"}`,details:{cteCount:m.length,cubes:m.map(C=>C.cube.name)}},{phase:"measure_strategy",decision:`Selected '${f.strategy}' measure strategy`,details:{strategy:f.strategy,regularMeasures:f.classification.regular.map(C=>C.name),multipliedMeasures:f.classification.multiplied.map(C=>C.name),deduplicationSafeMeasures:f.classification.deduplicationSafe.map(C=>C.name),sourceType:h.type}},{phase:"warnings",decision:p.length>0?`Generated ${p.length} planning warning${p.length===1?"":"s"}`:"No planning warnings generated",details:{warningCodes:p.map(C=>C.code)}}]}};return{plan:g,analysis:S}}buildSourceFromPhases(e,t,n,i,s,o){const a=this.tryBuildMultiFactMergeSource(s,i,o);if(a){const p={regular:this.buildMeasureRefs(s,i),multiplied:[],deduplicationSafe:[]};return{source:a,strategy:"multiFactMerge",classification:p}}const u=this.buildSimpleSourceFromPhases(e,t,n,i,s),c=this.classifyMeasuresForStrategy(u.schema.measures,n),l=this.selectMeasureStrategy(c,s,i);return l==="keysDeduplication"?{source:this.buildKeysDeduplicationSource(u,c),strategy:l,classification:c}:{source:u,strategy:l,classification:c}}buildSimpleSourceFromPhases(e,t,n,i,s){const o=this.buildMeasureRefs(s,i),a=this.buildDimensionRefs(s,i),u=this.buildTimeDimensionRefs(s,i),c=this.toCubeRef(e),l=t.map(f=>({target:this.toCubeRef(f.cube),alias:f.alias,joinType:f.joinType,joinCondition:f.joinCondition,relationship:f.relationship,junctionTable:f.junctionTable})),m=n.map(f=>{const h=this.toCubeRef(f.cube);return{type:"ctePreAggregate",schema:this.buildCTESchema(f,i),cube:h,alias:f.alias,cteAlias:f.cteAlias,joinKeys:f.joinKeys,measures:f.measures,propagatingFilters:f.propagatingFilters,downstreamJoinKeys:f.downstreamJoinKeys,intermediateJoins:f.intermediateJoins,cteType:f.cteType??"aggregate",cteReason:f.cteReason??"hasMany"}});return{type:"simpleSource",schema:{measures:o,dimensions:a,timeDimensions:u},primaryCube:c,joins:l,ctes:m}}tryBuildMultiFactMergeSource(e,t,n){if(!e.measures||e.measures.length<2)return null;const i=new Set;for(const h of e.measures){const[g]=h.split(".");g&&i.add(g)}if(i.size<2)return null;const s=new Set;for(const h of e.dimensions??[]){const[g]=h.split(".");g&&s.add(g)}for(const h of e.timeDimensions??[]){const[g]=h.dimension.split(".");g&&s.add(g)}if(s.size!==1)return null;const o=Array.from(s)[0];if(i.has(o)||!t.get(o))return null;const u=Array.from(i);if(!u.every(h=>this.hasDirectJoinToSharedDimension(t.get(h),o)))return null;const l=this.buildDimensionRefs(e,t),m=this.buildTimeDimensionRefs(e,t),p={measures:this.buildMeasureRefs(e,t),dimensions:l,timeDimensions:m},f=[];for(const h of u){const g=(e.measures??[]).filter($=>$.startsWith(`${h}.`)),y=new Set([h,o]),b={measures:g,dimensions:e.dimensions,timeDimensions:e.timeDimensions,filters:this.projectFiltersToAllowedCubes(e.filters,y)},w=this.buildGroupQueryNode(b,t,n);if(!w)return null;f.push(w)}return f.length<2?null:{type:"multiFactMerge",schema:p,groups:f,sharedDimensions:l,mergeStrategy:"fullJoin"}}hasDirectJoinToSharedDimension(e,t){if(!e?.joins)return!1;for(const[,n]of Object.entries(e.joins)){const i=n.targetCube,s=typeof i=="function"?i():i;if(!(!s||s.name!==t)&&(n.relationship==="belongsTo"||n.relationship==="hasOne"))return!0}return!1}buildGroupQueryNode(e,t,n){const i=Array.from(this.queryPlanner.analyzeCubeUsage(e));if(i.length===0)return null;const s=this.queryPlanner.analyzePrimaryCube(i,e,t),o=t.get(s.selectedCube);if(!o)return null;const a=i.length>1?this.queryPlanner.buildJoinPlanForPrimary(t,o,i,n,e):[],u=i.length>1?this.queryPlanner.buildPreAggregationCTEs(t,o,a,e,n)??[]:[],c=this.queryPlanner.buildWarnings(e,u),l=this.buildSourceFromPhases(o,a,u,t,e,n);return this.buildQueryNode(l.source,e,t,c)}projectFiltersToAllowedCubes(e,t){if(!e||e.length===0)return;const n=e.map(i=>this.projectFilterNodeToAllowedCubes(i,t)).filter(i=>!!i);return n.length>0?n:void 0}projectFilterNodeToAllowedCubes(e,t){if("member"in e){const[n]=e.member.split(".");return n&&t.has(n)?e:null}if("and"in e){const n=(e.and??[]).map(i=>this.projectFilterNodeToAllowedCubes(i,t)).filter(i=>!!i);return n.length===0?null:n.length===1?n[0]:{and:n}}if("or"in e){const n=(e.or??[]).map(i=>this.projectFilterNodeToAllowedCubes(i,t)).filter(i=>!!i);return n.length===0?null:n.length===1?n[0]:{or:n}}return null}classifyMeasuresForStrategy(e,t){const n={regular:[],multiplied:[],deduplicationSafe:[]},i=new Set(t.filter(s=>s.cteReason==="fanOutPrevention").map(s=>s.cube.name));for(const s of e){const o=s.cube.cube,a=o.measures?.[s.localName];if(!a||!i.has(o.name)){n.regular.push(s);continue}this.isDeduplicationSafeMeasure(a)?n.deduplicationSafe.push(s):n.multiplied.push(s)}return n}selectMeasureStrategy(e,t,n){return e.multiplied.length===0?"simple":e.multiplied.every(s=>this.getPrimaryKeyColumns(s.cube.cube).length>0)&&this.isKeysDeduplicationExecutionSupported(e,t,n)?"keysDeduplication":"ctePreAggregateFallback"}isKeysDeduplicationExecutionSupported(e,t,n){const i=new Set(e.multiplied.map(u=>u.cube.name));if(i.size!==1)return!1;const s=Array.from(i)[0],o=t.measures??[];if(o.length===0)return!1;const a=n.get(s);if(!a)return!1;for(const u of o){const[c,l]=u.split(".");if(c!==s){const f=n.get(c)?.measures?.[l];if(!f||!["sum","count","number","min","max"].includes(f.type))return!1;continue}const m=a.measures?.[l];if(!m||!["sum","count","number","min","max","avg"].includes(m.type))return!1}return!this.queryHasMeasureFilter(t,s,a)}queryHasMeasureFilter(e,t,n){const i=o=>{const[a,u]=o.split(".");return a===t&&!!n.measures?.[u]},s=o=>{if(!o)return!1;for(const a of o){if("and"in a){if(s(a.and))return!0;continue}if("or"in a){if(s(a.or))return!0;continue}if("member"in a&&i(a.member))return!0}return!1};return s(e.filters)}buildKeysDeduplicationSource(e,t){const n=this.deduplicateColumnRefs(t.multiplied.flatMap(s=>this.getPrimaryKeyColumns(s.cube.cube))),i=t.regular.length>0?t.regular.map(s=>s.name):void 0;return{type:"keysDeduplication",schema:e.schema,keysSource:e,measureSource:e,joinOn:n,regularMeasures:i}}isDeduplicationSafeMeasure(e){return e.type==="countDistinct"||e.type==="countDistinctApprox"}getPrimaryKeyColumns(e){const t=[];for(const[n,i]of Object.entries(e.dimensions??{}))!i.primaryKey||typeof i.sql=="function"||t.push({column:i.sql,alias:`${e.name}.${n}`});return t}deduplicateColumnRefs(e){const t=new Map;for(const n of e){const i=n.alias??String(n.column?.name??"");t.has(i)||t.set(i,n)}return Array.from(t.values())}buildQueryNode(e,t,n,i){const s=this.buildMeasureRefs(t,n),o=this.buildDimensionRefs(t,n),a=this.buildTimeDimensionRefs(t,n),u=this.buildOrderByRefs(t),c=t.filters??[];return{type:"query",schema:{measures:s,dimensions:o,timeDimensions:a},source:e,dimensions:o,measures:s,filters:c,timeDimensions:a,orderBy:u,limit:t.limit,offset:t.offset,warnings:i}}buildPreAggregationAnalysis(e){return e.map(t=>({cubeName:t.cube.name,cteAlias:t.cteAlias,reason:t.cteReason==="fanOutPrevention"?`Potential fan-out from hasMany joins - pre-aggregate ${t.cube.name} to preserve correctness`:`hasMany relationship requires pre-aggregation for ${t.cube.name}`,reasonType:t.cteReason,measures:t.measures,joinKeys:t.joinKeys.map(n=>({sourceColumn:n.sourceColumn,targetColumn:n.targetColumn})),cteType:t.cteType}))}buildMeasureRefs(e,t){return e.measures?e.measures.map(n=>{const[i,s]=n.split("."),o=t.get(i);if(!o)throw new Error(`Cube '${i}' not found for measure '${n}'`);return{name:n,cube:this.toCubeRef(o),localName:s}}):[]}buildDimensionRefs(e,t){return e.dimensions?e.dimensions.map(n=>{const[i,s]=n.split("."),o=t.get(i);if(!o)throw new Error(`Cube '${i}' not found for dimension '${n}'`);return{name:n,cube:this.toCubeRef(o),localName:s}}):[]}buildTimeDimensionRefs(e,t){return e.timeDimensions?e.timeDimensions.map(n=>{const[i,s]=n.dimension.split("."),o=t.get(i);if(!o)throw new Error(`Cube '${i}' not found for time dimension '${n.dimension}'`);return{name:n.dimension,cube:this.toCubeRef(o),localName:s,granularity:n.granularity,dateRange:n.dateRange,fillMissingDates:n.fillMissingDates,compareDateRange:n.compareDateRange}}):[]}buildOrderByRefs(e){return e.order?Object.entries(e.order).map(([t,n])=>({name:t,direction:n})):[]}toCubeRef(e){return{name:e.name,cube:e}}buildCTESchema(e,t){return{measures:e.measures.map(i=>{const[s,o]=i.split("."),a=t.get(s);return{name:i,cube:{name:s,cube:a},localName:o}}),dimensions:[],timeDimensions:[]}}}class Tn{name="identity";optimise(e){return e}}function En(d,e,t,n){const i=new Map;if(d.preAggregationCTEs&&d.preAggregationCTEs.length>0){for(const u of d.preAggregationCTEs)if(u.propagatingFilters&&u.propagatingFilters.length>0)for(const c of u.propagatingFilters){const l=c.sourceCube.name;if(!i.has(l)){const p={filters:c.filters},f=new Map([[l,c.sourceCube]]),h=n.queryBuilder.buildWhereConditions(f,p,t);i.set(l,h)}const m=i.get(l);m&&m.length>0&&(c.preBuiltFilterSQL=m.length===1?m[0]:A(...m))}}const s=[],o=new Map,a=new Map;if(d.preAggregationCTEs&&d.preAggregationCTEs.length>0)for(const u of d.preAggregationCTEs){const c=n.cteBuilder.buildPreAggregationCTE(u,e,t,d,i);if(c&&(s.push(c),o.set(u.cube.name,u.cteAlias),u.downstreamJoinKeys))for(const l of u.downstreamJoinKeys)a.set(l.targetCubeName,{cteAlias:u.cteAlias,joinKeys:l.joinKeys})}return{preBuiltFilterMap:i,ctes:s,cteAliasMap:o,downstreamCubeMap:a}}function Sn(d,e,t,n,i,s){if(t.measures)for(const o of t.measures){const[a,u]=o.split("."),c=i.get(a);if(!c?.measures?.[u])continue;const l=c.measures[u];if(!L.isPostAggregationWindow(l))continue;const m=L.getWindowBaseMeasure(l,a);if(!m)continue;const[p,f]=m.split("."),h=i.get(p);if(!h?.measures?.[f])continue;const g=h.measures[f],y=e.preAggregationCTEs?.find($=>$.cube?.name===p&&$.measures?.includes(m));let b;if(y){const $=r`${r.identifier(y.cteAlias)}.${r.identifier(f)}`;b=r`sum(${$})`}else b=s.queryBuilder.buildMeasureExpression(g,n,h);d[m]||(d[m]=r`${b}`.as(m));const w=Dn(l,b,t,n,c,e,s);w&&(d[o]=r`${w}`.as(o))}}function Dn(d,e,t,n,i,s,o){const a=d.windowConfig||{},u=(f,h)=>{if(!s.preAggregationCTEs)return null;const g=s.preAggregationCTEs.find(y=>y.cube?.name===f);return g&&g.cteAlias?r`${r.identifier(g.cteAlias)}.${r.identifier(h)}`:null};let c;if(a.orderBy&&a.orderBy.length>0)c=a.orderBy.map(f=>{const h=f.field.includes(".")?f.field.split(".")[1]:f.field;if(t.timeDimensions)for(const b of t.timeDimensions){const[w,$]=b.dimension.split(".");if($===h){const S=u(w,h);if(S)return{field:S,direction:f.direction};const C=i.dimensions?.[$];if(C)return{field:o.queryBuilder.buildTimeDimensionExpression(C.sql,b.granularity,n),direction:f.direction}}}const g=i.dimensions?.[h];if(g)return{field:R(g.sql,n),direction:f.direction};const y=a.measure?.includes(".")?a.measure.split(".")[1]:a.measure;return h===y||f.field===a.measure?{field:e,direction:f.direction}:null}).filter(f=>f!==null);else if(t.timeDimensions&&t.timeDimensions.length>0){const f=t.timeDimensions[0],[h,g]=f.dimension.split("."),y=u(h,g);if(y)c=[{field:y,direction:"asc"}];else{const b=i.name===h?i:void 0;if(b?.dimensions?.[g]){const w=b.dimensions[g];c=[{field:o.queryBuilder.buildTimeDimensionExpression(w.sql,f.granularity,n),direction:"asc"}]}}}let l;a.partitionBy&&a.partitionBy.length>0&&(l=a.partitionBy.map(f=>{const h=f.includes(".")?f.split(".")[1]:f,g=i.dimensions?.[h];return g?R(g.sql,n):null}).filter(f=>f!==null));const m=o.databaseAdapter.buildWindowFunction(d.type,e,l,c,{offset:a.offset,defaultValue:a.defaultValue,nTile:a.nTile,frame:a.frame});if(!m)return null;switch(a.operation||L.getDefaultWindowOperation(d.type)){case"difference":return r`${e} - ${m}`;case"ratio":return r`${e} / NULLIF(${m}, 0)`;case"percentChange":return r`((${e} - ${m}) / NULLIF(${m}, 0)) * 100`;default:return m}}function Nn(d,e,t,n,i){const o={...i.queryBuilder.buildSelections(d.joinCubes.length>0?n:d.primaryCube,e,t)};if(d.preAggregationCTEs)for(const a of d.preAggregationCTEs){const u=a.cube.name;for(const c of a.measures){if(!o[c])continue;const[,l]=c.split("."),m=n.get(u);if(!m?.measures?.[l])continue;const p=m.measures[l],f=r`${r.identifier(a.cteAlias)}.${r.identifier(l)}`;let h;if(p.type==="calculated"&&p.calculatedSql)h=i.queryBuilder.buildCTECalculatedMeasure(p,m,a,n,t);else{const g=a.cteReason==="fanOutPrevention",y=An(a,e,n),b=g||y;switch(p.type){case"count":case"countDistinct":case"sum":h=b?H(f):z(f);break;case"avg":h=b?H(f):i.databaseAdapter.buildAvg(f);break;case"min":h=ae(f);break;case"max":h=H(f);break;case"number":h=b?H(f):z(f);break;default:h=b?H(f):z(f)}}o[c]=r`${h}`.as(c)}for(const c in o){const[l,m]=c.split(".");if(l!==u)continue;const p=n.get(u),f=p&&p.dimensions?.[m],h=c.startsWith(u+".");if(!f&&!h)continue;let g=a.joinKeys.find(y=>y.targetColumn===m);if(!g&&p?.dimensions?.[m]){const y=p.dimensions[m].sql;g=a.joinKeys.find(b=>b.targetColumnObj===y)}g?o[c]=r`${r.identifier(a.cteAlias)}.${r.identifier(m)}`.as(c):h&&p?.dimensions?.[m]&&(o[c]=r`${r.identifier(a.cteAlias)}.${r.identifier(m)}`.as(c))}}return Sn(o,d,e,t,n,i),o}function An(d,e,t){return d.cteReason!=="hasMany"||d.downstreamJoinKeys&&d.downstreamJoinKeys.length>0||d.intermediateJoins&&d.intermediateJoins.length>0||!!!(e.dimensions&&e.dimensions.length>0||e.timeDimensions&&e.timeDimensions.length>0)||!!(e.dimensions?.some(s=>s.startsWith(`${d.cube.name}.`))||e.timeDimensions?.some(s=>s.dimension.startsWith(`${d.cube.name}.`)))?!1:d.joinKeys.length>0&&d.joinKeys.every(s=>!!s.sourceColumnObj&&_n(s.sourceColumnObj,e,t))}function _n(d,e,t){if(e.dimensions)for(const n of e.dimensions){const[i,s]=n.split(".");if(t.get(i)?.dimensions?.[s]?.sql===d)return!0}if(e.timeDimensions)for(const n of e.timeDimensions){if(n.granularity)continue;const[i,s]=n.dimension.split(".");if(t.get(i)?.dimensions?.[s]?.sql===d)return!0}return!1}function vn(d,e,t,n,i,s){const o=[];let a=e.db.select(n).from(t.from);if(i.ctes.length>0&&(a=e.db.with(...i.ctes).select(n).from(t.from)),t.joins)for(const l of t.joins)switch(l.type||"left"){case"left":a=a.leftJoin(l.table,l.on);break;case"inner":a=a.innerJoin(l.table,l.on);break;case"right":a=a.rightJoin(l.table,l.on);break;case"full":a=a.fullJoin(l.table,l.on);break}const u=new Set,c=new Set;if(d.preAggregationCTEs){for(const l of d.preAggregationCTEs)if(l.intermediateJoins&&l.intermediateJoins.length>0)for(const m of l.intermediateJoins)c.add(m.cube.name)}if(d.joinCubes&&d.joinCubes.length>0)for(const l of d.joinCubes){const m=l.cube.name;if(c.has(m)&&!i.cteAliasMap.has(m))continue;const p=i.cteAliasMap.get(l.cube.name);if(l.junctionTable){const w=l.junctionTable;let $=w.joinCondition;const S=w.sourceCubeName?i.cteAliasMap.get(w.sourceCubeName):void 0;if(S){const D=d.preAggregationCTEs?.find(N=>N.cube.name===w.sourceCubeName)?.downstreamJoinKeys?.find(N=>N.targetCubeName===l.cube.name);if(D&&D.joinKeys.length>0){const N=[];for(const M of D.joinKeys){const v=r`${r.identifier(S)}.${r.identifier(M.sourceColumn)}`,U=M.targetColumnObj;U&&N.push(k(U,v))}N.length>0&&($=A(...N))}}const C=[];if(w.securitySql){const T=w.securitySql(e.securityContext);Array.isArray(T)?C.push(...T):C.push(T)}try{switch(w.joinType||"left"){case"left":a=a.leftJoin(w.table,$);break;case"inner":a=a.innerJoin(w.table,$);break;case"right":a=a.rightJoin(w.table,$);break;case"full":a=a.fullJoin(w.table,$);break}C.length>0&&o.push(...C)}catch{}}let f,h,g;if(p)f=r`${r.identifier(p)}`,h=s.cteBuilder.buildCTEJoinCondition(l,p,d),g=void 0;else{const w=i.downstreamCubeMap.get(l.cube.name),$=l.cube.sql(e);if(f=$.from,g=$.where,w&&!l.junctionTable){const S=[];for(const C of w.joinKeys){const T=r`${r.identifier(w.cteAlias)}.${r.identifier(C.sourceColumn)}`,D=C.targetColumnObj||r.identifier(C.targetColumn);S.push(k(T,D))}h=S.length===1?S[0]:A(...S)}else h=l.joinCondition}const y=l.joinType||"left",b=y!=="inner"&&g?A(h,g):h;try{switch(y){case"left":a=a.leftJoin(f,b),g&&u.add(l.cube.name);break;case"inner":a=a.innerJoin(f,h);break;case"right":a=a.rightJoin(f,b),g&&u.add(l.cube.name);break;case"full":a=a.fullJoin(f,b),g&&u.add(l.cube.name);break}}catch{}}return{drizzleQuery:a,allWhereConditions:o,cubesWithSecurityInJoin:u,absorbedIntermediateCubes:c}}function Rn(d,e,t,n,i,s,o,a){const u=[...o.allWhereConditions];if(i.where&&u.push(i.where),d.joinCubes&&d.joinCubes.length>0)for(const h of d.joinCubes){const g=h.cube.name;if(s.cteAliasMap.get(g)||o.absorbedIntermediateCubes.has(g)||o.cubesWithSecurityInJoin.has(g))continue;const b=h.cube.sql(t);b.where&&u.push(b.where)}const c=a.queryBuilder.buildWhereConditions(d.joinCubes.length>0?n:d.primaryCube,e,t,d,s.preBuiltFilterMap);c.length>0&&u.push(...c);let l=o.drizzleQuery;if(u.length>0){const h=u.length===1?u[0]:A(...u);l=l.where(h)}const m=a.queryBuilder.buildGroupByFields(d.joinCubes.length>0?n:d.primaryCube,e,t,d);m.length>0&&(l=l.groupBy(...m));const p=a.queryBuilder.buildHavingConditions(d.joinCubes.length>0?n:d.primaryCube,e,t,d);if(p.length>0){const h=p.length===1?p[0]:A(...p);l=l.having(h)}const f=a.queryBuilder.buildOrderBy(e);return f.length>0&&(l=l.orderBy(...f)),l=a.queryBuilder.applyLimitAndOffset(l,e),l}function tt(d){const e=new Map;if(e.set(d.primaryCube.name,d.primaryCube),d.joinCubes)for(const t of d.joinCubes)e.set(t.cube.name,t.cube);return e}class Fn{constructor(e,t,n){this.queryBuilder=e,this.cteBuilder=t,this.databaseAdapter=n}derivePhysicalPlanContext(e){const t=e.source;if(t.type==="multiFactMerge")return this.derivePhysicalPlanContextFromMultiFact(e,t);if(t.type==="fullKeyAggregate")return this.derivePhysicalPlanContextFromFullKeyAggregate(e,t);const n=this.resolvePhysicalSimpleSource(t),i=this.resolveKeysDeduplicationMeta(t);return{primaryCube:n.primaryCube.cube,joinCubes:n.joins.map(s=>({cube:s.target.cube,alias:s.alias,joinType:s.joinType,joinCondition:s.joinCondition,junctionTable:s.junctionTable})),preAggregationCTEs:n.ctes.map(s=>({cube:s.cube.cube,alias:s.alias,cteAlias:s.cteAlias,joinKeys:s.joinKeys,measures:s.measures,propagatingFilters:s.propagatingFilters,downstreamJoinKeys:s.downstreamJoinKeys,intermediateJoins:s.intermediateJoins,cteType:s.cteType,cteReason:s.cteReason})),keysDeduplication:i,warnings:e.warnings.length>0?e.warnings:void 0}}derivePhysicalPlanContextFromMultiFact(e,t){const n=t.groups.map((s,o)=>{if(s.type!=="query")return null;const a=s,u=this.derivePhysicalPlanContext(a),c=this.toSemanticQuery(a);return{alias:`mf_group_${o+1}`,query:c,queryPlan:u,measures:c.measures??[]}}).filter(s=>!!s);if(n.length===0)throw new Error("multiFactMerge requires at least one query group");const i=n[0];return{primaryCube:i.queryPlan.primaryCube,joinCubes:i.queryPlan.joinCubes,preAggregationCTEs:i.queryPlan.preAggregationCTEs,warnings:e.warnings.length>0?e.warnings:void 0,multiFactMerge:{mergeStrategy:t.mergeStrategy,sharedDimensions:t.sharedDimensions.map(s=>s.name),groups:n}}}derivePhysicalPlanContextFromFullKeyAggregate(e,t){const n=t.subqueries.map((s,o)=>{if(s.type!=="query")throw new Error("fullKeyAggregate currently requires query subqueries");const a=s,u=this.derivePhysicalPlanContext(a),c=this.toSemanticQuery(a);return{alias:`fka_group_${o+1}`,query:c,queryPlan:u,measures:c.measures??[]}});if(n.length===0)throw new Error("fullKeyAggregate requires at least one subquery");const i=n[0];return{primaryCube:i.queryPlan.primaryCube,joinCubes:i.queryPlan.joinCubes,preAggregationCTEs:i.queryPlan.preAggregationCTEs,warnings:e.warnings.length>0?e.warnings:void 0,multiFactMerge:{mergeStrategy:"fullJoin",sharedDimensions:t.dimensions.map(s=>s.name),groups:n}}}toSemanticQuery(e){const t=e.orderBy.length>0?Object.fromEntries(e.orderBy.map(n=>[n.name,n.direction])):void 0;return{measures:e.measures.map(n=>n.name),dimensions:e.dimensions.map(n=>n.name),timeDimensions:e.timeDimensions.map(n=>({dimension:n.name,granularity:n.granularity,dateRange:n.dateRange,fillMissingDates:n.fillMissingDates,compareDateRange:n.compareDateRange})),filters:e.filters,order:t,limit:e.limit,offset:e.offset}}resolvePhysicalSimpleSource(e){switch(e.type){case"simpleSource":return e;case"keysDeduplication":return this.resolvePhysicalSimpleSourceFromKeysDedup(e);default:throw new Error(`Current SQL builder does not support logical node '${e.type}' in physical conversion`)}}resolvePhysicalSimpleSourceFromKeysDedup(e){const t=e.measureSource;if(t.type==="simpleSource")return t;const n=e.keysSource;if(n.type==="simpleSource")return n;throw new Error("keysDeduplication requires at least one simpleSource child for SQL physical conversion")}resolveKeysDeduplicationMeta(e){if(e.type!=="keysDeduplication")return;const t=e,n=new Set;for(const s of t.joinOn){if(!s.alias)continue;const[o,a]=s.alias.split(".");o&&a&&n.add(o)}const i=n.size===1?Array.from(n)[0]:"";return i?{multipliedCubeName:i,primaryKeyDimensions:t.joinOn.map(s=>s.alias?.split(".")[1]??"").filter(Boolean),regularMeasures:t.regularMeasures}:void 0}build(e,t,n){const i={queryBuilder:this.queryBuilder,cteBuilder:this.cteBuilder,databaseAdapter:this.databaseAdapter},s=this.tryBuildMultiFactMergeQuery(e,t,n,i);if(s)return s;const o=this.tryBuildKeysDeduplicationQuery(e,t,n,i);if(o)return o;const a=En(e,t,n,i),u=e.primaryCube.sql(n),c=e.joinCubes.length>0?tt(e):new Map([[e.primaryCube.name,e.primaryCube]]),l=Nn(e,t,n,c,i),m=vn(e,n,u,l,a,i);return Rn(e,t,n,c,u,a,m,i)}tryBuildKeysDeduplicationQuery(e,t,n,i){const s=e.keysDeduplication;if(!s?.multipliedCubeName||!t.measures?.length)return null;const o=e.joinCubes.length>0?tt(e):new Map([[e.primaryCube.name,e.primaryCube]]),a=o.get(s.multipliedCubeName);if(!a||!this.canExecuteKeysDeduplication(t,a,s.multipliedCubeName))return null;const u=s.primaryKeyDimensions.length>0?s.primaryKeyDimensions:this.getPrimaryKeyDimensions(a);if(u.length===0)return null;const c=`${s.multipliedCubeName.toLowerCase()}_keys`,l=`${s.multipliedCubeName.toLowerCase()}_pk_agg`,m={},p=[];if(t.dimensions)for(const E of t.dimensions){const[_,F]=E.split("."),j=o.get(_),W=j?.dimensions?.[F];if(!j||!W)return null;const J=R(W.sql,n);m[E]=r`${J}`.as(E),p.push(J)}if(t.timeDimensions)for(const E of t.timeDimensions){const[_,F]=E.dimension.split("."),j=o.get(_),W=j?.dimensions?.[F];if(!j||!W)return null;const J=i.queryBuilder.buildTimeDimensionExpression(W.sql,E.granularity,n);m[E.dimension]=r`${J}`.as(E.dimension),p.push(J)}const f=[];for(const E of u){const _=a.dimensions?.[E];if(!_)return null;const F=R(_.sql,n),j=`__pk__${E}`;m[j]=r`${F}`.as(j),p.push(F),f.push(j)}const h=s.regularMeasures??[],g=new Set(h),y=t.measures.filter(E=>!g.has(E));if(h.length>0){const E=i.queryBuilder.buildResolvedMeasures(h,o,n);for(const _ of h){const F=E.get(_);if(!F)return null;const j=`__reg__${_.replace(".","__")}`;m[j]=r`${F()}`.as(j)}}const b=e.primaryCube.sql(n),w=[];b.where&&w.push(b.where);let $=n.db.select(m).from(b.from);if(b.joins)for(const E of b.joins)$=this.applyJoinByType($,E.type??"left",E.table,E.on);for(const E of e.joinCubes){if(E.junctionTable&&($=this.applyJoinByType($,E.junctionTable.joinType??"left",E.junctionTable.table,E.junctionTable.joinCondition),E.junctionTable.securitySql)){const F=E.junctionTable.securitySql(n.securityContext);Array.isArray(F)?w.push(...F):w.push(F)}const _=E.cube.sql(n);$=this.applyJoinByType($,E.joinType??"left",_.from,E.joinCondition),_.where&&w.push(_.where)}w.push(...i.queryBuilder.buildWhereConditions(o,t,n)),w.length>0&&($=$.where(w.length===1?w[0]:A(...w))),p.length>0&&($=$.groupBy(...p));const S=n.db.$with(c).as($),C=a.sql(n),T={},D=[];for(const E of u){const _=a.dimensions?.[E];if(!_)return null;const F=R(_.sql,n);T[E]=r`${F}`.as(E),D.push(F)}const N=new Set;for(const E of y){const[,_]=E.split(".");a.measures?.[_]?.type==="avg"&&N.add(_)}const M=y.filter(E=>{const[,_]=E.split(".");return!N.has(_)});if(M.length>0){const E=i.queryBuilder.buildResolvedMeasures(M,new Map([[a.name,a]]),n);for(const _ of M){const[,F]=_.split("."),j=E.get(_);if(!j)return null;T[F]=r`${j()}`.as(F)}}for(const E of y){const[,_]=E.split(".");if(!N.has(_))continue;const F=a.measures?.[_];if(!F?.sql)return null;const j=R(F.sql,n),W=`__avg_sum__${_}`,J=`__avg_count__${_}`;T[W]=r`sum(${j})`.as(W),T[J]=r`count(${j})`.as(J)}let v=n.db.select(T).from(C.from);const U=[];C.where&&U.push(C.where),U.push(...i.queryBuilder.buildWhereConditions(a,t,n)),U.length>0&&(v=v.where(U.length===1?U[0]:A(...U))),D.length>0&&(v=v.groupBy(...D));const bt=n.db.$with(l).as(v),Z={};for(const E of t.dimensions??[])Z[E]=r`${r.identifier(c)}.${r.identifier(E)}`.as(E);for(const E of t.timeDimensions??[])Z[E.dimension]=r`${r.identifier(c)}.${r.identifier(E.dimension)}`.as(E.dimension);for(const E of y){const[,_]=E.split("."),F=a.measures?.[_];Z[E]=this.buildKeysOuterAggregation(F?.type??"sum",l,_,E)}for(const E of h){const[_,F]=E.split("."),W=o.get(_)?.measures?.[F],J=`__reg__${E.replace(".","__")}`;Z[E]=this.buildKeysOuterAggregation(W?.type??"sum",c,J,E)}let V=n.db.with(S,bt).select(Z).from(r`${r.identifier(c)}`);const ye=f.map((E,_)=>k(r`${r.identifier(c)}.${r.identifier(E)}`,r`${r.identifier(l)}.${r.identifier(u[_])}`)),yt=ye.length===1?ye[0]:A(...ye);V=V.leftJoin(r`${r.identifier(l)}`,yt);const Ie=[...(t.dimensions??[]).map(E=>r`${r.identifier(c)}.${r.identifier(E)}`),...(t.timeDimensions??[]).map(E=>r`${r.identifier(c)}.${r.identifier(E.dimension)}`)];Ie.length>0&&(V=V.groupBy(...Ie));const je=i.queryBuilder.buildOrderBy(t,Object.keys(Z));return je.length>0&&(V=V.orderBy(...je)),V=i.queryBuilder.applyLimitAndOffset(V,t),V}tryBuildMultiFactMergeQuery(e,t,n,i){const s=e.multiFactMerge;if(!s||s.groups.length<2)return null;const o=[...t.dimensions??[],...(t.timeDimensions??[]).map(b=>b.dimension)],a=Array.from(new Set(o)),u=a.length>0&&s.mergeStrategy==="fullJoin"&&!this.supportsFullOuterJoin(),c=this.selectRuntimeMergeStrategy(s.mergeStrategy,a.length>0),l=s.groups.map(b=>{const w=this.build(b.queryPlan,b.query,n);return n.db.$with(b.alias).as(w)});if(u)return this.buildMultiFactUnionKeysFallbackQuery(t,n,i,s,l,a);const m=s.groups[0].alias,p=s.groups.map(b=>b.alias),f={};if(a.length>0)for(const b of a){const w=this.coalesceQualifiedColumn(p,b);f[b]=r`${w}`.as(b)}for(const b of s.groups)for(const w of b.measures){const $=r`${r.identifier(b.alias)}.${r.identifier(w)}`;f[w]=r`coalesce(${$}, 0)`.as(w)}let h=n.db.with(...l).select(f).from(r`${r.identifier(m)}`),g=new Map;for(const b of a)g.set(b,r`${r.identifier(m)}.${r.identifier(b)}`);for(let b=1;b<s.groups.length;b++){const w=s.groups[b].alias;let $;if(a.length===0)$=r`1 = 1`;else{const S=a.map(C=>k(g.get(C),r`${r.identifier(w)}.${r.identifier(C)}`));$=S.length===1?S[0]:A(...S)}if(h=this.applyJoinByType(h,c,r`${r.identifier(w)}`,$),a.length>0&&c==="full")for(const S of a)g.set(S,r`coalesce(${g.get(S)}, ${r`${r.identifier(w)}.${r.identifier(S)}`})`)}const y=i.queryBuilder.buildOrderBy(t,Object.keys(f));return y.length>0&&(h=h.orderBy(...y)),i.queryBuilder.applyLimitAndOffset(h,t)}buildMultiFactUnionKeysFallbackQuery(e,t,n,i,s,o){const a="mf_all_keys",u=i.groups.map(h=>r`select ${this.buildSharedKeySelection(h.alias,o)} from ${r.identifier(h.alias)}`),c=r`${r.join(u,r` union `)}`,l=t.db.$with(a).as(c),m={};for(const h of o)m[h]=r`${r.identifier(a)}.${r.identifier(h)}`.as(h);for(const h of i.groups)for(const g of h.measures){const y=r`${r.identifier(h.alias)}.${r.identifier(g)}`;m[g]=r`coalesce(${y}, 0)`.as(g)}let p=t.db.with(...s,l).select(m).from(r`${r.identifier(a)}`);for(const h of i.groups){const g=o.map(b=>k(r`${r.identifier(a)}.${r.identifier(b)}`,r`${r.identifier(h.alias)}.${r.identifier(b)}`)),y=g.length===1?g[0]:A(...g);p=p.leftJoin(r`${r.identifier(h.alias)}`,y)}const f=n.queryBuilder.buildOrderBy(e,Object.keys(m));return f.length>0&&(p=p.orderBy(...f)),n.queryBuilder.applyLimitAndOffset(p,e)}buildSharedKeySelection(e,t){const n=t.map(i=>r`${r.identifier(e)}.${r.identifier(i)} as ${r.identifier(i)}`);return r.join(n,r`, `)}selectRuntimeMergeStrategy(e,t){return!t||e==="innerJoin"?"inner":e==="leftJoin"?"left":this.supportsFullOuterJoin()?"full":"left"}supportsFullOuterJoin(){const e=this.databaseAdapter.getEngineType();return e==="postgres"||e==="duckdb"}coalesceQualifiedColumn(e,t){if(e.length===1)return r`${r.identifier(e[0])}.${r.identifier(t)}`;const n=e.map(s=>r`${r.identifier(s)}.${r.identifier(t)}`);let i=n[0];for(let s=1;s<n.length;s++)i=r`coalesce(${i}, ${n[s]})`;return i}canExecuteKeysDeduplication(e,t,n){if(!e.measures?.length)return!1;for(const i of e.measures){const[s,o]=i.split(".");if(s!==n)continue;const a=t.measures?.[o];if(!a||!["sum","count","number","min","max","avg"].includes(a.type))return!1}return!this.queryContainsMeasureFilter(e,t,n)}queryContainsMeasureFilter(e,t,n){const i=s=>{if(!s)return!1;for(const o of s){if("and"in o){if(i(o.and))return!0;continue}if("or"in o){if(i(o.or))return!0;continue}if("member"in o){const[a,u]=o.member.split(".");if(a===n&&t.measures?.[u])return!0}}return!1};return i(e.filters)}getPrimaryKeyDimensions(e){return Object.entries(e.dimensions??{}).filter(([,t])=>!!t.primaryKey).map(([t])=>t)}buildKeysOuterAggregation(e,t,n,i){switch(e){case"min":{const s=r`${r.identifier(t)}.${r.identifier(n)}`;return r`min(${s})`.as(i)}case"max":{const s=r`${r.identifier(t)}.${r.identifier(n)}`;return r`max(${s})`.as(i)}case"avg":{const s=r`${r.identifier(t)}.${r.identifier(`__avg_sum__${n}`)}`,o=r`${r.identifier(t)}.${r.identifier(`__avg_count__${n}`)}`;return r`sum(${s}) / nullif(sum(${o}), 0)`.as(i)}default:{const s=r`${r.identifier(t)}.${r.identifier(n)}`;return r`coalesce(sum(${s}), 0)`.as(i)}}}applyJoinByType(e,t,n,i){switch(t){case"inner":return e.innerJoin(n,i);case"right":return e.rightJoin(n,i);case"full":return e.fullJoin(n,i);default:return e.leftJoin(n,i)}}}class Mn{constructor(e,t){if(this.dbExecutor=e,this.databaseAdapter=e.databaseAdapter,!this.databaseAdapter)throw new Error("DatabaseExecutor must have a databaseAdapter property");this.queryBuilder=new un(this.databaseAdapter);const n=new ln,i=new cn(this.queryBuilder);this.drizzlePlanBuilder=new Fn(this.queryBuilder,i,this.databaseAdapter),this.comparisonQueryBuilder=new bn(this.databaseAdapter),this.funnelQueryBuilder=new yn(this.databaseAdapter),this.flowQueryBuilder=new Cn(this.databaseAdapter),this.retentionQueryBuilder=new wn(this.databaseAdapter),this.logicalPlanBuilder=new $n(n),this.planOptimiser=new Tn,this.cacheConfig=t}queryBuilder;drizzlePlanBuilder;databaseAdapter;comparisonQueryBuilder;funnelQueryBuilder;flowQueryBuilder;retentionQueryBuilder;cacheConfig;logicalPlanBuilder;planOptimiser;async execute(e,t,n,i){try{const s=this.resolveQueryMode(t);this.validateQueryForMode(s,e,t);let o;if(this.cacheConfig?.enabled!==!1&&this.cacheConfig?.provider)if(o=Xt(t,n,this.cacheConfig),i?.skipCache)this.cacheConfig.onCacheEvent?.({type:"miss",key:o,durationMs:0});else try{const a=Date.now(),u=await this.cacheConfig.provider.get(o);if(u)return this.cacheConfig.onCacheEvent?.({type:"hit",key:o,durationMs:Date.now()-a}),{...u.value,cache:u.metadata?{hit:!0,cachedAt:new Date(u.metadata.cachedAt).toISOString(),ttlMs:u.metadata.ttlMs,ttlRemainingMs:u.metadata.ttlRemainingMs}:{hit:!0,cachedAt:new Date().toISOString(),ttlMs:0,ttlRemainingMs:0}};this.cacheConfig.onCacheEvent?.({type:"miss",key:o,durationMs:Date.now()-a})}catch(a){this.cacheConfig.onError?.(a,"get")}return await this.executeQueryByModeWithCache(s,e,t,n,o)}catch(s){if(s instanceof Error){let o=s;for(;o.cause instanceof Error;)o=o.cause;let a=o.message;const u=o;throw u.code&&(a+=` [${u.code}]`),u.detail&&(a+=` Detail: ${u.detail}`),u.hint&&(a+=` Hint: ${u.hint}`),s.message=`Query execution failed: ${a}`,s}throw new Error("Query execution failed: Unknown error")}}buildLogicalPlan(e,t,n){const i=new ne,s=this.createQueryContext(n,i);return this.preloadFilterCache(t,i,e,s),this.buildRegularQueryArtifacts(e,t,s).optimisedPlan}analyzeQuery(e,t,n){const i=new ne,s=this.createQueryContext(n,i);return this.preloadFilterCache(t,i,e,s),this.buildRegularQueryArtifacts(e,t,s).analysis}async executeQuery(e,t,n){const i=new Map;return i.set(e.name,e),this.execute(i,t,n)}async executeComparisonQueryWithCache(e,t,n,i){const s=await this.executeComparisonQuery(e,t,n);return await this.cacheResult(i,s),s}async executeComparisonQuery(e,t,n){const i=this.buildComparisonExecutionPlan(t),{timeDimension:s,periods:o,granularity:a,periodQueries:u}=i,c=u.map(async(p,f)=>({result:await this.executeStandardQuery(e,p,n),period:o[f]})),l=await Promise.all(c),m=this.comparisonQueryBuilder.mergeComparisonResults(l,s,a);return m.data=this.comparisonQueryBuilder.sortComparisonResults(m.data,s.dimension),m}buildComparisonExecutionPlan(e){const t=this.comparisonQueryBuilder.getComparisonTimeDimension(e);if(!t||!t.compareDateRange)throw new Error("No compareDateRange found in query");const n=this.comparisonQueryBuilder.normalizePeriods(t.compareDateRange);if(n.length<2)throw new Error("compareDateRange requires at least 2 periods");const i=n.map(s=>this.comparisonQueryBuilder.createPeriodQuery(e,s));return{timeDimension:t,granularity:t.granularity||"day",periods:n,periodQueries:i}}async executeFunnelQueryWithCache(e,t,n,i){const s=await this.executeFunnelQuery(e,t,n);return await this.cacheResult(i,s),{...s,cache:{hit:!1}}}async executeFunnelQuery(e,t,n){const i=t.funnel,s=this.funnelQueryBuilder.validateConfig(i,e);if(!s.isValid)throw new Error(`Funnel validation failed: ${s.errors.join(", ")}`);const o={db:this.dbExecutor.db,schema:this.dbExecutor.schema,securityContext:n},u=await this.funnelQueryBuilder.buildFunnelQuery(i,e,o),c=this.funnelQueryBuilder.transformResult(u,i),l={measures:{},dimensions:{},segments:{},timeDimensions:{}};return l.funnel={config:i,steps:i.steps.map((m,p)=>({name:m.name,index:p,timeToConvert:m.timeToConvert}))},{data:c,annotation:l}}async executeFlowQueryWithCache(e,t,n,i){const s=await this.executeFlowQuery(e,t,n);return await this.cacheResult(i,s),{...s,cache:{hit:!1}}}async executeFlowQuery(e,t,n){const i=t.flow,s=this.flowQueryBuilder.validateConfig(i,e);if(!s.isValid)throw new Error(`Flow validation failed: ${s.errors.join(", ")}`);const o={db:this.dbExecutor.db,schema:this.dbExecutor.schema,securityContext:n},u=await this.flowQueryBuilder.buildFlowQuery(i,e,o),c=this.flowQueryBuilder.transformResult(u),l={measures:{},dimensions:{},segments:{},timeDimensions:{}};return l.flow={config:i,startingStep:{name:i.startingStep.name},stepsBefore:i.stepsBefore,stepsAfter:i.stepsAfter},{data:[c],annotation:l}}async executeRetentionQueryWithCache(e,t,n,i){const s=await this.executeRetentionQuery(e,t,n);return await this.cacheResult(i,s),{...s,cache:{hit:!1}}}async executeRetentionQuery(e,t,n){const i=t.retention,s=this.retentionQueryBuilder.validateConfig(i,e);if(!s.isValid)throw new Error(`Retention validation failed: ${s.errors.join(", ")}`);const o={db:this.dbExecutor.db,schema:this.dbExecutor.schema,securityContext:n},u=await this.retentionQueryBuilder.buildRetentionQuery(i,e,o),c=this.retentionQueryBuilder.transformResult(u,i),l={measures:{},dimensions:{},segments:{},timeDimensions:{}};return l.retention={config:i,granularity:i.granularity,periods:i.periods,retentionType:i.retentionType,breakdownDimensions:i.breakdownDimensions},{data:c,annotation:l}}async executeStandardQuery(e,t,n){const i=new ne,s=this.createQueryContext(n,i);this.preloadFilterCache(t,i,e,s);const{optimisedPlan:o}=this.buildRegularQueryArtifacts(e,t,s),a=this.drizzlePlanBuilder.derivePhysicalPlanContext(o),u=this.drizzlePlanBuilder.build(a,t,s),c=this.queryBuilder.collectNumericFields(e,t),l=await this.dbExecutor.execute(u,c),m=Array.isArray(l)?l.map(g=>{const y={...g};if(t.timeDimensions){for(const b of t.timeDimensions)if(b.dimension in y){let w=y[b.dimension];if(typeof w=="string"&&w.match(/^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}/)){const $=w.replace(" ","T"),S=!$.endsWith("Z")&&!$.includes("+")?$+"Z":$;w=new Date(S)}w=this.databaseAdapter.convertTimeDimensionResult(w),y[b.dimension]=w}}return y}):[l],p=t.measures||[],f=Ye(m,t,p),h=this.generateAnnotations(a,t);return{data:f,annotation:h}}createQueryContext(e,t){return{db:this.dbExecutor.db,schema:this.dbExecutor.schema,securityContext:e,filterCache:t}}getOptimiserEngineType(){const e=this.dbExecutor.getEngineType?.();return e==="singlestore"?"mysql":e??"postgres"}buildRegularQueryArtifacts(e,t,n){const i=this.logicalPlanBuilder.planWithAnalysis(e,t,n),s=this.planOptimiser.optimise(i.plan,{engineType:this.getOptimiserEngineType()});return{logicalPlan:i.plan,analysis:i.analysis,optimisedPlan:s}}validateSecurityContext(e,t){const n=typeof process<"u"?process.env?.NODE_ENV:void 0,i=typeof process<"u"?process.env?.DRIZZLE_CUBE_WARN_SECURITY:void 0;if(n!=="development"&&!i)return;const s=[e.primaryCube];for(const a of e.joinCubes||[])s.push(a.cube);for(const a of e.preAggregationCTEs||[])s.push(a.cube);const o=new Set;for(const a of s)if(!o.has(a.name)){o.add(a.name);try{if(a.public)continue;a.sql(t).where||console.warn(`[drizzle-cube] WARNING: Cube '${a.name}' has no security filtering. If this cube contains public data, add 'public: true' to suppress this warning. Otherwise, ensure sql() returns: { from: table, where: eq(table.orgId, ctx.securityContext.orgId) }`)}catch{}}}async generateSQL(e,t,n){const i=new Map;return i.set(e.name,e),this.generateUnifiedSQL(i,t,n)}async generateMultiCubeSQL(e,t,n){return this.generateUnifiedSQL(e,t,n)}async dryRunFunnel(e,t,n){if(!this.funnelQueryBuilder.hasFunnel(t))throw new Error("Query does not contain a valid funnel configuration");const i=t.funnel,s=this.funnelQueryBuilder.validateConfig(i,e);if(!s.isValid)throw new Error(`Funnel validation failed: ${s.errors.join(", ")}`);const o={db:this.dbExecutor.db,schema:this.dbExecutor.schema,securityContext:n},u=this.funnelQueryBuilder.buildFunnelQuery(i,e,o).toSQL();return{sql:u.sql,params:u.params}}async dryRunFlow(e,t,n){if(!this.flowQueryBuilder.hasFlow(t))throw new Error("Query does not contain a valid flow configuration");const i=t.flow,s=this.flowQueryBuilder.validateConfig(i,e);if(!s.isValid)throw new Error(`Flow validation failed: ${s.errors.join(", ")}`);const o={db:this.dbExecutor.db,schema:this.dbExecutor.schema,securityContext:n},u=this.flowQueryBuilder.buildFlowQuery(i,e,o).toSQL();return{sql:u.sql,params:u.params}}async dryRunRetention(e,t,n){if(!this.retentionQueryBuilder.hasRetention(t))throw new Error("Query does not contain a valid retention configuration");const i=t.retention,s=this.retentionQueryBuilder.validateConfig(i,e);if(!s.isValid)throw new Error(`Retention validation failed: ${s.errors.join(", ")}`);const o={db:this.dbExecutor.db,schema:this.dbExecutor.schema,securityContext:n},u=this.retentionQueryBuilder.buildRetentionQuery(i,e,o).toSQL();return{sql:u.sql,params:u.params}}async explainQuery(e,t,n,i){const s=await this.dryRunSQL(e,t,n);return this.dbExecutor.explainQuery(s.sql,s.params||[],i)}async dryRunSQL(e,t,n){const i=this.resolveQueryMode(t);return this.validateQueryForMode(i,e,t),this.generateSqlForMode(i,e,t,n)}async generateUnifiedSQL(e,t,n){const i=new ne,s=this.createQueryContext(n,i);this.preloadFilterCache(t,i,e,s);const{optimisedPlan:o}=this.buildRegularQueryArtifacts(e,t,s),a=this.drizzlePlanBuilder.derivePhysicalPlanContext(o),c=this.drizzlePlanBuilder.build(a,t,s).toSQL();return{sql:c.sql,params:c.params}}resolveQueryMode(e){const t=[];if(this.comparisonQueryBuilder.hasComparison(e)&&t.push("comparison"),this.funnelQueryBuilder.hasFunnel(e)&&t.push("funnel"),this.flowQueryBuilder.hasFlow(e)&&t.push("flow"),this.retentionQueryBuilder.hasRetention(e)&&t.push("retention"),t.length===0)return"regular";if(t.length>1)throw new Error(`Query contains multiple query modes: ${t.join(", ")}`);return t[0]}validateQueryForMode(e,t,n){const i=()=>{const o=dt(t,n);if(!o.isValid)throw new Error(`Query validation failed: ${o.errors.join(", ")}`)};({regular:i,comparison:i,funnel:()=>{const o=this.funnelQueryBuilder.validateConfig(n.funnel,t);if(!o.isValid)throw new Error(`Funnel validation failed: ${o.errors.join(", ")}`)},flow:()=>{const o=this.flowQueryBuilder.validateConfig(n.flow,t);if(!o.isValid)throw new Error(`Flow validation failed: ${o.errors.join(", ")}`)},retention:()=>{const o=this.retentionQueryBuilder.validateConfig(n.retention,t);if(!o.isValid)throw new Error(`Retention validation failed: ${o.errors.join(", ")}`)}})[e]()}async executeQueryByModeWithCache(e,t,n,i,s){return{regular:()=>this.executeRegularQueryWithCache(t,n,i,s),comparison:()=>this.executeComparisonQueryWithCache(t,n,i,s),funnel:()=>this.executeFunnelQueryWithCache(t,n,i,s),flow:()=>this.executeFlowQueryWithCache(t,n,i,s),retention:()=>this.executeRetentionQueryWithCache(t,n,i,s)}[e]()}async executeRegularQueryWithCache(e,t,n,i){const s=new ne,o=this.createQueryContext(n,s);this.preloadFilterCache(t,s,e,o);const{optimisedPlan:a}=this.buildRegularQueryArtifacts(e,t,o),u=this.drizzlePlanBuilder.derivePhysicalPlanContext(a);this.validateSecurityContext(u,o);const c=this.drizzlePlanBuilder.build(u,t,o),l=this.queryBuilder.collectNumericFields(e,t),m=await this.dbExecutor.execute(c,l),p=Array.isArray(m)?m.map(b=>{const w={...b};if(t.timeDimensions){for(const $ of t.timeDimensions)if($.dimension in w){let S=w[$.dimension];if(typeof S=="string"&&S.match(/^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}/)){const C=S.replace(" ","T"),T=!C.endsWith("Z")&&!C.includes("+")?C+"Z":C;S=new Date(T)}S=this.databaseAdapter.convertTimeDimensionResult(S),w[$.dimension]=S}}return w}):[m],f=t.measures||[],h=Ye(p,t,f),g=this.generateAnnotations(u,t),y={data:h,annotation:g,warnings:a.warnings?.length?a.warnings:void 0};return await this.cacheResult(i,y),y}async cacheResult(e,t){if(!(!e||!this.cacheConfig?.provider))try{const n=Date.now();await this.cacheConfig.provider.set(e,t,this.cacheConfig.defaultTtlMs??3e5),this.cacheConfig.onCacheEvent?.({type:"set",key:e,durationMs:Date.now()-n})}catch(n){this.cacheConfig.onError?.(n,"set")}}async generateSqlForMode(e,t,n,i){return{regular:()=>this.generateUnifiedSQL(t,n,i),comparison:()=>this.generateComparisonSQL(t,n,i),funnel:()=>this.dryRunFunnel(t,n,i),flow:()=>this.dryRunFlow(t,n,i),retention:()=>this.dryRunRetention(t,n,i)}[e]()}async generateComparisonSQL(e,t,n){const s=this.buildComparisonExecutionPlan(t).periodQueries[0];return this.generateUnifiedSQL(e,s,n)}generateAnnotations(e,t){const n={},i={},s={},o=[e.primaryCube].filter(Boolean);if(e.joinCubes&&e.joinCubes.length>0&&o.push(...e.joinCubes.map(a=>a.cube).filter(Boolean)),e.multiFactMerge?.groups?.length)for(const a of e.multiFactMerge.groups)a.queryPlan.primaryCube&&o.push(a.queryPlan.primaryCube),a.queryPlan.joinCubes?.length&&o.push(...a.queryPlan.joinCubes.map(u=>u.cube).filter(Boolean));if(t.measures)for(const a of t.measures){const[u,c]=a.split("."),l=o.find(m=>m?.name===u);if(l&&l.measures[c]){const m=l.measures[c];n[a]={title:m.title||c,shortTitle:m.title||c,type:m.type}}}if(t.dimensions)for(const a of t.dimensions){const[u,c]=a.split("."),l=o.find(m=>m?.name===u);if(l&&l.dimensions?.[c]){const m=l.dimensions[c];i[a]={title:m.title||c,shortTitle:m.title||c,type:m.type}}}if(t.timeDimensions)for(const a of t.timeDimensions){const[u,c]=a.dimension.split("."),l=o.find(m=>m?.name===u);if(l&&l.dimensions?.[c]){const m=l.dimensions[c];s[a.dimension]={title:m.title||c,shortTitle:m.title||c,type:m.type,granularity:a.granularity}}}return{measures:n,dimensions:i,segments:{},timeDimensions:s}}preloadFilterCache(e,t,n,i){if(e.filters&&e.filters.length>0){const s=Me(e.filters);for(const o of s){const a=fe(o);if(t.has(a))continue;const[u,c]=o.member.split("."),l=n.get(u);if(!l)continue;const m=l.dimensions?.[c];if(!m||["arrayContains","arrayOverlaps","arrayContained"].includes(o.operator))continue;const f=R(m.sql,i),h=this.queryBuilder.buildFilterConditionPublic(f,o.operator,o.values,m,o.dateRange);h&&t.set(a,h)}}if(e.timeDimensions){for(const s of e.timeDimensions)if(s.dateRange){const o=lt(s.dimension,s.dateRange);if(t.has(o))continue;const[a,u]=s.dimension.split("."),c=n.get(a);if(!c)continue;const l=c.dimensions?.[u];if(!l)continue;const m=R(l.sql,i),p=this.queryBuilder.buildDateRangeCondition(m,s.dateRange);p&&t.set(o,p)}}}}const On={name:"drizzle-cube-mcp-guide",description:"How to use drizzle-cube MCP tools to generate and run queries",messages:[{role:"user",content:{type:"text",text:["You are an analyst agent using drizzle-cube MCP.","","Workflow:","1) tools/call name=discover {topic|intent} - Find cubes and understand schema","2) Construct your query using the schema from discover (see cross-cube joins below)","3) tools/call name=validate {query} - Optional: fix schema issues","4) tools/call name=load {query} - Execute and get results","","CRITICAL - CROSS-CUBE JOINS:",'The "joins" property in discover results shows relationships between cubes.',"You can include dimensions from ANY related cube in your query!","Example: If Productivity joins to Employees, query:",'{ "measures": ["Productivity.totalPullRequests"], "dimensions": ["Employees.name"] }',"The system automatically joins the cubes for you.","","Query shapes:","- Regular: { measures, dimensions, filters[], timeDimensions[], order, limit, offset }","- Funnel: { funnel: { bindingKey, timeDimension, steps[], includeTimeMetrics? } }","- Flow: { flow: { bindingKey, eventDimension, steps?, window? } }","- Retention: { retention: { bindingKey, timeDimension, periods, granularity, retentionType, breakdownDimensions } }","","Time handling:",'- For AGGREGATED TOTALS (e.g., "last 3 months"): use filters with inDateRange, NOT timeDimensions','- For TIME SERIES (e.g., "by month"): use timeDimensions with granularity',"- You can combine both when needed","","Filters: flat arrays of { member, operator, values }. Do not nest arrays.","Do NOT hallucinate cube/field names—always use discover first."].join(`
194
+ )`,a=this.databaseAdapter.buildPeriodSeriesSubquery(e.periods),u={period_number:r`p.period_number`.as("period_number"),retained_users:r`COUNT(DISTINCT CASE WHEN ump.max_period >= p.period_number THEN ump.binding_key END)`.as("retained_users")},c=[r`p.period_number`];for(let l=0;l<n;l++)u[`breakdown_${l}`]=r.raw(`ump.breakdown_${l}`).as(`breakdown_${l}`),c.push(r.raw(`ump.breakdown_${l}`));return t.db.select(u).from(r`${o} ump`).crossJoin(a).groupBy(...c)}buildPeriodNumberExpression(e,t,n){return this.databaseAdapter.buildDateDiffPeriods(e,t,n)}extractDimensionName(e){const t=e.split(".");return t.length>1?t[1]:t[0]}}class $n{constructor(e){this.queryPlanner=e}plan(e,t,n){return this.planWithAnalysis(e,t,n).plan}planWithAnalysis(e,t,n){const i=Array.from(this.queryPlanner.analyzeCubeUsage(t));if(i.length===0)throw new Error("No cubes found in query");const s=this.queryPlanner.analyzePrimaryCube(i,t,e),o=s.selectedCube,a=e.get(o);if(!a)throw new Error(`Primary cube '${o}' not found`);const c=i.filter(C=>C!==o).map(C=>this.queryPlanner.analyzeJoinPathForTarget(e,o,C,t)),l=i.length>1?this.queryPlanner.buildJoinPlanForPrimary(e,a,i,n,t):[],m=i.length>1?this.queryPlanner.buildPreAggregationCTEs(e,a,l,t,n)??[]:[],p=this.queryPlanner.buildWarnings(t,m),f=this.buildSourceFromPhases(a,l,m,e,t,n),h=f.source,g=this.buildQueryNode(h,t,e,p),y=this.buildPreAggregationAnalysis(m),b=new Map;for(const C of i){const T=e.get(C);T&&b.set(C,T)}const w=L.hasPostAggregationWindows(t.measures??[],b),$=[...c.filter(C=>!C.pathFound&&C.error).map(C=>C.error),...p.map(C=>C.message)],S={timestamp:new Date().toISOString(),cubeCount:i.length,cubesInvolved:[...i].sort(),primaryCube:s,joinPaths:c,preAggregations:y,querySummary:{queryType:m.length>0?"multi_cube_cte":i.length>1?"multi_cube_join":"single_cube",measureStrategy:f.strategy,joinCount:l.length,cteCount:m.length,hasPreAggregation:m.length>0,hasWindowFunctions:w},warnings:$.length>0?$:void 0,planningTrace:{steps:[{phase:"cube_usage",decision:`Identified ${i.length} cube${i.length===1?"":"s"} from query members`,details:{cubesInvolved:[...i].sort()}},{phase:"primary_cube_selection",decision:`Selected '${s.selectedCube}' as primary cube (${s.reason})`,details:{selectedCube:s.selectedCube,reason:s.reason,candidates:s.candidates?.map(C=>C.cubeName)}},{phase:"join_planning",decision:`Planned ${l.length} join${l.length===1?"":"s"}`,details:{joinCount:l.length,joinTargets:l.map(C=>C.cube.name),pathSelection:c.map(C=>({targetCube:C.targetCube,strategy:C.selection?.strategy,selectedRank:C.selection?.selectedRank,selectedScore:C.selection?.selectedScore}))}},{phase:"cte_planning",decision:`Planned ${m.length} pre-aggregation CTE${m.length===1?"":"s"}`,details:{cteCount:m.length,cubes:m.map(C=>C.cube.name)}},{phase:"measure_strategy",decision:`Selected '${f.strategy}' measure strategy`,details:{strategy:f.strategy,regularMeasures:f.classification.regular.map(C=>C.name),multipliedMeasures:f.classification.multiplied.map(C=>C.name),deduplicationSafeMeasures:f.classification.deduplicationSafe.map(C=>C.name),sourceType:h.type}},{phase:"warnings",decision:p.length>0?`Generated ${p.length} planning warning${p.length===1?"":"s"}`:"No planning warnings generated",details:{warningCodes:p.map(C=>C.code)}}]}};return{plan:g,analysis:S}}buildSourceFromPhases(e,t,n,i,s,o){const a=this.tryBuildMultiFactMergeSource(s,i,o);if(a){const p={regular:this.buildMeasureRefs(s,i),multiplied:[],deduplicationSafe:[]};return{source:a,strategy:"multiFactMerge",classification:p}}const u=this.buildSimpleSourceFromPhases(e,t,n,i,s),c=this.classifyMeasuresForStrategy(u.schema.measures,n),l=this.selectMeasureStrategy(c,s,i);return l==="keysDeduplication"?{source:this.buildKeysDeduplicationSource(u,c),strategy:l,classification:c}:{source:u,strategy:l,classification:c}}buildSimpleSourceFromPhases(e,t,n,i,s){const o=this.buildMeasureRefs(s,i),a=this.buildDimensionRefs(s,i),u=this.buildTimeDimensionRefs(s,i),c=this.toCubeRef(e),l=t.map(f=>({target:this.toCubeRef(f.cube),alias:f.alias,joinType:f.joinType,joinCondition:f.joinCondition,relationship:f.relationship,junctionTable:f.junctionTable})),m=n.map(f=>{const h=this.toCubeRef(f.cube);return{type:"ctePreAggregate",schema:this.buildCTESchema(f,i),cube:h,alias:f.alias,cteAlias:f.cteAlias,joinKeys:f.joinKeys,measures:f.measures,propagatingFilters:f.propagatingFilters,downstreamJoinKeys:f.downstreamJoinKeys,intermediateJoins:f.intermediateJoins,cteType:f.cteType??"aggregate",cteReason:f.cteReason??"hasMany"}});return{type:"simpleSource",schema:{measures:o,dimensions:a,timeDimensions:u},primaryCube:c,joins:l,ctes:m}}tryBuildMultiFactMergeSource(e,t,n){if(!e.measures||e.measures.length<2)return null;const i=new Set;for(const h of e.measures){const[g]=h.split(".");g&&i.add(g)}if(i.size<2)return null;const s=new Set;for(const h of e.dimensions??[]){const[g]=h.split(".");g&&s.add(g)}for(const h of e.timeDimensions??[]){const[g]=h.dimension.split(".");g&&s.add(g)}if(s.size!==1)return null;const o=Array.from(s)[0];if(i.has(o)||!t.get(o))return null;const u=Array.from(i);if(!u.every(h=>this.hasDirectJoinToSharedDimension(t.get(h),o)))return null;const l=this.buildDimensionRefs(e,t),m=this.buildTimeDimensionRefs(e,t),p={measures:this.buildMeasureRefs(e,t),dimensions:l,timeDimensions:m},f=[];for(const h of u){const g=(e.measures??[]).filter($=>$.startsWith(`${h}.`)),y=new Set([h,o]),b={measures:g,dimensions:e.dimensions,timeDimensions:e.timeDimensions,filters:this.projectFiltersToAllowedCubes(e.filters,y)},w=this.buildGroupQueryNode(b,t,n);if(!w)return null;f.push(w)}return f.length<2?null:{type:"multiFactMerge",schema:p,groups:f,sharedDimensions:l,mergeStrategy:"fullJoin"}}hasDirectJoinToSharedDimension(e,t){if(!e?.joins)return!1;for(const[,n]of Object.entries(e.joins)){const i=n.targetCube,s=typeof i=="function"?i():i;if(!(!s||s.name!==t)&&(n.relationship==="belongsTo"||n.relationship==="hasOne"))return!0}return!1}buildGroupQueryNode(e,t,n){const i=Array.from(this.queryPlanner.analyzeCubeUsage(e));if(i.length===0)return null;const s=this.queryPlanner.analyzePrimaryCube(i,e,t),o=t.get(s.selectedCube);if(!o)return null;const a=i.length>1?this.queryPlanner.buildJoinPlanForPrimary(t,o,i,n,e):[],u=i.length>1?this.queryPlanner.buildPreAggregationCTEs(t,o,a,e,n)??[]:[],c=this.queryPlanner.buildWarnings(e,u),l=this.buildSourceFromPhases(o,a,u,t,e,n);return this.buildQueryNode(l.source,e,t,c)}projectFiltersToAllowedCubes(e,t){if(!e||e.length===0)return;const n=e.map(i=>this.projectFilterNodeToAllowedCubes(i,t)).filter(i=>!!i);return n.length>0?n:void 0}projectFilterNodeToAllowedCubes(e,t){if("member"in e){const[n]=e.member.split(".");return n&&t.has(n)?e:null}if("and"in e){const n=(e.and??[]).map(i=>this.projectFilterNodeToAllowedCubes(i,t)).filter(i=>!!i);return n.length===0?null:n.length===1?n[0]:{and:n}}if("or"in e){const n=(e.or??[]).map(i=>this.projectFilterNodeToAllowedCubes(i,t)).filter(i=>!!i);return n.length===0?null:n.length===1?n[0]:{or:n}}return null}classifyMeasuresForStrategy(e,t){const n={regular:[],multiplied:[],deduplicationSafe:[]},i=new Set(t.filter(s=>s.cteReason==="fanOutPrevention").map(s=>s.cube.name));for(const s of e){const o=s.cube.cube,a=o.measures?.[s.localName];if(!a||!i.has(o.name)){n.regular.push(s);continue}this.isDeduplicationSafeMeasure(a)?n.deduplicationSafe.push(s):n.multiplied.push(s)}return n}selectMeasureStrategy(e,t,n){return e.multiplied.length===0?"simple":e.multiplied.every(s=>this.getPrimaryKeyColumns(s.cube.cube).length>0)&&this.isKeysDeduplicationExecutionSupported(e,t,n)?"keysDeduplication":"ctePreAggregateFallback"}isKeysDeduplicationExecutionSupported(e,t,n){const i=new Set(e.multiplied.map(u=>u.cube.name));if(i.size!==1)return!1;const s=Array.from(i)[0],o=t.measures??[];if(o.length===0)return!1;const a=n.get(s);if(!a)return!1;for(const u of o){const[c,l]=u.split(".");if(c!==s){const f=n.get(c)?.measures?.[l];if(!f||!["sum","count","number","min","max"].includes(f.type))return!1;continue}const m=a.measures?.[l];if(!m||!["sum","count","number","min","max","avg"].includes(m.type))return!1}return!this.queryHasMeasureFilter(t,s,a)}queryHasMeasureFilter(e,t,n){const i=o=>{const[a,u]=o.split(".");return a===t&&!!n.measures?.[u]},s=o=>{if(!o)return!1;for(const a of o){if("and"in a){if(s(a.and))return!0;continue}if("or"in a){if(s(a.or))return!0;continue}if("member"in a&&i(a.member))return!0}return!1};return s(e.filters)}buildKeysDeduplicationSource(e,t){const n=this.deduplicateColumnRefs(t.multiplied.flatMap(s=>this.getPrimaryKeyColumns(s.cube.cube))),i=t.regular.length>0?t.regular.map(s=>s.name):void 0;return{type:"keysDeduplication",schema:e.schema,keysSource:e,measureSource:e,joinOn:n,regularMeasures:i}}isDeduplicationSafeMeasure(e){return e.type==="countDistinct"||e.type==="countDistinctApprox"}getPrimaryKeyColumns(e){const t=[];for(const[n,i]of Object.entries(e.dimensions??{}))!i.primaryKey||typeof i.sql=="function"||t.push({column:i.sql,alias:`${e.name}.${n}`});return t}deduplicateColumnRefs(e){const t=new Map;for(const n of e){const i=n.alias??String(n.column?.name??"");t.has(i)||t.set(i,n)}return Array.from(t.values())}buildQueryNode(e,t,n,i){const s=this.buildMeasureRefs(t,n),o=this.buildDimensionRefs(t,n),a=this.buildTimeDimensionRefs(t,n),u=this.buildOrderByRefs(t),c=t.filters??[];return{type:"query",schema:{measures:s,dimensions:o,timeDimensions:a},source:e,dimensions:o,measures:s,filters:c,timeDimensions:a,orderBy:u,limit:t.limit,offset:t.offset,warnings:i}}buildPreAggregationAnalysis(e){return e.map(t=>({cubeName:t.cube.name,cteAlias:t.cteAlias,reason:t.cteReason==="fanOutPrevention"?`Potential fan-out from hasMany joins - pre-aggregate ${t.cube.name} to preserve correctness`:`hasMany relationship requires pre-aggregation for ${t.cube.name}`,reasonType:t.cteReason,measures:t.measures,joinKeys:t.joinKeys.map(n=>({sourceColumn:n.sourceColumn,targetColumn:n.targetColumn})),cteType:t.cteType}))}buildMeasureRefs(e,t){return e.measures?e.measures.map(n=>{const[i,s]=n.split("."),o=t.get(i);if(!o)throw new Error(`Cube '${i}' not found for measure '${n}'`);return{name:n,cube:this.toCubeRef(o),localName:s}}):[]}buildDimensionRefs(e,t){return e.dimensions?e.dimensions.map(n=>{const[i,s]=n.split("."),o=t.get(i);if(!o)throw new Error(`Cube '${i}' not found for dimension '${n}'`);return{name:n,cube:this.toCubeRef(o),localName:s}}):[]}buildTimeDimensionRefs(e,t){return e.timeDimensions?e.timeDimensions.map(n=>{const[i,s]=n.dimension.split("."),o=t.get(i);if(!o)throw new Error(`Cube '${i}' not found for time dimension '${n.dimension}'`);return{name:n.dimension,cube:this.toCubeRef(o),localName:s,granularity:n.granularity,dateRange:n.dateRange,fillMissingDates:n.fillMissingDates,compareDateRange:n.compareDateRange}}):[]}buildOrderByRefs(e){return e.order?Object.entries(e.order).map(([t,n])=>({name:t,direction:n})):[]}toCubeRef(e){return{name:e.name,cube:e}}buildCTESchema(e,t){return{measures:e.measures.map(i=>{const[s,o]=i.split("."),a=t.get(s);return{name:i,cube:{name:s,cube:a},localName:o}}),dimensions:[],timeDimensions:[]}}}class Tn{name="identity";optimise(e){return e}}function En(d,e,t,n){const i=new Map;if(d.preAggregationCTEs&&d.preAggregationCTEs.length>0){for(const u of d.preAggregationCTEs)if(u.propagatingFilters&&u.propagatingFilters.length>0)for(const c of u.propagatingFilters){const l=c.sourceCube.name;if(!i.has(l)){const p={filters:c.filters},f=new Map([[l,c.sourceCube]]),h=n.queryBuilder.buildWhereConditions(f,p,t);i.set(l,h)}const m=i.get(l);m&&m.length>0&&(c.preBuiltFilterSQL=m.length===1?m[0]:A(...m))}}const s=[],o=new Map,a=new Map;if(d.preAggregationCTEs&&d.preAggregationCTEs.length>0)for(const u of d.preAggregationCTEs){const c=n.cteBuilder.buildPreAggregationCTE(u,e,t,d,i);if(c&&(s.push(c),o.set(u.cube.name,u.cteAlias),u.downstreamJoinKeys))for(const l of u.downstreamJoinKeys)a.set(l.targetCubeName,{cteAlias:u.cteAlias,joinKeys:l.joinKeys})}return{preBuiltFilterMap:i,ctes:s,cteAliasMap:o,downstreamCubeMap:a}}function Sn(d,e,t,n,i,s){if(t.measures)for(const o of t.measures){const[a,u]=o.split("."),c=i.get(a);if(!c?.measures?.[u])continue;const l=c.measures[u];if(!L.isPostAggregationWindow(l))continue;const m=L.getWindowBaseMeasure(l,a);if(!m)continue;const[p,f]=m.split("."),h=i.get(p);if(!h?.measures?.[f])continue;const g=h.measures[f],y=e.preAggregationCTEs?.find($=>$.cube?.name===p&&$.measures?.includes(m));let b;if(y){const $=r`${r.identifier(y.cteAlias)}.${r.identifier(f)}`;b=r`sum(${$})`}else b=s.queryBuilder.buildMeasureExpression(g,n,h);d[m]||(d[m]=r`${b}`.as(m));const w=Dn(l,b,t,n,c,e,s);w&&(d[o]=r`${w}`.as(o))}}function Dn(d,e,t,n,i,s,o){const a=d.windowConfig||{},u=(f,h)=>{if(!s.preAggregationCTEs)return null;const g=s.preAggregationCTEs.find(y=>y.cube?.name===f);return g&&g.cteAlias?r`${r.identifier(g.cteAlias)}.${r.identifier(h)}`:null};let c;if(a.orderBy&&a.orderBy.length>0)c=a.orderBy.map(f=>{const h=f.field.includes(".")?f.field.split(".")[1]:f.field;if(t.timeDimensions)for(const b of t.timeDimensions){const[w,$]=b.dimension.split(".");if($===h){const S=u(w,h);if(S)return{field:S,direction:f.direction};const C=i.dimensions?.[$];if(C)return{field:o.queryBuilder.buildTimeDimensionExpression(C.sql,b.granularity,n),direction:f.direction}}}const g=i.dimensions?.[h];if(g)return{field:R(g.sql,n),direction:f.direction};const y=a.measure?.includes(".")?a.measure.split(".")[1]:a.measure;return h===y||f.field===a.measure?{field:e,direction:f.direction}:null}).filter(f=>f!==null);else if(t.timeDimensions&&t.timeDimensions.length>0){const f=t.timeDimensions[0],[h,g]=f.dimension.split("."),y=u(h,g);if(y)c=[{field:y,direction:"asc"}];else{const b=i.name===h?i:void 0;if(b?.dimensions?.[g]){const w=b.dimensions[g];c=[{field:o.queryBuilder.buildTimeDimensionExpression(w.sql,f.granularity,n),direction:"asc"}]}}}let l;a.partitionBy&&a.partitionBy.length>0&&(l=a.partitionBy.map(f=>{const h=f.includes(".")?f.split(".")[1]:f,g=i.dimensions?.[h];return g?R(g.sql,n):null}).filter(f=>f!==null));const m=o.databaseAdapter.buildWindowFunction(d.type,e,l,c,{offset:a.offset,defaultValue:a.defaultValue,nTile:a.nTile,frame:a.frame});if(!m)return null;switch(a.operation||L.getDefaultWindowOperation(d.type)){case"difference":return r`${e} - ${m}`;case"ratio":return r`${e} / NULLIF(${m}, 0)`;case"percentChange":return r`((${e} - ${m}) / NULLIF(${m}, 0)) * 100`;default:return m}}function Nn(d,e,t,n,i){const o={...i.queryBuilder.buildSelections(d.joinCubes.length>0?n:d.primaryCube,e,t)};if(d.preAggregationCTEs)for(const a of d.preAggregationCTEs){const u=a.cube.name;for(const c of a.measures){if(!o[c])continue;const[,l]=c.split("."),m=n.get(u);if(!m?.measures?.[l])continue;const p=m.measures[l],f=r`${r.identifier(a.cteAlias)}.${r.identifier(l)}`;let h;if(p.type==="calculated"&&p.calculatedSql)h=i.queryBuilder.buildCTECalculatedMeasure(p,m,a,n,t);else{const g=a.cteReason==="fanOutPrevention",y=An(a,e,n),b=g||y;switch(p.type){case"count":case"countDistinct":case"sum":h=b?H(f):V(f);break;case"avg":h=b?H(f):i.databaseAdapter.buildAvg(f);break;case"min":h=ae(f);break;case"max":h=H(f);break;case"number":h=H(f);break;default:h=b?H(f):V(f)}}o[c]=r`${h}`.as(c)}for(const c in o){const[l,m]=c.split(".");if(l!==u)continue;const p=n.get(u),f=p&&p.dimensions?.[m],h=c.startsWith(u+".");if(!f&&!h)continue;let g=a.joinKeys.find(y=>y.targetColumn===m);if(!g&&p?.dimensions?.[m]){const y=p.dimensions[m].sql;g=a.joinKeys.find(b=>b.targetColumnObj===y)}g?o[c]=r`${r.identifier(a.cteAlias)}.${r.identifier(m)}`.as(c):h&&p?.dimensions?.[m]&&(o[c]=r`${r.identifier(a.cteAlias)}.${r.identifier(m)}`.as(c))}}return Sn(o,d,e,t,n,i),o}function An(d,e,t){return d.cteReason!=="hasMany"||d.downstreamJoinKeys&&d.downstreamJoinKeys.length>0||d.intermediateJoins&&d.intermediateJoins.length>0||!!!(e.dimensions&&e.dimensions.length>0||e.timeDimensions&&e.timeDimensions.length>0)||!!(e.dimensions?.some(s=>s.startsWith(`${d.cube.name}.`))||e.timeDimensions?.some(s=>s.dimension.startsWith(`${d.cube.name}.`)))?!1:d.joinKeys.length>0&&d.joinKeys.every(s=>!!s.sourceColumnObj&&_n(s.sourceColumnObj,e,t))}function _n(d,e,t){if(e.dimensions)for(const n of e.dimensions){const[i,s]=n.split(".");if(t.get(i)?.dimensions?.[s]?.sql===d)return!0}if(e.timeDimensions)for(const n of e.timeDimensions){if(n.granularity)continue;const[i,s]=n.dimension.split(".");if(t.get(i)?.dimensions?.[s]?.sql===d)return!0}return!1}function vn(d,e,t,n,i,s){const o=[];let a=e.db.select(n).from(t.from);if(i.ctes.length>0&&(a=e.db.with(...i.ctes).select(n).from(t.from)),t.joins)for(const l of t.joins)switch(l.type||"left"){case"left":a=a.leftJoin(l.table,l.on);break;case"inner":a=a.innerJoin(l.table,l.on);break;case"right":a=a.rightJoin(l.table,l.on);break;case"full":a=a.fullJoin(l.table,l.on);break}const u=new Set,c=new Set;if(d.preAggregationCTEs){for(const l of d.preAggregationCTEs)if(l.intermediateJoins&&l.intermediateJoins.length>0)for(const m of l.intermediateJoins)c.add(m.cube.name)}if(d.joinCubes&&d.joinCubes.length>0)for(const l of d.joinCubes){const m=l.cube.name;if(c.has(m)&&!i.cteAliasMap.has(m))continue;const p=i.cteAliasMap.get(l.cube.name);if(l.junctionTable){const w=l.junctionTable;let $=w.joinCondition;const S=w.sourceCubeName?i.cteAliasMap.get(w.sourceCubeName):void 0;if(S){const D=d.preAggregationCTEs?.find(N=>N.cube.name===w.sourceCubeName)?.downstreamJoinKeys?.find(N=>N.targetCubeName===l.cube.name);if(D&&D.joinKeys.length>0){const N=[];for(const M of D.joinKeys){const v=r`${r.identifier(S)}.${r.identifier(M.sourceColumn)}`,U=M.targetColumnObj;U&&N.push(k(U,v))}N.length>0&&($=A(...N))}}const C=[];if(w.securitySql){const T=w.securitySql(e.securityContext);Array.isArray(T)?C.push(...T):C.push(T)}try{switch(w.joinType||"left"){case"left":a=a.leftJoin(w.table,$);break;case"inner":a=a.innerJoin(w.table,$);break;case"right":a=a.rightJoin(w.table,$);break;case"full":a=a.fullJoin(w.table,$);break}C.length>0&&o.push(...C)}catch{}}let f,h,g;if(p)f=r`${r.identifier(p)}`,h=s.cteBuilder.buildCTEJoinCondition(l,p,d),g=void 0;else{const w=i.downstreamCubeMap.get(l.cube.name),$=l.cube.sql(e);if(f=$.from,g=$.where,w&&!l.junctionTable){const S=[];for(const C of w.joinKeys){const T=r`${r.identifier(w.cteAlias)}.${r.identifier(C.sourceColumn)}`,D=C.targetColumnObj||r.identifier(C.targetColumn);S.push(k(T,D))}h=S.length===1?S[0]:A(...S)}else h=l.joinCondition}const y=l.joinType||"left",b=y!=="inner"&&g?A(h,g):h;try{switch(y){case"left":a=a.leftJoin(f,b),g&&u.add(l.cube.name);break;case"inner":a=a.innerJoin(f,h);break;case"right":a=a.rightJoin(f,b),g&&u.add(l.cube.name);break;case"full":a=a.fullJoin(f,b),g&&u.add(l.cube.name);break}}catch{}}return{drizzleQuery:a,allWhereConditions:o,cubesWithSecurityInJoin:u,absorbedIntermediateCubes:c}}function Rn(d,e,t,n,i,s,o,a){const u=[...o.allWhereConditions];if(i.where&&u.push(i.where),d.joinCubes&&d.joinCubes.length>0)for(const h of d.joinCubes){const g=h.cube.name;if(s.cteAliasMap.get(g)||o.absorbedIntermediateCubes.has(g)||o.cubesWithSecurityInJoin.has(g))continue;const b=h.cube.sql(t);b.where&&u.push(b.where)}const c=a.queryBuilder.buildWhereConditions(d.joinCubes.length>0?n:d.primaryCube,e,t,d,s.preBuiltFilterMap);c.length>0&&u.push(...c);let l=o.drizzleQuery;if(u.length>0){const h=u.length===1?u[0]:A(...u);l=l.where(h)}const m=a.queryBuilder.buildGroupByFields(d.joinCubes.length>0?n:d.primaryCube,e,t,d);m.length>0&&(l=l.groupBy(...m));const p=a.queryBuilder.buildHavingConditions(d.joinCubes.length>0?n:d.primaryCube,e,t,d);if(p.length>0){const h=p.length===1?p[0]:A(...p);l=l.having(h)}const f=a.queryBuilder.buildOrderBy(e);return f.length>0&&(l=l.orderBy(...f)),l=a.queryBuilder.applyLimitAndOffset(l,e),l}function tt(d){const e=new Map;if(e.set(d.primaryCube.name,d.primaryCube),d.joinCubes)for(const t of d.joinCubes)e.set(t.cube.name,t.cube);return e}class Fn{constructor(e,t,n){this.queryBuilder=e,this.cteBuilder=t,this.databaseAdapter=n}derivePhysicalPlanContext(e){const t=e.source;if(t.type==="multiFactMerge")return this.derivePhysicalPlanContextFromMultiFact(e,t);if(t.type==="fullKeyAggregate")return this.derivePhysicalPlanContextFromFullKeyAggregate(e,t);const n=this.resolvePhysicalSimpleSource(t),i=this.resolveKeysDeduplicationMeta(t);return{primaryCube:n.primaryCube.cube,joinCubes:n.joins.map(s=>({cube:s.target.cube,alias:s.alias,joinType:s.joinType,joinCondition:s.joinCondition,junctionTable:s.junctionTable})),preAggregationCTEs:n.ctes.map(s=>({cube:s.cube.cube,alias:s.alias,cteAlias:s.cteAlias,joinKeys:s.joinKeys,measures:s.measures,propagatingFilters:s.propagatingFilters,downstreamJoinKeys:s.downstreamJoinKeys,intermediateJoins:s.intermediateJoins,cteType:s.cteType,cteReason:s.cteReason})),keysDeduplication:i,warnings:e.warnings.length>0?e.warnings:void 0}}derivePhysicalPlanContextFromMultiFact(e,t){const n=t.groups.map((s,o)=>{if(s.type!=="query")return null;const a=s,u=this.derivePhysicalPlanContext(a),c=this.toSemanticQuery(a);return{alias:`mf_group_${o+1}`,query:c,queryPlan:u,measures:c.measures??[]}}).filter(s=>!!s);if(n.length===0)throw new Error("multiFactMerge requires at least one query group");const i=n[0];return{primaryCube:i.queryPlan.primaryCube,joinCubes:i.queryPlan.joinCubes,preAggregationCTEs:i.queryPlan.preAggregationCTEs,warnings:e.warnings.length>0?e.warnings:void 0,multiFactMerge:{mergeStrategy:t.mergeStrategy,sharedDimensions:t.sharedDimensions.map(s=>s.name),groups:n}}}derivePhysicalPlanContextFromFullKeyAggregate(e,t){const n=t.subqueries.map((s,o)=>{if(s.type!=="query")throw new Error("fullKeyAggregate currently requires query subqueries");const a=s,u=this.derivePhysicalPlanContext(a),c=this.toSemanticQuery(a);return{alias:`fka_group_${o+1}`,query:c,queryPlan:u,measures:c.measures??[]}});if(n.length===0)throw new Error("fullKeyAggregate requires at least one subquery");const i=n[0];return{primaryCube:i.queryPlan.primaryCube,joinCubes:i.queryPlan.joinCubes,preAggregationCTEs:i.queryPlan.preAggregationCTEs,warnings:e.warnings.length>0?e.warnings:void 0,multiFactMerge:{mergeStrategy:"fullJoin",sharedDimensions:t.dimensions.map(s=>s.name),groups:n}}}toSemanticQuery(e){const t=e.orderBy.length>0?Object.fromEntries(e.orderBy.map(n=>[n.name,n.direction])):void 0;return{measures:e.measures.map(n=>n.name),dimensions:e.dimensions.map(n=>n.name),timeDimensions:e.timeDimensions.map(n=>({dimension:n.name,granularity:n.granularity,dateRange:n.dateRange,fillMissingDates:n.fillMissingDates,compareDateRange:n.compareDateRange})),filters:e.filters,order:t,limit:e.limit,offset:e.offset}}resolvePhysicalSimpleSource(e){switch(e.type){case"simpleSource":return e;case"keysDeduplication":return this.resolvePhysicalSimpleSourceFromKeysDedup(e);default:throw new Error(`Current SQL builder does not support logical node '${e.type}' in physical conversion`)}}resolvePhysicalSimpleSourceFromKeysDedup(e){const t=e.measureSource;if(t.type==="simpleSource")return t;const n=e.keysSource;if(n.type==="simpleSource")return n;throw new Error("keysDeduplication requires at least one simpleSource child for SQL physical conversion")}resolveKeysDeduplicationMeta(e){if(e.type!=="keysDeduplication")return;const t=e,n=new Set;for(const s of t.joinOn){if(!s.alias)continue;const[o,a]=s.alias.split(".");o&&a&&n.add(o)}const i=n.size===1?Array.from(n)[0]:"";return i?{multipliedCubeName:i,primaryKeyDimensions:t.joinOn.map(s=>s.alias?.split(".")[1]??"").filter(Boolean),regularMeasures:t.regularMeasures}:void 0}build(e,t,n){const i={queryBuilder:this.queryBuilder,cteBuilder:this.cteBuilder,databaseAdapter:this.databaseAdapter},s=this.tryBuildMultiFactMergeQuery(e,t,n,i);if(s)return s;const o=this.tryBuildKeysDeduplicationQuery(e,t,n,i);if(o)return o;const a=En(e,t,n,i),u=e.primaryCube.sql(n),c=e.joinCubes.length>0?tt(e):new Map([[e.primaryCube.name,e.primaryCube]]),l=Nn(e,t,n,c,i),m=vn(e,n,u,l,a,i);return Rn(e,t,n,c,u,a,m,i)}tryBuildKeysDeduplicationQuery(e,t,n,i){const s=e.keysDeduplication;if(!s?.multipliedCubeName||!t.measures?.length)return null;const o=e.joinCubes.length>0?tt(e):new Map([[e.primaryCube.name,e.primaryCube]]),a=o.get(s.multipliedCubeName);if(!a||!this.canExecuteKeysDeduplication(t,a,s.multipliedCubeName))return null;const u=s.primaryKeyDimensions.length>0?s.primaryKeyDimensions:this.getPrimaryKeyDimensions(a);if(u.length===0)return null;const c=`${s.multipliedCubeName.toLowerCase()}_keys`,l=`${s.multipliedCubeName.toLowerCase()}_pk_agg`,m={},p=[];if(t.dimensions)for(const E of t.dimensions){const[_,F]=E.split("."),j=o.get(_),W=j?.dimensions?.[F];if(!j||!W)return null;const J=R(W.sql,n);m[E]=r`${J}`.as(E),p.push(J)}if(t.timeDimensions)for(const E of t.timeDimensions){const[_,F]=E.dimension.split("."),j=o.get(_),W=j?.dimensions?.[F];if(!j||!W)return null;const J=i.queryBuilder.buildTimeDimensionExpression(W.sql,E.granularity,n);m[E.dimension]=r`${J}`.as(E.dimension),p.push(J)}const f=[];for(const E of u){const _=a.dimensions?.[E];if(!_)return null;const F=R(_.sql,n),j=`__pk__${E}`;m[j]=r`${F}`.as(j),p.push(F),f.push(j)}const h=s.regularMeasures??[],g=new Set(h),y=t.measures.filter(E=>!g.has(E));if(h.length>0){const E=i.queryBuilder.buildResolvedMeasures(h,o,n);for(const _ of h){const F=E.get(_);if(!F)return null;const j=`__reg__${_.replace(".","__")}`;m[j]=r`${F()}`.as(j)}}const b=e.primaryCube.sql(n),w=[];b.where&&w.push(b.where);let $=n.db.select(m).from(b.from);if(b.joins)for(const E of b.joins)$=this.applyJoinByType($,E.type??"left",E.table,E.on);for(const E of e.joinCubes){if(E.junctionTable&&($=this.applyJoinByType($,E.junctionTable.joinType??"left",E.junctionTable.table,E.junctionTable.joinCondition),E.junctionTable.securitySql)){const F=E.junctionTable.securitySql(n.securityContext);Array.isArray(F)?w.push(...F):w.push(F)}const _=E.cube.sql(n);$=this.applyJoinByType($,E.joinType??"left",_.from,E.joinCondition),_.where&&w.push(_.where)}w.push(...i.queryBuilder.buildWhereConditions(o,t,n)),w.length>0&&($=$.where(w.length===1?w[0]:A(...w))),p.length>0&&($=$.groupBy(...p));const S=n.db.$with(c).as($),C=a.sql(n),T={},D=[];for(const E of u){const _=a.dimensions?.[E];if(!_)return null;const F=R(_.sql,n);T[E]=r`${F}`.as(E),D.push(F)}const N=new Set;for(const E of y){const[,_]=E.split(".");a.measures?.[_]?.type==="avg"&&N.add(_)}const M=y.filter(E=>{const[,_]=E.split(".");return!N.has(_)});if(M.length>0){const E=i.queryBuilder.buildResolvedMeasures(M,new Map([[a.name,a]]),n);for(const _ of M){const[,F]=_.split("."),j=E.get(_);if(!j)return null;T[F]=r`${j()}`.as(F)}}for(const E of y){const[,_]=E.split(".");if(!N.has(_))continue;const F=a.measures?.[_];if(!F?.sql)return null;const j=R(F.sql,n),W=`__avg_sum__${_}`,J=`__avg_count__${_}`;T[W]=r`sum(${j})`.as(W),T[J]=r`count(${j})`.as(J)}let v=n.db.select(T).from(C.from);const U=[];C.where&&U.push(C.where),U.push(...i.queryBuilder.buildWhereConditions(a,t,n)),U.length>0&&(v=v.where(U.length===1?U[0]:A(...U))),D.length>0&&(v=v.groupBy(...D));const bt=n.db.$with(l).as(v),Z={};for(const E of t.dimensions??[])Z[E]=r`${r.identifier(c)}.${r.identifier(E)}`.as(E);for(const E of t.timeDimensions??[])Z[E.dimension]=r`${r.identifier(c)}.${r.identifier(E.dimension)}`.as(E.dimension);for(const E of y){const[,_]=E.split("."),F=a.measures?.[_];Z[E]=this.buildKeysOuterAggregation(F?.type??"sum",l,_,E)}for(const E of h){const[_,F]=E.split("."),W=o.get(_)?.measures?.[F],J=`__reg__${E.replace(".","__")}`;Z[E]=this.buildKeysOuterAggregation(W?.type??"sum",c,J,E)}let q=n.db.with(S,bt).select(Z).from(r`${r.identifier(c)}`);const ye=f.map((E,_)=>k(r`${r.identifier(c)}.${r.identifier(E)}`,r`${r.identifier(l)}.${r.identifier(u[_])}`)),yt=ye.length===1?ye[0]:A(...ye);q=q.leftJoin(r`${r.identifier(l)}`,yt);const Ie=[...(t.dimensions??[]).map(E=>r`${r.identifier(c)}.${r.identifier(E)}`),...(t.timeDimensions??[]).map(E=>r`${r.identifier(c)}.${r.identifier(E.dimension)}`)];Ie.length>0&&(q=q.groupBy(...Ie));const je=i.queryBuilder.buildOrderBy(t,Object.keys(Z));return je.length>0&&(q=q.orderBy(...je)),q=i.queryBuilder.applyLimitAndOffset(q,t),q}tryBuildMultiFactMergeQuery(e,t,n,i){const s=e.multiFactMerge;if(!s||s.groups.length<2)return null;const o=[...t.dimensions??[],...(t.timeDimensions??[]).map(b=>b.dimension)],a=Array.from(new Set(o)),u=a.length>0&&s.mergeStrategy==="fullJoin"&&!this.supportsFullOuterJoin(),c=this.selectRuntimeMergeStrategy(s.mergeStrategy,a.length>0),l=s.groups.map(b=>{const w=this.build(b.queryPlan,b.query,n);return n.db.$with(b.alias).as(w)});if(u)return this.buildMultiFactUnionKeysFallbackQuery(t,n,i,s,l,a);const m=s.groups[0].alias,p=s.groups.map(b=>b.alias),f={};if(a.length>0)for(const b of a){const w=this.coalesceQualifiedColumn(p,b);f[b]=r`${w}`.as(b)}for(const b of s.groups)for(const w of b.measures){const $=r`${r.identifier(b.alias)}.${r.identifier(w)}`;f[w]=r`coalesce(${$}, 0)`.as(w)}let h=n.db.with(...l).select(f).from(r`${r.identifier(m)}`),g=new Map;for(const b of a)g.set(b,r`${r.identifier(m)}.${r.identifier(b)}`);for(let b=1;b<s.groups.length;b++){const w=s.groups[b].alias;let $;if(a.length===0)$=r`1 = 1`;else{const S=a.map(C=>k(g.get(C),r`${r.identifier(w)}.${r.identifier(C)}`));$=S.length===1?S[0]:A(...S)}if(h=this.applyJoinByType(h,c,r`${r.identifier(w)}`,$),a.length>0&&c==="full")for(const S of a)g.set(S,r`coalesce(${g.get(S)}, ${r`${r.identifier(w)}.${r.identifier(S)}`})`)}const y=i.queryBuilder.buildOrderBy(t,Object.keys(f));return y.length>0&&(h=h.orderBy(...y)),i.queryBuilder.applyLimitAndOffset(h,t)}buildMultiFactUnionKeysFallbackQuery(e,t,n,i,s,o){const a="mf_all_keys",u=i.groups.map(h=>r`select ${this.buildSharedKeySelection(h.alias,o)} from ${r.identifier(h.alias)}`),c=r`${r.join(u,r` union `)}`,l=t.db.$with(a).as(c),m={};for(const h of o)m[h]=r`${r.identifier(a)}.${r.identifier(h)}`.as(h);for(const h of i.groups)for(const g of h.measures){const y=r`${r.identifier(h.alias)}.${r.identifier(g)}`;m[g]=r`coalesce(${y}, 0)`.as(g)}let p=t.db.with(...s,l).select(m).from(r`${r.identifier(a)}`);for(const h of i.groups){const g=o.map(b=>k(r`${r.identifier(a)}.${r.identifier(b)}`,r`${r.identifier(h.alias)}.${r.identifier(b)}`)),y=g.length===1?g[0]:A(...g);p=p.leftJoin(r`${r.identifier(h.alias)}`,y)}const f=n.queryBuilder.buildOrderBy(e,Object.keys(m));return f.length>0&&(p=p.orderBy(...f)),n.queryBuilder.applyLimitAndOffset(p,e)}buildSharedKeySelection(e,t){const n=t.map(i=>r`${r.identifier(e)}.${r.identifier(i)} as ${r.identifier(i)}`);return r.join(n,r`, `)}selectRuntimeMergeStrategy(e,t){return!t||e==="innerJoin"?"inner":e==="leftJoin"?"left":this.supportsFullOuterJoin()?"full":"left"}supportsFullOuterJoin(){const e=this.databaseAdapter.getEngineType();return e==="postgres"||e==="duckdb"}coalesceQualifiedColumn(e,t){if(e.length===1)return r`${r.identifier(e[0])}.${r.identifier(t)}`;const n=e.map(s=>r`${r.identifier(s)}.${r.identifier(t)}`);let i=n[0];for(let s=1;s<n.length;s++)i=r`coalesce(${i}, ${n[s]})`;return i}canExecuteKeysDeduplication(e,t,n){if(!e.measures?.length)return!1;for(const i of e.measures){const[s,o]=i.split(".");if(s!==n)continue;const a=t.measures?.[o];if(!a||!["sum","count","number","min","max","avg"].includes(a.type))return!1}return!this.queryContainsMeasureFilter(e,t,n)}queryContainsMeasureFilter(e,t,n){const i=s=>{if(!s)return!1;for(const o of s){if("and"in o){if(i(o.and))return!0;continue}if("or"in o){if(i(o.or))return!0;continue}if("member"in o){const[a,u]=o.member.split(".");if(a===n&&t.measures?.[u])return!0}}return!1};return i(e.filters)}getPrimaryKeyDimensions(e){return Object.entries(e.dimensions??{}).filter(([,t])=>!!t.primaryKey).map(([t])=>t)}buildKeysOuterAggregation(e,t,n,i){switch(e){case"min":{const s=r`${r.identifier(t)}.${r.identifier(n)}`;return r`min(${s})`.as(i)}case"max":{const s=r`${r.identifier(t)}.${r.identifier(n)}`;return r`max(${s})`.as(i)}case"avg":{const s=r`${r.identifier(t)}.${r.identifier(`__avg_sum__${n}`)}`,o=r`${r.identifier(t)}.${r.identifier(`__avg_count__${n}`)}`;return r`sum(${s}) / nullif(sum(${o}), 0)`.as(i)}default:{const s=r`${r.identifier(t)}.${r.identifier(n)}`;return r`coalesce(sum(${s}), 0)`.as(i)}}}applyJoinByType(e,t,n,i){switch(t){case"inner":return e.innerJoin(n,i);case"right":return e.rightJoin(n,i);case"full":return e.fullJoin(n,i);default:return e.leftJoin(n,i)}}}class Mn{constructor(e,t){if(this.dbExecutor=e,this.databaseAdapter=e.databaseAdapter,!this.databaseAdapter)throw new Error("DatabaseExecutor must have a databaseAdapter property");this.queryBuilder=new un(this.databaseAdapter);const n=new ln,i=new cn(this.queryBuilder);this.drizzlePlanBuilder=new Fn(this.queryBuilder,i,this.databaseAdapter),this.comparisonQueryBuilder=new bn(this.databaseAdapter),this.funnelQueryBuilder=new yn(this.databaseAdapter),this.flowQueryBuilder=new Cn(this.databaseAdapter),this.retentionQueryBuilder=new wn(this.databaseAdapter),this.logicalPlanBuilder=new $n(n),this.planOptimiser=new Tn,this.cacheConfig=t}queryBuilder;drizzlePlanBuilder;databaseAdapter;comparisonQueryBuilder;funnelQueryBuilder;flowQueryBuilder;retentionQueryBuilder;cacheConfig;logicalPlanBuilder;planOptimiser;async execute(e,t,n,i){try{const s=this.resolveQueryMode(t);this.validateQueryForMode(s,e,t);let o;if(this.cacheConfig?.enabled!==!1&&this.cacheConfig?.provider)if(o=Xt(t,n,this.cacheConfig),i?.skipCache)this.cacheConfig.onCacheEvent?.({type:"miss",key:o,durationMs:0});else try{const a=Date.now(),u=await this.cacheConfig.provider.get(o);if(u)return this.cacheConfig.onCacheEvent?.({type:"hit",key:o,durationMs:Date.now()-a}),{...u.value,cache:u.metadata?{hit:!0,cachedAt:new Date(u.metadata.cachedAt).toISOString(),ttlMs:u.metadata.ttlMs,ttlRemainingMs:u.metadata.ttlRemainingMs}:{hit:!0,cachedAt:new Date().toISOString(),ttlMs:0,ttlRemainingMs:0}};this.cacheConfig.onCacheEvent?.({type:"miss",key:o,durationMs:Date.now()-a})}catch(a){this.cacheConfig.onError?.(a,"get")}return await this.executeQueryByModeWithCache(s,e,t,n,o)}catch(s){if(s instanceof Error){let o=s;for(;o.cause instanceof Error;)o=o.cause;let a=o.message;const u=o;throw u.code&&(a+=` [${u.code}]`),u.detail&&(a+=` Detail: ${u.detail}`),u.hint&&(a+=` Hint: ${u.hint}`),s.message=`Query execution failed: ${a}`,s}throw new Error("Query execution failed: Unknown error")}}buildLogicalPlan(e,t,n){const i=new ne,s=this.createQueryContext(n,i);return this.preloadFilterCache(t,i,e,s),this.buildRegularQueryArtifacts(e,t,s).optimisedPlan}analyzeQuery(e,t,n){const i=new ne,s=this.createQueryContext(n,i);return this.preloadFilterCache(t,i,e,s),this.buildRegularQueryArtifacts(e,t,s).analysis}async executeQuery(e,t,n){const i=new Map;return i.set(e.name,e),this.execute(i,t,n)}async executeComparisonQueryWithCache(e,t,n,i){const s=await this.executeComparisonQuery(e,t,n);return await this.cacheResult(i,s),s}async executeComparisonQuery(e,t,n){const i=this.buildComparisonExecutionPlan(t),{timeDimension:s,periods:o,granularity:a,periodQueries:u}=i,c=u.map(async(p,f)=>({result:await this.executeStandardQuery(e,p,n),period:o[f]})),l=await Promise.all(c),m=this.comparisonQueryBuilder.mergeComparisonResults(l,s,a);return m.data=this.comparisonQueryBuilder.sortComparisonResults(m.data,s.dimension),m}buildComparisonExecutionPlan(e){const t=this.comparisonQueryBuilder.getComparisonTimeDimension(e);if(!t||!t.compareDateRange)throw new Error("No compareDateRange found in query");const n=this.comparisonQueryBuilder.normalizePeriods(t.compareDateRange);if(n.length<2)throw new Error("compareDateRange requires at least 2 periods");const i=n.map(s=>this.comparisonQueryBuilder.createPeriodQuery(e,s));return{timeDimension:t,granularity:t.granularity||"day",periods:n,periodQueries:i}}async executeFunnelQueryWithCache(e,t,n,i){const s=await this.executeFunnelQuery(e,t,n);return await this.cacheResult(i,s),{...s,cache:{hit:!1}}}async executeFunnelQuery(e,t,n){const i=t.funnel,s=this.funnelQueryBuilder.validateConfig(i,e);if(!s.isValid)throw new Error(`Funnel validation failed: ${s.errors.join(", ")}`);const o={db:this.dbExecutor.db,schema:this.dbExecutor.schema,securityContext:n},u=await this.funnelQueryBuilder.buildFunnelQuery(i,e,o),c=this.funnelQueryBuilder.transformResult(u,i),l={measures:{},dimensions:{},segments:{},timeDimensions:{}};return l.funnel={config:i,steps:i.steps.map((m,p)=>({name:m.name,index:p,timeToConvert:m.timeToConvert}))},{data:c,annotation:l}}async executeFlowQueryWithCache(e,t,n,i){const s=await this.executeFlowQuery(e,t,n);return await this.cacheResult(i,s),{...s,cache:{hit:!1}}}async executeFlowQuery(e,t,n){const i=t.flow,s=this.flowQueryBuilder.validateConfig(i,e);if(!s.isValid)throw new Error(`Flow validation failed: ${s.errors.join(", ")}`);const o={db:this.dbExecutor.db,schema:this.dbExecutor.schema,securityContext:n},u=await this.flowQueryBuilder.buildFlowQuery(i,e,o),c=this.flowQueryBuilder.transformResult(u),l={measures:{},dimensions:{},segments:{},timeDimensions:{}};return l.flow={config:i,startingStep:{name:i.startingStep.name},stepsBefore:i.stepsBefore,stepsAfter:i.stepsAfter},{data:[c],annotation:l}}async executeRetentionQueryWithCache(e,t,n,i){const s=await this.executeRetentionQuery(e,t,n);return await this.cacheResult(i,s),{...s,cache:{hit:!1}}}async executeRetentionQuery(e,t,n){const i=t.retention,s=this.retentionQueryBuilder.validateConfig(i,e);if(!s.isValid)throw new Error(`Retention validation failed: ${s.errors.join(", ")}`);const o={db:this.dbExecutor.db,schema:this.dbExecutor.schema,securityContext:n},u=await this.retentionQueryBuilder.buildRetentionQuery(i,e,o),c=this.retentionQueryBuilder.transformResult(u,i),l={measures:{},dimensions:{},segments:{},timeDimensions:{}};return l.retention={config:i,granularity:i.granularity,periods:i.periods,retentionType:i.retentionType,breakdownDimensions:i.breakdownDimensions},{data:c,annotation:l}}async executeStandardQuery(e,t,n){const i=new ne,s=this.createQueryContext(n,i);this.preloadFilterCache(t,i,e,s);const{optimisedPlan:o}=this.buildRegularQueryArtifacts(e,t,s),a=this.drizzlePlanBuilder.derivePhysicalPlanContext(o),u=this.drizzlePlanBuilder.build(a,t,s),c=this.queryBuilder.collectNumericFields(e,t),l=await this.dbExecutor.execute(u,c),m=Array.isArray(l)?l.map(g=>{const y={...g};if(t.timeDimensions){for(const b of t.timeDimensions)if(b.dimension in y){let w=y[b.dimension];if(typeof w=="string"&&w.match(/^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}/)){const $=w.replace(" ","T"),S=!$.endsWith("Z")&&!$.includes("+")?$+"Z":$;w=new Date(S)}w=this.databaseAdapter.convertTimeDimensionResult(w),y[b.dimension]=w}}return y}):[l],p=t.measures||[],f=Ye(m,t,p),h=this.generateAnnotations(a,t);return{data:f,annotation:h}}createQueryContext(e,t){return{db:this.dbExecutor.db,schema:this.dbExecutor.schema,securityContext:e,filterCache:t}}getOptimiserEngineType(){const e=this.dbExecutor.getEngineType?.();return e==="singlestore"?"mysql":e??"postgres"}buildRegularQueryArtifacts(e,t,n){const i=this.logicalPlanBuilder.planWithAnalysis(e,t,n),s=this.planOptimiser.optimise(i.plan,{engineType:this.getOptimiserEngineType()});return{logicalPlan:i.plan,analysis:i.analysis,optimisedPlan:s}}validateSecurityContext(e,t){const n=typeof process<"u"?process.env?.NODE_ENV:void 0,i=typeof process<"u"?process.env?.DRIZZLE_CUBE_WARN_SECURITY:void 0;if(n!=="development"&&!i)return;const s=[e.primaryCube];for(const a of e.joinCubes||[])s.push(a.cube);for(const a of e.preAggregationCTEs||[])s.push(a.cube);const o=new Set;for(const a of s)if(!o.has(a.name)){o.add(a.name);try{if(a.public)continue;a.sql(t).where||console.warn(`[drizzle-cube] WARNING: Cube '${a.name}' has no security filtering. If this cube contains public data, add 'public: true' to suppress this warning. Otherwise, ensure sql() returns: { from: table, where: eq(table.orgId, ctx.securityContext.orgId) }`)}catch{}}}async generateSQL(e,t,n){const i=new Map;return i.set(e.name,e),this.generateUnifiedSQL(i,t,n)}async generateMultiCubeSQL(e,t,n){return this.generateUnifiedSQL(e,t,n)}async dryRunFunnel(e,t,n){if(!this.funnelQueryBuilder.hasFunnel(t))throw new Error("Query does not contain a valid funnel configuration");const i=t.funnel,s=this.funnelQueryBuilder.validateConfig(i,e);if(!s.isValid)throw new Error(`Funnel validation failed: ${s.errors.join(", ")}`);const o={db:this.dbExecutor.db,schema:this.dbExecutor.schema,securityContext:n},u=this.funnelQueryBuilder.buildFunnelQuery(i,e,o).toSQL();return{sql:u.sql,params:u.params}}async dryRunFlow(e,t,n){if(!this.flowQueryBuilder.hasFlow(t))throw new Error("Query does not contain a valid flow configuration");const i=t.flow,s=this.flowQueryBuilder.validateConfig(i,e);if(!s.isValid)throw new Error(`Flow validation failed: ${s.errors.join(", ")}`);const o={db:this.dbExecutor.db,schema:this.dbExecutor.schema,securityContext:n},u=this.flowQueryBuilder.buildFlowQuery(i,e,o).toSQL();return{sql:u.sql,params:u.params}}async dryRunRetention(e,t,n){if(!this.retentionQueryBuilder.hasRetention(t))throw new Error("Query does not contain a valid retention configuration");const i=t.retention,s=this.retentionQueryBuilder.validateConfig(i,e);if(!s.isValid)throw new Error(`Retention validation failed: ${s.errors.join(", ")}`);const o={db:this.dbExecutor.db,schema:this.dbExecutor.schema,securityContext:n},u=this.retentionQueryBuilder.buildRetentionQuery(i,e,o).toSQL();return{sql:u.sql,params:u.params}}async explainQuery(e,t,n,i){const s=await this.dryRunSQL(e,t,n);return this.dbExecutor.explainQuery(s.sql,s.params||[],i)}async dryRunSQL(e,t,n){const i=this.resolveQueryMode(t);return this.validateQueryForMode(i,e,t),this.generateSqlForMode(i,e,t,n)}async generateUnifiedSQL(e,t,n){const i=new ne,s=this.createQueryContext(n,i);this.preloadFilterCache(t,i,e,s);const{optimisedPlan:o}=this.buildRegularQueryArtifacts(e,t,s),a=this.drizzlePlanBuilder.derivePhysicalPlanContext(o),c=this.drizzlePlanBuilder.build(a,t,s).toSQL();return{sql:c.sql,params:c.params}}resolveQueryMode(e){const t=[];if(this.comparisonQueryBuilder.hasComparison(e)&&t.push("comparison"),this.funnelQueryBuilder.hasFunnel(e)&&t.push("funnel"),this.flowQueryBuilder.hasFlow(e)&&t.push("flow"),this.retentionQueryBuilder.hasRetention(e)&&t.push("retention"),t.length===0)return"regular";if(t.length>1)throw new Error(`Query contains multiple query modes: ${t.join(", ")}`);return t[0]}validateQueryForMode(e,t,n){const i=()=>{const o=dt(t,n);if(!o.isValid)throw new Error(`Query validation failed: ${o.errors.join(", ")}`)};({regular:i,comparison:i,funnel:()=>{const o=this.funnelQueryBuilder.validateConfig(n.funnel,t);if(!o.isValid)throw new Error(`Funnel validation failed: ${o.errors.join(", ")}`)},flow:()=>{const o=this.flowQueryBuilder.validateConfig(n.flow,t);if(!o.isValid)throw new Error(`Flow validation failed: ${o.errors.join(", ")}`)},retention:()=>{const o=this.retentionQueryBuilder.validateConfig(n.retention,t);if(!o.isValid)throw new Error(`Retention validation failed: ${o.errors.join(", ")}`)}})[e]()}async executeQueryByModeWithCache(e,t,n,i,s){return{regular:()=>this.executeRegularQueryWithCache(t,n,i,s),comparison:()=>this.executeComparisonQueryWithCache(t,n,i,s),funnel:()=>this.executeFunnelQueryWithCache(t,n,i,s),flow:()=>this.executeFlowQueryWithCache(t,n,i,s),retention:()=>this.executeRetentionQueryWithCache(t,n,i,s)}[e]()}async executeRegularQueryWithCache(e,t,n,i){const s=new ne,o=this.createQueryContext(n,s);this.preloadFilterCache(t,s,e,o);const{optimisedPlan:a}=this.buildRegularQueryArtifacts(e,t,o),u=this.drizzlePlanBuilder.derivePhysicalPlanContext(a);this.validateSecurityContext(u,o);const c=this.drizzlePlanBuilder.build(u,t,o),l=this.queryBuilder.collectNumericFields(e,t),m=await this.dbExecutor.execute(c,l),p=Array.isArray(m)?m.map(b=>{const w={...b};if(t.timeDimensions){for(const $ of t.timeDimensions)if($.dimension in w){let S=w[$.dimension];if(typeof S=="string"&&S.match(/^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}/)){const C=S.replace(" ","T"),T=!C.endsWith("Z")&&!C.includes("+")?C+"Z":C;S=new Date(T)}S=this.databaseAdapter.convertTimeDimensionResult(S),w[$.dimension]=S}}return w}):[m],f=t.measures||[],h=Ye(p,t,f),g=this.generateAnnotations(u,t),y={data:h,annotation:g,warnings:a.warnings?.length?a.warnings:void 0};return await this.cacheResult(i,y),y}async cacheResult(e,t){if(!(!e||!this.cacheConfig?.provider))try{const n=Date.now();await this.cacheConfig.provider.set(e,t,this.cacheConfig.defaultTtlMs??3e5),this.cacheConfig.onCacheEvent?.({type:"set",key:e,durationMs:Date.now()-n})}catch(n){this.cacheConfig.onError?.(n,"set")}}async generateSqlForMode(e,t,n,i){return{regular:()=>this.generateUnifiedSQL(t,n,i),comparison:()=>this.generateComparisonSQL(t,n,i),funnel:()=>this.dryRunFunnel(t,n,i),flow:()=>this.dryRunFlow(t,n,i),retention:()=>this.dryRunRetention(t,n,i)}[e]()}async generateComparisonSQL(e,t,n){const s=this.buildComparisonExecutionPlan(t).periodQueries[0];return this.generateUnifiedSQL(e,s,n)}generateAnnotations(e,t){const n={},i={},s={},o=[e.primaryCube].filter(Boolean);if(e.joinCubes&&e.joinCubes.length>0&&o.push(...e.joinCubes.map(a=>a.cube).filter(Boolean)),e.multiFactMerge?.groups?.length)for(const a of e.multiFactMerge.groups)a.queryPlan.primaryCube&&o.push(a.queryPlan.primaryCube),a.queryPlan.joinCubes?.length&&o.push(...a.queryPlan.joinCubes.map(u=>u.cube).filter(Boolean));if(t.measures)for(const a of t.measures){const[u,c]=a.split("."),l=o.find(m=>m?.name===u);if(l&&l.measures[c]){const m=l.measures[c];n[a]={title:m.title||c,shortTitle:m.title||c,type:m.type}}}if(t.dimensions)for(const a of t.dimensions){const[u,c]=a.split("."),l=o.find(m=>m?.name===u);if(l&&l.dimensions?.[c]){const m=l.dimensions[c];i[a]={title:m.title||c,shortTitle:m.title||c,type:m.type}}}if(t.timeDimensions)for(const a of t.timeDimensions){const[u,c]=a.dimension.split("."),l=o.find(m=>m?.name===u);if(l&&l.dimensions?.[c]){const m=l.dimensions[c];s[a.dimension]={title:m.title||c,shortTitle:m.title||c,type:m.type,granularity:a.granularity}}}return{measures:n,dimensions:i,segments:{},timeDimensions:s}}preloadFilterCache(e,t,n,i){if(e.filters&&e.filters.length>0){const s=Me(e.filters);for(const o of s){const a=fe(o);if(t.has(a))continue;const[u,c]=o.member.split("."),l=n.get(u);if(!l)continue;const m=l.dimensions?.[c];if(!m||["arrayContains","arrayOverlaps","arrayContained"].includes(o.operator))continue;const f=R(m.sql,i),h=this.queryBuilder.buildFilterConditionPublic(f,o.operator,o.values,m,o.dateRange);h&&t.set(a,h)}}if(e.timeDimensions){for(const s of e.timeDimensions)if(s.dateRange){const o=lt(s.dimension,s.dateRange);if(t.has(o))continue;const[a,u]=s.dimension.split("."),c=n.get(a);if(!c)continue;const l=c.dimensions?.[u];if(!l)continue;const m=R(l.sql,i),p=this.queryBuilder.buildDateRangeCondition(m,s.dateRange);p&&t.set(o,p)}}}}const On={name:"drizzle-cube-mcp-guide",description:"How to use drizzle-cube MCP tools to generate and run queries",messages:[{role:"user",content:{type:"text",text:["You are an analyst agent using drizzle-cube MCP.","","Workflow:","1) tools/call name=discover {topic|intent} - Find cubes and understand schema","2) Construct your query using the schema from discover (see cross-cube joins below)","3) tools/call name=validate {query} - Optional: fix schema issues","4) tools/call name=load {query} - Execute and get results","","CRITICAL - CROSS-CUBE JOINS:",'The "joins" property in discover results shows relationships between cubes.',"You can include dimensions from ANY related cube in your query!","Example: If Productivity joins to Employees, query:",'{ "measures": ["Productivity.totalPullRequests"], "dimensions": ["Employees.name"] }',"The system automatically joins the cubes for you.","","Query shapes:","- Regular: { measures, dimensions, filters[], timeDimensions[], order, limit, offset }","- Funnel: { funnel: { bindingKey, timeDimension, steps[], includeTimeMetrics? } }","- Flow: { flow: { bindingKey, eventDimension, steps?, window? } }","- Retention: { retention: { bindingKey, timeDimension, periods, granularity, retentionType, breakdownDimensions } }","","Time handling:",'- For AGGREGATED TOTALS (e.g., "last 3 months"): use filters with inDateRange, NOT timeDimensions','- For TIME SERIES (e.g., "by month"): use timeDimensions with granularity',"- You can combine both when needed","","Filters: flat arrays of { member, operator, values }. Do not nest arrays.","Do NOT hallucinate cube/field names—always use discover first."].join(`
195
195
  `)}}]},Ln={name:"drizzle-cube-query-rules",description:"Key generation rules aligned with Gemini single-step prompt",messages:[{role:"user",content:{type:"text",text:["Rules (keep JSON only):","- Use only measures/dimensions/timeDimensions from schema.","- timeDimensions: include granularity when grouping; use inDateRange filter for relative windows; combine when both requested.","- Funnel detection keywords: funnel, conversion, journey, drop off, step by step; use funnel format only if eventStream metadata exists.","- Funnel rules: bindingKey/timeDimension from cube metadata; include time filter on step 0 (default last 6 months) using inDateRange; steps ordered; flat filters.","- Chart selection: line/area for time trends; bar for categories; scatter for 2-measure correlations; bubble for 3-measure correlations; funnel for funnels.","- Correlation keywords (correlation/relationship/vs/compare) -> scatter/bubble, never line.","- Prefer .name fields over .id; avoid Id dimensions unless requested.","- Filters: flat array of {member, operator, values}; operators equals, notEquals, contains, notContains, gt, gte, lt, lte, inDateRange, set, notSet."].join(`
196
196
  `)}}]},In={name:"drizzle-cube-query-building",description:"CRITICAL: Complete guide for building valid queries of all types with examples",messages:[{role:"user",content:{type:"text",text:["# Drizzle Cube Query Building Guide","","## CRITICAL: Cross-Cube Joins","","You can combine measures from one cube with dimensions from RELATED cubes!",'Check the "joins" property in discover results to see relationships.',"",'Example: "Top 5 employees by pull requests last 3 months"',"- Productivity cube has: measures (totalPullRequests), dimensions (date)","- Productivity joins to Employees (via employeeId)","- Employees cube has: dimensions (name, department)","","Query combining BOTH cubes:","```json","{",' "measures": ["Productivity.totalPullRequests"],',' "dimensions": ["Employees.name"],',' "filters": [',' { "member": "Productivity.date", "operator": "inDateRange", "values": ["last 3 months"] }'," ],",' "order": { "Productivity.totalPullRequests": "desc" },',' "limit": 5',"}","```","The system AUTOMATICALLY joins Productivity to Employees for you!","","---","","## Date Filtering vs Time Grouping","","### For AGGREGATED TOTALS (no time breakdown)","Use `filters` with `inDateRange` operator. Do NOT use timeDimensions.","","```json","{",' "measures": ["Productivity.totalPullRequests"],',' "dimensions": ["Employees.name"],',' "filters": [{ "member": "Productivity.date", "operator": "inDateRange", "values": ["last 3 months"] }],',' "order": { "Productivity.totalPullRequests": "desc" },',' "limit": 5',"}","```","Result: 5 rows total, one per employee, with SUMMED pull requests.","","### For TIME SERIES (grouped by period)","Use `timeDimensions` WITH `granularity`.","","```json","{",' "measures": ["Productivity.totalPullRequests"],',' "timeDimensions": [{ "dimension": "Productivity.date", "dateRange": "last 3 months", "granularity": "month" }]',"}","```","Result: 3 rows (one per month) with pull request totals.","","### WRONG: timeDimensions without granularity","```json","// DON'T DO THIS - groups by DAY, returns ~90 rows!",'{ "timeDimensions": [{ "dimension": "X.date", "dateRange": "last 3 months" }] }',"```","","---","","## Regular Query Structure","","```json","{",' "measures": ["Cube.measure1", "Cube.measure2"],',' "dimensions": ["Cube.dimension1", "RelatedCube.dimension"],',' "filters": [',' { "member": "Cube.field", "operator": "equals", "values": ["value"] },',' { "member": "Cube.date", "operator": "inDateRange", "values": ["last 30 days"] }'," ],",' "timeDimensions": [],',' "order": { "Cube.measure1": "desc" },',' "limit": 100,',' "offset": 0',"}","```","","### Filter Operators","- String: equals, notEquals, contains, notContains, startsWith, endsWith","- Numeric: gt, gte, lt, lte","- Null: set, notSet","- Date: inDateRange, beforeDate, afterDate","","### Date Range Values",'- Relative: "last 7 days", "last 3 months", "last year", "this week", "this month"','- Absolute: ["2024-01-01", "2024-03-31"]',"","---","","## Funnel Query Structure","","Use when: conversion analysis, user journeys, step-by-step analysis","Requires: Cube with eventStream metadata","","```json","{",' "funnel": {',' "bindingKey": "Events.userId",',' "timeDimension": "Events.timestamp",',' "steps": ['," {",' "name": "Step 1",',' "filter": [',' { "member": "Events.eventType", "operator": "equals", "values": ["signup"] },',' { "member": "Events.timestamp", "operator": "inDateRange", "values": ["last 6 months"] }'," ]"," },"," {",' "name": "Step 2",',' "filter": [',' { "member": "Events.eventType", "operator": "equals", "values": ["purchase"] }'," ],",' "timeToConvert": { "value": 7, "unit": "day" }'," }"," ],",' "includeTimeMetrics": true'," }","}","```","","IMPORTANT: Put time filter (inDateRange) ONLY on step 0!","","---","","## Flow Query Structure","","Use when: analyzing event sequences, path analysis","","```json","{",' "flow": {',' "bindingKey": "Events.sessionId",',' "eventDimension": "Events.eventType",',' "timeDimension": "Events.timestamp",',' "stepsBefore": 2,',' "stepsAfter": 2,',' "startingStep": "checkout"'," }","}","```","","---","","## Retention Query Structure","","Use when: cohort analysis, user retention tracking","","```json","{",' "retention": {',' "bindingKey": "Users.id",',' "timeDimension": "Events.timestamp",',' "periods": 8,',' "granularity": "week",',' "retentionType": "rolling",',' "breakdownDimensions": ["Events.country"]'," }","}","```","","---","","## Common Mistakes to Avoid","","1. Using timeDimensions when you want aggregated totals → Use filters with inDateRange instead","2. Omitting granularity in timeDimensions → Results in day-level grouping","3. Guessing field names → Always use discover first to get actual schema","4. Nested filter arrays → Filters must be flat: [{ member, operator, values }]",'5. Missing date filter for "last N" queries → Always add inDateRange filter'].join(`
197
197
  `)}}]},jn={name:"drizzle-cube-date-filtering",description:"CRITICAL: How to correctly filter by date vs group by time period - the #1 source of query mistakes",messages:[{role:"user",content:{type:"text",text:["# Date Filtering vs Time Grouping - CRITICAL GUIDE","","This is the most common mistake when building queries. These are TWO DIFFERENT operations.","","## Quick Decision Tree","","```","User wants data over a time period?",'├── Wants AGGREGATED TOTALS (e.g., "total sales last month")',"│ └── Use: filters with inDateRange operator","│",'└── Wants TIME SERIES breakdown (e.g., "daily sales last month")'," └── Use: timeDimensions with granularity","```","","## For Aggregated Totals (MOST COMMON)","",'When user says: "last 3 months", "over the past year", "in Q1", "since January"',"","```json","{",' "measures": ["Sales.totalRevenue"],',' "dimensions": ["Products.category"],',' "filters": [',' { "member": "Sales.date", "operator": "inDateRange", "values": ["last 3 months"] }'," ]","}","```","","Result: One row per category with TOTAL revenue over the 3-month period.","","## For Time Series (Trend Analysis)","",'When user says: "by month", "per week", "daily trend", "over time"',"","```json","{",' "measures": ["Sales.totalRevenue"],',' "timeDimensions": [',' { "dimension": "Sales.date", "dateRange": "last 3 months", "granularity": "month" }'," ]","}","```","","Result: Multiple rows, one per month.","","## WRONG: timeDimensions Without Granularity","","```json","// This returns ~90 rows (daily) instead of aggregates!","{",' "timeDimensions": [{ "dimension": "Sales.date", "dateRange": "last 3 months" }]',"}","```","","## Both: Filter AND Group","",'When user wants: "monthly breakdown for last quarter"',"","```json","{",' "measures": ["Sales.totalRevenue"],',' "filters": [',' { "member": "Sales.date", "operator": "inDateRange", "values": ["last quarter"] }'," ],",' "timeDimensions": [',' { "dimension": "Sales.date", "granularity": "month" }'," ]","}","```","","## Summary Table","","| User Request | Use | Example |","|-------------|-----|---------|",'| "total for last 3 months" | filters + inDateRange | { filters: [{ operator: "inDateRange", values: ["last 3 months"] }] } |','| "top 5 last quarter" | filters + inDateRange | Same as above + order + limit |','| "monthly trend" | timeDimensions + granularity | { timeDimensions: [{ granularity: "month" }] } |','| "daily breakdown last week" | timeDimensions | { timeDimensions: [{ dateRange: "last week", granularity: "day" }] } |'].join(`