From d3c5fe53a5d2c2c6b8dc133fc16f242709254c09 Mon Sep 17 00:00:00 2001 From: Stephane Nolin Date: Fri, 9 Jan 2026 10:33:45 -0500 Subject: [PATCH 1/3] Add support for AUTOINCREMENT in a PRIMARY KEY table constraint --- debug/main.c | 1 + debug/sql3parse_debug.c | 5 +++++ sql3parse_table.c | 14 ++++++++++++++ sql3parse_table.h | 1 + 4 files changed, 21 insertions(+) diff --git a/debug/main.c b/debug/main.c index ffb4a85..689bdd0 100644 --- a/debug/main.c +++ b/debug/main.c @@ -35,6 +35,7 @@ int main (void) { test_case("CREATE TABLE ct (d INT DEFAULT ( (1+2) ), e TEXT DEFAULT '))')"); test_case("CREATE TABLE foo (col1 INTEGER PRIMARY KEY AUTOINCREMENT, col2 TEXT, col3 TEXT);"); + test_case("CREATE TABLE tcpkai (col INTEGER, PRIMARY KEY (col AUTOINCREMENT));"); test_case("CREATE TABLE t1(x INTEGER PRIMARY KEY, y);"); test_case("create table employee(first varchar(15),last varchar(20),age number(3),address varchar(30),city varchar(20),state varchar(20));"); test_case("CREATE TEMP TABLE IF NOT EXISTS main.foo /* This is the main table */ (col1 INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, col2 TEXT DEFAULT CURRENT_TIMESTAMP, col3 FLOAT(8.12), col4 BLOB COLLATE BINARY /* Use this column for storing pictures */, CONSTRAINT tbl1 UNIQUE (col1 COLLATE c1 ASC, col2 COLLATE c2 DESC)) WITHOUT ROWID; -- this is a line comment"); diff --git a/debug/sql3parse_debug.c b/debug/sql3parse_debug.c index 93831f4..aaaf779 100644 --- a/debug/sql3parse_debug.c +++ b/debug/sql3parse_debug.c @@ -174,6 +174,11 @@ static void sql3tableconstraint_dump (sql3tableconstraint *constraint) { sql3string *ptr = sql3table_constraint_name(constraint); sql3string_dump(ptr, "Constraint Name"); + if (type == SQL3TABLECONSTRAINT_PRIMARYKEY) { + // autoincrement flag + printf("Autoincrement: %d\n", sql3table_constraint_is_autoincrement(constraint)); + } + if ((type == SQL3TABLECONSTRAINT_PRIMARYKEY) || (type == SQL3TABLECONSTRAINT_UNIQUE)) { // indexed columns size_t num_idx = sql3table_constraint_num_idxcolumns(constraint); diff --git a/sql3parse_table.c b/sql3parse_table.c index 7b75ee8..dca2192 100644 --- a/sql3parse_table.c +++ b/sql3parse_table.c @@ -81,6 +81,7 @@ struct sql3tableconstraint { size_t num_indexed; // number of indexed columns sql3idxcolumn *indexed_columns; // array fo indexed columns sql3conflict_clause conflict_clause; // conflict clause + bool is_autoincrement; // autoincrement flag (only for for SQL3TABLECONSTRAINT_PRIMARYKEY and num_indexed == 1) }; // if type SQL3TABLECONSTRAINT_CHECK @@ -729,9 +730,17 @@ static sql3tableconstraint *sql3parse_table_constraint (sql3state *state) { constraint->indexed_columns[constraint->num_indexed-1] = column; token = sql3lexer_peek(state); + if (token == TOK_AUTOINCREMENT) { + sql3lexer_next(state); // consume TOK_AUTOINCREMENT + if (constraint->type != SQL3TABLECONSTRAINT_PRIMARYKEY) goto error; + constraint->is_autoincrement = true; + token = sql3lexer_peek(state); + } if (token == TOK_COMMA) sql3lexer_next(state); // consume TOK_COMMA } while (token == TOK_COMMA); + + if (constraint->is_autoincrement && (constraint->num_indexed != 1)) goto error; if (sql3lexer_next(state) != TOK_CLOSED_PARENTHESIS) goto error; if (sql3parse_optionalconflitclause(state, &constraint->conflict_clause) != SQL3ERROR_NONE) goto error; @@ -1388,6 +1397,11 @@ sql3constraint_type sql3table_constraint_type (sql3tableconstraint *tconstraint) return tconstraint->type; } +bool sql3table_constraint_is_autoincrement(sql3tableconstraint* tconstraint) { + if (tconstraint->type != SQL3TABLECONSTRAINT_PRIMARYKEY) return false; + return tconstraint->is_autoincrement; +} + size_t sql3table_constraint_num_idxcolumns (sql3tableconstraint *tconstraint) { if ((tconstraint->type != SQL3TABLECONSTRAINT_PRIMARYKEY) && (tconstraint->type != SQL3TABLECONSTRAINT_UNIQUE)) return 0; return tconstraint->num_indexed; diff --git a/sql3parse_table.h b/sql3parse_table.h index 741ade6..5504842 100644 --- a/sql3parse_table.h +++ b/sql3parse_table.h @@ -121,6 +121,7 @@ sql3string *sql3table_new_name (sql3table *table); // Table Constraint sql3string *sql3table_constraint_name (sql3tableconstraint *tconstraint); sql3constraint_type sql3table_constraint_type (sql3tableconstraint *tconstraint); +bool sql3table_constraint_is_autoincrement(sql3tableconstraint* tconstraint); size_t sql3table_constraint_num_idxcolumns (sql3tableconstraint *tconstraint); sql3idxcolumn *sql3table_constraint_get_idxcolumn (sql3tableconstraint *tconstraint, size_t index); sql3conflict_clause sql3table_constraint_conflict_clause (sql3tableconstraint *tconstraint); From 16606328a46182eaec121b960db706d218f04496 Mon Sep 17 00:00:00 2001 From: Stephane Nolin Date: Sun, 11 Jan 2026 14:38:15 -0500 Subject: [PATCH 2/3] Standardize code --- sql3parse_table.c | 6 +++--- sql3parse_table.h | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/sql3parse_table.c b/sql3parse_table.c index 153ecb0..ac5e276 100644 --- a/sql3parse_table.c +++ b/sql3parse_table.c @@ -1433,7 +1433,7 @@ sql3constraint_type sql3table_constraint_type (sql3tableconstraint *tconstraint) return tconstraint->type; } -bool sql3table_constraint_is_autoincrement(sql3tableconstraint* tconstraint) { +bool sql3table_constraint_is_autoincrement (sql3tableconstraint* tconstraint) { if (tconstraint->type != SQL3TABLECONSTRAINT_PRIMARYKEY) return false; return tconstraint->is_autoincrement; } @@ -1555,12 +1555,12 @@ sql3foreignkey *sql3column_foreignkey_clause (sql3column *column) { return column->foreignkey_clause; } -sql3string* sql3column_generated_expr(sql3column* column) { +sql3string* sql3column_generated_expr (sql3column* column) { CHECK_STR(column->generated_expr); return &column->generated_expr; } -sql3gen_type sql3column_generated_type(sql3column* column) { +sql3gen_type sql3column_generated_type (sql3column* column) { return column->generated_type; } diff --git a/sql3parse_table.h b/sql3parse_table.h index f3fb457..5dfcb1a 100644 --- a/sql3parse_table.h +++ b/sql3parse_table.h @@ -127,7 +127,7 @@ sql3string *sql3table_new_name (sql3table *table); // Table Constraint sql3string *sql3table_constraint_name (sql3tableconstraint *tconstraint); sql3constraint_type sql3table_constraint_type (sql3tableconstraint *tconstraint); -bool sql3table_constraint_is_autoincrement(sql3tableconstraint* tconstraint); +bool sql3table_constraint_is_autoincrement (sql3tableconstraint* tconstraint); size_t sql3table_constraint_num_idxcolumns (sql3tableconstraint *tconstraint); sql3idxcolumn *sql3table_constraint_get_idxcolumn (sql3tableconstraint *tconstraint, size_t index); sql3conflict_clause sql3table_constraint_conflict_clause (sql3tableconstraint *tconstraint); @@ -154,8 +154,8 @@ sql3string *sql3column_check_expr (sql3column *column); sql3string *sql3column_default_expr (sql3column *column); sql3string *sql3column_collate_name (sql3column *column); sql3foreignkey *sql3column_foreignkey_clause (sql3column *column); -sql3string* sql3column_generated_expr(sql3column* column); -sql3gen_type sql3column_generated_type(sql3column* column); +sql3string* sql3column_generated_expr (sql3column* column); +sql3gen_type sql3column_generated_type (sql3column* column); // Foreign Key sql3string *sql3foreignkey_table (sql3foreignkey *fk); From 1853b4c1b214dfa1d2c0d195fc4909b5ab7adae0 Mon Sep 17 00:00:00 2001 From: Stephane Nolin Date: Sun, 11 Jan 2026 14:38:31 -0500 Subject: [PATCH 3/3] Update README.md --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 3e7725b..a98089b 100644 --- a/README.md +++ b/README.md @@ -60,6 +60,7 @@ sql3string *sql3table_new_name (sql3table *table); // Table constraints sql3string *sql3table_constraint_name (sql3tableconstraint *tconstraint); sql3constraint_type sql3table_constraint_type (sql3tableconstraint *tconstraint); +bool sql3table_constraint_is_autoincrement (sql3tableconstraint* tconstraint); size_t sql3table_constraint_num_idxcolumns (sql3tableconstraint *tconstraint); sql3idxcolumn *sql3table_constraint_get_idxcolumn (sql3tableconstraint *tconstraint, size_t index); sql3conflict_clause sql3table_constraint_conflict_clause (sql3tableconstraint *tconstraint);