{"record":{"id":"74068b23795d943e","repo":"laravel/framework","slug":"this-database-engine-does-not-support-upserts","errorCode":null,"errorMessage":"This database engine does not support upserts.","messagePattern":"This database engine does not support upserts\\.","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"src/Illuminate/Database/Query/Grammars/Grammar.php","lineNumber":1420,"sourceCode":"        $joins = $this->compileJoins($query, $query->joins);\n\n        return \"update {$table} {$joins} set {$columns} {$where}\";\n    }\n\n    /**\n     * Compile an \"upsert\" statement into SQL.\n     *\n     * @param  \\Illuminate\\Database\\Query\\Builder  $query\n     * @param  array  $values\n     * @param  array  $uniqueBy\n     * @param  array  $update\n     * @return string\n     *\n     * @throws \\RuntimeException\n     */\n    public function compileUpsert(Builder $query, array $values, array $uniqueBy, array $update)\n    {\n        throw new RuntimeException('This database engine does not support upserts.');\n    }\n\n    /**\n     * Prepare the bindings for an update statement.\n     *\n     * @param  array  $bindings\n     * @param  array  $values\n     * @return array\n     */\n    public function prepareBindingsForUpdate(array $bindings, array $values)\n    {\n        $cleanBindings = Arr::except($bindings, ['select', 'join']);\n\n        $values = Arr::flatten(array_map(fn ($value) => value($value), $values));\n\n        return array_values(\n            array_merge($bindings['join'], $values, Arr::flatten($cleanBindings))\n        );","sourceCodeStart":1402,"sourceCodeEnd":1438,"githubUrl":"https://github.com/laravel/framework/blob/e0f6eb3518ac29fbbca8529e97d0df7fc9f24481/src/Illuminate/Database/Query/Grammars/Grammar.php#L1402-L1438","documentation":"The base Grammar's compileUpsert throws by default. All four major engine grammars (MySqlGrammar, PostgresGrammar, SQLiteGrammar, SqlServerGrammar) override it with engine-specific syntax (INSERT ... ON DUPLICATE KEY UPDATE / ON CONFLICT DO UPDATE / INSERT ON CONFLICT DO UPDATE / MERGE). This error fires only for a custom grammar extending the base Grammar without an override.","triggerScenarios":"Using upsert() on a query builder whose grammar is a custom class extending Grammar without implementing compileUpsert. This occurs with third-party or community database drivers that lack upsert support.","commonSituations":"Using a community database package (e.g., a ClickHouse, DynamoDB, or Cassandra driver) that extends the base Grammar but has not implemented upsert operations.","solutions":["Switch to a built-in connection (mysql, pgsql, sqlite, or sqlsrv) — all four override compileUpsert","Override compileUpsert in your custom grammar with the correct SQL for your engine","Replace upsert() with a try/catch around insert() followed by update(), or use a raw statement with your engine's native upsert syntax"],"exampleFix":"// before — custom grammar without upsert support\nDB::table('users')->upsert(['email' => 'a@b.com', 'name' => 'Alice'], ['email'], ['name']);\n\n// after — manual insert-or-update fallback\n$exists = DB::table('users')->where('email', 'a@b.com')->exists();\nif ($exists) {\n    DB::table('users')->where('email', 'a@b.com')->update(['name' => 'Alice']);\n} else {\n    DB::table('users')->insert(['email' => 'a@b.com', 'name' => 'Alice']);\n}","handlingStrategy":"try-catch","validationCode":"$grammar = DB::connection()->getQueryGrammar();\n$method = new ReflectionMethod($grammar, 'compileUpsert');\n\nif ($method->getDeclaringClass()->getName() !== 'Illuminate\\\\Database\\\\Query\\\\Grammars\\\\Grammar') {\n    DB::table('users')->upsert($values, ['email'], ['name']);\n}","typeGuard":"function grammarSupportsUpsert(): bool {\n    $grammar = DB::connection()->getQueryGrammar();\n    $method = new ReflectionMethod($grammar, 'compileUpsert');\n    return $method->getDeclaringClass()->getName() !== 'Illuminate\\\\Database\\\\Query\\\\Grammars\\\\Grammar';\n}","tryCatchPattern":"try {\n    DB::table('users')->upsert($values, ['email'], ['name']);\n} catch (\\RuntimeException $e) {\n    if (str_contains($e->getMessage(), 'upserts')) {\n        // manual fallback: check existence then insert or update\n        foreach ($values as $row) {\n            $exists = DB::table('users')->where('email', $row['email'])->exists();\n            $exists\n                ? DB::table('users')->where('email', $row['email'])->update($row)\n                : DB::table('users')->insert($row);\n        }\n    } else {\n        throw $e;\n    }\n}","preventionTips":["Use a built-in connection — all four override compileUpsert","If using a custom grammar, override compileUpsert before calling upsert()","Keep a manual insert-or-update fallback ready for custom drivers"],"tags":["upsert","grammar","database","custom-driver"],"backgroundTag":null,"analyzedSha":"e0f6eb3518ac29fbbca8529e97d0df7fc9f24481","analyzedAt":"2026-08-11T20:52:37.562Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}