Skip to content

fix(dapper)!: validate and quote schema and table names - #49

Merged
giammin merged 1 commit into
mainfrom
fix/22-validate-identifiers
Oct 22, 2026
Merged

giammin merged 1 commit into
mainfrom
fix/22-validate-identifiers

Conversation

@giammin

@giammin giammin commented Oct 22, 2026

Copy link
Copy Markdown
Owner

Summary

  • Validation at startup. SchemaName and TableName are validated by an internal per-provider IValidateOptions<DapperDataProtectionConfig> registered with ValidateOnStart(). Without a host, validation runs when UseDapperDataProtection() reads the options. The OptionsValidationException names the option, the value and the rule.
    • SQL Server: ^[A-Za-z_][A-Za-z0-9_]*, schema <= 128, table <= 112 characters (so that IX_{TableName}_FriendlyName fits in 128).
    • PostgreSQL: lowercase only, ^[a-z_][a-z0-9_]*, <= 63 characters.
  • Quoting. Every identifier is quoted ([...] / "...", closing quote escaped), including constraint and index names, so reserved words work. SQL Server passes the names as parameters in the existence checks, QUOTENAME and the duplicate-index error message.
  • Missing schema. InitializeDb() creates the schema when it is missing, inside the initialization lock added in fix: serialize InitializeDb across concurrent instances #47. Existence is checked first (SCHEMA_ID / pg_namespace), because PostgreSQL's CREATE SCHEMA IF NOT EXISTS requires the database CREATE privilege even when the schema exists.
  • README ("Schema and table names" section), AGENTS.md and XML docs updated.

Design note: PostgreSQL names must be lowercase

The issue proposed documenting that quoting makes PostgreSQL names case-sensitive. That is not enough. Earlier versions did not quote names, so DpKeys created the table dpkeys. With quoting, the same configuration would silently target a new, empty "DpKeys" table, and the existing keys would be ignored. Rejecting mixed-case names turns that into a startup error with a clear fix: use the lowercase form, which is the name of the existing table. Lowercase quoted and unquoted names are the same, so existing installations keep working.

Tests

  • Validator unit tests for both providers (invalid characters, empty or null names, trailing newline, non-ASCII, length limits).
  • Startup-validation wiring through IStartupValidator and UseDapperDataProtection().
  • Integration: missing schema created for both providers; PostgreSQL reserved-word schema name (order); end-to-end with a missing custom schema and a reserved-word table name for both providers.
  • Release build without warnings; 158/158 tests pass locally.

Closes #22

BREAKING CHANGE: names that do not match the new rules now fail at startup with an OptionsValidationException. SQL Server names containing characters other than letters, digits and underscores must be renamed. PostgreSQL names must be lowercase: replace a mixed-case name with its lowercase form, which is the name of the table created by earlier versions.

Validate DapperDataProtectionConfig.SchemaName and TableName at startup
(options validation with ValidateOnStart) with a per-provider validator:
SQL Server accepts letters, digits and underscores (schema <= 128, table
<= 112 characters); PostgreSQL accepts the same in lowercase only (<= 63).
Quote every identifier, pass names as parameters in the SQL Server
existence checks, and create the schema in InitializeDb when it is missing.

Closes #22

BREAKING CHANGE: names that do not match the new rules now fail at startup
with an OptionsValidationException. SQL Server names containing characters
other than letters, digits and underscores must be renamed. PostgreSQL
names must be lowercase: replace a mixed-case name with its lowercase form,
which is the name of the table created by earlier versions.
@giammin
giammin merged commit 791c6ce into main Oct 22, 2026
1 check passed
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.

Validate and quote schema/table names, and create a missing schema

1 participant