Skip to content

Commit e5de897

Browse files
authored
Normalize generated VALUES columns for uppercase identifiers (#160)
1 parent f6089be commit e5de897

2 files changed

Lines changed: 71 additions & 2 deletions

File tree

‎datafusion/sql/src/values.rs‎

Lines changed: 41 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -420,11 +420,12 @@ impl<S: ContextProvider> SqlToRel<'_, S> {
420420
})
421421
.collect::<Vec<_>>();
422422
if array_columns.is_empty() {
423-
return if schema.fields().is_empty() {
423+
let plan = if schema.fields().is_empty() {
424424
LogicalPlanBuilder::values(values)?.build()
425425
} else {
426426
LogicalPlanBuilder::values_with_schema(values, &schema)?.build()
427427
};
428+
return self.normalize_values_column_names(plan?);
428429
}
429430
for row in &values {
430431
for expr in row {
@@ -560,10 +561,48 @@ impl<S: ContextProvider> SqlToRel<'_, S> {
560561
Default::default(),
561562
)?)
562563
};
563-
if values_schema.fields().is_empty() {
564+
let plan = if values_schema.fields().is_empty() {
564565
LogicalPlanBuilder::values(values)?.build()
565566
} else {
566567
LogicalPlanBuilder::values_with_schema(values, &values_schema)?.build()
568+
};
569+
self.normalize_values_column_names(plan?)
570+
}
571+
572+
fn normalize_values_column_names(
573+
&self,
574+
mut plan: LogicalPlan,
575+
) -> Result<LogicalPlan> {
576+
if !self.options.enable_ident_normalization
577+
|| !self
578+
.context_provider
579+
.options()
580+
.sql_parser
581+
.uppercase_unquoted_identifiers
582+
{
583+
return Ok(plan);
584+
}
585+
586+
if let LogicalPlan::Values(values) = &mut plan {
587+
let fields = values
588+
.schema
589+
.fields()
590+
.iter()
591+
.map(|field| {
592+
Arc::new(
593+
field
594+
.as_ref()
595+
.clone()
596+
.with_name(field.name().to_ascii_uppercase()),
597+
)
598+
})
599+
.collect::<Vec<_>>();
600+
values.schema = Arc::new(DFSchema::from_unqualified_fields(
601+
fields.into(),
602+
values.schema.metadata().clone(),
603+
)?);
567604
}
605+
606+
Ok(plan)
568607
}
569608
}

‎datafusion/sql/tests/sql_integration.rs‎

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3696,6 +3696,36 @@ fn uppercase_unquoted_identifiers_apply_to_schema_and_table_ddl() {
36963696
);
36973697
}
36983698

3699+
#[test]
3700+
fn uppercase_unquoted_identifiers_apply_to_values_columns() {
3701+
let default = logical_plan("VALUES (1, 'x')").unwrap();
3702+
assert_eq!(default.schema().field(0).name(), "column1");
3703+
assert_eq!(default.schema().field(1).name(), "column2");
3704+
3705+
let uppercase =
3706+
logical_plan_with_uppercase_unquoted_identifiers("VALUES (1, 'x')").unwrap();
3707+
assert_eq!(uppercase.schema().field(0).name(), "COLUMN1");
3708+
assert_eq!(uppercase.schema().field(1).name(), "COLUMN2");
3709+
logical_plan_with_uppercase_unquoted_identifiers("SELECT column1 FROM (VALUES (1))")
3710+
.unwrap();
3711+
assert!(
3712+
logical_plan_with_uppercase_unquoted_identifiers(
3713+
"SELECT \"column1\" FROM (VALUES (1))",
3714+
)
3715+
.is_err()
3716+
);
3717+
3718+
let mut config = datafusion_common::config::ConfigOptions::default();
3719+
config.sql_parser.uppercase_unquoted_identifiers = true;
3720+
let unnormalized = logical_plan_with_config_and_options(
3721+
"VALUES (1)",
3722+
config,
3723+
ParserOptions::default().with_enable_ident_normalization(false),
3724+
)
3725+
.unwrap();
3726+
assert_eq!(unnormalized.schema().field(0).name(), "column1");
3727+
}
3728+
36993729
#[test]
37003730
fn uppercase_unquoted_prepared_statement_names() {
37013731
use datafusion_expr::logical_plan::Statement as PlanStatement;

0 commit comments

Comments
 (0)