• Модуль: main
  • Путь к файлу: ~/bitrix/modules/main/classes/general/sql_util.php
  • Класс: CSqlUtil
  • Вызов: CSqlUtil::PrepareSql
static function PrepareSql(&$arFields, $arOrder, $arFilter, $arGroupBy, $arSelectFields, $arOptions = array())
{
	global $DB;

	if(!is_array($arOptions))
	{
		$arOptions = array();
	}

	$strSqlSelect = '';
	$strSqlFrom = '';
	$strSqlFromWhere = '';
	$strSqlGroupBy = '';

	$arGroupByFunct = array("COUNT", "AVG", "MIN", "MAX", "SUM");

	$arAlreadyJoined = array();

	// GROUP BY -->
	if (is_array($arGroupBy) && !empty($arGroupBy))
	{
		$arSelectFields = $arGroupBy;
		foreach ($arGroupBy as $key => $val)
		{
			$val = mb_strtoupper($val);
			$key = mb_strtoupper($key);
			if (array_key_exists($val, $arFields) && !in_array($key, $arGroupByFunct))
			{
				if ($strSqlGroupBy <> '')
					$strSqlGroupBy .= ", ";
				$strSqlGroupBy .= $arFields[$val]["FIELD"];

				if (isset($arFields[$val]["FROM"])
					&& $arFields[$val]["FROM"] <> ''
					&& !in_array($arFields[$val]["FROM"], $arAlreadyJoined))
				{
					if ($strSqlFrom <> '')
						$strSqlFrom .= " ";
					$strSqlFrom .= $arFields[$val]["FROM"];
					$arAlreadyJoined[] = $arFields[$val]["FROM"];
				}
			}
		}
	}
	// <-- GROUP BY

	// SELECT -->
	$arFieldsKeys = array_keys($arFields);

	if (is_array($arGroupBy) && empty($arGroupBy))
	{
		$strSqlSelect = "COUNT(%%_DISTINCT_%% ".$arFields[$arFieldsKeys[0]]["FIELD"].") as CNT ";
	}
	else
	{
		if (isset($arSelectFields) && !is_array($arSelectFields) && is_string($arSelectFields) && $arSelectFields <> '' && array_key_exists($arSelectFields, $arFields))
			$arSelectFields = array($arSelectFields);

		if (!isset($arSelectFields)
			|| !is_array($arSelectFields)
			|| empty($arSelectFields))
		{
			self::PrepareDefaultFields($arFields, $arOrder, $arAlreadyJoined, $strSqlSelect, $strSqlFrom);
		}
		else
		{
			foreach ($arSelectFields as $key => $val)
			{
				if($val === '*')
				{
					self::PrepareDefaultFields($arFields, $arOrder, $arAlreadyJoined, $strSqlSelect, $strSqlFrom);
				}

				$val = mb_strtoupper($val);
				$key = mb_strtoupper($key);

				if (!array_key_exists($val, $arFields))
				{
					continue;
				}

				if (in_array($key, $arGroupByFunct))
				{
					if ($strSqlSelect <> '')
						$strSqlSelect .= ", ";

					$strSqlSelect .= $key."(".$arFields[$val]["FIELD"].") as ".$val;
				}
				else
				{
					self::AddToSelect($val, $arFields[$val], $arOrder, $strSqlSelect);
				}
				self::AddToFrom($arFields[$val], $arAlreadyJoined, $strSqlFrom);
			}
		}

		if($strSqlGroupBy === '')
		{
			$strSqlSelect = "%%_DISTINCT_%% ".$strSqlSelect;
		}
		elseif(!isset($arOptions['ENABLE_GROUPING_COUNT']) || $arOptions['ENABLE_GROUPING_COUNT'] === true)
		{
			if ($strSqlSelect <> '')
				$strSqlSelect .= ", ";
			$strSqlSelect .= "COUNT(%%_DISTINCT_%% ".$arFields[$arFieldsKeys[0]]["FIELD"].") as CNT";
		}
	}
	// <-- SELECT

	// WHERE -->
	$arJoins = array();
	$strSqlWhere = self::PrepareWhere($arFields, $arFilter, $arJoins);

	foreach($arJoins as $join)
	{
		if($join === '')
		{
			continue;
		}

		if ($strSqlFromWhere !== '')
		{
			$strSqlFromWhere .= ' ';
		}
		$strSqlFromWhere .= $join;

		if(!in_array($join, $arAlreadyJoined))
		{
			if ($strSqlFrom !== '')
			{
				$strSqlFrom .= ' ';
			}

			$strSqlFrom .= $join;
			$arAlreadyJoined[] = $join;
		}
	}
	// <-- WHERE

	// ORDER BY -->
	$arSqlOrder = array();
	$dbType = $DB->type;
	$nullsLast = isset($arOptions['NULLS_LAST']) ? (bool)$arOptions['NULLS_LAST'] : false;
	foreach ($arOrder as $by => $order)
	{
		$by = mb_strtoupper($by);
		$order = mb_strtoupper($order);

		if ($order != "ASC")
			$order = "DESC";

		if (array_key_exists($by, $arFields))
		{
			if(!$nullsLast)
			{
				if($dbType !== "ORACLE")
				{
					$arSqlOrder[] = $arFields[$by]["FIELD"]." ".$order;
				}
				else
				{
					if($order === 'ASC')
						$arSqlOrder[] = $arFields[$by]["FIELD"]." ".$order." NULLS FIRST";
					else
						$arSqlOrder[] = $arFields[$by]["FIELD"]." ".$order." NULLS LAST";
				}
			}
			else
			{
				if($dbType === "MYSQL")
				{
					//Use MySql feature for sort in 'NULLS_LAST' mode
					if($order === 'ASC')
						$arSqlOrder[] = "-".$arFields[$by]["FIELD"]." DESC";
					else
						$arSqlOrder[] = $arFields[$by]["FIELD"]." ".$order;
				}
			}

			if (isset($arFields[$by]["FROM"])
				&& $arFields[$by]["FROM"] <> ''
				&& !in_array($arFields[$by]["FROM"], $arAlreadyJoined))
			{
				if ($strSqlFrom <> '')
					$strSqlFrom .= " ";
				$strSqlFrom .= $arFields[$by]["FROM"];
				$arAlreadyJoined[] = $arFields[$by]["FROM"];
			}
		}
	}

	$strSqlOrderBy = '';
	DelDuplicateSort($arSqlOrder);
	$sqlOrderQty = count($arSqlOrder);
	for ($i = 0; $i < $sqlOrderQty; $i++)
	{
		if ($strSqlOrderBy <> '')
			$strSqlOrderBy .= ", ";

		$strSqlOrderBy .= $arSqlOrder[$i];
	}
	// <-- ORDER BY

	return array(
		"SELECT" => $strSqlSelect,
		"FROM" => $strSqlFrom,
		"WHERE" => $strSqlWhere,
		"FROM_WHERE" => $strSqlFromWhere,
		"GROUPBY" => $strSqlGroupBy,
		"ORDERBY" => $strSqlOrderBy
	);
}