Skip to content

Commit fe62c6c

Browse files
committed
- Support multiple column's check constraints
- Standardize code
1 parent ae8ee26 commit fe62c6c

5 files changed

Lines changed: 69 additions & 47 deletions

File tree

README.md

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -78,24 +78,25 @@ bool sql3column_is_primarykey (sql3column *column);
7878
bool sql3column_is_autoincrement (sql3column *column);
7979
bool sql3column_is_notnull (sql3column *column);
8080
bool sql3column_is_unique (sql3column *column);
81-
sql3string *sql3column_pk_constraint_name (sql3column* column);
81+
sql3string *sql3column_pk_constraint_name (sql3column *column);
8282
sql3order_clause sql3column_pk_order (sql3column *column);
8383
sql3conflict_clause sql3column_pk_conflictclause (sql3column *column);
84-
sql3string *sql3column_notnull_constraint_name (sql3column* column);
84+
sql3string *sql3column_notnull_constraint_name (sql3column *column);
8585
sql3conflict_clause sql3column_notnull_conflictclause (sql3column *column);
86-
sql3string *sql3column_unique_constraint_name (sql3column* column);
86+
sql3string *sql3column_unique_constraint_name (sql3column *column);
8787
sql3conflict_clause sql3column_unique_conflictclause (sql3column *column);
88-
sql3string *sql3column_check_constraint_name (sql3column* column);
89-
sql3string *sql3column_check_expr (sql3column *column);
90-
sql3string *sql3column_default_constraint_name (sql3column* column);
88+
size_t sql3column_num_check_constraints (sql3column *column);
89+
sql3string *sql3column_check_constraint_name (sql3column *column, size_t index);
90+
sql3string *sql3column_check_expr (sql3column *column, size_t index);
91+
sql3string *sql3column_default_constraint_name (sql3column *column);
9192
sql3string *sql3column_default_expr (sql3column *column);
92-
sql3string *sql3column_collate_constraint_name (sql3column* column);
93+
sql3string *sql3column_collate_constraint_name (sql3column *column);
9394
sql3string *sql3column_collate_name (sql3column *column);
94-
sql3string *sql3column_foreignkey_constraint_name (sql3column* column);
95+
sql3string *sql3column_foreignkey_constraint_name (sql3column *column);
9596
sql3foreignkey *sql3column_foreignkey_clause (sql3column *column);
96-
sql3string *sql3column_generated_constraint_name (sql3column* column);
97-
sql3string *sql3column_generated_expr (sql3column* column);
98-
sql3gen_type sql3column_generated_type (sql3column* column);
97+
sql3string *sql3column_generated_constraint_name (sql3column *column);
98+
sql3string *sql3column_generated_expr (sql3column *column);
99+
sql3gen_type sql3column_generated_type (sql3column *column);
99100
100101
// Foreign key
101102
sql3string *sql3foreignkey_table (sql3foreignkey *fk);

debug/main.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -55,12 +55,13 @@ int main (void) {
5555
, test -- test 123\n\
5656
INTEGER, UNIQUE (flags /* Hello World*/, test) -- This is another table comment\n\
5757
);");
58-
test_case("CREATE TABLE Sales(Price INT, Qty INT, Total INT GENERATED ALWAYS AS (Price*Qty) VIRTUAL, Item TEXT)");
59-
test_case("CREATE TABLE Constraints (\
58+
test_case("CREATE TABLE Sales(Price INT, Qty INT, Total INT GENERATED ALWAYS AS (Price*Qty) VIRTUAL, Item TEXT);");
59+
test_case("CREATE TABLE Constraints(\
6060
PK INTEGER CONSTRAINT 'PrimaryKey' PRIMARY KEY CONSTRAINT 'NotNull' NOT NULL CONSTRAINT 'Unique' UNIQUE\
6161
CONSTRAINT 'Check' CHECK (PK>0) CONSTRAINT 'Default' DEFAULT 2 CONSTRAINT 'Collate' COLLATE NOCASE,\
6262
FK INTEGER CONSTRAINT 'ForeignKey' REFERENCES ForeignTable (Id),\
63-
GEN INTEGER CONSTRAINT 'Generated' AS (abs(PK)))");
63+
GEN INTEGER CONSTRAINT 'Generated' AS (abs(PK)));");
64+
test_case("CREATE TABLE ColumnChecks(Num INT CONSTRAINT 'GT' CHECK (Num>0) CONSTRAINT 'LT' CHECK (Num<10) CONSTRAINT 'NE' CHECK(Num<>5));");
6465

6566
// https://www.sqlite.org/lang_altertable.html
6667
test_case("ALTER TABLE foo RENAME TO bar");

debug/sql3parse_debug.c

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -168,13 +168,17 @@ static void sql3column_dump (sql3column *column) {
168168
if (clause != SQL3CONFLICT_NONE)
169169
printf("Unique Conflict Cause: %s\n", sql3conflict_clause_str(clause));
170170

171-
// check constraint name
172-
ptr = sql3column_check_constraint_name(column);
173-
sql3string_dump(ptr, "Check Constraint Name");
174-
175-
// check expr
176-
ptr = sql3column_check_expr(column);
177-
sql3string_dump(ptr, "Check Expression");
171+
// check constraints
172+
size_t num_check_constraints = sql3column_num_check_constraints(column);
173+
for (size_t i = 0; i < num_check_constraints; ++i) {
174+
// check constraint name
175+
ptr = sql3column_check_constraint_name(column, i);
176+
sql3string_dump(ptr, "Check Constraint Name");
177+
178+
// check expr
179+
ptr = sql3column_check_expr(column, i);
180+
sql3string_dump(ptr, "Check Expression");
181+
}
178182

179183
// default constraint name
180184
ptr = sql3column_default_constraint_name(column);

sql3parse_table.c

Lines changed: 30 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,8 @@ struct sql3column {
7474
sql3conflict_clause notnull_conflictclause; // not null conflit clause
7575
sql3string unique_constraint_name; // unique constraint name (can be NULL)
7676
sql3conflict_clause unique_conflictclause; // unique conflit clause
77-
sql3checkconstraint check_constraint; // check constraint
77+
size_t num_check_constraints; // number of check constraints
78+
sql3checkconstraint *check_constraints; // array of check constraints (can be NULL)
7879
sql3string default_constraint_name; // default constraint name (can be NULL)
7980
sql3string default_expr; // default expression (can be NULL)
8081
sql3string collate_constraint_name; // collate constraint name (can be NULL)
@@ -963,9 +964,13 @@ static sql3error_code sql3parse_column_constraints (sql3state *state, sql3column
963964
} break;
964965

965966
case TOK_CHECK: {
966-
// TODO Support multiple
967-
column->check_constraint.name = constraint_name;
968-
column->check_constraint.expr = sql3parse_expression(state);
967+
// add check constraint to check constraints array
968+
++column->num_check_constraints;
969+
column->check_constraints = SQL3REALLOC(column->check_constraints, sizeof(sql3checkconstraint) * column->num_check_constraints);
970+
if (!column->check_constraints) return SQL3ERROR_MEMORY;
971+
sql3checkconstraint *ptr = &column->check_constraints[column->num_check_constraints-1];
972+
ptr->name = constraint_name;
973+
ptr->expr = sql3parse_expression(state);
969974
} break;
970975

971976
case TOK_DEFAULT: {
@@ -1416,6 +1421,9 @@ void sql3table_free (sql3table *table) {
14161421
// free columns
14171422
for (size_t i=0; i<table->num_columns; ++i) {
14181423
sql3column *column = table->columns[i];
1424+
if (column->check_constraints) {
1425+
SQL3FREE(column->check_constraints);
1426+
}
14191427
if (column->foreignkey_clause) {
14201428
if (column->foreignkey_clause->column_name) SQL3FREE(column->foreignkey_clause->column_name);
14211429
SQL3FREE(column->foreignkey_clause);
@@ -1536,7 +1544,7 @@ bool sql3column_is_unique (sql3column *column) {
15361544
return column->is_unique;
15371545
}
15381546

1539-
sql3string* sql3column_pk_constraint_name (sql3column* column) {
1547+
sql3string *sql3column_pk_constraint_name (sql3column *column) {
15401548
CHECK_STR(column->pk_constraint_name);
15411549
return &column->pk_constraint_name;
15421550
}
@@ -1558,7 +1566,7 @@ sql3conflict_clause sql3column_notnull_conflictclause (sql3column *column) {
15581566
return column->notnull_conflictclause;
15591567
}
15601568

1561-
sql3string* sql3column_unique_constraint_name (sql3column* column) {
1569+
sql3string *sql3column_unique_constraint_name (sql3column *column) {
15621570
CHECK_STR(column->unique_constraint_name);
15631571
return &column->unique_constraint_name;
15641572
}
@@ -1567,17 +1575,24 @@ sql3conflict_clause sql3column_unique_conflictclause (sql3column *column) {
15671575
return column->unique_conflictclause;
15681576
}
15691577

1570-
sql3string* sql3column_check_constraint_name (sql3column* column) {
1571-
CHECK_STR(column->check_constraint.name);
1572-
return &column->check_constraint.name;
1578+
size_t sql3column_num_check_constraints (sql3column *column)
1579+
{
1580+
return column->num_check_constraints;
1581+
}
1582+
1583+
sql3string *sql3column_check_constraint_name (sql3column *column, size_t index) {
1584+
CHECK_IDX(index, column->num_check_constraints);
1585+
CHECK_STR(column->check_constraints[index].name);
1586+
return &(column->check_constraints[index].name);
15731587
}
15741588

1575-
sql3string *sql3column_check_expr (sql3column *column) {
1576-
CHECK_STR(column->check_constraint.expr);
1577-
return &column->check_constraint.expr;
1589+
sql3string *sql3column_check_expr (sql3column *column, size_t index) {
1590+
CHECK_IDX(index, column->num_check_constraints);
1591+
CHECK_STR(column->check_constraints[index].expr);
1592+
return &(column->check_constraints[index].expr);
15781593
}
15791594

1580-
sql3string* sql3column_default_constraint_name (sql3column* column) {
1595+
sql3string *sql3column_default_constraint_name (sql3column *column) {
15811596
CHECK_STR(column->default_constraint_name);
15821597
return &column->default_constraint_name;
15831598
}
@@ -1611,12 +1626,12 @@ sql3string *sql3column_generated_constraint_name (sql3column *column) {
16111626
return &column->generated_constraint_name;
16121627
}
16131628

1614-
sql3string* sql3column_generated_expr (sql3column* column) {
1629+
sql3string *sql3column_generated_expr (sql3column *column) {
16151630
CHECK_STR(column->generated_expr);
16161631
return &column->generated_expr;
16171632
}
16181633

1619-
sql3gen_type sql3column_generated_type (sql3column* column) {
1634+
sql3gen_type sql3column_generated_type (sql3column *column) {
16201635
return column->generated_type;
16211636
}
16221637

sql3parse_table.h

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -145,24 +145,25 @@ bool sql3column_is_primarykey (sql3column *column);
145145
bool sql3column_is_autoincrement (sql3column *column);
146146
bool sql3column_is_notnull (sql3column *column);
147147
bool sql3column_is_unique (sql3column *column);
148-
sql3string* sql3column_pk_constraint_name (sql3column* column);
148+
sql3string *sql3column_pk_constraint_name (sql3column *column);
149149
sql3order_clause sql3column_pk_order (sql3column *column);
150150
sql3conflict_clause sql3column_pk_conflictclause (sql3column *column);
151-
sql3string* sql3column_notnull_constraint_name (sql3column* column);
151+
sql3string *sql3column_notnull_constraint_name (sql3column *column);
152152
sql3conflict_clause sql3column_notnull_conflictclause (sql3column *column);
153-
sql3string* sql3column_unique_constraint_name (sql3column* column);
153+
sql3string *sql3column_unique_constraint_name (sql3column *column);
154154
sql3conflict_clause sql3column_unique_conflictclause (sql3column *column);
155-
sql3string* sql3column_check_constraint_name (sql3column* column);
156-
sql3string *sql3column_check_expr (sql3column *column);
157-
sql3string* sql3column_default_constraint_name (sql3column* column);
155+
size_t sql3column_num_check_constraints (sql3column *column);
156+
sql3string *sql3column_check_constraint_name (sql3column *column, size_t index);
157+
sql3string *sql3column_check_expr (sql3column *column, size_t index);
158+
sql3string *sql3column_default_constraint_name (sql3column *column);
158159
sql3string *sql3column_default_expr (sql3column *column);
159-
sql3string* sql3column_collate_constraint_name (sql3column* column);
160+
sql3string *sql3column_collate_constraint_name (sql3column *column);
160161
sql3string *sql3column_collate_name (sql3column *column);
161-
sql3string* sql3column_foreignkey_constraint_name (sql3column* column);
162+
sql3string *sql3column_foreignkey_constraint_name (sql3column *column);
162163
sql3foreignkey *sql3column_foreignkey_clause (sql3column *column);
163-
sql3string* sql3column_generated_constraint_name (sql3column* column);
164-
sql3string* sql3column_generated_expr (sql3column* column);
165-
sql3gen_type sql3column_generated_type (sql3column* column);
164+
sql3string *sql3column_generated_constraint_name (sql3column *column);
165+
sql3string *sql3column_generated_expr (sql3column *column);
166+
sql3gen_type sql3column_generated_type (sql3column *column);
166167

167168
// Foreign Key
168169
sql3string *sql3foreignkey_table (sql3foreignkey *fk);

0 commit comments

Comments
 (0)