Skip to content

SqliteForeignKeySettingInsideTransaction ​

warning native on by default

Group: Probable bugs

Identify PRAGMA foreign_keys assignment inside a known active transaction on a resolved SQLite3 or PDO sqlite connection. Parse complete literal SQL statements; BEGIN opens, COMMIT/END/ROLLBACK close, and unknown transaction state excludes.

Detection ​

  • Report an exec() call on a resolved SQLite3 or PDO sqlite connection whose literal SQL assigns PRAGMA foreign_keys while a transaction is proven open. Parse complete literal SQL statements; BEGIN opens, COMMIT/END/ROLLBACK close, and unknown transaction state excludes.
  • Track the transaction through every earlier call on the same connection in the lexical scope:
    • exec() runs its whole literal script; query() and querySingle() (and PDO::query()) apply a single literal statement.
    • PDO::beginTransaction() opens; commit(), rollBack(), SQLite3::close() and SQLite3::open() leave no open transaction.
    • Other builtin methods of the connection do not change the state.
  • Only a call that is certain to have run before the PRAGMA can open a transaction: it is a statement of a block enclosing the PRAGMA, or its success guards the PRAGMA. A call that may or may not have run (another if/else branch, a try or catch body, a loop body, the right side of or/and/??, a ternary arm) leaves the state unknown when it would change it, and is ignored when its literal SQL holds no transaction statement. A later certain BEGIN makes the state known again. A call is disregarded altogether when its path cannot reach the PRAGMA: its statement is followed, in a block that does not contain the PRAGMA, only by plain expression statements and then a return, throw or exit, with no enclosing try or nested function in between (if ($failed) { $db->exec('ROLLBACK'); return; }).
  • Resolve builtin functions, classes, constants and methods, including imports and supported named arguments. Follow only bounded local facts within one lexical scope. Receiver and argument provenance must establish the specific API contract; variable names and comments never prove intent.
  • Report one finding per violating operation. A reachable path, unchanged value identity and applicable API behavior are required. Intervening mutation, unknown calls involving tracked values, escaped aliases or exhausted analysis budgets invalidate proof.

Exceptions (no report) ​

  • Exclude unresolved required symbols, user-defined lookalikes, incomplete syntax, unknown required values and unsupported versions.
  • The state is unknown, so nothing is reported, after any of these on the connection: SQL that is not a known literal or cannot be tokenized; a multi-statement string passed to a method other than exec(); a user-defined or dynamically named method.
  • No report at all when an earlier prepare() on the connection holds SQL that is unknown or contains a transaction statement: the prepared statement can run at any later point.
  • Both @custos-ignore SqliteForeignKeySettingInsideTransaction and @noinspection SqliteForeignKeySettingInsideTransaction suppress this native rule.

Fix ​

None. A repair requires a semantic decision or application error-handling policy.

PHP versions ​

Available in PHP 5.3–8.5 where the referenced API exists. Do not apply extension contracts when the resolved API is unavailable. Gate syntax and version-specific behavior to the configured target.

Configure ​

In custos.json:

json
{
  "rules": {
    "SqliteForeignKeySettingInsideTransaction": {
      "enabled": false
    }
  }
}

Suppress ​

Before the statement or declaration (or the first statement of the file):

php
// @custos-ignore SqliteForeignKeySettingInsideTransaction

Released under the MIT License. Native rules and rules modeled on Php Inspections (EA Extended); independent clean-room implementation.