mirror of
https://github.com/silverstripe/silverstripe-postgresql
synced 2024-10-22 17:05:45 +02:00
API Ensure table aliases longer than max characters are safely re-written
This commit is contained in:
parent
512f10d745
commit
e941f0b122
@ -3,7 +3,6 @@ language: php
|
|||||||
sudo: false
|
sudo: false
|
||||||
|
|
||||||
php:
|
php:
|
||||||
- 5.5
|
|
||||||
- 5.6
|
- 5.6
|
||||||
|
|
||||||
env:
|
env:
|
||||||
|
@ -2,12 +2,20 @@
|
|||||||
|
|
||||||
namespace SilverStripe\PostgreSQL;
|
namespace SilverStripe\PostgreSQL;
|
||||||
|
|
||||||
|
use SilverStripe\ORM\Queries\SQLConditionalExpression;
|
||||||
|
use SilverStripe\ORM\Queries\SQLExpression;
|
||||||
use SilverStripe\ORM\Queries\SQLSelect;
|
use SilverStripe\ORM\Queries\SQLSelect;
|
||||||
use SilverStripe\ORM\Connect\DBQueryBuilder;
|
use SilverStripe\ORM\Connect\DBQueryBuilder;
|
||||||
use InvalidArgumentException;
|
use InvalidArgumentException;
|
||||||
|
|
||||||
class PostgreSQLQueryBuilder extends DBQueryBuilder
|
class PostgreSQLQueryBuilder extends DBQueryBuilder
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* Max table length.
|
||||||
|
* Aliases longer than this will be re-written
|
||||||
|
*/
|
||||||
|
const MAX_TABLE = 63;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the LIMIT clause ready for inserting into a query.
|
* Return the LIMIT clause ready for inserting into a query.
|
||||||
*
|
*
|
||||||
@ -47,4 +55,53 @@ class PostgreSQLQueryBuilder extends DBQueryBuilder
|
|||||||
}
|
}
|
||||||
return $clause;
|
return $clause;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function buildSQL(SQLExpression $query, &$parameters)
|
||||||
|
{
|
||||||
|
$sql = parent::buildSQL($query, $parameters);
|
||||||
|
return $this->rewriteLongIdentifiers($query, $sql);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find and generate table aliases necessary in the given query
|
||||||
|
*
|
||||||
|
* @param SQLConditionalExpression $query
|
||||||
|
* @return array List of replacements
|
||||||
|
*/
|
||||||
|
protected function findRewrites(SQLConditionalExpression $query)
|
||||||
|
{
|
||||||
|
$rewrites = [];
|
||||||
|
foreach ($query->getFrom() as $alias => $from) {
|
||||||
|
$table = is_array($from) ? $from['table'] : $from;
|
||||||
|
if ($alias === $table || "\"{$alias}\"" === $table) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// Don't complain about aliases shorter than max length
|
||||||
|
if (strlen($alias) <= self::MAX_TABLE) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$replacement = substr(sha1($alias), 0, 7) . '_' . substr($alias, 8 - self::MAX_TABLE);
|
||||||
|
$rewrites["\"{$alias}\""] = "\"{$replacement}\"";
|
||||||
|
}
|
||||||
|
return $rewrites;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Rewrite all ` AS "Identifier"` with strlen(Identifier) > 63
|
||||||
|
*
|
||||||
|
* @param SQLExpression $query
|
||||||
|
* @param string $sql
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
protected function rewriteLongIdentifiers(SQLExpression $query, $sql)
|
||||||
|
{
|
||||||
|
// Check if this query has aliases
|
||||||
|
if ($query instanceof SQLConditionalExpression) {
|
||||||
|
$rewrites = $this->findRewrites($query);
|
||||||
|
if ($rewrites) {
|
||||||
|
return str_replace(array_keys($rewrites), array_values($rewrites), $sql);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $sql;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
41
tests/PostgreSQLQueryBuilderTest.php
Normal file
41
tests/PostgreSQLQueryBuilderTest.php
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
|
||||||
|
use SilverStripe\Dev\SapphireTest;
|
||||||
|
use SilverStripe\ORM\Queries\SQLSelect;
|
||||||
|
use SilverStripe\PostgreSQL\PostgreSQLQueryBuilder;
|
||||||
|
|
||||||
|
class PostgreSQLQueryBuilderTest extends SapphireTest
|
||||||
|
{
|
||||||
|
public function testLongAliases()
|
||||||
|
{
|
||||||
|
$query = new SQLSelect();
|
||||||
|
$longstring = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
|
||||||
|
$alias2 = $longstring . $longstring;
|
||||||
|
$query->selectField('*');
|
||||||
|
$query->addFrom('"Base"');
|
||||||
|
$query->addLeftJoin(
|
||||||
|
'Joined',
|
||||||
|
"\"Base\".\"ID\" = \"{$alias2}\".\"ID\"",
|
||||||
|
$alias2
|
||||||
|
);
|
||||||
|
$query->addWhere([
|
||||||
|
"\"{$alias2}\".\"Title\" = ?" => 'Value',
|
||||||
|
]);
|
||||||
|
|
||||||
|
$identifier = "c4afb43_hijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
|
||||||
|
$this->assertEquals(PostgreSQLQueryBuilder::MAX_TABLE, strlen($identifier));
|
||||||
|
|
||||||
|
$expected = <<<SQL
|
||||||
|
SELECT *
|
||||||
|
FROM "Base" LEFT JOIN "Joined" AS "c4afb43_hijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
|
||||||
|
ON "Base"."ID" = "c4afb43_hijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"."ID"
|
||||||
|
WHERE ("c4afb43_hijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"."Title" = ?)
|
||||||
|
SQL;
|
||||||
|
$builder = new PostgreSQLQueryBuilder();
|
||||||
|
$sql = $builder->buildSQL($query, $params);
|
||||||
|
|
||||||
|
$this->assertSQLEquals($expected, $sql);
|
||||||
|
$this->assertEquals(['Value'], $params);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user