Skip to content

Commit c4515bd

Browse files
authored
Added methods getIndexes hasIndex and getIndexListing into Hyperf\Database\Schema\Builder. (#6883)
1 parent 8e2242c commit c4515bd

File tree

4 files changed

+153
-0
lines changed

4 files changed

+153
-0
lines changed

src/Query/Processors/PostgresProcessor.php

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,4 +61,22 @@ public function processListing(array $results): array
6161
return (array) $result;
6262
}, $results);
6363
}
64+
65+
/**
66+
* Process the results of an indexes query.
67+
*/
68+
public function processIndexes(array $results): array
69+
{
70+
return array_map(function ($result) {
71+
$result = (object) $result;
72+
73+
return [
74+
'name' => strtolower($result->name),
75+
'columns' => explode(',', $result->columns),
76+
'type' => strtolower($result->type),
77+
'unique' => (bool) $result->unique,
78+
'primary' => (bool) $result->primary,
79+
];
80+
}, $results);
81+
}
6482
}

src/Schema/Grammars/PostgresGrammar.php

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,28 @@ public function compileColumns(): string
120120
return 'select table_schema,table_name,column_name,ordinal_position,column_default,is_nullable,data_type from information_schema.columns where table_schema = ? order by ORDINAL_POSITION';
121121
}
122122

123+
/**
124+
* Compile the query to determine the indexes.
125+
*/
126+
public function compileIndexes(string $schema, string $table): string
127+
{
128+
return sprintf(
129+
"select ic.relname as name, string_agg(a.attname, ',' order by indseq.ord) as columns, "
130+
. 'am.amname as "type", i.indisunique as "unique", i.indisprimary as "primary" '
131+
. 'from pg_index i '
132+
. 'join pg_class tc on tc.oid = i.indrelid '
133+
. 'join pg_namespace tn on tn.oid = tc.relnamespace '
134+
. 'join pg_class ic on ic.oid = i.indexrelid '
135+
. 'join pg_am am on am.oid = ic.relam '
136+
. 'join lateral unnest(i.indkey) with ordinality as indseq(num, ord) on true '
137+
. 'left join pg_attribute a on a.attrelid = i.indrelid and a.attnum = indseq.num '
138+
. 'where tc.relname = %s and tn.nspname = %s '
139+
. 'group by ic.relname, am.amname, i.indisunique, i.indisprimary',
140+
$this->quoteString($table),
141+
$this->quoteString($schema)
142+
);
143+
}
144+
123145
/**
124146
* Compile a create table command.
125147
*/

src/Schema/PostgresBuilder.php

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,20 @@ public function getColumnTypeListing($table)
236236
return $processor->processListing($results);
237237
}
238238

239+
/**
240+
* Get the indexes for a given table.
241+
*/
242+
public function getIndexes(string $table): array
243+
{
244+
[$schema, $table] = $this->parseSchemaAndTable($table);
245+
246+
$table = $this->connection->getTablePrefix() . $table;
247+
248+
return $this->connection->getPostProcessor()->processIndexes(
249+
$this->connection->selectFromWriteConnection($this->grammar->compileIndexes($schema, $table))
250+
);
251+
}
252+
239253
/**
240254
* Parse the table name and extract the schema and table.
241255
*

tests/Cases/SchemaBuilderTest.php

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@
1919
use PHPUnit\Framework\Attributes\RequiresPhpExtension;
2020
use PHPUnit\Framework\TestCase;
2121

22+
use function Hyperf\Collection\collect;
23+
2224
/**
2325
* @internal
2426
* @coversNothing
@@ -101,4 +103,101 @@ public function testColumn(): void
101103
$this->assertSame(['id', 'name', 'ranking'], array_column($columns, 'column_name'));
102104
Schema::drop('column_1');
103105
}
106+
107+
public function index(): void
108+
{
109+
Schema::create('users', function (Blueprint $table) {
110+
$table->string('name');
111+
$table->string('email');
112+
});
113+
114+
Schema::table('users', function (Blueprint $table) {
115+
$table->index(['name', 'email'], 'index1');
116+
});
117+
118+
$indexes = Schema::getIndexListing('users');
119+
120+
$this->assertContains('index1', $indexes);
121+
$this->assertNotContains('index2', $indexes);
122+
123+
Schema::table('users', function (Blueprint $table) {
124+
$table->renameIndex('index1', 'index2');
125+
});
126+
127+
$this->assertFalse(Schema::hasIndex('users', 'index1'));
128+
$this->assertTrue(collect(Schema::getIndexes('users'))->contains(
129+
fn ($index) => $index['name'] === 'index2' && $index['columns'] === ['name', 'email']
130+
));
131+
Schema::create('foo', function (Blueprint $table) {
132+
$table->id();
133+
$table->string('bar');
134+
$table->integer('baz');
135+
136+
$table->unique(['baz', 'bar']);
137+
});
138+
139+
$indexes = Schema::getIndexes('foo');
140+
141+
$this->assertCount(2, $indexes);
142+
$this->assertTrue(collect($indexes)->contains(
143+
fn ($index) => $index['columns'] === ['id'] && $index['primary']
144+
));
145+
$this->assertTrue(collect($indexes)->contains(
146+
fn ($index) => $index['name'] === 'foo_baz_bar_unique' && $index['columns'] === ['baz', 'bar'] && $index['unique']
147+
));
148+
$this->assertTrue(Schema::hasIndex('foo', 'foo_baz_bar_unique'));
149+
$this->assertTrue(Schema::hasIndex('foo', 'foo_baz_bar_unique', 'unique'));
150+
$this->assertTrue(Schema::hasIndex('foo', ['baz', 'bar']));
151+
$this->assertTrue(Schema::hasIndex('foo', ['baz', 'bar'], 'unique'));
152+
$this->assertFalse(Schema::hasIndex('foo', ['baz', 'bar'], 'primary'));
153+
Schema::drop('foo');
154+
Schema::create('foo', function (Blueprint $table) {
155+
$table->string('bar')->index('my_index');
156+
});
157+
158+
$indexes = Schema::getIndexes('foo');
159+
160+
$this->assertCount(1, $indexes);
161+
$this->assertTrue(
162+
$indexes[0]['name'] === 'my_index'
163+
&& $indexes[0]['columns'] === ['bar']
164+
&& ! $indexes[0]['unique']
165+
&& ! $indexes[0]['primary']
166+
);
167+
$this->assertTrue(Schema::hasIndex('foo', 'my_index'));
168+
$this->assertTrue(Schema::hasIndex('foo', ['bar']));
169+
$this->assertFalse(Schema::hasIndex('foo', 'my_index', 'primary'));
170+
$this->assertFalse(Schema::hasIndex('foo', ['bar'], 'unique'));
171+
Schema::drop('foo');
172+
Schema::create('foo', function (Blueprint $table) {
173+
$table->unsignedBigInteger('key');
174+
$table->string('bar')->unique();
175+
$table->integer('baz');
176+
177+
$table->primary(['baz', 'key']);
178+
});
179+
180+
$indexes = Schema::getIndexes('foo');
181+
182+
$this->assertCount(2, $indexes);
183+
$this->assertTrue(collect($indexes)->contains(
184+
fn ($index) => $index['columns'] === ['baz', 'key'] && $index['primary']
185+
));
186+
$this->assertTrue(collect($indexes)->contains(
187+
fn ($index) => $index['name'] === 'foo_bar_unique' && $index['columns'] === ['bar'] && $index['unique']
188+
));
189+
Schema::create('articles', function (Blueprint $table) {
190+
$table->id();
191+
$table->string('title', 200);
192+
$table->text('body');
193+
194+
$table->fulltext(['body', 'title']);
195+
});
196+
197+
$indexes = Schema::getIndexes('articles');
198+
199+
$this->assertCount(2, $indexes);
200+
$this->assertTrue(collect($indexes)->contains(fn ($index) => $index['columns'] === ['id'] && $index['primary']));
201+
$this->assertTrue(collect($indexes)->contains('name', 'articles_body_title_fulltext'));
202+
}
104203
}

0 commit comments

Comments
 (0)