{"record":{"id":"d090c48f7ca6dcdd","repo":"phalcon/cphalcon","slug":"returning-clauses-are-not-supported-by-this-dialec","errorCode":null,"errorMessage":"RETURNING clauses are not supported by this dialect","messagePattern":"RETURNING clauses are not supported by this dialect","errorType":"exception","errorClass":"ReturningNotSupported","httpStatus":null,"severity":"error","filePath":"phalcon/Db/Dialect.zep","lineNumber":576,"sourceCode":"            let assignments[] = this->escape((string) col)\n                . \" = excluded.\" . this->escape((string) col);\n        }\n\n        return sqlQuery\n            . \" ON CONFLICT (\" . this->getColumnList(conflictColumns) . \")\"\n            . \" DO UPDATE SET \" . implode(\", \", assignments);\n    }\n\n    /**\n     * Returns a SQL statement extended with a `RETURNING` clause so the\n     * INSERT/UPDATE/DELETE returns rows. Supported by PostgreSQL and\n     * SQLite 3.35+. Pass `[\"*\"]` for `RETURNING *`, or a list of column\n     * names. The base implementation throws - MySQL inherits it because\n     * MySQL has no RETURNING construct.\n     */\n    public function returning( string sqlQuery,  array columns) -> string\n    {\n        throw new ReturningNotSupported();\n    }\n\n    /**\n     * Generate SQL to release a savepoint\n     */\n    public function releaseSavepoint( string name) -> string\n    {\n        return \"RELEASE SAVEPOINT \" . name;\n    }\n\n    /**\n     * Generate SQL to rollback a savepoint\n     */\n    public function rollbackSavepoint( string name) -> string\n    {\n        return \"ROLLBACK TO SAVEPOINT \" . name;\n    }\n","sourceCodeStart":558,"sourceCodeEnd":594,"githubUrl":"https://github.com/phalcon/cphalcon/blob/b7419de9cd0a8a3f48441ead84c9f8415d463e25/phalcon/Db/Dialect.zep#L558-L594","documentation":"Dialect::returning() appends a `RETURNING` clause so INSERT/UPDATE/DELETE statements give back rows. It is a PostgreSQL and SQLite 3.35+ feature; the base dialect implements it as an unconditional throw, and the MySQL dialect inherits that because MySQL has no RETURNING construct. Use supportsReturning() (false on the base/MySQL dialects) to probe.","triggerScenarios":"Calling $dialect->returning($sql, ['id']) or an adapter helper built on it while connected through Pdo\\Mysql; portable repository code that relies on RETURNING for last-insert-id and runs against a MySQL deployment.","commonSituations":"Code written and tested on PostgreSQL/SQLite then deployed on MySQL; multi-driver packages assuming RETURNING everywhere; migrating from Postgres to MySQL without auditing RETURNING usage.","solutions":["Guard with if ($connection->getDialect()->supportsReturning()) and branch per adapter.","On MySQL use $connection->lastInsertId() after plain INSERT instead of RETURNING.","When portability matters, keep the RETURNING path but provide a MySQL fallback that re-selects by lastInsertId or by a client-generated unique key."],"exampleFix":"// before\n$sql = $connection->getDialect()->returning(\n    \"INSERT INTO users (email) VALUES ('a@b.c')\",\n    ['id']\n); // throws ReturningNotSupported on MySQL\n\n// after\nif ($connection->getDialect()->supportsReturning()) {\n    $sql = $connection->getDialect()->returning(\n        \"INSERT INTO users (email) VALUES ('a@b.c')\",\n        ['id']\n    );\n} else {\n    $connection->execute(\"INSERT INTO users (email) VALUES ('a@b.c')\");\n    $id = $connection->lastInsertId();\n}","handlingStrategy":"validation","validationCode":"if ($connection->getDialect()->supportsReturning()) {\n    $sql = $connection->getDialect()->returning($insert, ['id']);\n} else {\n    $connection->execute($insert);\n    $id = $connection->lastInsertId();\n}","typeGuard":null,"tryCatchPattern":"use Phalcon\\Db\\Exceptions\\ReturningNotSupported;\n\ntry {\n    $sql = $connection->getDialect()->returning($insert, ['id']);\n} catch (ReturningNotSupported $e) {\n    // MySQL path: plain insert + lastInsertId\n    $connection->execute($insert);\n    $id = $connection->lastInsertId();\n}","preventionTips":["Probe the dialect with supportsReturning() before building RETURNING SQL.","On MySQL, use lastInsertId() for auto-increment keys instead of RETURNING.","Test adapter-specific write paths against every database your app supports."],"tags":["returning","dialect","mysql","postgresql","sqlite","unsupported-feature"],"backgroundTag":"unsupported-dialect-feature","analyzedSha":"b7419de9cd0a8a3f48441ead84c9f8415d463e25","analyzedAt":"2026-08-21T06:21:18.811Z","schemaVersion":2},"datasetVersion":"2026-08-21T13:17:26.733Z"}