Skip to content

Commit

Permalink
fix: SQL 2016
Browse files Browse the repository at this point in the history
- Column defaults to nullable
- Fix the problem that Column is not lowercase when creating Table
- Added support for `TypedString`
- Support `START TRANSACTION & COMMIT WORK` on Server
- Fixed floating point number display problem and prioritized converting floating point numbers to double for calculation.
  • Loading branch information
KKould committed Feb 6, 2024
1 parent ab37a5b commit 44d8035
Show file tree
Hide file tree
Showing 102 changed files with 1,826 additions and 1,034 deletions.
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,9 @@ implement_from_tuple!(
- Date
- DateTime

## Roadmap
- SQL 2016

## License

FnckSQL uses the [Apache 2.0 license][1] to strike a balance between
Expand Down
4 changes: 2 additions & 2 deletions src/bin/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ impl SimpleQueryHandler for SessionBackend {
C: ClientInfo + Unpin + Send + Sync,
{
match query.to_uppercase().as_str() {
"BEGIN;" | "BEGIN" => {
"BEGIN;" | "BEGIN" | "START TRANSACTION;" | "START TRANSACTION" => {
let mut guard = self.tx.lock().await;

if guard.is_some() {
Expand All @@ -115,7 +115,7 @@ impl SimpleQueryHandler for SessionBackend {

Ok(vec![Response::Execution(Tag::new("OK").into())])
}
"COMMIT;" | "COMMIT" => {
"COMMIT;" | "COMMIT" | "COMMIT WORK;" | "COMMIT WORK" => {
let mut guard = self.tx.lock().await;

if let Some(transaction) = guard.take() {
Expand Down
6 changes: 3 additions & 3 deletions src/binder/create_table.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ impl<'a, T: Transaction> Binder<'a, T> {
is_primary,
..
} => {
for column_name in column_names {
for column_name in column_names.iter().map(|ident| ident.value.to_lowercase()) {
if let Some(column) = columns
.iter_mut()
.find(|column| column.name() == column_name.to_string())
Expand Down Expand Up @@ -102,13 +102,13 @@ impl<'a, T: Transaction> Binder<'a, T> {
false,
None,
);
let mut nullable = false;
let mut nullable = true;

// TODO: 这里可以对更多字段可设置内容进行补充
for option_def in &column_def.options {
match &option_def.option {
ColumnOption::Null => nullable = true,
ColumnOption::NotNull => (),
ColumnOption::NotNull => nullable = false,
ColumnOption::Unique { is_primary } => {
if *is_primary {
column_desc.is_primary = true;
Expand Down
67 changes: 44 additions & 23 deletions src/binder/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ impl<'a, T: Transaction> Binder<'a, T> {
Expr::CompoundIdentifier(idents) => self.bind_column_ref_from_identifiers(idents, None),
Expr::BinaryOp { left, right, op } => self.bind_binary_op_internal(left, right, op),
Expr::Value(v) => Ok(ScalarExpression::Constant(Arc::new(v.into()))),
Expr::Function(func) => self.bind_agg_call(func),
Expr::Function(func) => self.bind_function(func),
Expr::Nested(expr) => self.bind_expr(expr),
Expr::UnaryOp { expr, op } => self.bind_unary_op_internal(expr, op),
Expr::Like {
Expand All @@ -40,6 +40,12 @@ impl<'a, T: Transaction> Binder<'a, T> {
negated,
} => self.bind_is_in(expr, list, *negated),
Expr::Cast { expr, data_type } => self.bind_cast(expr, data_type),
Expr::TypedString { data_type, value } => {
let logical_type = LogicalType::try_from(data_type.clone())?;
let value = DataValue::Utf8(Some(value.to_string())).cast(&logical_type)?;

Ok(ScalarExpression::Constant(Arc::new(value)))
},
_ => {
todo!()
}
Expand Down Expand Up @@ -183,7 +189,7 @@ impl<'a, T: Transaction> Binder<'a, T> {
})
}

fn bind_agg_call(&mut self, func: &Function) -> Result<ScalarExpression, DatabaseError> {
fn bind_function(&mut self, func: &Function) -> Result<ScalarExpression, DatabaseError> {
let mut args = Vec::with_capacity(func.args.len());

for arg in func.args.iter() {
Expand All @@ -197,7 +203,6 @@ impl<'a, T: Transaction> Binder<'a, T> {
_ => todo!(),
}
}
let ty = args[0].return_type();

Ok(match func.name.to_string().to_lowercase().as_str() {
"count" => ScalarExpression::AggCall {
Expand All @@ -206,29 +211,45 @@ impl<'a, T: Transaction> Binder<'a, T> {
args,
ty: LogicalType::Integer,
},
"sum" => ScalarExpression::AggCall {
distinct: func.distinct,
kind: AggKind::Sum,
args,
ty,
"sum" => {
let ty = args[0].return_type();

ScalarExpression::AggCall {
distinct: func.distinct,
kind: AggKind::Sum,
args,
ty,
}
},
"min" => ScalarExpression::AggCall {
distinct: func.distinct,
kind: AggKind::Min,
args,
ty,
"min" => {
let ty = args[0].return_type();

ScalarExpression::AggCall {
distinct: func.distinct,
kind: AggKind::Min,
args,
ty,
}
},
"max" => ScalarExpression::AggCall {
distinct: func.distinct,
kind: AggKind::Max,
args,
ty,
"max" => {
let ty = args[0].return_type();

ScalarExpression::AggCall {
distinct: func.distinct,
kind: AggKind::Max,
args,
ty,
}
},
"avg" => ScalarExpression::AggCall {
distinct: func.distinct,
kind: AggKind::Avg,
args,
ty,
"avg" => {
let ty = args[0].return_type();

ScalarExpression::AggCall {
distinct: func.distinct,
kind: AggKind::Avg,
args,
ty,
}
},
_ => todo!(),
})
Expand Down
2 changes: 1 addition & 1 deletion src/catalog/column.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ impl ColumnCatalog {
name: column_name,
table_name: None,
},
nullable: false,
nullable: true,
desc: ColumnDesc::new(LogicalType::Varchar(None), false, false, None),
ref_expr: None,
}
Expand Down
1 change: 1 addition & 0 deletions src/types/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -316,6 +316,7 @@ impl TryFrom<sqlparser::ast::DataType> for LogicalType {
sqlparser::ast::DataType::BigInt(_) => Ok(LogicalType::Bigint),
sqlparser::ast::DataType::UnsignedBigInt(_) => Ok(LogicalType::UBigint),
sqlparser::ast::DataType::Boolean => Ok(LogicalType::Boolean),
sqlparser::ast::DataType::Date => Ok(LogicalType::Date),
sqlparser::ast::DataType::Datetime(_) => Ok(LogicalType::DateTime),
sqlparser::ast::DataType::Decimal(info) | sqlparser::ast::DataType::Dec(info) => match info {
ExactNumberInfo::None => Ok(Self::Decimal(None, None)),
Expand Down
29 changes: 23 additions & 6 deletions src/types/value.rs
Original file line number Diff line number Diff line change
Expand Up @@ -997,10 +997,10 @@ impl From<&sqlparser::ast::Value> for DataValue {
v.into()
} else if let Ok(v) = n.parse::<i64>() {
v.into()
} else if let Ok(v) = n.parse::<f32>() {
v.into()
} else if let Ok(v) = n.parse::<f64>() {
v.into()
} else if let Ok(v) = n.parse::<f32>() {
v.into()
} else {
panic!("unsupported number {:?}", n)
}
Expand All @@ -1015,20 +1015,37 @@ impl From<&sqlparser::ast::Value> for DataValue {
}

macro_rules! format_option {
($F:expr, $EXPR:expr) => {{
($F:expr, $EXPR:expr) => {
match $EXPR {
Some(e) => write!($F, "{}", e),
None => write!($F, "null"),
}
}};
};
}
macro_rules! format_float_option {
($F:expr, $EXPR:expr) => {
match $EXPR {
Some(e) => {
let formatted_string = format!("{:?}", e);
let formatted_result = if let Some(i) = formatted_string.find('.') {
format!("{:.1$}", e, formatted_string.len() - i - 1)
} else {
format!("{:.1}", e)
};

write!($F, "{}", formatted_result)
}
None => write!($F, "null"),
}
};
}

impl fmt::Display for DataValue {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
match self {
DataValue::Boolean(e) => format_option!(f, e)?,
DataValue::Float32(e) => format_option!(f, e)?,
DataValue::Float64(e) => format_option!(f, e)?,
DataValue::Float32(e) => format_float_option!(f, e)?,
DataValue::Float64(e) => format_float_option!(f, e)?,
DataValue::Int8(e) => format_option!(f, e)?,
DataValue::Int16(e) => format_option!(f, e)?,
DataValue::Int32(e) => format_option!(f, e)?,
Expand Down
2 changes: 1 addition & 1 deletion tests/slt/aggregation.slt
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ select sum(v1) as a from t
query IR
select sum(v1), sum(v3) from t
----
10 15.499999761581421
10 15.5

# query IR
# select sum(v1+v2),sum(v1+v3) from t
Expand Down
2 changes: 1 addition & 1 deletion tests/slt/alter_table.slt
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ statement ok
alter table t1 add column if not exists v3 int default 0

statement error
alter table t1 add column v4 int
alter table t1 add column v4 int not null

query IIII rowsort
select * from t1
Expand Down
4 changes: 2 additions & 2 deletions tests/slt/describe.slt
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ query TTTTI
describe t9;
----
c1 INTEGER false PRIMARY null
c2 INTEGER false EMPTY 0
c3 VARCHAR false UNIQUE null
c2 INTEGER true EMPTY 0
c3 VARCHAR true UNIQUE null

statement ok
drop table t9;
4 changes: 2 additions & 2 deletions tests/slt/sql_2016/E011_05.slt
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ false
query B
SELECT 3.7 < 5.2
----
false
true

query B
SELECT 3.7 <= 5.2
Expand All @@ -43,7 +43,7 @@ true
query B
SELECT 3.7 <> 5.2
----
false
true

query B
SELECT 3.7 = 5.2
Expand Down
2 changes: 0 additions & 2 deletions tests/slt/sql_2016/E021_02.slt
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,10 @@

# statement ok
# CREATE TABLE TABLE_E021_02_01_02 ( A CHAR VARING ( 8 CHARACTERS ) )
#


# statement ok
# CREATE TABLE TABLE_E021_02_01_03 ( A CHAR VARING ( 8 OCTETS ) )
#


# statement ok
Expand Down
9 changes: 2 additions & 7 deletions tests/slt/sql_2016/E021_03.slt
Original file line number Diff line number Diff line change
@@ -1,16 +1,11 @@
# E021-03: Character literals

query T
SELECT ''
----
''

query T
SELECT 'a'
----
'a'
a

query T
SELECT 'abc'
----
'abc'
abc
2 changes: 1 addition & 1 deletion tests/slt/sql_2016/E021_07.slt
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@
query T
SELECT 'foo' || 'bar'
----
'foobar'
foobar
4 changes: 4 additions & 0 deletions tests/slt/sql_2016/E021_10.slt
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,9 @@

# statement ok
# CREATE TABLE TABLE_E021_10_01_01 ( A CHARACTER ( 10 ) , B CHARACTER VARYING ( 15 ) );

# statement ok
# INSERT INTO TABLE_E021_10_01_01 ( A, B ) VALUES ( 'foo' , 'bar' );

# query B
# SELECT A = B FROM TABLE_E021_10_01_01
2 changes: 2 additions & 0 deletions tests/slt/sql_2016/E031_01.slt
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,6 @@

statement ok
CREATE TABLE TABLE_E031_01_01_01 ( ID INT PRIMARY KEY, "A" INT );

query T
SELECT "A" FROM TABLE_E031_01_01_01
6 changes: 4 additions & 2 deletions tests/slt/sql_2016/E031_02.slt
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# E031-02: Lower case identifiers

statement ok
CREATE TABLE TABLE_E031_02_01_01 ( ID INT PRIMARY KEY, A INT );
SELECT A FROM TABLE_E031_02_01_01
CREATE TABLE TABLE_E031_02_01_01 ( ID INT PRIMARY KEY, a INT );

query I
SELECT a FROM TABLE_E031_02_01_01
2 changes: 2 additions & 0 deletions tests/slt/sql_2016/E031_03.slt
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,6 @@

statement ok
CREATE TABLE TABLE_E031_03_01_01 ( ID INT PRIMARY KEY, A_ INT );

query I
SELECT A_ FROM TABLE_E031_03_01_01
8 changes: 8 additions & 0 deletions tests/slt/sql_2016/E051.slt
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,24 @@

statement ok
CREATE TABLE TABLE_E051_01_01 ( ID INT PRIMARY KEY, A INT );

query I
SELECT A FROM TABLE_E051_01_01

statement ok
CREATE TABLE TABLE_E051_01_02 ( ID INT PRIMARY KEY, A INT );

query I
SELECT A FROM TABLE_E051_01_02 WHERE A = 1

statement ok
CREATE TABLE TABLE_E051_01_03 ( ID INT PRIMARY KEY, A INT );

query I
SELECT ALL A FROM TABLE_E051_01_03

statement ok
CREATE TABLE TABLE_E051_01_04 ( ID INT PRIMARY KEY, A INT );

query I
SELECT ALL A FROM TABLE_E051_01_04 WHERE A = 1
4 changes: 4 additions & 0 deletions tests/slt/sql_2016/E051_01.slt
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,12 @@

statement ok
CREATE TABLE TABLE_E051_01_01_01 ( ID INT PRIMARY KEY, A INT );

query I
SELECT DISTINCT A FROM TABLE_E051_01_01_01

statement ok
CREATE TABLE TABLE_E051_01_01_02 ( ID INT PRIMARY KEY, A INT );

query I
SELECT DISTINCT A FROM TABLE_E051_01_01_02 WHERE A = 1
Loading

0 comments on commit 44d8035

Please sign in to comment.