Skip to content

Commit cda0174

Browse files
committed
Add repeat_row_non_negative as a new SQL function
1 parent 55d2af2 commit cda0174

7 files changed

Lines changed: 198 additions & 75 deletions

File tree

src/expr/src/relation/func.rs

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3289,6 +3289,22 @@ pub fn repeat_row(a: Datum) -> Option<(Row, Diff)> {
32893289
}
32903290
}
32913291

3292+
pub fn repeat_row_non_negative<'a>(
3293+
a: Datum,
3294+
) -> Result<Box<dyn Iterator<Item = (Row, Diff)> + 'a>, EvalError> {
3295+
let n = a.unwrap_int64();
3296+
if n < 0 {
3297+
Err(EvalError::InvalidParameterValue(
3298+
format!("repeat_row_non_negative got {}", n).into(),
3299+
))
3300+
} else if n == 0 {
3301+
Ok(Box::new(iter::empty()))
3302+
} else {
3303+
// iterator with 1 element; n goes into the diff
3304+
Ok(Box::new(iter::once((Row::default(), n.into()))))
3305+
}
3306+
}
3307+
32923308
fn wrap<'a>(datums: &'a [Datum<'a>], width: usize) -> impl Iterator<Item = (Row, Diff)> + 'a {
32933309
datums
32943310
.chunks(width)
@@ -3396,7 +3412,16 @@ pub enum TableFunc {
33963412
GuardSubquerySize {
33973413
column_type: SqlScalarType,
33983414
},
3415+
/// Repeats the input row the given number of times. Can even repeat a negative number of times,
3416+
/// which has some important consequences:
3417+
/// - can lead to negative accumulations downstream;
3418+
/// - can't be used in `WITH ORDINALITY` and other constructs that are implemented by
3419+
/// `TableFunc::WithOrdinality`, e.g., `ROWS FROM`;
3420+
/// - output is non-monotonic.
33993421
RepeatRow,
3422+
/// Same as `RepeatRow`, but errors on a negative count, and thereby avoids the above
3423+
/// peculiarities.
3424+
RepeatRowNonNegative,
34003425
UnnestArray {
34013426
el_typ: SqlScalarType,
34023427
},
@@ -3471,7 +3496,8 @@ impl TableFunc {
34713496
| TableFunc::GenerateSeriesTimestamp
34723497
| TableFunc::GenerateSeriesTimestampTz
34733498
| TableFunc::GuardSubquerySize { .. }
3474-
| TableFunc::RepeatRow
3499+
| TableFunc::RepeatRow // TODO: will move this to the not allowed category in the next commit
3500+
| TableFunc::RepeatRowNonNegative
34753501
| TableFunc::UnnestArray { .. }
34763502
| TableFunc::UnnestList { .. }
34773503
| TableFunc::UnnestMap { .. }
@@ -3567,6 +3593,7 @@ impl TableFunc {
35673593
}
35683594
}
35693595
TableFunc::RepeatRow => Ok(Box::new(repeat_row(datums[0]).into_iter())),
3596+
TableFunc::RepeatRowNonNegative => repeat_row_non_negative(datums[0]),
35703597
TableFunc::UnnestArray { .. } => Ok(Box::new(unnest_array(datums[0]))),
35713598
TableFunc::UnnestList { .. } => Ok(Box::new(unnest_list(datums[0]))),
35723599
TableFunc::UnnestMap { .. } => Ok(Box::new(unnest_map(datums[0]))),
@@ -3682,7 +3709,7 @@ impl TableFunc {
36823709
let keys = vec![];
36833710
(column_types, keys)
36843711
}
3685-
TableFunc::RepeatRow => {
3712+
TableFunc::RepeatRow | TableFunc::RepeatRowNonNegative => {
36863713
let column_types = vec![];
36873714
let keys = vec![];
36883715
(column_types, keys)
@@ -3764,6 +3791,7 @@ impl TableFunc {
37643791
TableFunc::GenerateSubscriptsArray => 1,
37653792
TableFunc::GuardSubquerySize { .. } => 1,
37663793
TableFunc::RepeatRow => 0,
3794+
TableFunc::RepeatRowNonNegative => 0,
37673795
TableFunc::UnnestArray { .. } => 1,
37683796
TableFunc::UnnestList { .. } => 1,
37693797
TableFunc::UnnestMap { .. } => 2,
@@ -3791,6 +3819,7 @@ impl TableFunc {
37913819
| TableFunc::RegexpExtract(_)
37923820
| TableFunc::CsvExtract(_)
37933821
| TableFunc::RepeatRow
3822+
| TableFunc::RepeatRowNonNegative
37943823
| TableFunc::UnnestArray { .. }
37953824
| TableFunc::UnnestList { .. }
37963825
| TableFunc::UnnestMap { .. }
@@ -3822,6 +3851,7 @@ impl TableFunc {
38223851
TableFunc::GenerateSeriesTimestampTz => true,
38233852
TableFunc::GenerateSubscriptsArray => true,
38243853
TableFunc::RepeatRow => false,
3854+
TableFunc::RepeatRowNonNegative => true,
38253855
TableFunc::UnnestArray { .. } => true,
38263856
TableFunc::UnnestList { .. } => true,
38273857
TableFunc::UnnestMap { .. } => true,
@@ -3853,6 +3883,7 @@ impl fmt::Display for TableFunc {
38533883
TableFunc::GenerateSubscriptsArray => f.write_str("generate_subscripts"),
38543884
TableFunc::GuardSubquerySize { .. } => f.write_str("guard_subquery_size"),
38553885
TableFunc::RepeatRow => f.write_str("repeat_row"),
3886+
TableFunc::RepeatRowNonNegative => f.write_str("repeat_row_non_negative"),
38563887
TableFunc::UnnestArray { .. } => f.write_str("unnest_array"),
38573888
TableFunc::UnnestList { .. } => f.write_str("unnest_list"),
38583889
TableFunc::UnnestMap { .. } => f.write_str("unnest_map"),

src/pgrepr-consts/src/oid.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -792,3 +792,4 @@ pub const VIEW_MZ_MCP_DATA_PRODUCT_DETAILS_OID: u32 = 17071;
792792
pub const VIEW_MZ_BUILTIN_MATERIALIZED_VIEWS_OID: u32 = 17072;
793793
pub const FUNC_PARSE_CATALOG_CREATE_SQL_OID: u32 = 17073;
794794
pub const FUNC_REDACT_SQL_OID: u32 = 17074;
795+
pub const FUNC_REPEAT_ROW_NON_NEGATIVE_OID: u32 = 17075;

src/sql/src/func.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4745,6 +4745,18 @@ pub static MZ_CATALOG_BUILTINS: LazyLock<BTreeMap<&'static str, Func>> = LazyLoc
47454745
})
47464746
}) => ReturnType::none(true), oid::FUNC_REPEAT_ROW_OID;
47474747
},
4748+
"repeat_row_non_negative" => Table {
4749+
params!(Int64) => Operation::unary(move |ecx, n| {
4750+
ecx.require_feature_flag(&vars::ENABLE_REPEAT_ROW_NON_NEGATIVE)?;
4751+
Ok(TableFuncPlan {
4752+
imp: TableFuncImpl::CallTable {
4753+
func: TableFunc::RepeatRowNonNegative,
4754+
exprs: vec![n],
4755+
},
4756+
column_names: vec![]
4757+
})
4758+
}) => ReturnType::none(true), oid::FUNC_REPEAT_ROW_NON_NEGATIVE_OID;
4759+
},
47484760
"seahash" => Scalar {
47494761
params!(String) => UnaryFunc::SeahashString(func::SeahashString)
47504762
=> UInt32, oid::FUNC_SEAHASH_STRING_OID;

src/sql/src/session/vars/definitions.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1880,6 +1880,12 @@ feature_flags!(
18801880
default: false,
18811881
enable_for_item_parsing: true,
18821882
},
1883+
{
1884+
name: enable_repeat_row_non_negative,
1885+
desc: "the repeat_row_non_negative function",
1886+
default: false,
1887+
enable_for_item_parsing: true,
1888+
},
18831889
{
18841890
name: enable_replica_targeted_materialized_views,
18851891
desc: "replica-targeted materialized views",

0 commit comments

Comments
 (0)