Skip to content

Conversation

@michaeldflowers
Copy link

Summary

  • Add Condition.EqualsIgnoreCase for case-insensitive database queries
  • Generate LOWER(column) = LOWER(?) SQL for email lookups
  • No mutation of input data - comparison handled at database level

Fixes #5723

Test plan

  • Register user with mixed-case email (e.g., [email protected])
  • Login with different case variation (e.g., [email protected])
  • Existing users unaffected - no data migration needed

@tananaev
Copy link
Member

This is not what we discussed either. We want to use citext.

@michaeldflowers
Copy link
Author

No problem. I saw that was a suggestion. I wasn't aware that it was a requirement. Let me take another look.

WARNING: This is a PostgreSQL-specific solution that will NOT work
with other databases (MySQL, H2, SQL Server, MariaDB, etc.).

Implementation:
- Enables PostgreSQL CITEXT extension
- Converts tc_users.email column to CITEXT type for case-insensitive comparison
- Migration only runs on PostgreSQL (skipped on other databases)

Limitations:
- Only fixes the issue for PostgreSQL installations
- MySQL, H2, and other database users will still experience case-sensitive
  email login behavior
- Breaks database portability - code expects case-insensitive email matching
  but only PostgreSQL provides it

Alternative approach (database-agnostic):
See branch fix-email-case-sensitivity-code-based for a solution using
LOWER() SQL functions that works across all supported databases.

Fixes traccar#5723

Co-Authored-By: Claude Sonnet 4.5 <[email protected]>
@michaeldflowers michaeldflowers force-pushed the fix-email-case-sensitivity branch from f219b71 to da48a99 Compare January 14, 2026 15:06
IMPORTANT: This solution requires BOTH database migration AND code changes.
CITEXT column type alone is insufficient due to JDBC parameter binding behavior.

## What This PR Does

1. **Database Migration** (schema/changelog-6.12.xml):
   - Enables PostgreSQL CITEXT extension
   - Converts tc_users.email column to CITEXT type

2. **Code Changes** (3 files modified):
   - Adds Condition.EqualsCitext for PostgreSQL-specific queries
   - Updates DatabaseStorage to generate "CAST(? AS CITEXT)" in SQL
   - Updates LoginService to use EqualsCitext for email lookups

## Why Code Changes Are Required

CITEXT column type alone does NOT fix the issue because:

When using JDBC prepared statements (the `?` placeholders), PostgreSQL
does not automatically infer that the parameter should be treated as CITEXT.
Instead, it treats the parameter as plain TEXT, making the comparison
case-sensitive despite the column being CITEXT.

**Without CAST:**
```sql
WHERE email = ?  -- Parameter treated as TEXT, comparison is case-sensitive
```

**With CAST (this PR):**
```sql
WHERE email = CAST(? AS CITEXT)  -- Forces case-insensitive comparison
```

## Database Portability Impact

**WARNING: This is a PostgreSQL-ONLY solution**

- MySQL users: No case-insensitive email matching
- H2 users: No case-insensitive email matching
- SQL Server users: No case-insensitive email matching
- Other databases: No case-insensitive email matching

The migration uses `<preConditions><dbms type="postgresql" /></preConditions>`
to skip on non-PostgreSQL databases, but the Java code now generates
PostgreSQL-specific CAST syntax that may fail or behave unexpectedly
on other databases.

## Alternative Approach

For a database-agnostic solution that works on ALL supported databases,
see branch: fix-email-case-sensitivity-code-based

That approach uses LOWER() functions in SQL which work universally:
```sql
WHERE LOWER(email) = LOWER(?)
```

## Testing

Tested on PostgreSQL 17:
- Registered user with email: [email protected]
- Successfully logged in with: [email protected]
- Verified CITEXT column type: \d tc_users shows "citext"
- Verified CAST syntax: Query logs show "CAST(? AS CITEXT)"

Fixes traccar#5723

Co-Authored-By: Claude Sonnet 4.5 <[email protected]>
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.

PostgreSQL is case sensitive - login input for email address's are problematic

2 participants