PostgreSQL: ("character varying = integer"), casting/quoting error

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • christb
    Junior Member
    • Mar 2026
    • 3

    #1

    PostgreSQL: ("character varying = integer"), casting/quoting error

    • EspoCRM version: 9.3.8
    • PHP version: 8.4.21
    • Database: PostgreSQL 18.3
    • Extensions involved: none — reproducible with core code only (see below)

    Steps to Reproduce

    1. On a PostgreSQL-backed instance, run the following against any core entity whose `id` (or any other varchar/text) attribute is being filtered with an `IN`-style array, where at least one element of that array is a native PHP `int` instead of a `string`:

    Code:
    $entityManager->getRDBRepository('Contact')
    ->where([
        'id' => [123456, 'anExistingContactId'],
    ])
    ->find();

    (`123456` is a plain PHP int; it does not need to correspond to a real record — the error happens during SQL generation, before execution against real data.)

    2. Observe the exception thrown when the query executes.

    Expected Result

    The query executes normally. Every element of the `IN (...)` list is quoted as a string literal, because the target column (`contact.id`, `character varying`) is a string type — regardless of the PHP-side type of the value being compared against it.

    Actual Result

    PDOException: SQLSTATE[42883]: Undefined function: 7 ERROR: operator does not exist: character varying = integer
    LINE 1: ...WHERE "contact"."id" IN (123456, 'anExistingContactId')
    ^
    HINT: No operator matches the given name and argument types. You might need to add explicit type casts.

    Root Cause

    `Espo\ORM\QueryComposer\BaseQueryComposer::quote() ` decides whether to quote a value purely based on the PHP type of the value, not the database type of the column it is being compared against:
    On MySQL this goes unnoticed because MySQL implicitly coerces between `varchar` and `integer` in comparisons. PostgreSQL does not, and rejects the query outright.

    EspoCRM's own default ID generator can produce IDs that are *purely numeric strings* purely by chance.

    Suggested Fix

    `quote()` (or the calling comparison-composition logic) should resolve the target column's declared type via `Espo\ORM\Metadata` for the attribute being compared, and quote the value according to that column type rather than the PHP type of the value. Alternatively, the value could be cast to a string whenever the target attribute type is `varchar`/`text`/`id`/`foreignId`, before quoting.

    Workaround

    We work around this in application code by explicitly casting ID arrays to strings before passing them into `where()`/`IN` filters, e.g. `array_map('strval', array_keys($idMap))`. This is safe but has to be applied manually at every call site that builds an ID array this way.
    Last edited by christb; 07-10-2026, 12:05 PM.
  • yuri
    EspoCRM product developer
    • Mar 2014
    • 9944

    #2
    It's not a bug.

    Comment

    Working...