Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Creating a column affinity based on a string does not produce the correct affinity #1215

Closed
stefansaasen opened this issue Jun 7, 2023 · 1 comment · Fixed by #1218
Closed

Comments

@stefansaasen
Copy link
Contributor

E.g. take the example table definition from the TestHelper:

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

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 Ventura 13.4
  • How do do you integrate SQLite.swift in your project: Swift Package manager
@stefansaasen
Copy link
Contributor Author

Possible fix: #1218

nathanfallet added a commit that referenced this issue Feb 23, 2024
…-parsing

Fix column affinity parsing to match how SQLite determines affinity (Fix #1215)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
1 participant