Skip to content

Commit

Permalink
Fix #17219: Fixed quoting of table names with spaces in MSSQL
Browse files Browse the repository at this point in the history
  • Loading branch information
alexkart authored and samdark committed Jul 19, 2019
1 parent 378f9ad commit 6fc04a6
Show file tree
Hide file tree
Showing 5 changed files with 77 additions and 13 deletions.
1 change: 1 addition & 0 deletions framework/CHANGELOG.md
Expand Up @@ -4,6 +4,7 @@ Yii Framework 2 Change Log
2.0.24 under development
------------------------

- Bug #17219: Fixed quoting of table names with spaces in MSSQL (alexkart)
- Bug #10020: Fixed quoting of column names with dots in MSSQL (alexkart)
- Bug #17424: Subdomain support for `User::loginRequired` (alex-code)

Expand Down
41 changes: 28 additions & 13 deletions framework/db/QueryBuilder.php
Expand Up @@ -270,11 +270,11 @@ public function build($query, $params = [])
* @param array $params the parameters to be bound to the generated SQL statement. These parameters will
* be included in the result with the additional parameters generated during the expression building process.
* @return string the SQL statement that will not be neither quoted nor encoded before passing to DBMS
* @see ExpressionInterface
* @throws InvalidArgumentException when $expression building is not supported by this QueryBuilder.
* @see ExpressionBuilderInterface
* @see expressionBuilders
* @since 2.0.14
* @throws InvalidArgumentException when $expression building is not supported by this QueryBuilder.
* @see ExpressionInterface
*/
public function buildExpression(ExpressionInterface $expression, &$params = [])
{
Expand All @@ -289,9 +289,9 @@ public function buildExpression(ExpressionInterface $expression, &$params = [])
*
* @param ExpressionInterface $expression
* @return ExpressionBuilderInterface
* @see expressionBuilders
* @since 2.0.14
* @throws InvalidArgumentException when $expression building is not supported by this QueryBuilder.
* @since 2.0.14
* @see expressionBuilders
*/
public function getExpressionBuilder(ExpressionInterface $expression)
{
Expand Down Expand Up @@ -488,7 +488,7 @@ public function batchInsert($table, $columns, $rows, &$params = [])
}

return 'INSERT INTO ' . $schema->quoteTableName($table)
. ' (' . implode(', ', $columns) . ') VALUES ' . implode(', ', $values);
. ' (' . implode(', ', $columns) . ') VALUES ' . implode(', ', $values);
}

/**
Expand Down Expand Up @@ -1136,7 +1136,7 @@ public function createView($viewName, $subQuery)
list($rawQuery, $params) = $this->build($subQuery);
array_walk(
$params,
function(&$param) {
function (&$param) {
$param = $this->db->quoteValue($param);
}
);
Expand Down Expand Up @@ -1298,7 +1298,7 @@ public function buildJoin($joins, &$params)
}
// 0:join type, 1:join table, 2:on-condition (optional)
list($joinType, $table) = $join;
$tables = $this->quoteTableNames((array) $table, $params);
$tables = $this->quoteTableNames((array)$table, $params);
$table = reset($tables);
$joins[$i] = "$joinType $table";
if (isset($join[2])) {
Expand Down Expand Up @@ -1331,8 +1331,8 @@ private function quoteTableNames($tables, &$params)
}
$tables[$i] = "$table " . $this->db->quoteTableName($i);
} elseif (strpos($table, '(') === false) {
if (preg_match('/^(.*?)(?i:\s+as|)\s+([^ ]+)$/', $table, $matches)) { // with alias
$tables[$i] = $this->db->quoteTableName($matches[1]) . ' ' . $this->db->quoteTableName($matches[2]);
if ($tableWithAlias = $this->extractAlias($table)) { // with alias
$tables[$i] = $this->db->quoteTableName($tableWithAlias[1]) . ' ' . $this->db->quoteTableName($tableWithAlias[2]);
} else {
$tables[$i] = $this->db->quoteTableName($table);
}
Expand Down Expand Up @@ -1454,7 +1454,7 @@ public function buildLimit($limit, $offset)
*/
protected function hasLimit($limit)
{
return ($limit instanceof ExpressionInterface) || ctype_digit((string) $limit);
return ($limit instanceof ExpressionInterface) || ctype_digit((string)$limit);
}

/**
Expand All @@ -1464,7 +1464,7 @@ protected function hasLimit($limit)
*/
protected function hasOffset($offset)
{
return ($offset instanceof ExpressionInterface) || ctype_digit((string) $offset) && (string) $offset !== '0';
return ($offset instanceof ExpressionInterface) || ctype_digit((string)$offset) && (string)$offset !== '0';
}

/**
Expand Down Expand Up @@ -1543,7 +1543,7 @@ public function buildCondition($condition, &$params)
return $this->buildExpression($condition, $params);
}

return (string) $condition;
return (string)$condition;
}

/**
Expand All @@ -1552,8 +1552,8 @@ public function buildCondition($condition, &$params)
* [[conditionClasses]] map.
*
* @param string|array $condition
* @see conditionClasses
* @return ConditionInterface
* @see conditionClasses
* @since 2.0.14
*/
public function createConditionFromArray($condition)
Expand Down Expand Up @@ -1733,4 +1733,19 @@ public function bindParam($value, &$params)

return $phName;
}

/**
* Extracts table alias if there is one or returns false
* @param $table
* @return bool|array
* @since 2.0.24
*/
protected function extractAlias($table)
{
if (preg_match('/^(.*?)(?i:\s+as|)\s+([^ ]+)$/', $table, $matches)) {
return $matches;
}

return false;
}
}
12 changes: 12 additions & 0 deletions framework/db/mssql/QueryBuilder.php
Expand Up @@ -429,4 +429,16 @@ public function getColumnType($type)

return $columnType;
}

/**
* {@inheritdoc}
*/
protected function extractAlias($table)
{
if (preg_match('/^\[.*\]$/', $table)) {
return false;
}

return parent::extractAlias($table);
}
}
23 changes: 23 additions & 0 deletions tests/framework/db/QueryBuilderTest.php
Expand Up @@ -1291,6 +1291,29 @@ public function filterConditionProvider()
return $conditions;
}

/**
* @dataProvider buildFromDataProvider
* @param $table
* @param $expected
* @throws \Exception
*/
public function testBuildFrom($table, $expected)
{
$params = [];
$sql = $this->getQueryBuilder()->buildFrom([$table], $params);
$this->assertEquals('FROM ' . $this->replaceQuotes($expected), $sql);
}

public function buildFromDataProvider()
{
return [
['test t1', '[[test]] [[t1]]'],
['test as t1', '[[test]] [[t1]]'],
['test AS t1', '[[test]] [[t1]]'],
['test', '[[test]]'],
];
}

/**
* @dataProvider conditionProvider
* @param array $condition
Expand Down
13 changes: 13 additions & 0 deletions tests/framework/db/mssql/QueryBuilderTest.php
Expand Up @@ -196,4 +196,17 @@ public function conditionProvider()

return $data;
}

public function buildFromDataProvider()
{
$data = parent::buildFromDataProvider();
$data[] = ['[test]', '[[test]]'];
$data[] = ['[test] [t1]', '[[test]] [[t1]]'];
$data[] = ['[table.name]', '[[table.name]]'];
$data[] = ['[table.name.with.dots]', '[[table.name.with.dots]]'];
$data[] = ['[table name]', '[[table name]]'];
$data[] = ['[table name with spaces]', '[[table name with spaces]]'];

return $data;
}
}

0 comments on commit 6fc04a6

Please sign in to comment.