From be10d88a7b63cf98f47bc8ab87c2ba2aa6958d93 Mon Sep 17 00:00:00 2001 From: WEI Xikai Date: Wed, 7 Dec 2022 15:47:54 +0800 Subject: [PATCH] fix: wrong primary key when define tsid and timestamp key as primary key (#453) * fix: wrong primary when define tsid and tiemstamp key as primary key * chore: add test for define primary with tsid * chore: fix harness test * refactor: add some comments * fix: wrong order of the primary key columns * chore: replace BTreeMap with HashMap for columns_by_names --- sql/src/planner.rs | 282 +++++++++++------- .../local/03_dml/case_insensitive.result | 24 +- tests/cases/local/03_dml/insert_mode.result | 62 ++-- tests/cases/local/05_ddl/alter_table.result | 24 +- tests/cases/local/05_ddl/create_tables.result | 66 +++- tests/cases/local/05_ddl/create_tables.sql | 13 + .../local/06_show/show_create_table.result | 6 +- tests/cases/local/basic.result | 10 +- 8 files changed, 307 insertions(+), 180 deletions(-) diff --git a/sql/src/planner.rs b/sql/src/planner.rs index acfed7a66d..929d4e09ce 100644 --- a/sql/src/planner.rs +++ b/sql/src/planner.rs @@ -31,7 +31,7 @@ use hashbrown::HashMap as NoStdHashMap; use log::debug; use snafu::{ensure, Backtrace, OptionExt, ResultExt, Snafu}; use sqlparser::ast::{ - ColumnDef, ColumnOption, Expr, ObjectName, Query, SetExpr, SqlOption, + ColumnDef, ColumnOption, Expr, Ident, ObjectName, Query, SetExpr, SqlOption, Statement as SqlStatement, TableConstraint, UnaryOperator, Value, Values, }; use table_engine::table::TableRef; @@ -100,14 +100,33 @@ pub enum Error { backtrace: Backtrace, }, + #[snafu(display( + "Undefined column is used in primary key, column name:{}.\nBacktrace:\n{}", + name, + backtrace + ))] + UndefinedColumnInPrimaryKey { name: String, backtrace: Backtrace }, + #[snafu(display("Primary key not found, column name:{}", name))] PrimaryKeyNotFound { name: String }, + #[snafu(display( + "Duplicate definitions of primary key are found, first:{:?}, second:{:?}.\nBacktrace:\n{:?}", + first, + second, + backtrace, + ))] + DuplicatePrimaryKey { + first: Vec, + second: Vec, + backtrace: Backtrace, + }, + #[snafu(display("Tag column not found, name:{}", name))] TagColumnNotFound { name: String }, #[snafu(display( - "Timestamp key column can not be tag, name:{}.\nBactrace:\n{:?}", + "Timestamp key column can not be tag, name:{}.\nBacktrace:\n{:?}", name, backtrace ))] @@ -214,6 +233,8 @@ pub enum Error { define_result!(Error); +const DEFAULT_QUOTE_CHAR: char = '`'; + /// Planner produces logical plans from SQL AST // TODO(yingwen): Rewrite Planner instead of using datafusion's planner pub struct Planner<'a, P: MetaProvider> { @@ -322,51 +343,50 @@ impl<'a, P: MetaProvider> PlannerDelegate<'a, P> { }) } - fn create_table_to_plan(&self, stmt: CreateTable) -> Result { - ensure!(!stmt.table_name.is_empty(), CreateTableNameEmpty); - - debug!("Create table to plan, stmt:{:?}", stmt); - - // TODO(yingwen): Maybe support create table on other schema? - let table_name = stmt.table_name.to_string(); - let table_ref = TableReference::from(table_name.as_str()); - - // Now we only takes the table name and ignore the schema and catalog name - let table = table_ref.table().to_string(); - - let mut schema_builder = - schema::Builder::with_capacity(stmt.columns.len()).auto_increment_column_id(true); - - // Build all column schemas. - let mut name_column_map = stmt - .columns - .iter() - .map(|col| Ok((col.name.value.as_str(), parse_column(col)?))) - .collect::>>()?; - - let name_column_index_map = stmt - .columns - .iter() - .enumerate() - .map(|(idx, col)| (col.name.value.as_str(), idx)) - .collect::>(); + fn create_table_schema( + columns: &[Ident], + primary_key_columns: &[Ident], + mut columns_by_name: HashMap<&str, ColumnSchema>, + column_idxs_by_name: HashMap<&str, usize>, + enable_tsid_primary_key: bool, + ) -> Result { + assert_eq!(columns_by_name.len(), column_idxs_by_name.len()); + + let mut schema_builder = schema::Builder::with_capacity(columns_by_name.len()) + .auto_increment_column_id(true) + .enable_tsid_primary_key(enable_tsid_primary_key); + + // Collect the key columns. + for key_col in primary_key_columns { + let col_name = key_col.value.as_str(); + let col = columns_by_name + .remove(col_name) + .context(UndefinedColumnInPrimaryKey { name: col_name })?; + schema_builder = schema_builder + .add_key_column(col) + .context(BuildTableSchema)?; + } - // Tsid column is a reserved column. - ensure!( - !name_column_map.contains_key(TSID_COLUMN), - ColumnNameReserved { - name: TSID_COLUMN.to_string(), + // Collect the normal columns. + for normal_col in columns { + let col_name = normal_col.value.as_str(); + // Only normal columns are kept in the `columns_by_name`. + if let Some(col) = columns_by_name.remove(col_name) { + schema_builder = schema_builder + .add_normal_column(col) + .context(BuildTableSchema)?; } - ); - - // Find timestamp key and primary key contraint - - let mut timestamp_column_idx = None; - let mut timestamp_name = None; + } - let mut primary_key_column_idxs = vec![]; + schema_builder.build().context(BuildTableSchema) + } - for constraint in stmt.constraints.iter() { + // Find the primary key columns and ensure at most only one exists. + fn find_and_ensure_primary_key_columns( + constraints: &[TableConstraint], + ) -> Result>> { + let mut primary_key_columns: Option> = None; + for constraint in constraints { if let TableConstraint::Unique { columns, is_primary, @@ -374,91 +394,145 @@ impl<'a, P: MetaProvider> PlannerDelegate<'a, P> { } = constraint { if *is_primary { - // Build primary key, the builder will check timestamp column is in primary key. - for column in columns { - if let Some(idx) = name_column_index_map.get(&*column.value) { - primary_key_column_idxs.push(*idx); + ensure!( + primary_key_columns.is_none(), + DuplicatePrimaryKey { + first: primary_key_columns.unwrap(), + second: columns.clone() } - } - } else if parser::is_timestamp_key_constraint(constraint) { + ); + primary_key_columns = Some(columns.clone()); + } + } + } + + Ok(primary_key_columns) + } + + // Find the timestamp column and ensure its valid existence (only one). + fn find_and_ensure_timestamp_column( + columns_by_name: &HashMap<&str, ColumnSchema>, + constraints: &[TableConstraint], + ) -> Result { + let mut timestamp_column_name = None; + for constraint in constraints { + if let TableConstraint::Unique { columns, .. } = constraint { + if parser::is_timestamp_key_constraint(constraint) { // Only one timestamp key constraint - ensure!(timestamp_column_idx.is_none(), InvalidTimestampKey); + ensure!(timestamp_column_name.is_none(), InvalidTimestampKey); // Only one column in constraint ensure!(columns.len() == 1, InvalidTimestampKey); + let timestamp_ident = columns[0].clone(); - let name = &columns[0].value; - let timestamp_column = name_column_map - .get(name as &str) - .context(TimestampColumnNotFound { name })?; - // Ensure type is timestamp + let timestamp_column = columns_by_name + .get(timestamp_ident.value.as_str()) + .context(TimestampColumnNotFound { + name: ×tamp_ident.value, + })?; + + // Ensure the timestamp key's type is timestamp. ensure!( timestamp_column.data_type == DatumKind::Timestamp, InvalidTimestampKey ); - let column_idx = name_column_index_map - .get(name as &str) - .context(TimestampColumnNotFound { name })?; + // Ensure the timestamp key is not a tag. + ensure!( + !timestamp_column.is_tag, + TimestampKeyTag { + name: ×tamp_ident.value, + } + ); - timestamp_column_idx = Some(*column_idx); - timestamp_name = Some(name.clone()); + timestamp_column_name = Some(timestamp_ident); } } } - // Timestamp column must be provided. - let timestamp_name = timestamp_name.context(RequireTimestamp)?; - // The timestamp key column must not be a Tag column - if let Some(timestamp_column) = name_column_map.get(×tamp_name.as_str()) { - ensure!( - !timestamp_column.is_tag, - TimestampKeyTag { - name: ×tamp_name, - } - ) - } + timestamp_column_name.context(RequireTimestamp) + } - let timestamp_col_idx = timestamp_column_idx.context(RequireTimestamp)?; - // The key columns have been consumed. - for (idx, col) in stmt.columns.iter().enumerate() { - let col_name = col.name.value.as_str(); - if let Some(col) = name_column_map.remove(col_name) { - if !primary_key_column_idxs.is_empty() { - if primary_key_column_idxs.contains(&idx) { - let key_column = if TSID_COLUMN == col.name { - schema_builder = schema_builder.enable_tsid_primary_key(true); - Self::tsid_column_schema()? - } else { - col - }; - schema_builder = schema_builder - .add_key_column(key_column) - .context(BuildTableSchema)?; - continue; - } - } else if timestamp_col_idx == idx { - // If primary key is not set, Use (timestamp, tsid) as primary key. - schema_builder = schema_builder - .enable_tsid_primary_key(true) - .add_key_column(col) - .context(BuildTableSchema)? - .add_key_column(Self::tsid_column_schema()?) - .context(BuildTableSchema)?; - continue; - } + fn create_table_to_plan(&self, stmt: CreateTable) -> Result { + ensure!(!stmt.table_name.is_empty(), CreateTableNameEmpty); - schema_builder = schema_builder - .add_normal_column(col) - .context(BuildTableSchema)?; + debug!("Create table to plan, stmt:{:?}", stmt); + + // Build all column schemas. + let mut columns_by_name = stmt + .columns + .iter() + .map(|col| Ok((col.name.value.as_str(), parse_column(col)?))) + .collect::>>()?; + + let mut column_idxs_by_name: HashMap<_, _> = stmt + .columns + .iter() + .enumerate() + .map(|(idx, col)| (col.name.value.as_str(), idx)) + .collect(); + + // Tsid column is a reserved column. + ensure!( + !columns_by_name.contains_key(TSID_COLUMN), + ColumnNameReserved { + name: TSID_COLUMN.to_string(), } - } + ); - let table_schema = schema_builder.build().context(BuildTableSchema)?; + let timestamp_column = + Self::find_and_ensure_timestamp_column(&columns_by_name, &stmt.constraints)?; + let tsid_column = Ident::with_quote(DEFAULT_QUOTE_CHAR, TSID_COLUMN); + let mut columns: Vec<_> = stmt.columns.iter().map(|col| col.name.clone()).collect(); + let mut enable_tsid_primary_key = false; + + let mut add_tsid_column = || { + columns_by_name.insert(TSID_COLUMN, Self::tsid_column_schema()?); + column_idxs_by_name.insert(TSID_COLUMN, columns.len()); + columns.push(tsid_column.clone()); + enable_tsid_primary_key = true; + Ok(()) + }; + let primary_key_columns = + match Self::find_and_ensure_primary_key_columns(&stmt.constraints)? { + Some(primary_key_columns) => { + // Ensure the primary key is defined already. + for col in &primary_key_columns { + let col_name = &col.value; + if col_name == TSID_COLUMN { + // tsid column is a reserved column which can't be + // defined by user, so let's add it manually. + add_tsid_column()?; + } + } + + primary_key_columns + } + None => { + // No primary key is provided explicitly, so let's use `(tsid, + // timestamp_key)` as the default primary key. + add_tsid_column()?; + + vec![tsid_column, timestamp_column] + } + }; + let table_schema = Self::create_table_schema( + &columns, + &primary_key_columns, + columns_by_name, + column_idxs_by_name, + enable_tsid_primary_key, + )?; let options = parse_options(stmt.options)?; // ensure default value options are valid ensure_column_default_value_valid(table_schema.columns(), &self.meta_provider)?; + // TODO(yingwen): Maybe support create table on other schema? + let table_name = stmt.table_name.to_string(); + let table_ref = TableReference::from(table_name.as_str()); + // Now we only takes the table name and ignore the schema and catalog name + let table = table_ref.table().to_string(); + let plan = CreateTablePlan { engine: stmt.engine, if_not_exists: stmt.if_not_exists, diff --git a/tests/cases/local/03_dml/case_insensitive.result b/tests/cases/local/03_dml/case_insensitive.result index a72e7afd81..8d7e11809f 100644 --- a/tests/cases/local/03_dml/case_insensitive.result +++ b/tests/cases/local/03_dml/case_insensitive.result @@ -22,10 +22,10 @@ SELECT FROM case_insensitive_table1; -ts,tsid,value1, -Timestamp(Timestamp(1)),Int64(0),Double(10.0), -Timestamp(Timestamp(2)),Int64(0),Double(20.0), -Timestamp(Timestamp(3)),Int64(0),Double(30.0), +tsid,ts,value1, +Int64(0),Timestamp(Timestamp(1)),Double(10.0), +Int64(0),Timestamp(Timestamp(2)),Double(20.0), +Int64(0),Timestamp(Timestamp(3)),Double(30.0), SELECT @@ -33,37 +33,37 @@ SELECT FROM CASE_INSENSITIVE_TABLE1; -ts,tsid,value1, -Timestamp(Timestamp(1)),Int64(0),Double(10.0), -Timestamp(Timestamp(2)),Int64(0),Double(20.0), -Timestamp(Timestamp(3)),Int64(0),Double(30.0), +tsid,ts,value1, +Int64(0),Timestamp(Timestamp(1)),Double(10.0), +Int64(0),Timestamp(Timestamp(2)),Double(20.0), +Int64(0),Timestamp(Timestamp(3)),Double(30.0), SHOW CREATE TABLE case_insensitive_table1; Table,Create Table, -String(StringBytes(b"case_insensitive_table1")),String(StringBytes(b"CREATE TABLE `case_insensitive_table1` (`ts` timestamp NOT NULL, `tsid` uint64 NOT NULL, `value1` double, PRIMARY KEY(ts,tsid), TIMESTAMP KEY(ts)) ENGINE=Analytic WITH(arena_block_size='2097152', compaction_strategy='default', compression='ZSTD', enable_ttl='false', num_rows_per_row_group='8192', segment_duration='', storage_format='COLUMNAR', ttl='7d', update_mode='OVERWRITE', write_buffer_size='33554432')")), +String(StringBytes(b"case_insensitive_table1")),String(StringBytes(b"CREATE TABLE `case_insensitive_table1` (`tsid` uint64 NOT NULL, `ts` timestamp NOT NULL, `value1` double, PRIMARY KEY(tsid,ts), TIMESTAMP KEY(ts)) ENGINE=Analytic WITH(arena_block_size='2097152', compaction_strategy='default', compression='ZSTD', enable_ttl='false', num_rows_per_row_group='8192', segment_duration='', storage_format='COLUMNAR', ttl='7d', update_mode='OVERWRITE', write_buffer_size='33554432')")), SHOW CREATE TABLE CASE_INSENSITIVE_TABLE1; Table,Create Table, -String(StringBytes(b"case_insensitive_table1")),String(StringBytes(b"CREATE TABLE `case_insensitive_table1` (`ts` timestamp NOT NULL, `tsid` uint64 NOT NULL, `value1` double, PRIMARY KEY(ts,tsid), TIMESTAMP KEY(ts)) ENGINE=Analytic WITH(arena_block_size='2097152', compaction_strategy='default', compression='ZSTD', enable_ttl='false', num_rows_per_row_group='8192', segment_duration='', storage_format='COLUMNAR', ttl='7d', update_mode='OVERWRITE', write_buffer_size='33554432')")), +String(StringBytes(b"case_insensitive_table1")),String(StringBytes(b"CREATE TABLE `case_insensitive_table1` (`tsid` uint64 NOT NULL, `ts` timestamp NOT NULL, `value1` double, PRIMARY KEY(tsid,ts), TIMESTAMP KEY(ts)) ENGINE=Analytic WITH(arena_block_size='2097152', compaction_strategy='default', compression='ZSTD', enable_ttl='false', num_rows_per_row_group='8192', segment_duration='', storage_format='COLUMNAR', ttl='7d', update_mode='OVERWRITE', write_buffer_size='33554432')")), DESC case_insensitive_table1; name,type,is_primary,is_nullable,is_tag, -String(StringBytes(b"ts")),String(StringBytes(b"timestamp")),Boolean(true),Boolean(false),Boolean(false), String(StringBytes(b"tsid")),String(StringBytes(b"uint64")),Boolean(true),Boolean(false),Boolean(false), +String(StringBytes(b"ts")),String(StringBytes(b"timestamp")),Boolean(true),Boolean(false),Boolean(false), String(StringBytes(b"value1")),String(StringBytes(b"double")),Boolean(false),Boolean(true),Boolean(false), DESC CASE_INSENSITIVE_TABLE1; name,type,is_primary,is_nullable,is_tag, -String(StringBytes(b"ts")),String(StringBytes(b"timestamp")),Boolean(true),Boolean(false),Boolean(false), String(StringBytes(b"tsid")),String(StringBytes(b"uint64")),Boolean(true),Boolean(false),Boolean(false), +String(StringBytes(b"ts")),String(StringBytes(b"timestamp")),Boolean(true),Boolean(false),Boolean(false), String(StringBytes(b"value1")),String(StringBytes(b"double")),Boolean(false),Boolean(true),Boolean(false), diff --git a/tests/cases/local/03_dml/insert_mode.result b/tests/cases/local/03_dml/insert_mode.result index b05acd503a..ecd3cf824d 100644 --- a/tests/cases/local/03_dml/insert_mode.result +++ b/tests/cases/local/03_dml/insert_mode.result @@ -25,10 +25,10 @@ FROM ORDER BY `value` ASC; -timestamp,tsid,value, -Timestamp(Timestamp(3)),Int64(0),Double(-30.0), -Timestamp(Timestamp(2)),Int64(0),Double(0.0), -Timestamp(Timestamp(1)),Int64(0),Double(10.0), +tsid,timestamp,value, +Int64(0),Timestamp(Timestamp(3)),Double(-30.0), +Int64(0),Timestamp(Timestamp(2)),Double(0.0), +Int64(0),Timestamp(Timestamp(1)),Double(10.0), INSERT INTO `03_dml_insert_mode_table1` (`timestamp`, `value`) @@ -43,10 +43,10 @@ FROM ORDER BY `value` ASC; -timestamp,tsid,value, -Timestamp(Timestamp(1)),Int64(0),Double(100.0), -Timestamp(Timestamp(2)),Int64(0),Double(200.0), -Timestamp(Timestamp(3)),Int64(0),Double(300.0), +tsid,timestamp,value, +Int64(0),Timestamp(Timestamp(1)),Double(100.0), +Int64(0),Timestamp(Timestamp(2)),Double(200.0), +Int64(0),Timestamp(Timestamp(3)),Double(300.0), DROP TABLE `03_dml_insert_mode_table1`; @@ -80,10 +80,10 @@ FROM ORDER BY `value` ASC; -timestamp,tsid,value, -Timestamp(Timestamp(1)),Int64(0),Double(10.0), -Timestamp(Timestamp(2)),Int64(0),Double(20.0), -Timestamp(Timestamp(3)),Int64(0),Double(30.0), +tsid,timestamp,value, +Int64(0),Timestamp(Timestamp(1)),Double(10.0), +Int64(0),Timestamp(Timestamp(2)),Double(20.0), +Int64(0),Timestamp(Timestamp(3)),Double(30.0), INSERT INTO `03_dml_insert_mode_table2` (`timestamp`, `value`) @@ -98,13 +98,13 @@ FROM ORDER BY `value` ASC; -timestamp,tsid,value, -Timestamp(Timestamp(1)),Int64(0),Double(10.0), -Timestamp(Timestamp(2)),Int64(0),Double(20.0), -Timestamp(Timestamp(3)),Int64(0),Double(30.0), -Timestamp(Timestamp(1)),Int64(0),Double(100.0), -Timestamp(Timestamp(2)),Int64(0),Double(200.0), -Timestamp(Timestamp(3)),Int64(0),Double(300.0), +tsid,timestamp,value, +Int64(0),Timestamp(Timestamp(1)),Double(10.0), +Int64(0),Timestamp(Timestamp(2)),Double(20.0), +Int64(0),Timestamp(Timestamp(3)),Double(30.0), +Int64(0),Timestamp(Timestamp(1)),Double(100.0), +Int64(0),Timestamp(Timestamp(2)),Double(200.0), +Int64(0),Timestamp(Timestamp(3)),Double(300.0), DROP TABLE `03_dml_insert_mode_table2`; @@ -137,10 +137,10 @@ FROM ORDER BY `value` ASC; -timestamp,tsid,value, -Timestamp(Timestamp(1)),Int64(0),Double(10.0), -Timestamp(Timestamp(2)),Int64(0),Double(20.0), -Timestamp(Timestamp(3)),Int64(0),Double(30.0), +tsid,timestamp,value, +Int64(0),Timestamp(Timestamp(1)),Double(10.0), +Int64(0),Timestamp(Timestamp(2)),Double(20.0), +Int64(0),Timestamp(Timestamp(3)),Double(30.0), INSERT INTO `03_dml_insert_mode_table3` (`timestamp`, `value`) @@ -155,10 +155,10 @@ FROM ORDER BY `value` ASC; -timestamp,tsid,value, -Timestamp(Timestamp(1)),Int64(0),Double(100.0), -Timestamp(Timestamp(2)),Int64(0),Double(200.0), -Timestamp(Timestamp(3)),Int64(0),Double(300.0), +tsid,timestamp,value, +Int64(0),Timestamp(Timestamp(1)),Double(100.0), +Int64(0),Timestamp(Timestamp(2)),Double(200.0), +Int64(0),Timestamp(Timestamp(3)),Double(300.0), DROP TABLE `03_dml_insert_mode_table3`; @@ -195,9 +195,9 @@ FROM ORDER BY `c1` ASC; -timestamp,tsid,c1,c2,c3,c4,c5, -Timestamp(Timestamp(1)),Int64(0),Int64(10),String(StringBytes(b"123")),Int64(11),Int64(12),Int64(3), -Timestamp(Timestamp(2)),Int64(0),Int64(20),String(StringBytes(b"123")),Int64(21),Int64(22),Int64(4), -Timestamp(Timestamp(3)),Int64(0),Int64(30),String(StringBytes(b"123")),Int64(31),Int64(32),Int64(5), +tsid,timestamp,c1,c2,c3,c4,c5, +Int64(0),Timestamp(Timestamp(1)),Int64(10),String(StringBytes(b"123")),Int64(11),Int64(12),Int64(3), +Int64(0),Timestamp(Timestamp(2)),Int64(20),String(StringBytes(b"123")),Int64(21),Int64(22),Int64(4), +Int64(0),Timestamp(Timestamp(3)),Int64(30),String(StringBytes(b"123")),Int64(31),Int64(32),Int64(5), diff --git a/tests/cases/local/05_ddl/alter_table.result b/tests/cases/local/05_ddl/alter_table.result index cf14f52448..a10a298d87 100644 --- a/tests/cases/local/05_ddl/alter_table.result +++ b/tests/cases/local/05_ddl/alter_table.result @@ -12,8 +12,8 @@ affected_rows: 1 SELECT * FROM `05_alter_table_t0`; -a,t,tsid, -Int32(1),Timestamp(Timestamp(1)),Int64(0), +tsid,t,a, +Int64(0),Timestamp(Timestamp(1)),Int32(1), ALTER TABLE `05_alter_table_t0` RENAME TO `t1`; @@ -27,9 +27,9 @@ affected_rows: 0 DESCRIBE TABLE `05_alter_table_t0`; name,type,is_primary,is_nullable,is_tag, -String(StringBytes(b"a")),String(StringBytes(b"int")),Boolean(false),Boolean(true),Boolean(false), -String(StringBytes(b"t")),String(StringBytes(b"timestamp")),Boolean(true),Boolean(false),Boolean(false), String(StringBytes(b"tsid")),String(StringBytes(b"uint64")),Boolean(true),Boolean(false),Boolean(false), +String(StringBytes(b"t")),String(StringBytes(b"timestamp")),Boolean(true),Boolean(false),Boolean(false), +String(StringBytes(b"a")),String(StringBytes(b"int")),Boolean(false),Boolean(true),Boolean(false), String(StringBytes(b"b")),String(StringBytes(b"string")),Boolean(false),Boolean(true),Boolean(false), @@ -39,9 +39,9 @@ affected_rows: 1 SELECT * FROM `05_alter_table_t0`; -a,t,tsid,b, -Int32(1),Timestamp(Timestamp(1)),Int64(0),Null, -Int32(2),Timestamp(Timestamp(2)),Int64(0),String(StringBytes(b"2")), +tsid,t,a,b, +Int64(0),Timestamp(Timestamp(1)),Int32(1),Null, +Int64(0),Timestamp(Timestamp(2)),Int32(2),String(StringBytes(b"2")), ALTER TABLE `05_alter_table_t0` DROP COLUMN b; @@ -51,17 +51,17 @@ Failed to execute query, err: Server(ServerError { code: 500, msg: "Failed to cr DESCRIBE TABLE `05_alter_table_t0`; name,type,is_primary,is_nullable,is_tag, -String(StringBytes(b"a")),String(StringBytes(b"int")),Boolean(false),Boolean(true),Boolean(false), -String(StringBytes(b"t")),String(StringBytes(b"timestamp")),Boolean(true),Boolean(false),Boolean(false), String(StringBytes(b"tsid")),String(StringBytes(b"uint64")),Boolean(true),Boolean(false),Boolean(false), +String(StringBytes(b"t")),String(StringBytes(b"timestamp")),Boolean(true),Boolean(false),Boolean(false), +String(StringBytes(b"a")),String(StringBytes(b"int")),Boolean(false),Boolean(true),Boolean(false), String(StringBytes(b"b")),String(StringBytes(b"string")),Boolean(false),Boolean(true),Boolean(false), SELECT * FROM `05_alter_table_t0`; -a,t,tsid,b, -Int32(1),Timestamp(Timestamp(1)),Int64(0),Null, -Int32(2),Timestamp(Timestamp(2)),Int64(0),String(StringBytes(b"2")), +tsid,t,a,b, +Int64(0),Timestamp(Timestamp(1)),Int32(1),Null, +Int64(0),Timestamp(Timestamp(2)),Int32(2),String(StringBytes(b"2")), DROP TABLE `05_alter_table_t0`; diff --git a/tests/cases/local/05_ddl/create_tables.result b/tests/cases/local/05_ddl/create_tables.result index 99a2790456..e692bf4911 100644 --- a/tests/cases/local/05_ddl/create_tables.result +++ b/tests/cases/local/05_ddl/create_tables.result @@ -84,15 +84,15 @@ affected_rows: 0 describe table `05_create_tables_t4`; name,type,is_primary,is_nullable,is_tag, -String(StringBytes(b"a")),String(StringBytes(b"int")),Boolean(false),Boolean(true),Boolean(false), -String(StringBytes(b"t")),String(StringBytes(b"timestamp")),Boolean(true),Boolean(false),Boolean(false), String(StringBytes(b"tsid")),String(StringBytes(b"uint64")),Boolean(true),Boolean(false),Boolean(false), +String(StringBytes(b"t")),String(StringBytes(b"timestamp")),Boolean(true),Boolean(false),Boolean(false), +String(StringBytes(b"a")),String(StringBytes(b"int")),Boolean(false),Boolean(true),Boolean(false), show create table `05_create_tables_t4`; Table,Create Table, -String(StringBytes(b"05_create_tables_t4")),String(StringBytes(b"CREATE TABLE `05_create_tables_t4` (`a` int, `t` timestamp NOT NULL, `tsid` uint64 NOT NULL, PRIMARY KEY(t,tsid), TIMESTAMP KEY(t)) ENGINE=Analytic WITH(arena_block_size='2097152', compaction_strategy='default', compression='ZSTD', enable_ttl='true', num_rows_per_row_group='8192', segment_duration='', storage_format='COLUMNAR', ttl='7d', update_mode='OVERWRITE', write_buffer_size='33554432')")), +String(StringBytes(b"05_create_tables_t4")),String(StringBytes(b"CREATE TABLE `05_create_tables_t4` (`tsid` uint64 NOT NULL, `t` timestamp NOT NULL, `a` int, PRIMARY KEY(tsid,t), TIMESTAMP KEY(t)) ENGINE=Analytic WITH(arena_block_size='2097152', compaction_strategy='default', compression='ZSTD', enable_ttl='true', num_rows_per_row_group='8192', segment_duration='', storage_format='COLUMNAR', ttl='7d', update_mode='OVERWRITE', write_buffer_size='33554432')")), CREATE TABLE `05_create_tables_t5`(c1 int, t timestamp NOT NULL TIMESTAMP KEY) ENGINE = Analytic; @@ -102,15 +102,15 @@ affected_rows: 0 describe table `05_create_tables_t5`; name,type,is_primary,is_nullable,is_tag, -String(StringBytes(b"c1")),String(StringBytes(b"int")),Boolean(false),Boolean(true),Boolean(false), -String(StringBytes(b"t")),String(StringBytes(b"timestamp")),Boolean(true),Boolean(false),Boolean(false), String(StringBytes(b"tsid")),String(StringBytes(b"uint64")),Boolean(true),Boolean(false),Boolean(false), +String(StringBytes(b"t")),String(StringBytes(b"timestamp")),Boolean(true),Boolean(false),Boolean(false), +String(StringBytes(b"c1")),String(StringBytes(b"int")),Boolean(false),Boolean(true),Boolean(false), show create table `05_create_tables_t5`; Table,Create Table, -String(StringBytes(b"05_create_tables_t5")),String(StringBytes(b"CREATE TABLE `05_create_tables_t5` (`c1` int, `t` timestamp NOT NULL, `tsid` uint64 NOT NULL, PRIMARY KEY(t,tsid), TIMESTAMP KEY(t)) ENGINE=Analytic WITH(arena_block_size='2097152', compaction_strategy='default', compression='ZSTD', enable_ttl='true', num_rows_per_row_group='8192', segment_duration='', storage_format='COLUMNAR', ttl='7d', update_mode='OVERWRITE', write_buffer_size='33554432')")), +String(StringBytes(b"05_create_tables_t5")),String(StringBytes(b"CREATE TABLE `05_create_tables_t5` (`tsid` uint64 NOT NULL, `t` timestamp NOT NULL, `c1` int, PRIMARY KEY(tsid,t), TIMESTAMP KEY(t)) ENGINE=Analytic WITH(arena_block_size='2097152', compaction_strategy='default', compression='ZSTD', enable_ttl='true', num_rows_per_row_group='8192', segment_duration='', storage_format='COLUMNAR', ttl='7d', update_mode='OVERWRITE', write_buffer_size='33554432')")), CREATE TABLE `05_create_tables_t6`(c1 int, t1 timestamp NOT NULL TIMESTAMP KEY, t2 timestamp NOT NULL TIMESTAMP KEY) ENGINE = Analytic; @@ -124,15 +124,15 @@ affected_rows: 0 describe table `05_create_tables_t7`; name,type,is_primary,is_nullable,is_tag, -String(StringBytes(b"c1")),String(StringBytes(b"int")),Boolean(false),Boolean(true),Boolean(false), -String(StringBytes(b"t")),String(StringBytes(b"timestamp")),Boolean(true),Boolean(false),Boolean(false), String(StringBytes(b"tsid")),String(StringBytes(b"uint64")),Boolean(true),Boolean(false),Boolean(false), +String(StringBytes(b"t")),String(StringBytes(b"timestamp")),Boolean(true),Boolean(false),Boolean(false), +String(StringBytes(b"c1")),String(StringBytes(b"int")),Boolean(false),Boolean(true),Boolean(false), show create table `05_create_tables_t7`; Table,Create Table, -String(StringBytes(b"05_create_tables_t7")),String(StringBytes(b"CREATE TABLE `05_create_tables_t7` (`c1` int COMMENT 'id', `t` timestamp NOT NULL, `tsid` uint64 NOT NULL, PRIMARY KEY(t,tsid), TIMESTAMP KEY(t)) ENGINE=Analytic WITH(arena_block_size='2097152', compaction_strategy='default', compression='ZSTD', enable_ttl='true', num_rows_per_row_group='8192', segment_duration='', storage_format='COLUMNAR', ttl='7d', update_mode='OVERWRITE', write_buffer_size='33554432')")), +String(StringBytes(b"05_create_tables_t7")),String(StringBytes(b"CREATE TABLE `05_create_tables_t7` (`tsid` uint64 NOT NULL, `t` timestamp NOT NULL, `c1` int COMMENT 'id', PRIMARY KEY(tsid,t), TIMESTAMP KEY(t)) ENGINE=Analytic WITH(arena_block_size='2097152', compaction_strategy='default', compression='ZSTD', enable_ttl='true', num_rows_per_row_group='8192', segment_duration='', storage_format='COLUMNAR', ttl='7d', update_mode='OVERWRITE', write_buffer_size='33554432')")), CREATE TABLE `05_create_tables_t8`(c1 int, t1 timestamp NOT NULL TIMESTAMP KEY) ENGINE = Analytic; @@ -142,7 +142,7 @@ affected_rows: 0 show create table `05_create_tables_t8`; Table,Create Table, -String(StringBytes(b"05_create_tables_t8")),String(StringBytes(b"CREATE TABLE `05_create_tables_t8` (`c1` int, `t1` timestamp NOT NULL, `tsid` uint64 NOT NULL, PRIMARY KEY(t1,tsid), TIMESTAMP KEY(t1)) ENGINE=Analytic WITH(arena_block_size='2097152', compaction_strategy='default', compression='ZSTD', enable_ttl='true', num_rows_per_row_group='8192', segment_duration='', storage_format='COLUMNAR', ttl='7d', update_mode='OVERWRITE', write_buffer_size='33554432')")), +String(StringBytes(b"05_create_tables_t8")),String(StringBytes(b"CREATE TABLE `05_create_tables_t8` (`tsid` uint64 NOT NULL, `t1` timestamp NOT NULL, `c1` int, PRIMARY KEY(tsid,t1), TIMESTAMP KEY(t1)) ENGINE=Analytic WITH(arena_block_size='2097152', compaction_strategy='default', compression='ZSTD', enable_ttl='true', num_rows_per_row_group='8192', segment_duration='', storage_format='COLUMNAR', ttl='7d', update_mode='OVERWRITE', write_buffer_size='33554432')")), drop table `05_create_tables_t8`; @@ -156,7 +156,7 @@ affected_rows: 0 show create table `05_create_tables_t8`; Table,Create Table, -String(StringBytes(b"05_create_tables_t8")),String(StringBytes(b"CREATE TABLE `05_create_tables_t8` (`c1` int, `t1` timestamp NOT NULL, `tsid` uint64 NOT NULL, PRIMARY KEY(t1,tsid), TIMESTAMP KEY(t1)) ENGINE=Analytic WITH(arena_block_size='2097152', compaction_strategy='default', compression='ZSTD', enable_ttl='true', num_rows_per_row_group='8192', segment_duration='', storage_format='COLUMNAR', ttl='7d', update_mode='OVERWRITE', write_buffer_size='33554432')")), +String(StringBytes(b"05_create_tables_t8")),String(StringBytes(b"CREATE TABLE `05_create_tables_t8` (`tsid` uint64 NOT NULL, `t1` timestamp NOT NULL, `c1` int, PRIMARY KEY(tsid,t1), TIMESTAMP KEY(t1)) ENGINE=Analytic WITH(arena_block_size='2097152', compaction_strategy='default', compression='ZSTD', enable_ttl='true', num_rows_per_row_group='8192', segment_duration='', storage_format='COLUMNAR', ttl='7d', update_mode='OVERWRITE', write_buffer_size='33554432')")), drop table `05_create_tables_t8`; @@ -170,7 +170,7 @@ affected_rows: 0 show create table `05_create_tables_t8`; Table,Create Table, -String(StringBytes(b"05_create_tables_t8")),String(StringBytes(b"CREATE TABLE `05_create_tables_t8` (`c1` int, `t1` timestamp NOT NULL, `tsid` uint64 NOT NULL, PRIMARY KEY(t1,tsid), TIMESTAMP KEY(t1)) ENGINE=Analytic WITH(arena_block_size='2097152', compaction_strategy='default', compression='ZSTD', enable_ttl='true', num_rows_per_row_group='8192', segment_duration='', storage_format='HYBRID', ttl='7d', update_mode='OVERWRITE', write_buffer_size='33554432')")), +String(StringBytes(b"05_create_tables_t8")),String(StringBytes(b"CREATE TABLE `05_create_tables_t8` (`tsid` uint64 NOT NULL, `t1` timestamp NOT NULL, `c1` int, PRIMARY KEY(tsid,t1), TIMESTAMP KEY(t1)) ENGINE=Analytic WITH(arena_block_size='2097152', compaction_strategy='default', compression='ZSTD', enable_ttl='true', num_rows_per_row_group='8192', segment_duration='', storage_format='HYBRID', ttl='7d', update_mode='OVERWRITE', write_buffer_size='33554432')")), drop table `05_create_tables_t8`; @@ -184,13 +184,41 @@ affected_rows: 0 show create table `05_create_tables_t9`; Table,Create Table, -String(StringBytes(b"05_create_tables_t9")),String(StringBytes(b"CREATE TABLE `05_create_tables_t9` (`c1` int, `c2` bigint DEFAULT 0, `c3` uint32 DEFAULT 1 + 1, `c4` string DEFAULT 'xxx', `c5` uint32 DEFAULT c3 * 2 + 1, `t1` timestamp NOT NULL, `tsid` uint64 NOT NULL, PRIMARY KEY(t1,tsid), TIMESTAMP KEY(t1)) ENGINE=Analytic WITH(arena_block_size='2097152', compaction_strategy='default', compression='ZSTD', enable_ttl='true', num_rows_per_row_group='8192', segment_duration='', storage_format='COLUMNAR', ttl='7d', update_mode='OVERWRITE', write_buffer_size='33554432')")), +String(StringBytes(b"05_create_tables_t9")),String(StringBytes(b"CREATE TABLE `05_create_tables_t9` (`tsid` uint64 NOT NULL, `t1` timestamp NOT NULL, `c1` int, `c2` bigint DEFAULT 0, `c3` uint32 DEFAULT 1 + 1, `c4` string DEFAULT 'xxx', `c5` uint32 DEFAULT c3 * 2 + 1, PRIMARY KEY(tsid,t1), TIMESTAMP KEY(t1)) ENGINE=Analytic WITH(arena_block_size='2097152', compaction_strategy='default', compression='ZSTD', enable_ttl='true', num_rows_per_row_group='8192', segment_duration='', storage_format='COLUMNAR', ttl='7d', update_mode='OVERWRITE', write_buffer_size='33554432')")), drop table `05_create_tables_t9`; affected_rows: 0 +CREATE TABLE `05_create_tables_t10`(c1 int, t1 timestamp NOT NULL TIMESTAMP KEY, PRIMARY KEY(tsid, t1)) ENGINE = Analytic; + +affected_rows: 0 + +show create table `05_create_tables_t10`; + +Table,Create Table, +String(StringBytes(b"05_create_tables_t10")),String(StringBytes(b"CREATE TABLE `05_create_tables_t10` (`tsid` uint64 NOT NULL, `t1` timestamp NOT NULL, `c1` int, PRIMARY KEY(tsid,t1), TIMESTAMP KEY(t1)) ENGINE=Analytic WITH(arena_block_size='2097152', compaction_strategy='default', compression='ZSTD', enable_ttl='true', num_rows_per_row_group='8192', segment_duration='', storage_format='COLUMNAR', ttl='7d', update_mode='OVERWRITE', write_buffer_size='33554432')")), + + +drop table `05_create_tables_t10`; + +affected_rows: 0 + +CREATE TABLE `05_create_tables_t11`(c1 int, t1 timestamp NOT NULL TIMESTAMP KEY, PRIMARY KEY(t1, tsid)) ENGINE = Analytic; + +affected_rows: 0 + +show create table `05_create_tables_t11`; + +Table,Create Table, +String(StringBytes(b"05_create_tables_t11")),String(StringBytes(b"CREATE TABLE `05_create_tables_t11` (`t1` timestamp NOT NULL, `tsid` uint64 NOT NULL, `c1` int, PRIMARY KEY(t1,tsid), TIMESTAMP KEY(t1)) ENGINE=Analytic WITH(arena_block_size='2097152', compaction_strategy='default', compression='ZSTD', enable_ttl='true', num_rows_per_row_group='8192', segment_duration='', storage_format='COLUMNAR', ttl='7d', update_mode='OVERWRITE', write_buffer_size='33554432')")), + + +drop table `05_create_tables_t11`; + +affected_rows: 0 + DROP TABLE IF EXISTS `05_create_tables_t`; affected_rows: 0 @@ -223,3 +251,15 @@ DROP TABLE IF EXISTS `05_create_tables_t8`; affected_rows: 0 +DROP TABLE IF EXISTS `05_create_tables_t9`; + +affected_rows: 0 + +DROP TABLE IF EXISTS `05_create_tables_t10`; + +affected_rows: 0 + +DROP TABLE IF EXISTS `05_create_tables_t11`; + +affected_rows: 0 + diff --git a/tests/cases/local/05_ddl/create_tables.sql b/tests/cases/local/05_ddl/create_tables.sql index 1625fa1d1c..14ae6dad3b 100644 --- a/tests/cases/local/05_ddl/create_tables.sql +++ b/tests/cases/local/05_ddl/create_tables.sql @@ -69,6 +69,16 @@ CREATE TABLE `05_create_tables_t9`(c1 int, c2 bigint default 0, c3 uint32 defaul show create table `05_create_tables_t9`; drop table `05_create_tables_t9`; +-- Explicit primary key with tsid +CREATE TABLE `05_create_tables_t10`(c1 int, t1 timestamp NOT NULL TIMESTAMP KEY, PRIMARY KEY(tsid, t1)) ENGINE = Analytic; +show create table `05_create_tables_t10`; +drop table `05_create_tables_t10`; + +-- Explicit primary key with tsid +CREATE TABLE `05_create_tables_t11`(c1 int, t1 timestamp NOT NULL TIMESTAMP KEY, PRIMARY KEY(t1, tsid)) ENGINE = Analytic; +show create table `05_create_tables_t11`; +drop table `05_create_tables_t11`; + DROP TABLE IF EXISTS `05_create_tables_t`; DROP TABLE IF EXISTS `05_create_tables_t2`; DROP TABLE IF EXISTS `05_create_tables_t3`; @@ -77,3 +87,6 @@ DROP TABLE IF EXISTS `05_create_tables_t5`; DROP TABLE IF EXISTS `05_create_tables_t6`; DROP TABLE IF EXISTS `05_create_tables_t7`; DROP TABLE IF EXISTS `05_create_tables_t8`; +DROP TABLE IF EXISTS `05_create_tables_t9`; +DROP TABLE IF EXISTS `05_create_tables_t10`; +DROP TABLE IF EXISTS `05_create_tables_t11`; diff --git a/tests/cases/local/06_show/show_create_table.result b/tests/cases/local/06_show/show_create_table.result index 2fe5f481e1..b5f0bf2d80 100644 --- a/tests/cases/local/06_show/show_create_table.result +++ b/tests/cases/local/06_show/show_create_table.result @@ -17,7 +17,7 @@ affected_rows: 0 SHOW CREATE TABLE `06_show_a`; Table,Create Table, -String(StringBytes(b"06_show_a")),String(StringBytes(b"CREATE TABLE `06_show_a` (`a` bigint, `b` int DEFAULT 3, `c` string DEFAULT 'x', `d` smallint, `t` timestamp NOT NULL, `tsid` uint64 NOT NULL, PRIMARY KEY(t,tsid), TIMESTAMP KEY(t)) ENGINE=Analytic WITH(arena_block_size='2097152', compaction_strategy='default', compression='ZSTD', enable_ttl='true', num_rows_per_row_group='8192', segment_duration='', storage_format='COLUMNAR', ttl='7d', update_mode='OVERWRITE', write_buffer_size='33554432')")), +String(StringBytes(b"06_show_a")),String(StringBytes(b"CREATE TABLE `06_show_a` (`tsid` uint64 NOT NULL, `t` timestamp NOT NULL, `a` bigint, `b` int DEFAULT 3, `c` string DEFAULT 'x', `d` smallint, PRIMARY KEY(tsid,t), TIMESTAMP KEY(t)) ENGINE=Analytic WITH(arena_block_size='2097152', compaction_strategy='default', compression='ZSTD', enable_ttl='true', num_rows_per_row_group='8192', segment_duration='', storage_format='COLUMNAR', ttl='7d', update_mode='OVERWRITE', write_buffer_size='33554432')")), CREATE TABLE `06_show_b` (a bigint, b int null default null, c string, d smallint null, t timestamp NOT NULL, TIMESTAMP KEY(t)) ENGINE = Analytic; @@ -27,7 +27,7 @@ affected_rows: 0 SHOW CREATE TABLE `06_show_b`; Table,Create Table, -String(StringBytes(b"06_show_b")),String(StringBytes(b"CREATE TABLE `06_show_b` (`a` bigint, `b` int DEFAULT NULL, `c` string, `d` smallint, `t` timestamp NOT NULL, `tsid` uint64 NOT NULL, PRIMARY KEY(t,tsid), TIMESTAMP KEY(t)) ENGINE=Analytic WITH(arena_block_size='2097152', compaction_strategy='default', compression='ZSTD', enable_ttl='true', num_rows_per_row_group='8192', segment_duration='', storage_format='COLUMNAR', ttl='7d', update_mode='OVERWRITE', write_buffer_size='33554432')")), +String(StringBytes(b"06_show_b")),String(StringBytes(b"CREATE TABLE `06_show_b` (`tsid` uint64 NOT NULL, `t` timestamp NOT NULL, `a` bigint, `b` int DEFAULT NULL, `c` string, `d` smallint, PRIMARY KEY(tsid,t), TIMESTAMP KEY(t)) ENGINE=Analytic WITH(arena_block_size='2097152', compaction_strategy='default', compression='ZSTD', enable_ttl='true', num_rows_per_row_group='8192', segment_duration='', storage_format='COLUMNAR', ttl='7d', update_mode='OVERWRITE', write_buffer_size='33554432')")), CREATE TABLE `06_show_c` (a int, t timestamp NOT NULL, TIMESTAMP KEY(t)) ENGINE = Analytic; @@ -37,7 +37,7 @@ affected_rows: 0 SHOW CREATE TABLE `06_show_c`; Table,Create Table, -String(StringBytes(b"06_show_c")),String(StringBytes(b"CREATE TABLE `06_show_c` (`a` int, `t` timestamp NOT NULL, `tsid` uint64 NOT NULL, PRIMARY KEY(t,tsid), TIMESTAMP KEY(t)) ENGINE=Analytic WITH(arena_block_size='2097152', compaction_strategy='default', compression='ZSTD', enable_ttl='true', num_rows_per_row_group='8192', segment_duration='', storage_format='COLUMNAR', ttl='7d', update_mode='OVERWRITE', write_buffer_size='33554432')")), +String(StringBytes(b"06_show_c")),String(StringBytes(b"CREATE TABLE `06_show_c` (`tsid` uint64 NOT NULL, `t` timestamp NOT NULL, `a` int, PRIMARY KEY(tsid,t), TIMESTAMP KEY(t)) ENGINE=Analytic WITH(arena_block_size='2097152', compaction_strategy='default', compression='ZSTD', enable_ttl='true', num_rows_per_row_group='8192', segment_duration='', storage_format='COLUMNAR', ttl='7d', update_mode='OVERWRITE', write_buffer_size='33554432')")), DROP TABLE `06_show_a`; diff --git a/tests/cases/local/basic.result b/tests/cases/local/basic.result index 52a3642859..b21a1455fa 100644 --- a/tests/cases/local/basic.result +++ b/tests/cases/local/basic.result @@ -19,8 +19,8 @@ affected_rows: 1 SELECT * FROM demo; -name,value,t,tsid, -String(StringBytes(b"ceresdb")),Double(100.0),Timestamp(Timestamp(1651737067000)),Int64(102432447525557625), +tsid,t,name,value, +Int64(-6317898613073581291),Timestamp(Timestamp(1651737067000)),String(StringBytes(b"ceresdb")),Double(100.0), INSERT INTO demo (t, name, value) @@ -30,9 +30,9 @@ affected_rows: 1 SELECT * FROM demo; -name,value,t,tsid, -String(StringBytes(b"ceresdb")),Double(100.0),Timestamp(Timestamp(1651737067000)),Int64(102432447525557625), -String(StringBytes(b"ceresdb")),Double(100.0),Timestamp(Timestamp(1651737067001)),Int64(102432447525557625), +tsid,t,name,value, +Int64(-6317898613073581291),Timestamp(Timestamp(1651737067000)),String(StringBytes(b"ceresdb")),Double(100.0), +Int64(-6317898613073581291),Timestamp(Timestamp(1651737067001)),String(StringBytes(b"ceresdb")),Double(100.0), DROP TABLE IF EXISTS `demo`;