Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[pgsql] invalid input syntax for type boolean: "" #6780

Open
fabpico opened this issue Feb 11, 2025 · 3 comments
Open

[pgsql] invalid input syntax for type boolean: "" #6780

fabpico opened this issue Feb 11, 2025 · 3 comments
Labels

Comments

@fabpico
Copy link

fabpico commented Feb 11, 2025

Bug Report

Q A
Version 3.9.3

Summary

I usually use $queryBuilder->createNamedParameter($value) to create queries with prepared statements. Even for boolean values.
It was never a problem in mysql, mariadb and mssql in my cases years ago. Sometimes I had to add a type as second parameter.
pgsql now fails when the value ist false.

Current behavior

When I run one of following code, and the value is false

$queryBuilder->insert(self::TABLE)->values([
    'is_anonymous' => $queryBuilder->createNamedParameter($entity->isAnonymous()),
    // ..
])->executeQuery();
$queryBuilder->insert(self::TABLE)->values([
    'is_anonymous' => $queryBuilder->createNamedParameter($entity->isAnonymous(), ParameterType::BOOLEAN),
    // ..
])->executeQuery();

Following happens

Doctrine\DBAL\Exception\DriverException:
An exception occurred while executing a query: invalid input syntax for type boolean: ""

  at vendor/doctrine/dbal/src/Driver/API/PostgreSQL/ExceptionConverter.php:87
  at Doctrine\DBAL\Driver\API\PostgreSQL\ExceptionConverter->convert(object(Exception), object(Query))
     (vendor/doctrine/dbal/src/Connection.php:1939)
  at Doctrine\DBAL\Connection->handleDriverException(object(Exception), object(Query))
     (vendor/doctrine/dbal/src/Connection.php:1881)
...

After some debugging, I worked around to pass a literal 'false' string.

    private function booleanToLiteral(bool $value): string
    {
        return $value ? 'true' : 'false';
    }
$queryBuilder->insert(self::TABLE)->values([
    'is_anonymous' => $queryBuilder->createNamedParameter($this->booleanToLiteral($entity->isAnonymous())),
    // ..
])->executeQuery();

Expected behavior

The Query should succeed with one of these (without having to do an own conversion).

$queryBuilder->insert(self::TABLE)->values([
    'is_anonymous' => $queryBuilder->createNamedParameter($entity->isAnonymous()),
    // ..
])->executeQuery();
$queryBuilder->insert(self::TABLE)->values([
    'is_anonymous' => $queryBuilder->createNamedParameter($entity->isAnonymous(), ParameterType::BOOLEAN),
    // ..
])->executeQuery();

How to reproduce

See the code snippets.

Further

I searched for this issue and found some related issues, but they didn't talk directly about createNamedParameter: #1847, #564, #625,

@morozov
Copy link
Member

morozov commented Feb 19, 2025

Could you provide more details on reproducing the issue? This is what I tried:

<?php

declare(strict_types=1);

namespace Doctrine\DBAL\Tests;

use Doctrine\DBAL\ParameterType;
use Doctrine\DBAL\Schema\Table;

class AdHocTest extends FunctionalTestCase
{
    public function testBoolean(): void
    {
        $table = new Table('t');
        $table->addColumn('v', 'boolean');
        $this->dropAndCreateTable($table);

        $queryBuilder = $this->connection->createQueryBuilder();

        $result = $queryBuilder->insert('t')->values([
            'v' => $queryBuilder->createNamedParameter(true, ParameterType::BOOLEAN),
        ])->executeStatement();

        self::assertSame(1, $result);
    }
}

The test passes on both the pgsql and pdo_pgsql drivers on DBAL 3.9.3. Are you using the former? What else is missing from the test?

@fabpico
Copy link
Author

fabpico commented Mar 7, 2025

@morozov The problem is when the value is false.

This will work: $queryBuilder->createNamedParameter(true, ParameterType::BOOLEAN).
But this doesn't work: $queryBuilder->createNamedParameter(false, ParameterType::BOOLEAN)

My connection uses driver: pgsql
DBAL version is: 3.9.3

What happens on your setup when you pass value false?

@morozov
Copy link
Member

morozov commented Mar 7, 2025

Yes, the issue with false is reproducible on pgsql. @fabpico, thanks for the clarification!

The underlying issue is that pg_send_execute() accepts only parameter values but not their types, so it seems to interpret all parameters as strings (hence, false becomes empty string). The documentation doesn't say anything about supported parameter types.

This is similar to #2481 / php/pecl-database-pdo_oci#12.

@derrabus do you think this one actually should be fixed in DBAL? Unlike PDO_OCI (which fails to fulfill the PDO API contract), pgsql doesn't declare that is supports various parameter types, and the need to convert binary data to strings before binding implies that the same should be done for all types that PHP cannot convert to a string representation understandable by Postgres.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants