Skip to content

Commit a84d8ba

Browse files
committed
feat: Update supports Set using expressions
fix: - primary key value position when declaring multiple primary keys(update & insert & delete) - decimal type conversion - the `Eq` expression of `PushPredicateIntoScan` must satisfy all index columns before it can be used - `PrimaryKey` index supplementary composite index type - `Tuple` deserialize may fail due to a large difference in the number of projection columns and table schema
1 parent 36aa42f commit a84d8ba

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

45 files changed

+486
-319
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,5 +26,6 @@ Cargo.lock
2626
fncksql_data
2727
fncksql_bench
2828
sqlite_bench
29+
fnck_sql_tpcc
2930

3031
tests/data/row_20000.csv

src/binder/alter_table.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ impl<T: Transaction> Binder<'_, '_, T> {
3030
column_def,
3131
} => {
3232
let plan = TableScanOperator::build(table_name.clone(), table);
33-
let column = self.bind_column(column_def)?;
33+
let column = self.bind_column(column_def, None)?;
3434

3535
if !is_valid_identifier(column.name()) {
3636
return Err(DatabaseError::InvalidColumn(

src/binder/create_table.rs

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,8 @@ impl<T: Transaction> Binder<'_, '_, T> {
4747
}
4848
let mut columns: Vec<ColumnCatalog> = columns
4949
.iter()
50-
.map(|col| self.bind_column(col))
50+
.enumerate()
51+
.map(|(i, col)| self.bind_column(col, Some(i)))
5152
.try_collect()?;
5253
for constraint in constraints {
5354
match constraint {
@@ -56,13 +57,17 @@ impl<T: Transaction> Binder<'_, '_, T> {
5657
is_primary,
5758
..
5859
} => {
59-
for column_name in column_names.iter().map(|ident| ident.value.to_lowercase()) {
60+
for (i, column_name) in column_names
61+
.iter()
62+
.map(|ident| ident.value.to_lowercase())
63+
.enumerate()
64+
{
6065
if let Some(column) = columns
6166
.iter_mut()
6267
.find(|column| column.name() == column_name)
6368
{
6469
if *is_primary {
65-
column.desc_mut().set_primary(true);
70+
column.desc_mut().set_primary(Some(i));
6671
} else {
6772
column.desc_mut().set_unique(true);
6873
}
@@ -89,11 +94,15 @@ impl<T: Transaction> Binder<'_, '_, T> {
8994
))
9095
}
9196

92-
pub fn bind_column(&mut self, column_def: &ColumnDef) -> Result<ColumnCatalog, DatabaseError> {
97+
pub fn bind_column(
98+
&mut self,
99+
column_def: &ColumnDef,
100+
column_index: Option<usize>,
101+
) -> Result<ColumnCatalog, DatabaseError> {
93102
let column_name = column_def.name.value.to_lowercase();
94103
let mut column_desc = ColumnDesc::new(
95104
LogicalType::try_from(column_def.data_type.clone())?,
96-
false,
105+
None,
97106
false,
98107
None,
99108
)?;
@@ -106,7 +115,7 @@ impl<T: Transaction> Binder<'_, '_, T> {
106115
ColumnOption::NotNull => nullable = false,
107116
ColumnOption::Unique { is_primary, .. } => {
108117
if *is_primary {
109-
column_desc.set_primary(true);
118+
column_desc.set_primary(column_index);
110119
nullable = false;
111120
// Skip other options when using primary key
112121
break;
@@ -184,15 +193,15 @@ mod tests {
184193
debug_assert_eq!(op.columns[0].nullable(), false);
185194
debug_assert_eq!(
186195
op.columns[0].desc(),
187-
&ColumnDesc::new(LogicalType::Integer, true, false, None)?
196+
&ColumnDesc::new(LogicalType::Integer, Some(0), false, None)?
188197
);
189198
debug_assert_eq!(op.columns[1].name(), "name");
190199
debug_assert_eq!(op.columns[1].nullable(), true);
191200
debug_assert_eq!(
192201
op.columns[1].desc(),
193202
&ColumnDesc::new(
194203
LogicalType::Varchar(Some(10), CharLengthUnits::Characters),
195-
false,
204+
None,
196205
false,
197206
None
198207
)?

src/binder/delete.rs

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use crate::planner::operator::table_scan::TableScanOperator;
55
use crate::planner::operator::Operator;
66
use crate::planner::LogicalPlan;
77
use crate::storage::Transaction;
8+
use itertools::Itertools;
89
use sqlparser::ast::{Expr, TableAlias, TableFactor, TableWithJoins};
910
use std::sync::Arc;
1011

@@ -23,20 +24,19 @@ impl<T: Transaction> Binder<'_, '_, T> {
2324
table_alias = Some(Arc::new(name.value.to_lowercase()));
2425
alias_idents = Some(columns);
2526
}
26-
let source = self
27+
let Source::Table(table) = self
2728
.context
28-
.source_and_bind(table_name.clone(), table_alias.as_ref(), None, false)?
29-
.ok_or(DatabaseError::SourceNotFound)?;
30-
let schema_buf = self.table_schema_buf.entry(table_name.clone()).or_default();
31-
let primary_key_column = source
32-
.columns(schema_buf)
33-
.find(|column| column.desc().is_primary())
34-
.cloned()
35-
.unwrap();
36-
let mut plan = match source {
37-
Source::Table(table) => TableScanOperator::build(table_name.clone(), table),
38-
Source::View(view) => LogicalPlan::clone(&view.plan),
29+
.source_and_bind(table_name.clone(), table_alias.as_ref(), None, true)?
30+
.ok_or(DatabaseError::TableNotFound)?
31+
else {
32+
unreachable!()
3933
};
34+
let primary_keys = table
35+
.primary_keys()
36+
.iter()
37+
.map(|(_, column)| column.clone())
38+
.collect_vec();
39+
let mut plan = TableScanOperator::build(table_name.clone(), table);
4040

4141
if let Some(alias_idents) = alias_idents {
4242
plan =
@@ -50,7 +50,7 @@ impl<T: Transaction> Binder<'_, '_, T> {
5050
Ok(LogicalPlan::new(
5151
Operator::Delete(DeleteOperator {
5252
table_name,
53-
primary_key_column,
53+
primary_keys,
5454
}),
5555
vec![plan],
5656
))

src/binder/expr.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -333,7 +333,7 @@ impl<'a, T: Transaction> Binder<'a, '_, T> {
333333
Ok(ScalarExpression::ColumnRef(
334334
source
335335
.column(&full_name.1, schema_buf)
336-
.ok_or_else(|| DatabaseError::NotFound("column", full_name.1.to_string()))?,
336+
.ok_or_else(|| DatabaseError::ColumnNotFound(full_name.1.to_string()))?,
337337
))
338338
} else {
339339
let op =
@@ -373,7 +373,7 @@ impl<'a, T: Transaction> Binder<'a, '_, T> {
373373
if let Some(parent) = self.parent {
374374
op(&mut got_column, &parent.context, &mut self.table_schema_buf);
375375
}
376-
Ok(got_column.ok_or(DatabaseError::NotFound("column", full_name.1))?)
376+
Ok(got_column.ok_or(DatabaseError::ColumnNotFound(full_name.1))?)
377377
}
378378
}
379379

@@ -621,7 +621,7 @@ impl<'a, T: Transaction> Binder<'a, '_, T> {
621621
}));
622622
}
623623

624-
Err(DatabaseError::NotFound("function", summary.name))
624+
Err(DatabaseError::FunctionNotFound(summary.name))
625625
}
626626

627627
fn return_type(

src/binder/mod.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -569,12 +569,12 @@ pub mod test {
569569
ColumnCatalog::new(
570570
"c1".to_string(),
571571
false,
572-
ColumnDesc::new(Integer, true, false, None)?,
572+
ColumnDesc::new(Integer, Some(0), false, None)?,
573573
),
574574
ColumnCatalog::new(
575575
"c2".to_string(),
576576
false,
577-
ColumnDesc::new(Integer, false, true, None)?,
577+
ColumnDesc::new(Integer, None, true, None)?,
578578
),
579579
],
580580
false,
@@ -587,12 +587,12 @@ pub mod test {
587587
ColumnCatalog::new(
588588
"c3".to_string(),
589589
false,
590-
ColumnDesc::new(Integer, true, false, None)?,
590+
ColumnDesc::new(Integer, Some(0), false, None)?,
591591
),
592592
ColumnCatalog::new(
593593
"c4".to_string(),
594594
false,
595-
ColumnDesc::new(Integer, false, false, None)?,
595+
ColumnDesc::new(Integer, None, false, None)?,
596596
),
597597
],
598598
false,

src/binder/update.rs

Lines changed: 19 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -26,52 +26,41 @@ impl<T: Transaction> Binder<'_, '_, T> {
2626
if let Some(predicate) = selection {
2727
plan = self.bind_where(plan, predicate)?;
2828
}
29+
let mut value_exprs = Vec::with_capacity(assignments.len());
2930

30-
let mut schema = Vec::with_capacity(assignments.len());
31-
let mut row = Vec::with_capacity(assignments.len());
32-
31+
if assignments.is_empty() {
32+
return Err(DatabaseError::ColumnsEmpty);
33+
}
3334
for Assignment { id, value } in assignments {
34-
let mut expression = self.bind_expr(value)?;
35-
expression.constant_calculation()?;
35+
let expression = self.bind_expr(value)?;
3636

3737
for ident in id {
3838
match self.bind_column_ref_from_identifiers(
3939
slice::from_ref(ident),
4040
Some(table_name.to_string()),
4141
)? {
4242
ScalarExpression::ColumnRef(column) => {
43-
match &expression {
44-
ScalarExpression::Constant(value) => {
45-
let ty = column.datatype();
46-
// Check if the value length is too long
47-
value.check_len(ty)?;
48-
49-
let mut value = value.clone();
50-
if value.logical_type() != *ty {
51-
value = value.cast(ty)?;
52-
}
53-
row.push(value);
54-
}
55-
ScalarExpression::Empty => {
56-
let default_value = column
57-
.default_value()?
58-
.ok_or(DatabaseError::DefaultNotExist)?;
59-
row.push(default_value);
60-
}
61-
_ => return Err(DatabaseError::UnsupportedStmt(value.to_string())),
62-
}
63-
schema.push(column);
43+
let expr = if matches!(expression, ScalarExpression::Empty) {
44+
let default_value = column
45+
.default_value()?
46+
.ok_or(DatabaseError::DefaultNotExist)?;
47+
ScalarExpression::Constant(default_value)
48+
} else {
49+
expression.clone()
50+
};
51+
value_exprs.push((column, expr));
6452
}
6553
_ => return Err(DatabaseError::InvalidColumn(ident.to_string())),
6654
}
6755
}
6856
}
6957
self.context.allow_default = false;
70-
let values_plan = self.bind_values(vec![row], Arc::new(schema));
71-
7258
Ok(LogicalPlan::new(
73-
Operator::Update(UpdateOperator { table_name }),
74-
vec![plan, values_plan],
59+
Operator::Update(UpdateOperator {
60+
table_name,
61+
value_exprs,
62+
}),
63+
vec![plan],
7564
))
7665
} else {
7766
unreachable!("only table")

src/catalog/column.rs

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ impl ColumnCatalog {
100100
// SAFETY: default expr must not be [`ScalarExpression::ColumnRef`]
101101
desc: ColumnDesc::new(
102102
LogicalType::Varchar(None, CharLengthUnits::Characters),
103-
false,
103+
None,
104104
false,
105105
None,
106106
)
@@ -187,15 +187,15 @@ impl ColumnCatalog {
187187
#[derive(Debug, Clone, PartialEq, Eq, Hash, ReferenceSerialization)]
188188
pub struct ColumnDesc {
189189
pub(crate) column_datatype: LogicalType,
190-
is_primary: bool,
190+
primary: Option<usize>,
191191
is_unique: bool,
192192
pub(crate) default: Option<ScalarExpression>,
193193
}
194194

195195
impl ColumnDesc {
196196
pub fn new(
197197
column_datatype: LogicalType,
198-
is_primary: bool,
198+
primary: Option<usize>,
199199
is_unique: bool,
200200
default: Option<ScalarExpression>,
201201
) -> Result<ColumnDesc, DatabaseError> {
@@ -207,18 +207,22 @@ impl ColumnDesc {
207207

208208
Ok(ColumnDesc {
209209
column_datatype,
210-
is_primary,
210+
primary,
211211
is_unique,
212212
default,
213213
})
214214
}
215215

216+
pub(crate) fn primary(&self) -> Option<usize> {
217+
self.primary
218+
}
219+
216220
pub(crate) fn is_primary(&self) -> bool {
217-
self.is_primary
221+
self.primary.is_some()
218222
}
219223

220-
pub(crate) fn set_primary(&mut self, is_primary: bool) {
221-
self.is_primary = is_primary
224+
pub(crate) fn set_primary(&mut self, is_primary: Option<usize>) {
225+
self.primary = is_primary
222226
}
223227

224228
pub(crate) fn is_unique(&self) -> bool {

src/catalog/table.rs

Lines changed: 19 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -169,13 +169,7 @@ impl TableCatalog {
169169
.add_column(col_catalog, &mut generator)
170170
.unwrap();
171171
}
172-
table_catalog.primary_keys = table_catalog
173-
.schema_ref
174-
.iter()
175-
.enumerate()
176-
.filter(|&(_, column)| column.desc().is_primary())
177-
.map(|(i, column)| (i, column.clone()))
178-
.collect_vec();
172+
table_catalog.primary_keys = Self::build_primary_keys(&table_catalog.schema_ref);
179173

180174
Ok(table_catalog)
181175
}
@@ -197,12 +191,7 @@ impl TableCatalog {
197191
columns.insert(column_id, i);
198192
}
199193
let schema_ref = Arc::new(column_refs.clone());
200-
let primary_keys = schema_ref
201-
.iter()
202-
.enumerate()
203-
.filter(|&(_, column)| column.desc().is_primary())
204-
.map(|(i, column)| (i, column.clone()))
205-
.collect_vec();
194+
let primary_keys = Self::build_primary_keys(&schema_ref);
206195

207196
Ok(TableCatalog {
208197
name,
@@ -213,6 +202,21 @@ impl TableCatalog {
213202
primary_keys,
214203
})
215204
}
205+
206+
fn build_primary_keys(schema_ref: &Arc<Vec<ColumnRef>>) -> Vec<(usize, ColumnRef)> {
207+
schema_ref
208+
.iter()
209+
.enumerate()
210+
.filter_map(|(i, column)| {
211+
column
212+
.desc()
213+
.primary()
214+
.map(|p_i| (p_i, (i, column.clone())))
215+
})
216+
.sorted_by_key(|(p_i, _)| *p_i)
217+
.map(|(_, entry)| entry)
218+
.collect_vec()
219+
}
216220
}
217221

218222
impl TableMeta {
@@ -236,12 +240,12 @@ mod tests {
236240
let col0 = ColumnCatalog::new(
237241
"a".into(),
238242
false,
239-
ColumnDesc::new(LogicalType::Integer, false, false, None).unwrap(),
243+
ColumnDesc::new(LogicalType::Integer, None, false, None).unwrap(),
240244
);
241245
let col1 = ColumnCatalog::new(
242246
"b".into(),
243247
false,
244-
ColumnDesc::new(LogicalType::Boolean, false, false, None).unwrap(),
248+
ColumnDesc::new(LogicalType::Boolean, None, false, None).unwrap(),
245249
);
246250
let col_catalogs = vec![col0, col1];
247251
let table_catalog = TableCatalog::new(Arc::new("test".to_string()), col_catalogs).unwrap();

0 commit comments

Comments
 (0)