Skip to content

Commit b7f8498

Browse files
committed
missing field of tuple as null.
1 parent e0d1a77 commit b7f8498

File tree

3 files changed

+130
-16
lines changed

3 files changed

+130
-16
lines changed

Cargo.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/query/sql/src/planner/binder/copy_into_table.rs

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -182,15 +182,12 @@ impl Binder {
182182
files: stmt.files.clone(),
183183
pattern,
184184
};
185-
let required_values_schema: DataSchemaRef = Arc::new(
186-
match &stmt.dst_columns {
187-
Some(cols) => self.schema_project(&table.schema(), cols)?,
188-
None => self.schema_project(&table.schema(), &[])?,
189-
}
190-
.into(),
191-
);
185+
let stage_schema = match &stmt.dst_columns {
186+
Some(cols) => self.schema_project(&table.schema(), cols)?,
187+
None => self.schema_project(&table.schema(), &[])?,
188+
};
192189

193-
let stage_schema = infer_table_schema(&required_values_schema)?;
190+
let required_values_schema: DataSchemaRef = Arc::new(stage_schema.clone().into());
194191

195192
let default_values = if stage_info.file_format_params.need_field_default() {
196193
Some(

src/query/storages/common/stage/src/read/columnar/projection.rs

Lines changed: 124 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,13 @@
1414

1515
use databend_common_exception::ErrorCode;
1616
use databend_common_expression::type_check::check_cast;
17+
use databend_common_expression::type_check::check_function;
18+
use databend_common_expression::types::DataType;
19+
use databend_common_expression::types::NumberScalar;
1720
use databend_common_expression::Expr;
1821
use databend_common_expression::RemoteExpr;
1922
use databend_common_expression::Scalar;
23+
use databend_common_expression::TableDataType;
2024
use databend_common_expression::TableSchemaRef;
2125
use databend_common_functions::BUILTIN_FUNCTIONS;
2226
use databend_common_meta_app::principal::NullAs;
@@ -82,13 +86,126 @@ pub fn project_columnar(
8286
&BUILTIN_FUNCTIONS,
8387
)?
8488
} else {
85-
return Err(ErrorCode::BadDataValueType(format!(
86-
"fail to load file {}: Cannot cast column {} from {:?} to {:?}",
87-
location,
88-
field_name,
89-
from_field.data_type(),
90-
to_field.data_type()
91-
)));
89+
// special cast for tuple type, fill in default values for the missing fields.
90+
match (
91+
from_field.data_type.remove_nullable(),
92+
to_field.data_type.remove_nullable(),
93+
) {
94+
(
95+
TableDataType::Tuple {
96+
fields_name: from_fields_name,
97+
fields_type: from_fields_type,
98+
},
99+
TableDataType::Tuple {
100+
fields_name: to_fields_name,
101+
fields_type: to_fields_type,
102+
},
103+
) => {
104+
println!("tuple: {from_fields_name:?} {from_fields_type:?} to {to_fields_name:?} {to_fields_type:?}");
105+
let mut inner_columns = Vec::with_capacity(to_fields_name.len());
106+
107+
for (to_field_name, to_field_type) in
108+
to_fields_name.iter().zip(to_fields_type.iter())
109+
{
110+
let inner_column = match from_fields_name
111+
.iter()
112+
.position(|k| k == to_field_name)
113+
{
114+
Some(idx) => {
115+
let from_field_type =
116+
from_fields_type.get(idx).unwrap();
117+
let tuple_idx = Scalar::Number(NumberScalar::Int64(
118+
(idx + 1) as i64,
119+
));
120+
let inner_column = check_function(
121+
None,
122+
"get",
123+
&[tuple_idx],
124+
&[expr.clone()],
125+
&BUILTIN_FUNCTIONS,
126+
)?;
127+
if from_field_type != to_field_type {
128+
check_cast(
129+
None,
130+
false,
131+
inner_column,
132+
&to_field_type.into(),
133+
&BUILTIN_FUNCTIONS,
134+
)?
135+
} else {
136+
inner_column
137+
}
138+
}
139+
None => {
140+
// if inner field not exists, fill default value.
141+
let data_type: DataType = to_field_type.into();
142+
let scalar = Scalar::default_value(&data_type);
143+
Expr::Constant {
144+
span: None,
145+
scalar,
146+
data_type,
147+
}
148+
}
149+
};
150+
inner_columns.push(inner_column);
151+
}
152+
let tuple_column = check_function(
153+
None,
154+
"tuple",
155+
&[],
156+
&inner_columns,
157+
&BUILTIN_FUNCTIONS,
158+
)?;
159+
let tuple_column = if from_field.data_type != to_field.data_type {
160+
let dest_ty: DataType = (&to_field.data_type).into();
161+
check_cast(
162+
None,
163+
false,
164+
tuple_column,
165+
&dest_ty,
166+
&BUILTIN_FUNCTIONS,
167+
)?
168+
} else {
169+
tuple_column
170+
};
171+
172+
if from_field.data_type.is_nullable()
173+
&& to_field.data_type.is_nullable()
174+
{
175+
// add if function to cast null value
176+
let is_not_null = check_function(
177+
None,
178+
"is_not_null",
179+
&[],
180+
&[expr.clone()],
181+
&BUILTIN_FUNCTIONS,
182+
)?;
183+
let null_scalar = Expr::Constant {
184+
span: None,
185+
scalar: Scalar::Null,
186+
data_type: DataType::Null,
187+
};
188+
check_function(
189+
None,
190+
"if",
191+
&[],
192+
&[is_not_null, tuple_column, null_scalar],
193+
&BUILTIN_FUNCTIONS,
194+
)?
195+
} else {
196+
tuple_column
197+
}
198+
}
199+
(_, _) => {
200+
return Err(ErrorCode::BadDataValueType(format!(
201+
"fail to load file {}: Cannot cast column {} from {:?} to {:?}",
202+
location,
203+
field_name,
204+
from_field.data_type(),
205+
to_field.data_type()
206+
)));
207+
}
208+
}
92209
}
93210
}
94211
}

0 commit comments

Comments
 (0)