diff --git a/src/compute-types/src/plan/interpret/physically_monotonic.rs b/src/compute-types/src/plan/interpret/physically_monotonic.rs index a48de2f6a7e57..e7cc1945d06dc 100644 --- a/src/compute-types/src/plan/interpret/physically_monotonic.rs +++ b/src/compute-types/src/plan/interpret/physically_monotonic.rs @@ -139,12 +139,10 @@ impl Interpreter for SingleTimeMonotonic<'_> { _input_key: &Option>, input: Self::Domain, _exprs: &Vec, - _func: &TableFunc, + func: &TableFunc, _mfp: &MapFilterProject, ) -> Self::Domain { - // In a single-time context, we just propagate the monotonicity - // status of the input - input + PhysicallyMonotonic(input.0 && func.preserves_monotonicity()) } fn join( diff --git a/src/expr/src/lib.rs b/src/expr/src/lib.rs index e2c97d292e23f..a58a3aaa8fbb1 100644 --- a/src/expr/src/lib.rs +++ b/src/expr/src/lib.rs @@ -33,6 +33,7 @@ pub use interpret::{ColumnSpec, ColumnSpecs, Interpreter, ResultSpec, Trace, Tra pub use linear::plan::{MfpPlan, SafeMfpPlan}; pub use linear::util::{join_permutations, permutation_for_arrangement}; pub use linear::{MapFilterProject, memoize_expr}; +pub use relation::func::REPEAT_ROW_NAME; pub use relation::func::order_aggregate_datums as order_aggregate_datums_exported_for_benchmarking; pub use relation::func::{ AggregateFunc, AnalyzedRegex, AnalyzedRegexOpts, CaptureGroupDesc, LagLeadType, diff --git a/src/expr/src/relation/func.rs b/src/expr/src/relation/func.rs index 1d69955d61f86..6d19e25524a55 100644 --- a/src/expr/src/relation/func.rs +++ b/src/expr/src/relation/func.rs @@ -3280,7 +3280,7 @@ pub fn csv_extract(a: Datum<'_>, n_cols: usize) -> impl Iterator Option<(Row, Diff)> { +pub fn repeat_row(a: Datum) -> Option<(Row, Diff)> { let n = a.unwrap_int64(); if n != 0 { Some((Row::default(), n.into())) @@ -3289,6 +3289,22 @@ pub fn repeat(a: Datum) -> Option<(Row, Diff)> { } } +pub fn repeat_row_non_negative<'a>( + a: Datum, +) -> Result + 'a>, EvalError> { + let n = a.unwrap_int64(); + if n < 0 { + Err(EvalError::InvalidParameterValue( + format!("repeat_row_non_negative got {}", n).into(), + )) + } else if n == 0 { + Ok(Box::new(iter::empty())) + } else { + // iterator with 1 element; n goes into the diff + Ok(Box::new(iter::once((Row::default(), n.into())))) + } +} + fn wrap<'a>(datums: &'a [Datum<'a>], width: usize) -> impl Iterator + 'a { datums .chunks(width) @@ -3396,7 +3412,16 @@ pub enum TableFunc { GuardSubquerySize { column_type: SqlScalarType, }, - Repeat, + /// Repeats the input row the given number of times. Can even repeat a negative number of times, + /// which has some important consequences: + /// - can lead to negative accumulations downstream; + /// - can't be used in `WITH ORDINALITY` and other constructs that are implemented by + /// `TableFunc::WithOrdinality`, e.g., `ROWS FROM`; + /// - output is non-monotonic. + RepeatRow, + /// Same as `RepeatRow`, but errors on a negative count, and thereby avoids the above + /// peculiarities. + RepeatRowNonNegative, UnnestArray { el_typ: SqlScalarType, }, @@ -3471,7 +3496,7 @@ impl TableFunc { | TableFunc::GenerateSeriesTimestamp | TableFunc::GenerateSeriesTimestampTz | TableFunc::GuardSubquerySize { .. } - | TableFunc::Repeat + | TableFunc::RepeatRowNonNegative | TableFunc::UnnestArray { .. } | TableFunc::UnnestList { .. } | TableFunc::UnnestMap { .. } @@ -3481,9 +3506,13 @@ impl TableFunc { | TableFunc::RegexpMatches => Some(TableFunc::WithOrdinality(WithOrdinality { inner: Box::new(inner), })), - // IMPORTANT: Before adding a new table function here, consider negative diffs: + // IMPORTANT: Before adding a new table function above, consider negative diffs: // `WithOrdinality::eval` will panic if the inner table function emits a negative diff. - TableFunc::WithOrdinality(_) => None, + // (Note that negative diffs in the table function's _input_ don't matter. The table + // function implementation doesn't see the input diffs, so the thing that matters here + // is whether the table function itself can emit a negative diff.) + TableFunc::RepeatRow // can produce negative diffs + | TableFunc::WithOrdinality(_) => None, // no nesting of `WITH ORDINALITY` allowed } } } @@ -3566,7 +3595,8 @@ impl TableFunc { Ok(Box::new([].into_iter())) } } - TableFunc::Repeat => Ok(Box::new(repeat(datums[0]).into_iter())), + TableFunc::RepeatRow => Ok(Box::new(repeat_row(datums[0]).into_iter())), + TableFunc::RepeatRowNonNegative => repeat_row_non_negative(datums[0]), TableFunc::UnnestArray { .. } => Ok(Box::new(unnest_array(datums[0]))), TableFunc::UnnestList { .. } => Ok(Box::new(unnest_list(datums[0]))), TableFunc::UnnestMap { .. } => Ok(Box::new(unnest_map(datums[0]))), @@ -3682,7 +3712,7 @@ impl TableFunc { let keys = vec![]; (column_types, keys) } - TableFunc::Repeat => { + TableFunc::RepeatRow | TableFunc::RepeatRowNonNegative => { let column_types = vec![]; let keys = vec![]; (column_types, keys) @@ -3763,7 +3793,8 @@ impl TableFunc { TableFunc::GenerateSeriesTimestampTz => 1, TableFunc::GenerateSubscriptsArray => 1, TableFunc::GuardSubquerySize { .. } => 1, - TableFunc::Repeat => 0, + TableFunc::RepeatRow => 0, + TableFunc::RepeatRowNonNegative => 0, TableFunc::UnnestArray { .. } => 1, TableFunc::UnnestList { .. } => 1, TableFunc::UnnestMap { .. } => 2, @@ -3790,7 +3821,8 @@ impl TableFunc { | TableFunc::GenerateSubscriptsArray | TableFunc::RegexpExtract(_) | TableFunc::CsvExtract(_) - | TableFunc::Repeat + | TableFunc::RepeatRow + | TableFunc::RepeatRowNonNegative | TableFunc::UnnestArray { .. } | TableFunc::UnnestList { .. } | TableFunc::UnnestMap { .. } @@ -3821,7 +3853,8 @@ impl TableFunc { TableFunc::GenerateSeriesTimestamp => true, TableFunc::GenerateSeriesTimestampTz => true, TableFunc::GenerateSubscriptsArray => true, - TableFunc::Repeat => false, + TableFunc::RepeatRow => false, + TableFunc::RepeatRowNonNegative => true, TableFunc::UnnestArray { .. } => true, TableFunc::UnnestList { .. } => true, TableFunc::UnnestMap { .. } => true, @@ -3852,7 +3885,8 @@ impl fmt::Display for TableFunc { TableFunc::GenerateSeriesTimestampTz => f.write_str("generate_series"), TableFunc::GenerateSubscriptsArray => f.write_str("generate_subscripts"), TableFunc::GuardSubquerySize { .. } => f.write_str("guard_subquery_size"), - TableFunc::Repeat => f.write_str("repeat_row"), + TableFunc::RepeatRow => f.write_str(REPEAT_ROW_NAME), + TableFunc::RepeatRowNonNegative => f.write_str("repeat_row_non_negative"), TableFunc::UnnestArray { .. } => f.write_str("unnest_array"), TableFunc::UnnestList { .. } => f.write_str("unnest_list"), TableFunc::UnnestMap { .. } => f.write_str("unnest_map"), @@ -3886,12 +3920,13 @@ impl WithOrdinality { .eval(datums, temp_storage)? .flat_map(move |(mut row, diff)| { let diff = diff.into_inner(); - // WITH ORDINALITY is not well-defined for negative diffs. This is ok, since the - // only table function that can emit negative diffs is `repeat_row`, which is in - // `mz_unsafe`, so users can never call it. + // WITH ORDINALITY is not well-defined for negative diffs. This is ok, and + // `TableFunc::with_ordinality` refuses to wrap such table functions in + // `WithOrdinality` that can emit negative diffs, e.g., `repeat_row`. // - // (We also don't need to worry about negative diffs in FlatMap's input, because - // the diff of the input of the FlatMap is factored in after we return from here.) + // (Note that we don't need to worry about negative diffs in FlatMap's input, + // because the diff of the input of the FlatMap is factored in after we return from + // here.) assert!(diff >= 0); // The ordinals that will be associated with this row. let mut ordinals = next_ordinal..(next_ordinal + diff); @@ -3916,3 +3951,5 @@ impl WithOrdinality { Ok(Box::new(it)) } } + +pub const REPEAT_ROW_NAME: &str = "repeat_row"; diff --git a/src/pgrepr-consts/src/oid.rs b/src/pgrepr-consts/src/oid.rs index f80b943f98b69..8f20776dd6f7c 100644 --- a/src/pgrepr-consts/src/oid.rs +++ b/src/pgrepr-consts/src/oid.rs @@ -139,7 +139,7 @@ pub const FUNC_MZ_LOGICAL_TIMESTAMP_OID: u32 = 16_409; pub const FUNC_MZ_RENDER_TYPMOD_OID: u32 = 16_410; pub const FUNC_MZ_VERSION_OID: u32 = 16_411; pub const FUNC_REGEXP_EXTRACT_OID: u32 = 16_412; -pub const FUNC_REPEAT_OID: u32 = 16_413; +pub const FUNC_REPEAT_ROW_OID: u32 = 16_413; pub const FUNC_ROUND_F32_OID: u32 = 16_414; pub const FUNC_UNNEST_LIST_OID: u32 = 16_416; pub const OP_CONCAT_ELEMENY_LIST_OID: u32 = 16_417; @@ -792,3 +792,4 @@ pub const VIEW_MZ_MCP_DATA_PRODUCT_DETAILS_OID: u32 = 17071; pub const VIEW_MZ_BUILTIN_MATERIALIZED_VIEWS_OID: u32 = 17072; pub const FUNC_PARSE_CATALOG_CREATE_SQL_OID: u32 = 17073; pub const FUNC_REDACT_SQL_OID: u32 = 17074; +pub const FUNC_REPEAT_ROW_NON_NEGATIVE_OID: u32 = 17075; diff --git a/src/sql/src/func.rs b/src/sql/src/func.rs index b9ced3945e69b..25cc984aceab1 100644 --- a/src/sql/src/func.rs +++ b/src/sql/src/func.rs @@ -4566,7 +4566,7 @@ pub static MZ_CATALOG_BUILTINS: LazyLock> = LazyLoc }, "list_n_layers" => Scalar { vec![ListAny] => Operation::unary(|ecx, e| { - ecx.require_feature_flag(&crate::session::vars::ENABLE_LIST_N_LAYERS)?; + ecx.require_feature_flag(&vars::ENABLE_LIST_N_LAYERS)?; let d = ecx.scalar_type(&e).unwrap_list_n_layers(); match i32::try_from(d) { Ok(d) => Ok(HirScalarExpr::literal(Datum::Int32(d), SqlScalarType::Int32)), @@ -4581,7 +4581,7 @@ pub static MZ_CATALOG_BUILTINS: LazyLock> = LazyLoc }, "list_length_max" => Scalar { vec![ListAny, Plain(SqlScalarType::Int64)] => Operation::binary(|ecx, lhs, rhs| { - ecx.require_feature_flag(&crate::session::vars::ENABLE_LIST_LENGTH_MAX)?; + ecx.require_feature_flag(&vars::ENABLE_LIST_LENGTH_MAX)?; let max_layer = ecx.scalar_type(&lhs).unwrap_list_n_layers(); Ok(lhs.call_binary(rhs, BinaryFunc::from(func::ListLengthMax { max_layer }))) }) => Int32, oid::FUNC_LIST_LENGTH_MAX_OID; @@ -4593,7 +4593,7 @@ pub static MZ_CATALOG_BUILTINS: LazyLock> = LazyLoc }, "list_remove" => Scalar { vec![ListAnyCompatible, ListElementAnyCompatible] => Operation::binary(|ecx, lhs, rhs| { - ecx.require_feature_flag(&crate::session::vars::ENABLE_LIST_REMOVE)?; + ecx.require_feature_flag(&vars::ENABLE_LIST_REMOVE)?; Ok(lhs.call_binary(rhs, func::ListRemove)) }) => ListAnyCompatible, oid::FUNC_LIST_REMOVE_OID; }, @@ -4733,17 +4733,29 @@ pub static MZ_CATALOG_BUILTINS: LazyLock> = LazyLoc }) }) => ReturnType::set_of(RecordAny), oid::FUNC_REGEXP_EXTRACT_OID; }, - "repeat_row" => Table { + mz_expr::REPEAT_ROW_NAME => Table { params!(Int64) => Operation::unary(move |ecx, n| { - ecx.require_feature_flag(&crate::session::vars::ENABLE_REPEAT_ROW)?; + ecx.require_feature_flag(&vars::ENABLE_REPEAT_ROW)?; Ok(TableFuncPlan { imp: TableFuncImpl::CallTable { - func: TableFunc::Repeat, + func: TableFunc::RepeatRow, exprs: vec![n], }, column_names: vec![] }) - }) => ReturnType::none(true), oid::FUNC_REPEAT_OID; + }) => ReturnType::none(true), oid::FUNC_REPEAT_ROW_OID; + }, + "repeat_row_non_negative" => Table { + params!(Int64) => Operation::unary(move |ecx, n| { + ecx.require_feature_flag(&vars::ENABLE_REPEAT_ROW_NON_NEGATIVE)?; + Ok(TableFuncPlan { + imp: TableFuncImpl::CallTable { + func: TableFunc::RepeatRowNonNegative, + exprs: vec![n], + }, + column_names: vec![] + }) + }) => ReturnType::none(true), oid::FUNC_REPEAT_ROW_NON_NEGATIVE_OID; }, "seahash" => Scalar { params!(String) => UnaryFunc::SeahashString(func::SeahashString) diff --git a/src/sql/src/plan/query.rs b/src/sql/src/plan/query.rs index 6d01c81c53935..67ec335f4bdae 100644 --- a/src/sql/src/plan/query.rs +++ b/src/sql/src/plan/query.rs @@ -52,8 +52,8 @@ use mz_expr::func::variadic::{ }; use mz_expr::virtual_syntax::AlgExcept; use mz_expr::{ - Id, LetRecLimit, LocalId, MapFilterProject, MirScalarExpr, RowSetFinishing, TableFunc, - func as expr_func, + Id, LetRecLimit, LocalId, MapFilterProject, MirScalarExpr, REPEAT_ROW_NAME, RowSetFinishing, + TableFunc, func as expr_func, }; use mz_ore::assert_none; use mz_ore::collections::CollectionExt; @@ -66,6 +66,7 @@ use mz_repr::adt::char::CharLength; use mz_repr::adt::numeric::{NUMERIC_DATUM_MAX_PRECISION, NumericMaxScale}; use mz_repr::adt::timestamp::TimestampPrecision; use mz_repr::adt::varchar::VarCharMaxLength; +use mz_repr::namespaces::MZ_CATALOG_SCHEMA; use mz_repr::{ CatalogItemId, ColumnIndex, ColumnName, Datum, RelationDesc, RelationVersionSelector, ReprColumnType, Row, RowArena, SqlColumnType, SqlRelationType, SqlScalarType, @@ -2826,6 +2827,14 @@ fn plan_scalar_table_funcs( } return Ok((expr, scope)); } + if table_funcs.keys().any(is_repeat_row) { + // Note: Would be also caught by WITH ORDINALITY checking for `repeat_row`, but then the + // error message would be misleading, because it would refer to WITH ORDINALITY. + bail_unsupported!(format!( + "{} in a SELECT clause with multiple table functions", + REPEAT_ROW_NAME + )); + } // Otherwise, plan as usual, emulating the ROWS FROM behavior let (expr, mut scope, num_cols) = plan_rows_from_internal(&rows_from_qcx, table_funcs.keys(), None)?; @@ -3111,6 +3120,14 @@ fn plan_rows_from( alias: Option<&TableAlias>, with_ordinality: bool, ) -> Result<(HirRelationExpr, Scope), PlanError> { + // The `repeat_row` function is not supported in ROWS FROM. + if functions.iter().any(is_repeat_row) { + // Note: Would be also caught by WITH ORDINALITY checking for `repeat_row`, but then the + // error message would be misleading, because it would refer to WITH ORDINALITY instead of + // ROWS FROM. + bail_unsupported!(format!("{} in ROWS FROM", REPEAT_ROW_NAME)); + } + // If there's only a single table function, planning proceeds as if `ROWS // FROM` hadn't been written at all. if let [function] = functions { @@ -3155,6 +3172,10 @@ fn plan_rows_from( Ok((expr, scope)) } +fn is_repeat_row(f: &Function) -> bool { + f.name.full_name_str().as_str() == format!("{}.{}", MZ_CATALOG_SCHEMA, REPEAT_ROW_NAME) +} + /// Plans an expression coalescing multiple table functions. Each table /// function is followed by its row ordinality. The entire expression is /// followed by the coalesced row ordinality. diff --git a/src/sql/src/session/vars/definitions.rs b/src/sql/src/session/vars/definitions.rs index 99a4148059c79..bb218a76e3ee6 100644 --- a/src/sql/src/session/vars/definitions.rs +++ b/src/sql/src/session/vars/definitions.rs @@ -1880,6 +1880,12 @@ feature_flags!( default: false, enable_for_item_parsing: true, }, + { + name: enable_repeat_row_non_negative, + desc: "the repeat_row_non_negative function", + default: false, + enable_for_item_parsing: true, + }, { name: enable_replica_targeted_materialized_views, desc: "replica-targeted materialized views", diff --git a/test/sqllogictest/mz_catalog_server_index_accounting.slt b/test/sqllogictest/mz_catalog_server_index_accounting.slt index 85fffbf7244d4..f08518bf43e97 100644 --- a/test/sqllogictest/mz_catalog_server_index_accounting.slt +++ b/test/sqllogictest/mz_catalog_server_index_accounting.slt @@ -37,100 +37,100 @@ mz_arrangement_heap_capacity_raw_s2_primary_idx CREATE␠INDEX␠"mz_arrangemen mz_arrangement_heap_size_raw_s2_primary_idx CREATE␠INDEX␠"mz_arrangement_heap_size_raw_s2_primary_idx"␠IN␠CLUSTER␠[s2]␠ON␠"mz_introspection"."mz_arrangement_heap_size_raw"␠("operator_id",␠"worker_id") mz_arrangement_records_raw_s2_primary_idx CREATE␠INDEX␠"mz_arrangement_records_raw_s2_primary_idx"␠IN␠CLUSTER␠[s2]␠ON␠"mz_introspection"."mz_arrangement_records_raw"␠("operator_id",␠"worker_id") mz_arrangement_sharing_raw_s2_primary_idx CREATE␠INDEX␠"mz_arrangement_sharing_raw_s2_primary_idx"␠IN␠CLUSTER␠[s2]␠ON␠"mz_introspection"."mz_arrangement_sharing_raw"␠("operator_id",␠"worker_id") -mz_cluster_deployment_lineage_ind CREATE␠INDEX␠"mz_cluster_deployment_lineage_ind"␠IN␠CLUSTER␠[s2]␠ON␠[s741␠AS␠"mz_internal"."mz_cluster_deployment_lineage"]␠("cluster_id") +mz_cluster_deployment_lineage_ind CREATE␠INDEX␠"mz_cluster_deployment_lineage_ind"␠IN␠CLUSTER␠[s2]␠ON␠[s742␠AS␠"mz_internal"."mz_cluster_deployment_lineage"]␠("cluster_id") mz_cluster_prometheus_metrics_s2_primary_idx CREATE␠INDEX␠"mz_cluster_prometheus_metrics_s2_primary_idx"␠IN␠CLUSTER␠[s2]␠ON␠"mz_introspection"."mz_cluster_prometheus_metrics"␠("process_id",␠"metric_name",␠"labels") -mz_cluster_replica_frontiers_ind CREATE␠INDEX␠"mz_cluster_replica_frontiers_ind"␠IN␠CLUSTER␠[s2]␠ON␠[s735␠AS␠"mz_catalog"."mz_cluster_replica_frontiers"]␠("object_id") -mz_cluster_replica_history_ind CREATE␠INDEX␠"mz_cluster_replica_history_ind"␠IN␠CLUSTER␠[s2]␠ON␠[s598␠AS␠"mz_internal"."mz_cluster_replica_history"]␠("dropped_at") -mz_cluster_replica_metrics_history_ind CREATE␠INDEX␠"mz_cluster_replica_metrics_history_ind"␠IN␠CLUSTER␠[s2]␠ON␠[s506␠AS␠"mz_internal"."mz_cluster_replica_metrics_history"]␠("replica_id") -mz_cluster_replica_metrics_ind CREATE␠INDEX␠"mz_cluster_replica_metrics_ind"␠IN␠CLUSTER␠[s2]␠ON␠[s507␠AS␠"mz_internal"."mz_cluster_replica_metrics"]␠("replica_id") -mz_cluster_replica_name_history_ind CREATE␠INDEX␠"mz_cluster_replica_name_history_ind"␠IN␠CLUSTER␠[s2]␠ON␠[s599␠AS␠"mz_internal"."mz_cluster_replica_name_history"]␠("id") -mz_cluster_replica_sizes_ind CREATE␠INDEX␠"mz_cluster_replica_sizes_ind"␠IN␠CLUSTER␠[s2]␠ON␠[s508␠AS␠"mz_catalog"."mz_cluster_replica_sizes"]␠("size") -mz_cluster_replica_status_history_ind CREATE␠INDEX␠"mz_cluster_replica_status_history_ind"␠IN␠CLUSTER␠[s2]␠ON␠[s509␠AS␠"mz_internal"."mz_cluster_replica_status_history"]␠("replica_id") -mz_cluster_replica_statuses_ind CREATE␠INDEX␠"mz_cluster_replica_statuses_ind"␠IN␠CLUSTER␠[s2]␠ON␠[s510␠AS␠"mz_internal"."mz_cluster_replica_statuses"]␠("replica_id") -mz_cluster_replicas_ind CREATE␠INDEX␠"mz_cluster_replicas_ind"␠IN␠CLUSTER␠[s2]␠ON␠[s505␠AS␠"mz_catalog"."mz_cluster_replicas"]␠("id") -mz_clusters_ind CREATE␠INDEX␠"mz_clusters_ind"␠IN␠CLUSTER␠[s2]␠ON␠[s499␠AS␠"mz_catalog"."mz_clusters"]␠("id") -mz_columns_ind CREATE␠INDEX␠"mz_columns_ind"␠IN␠CLUSTER␠[s2]␠ON␠[s472␠AS␠"mz_catalog"."mz_columns"]␠("name") -mz_comments_ind CREATE␠INDEX␠"mz_comments_ind"␠IN␠CLUSTER␠[s2]␠ON␠[s522␠AS␠"mz_internal"."mz_comments"]␠("id") +mz_cluster_replica_frontiers_ind CREATE␠INDEX␠"mz_cluster_replica_frontiers_ind"␠IN␠CLUSTER␠[s2]␠ON␠[s736␠AS␠"mz_catalog"."mz_cluster_replica_frontiers"]␠("object_id") +mz_cluster_replica_history_ind CREATE␠INDEX␠"mz_cluster_replica_history_ind"␠IN␠CLUSTER␠[s2]␠ON␠[s599␠AS␠"mz_internal"."mz_cluster_replica_history"]␠("dropped_at") +mz_cluster_replica_metrics_history_ind CREATE␠INDEX␠"mz_cluster_replica_metrics_history_ind"␠IN␠CLUSTER␠[s2]␠ON␠[s507␠AS␠"mz_internal"."mz_cluster_replica_metrics_history"]␠("replica_id") +mz_cluster_replica_metrics_ind CREATE␠INDEX␠"mz_cluster_replica_metrics_ind"␠IN␠CLUSTER␠[s2]␠ON␠[s508␠AS␠"mz_internal"."mz_cluster_replica_metrics"]␠("replica_id") +mz_cluster_replica_name_history_ind CREATE␠INDEX␠"mz_cluster_replica_name_history_ind"␠IN␠CLUSTER␠[s2]␠ON␠[s600␠AS␠"mz_internal"."mz_cluster_replica_name_history"]␠("id") +mz_cluster_replica_sizes_ind CREATE␠INDEX␠"mz_cluster_replica_sizes_ind"␠IN␠CLUSTER␠[s2]␠ON␠[s509␠AS␠"mz_catalog"."mz_cluster_replica_sizes"]␠("size") +mz_cluster_replica_status_history_ind CREATE␠INDEX␠"mz_cluster_replica_status_history_ind"␠IN␠CLUSTER␠[s2]␠ON␠[s510␠AS␠"mz_internal"."mz_cluster_replica_status_history"]␠("replica_id") +mz_cluster_replica_statuses_ind CREATE␠INDEX␠"mz_cluster_replica_statuses_ind"␠IN␠CLUSTER␠[s2]␠ON␠[s511␠AS␠"mz_internal"."mz_cluster_replica_statuses"]␠("replica_id") +mz_cluster_replicas_ind CREATE␠INDEX␠"mz_cluster_replicas_ind"␠IN␠CLUSTER␠[s2]␠ON␠[s506␠AS␠"mz_catalog"."mz_cluster_replicas"]␠("id") +mz_clusters_ind CREATE␠INDEX␠"mz_clusters_ind"␠IN␠CLUSTER␠[s2]␠ON␠[s500␠AS␠"mz_catalog"."mz_clusters"]␠("id") +mz_columns_ind CREATE␠INDEX␠"mz_columns_ind"␠IN␠CLUSTER␠[s2]␠ON␠[s473␠AS␠"mz_catalog"."mz_columns"]␠("name") +mz_comments_ind CREATE␠INDEX␠"mz_comments_ind"␠IN␠CLUSTER␠[s2]␠ON␠[s523␠AS␠"mz_internal"."mz_comments"]␠("id") mz_compute_dataflow_global_ids_per_worker_s2_primary_idx CREATE␠INDEX␠"mz_compute_dataflow_global_ids_per_worker_s2_primary_idx"␠IN␠CLUSTER␠[s2]␠ON␠"mz_introspection"."mz_compute_dataflow_global_ids_per_worker"␠("id",␠"worker_id",␠"global_id") -mz_compute_dependencies_ind CREATE␠INDEX␠"mz_compute_dependencies_ind"␠IN␠CLUSTER␠[s2]␠ON␠[s724␠AS␠"mz_internal"."mz_compute_dependencies"]␠("dependency_id") +mz_compute_dependencies_ind CREATE␠INDEX␠"mz_compute_dependencies_ind"␠IN␠CLUSTER␠[s2]␠ON␠[s725␠AS␠"mz_internal"."mz_compute_dependencies"]␠("dependency_id") mz_compute_error_counts_raw_s2_primary_idx CREATE␠INDEX␠"mz_compute_error_counts_raw_s2_primary_idx"␠IN␠CLUSTER␠[s2]␠ON␠"mz_introspection"."mz_compute_error_counts_raw"␠("export_id",␠"worker_id") mz_compute_exports_per_worker_s2_primary_idx CREATE␠INDEX␠"mz_compute_exports_per_worker_s2_primary_idx"␠IN␠CLUSTER␠[s2]␠ON␠"mz_introspection"."mz_compute_exports_per_worker"␠("export_id",␠"worker_id") mz_compute_frontiers_per_worker_s2_primary_idx CREATE␠INDEX␠"mz_compute_frontiers_per_worker_s2_primary_idx"␠IN␠CLUSTER␠[s2]␠ON␠"mz_introspection"."mz_compute_frontiers_per_worker"␠("export_id",␠"worker_id") -mz_compute_hydration_times_ind CREATE␠INDEX␠"mz_compute_hydration_times_ind"␠IN␠CLUSTER␠[s2]␠ON␠[s731␠AS␠"mz_internal"."mz_compute_hydration_times"]␠("replica_id") +mz_compute_hydration_times_ind CREATE␠INDEX␠"mz_compute_hydration_times_ind"␠IN␠CLUSTER␠[s2]␠ON␠[s732␠AS␠"mz_internal"."mz_compute_hydration_times"]␠("replica_id") mz_compute_hydration_times_per_worker_s2_primary_idx CREATE␠INDEX␠"mz_compute_hydration_times_per_worker_s2_primary_idx"␠IN␠CLUSTER␠[s2]␠ON␠"mz_introspection"."mz_compute_hydration_times_per_worker"␠("export_id",␠"worker_id") mz_compute_import_frontiers_per_worker_s2_primary_idx CREATE␠INDEX␠"mz_compute_import_frontiers_per_worker_s2_primary_idx"␠IN␠CLUSTER␠[s2]␠ON␠"mz_introspection"."mz_compute_import_frontiers_per_worker"␠("export_id",␠"import_id",␠"worker_id") mz_compute_lir_mapping_per_worker_s2_primary_idx CREATE␠INDEX␠"mz_compute_lir_mapping_per_worker_s2_primary_idx"␠IN␠CLUSTER␠[s2]␠ON␠"mz_introspection"."mz_compute_lir_mapping_per_worker"␠("global_id",␠"lir_id",␠"worker_id") mz_compute_operator_durations_histogram_raw_s2_primary_idx CREATE␠INDEX␠"mz_compute_operator_durations_histogram_raw_s2_primary_idx"␠IN␠CLUSTER␠[s2]␠ON␠"mz_introspection"."mz_compute_operator_durations_histogram_raw"␠("id",␠"worker_id",␠"duration_ns") mz_compute_operator_hydration_statuses_per_worker_s2_primary_idx CREATE␠INDEX␠"mz_compute_operator_hydration_statuses_per_worker_s2_primary_idx"␠IN␠CLUSTER␠[s2]␠ON␠"mz_introspection"."mz_compute_operator_hydration_statuses_per_worker"␠("export_id",␠"lir_id") -mz_connections_ind CREATE␠INDEX␠"mz_connections_ind"␠IN␠CLUSTER␠[s2]␠ON␠[s503␠AS␠"mz_catalog"."mz_connections"]␠("schema_id") -mz_console_cluster_utilization_overview_ind CREATE␠INDEX␠"mz_console_cluster_utilization_overview_ind"␠IN␠CLUSTER␠[s2]␠ON␠[s727␠AS␠"mz_internal"."mz_console_cluster_utilization_overview"]␠("cluster_id") -mz_continual_tasks_ind CREATE␠INDEX␠"mz_continual_tasks_ind"␠IN␠CLUSTER␠[s2]␠ON␠[s527␠AS␠"mz_internal"."mz_continual_tasks"]␠("id") -mz_databases_ind CREATE␠INDEX␠"mz_databases_ind"␠IN␠CLUSTER␠[s2]␠ON␠[s470␠AS␠"mz_catalog"."mz_databases"]␠("name") +mz_connections_ind CREATE␠INDEX␠"mz_connections_ind"␠IN␠CLUSTER␠[s2]␠ON␠[s504␠AS␠"mz_catalog"."mz_connections"]␠("schema_id") +mz_console_cluster_utilization_overview_ind CREATE␠INDEX␠"mz_console_cluster_utilization_overview_ind"␠IN␠CLUSTER␠[s2]␠ON␠[s728␠AS␠"mz_internal"."mz_console_cluster_utilization_overview"]␠("cluster_id") +mz_continual_tasks_ind CREATE␠INDEX␠"mz_continual_tasks_ind"␠IN␠CLUSTER␠[s2]␠ON␠[s528␠AS␠"mz_internal"."mz_continual_tasks"]␠("id") +mz_databases_ind CREATE␠INDEX␠"mz_databases_ind"␠IN␠CLUSTER␠[s2]␠ON␠[s471␠AS␠"mz_catalog"."mz_databases"]␠("name") mz_dataflow_addresses_per_worker_s2_primary_idx CREATE␠INDEX␠"mz_dataflow_addresses_per_worker_s2_primary_idx"␠IN␠CLUSTER␠[s2]␠ON␠"mz_introspection"."mz_dataflow_addresses_per_worker"␠("id",␠"worker_id") mz_dataflow_channels_per_worker_s2_primary_idx CREATE␠INDEX␠"mz_dataflow_channels_per_worker_s2_primary_idx"␠IN␠CLUSTER␠[s2]␠ON␠"mz_introspection"."mz_dataflow_channels_per_worker"␠("id",␠"worker_id") mz_dataflow_operator_reachability_raw_s2_primary_idx CREATE␠INDEX␠"mz_dataflow_operator_reachability_raw_s2_primary_idx"␠IN␠CLUSTER␠[s2]␠ON␠"mz_introspection"."mz_dataflow_operator_reachability_raw"␠("id",␠"worker_id",␠"source",␠"port",␠"update_type",␠"time") mz_dataflow_operators_per_worker_s2_primary_idx CREATE␠INDEX␠"mz_dataflow_operators_per_worker_s2_primary_idx"␠IN␠CLUSTER␠[s2]␠ON␠"mz_introspection"."mz_dataflow_operators_per_worker"␠("id",␠"worker_id") -mz_frontiers_ind CREATE␠INDEX␠"mz_frontiers_ind"␠IN␠CLUSTER␠[s2]␠ON␠[s715␠AS␠"mz_internal"."mz_frontiers"]␠("object_id") -mz_hydration_statuses_ind CREATE␠INDEX␠"mz_hydration_statuses_ind"␠IN␠CLUSTER␠[s2]␠ON␠[s737␠AS␠"mz_internal"."mz_hydration_statuses"]␠("object_id",␠"replica_id") -mz_indexes_ind CREATE␠INDEX␠"mz_indexes_ind"␠IN␠CLUSTER␠[s2]␠ON␠[s473␠AS␠"mz_catalog"."mz_indexes"]␠("id") -mz_kafka_sources_ind CREATE␠INDEX␠"mz_kafka_sources_ind"␠IN␠CLUSTER␠[s2]␠ON␠[s467␠AS␠"mz_catalog"."mz_kafka_sources"]␠("id") -mz_materialized_views_ind CREATE␠INDEX␠"mz_materialized_views_ind"␠IN␠CLUSTER␠[s2]␠ON␠[s525␠AS␠"mz_catalog"."mz_materialized_views"]␠("id") +mz_frontiers_ind CREATE␠INDEX␠"mz_frontiers_ind"␠IN␠CLUSTER␠[s2]␠ON␠[s716␠AS␠"mz_internal"."mz_frontiers"]␠("object_id") +mz_hydration_statuses_ind CREATE␠INDEX␠"mz_hydration_statuses_ind"␠IN␠CLUSTER␠[s2]␠ON␠[s738␠AS␠"mz_internal"."mz_hydration_statuses"]␠("object_id",␠"replica_id") +mz_indexes_ind CREATE␠INDEX␠"mz_indexes_ind"␠IN␠CLUSTER␠[s2]␠ON␠[s474␠AS␠"mz_catalog"."mz_indexes"]␠("id") +mz_kafka_sources_ind CREATE␠INDEX␠"mz_kafka_sources_ind"␠IN␠CLUSTER␠[s2]␠ON␠[s468␠AS␠"mz_catalog"."mz_kafka_sources"]␠("id") +mz_materialized_views_ind CREATE␠INDEX␠"mz_materialized_views_ind"␠IN␠CLUSTER␠[s2]␠ON␠[s526␠AS␠"mz_catalog"."mz_materialized_views"]␠("id") mz_message_batch_counts_received_raw_s2_primary_idx CREATE␠INDEX␠"mz_message_batch_counts_received_raw_s2_primary_idx"␠IN␠CLUSTER␠[s2]␠ON␠"mz_introspection"."mz_message_batch_counts_received_raw"␠("channel_id",␠"from_worker_id",␠"to_worker_id") mz_message_batch_counts_sent_raw_s2_primary_idx CREATE␠INDEX␠"mz_message_batch_counts_sent_raw_s2_primary_idx"␠IN␠CLUSTER␠[s2]␠ON␠"mz_introspection"."mz_message_batch_counts_sent_raw"␠("channel_id",␠"from_worker_id",␠"to_worker_id") mz_message_counts_received_raw_s2_primary_idx CREATE␠INDEX␠"mz_message_counts_received_raw_s2_primary_idx"␠IN␠CLUSTER␠[s2]␠ON␠"mz_introspection"."mz_message_counts_received_raw"␠("channel_id",␠"from_worker_id",␠"to_worker_id") mz_message_counts_sent_raw_s2_primary_idx CREATE␠INDEX␠"mz_message_counts_sent_raw_s2_primary_idx"␠IN␠CLUSTER␠[s2]␠ON␠"mz_introspection"."mz_message_counts_sent_raw"␠("channel_id",␠"from_worker_id",␠"to_worker_id") -mz_notices_ind CREATE␠INDEX␠"mz_notices_ind"␠IN␠CLUSTER␠[s2]␠ON␠[s807␠AS␠"mz_internal"."mz_notices"]␠("id") -mz_object_dependencies_ind CREATE␠INDEX␠"mz_object_dependencies_ind"␠IN␠CLUSTER␠[s2]␠ON␠[s468␠AS␠"mz_internal"."mz_object_dependencies"]␠("object_id") -mz_object_history_ind CREATE␠INDEX␠"mz_object_history_ind"␠IN␠CLUSTER␠[s2]␠ON␠[s537␠AS␠"mz_internal"."mz_object_history"]␠("id") -mz_object_lifetimes_ind CREATE␠INDEX␠"mz_object_lifetimes_ind"␠IN␠CLUSTER␠[s2]␠ON␠[s538␠AS␠"mz_internal"."mz_object_lifetimes"]␠("id") -mz_object_transitive_dependencies_ind CREATE␠INDEX␠"mz_object_transitive_dependencies_ind"␠IN␠CLUSTER␠[s2]␠ON␠[s554␠AS␠"mz_internal"."mz_object_transitive_dependencies"]␠("object_id") -mz_objects_ind CREATE␠INDEX␠"mz_objects_ind"␠IN␠CLUSTER␠[s2]␠ON␠[s534␠AS␠"mz_catalog"."mz_objects"]␠("schema_id") +mz_notices_ind CREATE␠INDEX␠"mz_notices_ind"␠IN␠CLUSTER␠[s2]␠ON␠[s808␠AS␠"mz_internal"."mz_notices"]␠("id") +mz_object_dependencies_ind CREATE␠INDEX␠"mz_object_dependencies_ind"␠IN␠CLUSTER␠[s2]␠ON␠[s469␠AS␠"mz_internal"."mz_object_dependencies"]␠("object_id") +mz_object_history_ind CREATE␠INDEX␠"mz_object_history_ind"␠IN␠CLUSTER␠[s2]␠ON␠[s538␠AS␠"mz_internal"."mz_object_history"]␠("id") +mz_object_lifetimes_ind CREATE␠INDEX␠"mz_object_lifetimes_ind"␠IN␠CLUSTER␠[s2]␠ON␠[s539␠AS␠"mz_internal"."mz_object_lifetimes"]␠("id") +mz_object_transitive_dependencies_ind CREATE␠INDEX␠"mz_object_transitive_dependencies_ind"␠IN␠CLUSTER␠[s2]␠ON␠[s555␠AS␠"mz_internal"."mz_object_transitive_dependencies"]␠("object_id") +mz_objects_ind CREATE␠INDEX␠"mz_objects_ind"␠IN␠CLUSTER␠[s2]␠ON␠[s535␠AS␠"mz_catalog"."mz_objects"]␠("schema_id") mz_peek_durations_histogram_raw_s2_primary_idx CREATE␠INDEX␠"mz_peek_durations_histogram_raw_s2_primary_idx"␠IN␠CLUSTER␠[s2]␠ON␠"mz_introspection"."mz_peek_durations_histogram_raw"␠("worker_id",␠"type",␠"duration_ns") -mz_recent_activity_log_thinned_ind CREATE␠INDEX␠"mz_recent_activity_log_thinned_ind"␠IN␠CLUSTER␠[s2]␠ON␠[s699␠AS␠"mz_internal"."mz_recent_activity_log_thinned"]␠("sql_hash") -mz_recent_sql_text_ind CREATE␠INDEX␠"mz_recent_sql_text_ind"␠IN␠CLUSTER␠[s2]␠ON␠[s695␠AS␠"mz_internal"."mz_recent_sql_text"]␠("sql_hash") -mz_recent_storage_usage_ind CREATE␠INDEX␠"mz_recent_storage_usage_ind"␠IN␠CLUSTER␠[s2]␠ON␠[s800␠AS␠"mz_catalog"."mz_recent_storage_usage"]␠("object_id") -mz_roles_ind CREATE␠INDEX␠"mz_roles_ind"␠IN␠CLUSTER␠[s2]␠ON␠[s491␠AS␠"mz_catalog"."mz_roles"]␠("id") +mz_recent_activity_log_thinned_ind CREATE␠INDEX␠"mz_recent_activity_log_thinned_ind"␠IN␠CLUSTER␠[s2]␠ON␠[s700␠AS␠"mz_internal"."mz_recent_activity_log_thinned"]␠("sql_hash") +mz_recent_sql_text_ind CREATE␠INDEX␠"mz_recent_sql_text_ind"␠IN␠CLUSTER␠[s2]␠ON␠[s696␠AS␠"mz_internal"."mz_recent_sql_text"]␠("sql_hash") +mz_recent_storage_usage_ind CREATE␠INDEX␠"mz_recent_storage_usage_ind"␠IN␠CLUSTER␠[s2]␠ON␠[s801␠AS␠"mz_catalog"."mz_recent_storage_usage"]␠("object_id") +mz_roles_ind CREATE␠INDEX␠"mz_roles_ind"␠IN␠CLUSTER␠[s2]␠ON␠[s492␠AS␠"mz_catalog"."mz_roles"]␠("id") mz_scheduling_elapsed_raw_s2_primary_idx CREATE␠INDEX␠"mz_scheduling_elapsed_raw_s2_primary_idx"␠IN␠CLUSTER␠[s2]␠ON␠"mz_introspection"."mz_scheduling_elapsed_raw"␠("id",␠"worker_id") mz_scheduling_parks_histogram_raw_s2_primary_idx CREATE␠INDEX␠"mz_scheduling_parks_histogram_raw_s2_primary_idx"␠IN␠CLUSTER␠[s2]␠ON␠"mz_introspection"."mz_scheduling_parks_histogram_raw"␠("worker_id",␠"slept_for_ns",␠"requested_ns") -mz_schemas_ind CREATE␠INDEX␠"mz_schemas_ind"␠IN␠CLUSTER␠[s2]␠ON␠[s471␠AS␠"mz_catalog"."mz_schemas"]␠("database_id") -mz_secrets_ind CREATE␠INDEX␠"mz_secrets_ind"␠IN␠CLUSTER␠[s2]␠ON␠[s502␠AS␠"mz_catalog"."mz_secrets"]␠("name") -mz_show_all_objects_ind CREATE␠INDEX␠"mz_show_all_objects_ind"␠IN␠CLUSTER␠[s2]␠ON␠[s582␠AS␠"mz_internal"."mz_show_all_objects"]␠("schema_id") -mz_show_cluster_replicas_ind CREATE␠INDEX␠"mz_show_cluster_replicas_ind"␠IN␠CLUSTER␠[s2]␠ON␠[s739␠AS␠"mz_internal"."mz_show_cluster_replicas"]␠("cluster") -mz_show_clusters_ind CREATE␠INDEX␠"mz_show_clusters_ind"␠IN␠CLUSTER␠[s2]␠ON␠[s584␠AS␠"mz_internal"."mz_show_clusters"]␠("name") -mz_show_columns_ind CREATE␠INDEX␠"mz_show_columns_ind"␠IN␠CLUSTER␠[s2]␠ON␠[s583␠AS␠"mz_internal"."mz_show_columns"]␠("id") -mz_show_connections_ind CREATE␠INDEX␠"mz_show_connections_ind"␠IN␠CLUSTER␠[s2]␠ON␠[s592␠AS␠"mz_internal"."mz_show_connections"]␠("schema_id") -mz_show_databases_ind CREATE␠INDEX␠"mz_show_databases_ind"␠IN␠CLUSTER␠[s2]␠ON␠[s586␠AS␠"mz_internal"."mz_show_databases"]␠("name") -mz_show_indexes_ind CREATE␠INDEX␠"mz_show_indexes_ind"␠IN␠CLUSTER␠[s2]␠ON␠[s596␠AS␠"mz_internal"."mz_show_indexes"]␠("schema_id") -mz_show_materialized_views_ind CREATE␠INDEX␠"mz_show_materialized_views_ind"␠IN␠CLUSTER␠[s2]␠ON␠[s595␠AS␠"mz_internal"."mz_show_materialized_views"]␠("schema_id") -mz_show_roles_ind CREATE␠INDEX␠"mz_show_roles_ind"␠IN␠CLUSTER␠[s2]␠ON␠[s591␠AS␠"mz_internal"."mz_show_roles"]␠("name") -mz_show_schemas_ind CREATE␠INDEX␠"mz_show_schemas_ind"␠IN␠CLUSTER␠[s2]␠ON␠[s587␠AS␠"mz_internal"."mz_show_schemas"]␠("database_id") -mz_show_secrets_ind CREATE␠INDEX␠"mz_show_secrets_ind"␠IN␠CLUSTER␠[s2]␠ON␠[s585␠AS␠"mz_internal"."mz_show_secrets"]␠("schema_id") -mz_show_sinks_ind CREATE␠INDEX␠"mz_show_sinks_ind"␠IN␠CLUSTER␠[s2]␠ON␠[s594␠AS␠"mz_internal"."mz_show_sinks"]␠("schema_id") -mz_show_sources_ind CREATE␠INDEX␠"mz_show_sources_ind"␠IN␠CLUSTER␠[s2]␠ON␠[s593␠AS␠"mz_internal"."mz_show_sources"]␠("schema_id") -mz_show_tables_ind CREATE␠INDEX␠"mz_show_tables_ind"␠IN␠CLUSTER␠[s2]␠ON␠[s588␠AS␠"mz_internal"."mz_show_tables"]␠("schema_id") -mz_show_types_ind CREATE␠INDEX␠"mz_show_types_ind"␠IN␠CLUSTER␠[s2]␠ON␠[s590␠AS␠"mz_internal"."mz_show_types"]␠("schema_id") -mz_show_views_ind CREATE␠INDEX␠"mz_show_views_ind"␠IN␠CLUSTER␠[s2]␠ON␠[s589␠AS␠"mz_internal"."mz_show_views"]␠("schema_id") -mz_sink_statistics_ind CREATE␠INDEX␠"mz_sink_statistics_ind"␠IN␠CLUSTER␠[s2]␠ON␠[s712␠AS␠"mz_internal"."mz_sink_statistics"]␠("id",␠"replica_id") -mz_sink_status_history_ind CREATE␠INDEX␠"mz_sink_status_history_ind"␠IN␠CLUSTER␠[s2]␠ON␠[s684␠AS␠"mz_internal"."mz_sink_status_history"]␠("sink_id") -mz_sink_statuses_ind CREATE␠INDEX␠"mz_sink_statuses_ind"␠IN␠CLUSTER␠[s2]␠ON␠[s685␠AS␠"mz_internal"."mz_sink_statuses"]␠("id") -mz_sinks_ind CREATE␠INDEX␠"mz_sinks_ind"␠IN␠CLUSTER␠[s2]␠ON␠[s483␠AS␠"mz_catalog"."mz_sinks"]␠("id") -mz_source_statistics_ind CREATE␠INDEX␠"mz_source_statistics_ind"␠IN␠CLUSTER␠[s2]␠ON␠[s710␠AS␠"mz_internal"."mz_source_statistics"]␠("id",␠"replica_id") -mz_source_statistics_with_history_ind CREATE␠INDEX␠"mz_source_statistics_with_history_ind"␠IN␠CLUSTER␠[s2]␠ON␠[s708␠AS␠"mz_internal"."mz_source_statistics_with_history"]␠("id",␠"replica_id") -mz_source_status_history_ind CREATE␠INDEX␠"mz_source_status_history_ind"␠IN␠CLUSTER␠[s2]␠ON␠[s686␠AS␠"mz_internal"."mz_source_status_history"]␠("source_id") -mz_source_statuses_ind CREATE␠INDEX␠"mz_source_statuses_ind"␠IN␠CLUSTER␠[s2]␠ON␠[s703␠AS␠"mz_internal"."mz_source_statuses"]␠("id") -mz_sources_ind CREATE␠INDEX␠"mz_sources_ind"␠IN␠CLUSTER␠[s2]␠ON␠[s476␠AS␠"mz_catalog"."mz_sources"]␠("id") -mz_tables_ind CREATE␠INDEX␠"mz_tables_ind"␠IN␠CLUSTER␠[s2]␠ON␠[s475␠AS␠"mz_catalog"."mz_tables"]␠("schema_id") -mz_types_ind CREATE␠INDEX␠"mz_types_ind"␠IN␠CLUSTER␠[s2]␠ON␠[s485␠AS␠"mz_catalog"."mz_types"]␠("schema_id") -mz_views_ind CREATE␠INDEX␠"mz_views_ind"␠IN␠CLUSTER␠[s2]␠ON␠[s484␠AS␠"mz_catalog"."mz_views"]␠("schema_id") -mz_wallclock_global_lag_recent_history_ind CREATE␠INDEX␠"mz_wallclock_global_lag_recent_history_ind"␠IN␠CLUSTER␠[s2]␠ON␠[s719␠AS␠"mz_internal"."mz_wallclock_global_lag_recent_history"]␠("object_id") -mz_webhook_sources_ind CREATE␠INDEX␠"mz_webhook_sources_ind"␠IN␠CLUSTER␠[s2]␠ON␠[s523␠AS␠"mz_internal"."mz_webhook_sources"]␠("id") -pg_attrdef_all_databases_ind CREATE␠INDEX␠"pg_attrdef_all_databases_ind"␠IN␠CLUSTER␠[s2]␠ON␠[s624␠AS␠"mz_internal"."pg_attrdef_all_databases"]␠("oid",␠"adrelid",␠"adnum",␠"adbin",␠"adsrc") -pg_attribute_all_databases_ind CREATE␠INDEX␠"pg_attribute_all_databases_ind"␠IN␠CLUSTER␠[s2]␠ON␠[s617␠AS␠"mz_internal"."pg_attribute_all_databases"]␠("attrelid",␠"attname",␠"atttypid",␠"attlen",␠"attnum",␠"atttypmod",␠"attnotnull",␠"atthasdef",␠"attidentity",␠"attgenerated",␠"attisdropped",␠"attcollation",␠"database_name",␠"pg_type_database_name") -pg_authid_core_ind CREATE␠INDEX␠"pg_authid_core_ind"␠IN␠CLUSTER␠[s2]␠ON␠[s634␠AS␠"mz_internal"."pg_authid_core"]␠("rolname") -pg_class_all_databases_ind CREATE␠INDEX␠"pg_class_all_databases_ind"␠IN␠CLUSTER␠[s2]␠ON␠[s605␠AS␠"mz_internal"."pg_class_all_databases"]␠("relname") -pg_description_all_databases_ind CREATE␠INDEX␠"pg_description_all_databases_ind"␠IN␠CLUSTER␠[s2]␠ON␠[s614␠AS␠"mz_internal"."pg_description_all_databases"]␠("objoid",␠"classoid",␠"objsubid",␠"description",␠"oid_database_name",␠"class_database_name") -pg_namespace_all_databases_ind CREATE␠INDEX␠"pg_namespace_all_databases_ind"␠IN␠CLUSTER␠[s2]␠ON␠[s602␠AS␠"mz_internal"."pg_namespace_all_databases"]␠("nspname") -pg_type_all_databases_ind CREATE␠INDEX␠"pg_type_all_databases_ind"␠IN␠CLUSTER␠[s2]␠ON␠[s611␠AS␠"mz_internal"."pg_type_all_databases"]␠("oid") +mz_schemas_ind CREATE␠INDEX␠"mz_schemas_ind"␠IN␠CLUSTER␠[s2]␠ON␠[s472␠AS␠"mz_catalog"."mz_schemas"]␠("database_id") +mz_secrets_ind CREATE␠INDEX␠"mz_secrets_ind"␠IN␠CLUSTER␠[s2]␠ON␠[s503␠AS␠"mz_catalog"."mz_secrets"]␠("name") +mz_show_all_objects_ind CREATE␠INDEX␠"mz_show_all_objects_ind"␠IN␠CLUSTER␠[s2]␠ON␠[s583␠AS␠"mz_internal"."mz_show_all_objects"]␠("schema_id") +mz_show_cluster_replicas_ind CREATE␠INDEX␠"mz_show_cluster_replicas_ind"␠IN␠CLUSTER␠[s2]␠ON␠[s740␠AS␠"mz_internal"."mz_show_cluster_replicas"]␠("cluster") +mz_show_clusters_ind CREATE␠INDEX␠"mz_show_clusters_ind"␠IN␠CLUSTER␠[s2]␠ON␠[s585␠AS␠"mz_internal"."mz_show_clusters"]␠("name") +mz_show_columns_ind CREATE␠INDEX␠"mz_show_columns_ind"␠IN␠CLUSTER␠[s2]␠ON␠[s584␠AS␠"mz_internal"."mz_show_columns"]␠("id") +mz_show_connections_ind CREATE␠INDEX␠"mz_show_connections_ind"␠IN␠CLUSTER␠[s2]␠ON␠[s593␠AS␠"mz_internal"."mz_show_connections"]␠("schema_id") +mz_show_databases_ind CREATE␠INDEX␠"mz_show_databases_ind"␠IN␠CLUSTER␠[s2]␠ON␠[s587␠AS␠"mz_internal"."mz_show_databases"]␠("name") +mz_show_indexes_ind CREATE␠INDEX␠"mz_show_indexes_ind"␠IN␠CLUSTER␠[s2]␠ON␠[s597␠AS␠"mz_internal"."mz_show_indexes"]␠("schema_id") +mz_show_materialized_views_ind CREATE␠INDEX␠"mz_show_materialized_views_ind"␠IN␠CLUSTER␠[s2]␠ON␠[s596␠AS␠"mz_internal"."mz_show_materialized_views"]␠("schema_id") +mz_show_roles_ind CREATE␠INDEX␠"mz_show_roles_ind"␠IN␠CLUSTER␠[s2]␠ON␠[s592␠AS␠"mz_internal"."mz_show_roles"]␠("name") +mz_show_schemas_ind CREATE␠INDEX␠"mz_show_schemas_ind"␠IN␠CLUSTER␠[s2]␠ON␠[s588␠AS␠"mz_internal"."mz_show_schemas"]␠("database_id") +mz_show_secrets_ind CREATE␠INDEX␠"mz_show_secrets_ind"␠IN␠CLUSTER␠[s2]␠ON␠[s586␠AS␠"mz_internal"."mz_show_secrets"]␠("schema_id") +mz_show_sinks_ind CREATE␠INDEX␠"mz_show_sinks_ind"␠IN␠CLUSTER␠[s2]␠ON␠[s595␠AS␠"mz_internal"."mz_show_sinks"]␠("schema_id") +mz_show_sources_ind CREATE␠INDEX␠"mz_show_sources_ind"␠IN␠CLUSTER␠[s2]␠ON␠[s594␠AS␠"mz_internal"."mz_show_sources"]␠("schema_id") +mz_show_tables_ind CREATE␠INDEX␠"mz_show_tables_ind"␠IN␠CLUSTER␠[s2]␠ON␠[s589␠AS␠"mz_internal"."mz_show_tables"]␠("schema_id") +mz_show_types_ind CREATE␠INDEX␠"mz_show_types_ind"␠IN␠CLUSTER␠[s2]␠ON␠[s591␠AS␠"mz_internal"."mz_show_types"]␠("schema_id") +mz_show_views_ind CREATE␠INDEX␠"mz_show_views_ind"␠IN␠CLUSTER␠[s2]␠ON␠[s590␠AS␠"mz_internal"."mz_show_views"]␠("schema_id") +mz_sink_statistics_ind CREATE␠INDEX␠"mz_sink_statistics_ind"␠IN␠CLUSTER␠[s2]␠ON␠[s713␠AS␠"mz_internal"."mz_sink_statistics"]␠("id",␠"replica_id") +mz_sink_status_history_ind CREATE␠INDEX␠"mz_sink_status_history_ind"␠IN␠CLUSTER␠[s2]␠ON␠[s685␠AS␠"mz_internal"."mz_sink_status_history"]␠("sink_id") +mz_sink_statuses_ind CREATE␠INDEX␠"mz_sink_statuses_ind"␠IN␠CLUSTER␠[s2]␠ON␠[s686␠AS␠"mz_internal"."mz_sink_statuses"]␠("id") +mz_sinks_ind CREATE␠INDEX␠"mz_sinks_ind"␠IN␠CLUSTER␠[s2]␠ON␠[s484␠AS␠"mz_catalog"."mz_sinks"]␠("id") +mz_source_statistics_ind CREATE␠INDEX␠"mz_source_statistics_ind"␠IN␠CLUSTER␠[s2]␠ON␠[s711␠AS␠"mz_internal"."mz_source_statistics"]␠("id",␠"replica_id") +mz_source_statistics_with_history_ind CREATE␠INDEX␠"mz_source_statistics_with_history_ind"␠IN␠CLUSTER␠[s2]␠ON␠[s709␠AS␠"mz_internal"."mz_source_statistics_with_history"]␠("id",␠"replica_id") +mz_source_status_history_ind CREATE␠INDEX␠"mz_source_status_history_ind"␠IN␠CLUSTER␠[s2]␠ON␠[s687␠AS␠"mz_internal"."mz_source_status_history"]␠("source_id") +mz_source_statuses_ind CREATE␠INDEX␠"mz_source_statuses_ind"␠IN␠CLUSTER␠[s2]␠ON␠[s704␠AS␠"mz_internal"."mz_source_statuses"]␠("id") +mz_sources_ind CREATE␠INDEX␠"mz_sources_ind"␠IN␠CLUSTER␠[s2]␠ON␠[s477␠AS␠"mz_catalog"."mz_sources"]␠("id") +mz_tables_ind CREATE␠INDEX␠"mz_tables_ind"␠IN␠CLUSTER␠[s2]␠ON␠[s476␠AS␠"mz_catalog"."mz_tables"]␠("schema_id") +mz_types_ind CREATE␠INDEX␠"mz_types_ind"␠IN␠CLUSTER␠[s2]␠ON␠[s486␠AS␠"mz_catalog"."mz_types"]␠("schema_id") +mz_views_ind CREATE␠INDEX␠"mz_views_ind"␠IN␠CLUSTER␠[s2]␠ON␠[s485␠AS␠"mz_catalog"."mz_views"]␠("schema_id") +mz_wallclock_global_lag_recent_history_ind CREATE␠INDEX␠"mz_wallclock_global_lag_recent_history_ind"␠IN␠CLUSTER␠[s2]␠ON␠[s720␠AS␠"mz_internal"."mz_wallclock_global_lag_recent_history"]␠("object_id") +mz_webhook_sources_ind CREATE␠INDEX␠"mz_webhook_sources_ind"␠IN␠CLUSTER␠[s2]␠ON␠[s524␠AS␠"mz_internal"."mz_webhook_sources"]␠("id") +pg_attrdef_all_databases_ind CREATE␠INDEX␠"pg_attrdef_all_databases_ind"␠IN␠CLUSTER␠[s2]␠ON␠[s625␠AS␠"mz_internal"."pg_attrdef_all_databases"]␠("oid",␠"adrelid",␠"adnum",␠"adbin",␠"adsrc") +pg_attribute_all_databases_ind CREATE␠INDEX␠"pg_attribute_all_databases_ind"␠IN␠CLUSTER␠[s2]␠ON␠[s618␠AS␠"mz_internal"."pg_attribute_all_databases"]␠("attrelid",␠"attname",␠"atttypid",␠"attlen",␠"attnum",␠"atttypmod",␠"attnotnull",␠"atthasdef",␠"attidentity",␠"attgenerated",␠"attisdropped",␠"attcollation",␠"database_name",␠"pg_type_database_name") +pg_authid_core_ind CREATE␠INDEX␠"pg_authid_core_ind"␠IN␠CLUSTER␠[s2]␠ON␠[s635␠AS␠"mz_internal"."pg_authid_core"]␠("rolname") +pg_class_all_databases_ind CREATE␠INDEX␠"pg_class_all_databases_ind"␠IN␠CLUSTER␠[s2]␠ON␠[s606␠AS␠"mz_internal"."pg_class_all_databases"]␠("relname") +pg_description_all_databases_ind CREATE␠INDEX␠"pg_description_all_databases_ind"␠IN␠CLUSTER␠[s2]␠ON␠[s615␠AS␠"mz_internal"."pg_description_all_databases"]␠("objoid",␠"classoid",␠"objsubid",␠"description",␠"oid_database_name",␠"class_database_name") +pg_namespace_all_databases_ind CREATE␠INDEX␠"pg_namespace_all_databases_ind"␠IN␠CLUSTER␠[s2]␠ON␠[s603␠AS␠"mz_internal"."pg_namespace_all_databases"]␠("nspname") +pg_type_all_databases_ind CREATE␠INDEX␠"pg_type_all_databases_ind"␠IN␠CLUSTER␠[s2]␠ON␠[s612␠AS␠"mz_internal"."pg_type_all_databases"]␠("oid") # Record all transitive dependencies (tables, sources, views, mvs) of indexes on # the mz_catalog_server cluster. diff --git a/test/sqllogictest/oid.slt b/test/sqllogictest/oid.slt index 319b8507359f9..5026d0c0c537d 100644 --- a/test/sqllogictest/oid.slt +++ b/test/sqllogictest/oid.slt @@ -1182,3 +1182,4 @@ SELECT oid, name FROM mz_objects WHERE id LIKE 's%' AND oid < 20000 ORDER BY oid 17072 mz_builtin_materialized_views 17073 parse_catalog_create_sql 17074 redact_sql +17075 repeat_row_non_negative diff --git a/test/sqllogictest/table_func.slt b/test/sqllogictest/table_func.slt index 930582186105e..321402833e8a5 100644 --- a/test/sqllogictest/table_func.slt +++ b/test/sqllogictest/table_func.slt @@ -26,6 +26,11 @@ ALTER SYSTEM SET enable_repeat_row = true ---- COMPLETE 0 +simple conn=mz_system,user=mz_system +ALTER SYSTEM SET enable_repeat_row_non_negative = true +---- +COMPLETE 0 + statement ok CREATE TABLE y (a JSONB); @@ -462,8 +467,21 @@ SELECT * FROM generate_series(0,3), repeat_row(generate_series); 3 3 -query II +query I +SELECT * FROM generate_series(0,3), repeat_row_non_negative(generate_series); +---- +1 +2 +2 +3 +3 +3 + +query error WITH ORDINALITY on repeat_row not yet supported SELECT * FROM generate_series(0,3), repeat_row(generate_series) WITH ORDINALITY; + +query II +SELECT * FROM generate_series(0,3), repeat_row_non_negative(generate_series) WITH ORDINALITY; ---- 1 1 2 1 @@ -472,8 +490,11 @@ SELECT * FROM generate_series(0,3), repeat_row(generate_series) WITH ORDINALITY; 3 2 3 3 -query II +query error WITH ORDINALITY on repeat_row not yet supported SELECT * FROM generate_series(0,3), repeat_row(abs(generate_series - 1)) WITH ORDINALITY; + +query II +SELECT * FROM generate_series(0,3), repeat_row_non_negative(abs(generate_series - 1)) WITH ORDINALITY; ---- 0 1 2 1 @@ -486,6 +507,20 @@ SELECT abs(generate_series) FROM generate_series(-1, 2), repeat_row(generate_ser 2 2 +query error repeat_row_non_negative got \-1 +SELECT abs(generate_series) FROM generate_series(-1, 2), repeat_row_non_negative(generate_series); + +query error repeat_row_non_negative got \-7 +SELECT 4 FROM repeat_row_non_negative(-7); + +query I +SELECT 5 FROM repeat_row(null); +---- + +query I +SELECT 5 FROM repeat_row_non_negative(null); +---- + statement error Negative multiplicity in constant result: -1 SELECT * FROM (values ('a')), repeat_row(-1) @@ -795,10 +830,25 @@ SELECT jsonb_array_elements.generate_series FROM ROWS FROM (jsonb_array_elements generate_series 1 -query T colnames,rowsort +query error repeat_row in ROWS FROM not yet supported SELECT repeat_row FROM ROWS FROM (repeat_row(2), generate_series(1, 1)); + +query error repeat_row in a SELECT clause with multiple table functions not yet supported +SELECT repeat_row(5), generate_series(1,2); + +query TI +SELECT repeat_row_non_negative(5), generate_series(1,2); +---- +() NULL +() NULL +() NULL +() 1 +() 2 + +query T colnames,rowsort +SELECT repeat_row_non_negative FROM ROWS FROM (repeat_row_non_negative(2), generate_series(1, 1)); ---- -repeat_row +repeat_row_non_negative () (1) diff --git a/test/sqllogictest/transform/relax_must_consolidate.slt b/test/sqllogictest/transform/relax_must_consolidate.slt index 2540946a84c14..aa6543c0db67b 100644 --- a/test/sqllogictest/transform/relax_must_consolidate.slt +++ b/test/sqllogictest/transform/relax_must_consolidate.slt @@ -1203,3 +1203,169 @@ Explained Query: Target cluster: quickstart EOF + +simple conn=mz_system,user=mz_system +ALTER SYSTEM SET enable_repeat_row = true +---- +COMPLETE 0 + +simple conn=mz_system,user=mz_system +ALTER SYSTEM SET enable_repeat_row_non_negative = true +---- +COMPLETE 0 + +statement ok +CREATE SOURCE mono_src FROM WEBHOOK BODY FORMAT TEXT; + +# Regression test for https://github.com/MaterializeInc/database-issues/issues/11310, i.e., that we set the +# `must_consolidate` flag when `repeat_row` is involved. +# Relies on RelaxMustConsolidate's SingleTimeMonotonic correctly handling FlatMap's TableFunc being !preserves_monotonicity. +# Note that the plans are still somewhat wrong, in that monotonic operators won't produce correct results when presented +# with negative accumulations even with the `must_consolidate` flag set. However, the expectation is that they'll have +# an easier time detecting negative accumulations and cleanly erroring out when the `must_consolidate` flag is set. +# See also https://github.com/MaterializeInc/materialize/pull/36184 for more discussion, where we considered not +# choosing monotonic operators when `repeat_row` is involved, but eventually decided to go with the current behavior. +query T multiline +EXPLAIN PHYSICAL PLAN AS VERBOSE TEXT FOR +SELECT MAX(body) FROM mono_src, repeat_row(length(body)); +---- +Explained Query: + With + cte l0 = + Reduce::Hierarchical + aggr_funcs=[max] + monotonic + must_consolidate + key_plan + project=() + val_plan=id + FlatMap repeat_row(integer_to_bigint(char_length(#0{body}))) + Get::PassArrangements materialize.public.mono_src + raw=true + Return + Union + ArrangeBy + input_key=[] + raw=true + Get::PassArrangements l0 + raw=false + arrangements[0]={ key=[], permutation=id, thinning=(#0) } + Mfp + project=(#0) + map=(null) + Union consolidate_output=true + Negate + Get::Arrangement l0 + project=() + key= + raw=false + arrangements[0]={ key=[], permutation=id, thinning=(#0) } + Constant + - () + +Source materialize.public.mono_src + +Target cluster: quickstart + +EOF + +# Relies on RelaxMustConsolidate's SingleTimeMonotonic correctly handling negative diffs in Constants. +query T multiline +EXPLAIN PHYSICAL PLAN AS VERBOSE TEXT FOR +SELECT MAX(body) FROM mono_src, repeat_row(-1); +---- +Explained Query: + With + cte l0 = + Reduce::Hierarchical + aggr_funcs=[max] + monotonic + must_consolidate + key_plan + project=() + val_plan=id + Join::Linear + linear_stage[0] + lookup={ relation=1, key=[] } + stream={ key=[], thinning=(#0) } + source={ relation=0, key=[] } + ArrangeBy + raw=true + arrangements[0]={ key=[], permutation=id, thinning=(#0) } + Get::PassArrangements materialize.public.mono_src + raw=true + ArrangeBy + raw=true + arrangements[0]={ key=[], permutation=id, thinning=() } + Constant + - (() x -1) + Return + Union + ArrangeBy + input_key=[] + raw=true + Get::PassArrangements l0 + raw=false + arrangements[0]={ key=[], permutation=id, thinning=(#0) } + Mfp + project=(#0) + map=(null) + Union consolidate_output=true + Negate + Get::Arrangement l0 + project=() + key= + raw=false + arrangements[0]={ key=[], permutation=id, thinning=(#0) } + Constant + - () + +Source materialize.public.mono_src + +Target cluster: quickstart + +EOF + +# Relies on `repeat_row_non_negative` being marked as `preserves_monotonicity` (as opposed to `repeat_row`). +query T multiline +EXPLAIN PHYSICAL PLAN AS VERBOSE TEXT FOR +SELECT MAX(body) FROM mono_src, repeat_row_non_negative(length(body)); +---- +Explained Query: + With + cte l0 = + Reduce::Hierarchical + aggr_funcs=[max] + monotonic + key_plan + project=() + val_plan=id + FlatMap repeat_row_non_negative(integer_to_bigint(char_length(#0{body}))) + Get::PassArrangements materialize.public.mono_src + raw=true + Return + Union + ArrangeBy + input_key=[] + raw=true + Get::PassArrangements l0 + raw=false + arrangements[0]={ key=[], permutation=id, thinning=(#0) } + Mfp + project=(#0) + map=(null) + Union consolidate_output=true + Negate + Get::Arrangement l0 + project=() + key= + raw=false + arrangements[0]={ key=[], permutation=id, thinning=(#0) } + Constant + - () + +Source materialize.public.mono_src + +Target cluster: quickstart + +EOF