Skip to content

fix(sqlite): preserve NOT NULL from schema when explain loses it through ORDER BY#4222

Closed
barry3406 wants to merge 1 commit intolaunchbadge:mainfrom
barry3406:fix/sqlite-nullable-order-by
Closed

fix(sqlite): preserve NOT NULL from schema when explain loses it through ORDER BY#4222
barry3406 wants to merge 1 commit intolaunchbadge:mainfrom
barry3406:fix/sqlite-nullable-order-by

Conversation

@barry3406
Copy link
Copy Markdown
Contributor

Fixes #4147

When a query includes ORDER BY, SQLite routes data through an ephemeral sorter table. This causes two problems for nullability inference:

  1. The EXPLAIN-based analysis loses NOT NULL constraints as data passes through the ephemeral table
  2. sqlite3_column_table_name() returns NULL for columns from ephemeral tables, so the schema-based column_nullable() fallback also returns None

Before:

// exp_nullable = Some(true) (explain lost NOT NULL through sorter)
// col_nullable = None (origin unknown for ephemeral column)
nullable.push(exp_nullable.or(col_nullable));
// Result: Some(true) — incorrectly says nullable

The macro then generates Option<String> instead of String, causing a compile error.

After:
If the schema definitively says NOT NULL (col_nullable = Some(false)), that takes priority over explain. The schema is the source of truth for column constraints.

// col_nullable says NOT NULL → trust it
(Some(false), _) => Some(false)

This fixes the case where query_as! considers TEXT NOT NULL as nullable when ORDER BY is present.

When a query uses ORDER BY, SQLite routes data through an ephemeral
sorter table. The explain-based nullability analysis can lose NOT NULL
constraints through this indirection, and sqlite3_column_table_name()
returns NULL for ephemeral columns so the schema lookup also fails.

Previously, the explain result took priority: exp_nullable.or(col_nullable).
This meant a false "nullable" from explain would override the schema.

Now, if the schema definitively says NOT NULL (col_nullable = Some(false)),
that takes priority regardless of what explain inferred. The schema is
the source of truth for column constraints.

Fixes launchbadge#4147
@barry3406
Copy link
Copy Markdown
Contributor Author

Closing this — my fix was too aggressive and breaks LEFT JOIN / UNION nullability inference. The real issue is in the explain analyzer losing NOT NULL through ORDER BY + LIMIT ephemeral tables. Need to dig deeper into the EXPLAIN opcode tracking. Sorry for the noise.

@barry3406 barry3406 closed this Apr 9, 2026
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.

with sqlite query_as considers TEXT NOT NULL as nullable when there is an ORDER BY clause

1 participant