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

Function plan_values_insert

src/sql/src/plan/query.rs:2159–2218  ·  view source on GitHub ↗

Plans a `VALUES` clause that appears at the top level of an `INSERT` statement. This is special-cased in PostgreSQL and different enough from `plan_values` that it is easier to use a separate function entirely. Unlike a normal `VALUES` clause, each value is coerced to the type of the target table via an assignment cast. See: <https://github.com/postgres/postgres/blob/ad77039fa/src/backend/parser

(
    qcx: &QueryContext,
    target_names: &[&ColumnName],
    target_types: &[&SqlScalarType],
    values: &[Vec<Expr<Aug>>],
)

Source from the content-addressed store, hash-verified

2157///
2158/// See: <https://github.com/postgres/postgres/blob/ad77039fa/src/backend/parser/analyze.c#L504-L518>
2159fn plan_values_insert(
2160 qcx: &QueryContext,
2161 target_names: &[&ColumnName],
2162 target_types: &[&SqlScalarType],
2163 values: &[Vec<Expr<Aug>>],
2164) -> Result<HirRelationExpr, PlanError> {
2165 assert!(!values.is_empty());
2166
2167 if !values.iter().map(|row| row.len()).all_equal() {
2168 sql_bail!("VALUES lists must all be the same length");
2169 }
2170
2171 let ecx = &ExprContext {
2172 qcx,
2173 name: "VALUES",
2174 scope: &Scope::empty(),
2175 relation_type: &SqlRelationType::empty(),
2176 allow_aggregates: false,
2177 allow_subqueries: true,
2178 allow_parameters: true,
2179 allow_windows: false,
2180 };
2181
2182 let mut exprs = vec![];
2183 let mut types = vec![];
2184 for row in values {
2185 if row.len() > target_names.len() {
2186 sql_bail!("INSERT has more expressions than target columns");
2187 }
2188 for (column, val) in row.into_iter().enumerate() {
2189 let target_type = &target_types[column];
2190 let val = plan_expr(ecx, val)?;
2191 let val = typeconv::plan_coerce(ecx, val, target_type)?;
2192 let source_type = &ecx.scalar_type(&val);
2193 let val = match typeconv::plan_cast(ecx, CastContext::Assignment, val, target_type) {
2194 Ok(val) => val,
2195 Err(_) => sql_bail!(
2196 "column {} is of type {} but expression is of type {}",
2197 target_names[column].quoted(),
2198 qcx.humanize_sql_scalar_type(target_type, false),
2199 qcx.humanize_sql_scalar_type(source_type, false),
2200 ),
2201 };
2202 if column >= types.len() {
2203 types.push(ecx.column_type(&val));
2204 } else {
2205 types[column] = types[column].sql_union(&ecx.column_type(&val))?; // HIR deliberately not using `union`
2206 }
2207 exprs.push(val);
2208 }
2209 }
2210
2211 Ok(HirRelationExpr::CallTable {
2212 func: TableFunc::Wrap {
2213 width: values[0].len(),
2214 types,
2215 },
2216 exprs,

Callers 1

plan_insert_queryFunction · 0.85

Calls 13

plan_exprFunction · 0.85
plan_coerceFunction · 0.85
all_equalMethod · 0.80
enumerateMethod · 0.80
column_typeMethod · 0.80
sql_unionMethod · 0.80
plan_castFunction · 0.70
mapMethod · 0.45
iterMethod · 0.45
lenMethod · 0.45
into_iterMethod · 0.45
scalar_typeMethod · 0.45

Tested by

no test coverage detected