Details
-
Type:
Bug
-
Status:
Resolved
-
Priority:
Major
-
Resolution: Invalid
-
Affects Version/s: 2.1.1
-
Fix Version/s: None
-
Component/s: DQL
-
Security Level: All
-
Labels:None
-
Environment:Debian 5.0, PostgreSQL 8.4
Description
Using boolean literals in a DQL query results in a PDOException on PostgreSQL, when used together with the equals comparison operator.
Here's an example DQL query involving a boolean literal and an equals comparison operator:
SELECT run
FROM \persistentData\model\core\Run run
WHERE run.isClosed = false
ORDER BY run.timestamp DESC
On PostgreSQL 8.4 this query gets compiled down to:
SELECT r0_.timestamp AS timestamp0, r0_.isClosed AS isClosed1, r0_.dbID AS dbID2, r0_.invoiceCreatorResult_dbID AS invoiceCreatorResult_dbID3, r0_.commissionNoteCreatorResult_dbID AS commissionNoteCreatorResult_dbID4, r0_.consumerInvoiceExporterResult_dbID AS consumerInvoiceExporterResult_dbID5
FROM Run r0_ WHERE r0_.isClosed = 0
ORDER BY r0_.timestamp DESC
When this query gets processed by PostgreSQL, it results in a PDOException, as 0 is not a boolean literal. For boolean literals supported by PostgreSQL, see http://www.postgresql.org/docs/9.1/static/datatype-boolean.html. Interestingly, '0' (meaning the string literal 0) would be a valid boolean literal.
Here is what the log says:
2011-09-27 01:04:03 CEST ERROR: operator does not exist: boolean = integer at character 329
2011-09-27 01:04:03 CEST HINT: No operator matches the given name and argument type(s). You might need to add explicit type casts.
2011-09-27 01:04:03 CEST STATEMENT: SELECT r0_.timestamp AS timestamp0, r0_.isClosed AS isClosed1, r0_.dbID AS dbID2, r0_.invoiceCreatorResult_dbID AS invoiceCreatorResult_dbID3, r0_.commissionNoteCreatorResult_dbID AS commissionNoteCreatorResult_dbID4, r0_.consumerInvoiceExporterResult_dbID AS consumerInvoiceExporterResult_dbID5 FROM Run r0_ WHERE r0_.isClosed = 0 ORDER BY r0_.timestamp DESC
Sidenote: For a while I used to wrongly use 0 and 1 as boolean placeholders in DQL, and, running on MySQL 5.0 for a while on customer request, it somehow worked without any problem whatsoever, in spite of the fact that the Doctrine reference documentation requires boolean literals to be either "true" or "false". MySQL silently accepted the wrong code, generally interpreting the boolean datatype as an alias for TINYINT(1). PostgreSQL, however, implements booleans according to the SQL 2003 standard, and correctly complains about a non-safe comparison between a boolean column and an integer literal. So basically, the compilation of boolean literals is generally broken, but on MySQL it simply does not matter, while on PostgreSQL (and possibly other systems as well) it does.
After changing the DQL literal from "0" to "false", as required by the Doctrine reference documentation, I still get the same error, and I can verify (as shown above) that the value "false" in DQL gets compiled to the integer literal "0" in SQL, which it should not.
Issue Links
- is referenced by
-
DDC-1048
Boolean type issue
-
Is this issue still valid in latest trunk?
Also, it seems PostgreSQL still supports '0', 'false', 0, f. 'off' in 8.4: http://www.postgresql.org/docs/8.4/static/datatype-boolean.html
Cheers,