Your IP : 3.145.12.145


Current Path : /var/www/www-root/data/webdav/www/monolith-realty.ru/bitrix/modules/main/lib/db/
Upload File :
Current File : /var/www/www-root/data/webdav/www/monolith-realty.ru/bitrix/modules/main/lib/db/mysqlisqlhelper.php

<?php

/**
 * Bitrix Framework
 * @package bitrix
 * @subpackage main
 * @copyright 2001-2023 Bitrix
 */

namespace Bitrix\Main\DB;

use Bitrix\Main\Type;
use Bitrix\Main\ORM;
use Bitrix\Main\ORM\Fields\ScalarField;

/**
 * @property MysqliConnection $connection
 */
class MysqliSqlHelper extends SqlHelper
{
	/**
	 * @inheritdoc
	 */
	public function getLeftQuote()
	{
		return '`';
	}

	/**
	 * @inheritdoc
	 */
	public function getRightQuote()
	{
		return '`';
	}

	/**
	 * @inheritdoc
	 */
	public function getAliasLength()
	{
		return 256;
	}

	/**
	 * @inheritdoc
	 */
	public function getQueryDelimiter()
	{
		return ';';
	}

	/**
	 * @inheritdoc
	 */
	public function getCurrentDateTimeFunction()
	{
		return "NOW()";
	}

	/**
	 * @inheritdoc
	 */
	public function getCurrentDateFunction()
	{
		return "CURDATE()";
	}

	/**
	 * @inheritdoc
	 */
	public function addSecondsToDateTime($seconds, $from = null)
	{
		if ($from === null)
		{
			$from = static::getCurrentDateTimeFunction();
		}

		return 'DATE_ADD('.$from.', INTERVAL '.$seconds.' SECOND)';
	}

	/**
	 * @inheritdoc
	 */
	public function addDaysToDateTime($days, $from = null)
	{
		if ($from === null)
		{
			$from = static::getCurrentDateTimeFunction();
		}

		return 'DATE_ADD('.$from.', INTERVAL '.$days.' DAY)';
	}

	/**
	 * @inheritdoc
	 */
	public function getDatetimeToDateFunction($value)
	{
		return 'DATE('.$value.')';
	}

	/**
	 * @inheritdoc
	 */
	public function formatDate($format, $field = null)
	{
		static $search  = array(
			"YYYY",
			"MMMM",
			"MM",
			"MI",
			"DD",
			"HH",
			"GG",
			"G",
			"SS",
			"TT",
			"T",
			"W",
		);
		static $replace = array(
			"%Y",
			"%M",
			"%m",
			"%i",
			"%d",
			"%H",
			"%h",
			"%l",
			"%s",
			"%p",
			"%p",
			"%w",
		);

		$format = str_replace($search, $replace, $format);

		if (!str_contains($format, '%H'))
		{
			$format = str_replace("H", "%h", $format);
		}

		if (!str_contains($format, '%M'))
		{
			$format = str_replace("M", "%b", $format);
		}

		if($field === null)
		{
			return $format;
		}
		else
		{
			return "DATE_FORMAT(".$field.", '".$format."')";
		}
	}

	/**
	 * @inheritdoc
	 */
	public function getConcatFunction()
	{
		$str = implode(", ", func_get_args());
		if ($str != '')
		{
			$str = "CONCAT(".$str.")";
		}
		return $str;
	}

	/**
	 * @inheritdoc
	 */
	public function getIsNullFunction($expression, $result)
	{
		return "IFNULL(".$expression.", ".$result.")";
	}

	/**
	 * @inheritdoc
	 */
	public function getLengthFunction($field)
	{
		return "LENGTH(".$field.")";
	}

	/**
	 * @inheritdoc
	 */
	public function getCharToDateFunction($value)
	{
		return "'".$value."'";
	}

	/**
	 * @inheritdoc
	 */
	public function getDateToCharFunction($fieldName)
	{
		return $fieldName;
	}

	/**
	 * @inheritdoc
	 */
	public function getConverter(ScalarField $field)
	{
		if($field instanceof ORM\Fields\DatetimeField)
		{
			return array($this, "convertFromDbDateTime");
		}
		elseif($field instanceof ORM\Fields\DateField)
		{
			return array($this, "convertFromDbDate");
		}
		else
		{
			return parent::getConverter($field);
		}
	}

	/**
	 * @inheritdoc
	 */
	public function convertFromDbDateTime($value)
	{
		if($value !== null && $value != '0000-00-00 00:00:00')
		{
			return new Type\DateTime($value, "Y-m-d H:i:s");
		}

		return null;
	}

	/**
	 * @inheritdoc
	 */
	public function convertFromDbDate($value)
	{
		if($value !== null && $value != '0000-00-00')
		{
			return new Type\Date($value, "Y-m-d");
		}

		return null;
	}

	/**
	 * @inheritdoc
	 */
	public function castToChar($fieldName)
	{
		return 'CAST('.$fieldName.' AS char)';
	}

	/**
	 * @inheritdoc
	 */
	public function softCastTextToChar($fieldName)
	{
		return $fieldName;
	}

	/**
	 * @inheritdoc
	 */
	public function getColumnTypeByField(ScalarField $field)
	{
		if ($field instanceof ORM\Fields\IntegerField)
		{
			switch ($field->getSize())
			{
				case 2:
					return 'smallint';
				case 4:
					return 'int';
				case 8:
					return 'bigint';
			}
			return 'int';
		}
		elseif ($field instanceof ORM\Fields\DecimalField)
		{
			$defaultPrecision = 18;
			$defaultScale = 2;

			$precision = $field->getPrecision() > 0 ? $field->getPrecision() : $defaultPrecision;
			$scale = $field->getScale() > 0 ? $field->getScale() : $defaultScale;

			if ($scale >= $precision)
			{
				$precision = $defaultPrecision;
				$scale = $defaultScale;
			}

			return "decimal($precision, $scale)";
		}
		elseif ($field instanceof ORM\Fields\FloatField)
		{
			return 'double';
		}
		elseif ($field instanceof ORM\Fields\DatetimeField)
		{
			return 'datetime';
		}
		elseif ($field instanceof ORM\Fields\DateField)
		{
			return 'date';
		}
		elseif ($field instanceof ORM\Fields\TextField)
		{
			return $field->isLong() ? 'longtext' : 'text';
		}
		elseif ($field instanceof ORM\Fields\BooleanField)
		{
			$values = $field->getValues();

			if (preg_match('/^[0-9]+$/', $values[0]) && preg_match('/^[0-9]+$/', $values[1]))
			{
				return 'int';
			}
			else
			{
				return 'varchar('.max(mb_strlen($values[0]), mb_strlen($values[1])).')';
			}
		}
		elseif ($field instanceof ORM\Fields\EnumField)
		{
			return 'varchar('.max(array_map('strlen', $field->getValues())).')';
		}
		else
		{
			// string by default
			$defaultLength = false;
			foreach ($field->getValidators() as $validator)
			{
				if ($validator instanceof ORM\Fields\Validators\LengthValidator)
				{
					if ($defaultLength === false || $defaultLength > $validator->getMax())
					{
						$defaultLength = $validator->getMax();
					}
				}
			}
			return 'varchar('.($defaultLength > 0? $defaultLength: 255).')';
		}
	}

	/**
	 * @inheritdoc
	 */
	public function getTopSql($sql, $limit, $offset = 0)
	{
		$offset = intval($offset);
		$limit = intval($limit);

		if ($offset > 0 && $limit <= 0)
			throw new \Bitrix\Main\ArgumentException("Limit must be set if offset is set");

		if ($limit > 0)
		{
			$sql .= "\nLIMIT ".$offset.", ".$limit."\n";
		}

		return $sql;
	}

	/**
	 * @inheritdoc
	 */
	public function prepareMerge($tableName, array $primaryFields, array $insertFields, array $updateFields)
	{
		$insert = $this->prepareInsert($tableName, $insertFields);
		$update = $this->prepareUpdate($tableName, $updateFields);

		if (
			$insert && $insert[0] != "" && $insert[1] != ""
			&& $update && $update[1] != ""
		)
		{
			$sql = "
				INSERT INTO ".$this->quote($tableName)." (".$insert[0].")
				VALUES (".$insert[1].")
				ON DUPLICATE KEY UPDATE ".$update[0]."
			";
		}
		else
		{
			$sql = "";
		}

		return array(
			$sql
		);
	}

	/**
	 * @inheritdoc
	 */
	public function forSql($value, $maxLength = 0)
	{
		if ($maxLength > 0)
			$value = mb_substr($value, 0, $maxLength);

		$con = $this->connection->getResource();

		return $con->real_escape_string($value);
	}

	/**
	 * @inheritdoc
	 */
	public function getFieldByColumnType($name, $type, array $parameters = null)
	{
		switch($type)
		{
			case MYSQLI_TYPE_TINY:
			case MYSQLI_TYPE_SHORT:
				$field = (new ORM\Fields\IntegerField($name))->configureSize(2);
				break;
			case MYSQLI_TYPE_LONG:
			case MYSQLI_TYPE_INT24:
			case MYSQLI_TYPE_CHAR:
				$field = (new ORM\Fields\IntegerField($name))->configureSize(4);
				break;
			case MYSQLI_TYPE_LONGLONG:
				$field = ((new ORM\Fields\IntegerField($name)))->configureSize(8);
				break;
			case MYSQLI_TYPE_DECIMAL:
			case MYSQLI_TYPE_NEWDECIMAL:
			case MYSQLI_TYPE_FLOAT:
			case MYSQLI_TYPE_DOUBLE:
				$field = new ORM\Fields\FloatField($name);
				break;
			case MYSQLI_TYPE_DATETIME:
			case MYSQLI_TYPE_TIMESTAMP:
				$field = new ORM\Fields\DatetimeField($name);
				break;
			case MYSQLI_TYPE_DATE:
			case MYSQLI_TYPE_NEWDATE:
				$field = new ORM\Fields\DateField($name);
				break;
			default:
				$field = new ORM\Fields\StringField($name);
		}
		//MYSQLI_TYPE_BIT
		//MYSQLI_TYPE_TIME
		//MYSQLI_TYPE_YEAR
		//MYSQLI_TYPE_INTERVAL
		//MYSQLI_TYPE_ENUM
		//MYSQLI_TYPE_SET
		//MYSQLI_TYPE_TINY_BLOB
		//MYSQLI_TYPE_MEDIUM_BLOB
		//MYSQLI_TYPE_LONG_BLOB
		//MYSQLI_TYPE_BLOB
		//MYSQLI_TYPE_VAR_STRING
		//MYSQLI_TYPE_STRING
		//MYSQLI_TYPE_GEOMETRY

		$field->setConnection($this->connection);

		return $field;
	}

	/**
	 * @inheritdoc
	 */
	public function getInsertIgnore($tableName, $fields, $sql)
	{
		return 'INSERT IGNORE INTO ' . $tableName . $fields . $sql;
	}

	/**
	 * @inheritdoc
	 */
	public function getRegexpOperator($field, $regexp)
	{
		return $field . ' regexp ' . $regexp;
	}

	/**
	 * @inheritdoc
	 */
	public function values($identifier)
	{
		return 'VALUES(' . $this->quote($identifier) . ')';
	}

	public function getMatchFunction($field, $value)
	{
		return "MATCH (" . $field . ") AGAINST (" . $value . " IN BOOLEAN MODE)";
	}

	public function getMatchAndExpression($values, $prefixSearch = false)
	{
		if ($prefixSearch)
		{
			foreach ($values as $i => $searchTerm)
			{
				$values[$i] = $searchTerm . '*';
			}
		}
		return '+' . implode(' +', $values);
	}

	public function getMatchOrExpression($values, $prefixSearch = false)
	{
		if ($prefixSearch)
		{
			foreach ($values as $i => $searchTerm)
			{
				$values[$i] = $searchTerm . '*';
			}
		}
		return implode(' ', $values);
	}

	/**
	 * @inheritdoc
	 */
	public function prepareMergeMultiple($tableName, array $primaryFields, array $insertRows)
	{
		$result = [];
		$head = '';
		$maxBodySize = 1024*1024; //1 Mb
		$body = [];
		$bodySize = 0;
		foreach ($insertRows as $insertFields)
		{
			$insert = $this->prepareInsert($tableName, $insertFields);
			if (!$head && $insert && $insert[0])
			{
				$head = 'REPLACE INTO ' . $this->quote($tableName) . ' (' . $insert[0] . ') VALUES ';
			}
			if ($insert && $insert[1])
			{
				$values = '(' . $insert[1] . ')';
				$bodySize += mb_strlen($values) + 4;
				$body[] = $values;
				if ($bodySize > $maxBodySize)
				{
					$result[] = $head.implode(', ', $body);
					$body = [];
					$bodySize = 0;
				}
			}
		}
		if ($body)
		{
			$result[] = $head.implode(', ', $body);
		}

		return $result;
	}

	/**
	 * @inheritdoc
	 */
	public function prepareMergeSelect($tableName, array $primaryFields, array $selectFields, $select, $updateFields)
	{
		$update = [];

		$tableFields = $this->connection->getTableFields($tableName);
		// one registry
		$tableFields = array_change_key_case($tableFields, CASE_UPPER);
		$updateFields = array_change_key_case($updateFields, CASE_UPPER);
		foreach ($updateFields as $columnName => $value)
		{
			if (isset($tableFields[$columnName]))
			{
				$update[] = $this->quote($columnName) . ' = '. $this->convertToDb($value, $tableFields[$columnName]);
			}
			else
			{
				trigger_error("Column `{$columnName}` is not found in the `{$tableName}` table", E_USER_WARNING);
			}
		}

		$sql = 'INSERT INTO ' . $this->quote($tableName) . ' (' . implode(',', array_map([$this, 'quote'], $selectFields)) . ') ';
		$sql .= $select;
		$sql .= ' ON DUPLICATE KEY UPDATE ' . implode(',', $update);

		return $sql;
	}

	/**
	 * @inheritdoc
	 */
	public function prepareDeleteLimit($tableName, array $primaryFields, $where, array $order, $limit)
	{
		$orderColumns = [];
		foreach ($order as $columnName => $sort)
		{
			$orderColumns[] = $this->quote($columnName) . ' ' . $sort;
		}
		$sqlOrder = $orderColumns ? ' ORDER BY ' . implode(', ', $orderColumns) : '';
		return 'DELETE FROM ' . $this->quote($tableName) . ' WHERE ' . $where . $sqlOrder . ' LIMIT ' . intval($limit);
	}

	public function initRowNumber($variableName)
	{
		return 'set @' . $variableName . ' = 0';
	}

	public function getRowNumber($variableName)
	{
		return '@' . $variableName . ':=' . '@' . $variableName . ' + 1';
	}

	/**
	 * @inheritdoc
	 */
	public function prepareCorrelatedUpdate($tableName, $tableAlias, $fields, $from, $where)
	{
		$dml = "UPDATE " . $tableName . ' AS ' . $tableAlias . ",\n";
		$dml .= $from . "\n";

		$set = '';
		foreach ($fields as $fieldName => $fieldValue)
		{
			$set .= ($set ? ',' : '') . $tableAlias . '.' . $fieldName . ' = ' .$fieldValue . "\n";
		}
		$dml .= 'SET ' . $set;
		$dml .= 'WHERE ' . $where . "\n";

		return $dml;
	}

	protected function getOrderByField(string $field, array $values, callable $callback, bool $quote = true): string
	{
		$field = $quote ? $this->quote($field) : $field;
		$values = implode(',', array_map($callback, $values));

		return "FIELD({$field}, {$values})";
	}
}