Skip to content

Commit

Permalink
[5.4] Can't Wrap DB Names Containing Spaces When Aliasing (#17312)
Browse files Browse the repository at this point in the history
* Can't Wrap DB Names Containing Spaces When Aliasing

Database names containing spaces are perfectly legal in Microsoft SQL Server.

Currently, when using SQL Server, if you have a database which includes spaces, the grammar handles wrapping it fine.

So this:

My Sample Database.dbo.my_table.my_column

Correctly becomes:

[My Sample Database].[dbo].[my_table].[my_column]

*But* if you also try to alias a column when the database contains spaces, it breaks.

This:

My Sample Database.dbo.my_table.my_column AS my_aliased_column

Becomes:

[My] AS [Sample]

I have traced the error to Database/Grammar/wrapAliasedValue() using explode( ' ' ) - the code thinks the spaces in the database name are the spaces around the "AS".

We can fix this by using regex instead of explode, splitting on the "AS" more accurately.

Just replace the explode with this:

$segments = preg_split( '/\s+as\s+/i', $value );

Note: When you have an Eloquent belongsToMany method that has to include the database name (eg. we need to join across DBs), this type of alias is created automatically, generating this error.

I originally committed this to 5.3 (#17292) and was asked to commit here instead.

* Adding Tests

RE: #17312
  • Loading branch information
voidstate authored and taylorotwell committed Jan 16, 2017
1 parent abe47a8 commit 5a9e55e
Show file tree
Hide file tree
Showing 2 changed files with 10 additions and 3 deletions.
6 changes: 3 additions & 3 deletions src/Illuminate/Database/Grammar.php
Original file line number Diff line number Diff line change
Expand Up @@ -71,17 +71,17 @@ public function wrap($value, $prefixAlias = false)
*/
protected function wrapAliasedValue($value, $prefixAlias = false)
{
$segments = explode(' ', $value);
$segments = preg_split( '/\s+as\s+/i', $value );

// If we are wrapping a table we need to prefix the alias with the table prefix
// as well in order to generate proper syntax. If this is a column of course
// no prefix is necessary. The condition will be true when from wrapTable.
if ($prefixAlias) {
$segments[2] = $this->tablePrefix.$segments[2];
$segments[1] = $this->tablePrefix.$segments[1];
}

return $this->wrap(
$segments[0]).' as '.$this->wrapValue($segments[2]
$segments[0]).' as '.$this->wrapValue($segments[1]
);
}

Expand Down
7 changes: 7 additions & 0 deletions tests/Database/DatabaseQueryBuilderTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,13 @@ public function testAliasWrappingAsWholeConstant()
$builder->select('x.y as foo.bar')->from('baz');
$this->assertEquals('select "x"."y" as "foo.bar" from "baz"', $builder->toSql());
}

public function testAliasWrappingWithSpacesInDatabaseName()
{
$builder = $this->getBuilder();
$builder->select('w x.y.z as foo.bar')->from('baz');
$this->assertEquals('select "w x"."y"."z" as "foo.bar" from "baz"', $builder->toSql());
}

public function testAddingSelects()
{
Expand Down

0 comments on commit 5a9e55e

Please sign in to comment.