Unverified Commit 94ba9d74 authored by Marco Pivetta's avatar Marco Pivetta Committed by GitHub

Merge pull request #3317 from morozov/platforms-literal-escaping

Implemented proper escaping of string literals in platforms and schema managers
parents 82fd5d66 423b03d5
...@@ -326,15 +326,15 @@ class DrizzlePlatform extends AbstractPlatform ...@@ -326,15 +326,15 @@ class DrizzlePlatform extends AbstractPlatform
public function getListTableColumnsSQL($table, $database = null) public function getListTableColumnsSQL($table, $database = null)
{ {
if ($database) { if ($database) {
$database = "'" . $database . "'"; $databaseSQL = $this->quoteStringLiteral($database);
} else { } else {
$database = 'DATABASE()'; $databaseSQL = 'DATABASE()';
} }
return 'SELECT COLUMN_NAME, DATA_TYPE, COLUMN_COMMENT, IS_NULLABLE, IS_AUTO_INCREMENT, CHARACTER_MAXIMUM_LENGTH, COLUMN_DEFAULT,' . return 'SELECT COLUMN_NAME, DATA_TYPE, COLUMN_COMMENT, IS_NULLABLE, IS_AUTO_INCREMENT, CHARACTER_MAXIMUM_LENGTH, COLUMN_DEFAULT,' .
' NUMERIC_PRECISION, NUMERIC_SCALE, COLLATION_NAME' . ' NUMERIC_PRECISION, NUMERIC_SCALE, COLLATION_NAME' .
' FROM DATA_DICTIONARY.COLUMNS' . ' FROM DATA_DICTIONARY.COLUMNS' .
' WHERE TABLE_SCHEMA=' . $database . " AND TABLE_NAME = '" . $table . "'"; ' WHERE TABLE_SCHEMA=' . $databaseSQL . ' AND TABLE_NAME = ' . $this->quoteStringLiteral($table);
} }
/** /**
...@@ -343,14 +343,14 @@ class DrizzlePlatform extends AbstractPlatform ...@@ -343,14 +343,14 @@ class DrizzlePlatform extends AbstractPlatform
public function getListTableForeignKeysSQL($table, $database = null) public function getListTableForeignKeysSQL($table, $database = null)
{ {
if ($database) { if ($database) {
$database = "'" . $database . "'"; $databaseSQL = $this->quoteStringLiteral($database);
} else { } else {
$database = 'DATABASE()'; $databaseSQL = 'DATABASE()';
} }
return 'SELECT CONSTRAINT_NAME, CONSTRAINT_COLUMNS, REFERENCED_TABLE_NAME, REFERENCED_TABLE_COLUMNS, UPDATE_RULE, DELETE_RULE' . return 'SELECT CONSTRAINT_NAME, CONSTRAINT_COLUMNS, REFERENCED_TABLE_NAME, REFERENCED_TABLE_COLUMNS, UPDATE_RULE, DELETE_RULE' .
' FROM DATA_DICTIONARY.FOREIGN_KEYS' . ' FROM DATA_DICTIONARY.FOREIGN_KEYS' .
' WHERE CONSTRAINT_SCHEMA=' . $database . " AND CONSTRAINT_TABLE='" . $table . "'"; ' WHERE CONSTRAINT_SCHEMA=' . $databaseSQL . ' AND CONSTRAINT_TABLE=' . $this->quoteStringLiteral($table);
} }
/** /**
...@@ -359,14 +359,14 @@ class DrizzlePlatform extends AbstractPlatform ...@@ -359,14 +359,14 @@ class DrizzlePlatform extends AbstractPlatform
public function getListTableIndexesSQL($table, $database = null) public function getListTableIndexesSQL($table, $database = null)
{ {
if ($database) { if ($database) {
$database = "'" . $database . "'"; $databaseSQL = $this->quoteStringLiteral($database);
} else { } else {
$database = 'DATABASE()'; $databaseSQL = 'DATABASE()';
} }
return "SELECT INDEX_NAME AS 'key_name', COLUMN_NAME AS 'column_name', IS_USED_IN_PRIMARY AS 'primary', IS_UNIQUE=0 AS 'non_unique'" . return "SELECT INDEX_NAME AS 'key_name', COLUMN_NAME AS 'column_name', IS_USED_IN_PRIMARY AS 'primary', IS_UNIQUE=0 AS 'non_unique'" .
' FROM DATA_DICTIONARY.INDEX_PARTS' . ' FROM DATA_DICTIONARY.INDEX_PARTS' .
' WHERE TABLE_SCHEMA=' . $database . " AND TABLE_NAME='" . $table . "'"; ' WHERE TABLE_SCHEMA=' . $databaseSQL . ' AND TABLE_NAME=' . $this->quoteStringLiteral($table);
} }
/** /**
......
...@@ -439,7 +439,7 @@ SQL ...@@ -439,7 +439,7 @@ SQL
*/ */
public function getDisallowDatabaseConnectionsSQL($database) public function getDisallowDatabaseConnectionsSQL($database)
{ {
return "UPDATE pg_database SET datallowconn = 'false' WHERE datname = '" . $database . "'"; return "UPDATE pg_database SET datallowconn = 'false' WHERE datname = " . $this->quoteStringLiteral($database);
} }
/** /**
......
...@@ -27,7 +27,7 @@ class DB2SchemaManager extends AbstractSchemaManager ...@@ -27,7 +27,7 @@ class DB2SchemaManager extends AbstractSchemaManager
public function listTableNames() public function listTableNames()
{ {
$sql = $this->_platform->getListTablesSQL(); $sql = $this->_platform->getListTablesSQL();
$sql .= " AND CREATOR = UPPER('" . $this->_conn->getUsername() . "')"; $sql .= ' AND CREATOR = UPPER(' . $this->_conn->quote($this->_conn->getUsername()) . ')';
$tables = $this->_conn->fetchAll($sql); $tables = $this->_conn->fetchAll($sql);
......
...@@ -117,15 +117,9 @@ class SqliteSchemaManager extends AbstractSchemaManager ...@@ -117,15 +117,9 @@ class SqliteSchemaManager extends AbstractSchemaManager
$tableForeignKeys = $this->_conn->fetchAll($sql); $tableForeignKeys = $this->_conn->fetchAll($sql);
if (! empty($tableForeignKeys)) { if (! empty($tableForeignKeys)) {
$createSql = $this->_conn->fetchAll( $createSql = $this->getCreateTableSQL($table);
sprintf(
"SELECT sql FROM (SELECT * FROM sqlite_master UNION ALL SELECT * FROM sqlite_temp_master) WHERE type = 'table' AND name = '%s'",
$table
)
);
$createSql = $createSql[0]['sql'] ?? '';
if (preg_match_all( if ($createSql !== null && preg_match_all(
'# '#
(?:CONSTRAINT\s+([^\s]+)\s+)? (?:CONSTRAINT\s+([^\s]+)\s+)?
(?:FOREIGN\s+KEY[^\)]+\)\s*)? (?:FOREIGN\s+KEY[^\)]+\)\s*)?
...@@ -174,9 +168,10 @@ class SqliteSchemaManager extends AbstractSchemaManager ...@@ -174,9 +168,10 @@ class SqliteSchemaManager extends AbstractSchemaManager
$indexBuffer = []; $indexBuffer = [];
// fetch primary // fetch primary
$stmt = $this->_conn->executeQuery( $stmt = $this->_conn->executeQuery(sprintf(
sprintf("PRAGMA TABLE_INFO ('%s')", $tableName) 'PRAGMA TABLE_INFO (%s)',
); $this->_conn->quote($tableName)
));
$indexArray = $stmt->fetchAll(FetchMode::ASSOCIATIVE); $indexArray = $stmt->fetchAll(FetchMode::ASSOCIATIVE);
usort($indexArray, static function ($a, $b) { usort($indexArray, static function ($a, $b) {
...@@ -212,10 +207,11 @@ class SqliteSchemaManager extends AbstractSchemaManager ...@@ -212,10 +207,11 @@ class SqliteSchemaManager extends AbstractSchemaManager
$idx['primary'] = false; $idx['primary'] = false;
$idx['non_unique'] = $tableIndex['unique']?false:true; $idx['non_unique'] = $tableIndex['unique']?false:true;
$stmt = $this->_conn->executeQuery( $stmt = $this->_conn->executeQuery(sprintf(
sprintf("PRAGMA INDEX_INFO ('%s')", $keyName) 'PRAGMA INDEX_INFO (%s)',
); $this->_conn->quote($keyName)
$indexArray = $stmt->fetchAll(FetchMode::ASSOCIATIVE); ));
$indexArray = $stmt->fetchAll(FetchMode::ASSOCIATIVE);
foreach ($indexArray as $indexColumnRow) { foreach ($indexArray as $indexColumnRow) {
$idx['column_name'] = $indexColumnRow['name']; $idx['column_name'] = $indexColumnRow['name'];
...@@ -272,13 +268,7 @@ class SqliteSchemaManager extends AbstractSchemaManager ...@@ -272,13 +268,7 @@ class SqliteSchemaManager extends AbstractSchemaManager
} }
// inspect column collation and comments // inspect column collation and comments
$createSql = $this->_conn->fetchAll( $createSql = $this->getCreateTableSQL($table) ?? '';
sprintf(
"SELECT sql FROM (SELECT * FROM sqlite_master UNION ALL SELECT * FROM sqlite_temp_master) WHERE type = 'table' AND name = '%s'",
$table
)
);
$createSql = $createSql[0]['sql'] ?? '';
foreach ($list as $columnName => $column) { foreach ($list as $columnName => $column) {
$type = $column->getType(); $type = $column->getType();
...@@ -488,4 +478,24 @@ class SqliteSchemaManager extends AbstractSchemaManager ...@@ -488,4 +478,24 @@ class SqliteSchemaManager extends AbstractSchemaManager
return $comment === '' ? null : $comment; return $comment === '' ? null : $comment;
} }
private function getCreateTableSQL(string $table) : ?string
{
return $this->_conn->fetchColumn(
<<<'SQL'
SELECT sql
FROM (
SELECT *
FROM sqlite_master
UNION ALL
SELECT *
FROM sqlite_temp_master
)
WHERE type = 'table'
AND name = ?
SQL
,
[$table]
) ?: null;
}
} }
...@@ -30,7 +30,7 @@ final class DB2SchemaManagerTest extends TestCase ...@@ -30,7 +30,7 @@ final class DB2SchemaManagerTest extends TestCase
$platform = $this->createMock(DB2Platform::class); $platform = $this->createMock(DB2Platform::class);
$this->conn = $this $this->conn = $this
->getMockBuilder(Connection::class) ->getMockBuilder(Connection::class)
->setMethods(['fetchAll']) ->setMethods(['fetchAll', 'quote'])
->setConstructorArgs([['platform' => $platform], $driverMock, new Configuration(), $eventManager]) ->setConstructorArgs([['platform' => $platform], $driverMock, new Configuration(), $eventManager])
->getMock(); ->getMock();
$this->manager = new DB2SchemaManager($this->conn); $this->manager = new DB2SchemaManager($this->conn);
...@@ -102,6 +102,7 @@ final class DB2SchemaManagerTest extends TestCase ...@@ -102,6 +102,7 @@ final class DB2SchemaManagerTest extends TestCase
$this->conn->getConfiguration()->setSchemaAssetsFilter(static function ($assetName) use ($accepted) { $this->conn->getConfiguration()->setSchemaAssetsFilter(static function ($assetName) use ($accepted) {
return in_array($assetName, $accepted); return in_array($assetName, $accepted);
}); });
$this->conn->expects($this->any())->method('quote');
$this->conn->expects($this->once())->method('fetchAll')->will($this->returnValue([ $this->conn->expects($this->once())->method('fetchAll')->will($this->returnValue([
['name' => 'FOO'], ['name' => 'FOO'],
['name' => 'T_FOO'], ['name' => 'T_FOO'],
...@@ -129,6 +130,7 @@ final class DB2SchemaManagerTest extends TestCase ...@@ -129,6 +130,7 @@ final class DB2SchemaManagerTest extends TestCase
$this->conn->getConfiguration()->setSchemaAssetsFilter(static function ($assetName) use ($accepted) { $this->conn->getConfiguration()->setSchemaAssetsFilter(static function ($assetName) use ($accepted) {
return in_array($assetName, $accepted); return in_array($assetName, $accepted);
}); });
$this->conn->expects($this->any())->method('quote');
$this->conn->expects($this->atLeastOnce())->method('fetchAll')->will($this->returnValue([ $this->conn->expects($this->atLeastOnce())->method('fetchAll')->will($this->returnValue([
['name' => 'FOO'], ['name' => 'FOO'],
['name' => 'T_FOO'], ['name' => 'T_FOO'],
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment