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

Function generate_column_casts

src/sql/src/pure/postgres.rs:553–640  ·  view source on GitHub ↗
(
    scx: &StatementContext,
    table: &PostgresTableDesc,
    text_columns: &Vec<Ident>,
)

Source from the content-addressed store, hash-verified

551}
552
553pub(crate) fn generate_column_casts(
554 scx: &StatementContext,
555 table: &PostgresTableDesc,
556 text_columns: &Vec<Ident>,
557) -> Result<Vec<(CastType, StorageScalarExpr)>, PlanError> {
558 // Generate the cast expressions required to convert the text encoded columns into
559 // the appropriate target types, creating a Vec<StorageScalarExpr>.
560 // The postgres source reader will then eval each of those on the incoming rows.
561
562 let text_columns = BTreeSet::from_iter(text_columns.iter().map(Ident::as_str));
563
564 let mut table_cast = vec![];
565 for (i, column) in table.columns.iter().enumerate() {
566 let (cast_type, ty) = if text_columns.contains(column.name.as_str()) {
567 // Treat the column as text if it was referenced in
568 // `TEXT COLUMNS`. This is the only place we need to
569 // perform this logic; even if the type is unsupported,
570 // we'll be able to ingest its values as text in
571 // storage.
572 (CastType::Text, mz_pgrepr::Type::Text)
573 } else {
574 match mz_pgrepr::Type::from_oid_and_typmod(column.type_oid, column.type_mod) {
575 Ok(t) => (CastType::Natural, t),
576 // If this reference survived purification, we
577 // do not expect it to be from a table that the
578 // user will consume., i.e. expect this table to
579 // be filtered out of table casts.
580 Err(_) => {
581 table_cast.push((
582 CastType::Natural,
583 StorageScalarExpr::ErrorIfNull(
584 Box::new(StorageScalarExpr::Literal(
585 Row::pack_slice(&[Datum::Null]),
586 ReprColumnType {
587 nullable: true,
588 scalar_type: ReprScalarType::String,
589 },
590 )),
591 format!("Unsupported type with OID {}", column.type_oid),
592 ),
593 ));
594 continue;
595 }
596 }
597 };
598
599 let cast_expr = match pg_type_to_cast_func(scx, &ty) {
600 Ok(None) => {
601 // No cast needed (e.g. Text → String identity).
602 StorageScalarExpr::Column(i)
603 }
604 Ok(Some(cast_func)) => {
605 StorageScalarExpr::CallUnary(cast_func, Box::new(StorageScalarExpr::Column(i)))
606 }
607 Err(PlanError::TableContainsUningestableTypes { type_, .. }) => {
608 // We expect only reg* types and similar to encounter
609 // this. Users can ingest the data as text if they need
610 // to. This is acceptable because we don't expect the

Callers 2

plan_create_subsourceFunction · 0.85

Calls 10

ErrorIfNullClass · 0.85
pg_type_to_cast_funcFunction · 0.85
enumerateMethod · 0.80
ColumnEnum · 0.50
mapMethod · 0.45
iterMethod · 0.45
containsMethod · 0.45
as_strMethod · 0.45
pushMethod · 0.45
to_stringMethod · 0.45

Tested by

no test coverage detected