Fixing issues with PostgreSQL#3289
Conversation
Greptile SummaryThis PR fixes several PostgreSQL compatibility issues by replacing MySQL-style backtick quoting with dialect-aware identifier escaping, correcting the inverted
Confidence Score: 3/5Safe to merge for PostgreSQL users; SQLite schema migrations will silently replace all column values with the column name string until the single-quote escaping is corrected. The PostgreSQL and MySQL fixes are solid and address real failures. However, the SQLite EscapeColumnName implementation returns single-quoted strings which SQL treats as literals not identifiers. Every AlterTable schema migration on SQLite will silently overwrite all row data with the column name strings themselves — a data-destructive regression for anyone running TShock on SQLite whose schema needs to evolve. TShockAPI/DB/Queries/SqliteQueryBuilder.cs — the new EscapeColumnName override needs double-quote or backtick quoting, not single-quote quoting. Important Files Changed
Flowchart%%{init: {'theme': 'neutral'}}%%
flowchart TD
QB[GenericQueryBuilder] -->|virtual| ECN[EscapeColumnName]
ECN -->|override| MYSQL["MysqlQueryBuilder\n` backtick `"]
ECN -->|override| PG["PostgresQueryBuilder\nlowercase double-quote"]
ECN -->|override| SQLITE["SqliteQueryBuilder\nsingle-quote string literal"]
QB -->|uses ECN| ALT[AlterTable\nINSERT INTO t cols SELECT cols FROM tmp]
PG -->|also used in| CT[CreateTable\ncolumn defs + UNIQUE list]
BW[BuildWhere\nfixed inverted ternary] -->|emits| WHERE["WHERE col = val AND ..."]
BW -->|used by| DQ[DeleteRow / UpdateValue / ReadColumn]
Reviews (1): Last reviewed commit: "Fixing issues with PostgreSQL" | Re-trigger Greptile |
| } | ||
|
|
||
| /// <inheritdoc /> | ||
| protected override string EscapeColumnName(string column) => $"\'{column}\'"; |
There was a problem hiding this comment.
Single-quoted column names corrupt data during schema migration
In SQL, single quotes denote string literals, not identifiers. When AlterTable generates its copy query it reuses the column list in both positions: INSERT INTO 'tablename' ('col1', 'col2') SELECT 'col1', 'col2' FROM 'tmpTableName'. SQLite resolves 'col1' in the SELECT expression as a string constant, so every row in the migrated table ends up with the column name as its value instead of the actual data. The identifier-escaping character for SQLite is " (double-quote, per SQL standard and the SQLite docs) or backtick — single quotes are not valid here.
| protected override string EscapeColumnName(string column) => $"\'{column}\'"; | |
| /// <inheritdoc /> | |
| protected override string EscapeColumnName(string column) => $"\"{column}\""; |
| SqlType.Mysql => /*lang=mysql*/"; SELECT LAST_INSERT_ID();", | ||
| SqlType.Sqlite => /*lang=sqlite*/"; SELECT last_insert_rowid();", | ||
| SqlType.Postgres => /*lang=postgresql*/"RETURNING \"Identifier\";", | ||
| SqlType.Postgres => /*lang=postgresql*/" RETURNING TicketNumber;", |
There was a problem hiding this comment.
The
RETURNING clause should quote TicketNumber consistently with how PostgresQueryBuilder.EscapeColumnName stores the column (lowercased, double-quoted). While PostgreSQL folds unquoted TicketNumber to ticketnumber at runtime and the match succeeds today, using the same quoting convention eliminates the silent dependency on case-folding.
| SqlType.Postgres => /*lang=postgresql*/" RETURNING TicketNumber;", | |
| SqlType.Postgres => /*lang=postgresql*/" RETURNING \"ticketnumber\";", |
Summary
Fixes several PostgreSQL compatibility issues in TShock database code.
This PR updates SQL generation and direct queries so PostgreSQL no longer receives MySQL-style backtick-quoted identifiers. It fixes region creation and region group updates on PostgreSQL by escaping the
Groupscolumn according to the active SQL backend.It also fixes PostgreSQL ban insertion by returning
TicketNumberinstead of"Identifier", and improves the legacyBanstable lookup by checking the current schema and using a case-insensitive table name match.The generic query builder now supports dialect-specific column escaping, uses case-insensitive column matching during table alteration, and fixes
BuildWhereso generated WHERE clauses are emitted correctly.Changelog
Groupscolumn.Banstable detection.Testing
Tested against a PostgreSQL-backed TShock server by creating regions with
/region define. The previous PostgreSQL syntax error near backticks no longer occurs.