@@ -7391,6 +7391,80 @@ const fieldColumnListsCanonicalized: MetadataConversion = {
73917391 * cube's `measures` RECORD (keyed by name), one level below the collection
73927392 * item, so the top-level-only `stripKeys` runs per metric, not per cube.
73937393 */
7394+ const metricFiltersRemoved : MetadataConversion = {
7395+ id : 'metric-filters-removed' ,
7396+ toMajor : 18 ,
7397+ retiredFromLoadPath : true ,
7398+ surface : 'analyticsCubes[].measures.<metric>.filters' ,
7399+ summary :
7400+ "cube metric key 'filters' removed (#10414, ADR-0049 — no strategy ever read it: the "
7401+ + 'authored raw-SQL condition was parsed and dropped, and the query returned the '
7402+ + "unfiltered aggregate. Filter at query time with `where`, fold the condition into the "
7403+ + "metric's own `sql` expression, or use an ADR-0021 dataset measure's structured `filter`)" ,
7404+ apply ( stack , emit ) {
7405+ return mapCollection ( stack , 'analyticsCubes' , ( cube , path ) => {
7406+ const measures = cube . measures ;
7407+ if ( ! isDict ( measures ) ) return cube ;
7408+ let touched = false ;
7409+ const nextMeasures : Record < string , unknown > = { ...measures } ;
7410+ for ( const [ name , metric ] of Object . entries ( measures ) ) {
7411+ if ( ! isDict ( metric ) ) continue ;
7412+ const stripped = stripKeys ( metric , [ 'filters' ] , emit , `${ path } .measures.${ name } ` ) ;
7413+ if ( stripped === metric ) continue ;
7414+ nextMeasures [ name ] = stripped ;
7415+ touched = true ;
7416+ }
7417+ if ( ! touched ) return cube ;
7418+ return { ...cube , measures : nextMeasures } ;
7419+ } ) ;
7420+ } ,
7421+ fixture : {
7422+ before : {
7423+ analyticsCubes : [ {
7424+ name : 'orders' ,
7425+ sql : 'orders' ,
7426+ measures : {
7427+ // The card's measured shape: parsed, registered, returned unfiltered.
7428+ closed_won_revenue : {
7429+ name : 'closed_won_revenue' ,
7430+ label : 'Closed-Won Revenue' ,
7431+ type : 'sum' ,
7432+ sql : 'amount' ,
7433+ filters : [ { sql : "stage = 'closed_won'" } ] ,
7434+ } ,
7435+ // A metric WITHOUT the key rides through untouched — the strip
7436+ // dispatches on key presence, and the copy-on-write contract keeps
7437+ // the reference.
7438+ order_count : { name : 'order_count' , label : 'Orders' , type : 'count' , sql : 'id' } ,
7439+ } ,
7440+ dimensions : {
7441+ stage : { name : 'stage' , label : 'Stage' , type : 'string' , sql : 'stage' } ,
7442+ } ,
7443+ } ] ,
7444+ } ,
7445+ after : {
7446+ analyticsCubes : [ {
7447+ name : 'orders' ,
7448+ sql : 'orders' ,
7449+ measures : {
7450+ closed_won_revenue : {
7451+ name : 'closed_won_revenue' ,
7452+ label : 'Closed-Won Revenue' ,
7453+ type : 'sum' ,
7454+ sql : 'amount' ,
7455+ } ,
7456+ order_count : { name : 'order_count' , label : 'Orders' , type : 'count' , sql : 'id' } ,
7457+ } ,
7458+ dimensions : {
7459+ stage : { name : 'stage' , label : 'Stage' , type : 'string' , sql : 'stage' } ,
7460+ } ,
7461+ } ] ,
7462+ } ,
7463+ // One notice: the single metric carrying `filters`.
7464+ expectedNotices : 1 ,
7465+ } ,
7466+ } ;
7467+
73947468/**
73957469 * `dimensions.<dim>.granularities` — the three sub-day names `TimeUpdateInterval`
73967470 * declared until protocol 18 (#17296, ADR-0049 enforce-or-remove).
@@ -7497,80 +7571,6 @@ const cubeSubDayGranularitiesRemoved: MetadataConversion = {
74977571 } ,
74987572} ;
74997573
7500- const metricFiltersRemoved : MetadataConversion = {
7501- id : 'metric-filters-removed' ,
7502- toMajor : 18 ,
7503- retiredFromLoadPath : true ,
7504- surface : 'analyticsCubes[].measures.<metric>.filters' ,
7505- summary :
7506- "cube metric key 'filters' removed (#10414, ADR-0049 — no strategy ever read it: the "
7507- + 'authored raw-SQL condition was parsed and dropped, and the query returned the '
7508- + "unfiltered aggregate. Filter at query time with `where`, fold the condition into the "
7509- + "metric's own `sql` expression, or use an ADR-0021 dataset measure's structured `filter`)" ,
7510- apply ( stack , emit ) {
7511- return mapCollection ( stack , 'analyticsCubes' , ( cube , path ) => {
7512- const measures = cube . measures ;
7513- if ( ! isDict ( measures ) ) return cube ;
7514- let touched = false ;
7515- const nextMeasures : Record < string , unknown > = { ...measures } ;
7516- for ( const [ name , metric ] of Object . entries ( measures ) ) {
7517- if ( ! isDict ( metric ) ) continue ;
7518- const stripped = stripKeys ( metric , [ 'filters' ] , emit , `${ path } .measures.${ name } ` ) ;
7519- if ( stripped === metric ) continue ;
7520- nextMeasures [ name ] = stripped ;
7521- touched = true ;
7522- }
7523- if ( ! touched ) return cube ;
7524- return { ...cube , measures : nextMeasures } ;
7525- } ) ;
7526- } ,
7527- fixture : {
7528- before : {
7529- analyticsCubes : [ {
7530- name : 'orders' ,
7531- sql : 'orders' ,
7532- measures : {
7533- // The card's measured shape: parsed, registered, returned unfiltered.
7534- closed_won_revenue : {
7535- name : 'closed_won_revenue' ,
7536- label : 'Closed-Won Revenue' ,
7537- type : 'sum' ,
7538- sql : 'amount' ,
7539- filters : [ { sql : "stage = 'closed_won'" } ] ,
7540- } ,
7541- // A metric WITHOUT the key rides through untouched — the strip
7542- // dispatches on key presence, and the copy-on-write contract keeps
7543- // the reference.
7544- order_count : { name : 'order_count' , label : 'Orders' , type : 'count' , sql : 'id' } ,
7545- } ,
7546- dimensions : {
7547- stage : { name : 'stage' , label : 'Stage' , type : 'string' , sql : 'stage' } ,
7548- } ,
7549- } ] ,
7550- } ,
7551- after : {
7552- analyticsCubes : [ {
7553- name : 'orders' ,
7554- sql : 'orders' ,
7555- measures : {
7556- closed_won_revenue : {
7557- name : 'closed_won_revenue' ,
7558- label : 'Closed-Won Revenue' ,
7559- type : 'sum' ,
7560- sql : 'amount' ,
7561- } ,
7562- order_count : { name : 'order_count' , label : 'Orders' , type : 'count' , sql : 'id' } ,
7563- } ,
7564- dimensions : {
7565- stage : { name : 'stage' , label : 'Stage' , type : 'string' , sql : 'stage' } ,
7566- } ,
7567- } ] ,
7568- } ,
7569- // One notice: the single metric carrying `filters`.
7570- expectedNotices : 1 ,
7571- } ,
7572- } ;
7573-
75747574/**
75757575 * `record:highlights` highlight-field `icon` — a declared, advertised key with
75767576 * zero read points (#10054, ADR-0049 enforce-or-remove; maintainer ruling
0 commit comments