* @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) . ')'; } }