1C-Bitrix 25.700.0
Загрузка...
Поиск...
Не найдено
pgsqlsqlhelper.php
См. документацию.
1<?php
2
3namespace Bitrix\Main\DB;
4
5use Bitrix\Main\Type;
6use Bitrix\Main\ORM;
7use Bitrix\Main\ORM\Fields\ScalarField;
8
10{
11 const FULLTEXT_MAXIMUM_LENGTH = 1000000;
15 public function getLeftQuote()
16 {
17 return '"';
18 }
19
23 public function getRightQuote()
24 {
25 return '"';
26 }
27
31 public function getAliasLength()
32 {
33 return 63;
34 }
35
39 public function quote($identifier)
40 {
41 return pg_escape_identifier($this->connection->getResource(), mb_strtolower($identifier));
42 }
43
47 public function values($identifier)
48 {
49 return 'EXCLUDED.' . $this->quote($identifier);
50 }
51
55 public function getQueryDelimiter()
56 {
57 return ';';
58 }
59
63 public function forSql($value, $maxLength = 0)
64 {
65 if ($maxLength > 0)
66 {
67 $value = mb_substr($value, 0, $maxLength);
68 }
69
70 return pg_escape_string($this->connection->getResource(), $value);
71 }
72
76 public function convertToDbBinary($value)
77 {
78 return "'" . pg_escape_bytea($value) . "'";
79 //return "E'\\\\x".bin2hex($value) . "'";
80 //return "decode('".bin2hex($value)."', 'hex')";
81 }
82
86 public function convertToFullText($value, $maxLength = 0)
87 {
88 $fulltextLength = $maxLength ? min($maxLength, static::FULLTEXT_MAXIMUM_LENGTH): static::FULLTEXT_MAXIMUM_LENGTH;
89 return "safe_text_for_tsvector('" . $this->forSql($value, $fulltextLength) . "')";
90 }
91
96 {
97 return 'now()';
98 }
99
103 public function getCurrentDateFunction()
104 {
105 return 'current_date';
106 }
107
111 public function addSecondsToDateTime($seconds, $from = null)
112 {
113 if ($from === null)
114 {
115 $from = static::getCurrentDateTimeFunction();
116 }
117 else
118 {
119 $from = $from . "::timestamp";
120 }
121
122 return $from . " + cast(" . $seconds . "||' second' as interval)";
123 }
124
128 public function addDaysToDateTime($days, $from = null)
129 {
130 if ($from === null)
131 {
132 $from = static::getCurrentDateTimeFunction();
133 }
134 else
135 {
136 $from = $from . "::timestamp";
137 }
138
139 return '(' . $from . " + cast(" . $days . "||' day' as interval))";
140 }
141
145 public function getDatetimeToDateFunction($value)
146 {
147 return 'cast('.$value.' as date)';
148 }
149
153 public function formatDate($format, $field = null)
154 {
155 static $translation = [
156 'YYYY' => 'YYYY',
157 'MMMM' => 'FMMonth',
158 'MI' => 'MI',
159 'HH' => 'HH24',
160 'GG' => 'HH12',
161 'TT' => 'PM',
162 'M' => 'Mon',
163 'H' => 'HH12',
164 'G' => 'FMHH12',
165 'T' => 'PM',
166 'W' => 'D',
167 ];
168
169 $dbFormat = '';
170 foreach (preg_split('/(YYYY|MMMM|MM|MI|DD|HH|GG|SS|TT|M|H|G|T|W)/', $format, -1, PREG_SPLIT_DELIM_CAPTURE) as $part)
171 {
172 $dbFormat .= $translation[$part] ?? $part;
173 }
174
175 if ($field === null)
176 {
177 return $dbFormat;
178 }
179 else
180 {
181 return "to_char(".$field.", '".$dbFormat."')";
182 }
183 }
184
188 public function getRegexpOperator($field, $regexp)
189 {
190 return $field . ' ~ ' . $regexp;
191 }
192
196 public function getIlikeOperator($field, $value)
197 {
198 return $field . ' ILIKE ' . $value;
199 }
200
204 public function getConcatFunction()
205 {
206 return implode(" || ", func_get_args());
207 }
208
212 public function getRandomFunction()
213 {
214 return 'random()';
215 }
216
220 public function getSha1Function($field)
221 {
222 return "encode(digest(replace(" . $field . ", '\\', '\\\\')::bytea, 'sha1'), 'hex')";
223 }
224
228 public function getIsNullFunction($expression, $result)
229 {
230 return "COALESCE(".$expression.", ".$result.")";
231 }
232
236 public function getLengthFunction($field)
237 {
238 return "OCTET_LENGTH(".$field.")";
239 }
240
241 public function getMatchFunction($field, $value)
242 {
243 return "to_tsvector('english'::regconfig, " . $field . ") @@ to_tsquery('english'::regconfig, " . $value . ")";
244 }
245
246 public function getMatchAndExpression($values, $prefixSearch = false)
247 {
248 if ($prefixSearch)
249 {
250 foreach ($values as $i => $searchTerm)
251 {
252 $values[$i] = $searchTerm . ':*';
253 }
254 }
255 return implode(' & ', $values);
256 }
257
258 public function getMatchOrExpression($values, $prefixSearch = false)
259 {
260 if ($prefixSearch)
261 {
262 foreach ($values as $i => $searchTerm)
263 {
264 $values[$i] = $searchTerm . ':*';
265 }
266 }
267 return implode(' | ', $values);
268 }
269
273 public function getCharToDateFunction($value)
274 {
275 return "timestamp '".$value."'";
276 }
277
281 public function getDateToCharFunction($fieldName)
282 {
283 return "TO_CHAR(".$fieldName.", 'YYYY-MM-DD HH24:MI:SS')";
284 }
285
289 public function getConverter(ScalarField $field)
290 {
291 if($field instanceof ORM\Fields\DatetimeField)
292 {
293 return array($this, "convertFromDbDateTime");
294 }
295 elseif($field instanceof ORM\Fields\DateField)
296 {
297 return array($this, "convertFromDbDate");
298 }
299 else
300 {
301 return parent::getConverter($field);
302 }
303 }
304
308 public function convertFromDbDateTime($value)
309 {
310 if($value !== null && $value != '0000-00-00 00:00:00')
311 {
312 return new Type\DateTime($value, "Y-m-d H:i:s");
313 }
314
315 return null;
316 }
317
321 public function convertFromDbDate($value)
322 {
323 if($value !== null && $value != '0000-00-00')
324 {
325 return new Type\Date($value, "Y-m-d");
326 }
327
328 return null;
329 }
330
334 public function castToChar($fieldName)
335 {
336 return 'CAST('.$fieldName.' AS varchar)';
337 }
338
342 public function softCastTextToChar($fieldName)
343 {
344 return $fieldName;
345 }
346
350 public function getColumnTypeByField(ScalarField $field)
351 {
352 if ($field instanceof ORM\Fields\IntegerField)
353 {
354 switch ($field->getSize())
355 {
356 case 2:
357 return 'smallint';
358 case 4:
359 return 'integer';
360 case 8:
361 return 'bigint';
362 }
363 return 'integer';
364 }
365 elseif ($field instanceof ORM\Fields\DecimalField)
366 {
367 $defaultPrecision = 18;
368 $defaultScale = 2;
369
370 $precision = $field->getPrecision() > 0 ? $field->getPrecision() : $defaultPrecision;
371 $scale = $field->getScale() > 0 ? $field->getScale() : $defaultScale;
372
373 if ($scale >= $precision)
374 {
375 $precision = $defaultPrecision;
376 $scale = $defaultScale;
377 }
378
379 return "decimal($precision, $scale)";
380 }
381 elseif ($field instanceof ORM\Fields\FloatField)
382 {
383 return 'float8';
384 }
385 elseif ($field instanceof ORM\Fields\DatetimeField)
386 {
387 return 'timestamp';
388 }
389 elseif ($field instanceof ORM\Fields\DateField)
390 {
391 return 'date';
392 }
393 elseif ($field instanceof ORM\Fields\TextField)
394 {
395 return 'text';
396 }
397 elseif ($field instanceof ORM\Fields\BooleanField)
398 {
399 $values = $field->getValues();
400
401 if (preg_match('/^[0-9]+$/', $values[0]) && preg_match('/^[0-9]+$/', $values[1]))
402 {
403 return 'int';
404 }
405 else
406 {
407 $falseLen = mb_strlen($values[0]);
408 $trueLen = mb_strlen($values[1]);
409 if ($falseLen === 1 && $trueLen === 1)
410 {
411 return 'char(1)';
412 }
413 return 'varchar(' . max($falseLen, $trueLen) . ')';
414 }
415 }
416 elseif ($field instanceof ORM\Fields\EnumField)
417 {
418 return 'varchar('.max(array_map('mb_strlen', $field->getValues())).')';
419 }
420 else
421 {
422 // string by default
423 $defaultLength = false;
424 foreach ($field->getValidators() as $validator)
425 {
426 if ($validator instanceof ORM\Fields\Validators\LengthValidator)
427 {
428 if ($defaultLength === false || $defaultLength > $validator->getMax())
429 {
430 $defaultLength = $validator->getMax();
431 }
432 }
433 }
434 return 'varchar('.($defaultLength > 0? $defaultLength: 255).')';
435 }
436 }
437
441 public function getFieldByColumnType($name, $type, array $parameters = null)
442 {
443 switch ($type)
444 {
445 case 'bigint':
446 case 'int8':
447 case 'bigserial':
448 case 'serial8':
449 $field = (new ORM\Fields\IntegerField($name))->configureSize(8);
450 break;
451 case 'integer':
452 case 'int':
453 case 'int4':
454 case 'serial':
455 case 'serial4':
456 $field = (new ORM\Fields\IntegerField($name))->configureSize(4);
457 break;
458 case 'smallint':
459 case 'int2':
460 case 'smallserial':
461 case 'serial2':
462 $field = (new ORM\Fields\IntegerField($name))->configureSize(2);
463 break;
464 case 'double precision':
465 case 'float4':
466 case 'float8':
467 case 'numeric':
468 case 'decimal':
469 case 'real':
470 $field = new ORM\Fields\FloatField($name);
471 break;
472 case 'timestamp':
473 case 'timestamp without time zone':
474 case 'timestamptz':
475 case 'timestamp with time zone':
476 $field = new ORM\Fields\DatetimeField($name);
477 break;
478 case 'date':
479 $field = new ORM\Fields\DateField($name);
480 break;
481 case 'bytea':
482 $field = new ORM\Fields\StringField($name, ['binary' => true]);
483 break;
484 default:
485 $field = new ORM\Fields\StringField($name);
486 }
487
488 $field->setConnection($this->connection);
489
490 return $field;
491 }
492
496 public function getTopSql($sql, $limit, $offset = 0)
497 {
498 $offset = intval($offset);
499 $limit = intval($limit);
500
501 if ($offset > 0 && $limit <= 0)
502 {
503 throw new \Bitrix\Main\ArgumentException("Limit must be set if offset is set");
504 }
505
506 if ($limit > 0)
507 {
508 $sql .= "\nLIMIT ".$limit;
509 }
510
511 if ($offset > 0)
512 {
513 $sql .= " OFFSET ".$offset;
514 }
515
516 $sql .= "\n";
517
518 return $sql;
519 }
520
524 public function getInsertIgnore($tableName, $fields, $sql)
525 {
526 return 'INSERT INTO ' . $tableName . $fields . $sql . ' ON CONFLICT DO NOTHING';
527 }
528
532 public function getAscendingOrder()
533 {
534 return 'ASC NULLS FIRST';
535 }
536
540 public function getDescendingOrder()
541 {
542 return 'DESC NULLS LAST';
543 }
544
548 public function prepareMerge($tableName, array $primaryFields, array $insertFields, array $updateFields)
549 {
550 $insert = $this->prepareInsert($tableName, $insertFields);
551 $update = $this->prepareUpdate($tableName, $updateFields);
552
553 if (
554 !empty($insert[0]) && !empty($insert[1])
555 && !empty($update[0])
556 && $primaryFields
557 )
558 {
559 $sql = 'INSERT INTO ' . $this->quote($tableName) . ' ('.$insert[0].')
560 VALUES (' . $insert[1] . ')
561 ON CONFLICT (' . implode(',', array_map([$this, 'quote'], $primaryFields)) . ')
562 DO UPDATE SET ' . $update[0];
563 }
564 else
565 {
566 $sql = "";
567 }
568
569 return array(
570 $sql
571 );
572
573 }
574
578 public function prepareMergeMultiple($tableName, array $primaryFields, array $insertRows)
579 {
580 $result = [];
581 $head = '';
582 $tail = '';
583 $maxBodySize = 1024*1024; //1 Mb
584 $body = [];
585 $bodySize = 0;
586 foreach ($insertRows as $insertFields)
587 {
588 $insert = $this->prepareInsert($tableName, $insertFields, true);
589 if (!$head && $insert && $insert[0])
590 {
591 $head = 'INSERT INTO ' . $this->quote($tableName) . ' (' . implode(', ', $insert[0]) . ') VALUES ';
592 $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])) . ')';
593 }
594 if ($insert && $insert[1])
595 {
596 $values = '(' . implode(', ', $insert[1]) . ')';
597 $bodySize += mb_strlen($values) + 4;
598 $body[] = $values;
599 if ($bodySize > $maxBodySize)
600 {
601 $result[] = $head.implode(', ', $body).$tail;
602 $body = [];
603 $bodySize = 0;
604 }
605 }
606 }
607 if ($body)
608 {
609 $result[] = $head.implode(', ', $body).$tail;
610 }
611
612 return $result;
613 }
614
618 public function prepareMergeSelect($tableName, array $primaryFields, array $selectFields, $select, $updateFields)
619 {
620 $updateColumns = [];
621 $updateValues = [];
622
623 $tableFields = $this->connection->getTableFields($tableName);
624 // one registry
625 $tableFields = array_change_key_case($tableFields, CASE_UPPER);
626 $updateFields = array_change_key_case($updateFields, CASE_UPPER);
627 foreach ($updateFields as $columnName => $value)
628 {
629 if (isset($tableFields[$columnName]))
630 {
631 $updateColumns[] = $this->quote($columnName);
632 $updateValues[] = $this->convertToDb($value, $tableFields[$columnName]);
633 }
634 else
635 {
636 trigger_error("Column `{$columnName}` is not found in the `{$tableName}` table", E_USER_WARNING);
637 }
638 }
639
640 $sql = 'INSERT INTO ' . $this->quote($tableName) . ' (' . implode(',', array_map([$this, 'quote'], $selectFields)) . ') ';
641 $sql .= $select;
642 $sql .= ' ON CONFLICT (' . implode(',', array_map([$this, 'quote'], $primaryFields)) . ') DO UPDATE SET ';
643 if (count($updateColumns) === 1)
644 {
645 $sql .= $updateColumns[0] . ' = ' . $updateValues[0];
646 }
647 else
648 {
649 $sql .= ' (' . implode(', ', $updateColumns) . ') = (' . implode(', ', $updateValues) . ')';
650 }
651
652 return $sql;
653 }
654
658 public function prepareDeleteLimit($tableName, array $primaryFields, $where, array $order, $limit)
659 {
660 $primaryColumns = [];
661 foreach ($primaryFields as $columnName)
662 {
663 $primaryColumns[] = $this->quote($columnName);
664 }
665 $sqlPrimary = implode(', ', $primaryColumns);
666
667 $orderColumns = [];
668 foreach ($order as $columnName => $sort)
669 {
670 $orderColumns[] = $this->quote($columnName) . ' ' . $sort;
671 }
672 $sqlOrder = $orderColumns ? ' ORDER BY ' . implode(', ', $orderColumns) : '';
673 return 'DELETE FROM ' . $this->quote($tableName) . ' WHERE (' . $sqlPrimary . ') IN (SELECT ' . $sqlPrimary . ' FROM ' . $this->quote($tableName) . ' WHERE ' . $where . $sqlOrder . ' LIMIT ' . intval($limit) . ')';
674 }
675
676 public function initRowNumber($variableName)
677 {
678 return '';
679 }
680
681 public function getRowNumber($variableName)
682 {
683 return 'row_number() over()';
684 }
685
689 public function prepareCorrelatedUpdate($tableName, $tableAlias, $fields, $from, $where)
690 {
691 $dml = "UPDATE " . $tableName . ' AS ' . $tableAlias . " SET\n";
692
693 $set = '';
694 foreach ($fields as $fieldName => $fieldValue)
695 {
696 $set .= ($set ? ',' : '') . $fieldName . ' = ' .$fieldValue . "\n";
697 }
698 $dml .= $set;
699 $dml .= 'FROM ' . $from . "\n";
700 $dml .= 'WHERE ' . $where . "\n";
701
702 return $dml;
703 }
704
705 protected function getOrderByField(string $field, array $values, callable $callback, bool $quote = true): string
706 {
707 $field = $quote ? $this->quote($field) : $field;
708 $values = implode(',', array_map($callback, $values));
709
710 return "array_position(ARRAY[{$values}], {$field})";
711 }
712}
$type
Определения options.php:106
softCastTextToChar($fieldName)
Определения pgsqlsqlhelper.php:342
getOrderByField(string $field, array $values, callable $callback, bool $quote=true)
Определения pgsqlsqlhelper.php:705
prepareMergeMultiple($tableName, array $primaryFields, array $insertRows)
Определения pgsqlsqlhelper.php:578
convertToDbBinary($value)
Определения pgsqlsqlhelper.php:76
getMatchFunction($field, $value)
Определения pgsqlsqlhelper.php:241
getTopSql($sql, $limit, $offset=0)
Определения pgsqlsqlhelper.php:496
getIsNullFunction($expression, $result)
Определения pgsqlsqlhelper.php:228
getDateToCharFunction($fieldName)
Определения pgsqlsqlhelper.php:281
getIlikeOperator($field, $value)
Определения pgsqlsqlhelper.php:196
formatDate($format, $field=null)
Определения pgsqlsqlhelper.php:153
getRegexpOperator($field, $regexp)
Определения pgsqlsqlhelper.php:188
getDatetimeToDateFunction($value)
Определения pgsqlsqlhelper.php:145
prepareDeleteLimit($tableName, array $primaryFields, $where, array $order, $limit)
Определения pgsqlsqlhelper.php:658
const FULLTEXT_MAXIMUM_LENGTH
Определения pgsqlsqlhelper.php:11
castToChar($fieldName)
Определения pgsqlsqlhelper.php:334
addDaysToDateTime($days, $from=null)
Определения pgsqlsqlhelper.php:128
getFieldByColumnType($name, $type, array $parameters=null)
Определения pgsqlsqlhelper.php:441
getColumnTypeByField(ScalarField $field)
Определения pgsqlsqlhelper.php:350
initRowNumber($variableName)
Определения pgsqlsqlhelper.php:676
getConverter(ScalarField $field)
Определения pgsqlsqlhelper.php:289
prepareCorrelatedUpdate($tableName, $tableAlias, $fields, $from, $where)
Определения pgsqlsqlhelper.php:689
getSha1Function($field)
Определения pgsqlsqlhelper.php:220
getMatchAndExpression($values, $prefixSearch=false)
Определения pgsqlsqlhelper.php:246
getLengthFunction($field)
Определения pgsqlsqlhelper.php:236
getMatchOrExpression($values, $prefixSearch=false)
Определения pgsqlsqlhelper.php:258
forSql($value, $maxLength=0)
Определения pgsqlsqlhelper.php:63
convertToFullText($value, $maxLength=0)
Определения pgsqlsqlhelper.php:86
convertFromDbDateTime($value)
Определения pgsqlsqlhelper.php:308
addSecondsToDateTime($seconds, $from=null)
Определения pgsqlsqlhelper.php:111
convertFromDbDate($value)
Определения pgsqlsqlhelper.php:321
prepareMergeSelect($tableName, array $primaryFields, array $selectFields, $select, $updateFields)
Определения pgsqlsqlhelper.php:618
getCharToDateFunction($value)
Определения pgsqlsqlhelper.php:273
quote($identifier)
Определения pgsqlsqlhelper.php:39
values($identifier)
Определения pgsqlsqlhelper.php:47
getInsertIgnore($tableName, $fields, $sql)
Определения pgsqlsqlhelper.php:524
prepareMerge($tableName, array $primaryFields, array $insertFields, array $updateFields)
Определения pgsqlsqlhelper.php:548
getRowNumber($variableName)
Определения pgsqlsqlhelper.php:681
prepareUpdate($tableName, array $fields)
Определения sqlhelper.php:382
prepareInsert($tableName, array $fields, $returnAsArray=false)
Определения sqlhelper.php:342
convertToDb($value, ORM\Fields\IReadable $field=null)
Определения sqlhelper.php:461
getValidators()
Определения field.php:236
Определения date.php:9
$f
Определения component_props.php:52
</td ></tr ></table ></td ></tr >< tr >< td class="bx-popup-label bx-width30"><?=GetMessage("PAGE_NEW_TAGS")?> array( $site)
Определения file_new.php:804
$result
Определения get_property_values.php:14
$select
Определения iblock_catalog_list.php:194
$selectFields
Определения iblock_catalog_list.php:160
$name
Определения menu_edit.php:35
$order
Определения payment.php:8
if( $daysToExpire >=0 &&$daysToExpire< 60 elseif)( $daysToExpire< 0)
Определения prolog_main_admin.php:393
$i
Определения factura.php:643
</p ></td >< td valign=top style='border-top:none;border-left:none;border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt;padding:0cm 2.0pt 0cm 2.0pt;height:9.0pt'>< p class=Normal align=center style='margin:0cm;margin-bottom:.0001pt;text-align:center;line-height:normal'>< a name=ТекстовоеПоле54 ></a ><?=($taxRate > count( $arTaxList) > 0) ? $taxRate."%"
Определения waybill.php:936
$precision
Определения template.php:403
$fields
Определения yandex_run.php:501