-
-
Notifications
You must be signed in to change notification settings - Fork 1.6k
Description
E.g. take the example table definition from the TestHelper
:
SQLite.swift/Tests/SQLiteTests/TestHelpers.swift
Lines 22 to 31 in f1bee07
CREATE TABLE users ( | |
id INTEGER PRIMARY KEY, | |
email TEXT NOT NULL UNIQUE, | |
age INTEGER, | |
salary REAL, | |
admin BOOLEAN NOT NULL DEFAULT 0 CHECK (admin IN (0, 1)), | |
manager_id INTEGER, | |
created_at DATETIME, | |
FOREIGN KEY(manager_id) REFERENCES users(id) | |
) |
According to 3.1. Determination Of Column Affinity
the affinity of a column is based on the declared type. With the "parsing" following a set of five rules (see linked page).
So for the above table definition, the column affinity should be:
id
-> rule 1:INTEGER
✅email
-> rule 2:TEXT
✅age
-> rule 1:INTEGER
✅salary
-> rule 4:REAL
✅admin
-> rule 5:NUMERIC
❌manager_id
-> rule 1:INTEGER
✅created_at
-> rule 5:NUMERIC
❌
but the affinity is incorrect for the following columns: admin
and created_at
(TEXT
instead of NUMERIC
).
See
SQLite.swift/Tests/SQLiteTests/Schema/SchemaReaderTests.swift
Lines 17 to 57 in f1bee07
ColumnDefinition(name: "id", | |
primaryKey: .init(autoIncrement: false, onConflict: nil), | |
type: .INTEGER, | |
nullable: true, | |
defaultValue: .NULL, | |
references: nil), | |
ColumnDefinition(name: "email", | |
primaryKey: nil, | |
type: .TEXT, | |
nullable: false, | |
defaultValue: .NULL, | |
references: nil), | |
ColumnDefinition(name: "age", | |
primaryKey: nil, | |
type: .INTEGER, | |
nullable: true, | |
defaultValue: .NULL, | |
references: nil), | |
ColumnDefinition(name: "salary", | |
primaryKey: nil, | |
type: .REAL, | |
nullable: true, | |
defaultValue: .NULL, | |
references: nil), | |
ColumnDefinition(name: "admin", | |
primaryKey: nil, | |
type: .TEXT, | |
nullable: false, | |
defaultValue: .numericLiteral("0"), | |
references: nil), | |
ColumnDefinition(name: "manager_id", | |
primaryKey: nil, type: .INTEGER, | |
nullable: true, | |
defaultValue: .NULL, | |
references: .init(table: "users", column: "manager_id", primaryKey: "id", onUpdate: nil, onDelete: nil)), | |
ColumnDefinition(name: "created_at", | |
primaryKey: nil, | |
type: .TEXT, | |
nullable: true, | |
defaultValue: .NULL, | |
references: nil) |
A possible solution is to create the Affinity
and implement the 5 rules, e.g. like here: stefansaasen@fabbe8c
There is one important thing to consider here, the default affinity for declared types that are not covered is now NUMERIC
instead of TEXT
. E.g. with the gotcha mentioned here: https://www.sqlite.org/datatype3.html#determination_of_column_affinity
And the declared type of "STRING" has an affinity of NUMERIC, not TEXT
Should probably considered to be a breaking change.
P.S.: Happy to create a PR if the approach in the commit linked above is acceptable.
Build Information
- Include the SQLite.swift version: 0.14.1
- Mention Xcode and OS X versions affected: Xcode
14.3
and macOS Ventura13.4
- How do do you integrate SQLite.swift in your project: Swift Package manager