From 642bcccfac5037dfa6d62c660127752b9cff491c Mon Sep 17 00:00:00 2001 From: Markus Sauermann <6299227+Sauermann@users.noreply.github.com> Date: Sat, 7 Dec 2024 23:40:54 +0100 Subject: [PATCH] Add support for multi-column primary keys --- README.md | 4 ++-- doc_classes/SQLite.xml | 4 ++-- src/gdsqlite.cpp | 30 +++++++++++++++++++++++++----- 3 files changed, 29 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 90514a5..f261b6c 100644 --- a/README.md +++ b/README.md @@ -157,11 +157,11 @@ Additionally, a video tutorial by [Mitch McCollum (finepointcgi)](https://github - **"default"**: The default value of the column if not explicitly given. - **"primary_key"** *(default = false)*: Is this the primary key of this table? - Evidently, only a single column can be set as the primary key. + Multiple columns can be set as a primary key. - **"auto_increment"** *(default = false)*: Automatically increment this column when no explicit value is given. This auto-generated value will be one more (+1) than the largest value currently in use. - ***NOTE**: Auto-incrementing a column only works when this column is the primary key!* + ***NOTE**: Auto-incrementing a column only works when this column is the primary key and no other columns are primary keys!* - **"foreign_key"**: Enforce an "exist" relationship between tables by setting this variable to `foreign_table.foreign_column`. In other words, when adding an additional row, the column value should be an existing value as found in the column with name `foreign_column` of the table with name `foreign_table`. diff --git a/doc_classes/SQLite.xml b/doc_classes/SQLite.xml index 2a8fa98..580f9bc 100644 --- a/doc_classes/SQLite.xml +++ b/doc_classes/SQLite.xml @@ -91,9 +91,9 @@ * [i]Data types not found in this list throw an error and end up finalizing the current SQLite statement.[/i][br] ** [i]with the question mark being replaced by the maximum amount of characters[/i] [b]Optional fields[/b]: - [b]"not_null"[/b] [i](default = false)[/i]: Is the NULL value an invalid value for this column?[br]- [b]"unique"[/b] [i](default = false)[/i]: Does the column have a unique constraint?[br]- [b]"default"[/b]: The default value of the column if not explicitly given.[br]- [b]"primary_key"[/b] [i](default = false)[/i]: Is this the primary key of this table? - Evidently, only a single column can be set as the primary key. + Multiple columns can be set as a primary key. - [b]"auto_increment"[/b] [i](default = false)[/i]: Automatically increment this column when no explicit value is given. This auto-generated value will be one more (+1) than the largest value currently in use. - [i][b]NOTE[/b]: Auto-incrementing a column only works when this column is the primary key![/i] + [i][b]NOTE[/b]: Auto-incrementing a column only works when this column is the primary key and no other columns are primary keys![/i] - [b]"foreign_key"[/b]: Enforce an "exist" relationship between tables by setting this variable to [code]foreign_table.foreign_column[/code]. In other words, when adding an additional row, the column value should be an existing value as found in the column with name [code]foreign_column[/code] of the table with name [code]foreign_table[/code]. [i][b]NOTE[/b]: Availability of foreign keys has to be enabled by setting the [code]foreign_keys[/code]-variable to true BEFORE opening the database.[/i] [b]Example usage[/b]: diff --git a/src/gdsqlite.cpp b/src/gdsqlite.cpp index f408da8..8b4ad22 100644 --- a/src/gdsqlite.cpp +++ b/src/gdsqlite.cpp @@ -335,15 +335,23 @@ bool SQLite::create_table(const String &p_name, const Dictionary &p_table_dict) return false; } - String query_string, type_string, key_string; + String query_string, type_string, key_string, primary_string; String integer_datatype = "int"; /* Create SQL statement */ query_string = "CREATE TABLE IF NOT EXISTS " + p_name + " ("; key_string = ""; + primary_string = ""; Dictionary column_dict; Array columns = p_table_dict.keys(); int64_t number_of_columns = columns.size(); + int primary_key_columns = 0; + for (int64_t i = 0; i <= number_of_columns - 1; i++) { + column_dict = p_table_dict[columns[i]]; + if (column_dict.get("primary_key", false)) { + primary_key_columns++; + } + } for (int64_t i = 0; i <= number_of_columns - 1; i++) { column_dict = p_table_dict[columns[i]]; query_string += (const String &)columns[i] + String(" "); @@ -356,10 +364,18 @@ bool SQLite::create_table(const String &p_name, const Dictionary &p_table_dict) /* Primary key check */ if (column_dict.get("primary_key", false)) { - query_string += String(" PRIMARY KEY"); - /* Autoincrement check */ - if (column_dict.get("auto_increment", false)) { - query_string += String(" AUTOINCREMENT"); + if (primary_key_columns == 1) { + query_string += String(" PRIMARY KEY"); + /* Autoincrement check */ + if (column_dict.get("auto_increment", false)) { + query_string += String(" AUTOINCREMENT"); + } + } else { + if (primary_string.is_empty()) { + primary_string = (const String &)columns[i]; + } else { + primary_string += String(", ") + (const String &)columns[i]; + } } } /* Not null check */ @@ -393,6 +409,10 @@ bool SQLite::create_table(const String &p_name, const Dictionary &p_table_dict) } } + if (primary_key_columns > 1) { + query_string += String(", PRIMARY KEY (") + primary_string + String(")"); + } + query_string += key_string + ");"; return query(query_string);