Search code examples
phpsqlitelaravelnotnull

"column" IS NOT NULL in query does not throw error when column does not exist


In my PHP unit tests, I am using an SQLite in-memory database, which contains the following table:

CREATE TABLE "battlegroup_request" (
  "id" INTEGER NULL PRIMARY KEY AUTOINCREMENT,
  "battlegroupID" INTEGER NULL,
  "inviterID" INTEGER NULL,
  "inviteeID" INTEGER NULL
)

When I execute the following query with two integer bindings;

SELECT *
FROM "battlegroup_request"
WHERE "inviteeid" = ? AND
  "inviter" IS NOT NULL AND
  "battlegroupid" = ?
LIMIT 1

The query returns one result, but I expect it to throw an error, since the column inviter does not exist. Is this expected behaviour of SQLite? Am I doing something wrong?

I am using PDO, the connection was created as follows:

new PDO(
    'sqlite::memory:',
    null,
    null,
    array(
        PDO::ATTR_CASE => PDO::CASE_LOWER,
        PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
        PDO::ATTR_ORACLE_NULLS => PDO::NULL_NATURAL,
        PDO::ATTR_STRINGIFY_FETCHES => false,
        PDO::ATTR_EMULATE_PREPARES => false,
    )
);

(These options are Laravel's default, which is the framework we're using.)


Solution

  • If you use something like:

    SELECT "inviter" IS NOT NULL FROM battlegroup_request
    

    it will return TRUE if column inviter did not exist, because SQLite will treat "inviter" as simply string value (and it is certainly not NULL here).

    However, if you drop double quotes:

    SELECT inviter IS NOT NULL FROM battlegroup_request
    

    it will raise exception if column inviter did not exist.

    EDIT: Using backticks also forces SQLite to treat it as name (not a string):

    SELECT `inviter` IS NOT NULL FROM battlegroup_request
    

    will raise an exception if column inviter did not exist.