Commit 805e66cc by Qiang Xue

Merge pull request #1621 from lucianobaraglia/master

Get DB unique indexes information
parents 5c575335 89f0bfe1
......@@ -248,6 +248,28 @@ abstract class Schema extends Object
}
/**
* Returns all unique indexes for the given table.
* Each array element is of the following structure:
*
* ~~~
* [
* 'IndexName1' => ['col1' [, ...]],
* 'IndexName2' => ['col2' [, ...]],
* ]
* ~~~
*
* This method should be overridden by child classes in order to support this feature
* because the default implementation simply throws an exception
* @param TableSchema $table the table metadata
* @return array all unique indexes for the given table.
* @throws NotSupportedException if this method is called
*/
public function findUniqueIndexes($schema = '')
{
throw new NotSupportedException(get_class($this) . ' does not support getting unique indexes information.');
}
/**
* Returns the ID of the last inserted row or sequence value.
* @param string $sequenceName name of the sequence object (required by some DBMS)
* @return string the row ID of the last row inserted, or the last value retrieved from the sequence object
......
......@@ -207,10 +207,11 @@ class Schema extends \yii\db\Schema
}
/**
* Collects the foreign key column details for the given table.
* Gets the CREATE TABLE sql string.
* @param TableSchema $table the table metadata
* @return string $sql the result of 'SHOW CREATE TABLE'
*/
protected function findConstraints($table)
protected function getCreateTableSql($table)
{
$row = $this->db->createCommand('SHOW CREATE TABLE ' . $this->quoteSimpleTableName($table->name))->queryOne();
if (isset($row['Create Table'])) {
......@@ -219,6 +220,16 @@ class Schema extends \yii\db\Schema
$row = array_values($row);
$sql = $row[1];
}
return $sql;
}
/**
* Collects the foreign key column details for the given table.
* @param TableSchema $table the table metadata
*/
protected function findConstraints($table)
{
$sql = $this->getCreateTableSql($table);
$regexp = '/FOREIGN KEY\s+\(([^\)]+)\)\s+REFERENCES\s+([^\(^\s]+)\s*\(([^\)]+)\)/mi';
if (preg_match_all($regexp, $sql, $matches, PREG_SET_ORDER)) {
......@@ -235,6 +246,36 @@ class Schema extends \yii\db\Schema
}
/**
* Returns all unique indexes for the given table.
* Each array element is of the following structure:
*
* ~~~
* [
* 'IndexName1' => ['col1' [, ...]],
* 'IndexName2' => ['col2' [, ...]],
* ]
* ~~~
*
* @param TableSchema $table the table metadata
* @return array all unique indexes for the given table.
*/
public function findUniqueIndexes($table)
{
$sql = $this->getCreateTableSql($table);
$uniqueIndexes = [];
$regexp = '/UNIQUE KEY\s+([^\(^\s]+)\s*\(([^\)]+)\)/mi';
if (preg_match_all($regexp, $sql, $matches, PREG_SET_ORDER)) {
foreach ($matches as $match) {
$indexName = str_replace('`', '', $match[2]);
$indexColumns = array_map('trim', explode(',', str_replace('`', '', $match[3])));
$uniqueIndexes[$indexName] = $indexColumns;
}
}
return $uniqueIndexes;
}
/**
* Returns all table names in the database.
* @param string $schema the schema of the tables. Defaults to empty string, meaning the current or default schema.
* @return array all table names in the database. The names have NO schema name prefix.
......
......@@ -227,6 +227,74 @@ SQL;
}
/**
* Gets information about given table unique indexes.
* @param TableSchema $table the table metadata
* @return array with index names, columns and if it is an expression tree
*/
protected function getUniqueIndexInformation($table)
{
$tableName = $this->quoteValue($table->name);
$tableSchema = $this->quoteValue($table->schemaName);
$sql = <<<SQL
SELECT
i.relname as indexname,
ARRAY(
SELECT pg_get_indexdef(idx.indexrelid, k + 1, True)
FROM generate_subscripts(idx.indkey, 1) AS k
ORDER BY k
) AS indexcolumns,
idx.indexprs IS NOT NULL AS indexprs
FROM pg_index idx
INNER JOIN pg_class i ON i.oid = idx.indexrelid
INNER JOIN pg_class c ON c.oid = idx.indrelid
INNER JOIN pg_namespace ns ON c.relnamespace = ns.oid
WHERE idx.indisprimary != True
AND idx.indisunique = True
AND c.relname = {$tableName}
AND ns.nspname = {$tableSchema}
;
SQL;
return $this->db->createCommand($sql)->queryAll();
}
/**
* Returns all unique indexes for the given table.
* Each array element is of the following structure:
*
* ~~~
* [
* 'IndexName1' => ['col1' [, ...]],
* 'IndexName2' => ['col2' [, ...]],
* ]
* ~~~
*
* @param TableSchema $table the table metadata
* @return array all unique indexes for the given table.
*/
public function findUniqueIndexes($table)
{
$indexes = $this->getUniqueIndexInformation($table);
$uniqueIndexes = [];
foreach ($indexes as $index) {
$indexName = $index['indexname'];
if ($index['indexprs']) {
// Index is an expression like "lower(colname::text)"
$indexColumns = preg_replace("/.*\(([^\:]+).*/mi", "$1", $index['indexcolumns']);
} else {
$indexColumns = array_map('trim', explode(',', str_replace(['{', '}'], '', $index['indexcolumns'])));
}
$uniqueIndexes[$indexName] = $indexColumns;
}
return $uniqueIndexes;
}
/**
* Collects the metadata of table columns.
* @param TableSchema $table the table metadata
* @return boolean whether the table exists in the database
......
......@@ -159,6 +159,40 @@ class Schema extends \yii\db\Schema
}
/**
* Returns all unique indexes for the given table.
* Each array element is of the following structure:
*
* ~~~
* [
* 'IndexName1' => ['col1' [, ...]],
* 'IndexName2' => ['col2' [, ...]],
* ]
* ~~~
*
* @param TableSchema $table the table metadata
* @return array all unique indexes for the given table.
*/
public function findUniqueIndexes($table)
{
$sql = "PRAGMA index_list(" . $this->quoteSimpleTableName($table->name) . ')';
$indexes = $this->db->createCommand($sql)->queryAll();
$uniqueIndexes = [];
foreach ($indexes as $index) {
$indexName = $index['name'];
$indexInfo = $this->db->createCommand("PRAGMA index_info(" . $this->quoteValue($index['name']) . ")")->queryAll();
if ($index['unique']) {
$uniqueIndexes[$indexName] = [];
foreach ($indexInfo as $row) {
$uniqueIndexes[$indexName][] = $row['name'];
}
}
}
return $uniqueIndexes;
}
/**
* Loads the column information into a [[ColumnSchema]] object.
* @param array $info column information
* @return ColumnSchema the column schema object
......
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