clause('epilog')) { $query->epilog('RETURNING *'); } return $query; } /** * Returns a dictionary of expressions to be transformed when compiling a Query * to SQL. Array keys are method names to be called in this class * * @return array */ protected function _expressionTranslators() { $namespace = 'Cake\Database\Expression'; return [ $namespace . '\FunctionExpression' => '_transformFunctionExpression' ]; } /** * Receives a FunctionExpression and changes it so that it conforms to this * SQL dialect. * * @param \Cake\Database\Expression\FunctionExpression $expression The function expression to convert * to postgres SQL. * @return void */ protected function _transformFunctionExpression(FunctionExpression $expression) { switch ($expression->getName()) { case 'CONCAT': // CONCAT function is expressed as exp1 || exp2 $expression->setName('')->setConjunction(' ||'); break; case 'DATEDIFF': $expression ->setName('') ->setConjunction('-') ->iterateParts(function ($p) { if (is_string($p)) { $p = ['value' => [$p => 'literal'], 'type' => null]; } else { $p['value'] = [$p['value']]; } return new FunctionExpression('DATE', $p['value'], [$p['type']]); }); break; case 'CURRENT_DATE': $time = new FunctionExpression('LOCALTIMESTAMP', [' 0 ' => 'literal']); $expression->setName('CAST')->setConjunction(' AS ')->add([$time, 'date' => 'literal']); break; case 'CURRENT_TIME': $time = new FunctionExpression('LOCALTIMESTAMP', [' 0 ' => 'literal']); $expression->setName('CAST')->setConjunction(' AS ')->add([$time, 'time' => 'literal']); break; case 'NOW': $expression->setName('LOCALTIMESTAMP')->add([' 0 ' => 'literal']); break; case 'RAND': $expression->setName('RANDOM'); break; case 'DATE_ADD': $expression ->setName('') ->setConjunction(' + INTERVAL') ->iterateParts(function ($p, $key) { if ($key === 1) { $p = sprintf("'%s'", $p); } return $p; }); break; case 'DAYOFWEEK': $expression ->setName('EXTRACT') ->setConjunction(' ') ->add(['DOW FROM' => 'literal'], [], true) ->add([') + (1' => 'literal']); // Postgres starts on index 0 but Sunday should be 1 break; } } /** * Get the schema dialect. * * Used by Cake\Database\Schema package to reflect schema and * generate schema. * * @return \Cake\Database\Schema\PostgresSchema */ public function schemaDialect() { if (!$this->_schemaDialect) { $this->_schemaDialect = new PostgresSchema($this); } return $this->_schemaDialect; } /** * {@inheritDoc} */ public function disableForeignKeySQL() { return 'SET CONSTRAINTS ALL DEFERRED'; } /** * {@inheritDoc} */ public function enableForeignKeySQL() { return 'SET CONSTRAINTS ALL IMMEDIATE'; } }