diff --git a/src/execution/volcano/dql/aggregate/sum.rs b/src/execution/volcano/dql/aggregate/sum.rs index d5d2ab53..938facb1 100644 --- a/src/execution/volcano/dql/aggregate/sum.rs +++ b/src/execution/volcano/dql/aggregate/sum.rs @@ -18,7 +18,7 @@ impl SumAccumulator { assert!(ty.is_numeric()); Ok(Self { - result: DataValue::init(ty), + result: DataValue::none(ty), evaluator: EvaluatorFactory::binary_create(*ty, BinaryOperator::Plus)?, }) } @@ -27,7 +27,11 @@ impl SumAccumulator { impl Accumulator for SumAccumulator { fn update_value(&mut self, value: &ValueRef) -> Result<(), DatabaseError> { if !value.is_null() { - self.result = self.evaluator.0.binary_eval(&self.result, value); + if self.result.is_null() { + self.result = DataValue::clone(value); + } else { + self.result = self.evaluator.0.binary_eval(&self.result, value); + } } Ok(()) diff --git a/src/storage/mod.rs b/src/storage/mod.rs index 4326c33a..4e942bde 100644 --- a/src/storage/mod.rs +++ b/src/storage/mod.rs @@ -276,6 +276,11 @@ pub trait Transaction: Sync + Send + 'static + Sized { columns: Vec, if_not_exists: bool, ) -> Result { + let mut table_catalog = TableCatalog::new(table_name.clone(), columns)?; + let (_, column) = table_catalog.primary_key()?; + + TableCodec::check_primary_key_type(column.datatype())?; + let (table_key, value) = TableCodec::encode_root_table(&TableMeta::empty(table_name.clone()))?; if self.get(&table_key)?.is_some() { @@ -284,11 +289,8 @@ pub trait Transaction: Sync + Send + 'static + Sized { } return Err(DatabaseError::TableExists); } - self.set(table_key, value)?; - - let mut table_catalog = TableCatalog::new(table_name.clone(), columns)?; - self.create_index_meta_for_table(&mut table_catalog)?; + self.set(table_key, value)?; for column in table_catalog.columns() { let (key, value) = TableCodec::encode_column(&table_name, column)?; diff --git a/src/storage/table_codec.rs b/src/storage/table_codec.rs index bbe954ff..3295e97b 100644 --- a/src/storage/table_codec.rs +++ b/src/storage/table_codec.rs @@ -30,6 +30,25 @@ enum CodecType { } impl TableCodec { + pub fn check_primary_key_type(ty: &LogicalType) -> Result<(), DatabaseError> { + if !matches!( + ty, + LogicalType::Tinyint + | LogicalType::Smallint + | LogicalType::Integer + | LogicalType::Bigint + | LogicalType::UTinyint + | LogicalType::USmallint + | LogicalType::UInteger + | LogicalType::UBigint + | LogicalType::Char(..) + | LogicalType::Varchar(..) + ) { + return Err(DatabaseError::InvalidType); + } + Ok(()) + } + /// TableName + Type /// /// Tips: Root full key = key_prefix @@ -159,23 +178,11 @@ impl TableCodec { table_name: &str, tuple_id: &TupleId, ) -> Result, DatabaseError> { + Self::check_primary_key_type(&tuple_id.logical_type())?; + let mut key_prefix = Self::key_prefix(CodecType::Tuple, table_name); key_prefix.push(BOUND_MIN_TAG); - if !matches!( - tuple_id.logical_type(), - LogicalType::Tinyint - | LogicalType::Smallint - | LogicalType::Integer - | LogicalType::Bigint - | LogicalType::UTinyint - | LogicalType::USmallint - | LogicalType::UInteger - | LogicalType::UBigint - | LogicalType::Varchar(..) - ) { - return Err(DatabaseError::InvalidType); - } tuple_id.memcomparable_encode(&mut key_prefix)?; Ok(key_prefix) diff --git a/tests/slt/crdb/overflow.slt b/tests/slt/crdb/overflow.slt new file mode 100644 index 00000000..70eed9dd --- /dev/null +++ b/tests/slt/crdb/overflow.slt @@ -0,0 +1,24 @@ +statement ok +drop table if exists large_numbers + +statement ok +CREATE TABLE large_numbers (a TINYINT PRIMARY KEY) + +statement error +INSERT INTO large_numbers VALUES (9223372036854775807),(1) + +query I +SELECT sum(a) FROM large_numbers +---- +null + +statement ok +DELETE FROM large_numbers + +statement error +INSERT INTO large_numbers VALUES (-9223372036854775808),(-1) + +query I +SELECT sum(a) FROM large_numbers +---- +null \ No newline at end of file diff --git a/tests/slt/crdb/select.slt b/tests/slt/crdb/select.slt new file mode 100644 index 00000000..35528a60 --- /dev/null +++ b/tests/slt/crdb/select.slt @@ -0,0 +1,533 @@ + +query II +SELECT 1+1 AS two, 2+2 AS four +---- +2 4 + +statement ok +drop table if exists abc + +statement ok +CREATE TABLE abc (a INT PRIMARY KEY, b INT NULL, c INT NULL) + +query III +SELECT * FROM abc WHERE 'hello' +--- + +statement ok +INSERT INTO abc VALUES (1, 2, 3) + +query III +SELECT * FROM abc +---- +1 2 3 + +query TIII +SELECT NULL AS z, * FROM abc +---- +null 1 2 3 + +statement ok +SELECT * FROM abc WHERE NULL + +statement ok +SELECT * FROM abc WHERE a = NULL + +query IIIIII +SELECT *,* FROM abc +---- +1 2 3 1 2 3 + +query IIII +SELECT a,a,a,a FROM abc +---- +1 1 1 1 + +query II +SELECT a,c FROM abc +---- +1 3 + +query I +SELECT a+b+c AS foo FROM abc +---- +6 + +statement ok +SELECT * FROM abc WHERE a > 5 AND a < 5 + +statement ok +SELECT * FROM abc WHERE a > 5 AND a < 5 AND b>=100 + +statement ok +INSERT INTO abc VALUES (0, 1, 2) + +query II +SELECT a,b FROM abc WHERE CASE WHEN a != 0 THEN b/a > 1.5 ELSE false END +---- +1 2 + +statement ok +drop table if exists kv + +statement ok +CREATE TABLE kv (k CHAR PRIMARY KEY, v CHAR NULL) + +statement ok +INSERT INTO kv (k, v) VALUES ('a', null) + +query TT +SELECT * FROM kv +---- +a null + +query TT +SELECT k,v FROM kv +---- +a null + +query T +SELECT v||'foo' FROM kv +---- +null + +# TODO: lower +# query T +# SELECT lower(v) FROM kv +# ---- +# NULL + +query T +SELECT k FROM kv +---- +a + +query TT +SELECT kv.K,KV.v FROM kv +---- +a null + +query TT +SELECT kv.* FROM kv +---- +a null + +query T +SELECT FOO.k FROM kv AS foo WHERE foo.k = 'a' +---- +a + +query T +SELECT foo.v FROM kv AS foo WHERE foo.k = 'a' +---- +null + +onlyif mysql +statement ok +drop table if exists kw + +onlyif mysql +statement ok +CREATE TABLE kw ("from" INT) + +onlyif mysql +statement ok +INSERT INTO kw VALUES (1) + +onlyif mysql +query III +SELECT *, "from", kw."from" FROM kw +---- +1 1 1 + +statement ok +drop table if exists xyzw + +statement ok +CREATE TABLE xyzw ( x INT PRIMARY KEY, y INT, z INT, w INT) + +statement ok +INSERT INTO xyzw VALUES (4, 5, 6, 7), (1, 2, 3, 4) + +statement error +SELECT * FROM xyzw LIMIT x + +statement error +SELECT * FROM xyzw OFFSET 1 + y + +statement error +SELECT * FROM xyzw LIMIT 3.3 + +statement error +SELECT * FROM xyzw ORDER BY 1 LIMIT '1' + +statement error +SELECT * FROM xyzw OFFSET 1.5 + +statement error +SELECT * FROM xyzw LIMIT -100 + +statement error +SELECT * FROM xyzw OFFSET -100 + +# query IIII +# SELECT * FROM xyzw LIMIT 9223372036854775808 +# ---- +# 4 5 6 7 +# 1 2 3 4 + +# statement ok +# SELECT * FROM xyzw OFFSET 9223372036854775808 + +statement error +SELECT * FROM xyzw ORDER BY x OFFSET 1 + 0.0 + +query T +SELECT (x,y) FROM xyzw +---- +(1, 2) +(4, 5) + +statement ok +SELECT * FROM xyzw LIMIT 0 + +query IIII +SELECT * FROM xyzw ORDER BY x LIMIT 1 +---- +1 2 3 4 + +query IIII +SELECT * FROM xyzw ORDER BY x LIMIT 1 OFFSET 1 +---- +4 5 6 7 + +query IIII +SELECT * FROM xyzw ORDER BY y OFFSET 1 +---- +4 5 6 7 + +# SELECT * FROM xyzw ORDER BY y OFFSET 1 LIMIT 1 +# SELECT * FROM xyzw LIMIT (random() * 0.0)::int OFFSET (random() * 0.0)::int +# ((SELECT a FROM t LIMIT 1)) LIMIT 1 + +statement ok +SELECT * FROM (SELECT * FROM xyzw LIMIT 5) OFFSET 5 + +# TODO: @ +# query II +# SELECT z, y FROM xyzw@foo +# ---- +# 6 5 +# 3 2 + +statement ok +drop table if exists boolean_table + +statement ok +CREATE TABLE boolean_table ( id INTEGER PRIMARY KEY, value BOOLEAN NULL) + +statement ok +INSERT INTO boolean_table (id, value) VALUES (1, NULL) + +query T +SELECT value FROM boolean_table +---- +null + +query I +SELECT CASE WHEN NULL THEN 1 ELSE 2 END +---- +2 + +statement ok +INSERT INTO abc VALUES (42, NULL, NULL) + +statement ok +SELECT 0 * b, b % 1, 0 % b from abc + +statement ok +drop table if exists maxinttest + +statement ok +CREATE TABLE MaxIntTest (a BIGINT PRIMARY KEY) + +statement ok +INSERT INTO MaxIntTest VALUES (9223372036854775807) + +query I +SELECT a FROM MaxIntTest WHERE a = 9223372036854775807 +---- +9223372036854775807 + +query I +SELECT 1 IN (1, 2) +---- +true + +query T +SELECT NULL IN (1, 2) +---- +null + +query I +SELECT 1 IN (1, NULL) +---- +true + +query I +SELECT 1 IN (NULL, 2) +---- +null + +# statement error 1105 +# SELECT NULL IN ((1, 1)) + +# statement error 1105 +# SELECT (1, NULL) IN ((1, 1)) + +# statement error 1105 +# SELECT (2, NULL) IN ((1, 1)) + +# statement error 1105 +# SELECT () IN (1,2) + +# statement error 1105 +# SELECT () IN ((1,2)) + +# statement error 1105 +# SELECT () IN (()) + +# statement error 1105 +# SELECT ('string', NULL) IN ((1, 1)) + +# statement error 1105 +# SELECT (2, 'string', NULL) IN ((1, 1)) + +# statement error 1105 +# SELECT (1, 1) IN ((1, NULL)) + +# statement error 1105 +# SELECT (1, 1) IN ((2, NULL)) + +# statement error 1105 +# SELECT NULL IN (SELECT * FROM (VALUES (1)) AS t(a)) + +# statement error 1105 +# SELECT (1, NULL) IN (SELECT * FROM (VALUES (1, 1)) AS t(a, b)) + +# statement error 1105 +# SELECT NULL IN (SELECT * FROM (VALUES (1, 1)) AS t(a, b)) + +# statement error 1105 +# SELECT () IN (SELECT * FROM (VALUES (1)) AS t(a)) + +# statement error 1105 +# SELECT () IN (SELECT * FROM (VALUES (1, 1)) AS t(a, b)) + +# statement error 1105 +# SELECT ('string', NULL) IN (SELECT * FROM (VALUES (1, 1)) AS t(a, b)) + +# statement error 1105 +# SELECT (2, 'string', NULL) IN (SELECT * FROM (VALUES (1, 1)) AS t(a, b)) + +# statement error 1105 +# SELECT (2, NULL) IN (SELECT * FROM (VALUES (1, 1)) AS t(a, b)) + +# statement error 1105 +# SELECT (NULL, 1) IN (SELECT * FROM (VALUES (1, 1)) AS t(a, b)) + +# statement error 1105 +# SELECT (NULL, 2) IN (SELECT * FROM (VALUES (1, 1)) AS t(a, b)) + +# statement error 1105 +# SELECT (NULL, NULL) IN (SELECT * FROM (VALUES (1, 1)) AS t(a, b)) + +# statement error 1105 +# SELECT NULL NOT IN (SELECT * FROM (VALUES (1)) AS t(a)) + +# statement error 1105 +# SELECT NULL NOT IN (SELECT * FROM (VALUES (1, 1)) AS t(a, b)) + +# statement error 1105 +# SELECT () NOT IN (SELECT * FROM (VALUES (1)) AS t(a)) + +# statement error 1105 +# SELECT () NOT IN (SELECT * FROM (VALUES (1, 1)) AS t(a, b)) + +# statement error 1105 +# SELECT ('string', NULL) NOT IN (SELECT * FROM (VALUES (1, 1)) AS t(a, b)) + +# statement error 1105 +# SELECT (2, 'string', NULL) NOT IN (SELECT * FROM (VALUES (1, 1)) AS t(a, b)) + +# statement error 1105 +# SELECT (1, NULL) NOT IN (SELECT * FROM (VALUES (1, 1)) AS t(a, b)) + +# statement error 1105 +# SELECT (2, NULL) NOT IN (SELECT * FROM (VALUES (1, 1)) AS t(a, b)) + +# statement error 1105 +# SELECT (NULL, 1) NOT IN (SELECT * FROM (VALUES (1, 1)) AS t(a, b)) + +# statement error 1105 +# SELECT (NULL, 2) NOT IN (SELECT * FROM (VALUES (1, 1)) AS t(a, b)) + +# statement error 1105 +# SELECT (NULL, NULL) NOT IN (SELECT * FROM (VALUES (1, 1)) AS t(a, b)) + +# statement error 1105 +# SELECT NULL IN (SELECT * FROM (VALUES (1)) AS t(a) WHERE a > 1) + +# statement error 1105 +# SELECT (1, NULL) IN (SELECT * FROM (VALUES (1, 1)) AS t(a, b) WHERE a > 1) + +# statement error 1105 +# SELECT (NULL, 1) IN (SELECT * FROM (VALUES (1, 1)) AS t(a, b) WHERE a > 1) + +# statement error 1105 +# SELECT (NULL, NULL) IN (SELECT * FROM (VALUES (1, 1)) AS t(a, b) WHERE a > 1) + +# statement error 1105 +# SELECT NULL NOT IN (SELECT * FROM (VALUES (1)) AS t(a) WHERE a > 1) + +# statement error 1105 +# SELECT (1, NULL) NOT IN (SELECT * FROM (VALUES (1, 1)) AS t(a, b) WHERE a > 1) + +# statement error 1105 +# SELECT (NULL, 1) NOT IN (SELECT * FROM (VALUES (1, 1)) AS t(a, b) WHERE a > 1) + +# statement error 1105 +# SELECT (NULL, NULL) NOT IN (SELECT * FROM (VALUES (1, 1)) AS t(a, b) WHERE a > 1) + +statement ok +drop table if exists a + +statement ok +CREATE TABLE a (x INT PRIMARY KEY, y INT) + +statement ok +INSERT INTO a VALUES (1, 10), (2, 20), (3, 30) + +query II +SELECT * FROM a WHERE x > 1 +---- +2 20 +3 30 + +query II +SELECT * FROM a WHERE y > 1 +---- +1 10 +2 20 +3 30 + +query II +SELECT * FROM a WHERE x > 1 AND x < 3 +---- +2 20 + +query II +SELECT * FROM a WHERE x > 1 AND y < 30 +---- +2 20 + +query I +SELECT x + 1 FROM a +---- +2 +3 +4 + +query IIIII +SELECT x, x + 1, y, y + 1, x + y FROM a +---- +1 2 10 11 11 +2 3 20 21 22 +3 4 30 31 33 + +# TODO +# query I +# SELECT u + v FROM (SELECT x + 3, y + 10 FROM a) AS foo(u, v) +# ---- +# 24 +# 35 +# 46 + +query IIII +SELECT x, x, y, x FROM a +---- +1 1 10 1 +2 2 20 2 +3 3 30 3 + +query II +SELECT x + 1, x + y FROM a WHERE x + y > 20 +---- +3 22 +4 33 + +statement ok +drop table if exists b + +statement ok +CREATE TABLE b (x INT PRIMARY KEY, y INT) + +statement ok +INSERT INTO b VALUES (1, 10), (2, 20), (3, 30) + +query II +SELECT * FROM b +---- +1 10 +2 20 +3 30 + +# query I +# SELECT x FROM b WHERE rowid > 0 + +# ---- +# 1 +# 2 +# 3 + +# query I +# SELECT x FROM b WHERE b.rowid > 0 + +# ---- +# 1 +# 2 +# 3 + +statement ok +drop table if exists c + +statement ok +CREATE TABLE c (n INT PRIMARY KEY, str STRING) + +statement ok +INSERT INTO c values (1, 'one'),(2, 'two'),(3, 'three'),(4, 'four'),(5, 'five'),(6, 'six'),(7, 'seven'),(8, 'eight'),(9, 'nine'),(10, 'ten') + +query IT +SELECT * FROM c WHERE str >= 'moo' +---- +1 one +2 two +3 three +6 six +7 seven +9 nine +10 ten + +statement ok +drop table if exists wide + +statement ok +CREATE TABLE wide (id TINYINT PRIMARY KEY, a TINYINT NOT NULL, b STRING NOT NULL, c TINYINT NOT NULL, d STRING NOT NULL, e STRING NOT NULL, f TINYINT NOT NULL, g STRING NOT NULL, h STRING NOT NULL, i STRING NOT NULL, j STRING NOT NULL, k TINYINT NOT NULL, l FLOAT NOT NULL, m FLOAT NOT NULL, n TINYINT NOT NULL) + +statement error +INSERT INTO wide(id, n) VALUES(0, 10) + +query T +SELECT count(*) FROM wide +---- +0 \ No newline at end of file diff --git a/tests/slt/sql_2016/E091_05.slt b/tests/slt/sql_2016/E091_05.slt index 03d3ba99..046380a7 100644 --- a/tests/slt/sql_2016/E091_05.slt +++ b/tests/slt/sql_2016/E091_05.slt @@ -6,4 +6,4 @@ CREATE TABLE TABLE_E091_05_01_01 ( ID INT PRIMARY KEY, A FLOAT ); query F SELECT SUM ( A ) FROM TABLE_E091_05_01_01 ---- -0.0 \ No newline at end of file +null \ No newline at end of file diff --git a/tests/slt/sql_2016/E091_06.slt b/tests/slt/sql_2016/E091_06.slt index a223d091..cbc91b63 100644 --- a/tests/slt/sql_2016/E091_06.slt +++ b/tests/slt/sql_2016/E091_06.slt @@ -38,4 +38,4 @@ CREATE TABLE TABLE_E091_06_05_01 ( ID INT PRIMARY KEY, A FLOAT ); query F SELECT SUM ( ALL A ) FROM TABLE_E091_06_05_01 ---- -0.0 +null diff --git a/tests/slt/sql_2016/E091_07.slt b/tests/slt/sql_2016/E091_07.slt index 3def4e2a..278cd385 100644 --- a/tests/slt/sql_2016/E091_07.slt +++ b/tests/slt/sql_2016/E091_07.slt @@ -38,4 +38,4 @@ CREATE TABLE TABLE_E091_07_01_05 ( ID INT PRIMARY KEY, A FLOAT ); query F SELECT SUM ( DISTINCT A ) FROM TABLE_E091_07_01_05 ---- -0.0 +null