【Laravel3.0.0源码阅读分析】SQLServer语法类

<?php namespace Laravel\Database\Query\Grammars;

use Laravel\Database\Query;

class SQLServer extends Grammar {

	/**
	 * The keyword identifier for the database system.
	 * 数据库系统的关键字标识符。
	 * @var string
	 */
	protected $wrapper = '[%s]';

	/**
	 * Compile a SQL SELECT statement from a Query instance.
	 * 从 Query 实例编译 SQL SELECT 语句。
	 * @param  Query   $query
	 * @return string
	 */
	public function select(Query $query)
	{
		$sql = parent::components($query);

		// SQL Server does not currently implement an "OFFSET" type keyword, so we
		// actually have to generate the ANSI standard SQL for doing offset like
		// functionality. In the next version of SQL Server, an OFFSET like
		// keyword is included for convenience.
        // SQL Server 目前没有实现“OFFSET”类型的关键字,因此我们实际上必须生成 ANSI 标准 SQL 来执行类似偏移的功能。
        // 在下一版本的 SQL Server 中,为方便起见,包含了一个类似 OFFSET 的关键字。
		if ($query->offset > 0)
		{
			return $this->ansi_offset($query, $sql);
		}

		// Once all of the clauses have been compiled, we can join them all as
		// one statement. Any segments that are null or an empty string will
		// be removed from the array of clauses before they are imploded.
        // 一旦编译了所有子句,我们就可以将它们全部连接为一个语句。 任何为 null 或空字符串的段都将在它们内爆之前从子句数组中删除。
		return $this->concatenate($sql);
	}

	/**
	 * Compile the SELECT clause for a query.
	 * 为查询编译 SELECT 子句。
	 * @param  Query   $query
	 * @return string
	 */
	protected function selects(Query $query)
	{
		if ( ! is_null($query->aggregate)) return;

		$select = ($query->distinct) ? 'SELECT DISTINCT ' : 'SELECT ';

		// Instead of using a "LIMIT" keyword, SQL Server uses the "TOP"
		// keyword within the SELECT statement. So, if we have a limit,
		// we will add it here.
		// SQL Server 不使用“LIMIT”关键字,而是在 SELECT 语句中使用“TOP”关键字。 所以,如果我们有一个限制,我们会在这里添加它。
		// We will not add the TOP clause if there is an offset however,
		// since we will have to handle offsets using the ANSI syntax
		// and will need to remove the TOP clause in that situation.
        // 但是,如果存在偏移,我们将不会添加 TOP 子句,因为我们必须使用 ANSI 语法处理偏移,并且在这种情况下需要删除 TOP 子句。
		if ($query->limit > 0 and $query->offset <= 0)
		{
			$select .= 'TOP '.$query->limit.' ';
		}

		return $select.$this->columnize($query->selects);
	}

	/**
	 * Generate the ANSI standard SQL for an offset clause.
	 * 为偏移子句生成 ANSI 标准 SQL。
	 * @param  Query  $query
	 * @param  array  $components
	 * @return array
	 */
	protected function ansi_offset(Query $query, $components)
	{
		// An ORDER BY clause is required to make this offset query
		// work, so if one doesn't exist, we'll just create a dummy
		// clause to satisfy the database.
        // 需要一个 ORDER BY 子句来使这个偏移查询工作,所以如果一个不存在,我们将只创建一个虚拟子句来满足数据库。
		if ( ! isset($components['orderings']))
		{
			$components['orderings'] = 'ORDER BY (SELECT 0)';
		}

		// We need to add the row number to the query results so we
		// can compare it against the offset and limit values given
		// for the statement. To do that we'll add an expression to
		// the select statement for the row number.
        // 我们需要将行号添加到查询结果中,以便我们可以将其与为语句给出的偏移量和限制值进行比较。
        // 为此,我们将为行号的 select 语句添加一个表达式。
		$orderings = $components['orderings'];

		$components['selects'] .= ", ROW_NUMBER() OVER ({$orderings}) AS RowNum";

		unset($components['orderings']);

		$start = $query->offset + 1;

		// Next we need to calculate the constraint that should be
		// placed on the row number to get the correct offset and
		// limit on the query. If a limit has not been set, we'll
		// only add a constraint to handle offset.
        // 接下来我们需要计算应该放在行号上的约束,以获得正确的偏移量和查询限制。 如果尚未设置限制,我们将只添加一个约束来处理偏移。
		if ($query->limit > 0)
		{
			$finish = $query->offset + $query->limit;

			$constraint = "BETWEEN {$start} AND {$finish}";
		}
		else
		{
			$constraint = ">= {$start}";
		}

		// Now, we're finally ready to build the final SQL query.
		// We'll create a common table expression with the query
		// and then select all of the results from it where the
		// row number is between oru given limit and offset.
        // 现在,我们终于准备好构建最终的 SQL 查询了。
        // 我们将使用查询创建一个公共表表达式,然后从中选择行号在 oru 给定限制和偏移量之间的所有结果。
		$sql = $this->concatenate($components);

		return "SELECT * FROM ($sql) AS TempTable WHERE RowNum {$constraint}";
	}

	/**
	 * Compile the LIMIT clause for a query.
	 * 为查询编译 LIMIT 子句。
	 * @param  Query   $query
	 * @return string
	 */
	protected function limit(Query $query)
	{
		return '';
	}

	/**
	 * Compile the OFFSET clause for a query.
	 * 为查询编译 OFFSET 子句。
	 * @param  Query   $query
	 * @return string
	 */
	protected function offset(Query $query)
	{
		return '';
	}

}

github地址: https://github.com/liu-shilong/laravel3-scr   

上一篇:# 小程序 | 原生实现左滑抽屉菜单


下一篇:mysql数据库(10)--limit与offset的用法