Skip to content

Commit

Permalink
[10.x] Get indexes of a table (#49204)
Browse files Browse the repository at this point in the history
* get indexes

* fix tests

* minor improvements

* minor improvements

* minor improvements
  • Loading branch information
hafezdivandari authored Dec 5, 2023
1 parent fd208de commit 7d26bfb
Show file tree
Hide file tree
Showing 16 changed files with 340 additions and 10 deletions.
21 changes: 21 additions & 0 deletions src/Illuminate/Database/Query/Processors/MySqlProcessor.php
Original file line number Diff line number Diff line change
Expand Up @@ -42,4 +42,25 @@ public function processColumns($results)
];
}, $results);
}

/**
* Process the results of an indexes query.
*
* @param array $results
* @return array
*/
public function processIndexes($results)
{
return array_map(function ($result) {
$result = (object) $result;

return [
'name' => $name = strtolower($result->name),
'columns' => explode(',', $result->columns),
'type' => strtolower($result->type),
'unique' => (bool) $result->unique,
'primary' => $name === 'primary',
];
}, $results);
}
}
21 changes: 21 additions & 0 deletions src/Illuminate/Database/Query/Processors/PostgresProcessor.php
Original file line number Diff line number Diff line change
Expand Up @@ -70,4 +70,25 @@ public function processColumns($results)
];
}, $results);
}

/**
* Process the results of an indexes query.
*
* @param array $results
* @return array
*/
public function processIndexes($results)
{
return array_map(function ($result) {
$result = (object) $result;

return [
'name' => strtolower($result->name),
'columns' => explode(',', $result->columns),
'type' => strtolower($result->type),
'unique' => (bool) $result->unique,
'primary' => (bool) $result->primary,
];
}, $results);
}
}
11 changes: 11 additions & 0 deletions src/Illuminate/Database/Query/Processors/Processor.php
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,17 @@ public function processColumns($results)
return $results;
}

/**
* Process the results of an indexes query.
*
* @param array $results
* @return array
*/
public function processIndexes($results)
{
return $results;
}

/**
* Process the results of a column listing query.
*
Expand Down
33 changes: 33 additions & 0 deletions src/Illuminate/Database/Query/Processors/SQLiteProcessor.php
Original file line number Diff line number Diff line change
Expand Up @@ -46,4 +46,37 @@ public function processColumns($results)
];
}, $results);
}

/**
* Process the results of an indexes query.
*
* @param array $results
* @return array
*/
public function processIndexes($results)
{
$primaryCount = 0;

$indexes = array_map(function ($result) use (&$primaryCount) {
$result = (object) $result;

if ($isPrimary = (bool) $result->primary) {
$primaryCount += 1;
}

return [
'name' => strtolower($result->name),
'columns' => explode(',', $result->columns),
'type' => null,
'unique' => (bool) $result->unique,
'primary' => $isPrimary,
];
}, $results);

if ($primaryCount > 1) {
$indexes = array_filter($indexes, fn ($index) => $index['name'] !== 'primary');
}

return $indexes;
}
}
21 changes: 21 additions & 0 deletions src/Illuminate/Database/Query/Processors/SqlServerProcessor.php
Original file line number Diff line number Diff line change
Expand Up @@ -100,4 +100,25 @@ public function processColumns($results)
];
}, $results);
}

/**
* Process the results of an indexes query.
*
* @param array $results
* @return array
*/
public function processIndexes($results)
{
return array_map(function ($result) {
$result = (object) $result;

return [
'name' => strtolower($result->name),
'columns' => explode(',', $result->columns),
'type' => strtolower($result->type),
'unique' => (bool) $result->unique,
'primary' => (bool) $result->primary,
];
}, $results);
}
}
15 changes: 15 additions & 0 deletions src/Illuminate/Database/Schema/Builder.php
Original file line number Diff line number Diff line change
Expand Up @@ -342,6 +342,21 @@ public function getColumns($table)
);
}

/**
* Get the indexes for a given table.
*
* @param string $table
* @return array
*/
public function getIndexes($table)
{
$table = $this->connection->getTablePrefix().$table;

return $this->connection->getPostProcessor()->processIndexes(
$this->connection->selectFromWriteConnection($this->grammar->compileIndexes($table))
);
}

/**
* Modify a table on the schema.
*
Expand Down
19 changes: 19 additions & 0 deletions src/Illuminate/Database/Schema/Grammars/MySqlGrammar.php
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,25 @@ public function compileColumns($database, $table)
);
}

/**
* Compile the query to determine the indexes.
*
* @param string $database
* @param string $table
* @return string
*/
public function compileIndexes($database, $table)
{
return sprintf(
'select index_name as `name`, group_concat(column_name order by seq_in_index) as `columns`, '
.'index_type as `type`, not non_unique as `unique` '
.'from information_schema.statistics where table_schema = %s and table_name = %s '
.'group by index_name, index_type, non_unique',
$this->quoteString($database),
$this->quoteString($table)
);
}

/**
* Compile a create table command.
*
Expand Down
26 changes: 26 additions & 0 deletions src/Illuminate/Database/Schema/Grammars/PostgresGrammar.php
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,32 @@ public function compileColumns($database, $schema, $table)
);
}

/**
* Compile the query to determine the indexes.
*
* @param string $schema
* @param string $table
* @return string
*/
public function compileIndexes($schema, $table)
{
return sprintf(
"select ic.relname as name, string_agg(a.attname, ',' order by indseq.ord) as columns, "
.'am.amname as "type", i.indisunique as "unique", i.indisprimary as "primary" '
.'from pg_index i '
.'join pg_class tc on tc.oid = i.indrelid '
.'join pg_namespace tn on tn.oid = tc.relnamespace '
.'join pg_class ic on ic.oid = i.indexrelid '
.'join pg_am am on am.oid = ic.relam '
.'join lateral unnest(i.indkey) with ordinality as indseq(num, ord) on true '
.'left join pg_attribute a on a.attrelid = i.indrelid and a.attnum = indseq.num '
.'where tc.relname = %s and tn.nspname = %s '
.'group by ic.relname, am.amname, i.indisunique, i.indisprimary',
$this->quoteString($table),
$this->quoteString($schema)
);
}

/**
* Compile a create table command.
*
Expand Down
19 changes: 19 additions & 0 deletions src/Illuminate/Database/Schema/Grammars/SQLiteGrammar.php
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,25 @@ public function compileColumns($table)
);
}

/**
* Compile the query to determine the indexes.
*
* @param string $table
* @return string
*/
public function compileIndexes($table)
{
return sprintf(
'select "primary" as name, group_concat(col) as columns, 1 as "unique", 1 as "primary" '
.'from (select name as col from pragma_table_info(%s) where pk > 0 order by pk, cid) group by name '
.'union select name, group_concat(col) as columns, "unique", origin = "pk" as "primary" '
.'from (select il.*, ii.name as col from pragma_index_list(%s) il, pragma_index_info(il.name) ii order by il.seq, ii.seqno) '
.'group by name, "unique", "primary"',
$table = $this->wrap(str_replace('.', '__', $table)),
$table
);
}

/**
* Compile a create table command.
*
Expand Down
22 changes: 22 additions & 0 deletions src/Illuminate/Database/Schema/Grammars/SqlServerGrammar.php
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,28 @@ public function compileColumns($table)
);
}

/**
* Compile the query to determine the indexes.
*
* @param string $table
* @return string
*/
public function compileIndexes($table)
{
return sprintf(
"select idx.name as name, string_agg(col.name, ',') within group (order by idxcol.key_ordinal) as columns, "
.'idx.type_desc as [type], idx.is_unique as [unique], idx.is_primary_key as [primary] '
.'from sys.indexes as idx '
.'join sys.tables as tbl on idx.object_id = tbl.object_id '
.'join sys.schemas as scm on tbl.schema_id = scm.schema_id '
.'join sys.index_columns as idxcol on idx.object_id = idxcol.object_id and idx.index_id = idxcol.index_id '
.'join sys.columns as col on idxcol.object_id = col.object_id and idxcol.column_id = col.column_id '
.'where tbl.name = %s and scm.name = SCHEMA_NAME() '
.'group by idx.name, idx.type_desc, idx.is_unique, idx.is_primary_key',
$this->quoteString($table),
);
}

/**
* Compile a create table command.
*
Expand Down
17 changes: 17 additions & 0 deletions src/Illuminate/Database/Schema/MySqlBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,23 @@ public function getColumns($table)
return $this->connection->getPostProcessor()->processColumns($results);
}

/**
* Get the indexes for a given table.
*
* @param string $table
* @return array
*/
public function getIndexes($table)
{
$table = $this->connection->getTablePrefix().$table;

return $this->connection->getPostProcessor()->processIndexes(
$this->connection->selectFromWriteConnection(
$this->grammar->compileIndexes($this->connection->getDatabaseName(), $table)
)
);
}

/**
* Drop all tables from the database.
*
Expand Down
17 changes: 17 additions & 0 deletions src/Illuminate/Database/Schema/PostgresBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,23 @@ public function getColumns($table)
return $this->connection->getPostProcessor()->processColumns($results);
}

/**
* Get the indexes for a given table.
*
* @param string $table
* @return array
*/
public function getIndexes($table)
{
[, $schema, $table] = $this->parseSchemaAndTable($table);

$table = $this->connection->getTablePrefix().$table;

return $this->connection->getPostProcessor()->processIndexes(
$this->connection->selectFromWriteConnection($this->grammar->compileIndexes($schema, $table))
);
}

/**
* Get the schemas for the connection.
*
Expand Down
1 change: 1 addition & 0 deletions src/Illuminate/Support/Facades/Schema.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
* @method static string getColumnType(string $table, string $column, bool $fullDefinition = false)
* @method static array getColumnListing(string $table)
* @method static array getColumns(string $table)
* @method static array getIndexes(string $table)
* @method static void table(string $table, \Closure $callback)
* @method static void create(string $table, \Closure $callback)
* @method static void drop(string $table)
Expand Down
17 changes: 9 additions & 8 deletions tests/Database/DatabaseSQLiteSchemaGrammarTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -164,20 +164,21 @@ public function testRenameIndex()
$table->index(['name', 'email'], 'index1');
});

$manager = $db->getConnection()->getDoctrineSchemaManager();
$details = $manager->listTableDetails('prefix_users');
$this->assertTrue($details->hasIndex('index1'));
$this->assertFalse($details->hasIndex('index2'));
$indexes = array_column($schema->getIndexes('users'), 'name');

$this->assertContains('index1', $indexes);
$this->assertNotContains('index2', $indexes);

$schema->table('users', function (Blueprint $table) {
$table->renameIndex('index1', 'index2');
});

$details = $manager->listTableDetails('prefix_users');
$this->assertFalse($details->hasIndex('index1'));
$this->assertTrue($details->hasIndex('index2'));
$indexes = $schema->getIndexes('users');

$this->assertEquals(['name', 'email'], $details->getIndex('index2')->getUnquotedColumns());
$this->assertNotContains('index1', array_column($indexes, 'name'));
$this->assertTrue(collect($indexes)->contains(
fn ($index) => $index['name'] === 'index2' && $index['columns'] === ['name', 'email']
));
}

public function testAddingPrimaryKey()
Expand Down
10 changes: 8 additions & 2 deletions tests/Database/DatabaseSchemaBuilderIntegrationTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,10 @@ public function testHasColumnAndIndexWithPrefixIndexDisabled()
$table->string('name')->index();
});

$this->assertArrayHasKey('table1_name_index', $this->db->connection()->getDoctrineSchemaManager()->listTableIndexes('example_table1'));
$this->assertContains(
'table1_name_index',
array_column($this->db->connection()->getSchemaBuilder()->getIndexes('table1'), 'name')
);
}

public function testHasColumnAndIndexWithPrefixIndexEnabled()
Expand All @@ -104,7 +107,10 @@ public function testHasColumnAndIndexWithPrefixIndexEnabled()
$table->string('name')->index();
});

$this->assertArrayHasKey('example_table1_name_index', $this->db->connection()->getDoctrineSchemaManager()->listTableIndexes('example_table1'));
$this->assertContains(
'example_table1_name_index',
array_column($this->db->connection()->getSchemaBuilder()->getIndexes('table1'), 'name')
);
}

public function testDropColumnWithTablePrefix()
Expand Down
Loading

0 comments on commit 7d26bfb

Please sign in to comment.