Skip to content

Conversation

@trueqbit
Copy link
Collaborator

@trueqbit trueqbit commented Nov 27, 2025

Improvements:

  • Objects mapped to tables with composite primary keys are now insertable with an ordinary insert statement: they get inserted with the values of the specified object except for default values.
    • This improvement contains a bug fix for insert statements into tables without rowid where providing values for primary key columns is required (and expected).

Other improvements:

  • Validate base table definition when calling make_table().
    • Specifically this ensures that only one primary key definition is specified.
    • It also means that we can get rid of a runtime error when serializing a get query statement.
  • Validate column definition with respect to auto-increment specifier on a column primary key and the field type.
    • Deprecated types other than 64-bit signed integers - it is clearly stated in the SQLite documentation that auto-increment is only valid for 64-bit signed integer columns and if they are an alias for the implicit rowid column. With SQLite it is a hard error if you try to use a type for a column other than INTEGER.
  • Finally return a 64-bit integer as the last inserted rowid.
    • The worst that can happen is a compiler warning or error depending on the compiler settings because of a narrowing conversion. Users should fix their code.

Fixes

  • Corrected some SQLite version test that enable version-dependent SQLite features.

The if-condition used for filtering primary key columns must be the same at run-time as at compile-time.
... to the mapped object type, avoiding hard to read error messages later.
Up until this commit, the functions were referred to as "composite PK functions", although this actually always meant "table PK functions", regardless of whether they were single or composite primary keys defined at the table level.
* Improved understanding through legibility.
For proper type safety `storage_t<>::insert()` needs to return an `sqlite3_int64` instead of an `int`.
This is the best way to correct the problem. Usually, compilers just accept narrowing type conversions, the nicest thing that can happen is a warning message, the worst is an error depending on compiler flags. The programmer has to handle the rest and it is the best thing to do anyway.
* Check column definition up front when making the column.
* Renamed internal traits.
* Removed unit test file `is_column_with_insertable_primary_key.cpp`. It became superfluous during the course of development in the past years. Column constraints are checked elsewhere already, and it is now only a duplicate of `is_primary_key_insertable.cpp`.
SQLite documentation clearly states that an auto-incrementable primary key column must be a 64-bit signed integer type.
@trueqbit trueqbit force-pushed the fix/insert-without-rowid branch from 337084c to 93a23fe Compare December 2, 2025 14:15
This approach keeps the previous way if all composite primary key columns have a default value, yet still enables inserting records if the table has composite primary key columns with only some or no default values.
* WITHOUT ROWID is only available since SQLite 3.8.2.
* FTS5: consider that it can be explicitly enabled with `SQLITE_ORM_ENABLE_FTS5`.
* Auxiliary virtual table columns are only available since SQLite 3.24.0.
* Hidden virtual table columns have no version attached.
@trueqbit trueqbit changed the title Fix insertion for tables without rowid Correcting ordinary insert statement for tables with composite primary keys Dec 4, 2025
@trueqbit trueqbit marked this pull request as ready for review December 4, 2025 19:33
@trueqbit trueqbit requested a review from fnc12 December 4, 2025 19:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

False NOT NULL constraint failure for table with true composite primary key

2 participants