{"record":{"id":"20086cdd8eeb9d06","repo":"phalcon/cphalcon","slug":"operator-is-not-supported-by-this-sql-dialect","errorCode":null,"errorMessage":"Operator '{}' is not supported by this SQL dialect","messagePattern":"Operator '(.+?)' is not supported by this SQL dialect","errorType":"exception","errorClass":"UnsupportedOperator","httpStatus":null,"severity":"error","filePath":"phalcon/Db/Dialect.zep","lineNumber":929,"sourceCode":"    }\n\n    /**\n     * Resolve binary operations expressions\n     *\n     * @param array expression\n     * @param string|null escapeChar\n     * @param array bindCounts\n     *\n     * @return string\n     */\n    final protected function getSqlExpressionBinaryOperations( array expression, string escapeChar = null,  array bindCounts = []) -> string\n    {\n        var left, right, operator;\n\n        let operator = expression[\"op\"];\n\n        if in_array(operator, this->guardedOperators) && !in_array(operator, this->supportedOperators) {\n            throw new UnsupportedOperator(operator);\n        }\n\n        let left  = this->getSqlExpression(\n            expression[\"left\"],\n            escapeChar,\n            bindCounts\n        );\n\n        let right = this->getSqlExpression(\n            expression[\"right\"],\n            escapeChar,\n            bindCounts\n        );\n\n        return left . \" \" . operator . \" \" . right;\n    }\n\n    /**","sourceCodeStart":911,"sourceCodeEnd":947,"githubUrl":"https://github.com/phalcon/cphalcon/blob/b7419de9cd0a8a3f48441ead84c9f8415d463e25/phalcon/Db/Dialect.zep#L911-L947","documentation":"getSqlExpressionBinaryOperations() throws UnsupportedOperator when a binary-op expression uses an operator from the dialect's guardedOperators list (['@@','@>','<@','&&','||','->','->>','#>','#>>']) that the current dialect does not support. Support is per-dialect: MySQL only allows '->' and '->>', SQLite allows '||','->','->>', PostgreSQL allows all of them. The guard exists so dialect-specific operators (mostly PostgreSQL JSONB/array ones) fail loudly instead of silently emitting SQL the server will reject.","triggerScenarios":"Compiling a raw expression with type 'binary-op' whose 'op' is e.g. '@>' or '#>>' while the adapter's dialect is Mysql or Sqlite; using dialect-agnostic query code with hardcoded JSONB operators on a MySQL connection; PHQL/RawValue expressions containing guarded operators on the wrong adapter.","commonSituations":"Porting an application from PostgreSQL to MySQL (or SQLite) while keeping JSONB/array operator expressions; shared model code deployed against different database backends; upgrading Phalcon to a version that added this guard, where previously the operator passed through unvalidated.","solutions":["Replace the guarded operator with syntax the current dialect supports, e.g. MySQL JSON extraction with '->' / '->>' or JSON_EXTRACT()/JSON_UNQUOTE(JSON_EXTRACT(...)) instead of '@>' or '#>>'","Switch the adapter to the dialect that supports the operator (Postgresql) if you truly need JSONB semantics","Branch the operator per adapter: check $adapter->getDialect()->supportedOperators (or getDialect() instanceof Postgresql) before building the expression","As a last resort use a RawValue / hand-written SQL string for the dialect-specific part"],"exampleFix":"// before (MySQL adapter)\n$expr = [\n    'type'  => 'binary-op',\n    'op'    => '@>',\n    'left'  => ['type' => 'qualified', 'name' => 'meta'],\n    'right' => ['type' => 'literal', 'value' => '\"tags\"'],\n];\n\n// after (MySQL: JSON_CONTAINS)\n$expr = new RawValue(\"JSON_CONTAINS(meta, '\\\"tags\\\"')\");","handlingStrategy":"type-guard","validationCode":"const GUARDED = ['@@','@>','<@','&&','||','->','->>','#>','#>>'];\n$supported = ['mysql' => ['->','->>'], 'sqlite' => ['||','->','->>'], 'postgresql' => GUARDED];\nif (in_array($operator, GUARDED, true) && !in_array($operator, $supported[$driver], true)) {\n    throw new InvalidArgumentException(\"Operator {$operator} not supported by {$driver}\");\n}","typeGuard":"/** @param array|string $dialect dialect name or Dialect instance */\nfunction supportsOperator(string $driver, string $op): bool\n{\n    $map = [\n        'mysql'      => ['->', '->>'],\n        'sqlite'     => ['||', '->', '->>'],\n        'postgresql' => ['@@','@>','<@','&&','||','->','->>','#>','#>>'],\n    ];\n    return in_array($op, $map[$driver] ?? [], true);\n}","tryCatchPattern":"try {\n    $sql = $dialect->select($definition);\n} catch (\\Phalcon\\Db\\Exceptions\\UnsupportedOperator $e) {\n    // fall back to dialect-specific raw SQL for this predicate\n    $sql = $dialect->select($definitionWithoutOp) . ' /* unsupported op */';\n}","preventionTips":["Feature-check operators against the dialect before building expressions","Keep JSONB/array operators behind a PostgreSQL-only code path","Run your test suite against every adapter you deploy"],"tags":["phalcon","sql","dialect","operator","jsonb","postgresql","mysql"],"backgroundTag":"unsupported-sql-operator","analyzedSha":"b7419de9cd0a8a3f48441ead84c9f8415d463e25","analyzedAt":"2026-08-21T06:21:18.811Z","schemaVersion":2},"datasetVersion":"2026-08-21T11:28:35.574Z"}