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); diff --git a/debug/main.c b/debug/main.c index f57b2fe..0e4c6bb 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 b134323..8db427a 100644 --- a/debug/sql3parse_debug.c +++ b/debug/sql3parse_debug.c @@ -190,6 +190,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 887ed13..ac5e276 100644 --- a/sql3parse_table.c +++ b/sql3parse_table.c @@ -84,6 +84,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 @@ -767,9 +768,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; @@ -1424,6 +1433,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; @@ -1541,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 9ad9393..5dfcb1a 100644 --- a/sql3parse_table.h +++ b/sql3parse_table.h @@ -127,6 +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); 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); @@ -153,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);