Skip to content

Commit 816f6c3

Browse files
committed
Rework Index attribute - move sort param to columns assoc array
1 parent 258d190 commit 816f6c3

File tree

6 files changed

+73
-63
lines changed

6 files changed

+73
-63
lines changed

src/Attributes/Index.php

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,44 @@
66
class Index
77
{
88
public function __construct(
9-
public readonly array $columns,
9+
private readonly array $columns,
1010
public readonly bool $isUnique = false,
11-
public readonly ?array $sort = [],
1211
public readonly ?string $name = null,
1312
) {}
13+
14+
public function getColumns(): array
15+
{
16+
return array_keys($this->getColumnsWithSort());
17+
}
18+
19+
/**
20+
* @return array<string, string>
21+
*/
22+
public function getSort(): array
23+
{
24+
$sort = $this->getColumnsWithSort();
25+
return in_array('DESC', $sort) ? $sort : [];
26+
}
27+
28+
/**
29+
* @return array<string, string>
30+
*/
31+
private function getColumnsWithSort(): array
32+
{
33+
$result = [];
34+
foreach ($this->columns as $columnName => $order) {
35+
if (is_numeric($columnName)) {
36+
$indexColumn = $order;
37+
$indexOrder = 'ASC';
38+
} else {
39+
$indexColumn = $columnName;
40+
$indexOrder = strtoupper($order);
41+
}
42+
if ($indexOrder !== 'ASC' && $indexOrder !== 'DESC') {
43+
throw new \Exception(sprintf("Unknown order `%s` in index column `%s`", $indexOrder, $indexColumn));
44+
}
45+
$result[$indexColumn] = $indexOrder;
46+
}
47+
return $result;
48+
}
1449
}

src/Generator/EntityClassBuilder.php

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -239,19 +239,20 @@ private function getIndexes(): array
239239
{
240240
$result = [];
241241
foreach ($this->sqlTable->indexes as $index) {
242+
$attributeIndexColumns = [];
243+
foreach ($index->columns as $columnName) {
244+
if (isset($index->order[$columnName]) && strtoupper($index->order[$columnName]) === 'DESC') {
245+
$attributeIndexColumns[] = "'$columnName' => 'DESC'";
246+
} else {
247+
$attributeIndexColumns[] = "'$columnName'";
248+
}
249+
}
242250
$properties = [
243-
"columns: ['" . implode("', '", $index->columns) . "']",
251+
"columns: [" . implode(", ", $attributeIndexColumns) . "]",
244252
];
245253
if ($index->isUnique) {
246254
$properties[] = "isUnique: true";
247255
}
248-
if ($index->order) {
249-
$sortParts = [];
250-
foreach ($index->order as $key => $direction) {
251-
$sortParts[] = "'$key' => '$direction'";
252-
}
253-
$properties[] = 'sort: [' . implode(', ', $sortParts) . ']';
254-
}
255256
if ($index->name) {
256257
$properties[] = "name: '" . $index->name . "'";
257258
}

src/Providers/MySQL/MySQLIndex.php

Lines changed: 16 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -31,14 +31,12 @@ public function __construct(
3131
*/
3232
public static function fromEntityAttribute(string $tableName, Attributes\Index $attribute): self
3333
{
34-
$columns = array_is_list($attribute->columns) ? $attribute->columns : array_keys($attribute->columns);
35-
$order = self::getOrder($attribute);
3634
return new MySQLIndex(
3735
type: $attribute->isUnique ? MySQLIndexType::UNIQUE : MySQLIndexType::INDEX,
38-
name: $attribute->name ?: self::generateIndexName($tableName, $attribute->isUnique, $columns, $order),
39-
columns: $columns,
36+
name: $attribute->name ?: self::generateIndexName($tableName, $attribute),
37+
columns: $attribute->getColumns(),
4038
isUnique: $attribute->isUnique,
41-
order: $order,
39+
order: $attribute->getSort(),
4240
);
4341
}
4442

@@ -69,36 +67,14 @@ public static function fromSqlParserArray(array $data): MySQLIndex
6967
);
7068
}
7169

72-
private static function getOrder(Attributes\Index $index): array
73-
{
74-
$columns = $index->columns;
75-
if (array_is_list($columns)) {
76-
return [];
77-
}
78-
$result = [];
79-
foreach ($columns as $columnName => $order) {
80-
$order = strtoupper($order);
81-
if ($order !== 'ASC' && $order !== 'DESC') {
82-
throw new \Exception(sprintf("Unknown order `%s` in index column `%s`", $order, $columns[$columnName]));
83-
}
84-
$result[$columnName] = $order;
85-
}
86-
return $result;
87-
}
88-
89-
private static function generateIndexName(string $tableName, bool $isUnique, array $columns, array $order): string
70+
private static function generateIndexName(string $tableName, Attributes\Index $attribute): string
9071
{
9172
$parts = [
9273
$tableName,
93-
$isUnique ? 'unq' : 'idx',
74+
$attribute->isUnique ? 'unq' : 'idx',
9475
];
95-
if ($order) {
96-
foreach ($order as $columnName => $orderDir) {
97-
$parts[] = strtolower($columnName);
98-
$parts[] = strtolower($orderDir);
99-
}
100-
} else {
101-
$parts = array_merge($parts, array_map('strtolower', $columns));
76+
foreach ($attribute->getColumns() as $columnName) {
77+
$parts[] = strtolower($columnName);
10278
}
10379
return implode('_', $parts);
10480
}
@@ -160,14 +136,16 @@ public function getDropSqlString(string $tableName): string
160136

161137
private function getSqlColumnsString(): string
162138
{
163-
if ($this->order) {
164-
$columns = [];
165-
foreach ($this->order as $columnName => $order) {
166-
$columns[] = "`$columnName` $order";
139+
$parts = [];
140+
$hasDesc = in_array('DESC', $this->order);
141+
foreach ($this->columns as $columnName) {
142+
$part = "`$columnName`";
143+
if ($hasDesc) {
144+
$sort = $this->order[$columnName] ?? 'ASC';
145+
$part .= " $sort";
167146
}
168-
} else {
169-
$columns = array_map(fn ($column) => "`$column`", $this->columns);
147+
$parts[] = $part;
170148
}
171-
return '(' . implode(',', $columns) . ')';
149+
return '(' . implode(',', $parts) . ')';
172150
}
173151
}

tests/Generator/MySQLEntityClassBuilderTest.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ public function __construct(
107107
`preferences` json DEFAULT NULL,
108108
`last_update` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
109109
PRIMARY KEY (`student_id`, `course_id`),
110-
KEY `idx_enrollment_date` (`enrollment_date`)
110+
KEY `idx_enrollment_date_age` (`enrollment_date`, `age` DESC)
111111
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
112112
",
113113
'App\TestEntity',
@@ -124,7 +124,7 @@ public function __construct(
124124
use App\Enums\Gender;
125125
126126
#[Table(connection: \'mysql\', name: \'test_table2\')]
127-
#[Index(columns: [\'enrollment_date\'], name: \'idx_enrollment_date\')]
127+
#[Index(columns: [\'enrollment_date\', \'age\' => \'DESC\'], name: \'idx_enrollment_date_age\')]
128128
class TestEntity extends AbstractEntity
129129
{
130130
public function __construct(

tests/Providers/MySQL/MySQLComparatorTest.php

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ public function __construct(
3939
$entityWithIndex = new
4040
#[Table(connection: 'mysql', name: 'FooI')]
4141
#[Index(columns: ['name'], isUnique: true)]
42-
#[Index(columns: ['name', 'created_at'])]
42+
#[Index(columns: ['name', 'created_at' => 'DESC'])]
4343
class(1, 'Test') extends AbstractEntity {
4444
use UpdatedAt;
4545
use SoftDelete;
@@ -163,6 +163,7 @@ public function __construct(
163163
name: 'FooI_idx_name_created_at',
164164
columns: ['name', 'created_at'],
165165
isUnique: false,
166+
order: ['name' => 'ASC', 'created_at' => 'DESC'],
166167
),
167168
],
168169
'expectedDeletedIndexes' => [],
@@ -177,7 +178,7 @@ public function __construct(
177178
`deleted_at` TIMESTAMP(6) NULL DEFAULT NULL,
178179
PRIMARY KEY (`id`),
179180
UNIQUE KEY `FooI_unq_name` (`name`),
180-
KEY `FooI_idx_name_created_at` (`name`,`created_at`)
181+
KEY `FooI_idx_name_created_at` (`name` ASC,`created_at` DESC)
181182
) ENGINE=InnoDB COLLATE=utf8mb4_unicode_ci;
182183
SQL,
183184
],
@@ -196,7 +197,7 @@ public function __construct(
196197
`deleted_at` TIMESTAMP(6) NULL DEFAULT NULL,
197198
PRIMARY KEY (`id`),
198199
UNIQUE KEY `FooI_unq_name` (`name`),
199-
KEY `FooI_idx_name_created_at` (`name`,`created_at`)
200+
KEY `FooI_idx_name_created_at` (`name` ASC, `created_at` DESC)
200201
) ENGINE=InnoDB COLLATE=utf8mb4_unicode_ci;
201202
SQL,
202203
'expectedNewColumns' => [],
@@ -234,6 +235,7 @@ public function __construct(
234235
name: 'FooI_idx_name_created_at',
235236
columns: ['name', 'created_at'],
236237
isUnique: false,
238+
order: ['name' => 'ASC', 'created_at' => 'DESC'],
237239
),
238240
],
239241
'expectedDeletedIndexes' => [
@@ -249,7 +251,7 @@ public function __construct(
249251
'ALTER TABLE `FooI` DROP PRIMARY KEY, ADD PRIMARY KEY(`id`);',
250252
'DROP INDEX `FooI_idx_created_at` ON `FooI`;',
251253
'CREATE UNIQUE KEY `FooI_unq_name` ON `FooI` (`name`);',
252-
'CREATE INDEX `FooI_idx_name_created_at` ON `FooI` (`name`,`created_at`);',
254+
'CREATE INDEX `FooI_idx_name_created_at` ON `FooI` (`name` ASC,`created_at` DESC);',
253255
],
254256
'expectedDownQueries' => [
255257
'ALTER TABLE `FooI` DROP PRIMARY KEY, ADD PRIMARY KEY(`name`);',
@@ -280,6 +282,7 @@ public function __construct(
280282
name: 'FooI_idx_name_created_at',
281283
columns: ['name', 'created_at'],
282284
isUnique: false,
285+
order: ['name' => 'ASC', 'created_at' => 'DESC'],
283286
),
284287
],
285288
'expectedDeletedIndexes' => [
@@ -294,7 +297,7 @@ public function __construct(
294297
'expectedUpQueries' => [
295298
'ALTER TABLE `FooI` MODIFY `name` VARCHAR(255) NOT NULL;',
296299
'DROP INDEX `FooI_idx_created_name_at` ON `FooI`;',
297-
'CREATE INDEX `FooI_idx_name_created_at` ON `FooI` (`name`,`created_at`);',
300+
'CREATE INDEX `FooI_idx_name_created_at` ON `FooI` (`name` ASC,`created_at` DESC);',
298301
],
299302
'expectedDownQueries' => [
300303
'ALTER TABLE `FooI` MODIFY `name` VARCHAR(128) NOT NULL;',

tests/Providers/MySQL/MySQLIndexTest.php

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ public static function index_dataProvider(): array
2020
name: 'example1_idx',
2121
columns: ['column1', 'column2'],
2222
isUnique: false,
23-
order: []
2423
)
2524
],
2625
[
@@ -30,7 +29,6 @@ public static function index_dataProvider(): array
3029
name: 'example2_uindex',
3130
columns: ['column3'],
3231
isUnique: true,
33-
order: []
3432
)
3533
],
3634
[
@@ -40,7 +38,6 @@ public static function index_dataProvider(): array
4038
name: 'example3_ftindex',
4139
columns: ['column4'],
4240
isUnique: false,
43-
order: []
4441
)
4542
],
4643
[
@@ -50,7 +47,6 @@ public static function index_dataProvider(): array
5047
name: '',
5148
columns: ['column5'],
5249
isUnique: true,
53-
order: []
5450
)
5551
],
5652
[
@@ -80,7 +76,6 @@ public static function index_dataProvider(): array
8076
name: 'example6_ftindex',
8177
columns: ['column10', 'column11'],
8278
isUnique: false,
83-
order: []
8479
)
8580
],
8681
[
@@ -90,17 +85,15 @@ public static function index_dataProvider(): array
9085
name: '',
9186
columns: ['column12', 'column13'],
9287
isUnique: true,
93-
order: []
9488
)
9589
],
9690
[
97-
"KEY `example7_idx` (`column14` ASC)",
91+
"KEY `example7_idx` (`column14`)",
9892
new MySQLIndex(
9993
type: MySQLIndexType::INDEX,
10094
name: 'example7_idx',
10195
columns: ['column14'],
10296
isUnique: false,
103-
order: ['column14' => 'ASC']
10497
)
10598
],
10699
[

0 commit comments

Comments
 (0)