From 6d6fc91da345db8e75e619a919f5a0ea65f3ad26 Mon Sep 17 00:00:00 2001 From: Jussi Saurio Date: Thu, 25 Sep 2025 15:47:30 +0300 Subject: [PATCH 1/3] Disallow multiple primary keys in table definition --- core/schema.rs | 12 ++++++++++++ testing/create_table.test | 12 ++++++++++++ 2 files changed, 24 insertions(+) diff --git a/core/schema.rs b/core/schema.rs index 2f5ebfec6..ca16c689b 100644 --- a/core/schema.rs +++ b/core/schema.rs @@ -1038,6 +1038,12 @@ pub fn create_table( .. } = &c.constraint { + if !primary_key_columns.is_empty() { + crate::bail_parse_error!( + "table \"{}\" has more than one primary key", + tbl_name + ); + } if *auto_increment { has_autoincrement = true; } @@ -1126,6 +1132,12 @@ pub fn create_table( auto_increment, .. } => { + if !primary_key_columns.is_empty() { + crate::bail_parse_error!( + "table \"{}\" has more than one primary key", + tbl_name + ); + } primary_key = true; if auto_increment { has_autoincrement = true; diff --git a/testing/create_table.test b/testing/create_table.test index 5b8dd830c..f5fceba67 100755 --- a/testing/create_table.test +++ b/testing/create_table.test @@ -33,3 +33,15 @@ do_execsql_test_on_specific_db {:memory:} create_table_with_empty_string_name { insert into '' values(9); select * from ''; } {9} + +do_execsql_test_in_memory_any_error create_table_multiple_column_primary_keys { + CREATE TABLE t(a primary key, b primary key); +} + +do_execsql_test_in_memory_any_error create_table_column_and_table_primary_keys { + CREATE TABLE t(a primary key, b,c, primary key(b,c)); +} + +do_execsql_test_in_memory_any_error create_table_multiple_table_primary_keys { + CREATE TABLE t(a,b,c,d,primary key(a,b), primary key(c,d)); +} From 3170077952316835028833782045724ce0a1e9e4 Mon Sep 17 00:00:00 2001 From: Jussi Saurio Date: Thu, 25 Sep 2025 16:19:28 +0300 Subject: [PATCH 2/3] Fix incorrect test --- core/schema.rs | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/core/schema.rs b/core/schema.rs index ca16c689b..53cf99628 100644 --- a/core/schema.rs +++ b/core/schema.rs @@ -1999,13 +1999,12 @@ mod tests { } #[test] - pub fn test_column_is_rowid_alias_inline_composite_primary_key() -> Result<()> { + pub fn test_multiple_pk_forbidden() -> Result<()> { let sql = r#"CREATE TABLE t1 (a INTEGER PRIMARY KEY, b TEXT PRIMARY KEY);"#; - let table = BTreeTable::from_sql(sql, 0)?; - let column = table.get_column("a").unwrap().1; + let table = BTreeTable::from_sql(sql, 0); + let error = table.unwrap_err(); assert!( - !table.column_is_rowid_alias(column), - "column 'a´ shouldn't be a rowid alias because table has composite primary key" + matches!(error, LimboError::ParseError(e) if e.contains("table \"t1\" has more than one primary key")) ); Ok(()) } From 252da9254a40a1835926230a2d0f9880da2c1990 Mon Sep 17 00:00:00 2001 From: Jussi Saurio Date: Thu, 25 Sep 2025 16:20:25 +0300 Subject: [PATCH 3/3] fix another incorrect test --- core/schema.rs | 20 +++++--------------- 1 file changed, 5 insertions(+), 15 deletions(-) diff --git a/core/schema.rs b/core/schema.rs index 53cf99628..2c5c4e647 100644 --- a/core/schema.rs +++ b/core/schema.rs @@ -2040,22 +2040,12 @@ mod tests { } #[test] - pub fn test_primary_key_inline_multiple() -> Result<()> { + pub fn test_primary_key_inline_multiple_forbidden() -> Result<()> { let sql = r#"CREATE TABLE t1 (a INTEGER PRIMARY KEY, b TEXT PRIMARY KEY, c REAL);"#; - let table = BTreeTable::from_sql(sql, 0)?; - let column = table.get_column("a").unwrap().1; - assert!(column.primary_key, "column 'a' should be a primary key"); - let column = table.get_column("b").unwrap().1; - assert!(column.primary_key, "column 'b' shouldn be a primary key"); - let column = table.get_column("c").unwrap().1; - assert!(!column.primary_key, "column 'c' shouldn't be a primary key"); - assert_eq!( - vec![ - ("a".to_string(), SortOrder::Asc), - ("b".to_string(), SortOrder::Asc) - ], - table.primary_key_columns, - "primary key column names should be ['a', 'b']" + let table = BTreeTable::from_sql(sql, 0); + let error = table.unwrap_err(); + assert!( + matches!(error, LimboError::ParseError(e) if e.contains("table \"t1\" has more than one primary key")) ); Ok(()) }