Skip to content

fix(datagrid): let a SQLite column declared with no type carry a label and a search - #3022

Merged
datlechin merged 2 commits into
mainfrom
fix/sqlite-untyped-column-label
Sep 20, 2026
Merged

datlechin merged 2 commits into
mainfrom
fix/sqlite-untyped-column-label

Conversation

@datlechin

Copy link
Copy Markdown
Member

Found while investigating #2996.

#3009 changed the same file and has since merged, so this is rebased onto it and stands alone.

The defect

create table t(a, b) is legal SQLite and common in hand-written databases. Measured on SQLite 3.54.0:

sqlite> CREATE TABLE marchi("marchio", "nome");
sqlite> SELECT name, '[' || type || ']', typeof(type), length(type) FROM pragma_table_xinfo('marchi');
marchio|[]|text|0
nome|[]|text|0

The declared type comes back as a zero-length string, not null, so the column is kept and dataType reaches the app as "". ColumnTypeClassifier falls through every lookup to its .text fallback, giving .text(rawType: ""), and then:

guard case .text = type, let base = Self.baseTypeName(of: type.rawType) else { return false }

baseTypeName returns nil for an empty name, so supportsPatternMatch is false. That has two consequences in the foreign key picker, and neither is reported:

  • ForeignKeyLabelColumn.resolve filters the column out of its candidates, so a table whose columns are all untyped offers no label at all and the picker lists bare keys.
  • Choosing one by hand does not help, because ForeignKeyLookupQuery.searchFilters gates the predicate on the same property, so the search silently matches nothing.

Repro, measured: CREATE TABLE marchi("marchio", "nome"); CREATE TABLE alimenti(id INTEGER PRIMARY KEY, marchio, FOREIGN KEY(marchio) REFERENCES marchi(marchio)); Open the picker on alimenti.marchio and it lists BRD, MUL with nothing beside them, though nome holds Barilla and Mulino Bianco.

Why the closed list was right and still is

The list is deliberately closed. ColumnTypeClassifier files uuid, inet and everything else it does not recognise under .text, and LIKE against a uuid, an enum or an array is an error on PostgreSQL rather than an empty result, so a name that is not a known character type carries no predicate.

An empty declared type is not a gap in that list. It is a different answer, and only a dynamically typed engine gives it: every strict engine always names a type, and SQLite is the one that does not. LIKE is defined on every column there, measured on the same build:

sqlite> SELECT marchio, nome FROM marchi WHERE nome LIKE '%Barilla%';
BRD|Barilla

So the fix is one branch, not a new entry in the list: a column whose declared type is present and empty takes a predicate.

What it deliberately does not do

A missing rawType stays untouched. .text(rawType: nil) is built by several of the app's own conversions (JsonRowConverter, InClauseConverter, MultiRowEditState), and that is the app having no type information, not an engine reporting a column declared without one. Reading the two the same way would hand a pattern predicate to a column nobody has typed, on any engine. declaresNoType is the distinction and it is tested in both directions.

Verified

Step Result
verify.sh generate PASS
verify.sh test (4 suites) PASS
verify.sh lint (2 files) 0 violations

ForeignKeyLookupColumnTests is new and pins the whole predicate, not just the new branch: the character types still match, the guessed ones still do not, a non-text type still does not, an empty declared type now does, a missing one still does not, and the reporter's all-untyped table now resolves nome as its label.

@datlechin
datlechin merged commit b6b9e30 into main Sep 20, 2026
4 of 5 checks passed
@datlechin
datlechin deleted the fix/sqlite-untyped-column-label branch September 20, 2026 15:15
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.

1 participant