MCPcopy Create free account
hub / github.com/MaterializeInc/materialize / plan_rows_from

Function plan_rows_from

src/sql/src/plan/query.rs:3082–3138  ·  view source on GitHub ↗

Plans a `ROWS FROM` expression. `ROWS FROM` concatenates table functions into a single table, filling in `NULL`s in places where one table function has fewer rows than another. We can achieve this by augmenting each table function with a row number, doing a `FULL JOIN` between each table function on the row number and eventually projecting away the row number columns. Concretely, the following qu

(
    qcx: &QueryContext,
    functions: &[Function<Aug>],
    alias: Option<&TableAlias>,
    with_ordinality: bool,
)

Source from the content-addressed store, hash-verified

3080/// `with_ordinality` can be used to have the output expression contain a
3081/// single coalesced ordinality column at the end of the entire expression.
3082fn plan_rows_from(
3083 qcx: &QueryContext,
3084 functions: &[Function<Aug>],
3085 alias: Option<&TableAlias>,
3086 with_ordinality: bool,
3087) -> Result<(HirRelationExpr, Scope), PlanError> {
3088 // The `repeat_row` function is not supported in ROWS FROM.
3089 if functions.iter().any(is_repeat_row) {
3090 // Note: Would be also caught by WITH ORDINALITY checking for `repeat_row`, but then the
3091 // error message would be misleading, because it would refer to WITH ORDINALITY instead of
3092 // ROWS FROM.
3093 bail_unsupported!(format!("{} in ROWS FROM", REPEAT_ROW_NAME));
3094 }
3095
3096 // If there's only a single table function, planning proceeds as if `ROWS
3097 // FROM` hadn't been written at all.
3098 if let [function] = functions {
3099 return plan_solitary_table_function(qcx, function, alias, with_ordinality);
3100 }
3101
3102 // Per PostgreSQL, all scope items take the name of the first function
3103 // (unless aliased).
3104 // See: https://github.com/postgres/postgres/blob/639a86e36/src/backend/parser/parse_relation.c#L1701-L1705
3105 let (expr, mut scope, num_cols) = plan_rows_from_internal(
3106 qcx,
3107 functions,
3108 Some(functions[0].name.full_item_name().clone()),
3109 )?;
3110
3111 // Columns tracks the set of columns we will keep in the projection.
3112 let mut columns = Vec::new();
3113 let mut offset = 0;
3114 // Retain table function's non-ordinality columns.
3115 for (idx, cols) in num_cols.into_iter().enumerate() {
3116 for i in 0..cols {
3117 columns.push(offset + i);
3118 }
3119 offset += cols + 1;
3120
3121 // Remove the ordinality column from the scope, accounting for previous scope
3122 // changes from this loop.
3123 scope.items.remove(offset - idx - 1);
3124 }
3125
3126 // If `WITH ORDINALITY` was specified, include the coalesced ordinality
3127 // column. Otherwise remove it from the scope.
3128 if with_ordinality {
3129 columns.push(offset);
3130 } else {
3131 scope.items.pop();
3132 }
3133
3134 let expr = expr.project(columns);
3135
3136 let scope = plan_table_alias(scope, alias)?;
3137 Ok((expr, scope))
3138}
3139

Callers 1

plan_table_factorFunction · 0.85

Calls 13

plan_rows_from_internalFunction · 0.85
plan_table_aliasFunction · 0.85
anyMethod · 0.80
full_item_nameMethod · 0.80
enumerateMethod · 0.80
iterMethod · 0.45
cloneMethod · 0.45
into_iterMethod · 0.45
pushMethod · 0.45
removeMethod · 0.45
popMethod · 0.45

Tested by

no test coverage detected