38 public function quote($identifier)
40 return pg_escape_identifier($this->connection->getResource(), mb_strtolower($identifier));
48 return 'EXCLUDED.' . $this->
quote($identifier);
62 public function forSql($value, $maxLength = 0)
66 $value = mb_substr($value, 0, $maxLength);
69 return pg_escape_string($this->connection->getResource(), $value);
85 return 'current_date';
95 $from = static::getCurrentDateTimeFunction();
99 $from = $from .
"::timestamp";
102 return $from .
" + cast(" . $seconds .
"||' second' as interval)";
112 $from = static::getCurrentDateTimeFunction();
116 $from = $from .
"::timestamp";
119 return '(' . $from .
" + cast(" . $days .
"||' day' as interval))";
127 return 'cast('.$value.
' as date)';
135 static $search = array(
144 static $replace = array(
154 $format = str_replace($search, $replace, $format);
162 return "to_char(".$field.
", '".$format.
"')";
171 return $field .
' ~ ' . $regexp;
179 return implode(
" || ", func_get_args());
195 return "encode(digest(replace(" . $field .
", '\\', '\\\\')::bytea, 'sha1'), 'hex')";
203 return "COALESCE(".$expression.
", ".$result.
")";
211 return "OCTET_LENGTH(".$field.
")";
216 return "to_tsvector('english'::regconfig, " . $field .
") @@ to_tsquery('english'::regconfig, " . $value .
")";
223 foreach ($values as $i => $searchTerm)
225 $values[$i] = $searchTerm .
':*';
228 return implode(
' & ', $values);
235 foreach ($values as $i => $searchTerm)
237 $values[$i] = $searchTerm .
':*';
240 return implode(
' | ', $values);
248 return "timestamp '".$value.
"'";
256 return "TO_CHAR(".$fieldName.
", 'YYYY-MM-DD HH24:MI:SS')";
266 return array($this,
"convertFromDbDateTime");
268 elseif($field instanceof ORM\Fields\
DateField)
270 return array($this,
"convertFromDbDate");
274 return parent::getConverter($field);
283 if($value !==
null && $value !=
'0000-00-00 00:00:00')
296 if($value !==
null && $value !=
'0000-00-00')
309 return 'CAST('.$fieldName.
' AS char)';
327 switch ($field->getSize())
340 $defaultPrecision = 18;
343 $precision = $field->getPrecision() > 0 ? $field->getPrecision() : $defaultPrecision;
344 $scale = $field->getScale() > 0 ? $field->getScale() : $defaultScale;
346 if ($scale >= $precision)
348 $precision = $defaultPrecision;
349 $scale = $defaultScale;
352 return "decimal($precision, $scale)";
354 elseif ($field instanceof ORM\Fields\
FloatField)
362 elseif ($field instanceof ORM\Fields\
DateField)
366 elseif ($field instanceof ORM\Fields\
TextField)
372 $values = $field->getValues();
374 if (preg_match(
'/^[0-9]+$/', $values[0]) && preg_match(
'/^[0-9]+$/', $values[1]))
380 return 'varchar('.max(mb_strlen($values[0]), mb_strlen($values[1])).
')';
383 elseif ($field instanceof ORM\Fields\
EnumField)
385 return 'varchar('.max(array_map(
'strlen', $field->getValues())).
')';
390 $defaultLength =
false;
393 if ($validator instanceof ORM\Fields\Validators\LengthValidator)
395 if ($defaultLength ===
false || $defaultLength > $validator->getMax())
397 $defaultLength = $validator->getMax();
401 return 'varchar('.($defaultLength > 0? $defaultLength: 255).
')';
416 return (
new ORM\Fields\
IntegerField($name))->configureSize(8);
422 return (
new ORM\Fields\
IntegerField($name))->configureSize(4);
427 return (
new ORM\Fields\
IntegerField($name))->configureSize(2);
428 case 'double precision':
436 case 'timestamp without time zone':
438 case 'timestamp with time zone':
451 $offset = intval($offset);
452 $limit = intval($limit);
454 if ($offset > 0 && $limit <= 0)
456 throw new \Bitrix\Main\ArgumentException(
"Limit must be set if offset is set");
461 $sql .=
"\nLIMIT ".$limit;
466 $sql .=
" OFFSET ".$offset;
479 return 'INSERT INTO ' . $tableName . $fields . $sql .
' ON CONFLICT DO NOTHING';
487 return 'ASC NULLS FIRST';
495 return 'DESC NULLS LAST';
501 public function prepareMerge($tableName, array $primaryFields, array $insertFields, array $updateFields)
507 $insert && $insert[0] !=
"" && $insert[1] !=
""
512 $sql =
'INSERT INTO ' . $this->
quote($tableName) .
' ('.$insert[0].
')
513 VALUES (' . $insert[1] .
')
514 ON CONFLICT (' . implode(
',', array_map([$this,
'quote'], $primaryFields)) .
')
515 DO UPDATE SET ' . $update[0];
536 $maxBodySize = 1024*1024;
539 foreach ($insertRows as $insertFields)
541 $insert = $this->
prepareInsert($tableName, $insertFields,
true);
542 if (!$head && $insert && $insert[0])
544 $head =
'INSERT INTO ' . $this->
quote($tableName) .
' (' . implode(
', ', $insert[0]) .
') VALUES ';
545 $tail =
' ON CONFLICT (' . implode(
',', array_map([$this,
'quote'], $primaryFields)) .
') DO UPDATE SET (' . implode(
', ', $insert[0]) .
') = (' . implode(
', ', array_map(
function($f){
return 'EXCLUDED.'.$f;}, $insert[0])) .
')';
547 if ($insert && $insert[1])
549 $values =
'(' . implode(
', ', $insert[1]) .
')';
550 $bodySize += mb_strlen($values) + 4;
552 if ($bodySize > $maxBodySize)
554 $result[] = $head.implode(
', ', $body).$tail;
562 $result[] = $head.implode(
', ', $body).$tail;
571 public function prepareMergeSelect($tableName, array $primaryFields, array $selectFields, $select, $updateFields)
576 $tableFields = $this->connection->getTableFields($tableName);
578 $tableFields = array_change_key_case($tableFields, CASE_UPPER);
579 $updateFields = array_change_key_case($updateFields, CASE_UPPER);
580 foreach ($updateFields as $columnName => $value)
582 if (isset($tableFields[$columnName]))
584 $updateColumns[] = $this->
quote($columnName);
585 $updateValues[] = $this->
convertToDb($value, $tableFields[$columnName]);
589 trigger_error(
"Column `{$columnName}` is not found in the `{$tableName}` table", E_USER_WARNING);
593 $sql =
'INSERT INTO ' . $this->
quote($tableName) .
' (' . implode(
',', array_map([$this,
'quote'], $selectFields)) .
') ';
595 $sql .=
' ON CONFLICT (' . implode(
',', array_map([$this,
'quote'], $primaryFields)) .
') DO UPDATE SET ';
596 if (count($updateColumns) === 1)
598 $sql .= $updateColumns[0] .
' = ' . $updateValues[0];
602 $sql .=
' (' . implode(
', ', $updateColumns) .
') = (' . implode(
', ', $updateValues) .
')';
613 $primaryColumns = [];
614 foreach ($primaryFields as $columnName)
616 $primaryColumns[] = $this->
quote($columnName);
618 $sqlPrimary = implode(
', ', $primaryColumns);
621 foreach ($order as $columnName => $sort)
623 $orderColumns[] = $this->
quote($columnName) .
' ' . $sort;
625 $sqlOrder = $orderColumns ?
' ORDER BY ' . implode(
', ', $orderColumns) :
'';
626 return 'DELETE FROM ' . $this->
quote($tableName) .
' WHERE (' . $sqlPrimary .
') IN (SELECT ' . $sqlPrimary .
' FROM ' . $this->
quote($tableName) .
' WHERE ' . $where . $sqlOrder .
' LIMIT ' . intval($limit) .
')';
636 return 'row_number() over()';
644 $dml =
"UPDATE " . $tableName .
' AS ' . $tableAlias .
" SET\n";
647 foreach ($fields as $fieldName => $fieldValue)
649 $set .= ($set ?
',' :
'') . $fieldName .
' = ' .$fieldValue .
"\n";
652 $dml .=
'FROM ' . $from .
"\n";
653 $dml .=
'WHERE ' . $where .
"\n";
658 protected function getOrderByField(
string $field, array $values, callable $callback,
bool $quote =
true): string
660 $field = $quote ? $this->
quote($field) : $field;
661 $values = implode(
',', array_map($callback, $values));
663 return "array_position(ARRAY[{$values}], {$field})";
softCastTextToChar($fieldName)
getOrderByField(string $field, array $values, callable $callback, bool $quote=true)
prepareMergeMultiple($tableName, array $primaryFields, array $insertRows)
getMatchFunction($field, $value)
getTopSql($sql, $limit, $offset=0)
getIsNullFunction($expression, $result)
getDateToCharFunction($fieldName)
formatDate($format, $field=null)
getRegexpOperator($field, $regexp)
getDatetimeToDateFunction($value)
prepareDeleteLimit($tableName, array $primaryFields, $where, array $order, $limit)
addDaysToDateTime($days, $from=null)
getFieldByColumnType($name, $type, array $parameters=null)
getColumnTypeByField(ScalarField $field)
initRowNumber($variableName)
getConverter(ScalarField $field)
prepareCorrelatedUpdate($tableName, $tableAlias, $fields, $from, $where)
getMatchAndExpression($values, $prefixSearch=false)
getLengthFunction($field)
getMatchOrExpression($values, $prefixSearch=false)
forSql($value, $maxLength=0)
getCurrentDateTimeFunction()
convertFromDbDateTime($value)
addSecondsToDateTime($seconds, $from=null)
convertFromDbDate($value)
prepareMergeSelect($tableName, array $primaryFields, array $selectFields, $select, $updateFields)
getCharToDateFunction($value)
getInsertIgnore($tableName, $fields, $sql)
prepareMerge($tableName, array $primaryFields, array $insertFields, array $updateFields)
getRowNumber($variableName)
prepareUpdate($tableName, array $fields)
prepareInsert($tableName, array $fields, $returnAsArray=false)
convertToDb($value, ORM\Fields\IReadable $field=null)