You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

123 lines
3.4 KiB

<?php
/**
* @link http://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
namespace yii\sphinx;
use yii\db\Expression;
/**
* Class QueryBuilder
*
* @author Paul Klimov <klimov.paul@gmail.com>
* @since 2.0
*/
class QueryBuilder extends \yii\db\mysql\QueryBuilder
{
/**
* Generates a SELECT SQL statement from a [[Query]] object.
* @param Query $query the [[Query]] object from which the SQL statement will be generated
* @return array the generated SQL statement (the first array element) and the corresponding
* parameters to be bound to the SQL statement (the second array element).
*/
public function build($query)
{
$params = $query->params;
$clauses = [
$this->buildSelect($query->select, $query->distinct, $query->selectOption),
$this->buildFrom($query->from),
$this->buildWhere($query->where, $params),
$this->buildGroupBy($query->groupBy),
$this->buildWithin($query->within),
$this->buildOrderBy($query->orderBy),
$this->buildLimit($query->limit, $query->offset),
$this->buildOption($query->options),
];
return [implode($this->separator, array_filter($clauses)), $params];
}
/**
* @param array $columns
* @return string the ORDER BY clause built from [[query]].
*/
public function buildWithin($columns)
{
if (empty($columns)) {
return '';
}
$orders = [];
foreach ($columns as $name => $direction) {
if (is_object($direction)) {
$orders[] = (string)$direction;
} else {
$orders[] = $this->db->quoteColumnName($name) . ($direction === Query::SORT_DESC ? ' DESC' : '');
}
}
return 'WITHIN GROUP ORDER BY ' . implode(', ', $orders);
}
/**
* @param array $options
* @return string the OPTION clause build from [[query]]
*/
public function buildOption(array $options)
{
if (empty($options)) {
return '';
}
$optionLines = [];
foreach ($options as $name => $value) {
$optionLines[] = $name . ' = ' . $value;
}
return 'OPTION ' . implode(', ', $optionLines);
}
/**
* Creates an INSERT SQL statement.
* For example,
*
* ~~~
* $sql = $queryBuilder->insert('tbl_user', [
* 'name' => 'Sam',
* 'age' => 30,
* ], $params);
* ~~~
*
* The method will properly escape the table and column names.
*
* @param string $table the table that new rows will be inserted into.
* @param array $columns the column data (name => value) to be inserted into the table.
* @param array $params the binding parameters that will be generated by this method.
* They should be bound to the DB command later.
* @return string the INSERT SQL
*/
public function insert($table, $columns, &$params)
{
if (($tableSchema = $this->db->getTableSchema($table)) !== null) {
$columnSchemas = $tableSchema->columns;
} else {
$columnSchemas = [];
}
$names = [];
$placeholders = [];
foreach ($columns as $name => $value) {
$names[] = $this->db->quoteColumnName($name);
if ($value instanceof Expression) {
$placeholders[] = $value->expression;
foreach ($value->params as $n => $v) {
$params[$n] = $v;
}
} else {
$phName = self::PARAM_PREFIX . count($params);
$placeholders[] = $phName;
$params[$phName] = !is_array($value) && isset($columnSchemas[$name]) ? $columnSchemas[$name]->typecast($value) : $value;
}
}
return 'INSERT INTO ' . $this->db->quoteTableName($table)
. ' (' . implode(', ', $names) . ') VALUES ('
. implode(', ', $placeholders) . ')';
}
}