3.0 KiB
3.0 KiB
SQLAlchemy Column Name Quoting Fix for PostgreSQL
Date: March 22, 2026
Issue: PostgreSQL case sensitivity with mapped_column parameter
Problem
SQLAlchemy's name= parameter generates unquoted column names by default, which PostgreSQL lowercases. When column definitions use uppercase CHECK constraints, they don't match the lowercased column names.
Example:
# Model definition
NM: Mapped[Union[int, None]] = mapped_column(
Integer,
name="NM", # Generates: CREATE TABLE ... ( "NM" INTEGER, ...)
nullable=True,
)
# SQL generated
CREATE TABLE sessions (
"NM" INTEGER, -- PostgreSQL lowercases to "nm"
...
CONSTRAINT ck_nm_range CHECK (NM IS NULL OR ...) -- References "NM" (uppercase)
)
Error: column "nm" does not exist (PostgreSQL can't find the uppercase constraint reference)
Solution
Use double-quoted identifiers to force PostgreSQL to preserve case:
# CORRECT - Preserves case
NM: Mapped[Union[int, None]] = mapped_column(
Integer,
name='"NM"', # Generates: CREATE TABLE ... ("NM" INTEGER, ...)
nullable=True,
)
This generates:
CREATE TABLE sessions (
"NM" INTEGER, -- Preserves "NM" in SQL
...
CONSTRAINT ck_nm_range CHECK ("NM" IS NULL OR ...) -- Matches quoted name
)
Applied Fixes
File: app/models/session.py
Lines 108-119: Fixed NM and NN column definitions to use name='"NM"' and name='"NN"'
Before:
NM: Mapped[Union[int, None]] = mapped_column(
Integer,
name="NM", # ❌ Gets lowercased
nullable=True,
comment="Nilai Mentah (raw score) [0, 1000]",
)
After:
NM: Mapped[Union[int, None]] = mapped_column(
Integer,
name='"NM"', # ✅ Preserves case in PostgreSQL
nullable=True,
comment="Nilai Mentah (raw score) [0, 1000]",
)
Why This Works
- Double quotes in Python string → SQL receives
"NM"as literal - SQL parser preserves literal inside double quotes → Column name stays
"NM"(uppercase) - CHECK constraints match → Both column and constraint use
"NM"
Notes
- This fix is PostgreSQL-specific - Other databases may handle this differently
- For MySQL: Use backticks:
NMinstead of quotes - Best practice: Use lowercase identifiers with underscores:
nm_score,nn_score - This issue affects all uppercase column names in CHECK constraints
Testing
After applying this fix, restart the application and verify:
cd /www/wwwroot/irt-bank-soal
git pull
source venv/bin/activate
pip install -r requirements.txt
pm2 restart irt-bank-soal
pm2 logs irt-bank-soal --lines 20
Expected: Application starts successfully without "column nm does not exist" error.