From 05b5a3ed5952450c27f9047d0d9658333d728078 Mon Sep 17 00:00:00 2001 From: Vitaly Iskrin Date: Wed, 22 Nov 2023 00:09:08 -0600 Subject: [PATCH 1/8] fix: unable to set sequence when primary key is not id --- src/Traits/FixturesTrait.php | 20 +++++++++++++------- tests/FixturesTraitTest.php | 14 +++----------- tests/TestCase.php | 2 +- 3 files changed, 17 insertions(+), 19 deletions(-) diff --git a/src/Traits/FixturesTrait.php b/src/Traits/FixturesTrait.php index 5ce121b9..5f120f72 100644 --- a/src/Traits/FixturesTrait.php +++ b/src/Traits/FixturesTrait.php @@ -3,6 +3,7 @@ namespace RonasIT\Support\Traits; use Illuminate\Support\Arr; +use Illuminate\Support\Facades\DB; use Illuminate\Testing\TestResponse; use RonasIT\Support\Exceptions\ForbiddenExportModeException; @@ -156,16 +157,21 @@ public function getClearMySQLDatabaseQuery(array $tables, array $except = ['migr return "{$query} SET FOREIGN_KEY_CHECKS = 1;\n"; } - public function prepareSequences(array $tables, array $except = []): void + public function prepareSequences(array $except = []): void { $except = array_merge($this->postgisTables, $this->prepareSequencesExceptTables, $except); - $query = array_concat($tables, function ($table) use ($except) { - if (in_array($table, $except)) { - return ''; - } else { - return "SELECT setval('{$table}_id_seq', (select coalesce(max(id), 1) from {$table}), (case when (select max(id) from {$table}) is NULL then false else true end));\n"; - } + $data = app('db.connection') + ->table('information_schema.columns') + ->select('table_name', 'column_name', 'column_default') + ->whereNotIn('table_name', $except) + ->where('column_default', 'LIKE', 'nextval%') + ->get(); + + $query = array_concat($data, function ($item) use ($except) { + $sequenceName = str_replace(["nextval('", "'::regclass"], '', $item->column_default); + + return "SELECT setval({$sequenceName}, (select max({$item->column_name}) from {$item->table_name}));\n"; }); app('db.connection')->unprepared($query); diff --git a/tests/FixturesTraitTest.php b/tests/FixturesTraitTest.php index 4e308fb9..776d7cd1 100644 --- a/tests/FixturesTraitTest.php +++ b/tests/FixturesTraitTest.php @@ -145,19 +145,11 @@ public function testLoadTestDumpForPgsql() public function testPrepareSequences() { $connection = $this->mockClass(Connection::class, [], true); - $mock = $this->mockClass(PostgreSQLSchemaManager::class, ['listTableNames'], true); $this->app->instance('db.connection', $connection); + $this->dumpFileName = 'clear_database/dump.sql'; - $mock - ->expects($this->once()) - ->method('listTableNames') - ->willReturn($this->getJsonFixture('prepare_sequences/tables.json')); - - $connection - ->expects($this->once()) - ->method('getDoctrineSchemaManager') - ->willReturn($mock); + Config::set('database.default', 'pgsql'); $connection ->expects($this->once()) @@ -165,7 +157,7 @@ public function testPrepareSequences() ->with($this->getFixture('prepare_sequences/sequences.sql')) ->willReturn(true); - $this->prepareSequences($this->getTables()); + $this->prepareSequences(); } public function testGetFixtureWithoutGlobalExportMode() diff --git a/tests/TestCase.php b/tests/TestCase.php index c017e889..da56ad72 100755 --- a/tests/TestCase.php +++ b/tests/TestCase.php @@ -51,7 +51,7 @@ public function setUp(): void } if (config('database.default') === 'pgsql') { - $this->prepareSequences($this->getTables()); + $this->prepareSequences(); } Carbon::setTestNow(Carbon::parse($this->testNow)); From e79dff83b733df7e5ab03012c95f0aa4caa68f91 Mon Sep 17 00:00:00 2001 From: Vitaly Iskrin Date: Sun, 26 Nov 2023 23:47:59 -0600 Subject: [PATCH 2/8] fix: unable to set sequence when primary key is not id --- src/Traits/FixturesTrait.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Traits/FixturesTrait.php b/src/Traits/FixturesTrait.php index 5f120f72..ffb779ec 100644 --- a/src/Traits/FixturesTrait.php +++ b/src/Traits/FixturesTrait.php @@ -169,9 +169,9 @@ public function prepareSequences(array $except = []): void ->get(); $query = array_concat($data, function ($item) use ($except) { - $sequenceName = str_replace(["nextval('", "'::regclass"], '', $item->column_default); + $sequenceName = str_replace(["nextval('", "'::regclass)"], '', $item->column_default); - return "SELECT setval({$sequenceName}, (select max({$item->column_name}) from {$item->table_name}));\n"; + return "SELECT setval('{$sequenceName}', (select coalesce(max({$item->column_name}), 1) from {$item->table_name}), (case when (select max({$item->column_name}) from {$item->table_name}) is NULL then false else true end));\n"; }); app('db.connection')->unprepared($query); From e2529651d61fce77332eca45a50d1e58e9173413 Mon Sep 17 00:00:00 2001 From: Vitaly Iskrin Date: Sun, 3 Dec 2023 23:35:01 -0600 Subject: [PATCH 3/8] style: update code-style --- src/Traits/FixturesTrait.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Traits/FixturesTrait.php b/src/Traits/FixturesTrait.php index ffb779ec..5c94b427 100644 --- a/src/Traits/FixturesTrait.php +++ b/src/Traits/FixturesTrait.php @@ -171,7 +171,9 @@ public function prepareSequences(array $except = []): void $query = array_concat($data, function ($item) use ($except) { $sequenceName = str_replace(["nextval('", "'::regclass)"], '', $item->column_default); - return "SELECT setval('{$sequenceName}', (select coalesce(max({$item->column_name}), 1) from {$item->table_name}), (case when (select max({$item->column_name}) from {$item->table_name}) is NULL then false else true end));\n"; + return "SELECT setval('{$sequenceName}', (select coalesce(max({$item->column_name}), 1) from " . + "{$item->table_name}), (case when (select max({$item->column_name}) from {$item->table_name}) " . + "is NULL then false else true end));\n"; }); app('db.connection')->unprepared($query); From 6be19e3d5fd67072c2c4d840edec2c6abe621e06 Mon Sep 17 00:00:00 2001 From: Vitaly Iskrin Date: Wed, 28 Feb 2024 01:59:36 -0600 Subject: [PATCH 4/8] test: increase coverage --- tests/EntityControlTraitTest.php | 4 ++-- tests/SearchTraitTest.php | 7 ++----- tests/support/Mock/ChildRelationModel.php | 9 +++++++++ tests/support/Mock/RelationModel.php | 5 +++++ tests/support/Traits/SqlMockTrait.php | 4 +++- 5 files changed, 21 insertions(+), 8 deletions(-) create mode 100644 tests/support/Mock/ChildRelationModel.php diff --git a/tests/EntityControlTraitTest.php b/tests/EntityControlTraitTest.php index 2bb0850b..6bcaf5d1 100644 --- a/tests/EntityControlTraitTest.php +++ b/tests/EntityControlTraitTest.php @@ -83,7 +83,7 @@ public function testWith() $this->assertEquals(['relation'], $attachedRelations); } - public function withCount() + public function testWithCount() { $this->testRepositoryClass->withCount('relation'); @@ -100,7 +100,7 @@ public function testAll() ->withTrashed() ->onlyTrashed() ->with('relation') - ->withCount('relation') + ->withCount(['relation', 'relation.child_relation']) ->force() ->all(); diff --git a/tests/SearchTraitTest.php b/tests/SearchTraitTest.php index cfbcec9d..dfe7b49e 100644 --- a/tests/SearchTraitTest.php +++ b/tests/SearchTraitTest.php @@ -21,7 +21,6 @@ class SearchTraitTest extends HelpersTestCase protected ReflectionProperty $forceModeProperty; protected ReflectionProperty $attachedRelationsProperty; protected ReflectionProperty $attachedRelationsCountProperty; - protected ReflectionProperty $queryProperty; protected ReflectionProperty $shouldSettablePropertiesBeResetProperty; protected ReflectionMethod $setAdditionalReservedFiltersMethod; @@ -58,9 +57,6 @@ public function setUp(): void ); $this->shouldSettablePropertiesBeResetProperty->setAccessible(true); - $this->queryProperty = new ReflectionProperty(TestRepository::class, 'query'); - $this->queryProperty->setAccessible(true); - $reflectionClass = new ReflectionClass(TestRepository::class); $this->setAdditionalReservedFiltersMethod = $reflectionClass->getMethod('setAdditionalReservedFilters'); $this->setAdditionalReservedFiltersMethod->setAccessible(true); @@ -79,7 +75,7 @@ public function testSearchQuery() 'with_count' => ['relation'] ]); - $sql = $this->queryProperty->getValue($this->testRepositoryClass)->toSql(); + $sql = $this->testRepositoryClass->getSearchQuery()->toSql(); $onlyTrashed = $this->onlyTrashedProperty->getValue($this->testRepositoryClass); $withTrashed = $this->withTrashedProperty->getValue($this->testRepositoryClass); @@ -218,6 +214,7 @@ public function testSearchQueryWithRelations() ]) ->filterByQuery(['query_field', 'relation.another_query_field']) ->filterBy('relation.name', 'relation_name') + ->filterBy('relation.another_name') ->getSearchResults(); } diff --git a/tests/support/Mock/ChildRelationModel.php b/tests/support/Mock/ChildRelationModel.php new file mode 100644 index 00000000..f46b0360 --- /dev/null +++ b/tests/support/Mock/ChildRelationModel.php @@ -0,0 +1,9 @@ +hasMany(ChildRelationModel::class); + } } \ No newline at end of file diff --git a/tests/support/Traits/SqlMockTrait.php b/tests/support/Traits/SqlMockTrait.php index 82b40bfc..4105270d 100644 --- a/tests/support/Traits/SqlMockTrait.php +++ b/tests/support/Traits/SqlMockTrait.php @@ -20,7 +20,9 @@ protected function mockAll(array $selectResult): void ); $this->mockSelect( - 'select * from `relation_models` where `relation_models`.`test_model_id` in (1)' + 'select `relation_models`.*, (select count(*) from `child_relation_models` ' + . 'where `relation_models`.`id` = `child_relation_models`.`relation_model_id`) as `child_relation_count` ' + . 'from `relation_models` where `relation_models`.`test_model_id` in (1)', ); } From 9c60d75cde4048cabed76f64ad5323cd70adabb1 Mon Sep 17 00:00:00 2001 From: Vitaly Iskrin Date: Wed, 28 Feb 2024 02:44:10 -0600 Subject: [PATCH 5/8] test: increase coverage --- src/Traits/SearchTrait.php | 8 +++----- tests/SearchTraitTest.php | 16 +++++++++++++++- 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/src/Traits/SearchTrait.php b/src/Traits/SearchTrait.php index d68773d2..0812eb4a 100644 --- a/src/Traits/SearchTrait.php +++ b/src/Traits/SearchTrait.php @@ -176,7 +176,7 @@ public function wrapPaginatedData(Collection $data): LengthAwarePaginator $perPage = $this->calculatePerPage($total); - $paginator = new LengthAwarePaginator($data, count($data), $perPage, 1, [ + $paginator = new LengthAwarePaginator($data, $total, $perPage, 1, [ 'path' => Paginator::resolveCurrentPath(), 'pageName' => 'page' ]); @@ -370,11 +370,9 @@ protected function calculatePerPage(int $total): int return $total; } - if (!empty($this->filter['per_page'])) { - return $this->filter['per_page']; - } + $defaultPerPage = config('defaults.items_per_page', 1); - return config('defaults.items_per_page', 1); + return Arr::get($this->filter, 'per_page', $defaultPerPage); } protected function postQueryHook(): void diff --git a/tests/SearchTraitTest.php b/tests/SearchTraitTest.php index dfe7b49e..77b80bbc 100644 --- a/tests/SearchTraitTest.php +++ b/tests/SearchTraitTest.php @@ -94,11 +94,25 @@ public function testSearchQuery() public function testGetSearchResultWithAll() { - $this->mockSelect('select * from `test_models` where `test_models`.`deleted_at` is null order by `id` asc'); + $this->mockSelect('select * from `test_models` where `test_models`.`deleted_at` is null order by `id` asc', [ + 1, 2, 3 + ]); $this->testRepositoryClass->searchQuery(['all' => true])->getSearchResults(); } + public function testGetSearchResultWithAllAndParams() + { + $this->mockSelect('select * from `test_models` where `test_models`.`deleted_at` is null order by `id` asc', []); + + $this->testRepositoryClass + ->searchQuery([ + 'all' => true, + 'per_page' => 20, + ]) + ->getSearchResults(); + } + public function testGetSearchResult() { $this->mockGetSearchResult($this->selectResult); From 86482944324fe0ee73c62bcdfcf91d3a48650d69 Mon Sep 17 00:00:00 2001 From: Vitaly Iskrin Date: Sat, 2 Mar 2024 21:24:54 -0600 Subject: [PATCH 6/8] test: increase coverage --- src/Traits/FixturesTrait.php | 56 +++++++++++-------- tests/FixturesTraitTest.php | 49 +++++++++++++--- .../clear_database/tables.json | 12 +++- .../get_tables/information_schema.json | 37 ++++++++++++ .../FixturesTraitTest/get_tables/mysql.json | 11 ++++ .../FixturesTraitTest/get_tables/pgsql.json | 37 ++++++++++++ .../FixturesTraitTest/get_tables/tables.json | 5 ++ .../prepare_sequences/sequences.sql | 1 - .../prepare_sequences/tables.json | 7 --- 9 files changed, 172 insertions(+), 43 deletions(-) create mode 100644 tests/fixtures/FixturesTraitTest/get_tables/information_schema.json create mode 100644 tests/fixtures/FixturesTraitTest/get_tables/mysql.json create mode 100644 tests/fixtures/FixturesTraitTest/get_tables/pgsql.json create mode 100644 tests/fixtures/FixturesTraitTest/get_tables/tables.json delete mode 100644 tests/fixtures/FixturesTraitTest/prepare_sequences/tables.json diff --git a/src/Traits/FixturesTrait.php b/src/Traits/FixturesTrait.php index d12acd83..d5f8fbef 100644 --- a/src/Traits/FixturesTrait.php +++ b/src/Traits/FixturesTrait.php @@ -61,9 +61,8 @@ protected function loadTestDump(): void } $databaseTables = $this->getTables(); - $scheme = config('database.default'); - $this->clearDatabase($scheme, $databaseTables, array_merge($this->postgisTables, $this->truncateExceptTables)); + $this->clearDatabase($databaseTables, array_merge($this->postgisTables, $this->truncateExceptTables)); app('db.connection')->unprepared($dump); } @@ -117,8 +116,10 @@ public function exportJson($fixture, $data): void $this->exportContent(json_encode($data, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE), $fixture); } - public function clearDatabase(string $scheme, array $tables, array $except): void + public function clearDatabase(array $tables, array $except): void { + $scheme = config('database.default'); + if ($scheme === 'pgsql') { $query = $this->getClearPsqlDatabaseQuery($tables, $except); } elseif ($scheme === 'mysql') { @@ -133,10 +134,10 @@ public function clearDatabase(string $scheme, array $tables, array $except): voi public function getClearPsqlDatabaseQuery(array $tables, array $except = ['migrations']): string { return array_concat($tables, function ($table) use ($except) { - if (in_array($table, $except)) { + if (in_array($table['table_name'], $except)) { return ''; } else { - return "TRUNCATE {$table} RESTART IDENTITY CASCADE; \n"; + return "TRUNCATE {$table['table_name']} RESTART IDENTITY CASCADE; \n"; } }); } @@ -146,10 +147,10 @@ public function getClearMySQLDatabaseQuery(array $tables, array $except = ['migr $query = "SET FOREIGN_KEY_CHECKS = 0;\n"; $query .= array_concat($tables, function ($table) use ($except) { - if (in_array($table, $except)) { + if (in_array($table['table_name'], $except)) { return ''; } else { - return "TRUNCATE TABLE {$table}; \n"; + return "TRUNCATE TABLE {$table['table_name']}; \n"; } }); @@ -160,20 +161,16 @@ public function prepareSequences(array $except = []): void { $except = array_merge($this->postgisTables, $this->prepareSequencesExceptTables, $except); - $data = app('db.connection') - ->table('information_schema.columns') - ->select('table_name', 'column_name', 'column_default') - ->whereNotIn('table_name', $except) - ->where('column_default', 'LIKE', 'nextval%') - ->get() - ->toArray(); - - $query = array_concat($data, function ($item) use ($except) { - $sequenceName = str_replace(["nextval('", "'::regclass)"], '', $item['column_default']); + $query = array_concat($this->getTables(), function ($item) use ($except) { + if (in_array($item['table_name'], $except)) { + return ''; + } else { + $sequenceName = str_replace(["nextval('", "'::regclass)"], '', $item['column_default']); - return "SELECT setval('{$sequenceName}', (select coalesce(max({$item['column_name']}), 1) from " . - "{$item['table_name']}), (case when (select max({$item['column_name']}) from {$item['table_name']}) " . - "is NULL then false else true end));\n"; + return "SELECT setval('{$sequenceName}', (select coalesce(max({$item['column_name']}), 1) from " . + "{$item['table_name']}), (case when (select max({$item['column_name']}) from {$item['table_name']}) " . + "is NULL then false else true end));\n"; + } }); app('db.connection')->unprepared($query); @@ -189,10 +186,23 @@ public function exportFile(TestResponse $response, string $fixture): void protected function getTables(): array { + $scheme = config('database.default'); + if (empty(self::$tables)) { - self::$tables = app('db.connection') - ->getDoctrineSchemaManager() - ->listTableNames(); + if ($scheme === 'mysql') { + $tables = app('db.connection') + ->getDoctrineSchemaManager() + ->listTableNames(); + + self::$tables = array_map(fn($value) => ['table_name' => $value], $tables); + } elseif ($scheme === 'pgsql') { + self::$tables = app('db.connection') + ->table('information_schema.columns') + ->select('table_name', 'column_name', 'column_default') + ->where('column_default', 'LIKE', 'nextval%') + ->get() + ->toArray(); + } } return self::$tables; diff --git a/tests/FixturesTraitTest.php b/tests/FixturesTraitTest.php index ea1e982b..987a7a03 100644 --- a/tests/FixturesTraitTest.php +++ b/tests/FixturesTraitTest.php @@ -2,7 +2,7 @@ namespace RonasIT\Support\Tests; -use Doctrine\DBAL\Schema\PostgreSQLSchemaManager; +use Doctrine\DBAL\Schema\MySQLSchemaManager; use Illuminate\Database\Connection; use Illuminate\Database\Query\Grammars\Grammar; use Illuminate\Database\Query\Processors\Processor; @@ -153,24 +153,55 @@ public function testLoadTestDumpForPgsql() $this->loadTestDump(); } - public function testPrepareSequences() + public function testGetTablesPgsql() + { + $connection = $this->mockClass(Connection::class, [ + $this->functionCall('getQueryGrammar', [], new Grammar), + $this->functionCall('getPostProcessor', [], new Processor), + $this->functionCall('select', [], collect($this->getJsonFixture('get_tables/information_schema.json'))), + ], true); + + $this->app->instance('db.connection', $connection); + + Config::set('database.default', 'pgsql'); + + $this->getTables(); + + $this->assertEqualsFixture('get_tables/pgsql.json', self::$tables); + } + + public function testGetTablesMysql() { - $mock = $this->mockClass(PostgreSQLSchemaManager::class, [ - $this->functionCall('listTableNames', [], $this->getJsonFixture('prepare_sequences/tables.json')), + $mock = $this->mockClass(MySQLSchemaManager::class, [ + $this->functionCall('listTableNames', [], $this->getJsonFixture('get_tables/tables.json')), ], true); $connection = $this->mockClass(Connection::class, [ $this->functionCall('getDoctrineSchemaManager', [], $mock), - $this->functionCall('getQueryGrammar', [], new Grammar), - $this->functionCall('getPostProcessor', [], new Processor), - $this->functionCall('select', [], collect($this->getJsonFixture('prepare_sequences/information_schema.json'))), + ], true); + + $this->app->instance('db.connection', $connection); + + Config::set('database.default', 'mysql'); + + $this->getTables(); + + $this->assertEqualsFixture('get_tables/mysql.json', self::$tables); + } + + public function testPrepareSequences() + { + $connection = $this->mockClass(Connection::class, [ $this->functionCall('unprepared', [$this->getFixture('prepare_sequences/sequences.sql')]), ], true); $this->app->instance('db.connection', $connection); - $this->dumpFileName = 'clear_database/dump.sql'; - $this->prepareSequences($this->getTables()); + Config::set('database.default', 'pgsql'); + + self::$tables = $this->getJsonFixture('prepare_sequences/information_schema.json'); + + $this->prepareSequences(['roles']); } public function testGetFixtureWithoutGlobalExportMode() diff --git a/tests/fixtures/FixturesTraitTest/clear_database/tables.json b/tests/fixtures/FixturesTraitTest/clear_database/tables.json index 087b20bc..1844e9bc 100644 --- a/tests/fixtures/FixturesTraitTest/clear_database/tables.json +++ b/tests/fixtures/FixturesTraitTest/clear_database/tables.json @@ -1,5 +1,11 @@ [ - "users", - "migrations", - "groups" + { + "table_name": "users" + }, + { + "table_name": "migrations" + }, + { + "table_name": "groups" + } ] diff --git a/tests/fixtures/FixturesTraitTest/get_tables/information_schema.json b/tests/fixtures/FixturesTraitTest/get_tables/information_schema.json new file mode 100644 index 00000000..26c78230 --- /dev/null +++ b/tests/fixtures/FixturesTraitTest/get_tables/information_schema.json @@ -0,0 +1,37 @@ +[ + { + "table_name": "articles", + "column_name": "id", + "column_default": "nextval('articles_id_seq'::regclass)" + }, + { + "table_name": "workers", + "column_name": "id", + "column_default": "nextval('workers_id_seq'::regclass)" + }, + { + "table_name": "groups", + "column_name": "id", + "column_default": "nextval('groups_id_seq'::regclass)" + }, + { + "table_name": "homes", + "column_name": "id", + "column_default": "nextval('homes_id_seq'::regclass)" + }, + { + "table_name": "users", + "column_name": "id", + "column_default": "nextval('users_id_seq'::regclass)" + }, + { + "table_name": "roles", + "column_name": "id", + "column_default": "nextval('roles_id_seq'::regclass)" + }, + { + "table_name": "telescope_entries", + "column_name": "sequence", + "column_default": "nextval('telescope_entries_sequence_seq'::regclass)" + } +] \ No newline at end of file diff --git a/tests/fixtures/FixturesTraitTest/get_tables/mysql.json b/tests/fixtures/FixturesTraitTest/get_tables/mysql.json new file mode 100644 index 00000000..3a974371 --- /dev/null +++ b/tests/fixtures/FixturesTraitTest/get_tables/mysql.json @@ -0,0 +1,11 @@ +[ + { + "table_name": "users" + }, + { + "table_name": "migrations" + }, + { + "table_name": "groups" + } +] \ No newline at end of file diff --git a/tests/fixtures/FixturesTraitTest/get_tables/pgsql.json b/tests/fixtures/FixturesTraitTest/get_tables/pgsql.json new file mode 100644 index 00000000..5dc13090 --- /dev/null +++ b/tests/fixtures/FixturesTraitTest/get_tables/pgsql.json @@ -0,0 +1,37 @@ +[ + { + "table_name": "articles", + "column_name": "id", + "column_default": "nextval('articles_id_seq'::regclass)" + }, + { + "table_name": "workers", + "column_name": "id", + "column_default": "nextval('workers_id_seq'::regclass)" + }, + { + "table_name": "groups", + "column_name": "id", + "column_default": "nextval('groups_id_seq'::regclass)" + }, + { + "table_name": "homes", + "column_name": "id", + "column_default": "nextval('homes_id_seq'::regclass)" + }, + { + "table_name": "users", + "column_name": "id", + "column_default": "nextval('users_id_seq'::regclass)" + }, + { + "table_name": "roles", + "column_name": "id", + "column_default": "nextval('roles_id_seq'::regclass)" + }, + { + "table_name": "telescope_entries", + "column_name": "sequence", + "column_default": "nextval('telescope_entries_sequence_seq'::regclass)" + } +] \ No newline at end of file diff --git a/tests/fixtures/FixturesTraitTest/get_tables/tables.json b/tests/fixtures/FixturesTraitTest/get_tables/tables.json new file mode 100644 index 00000000..48556aa5 --- /dev/null +++ b/tests/fixtures/FixturesTraitTest/get_tables/tables.json @@ -0,0 +1,5 @@ +[ + "users", + "migrations", + "groups" +] diff --git a/tests/fixtures/FixturesTraitTest/prepare_sequences/sequences.sql b/tests/fixtures/FixturesTraitTest/prepare_sequences/sequences.sql index e6cd21dc..b81b3c8f 100644 --- a/tests/fixtures/FixturesTraitTest/prepare_sequences/sequences.sql +++ b/tests/fixtures/FixturesTraitTest/prepare_sequences/sequences.sql @@ -3,5 +3,4 @@ SELECT setval('workers_id_seq', (select coalesce(max(id), 1) from workers), (cas SELECT setval('groups_id_seq', (select coalesce(max(id), 1) from groups), (case when (select max(id) from groups) is NULL then false else true end)); SELECT setval('homes_id_seq', (select coalesce(max(id), 1) from homes), (case when (select max(id) from homes) is NULL then false else true end)); SELECT setval('users_id_seq', (select coalesce(max(id), 1) from users), (case when (select max(id) from users) is NULL then false else true end)); -SELECT setval('roles_id_seq', (select coalesce(max(id), 1) from roles), (case when (select max(id) from roles) is NULL then false else true end)); SELECT setval('telescope_entries_sequence_seq', (select coalesce(max(sequence), 1) from telescope_entries), (case when (select max(sequence) from telescope_entries) is NULL then false else true end)); diff --git a/tests/fixtures/FixturesTraitTest/prepare_sequences/tables.json b/tests/fixtures/FixturesTraitTest/prepare_sequences/tables.json deleted file mode 100644 index f85ced8b..00000000 --- a/tests/fixtures/FixturesTraitTest/prepare_sequences/tables.json +++ /dev/null @@ -1,7 +0,0 @@ -[ - "users", - "migrations", - "groups", - "tiger.state", - "projects" -] From 251726e31e583d4d82c8580f91ecafca1bfde388 Mon Sep 17 00:00:00 2001 From: Vitaly Iskrin Date: Sat, 2 Mar 2024 22:42:52 -0600 Subject: [PATCH 7/8] fix: use stdClass instead of arrays in getTable function --- src/Traits/FixturesTrait.php | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/Traits/FixturesTrait.php b/src/Traits/FixturesTrait.php index d5f8fbef..1b8b1f85 100644 --- a/src/Traits/FixturesTrait.php +++ b/src/Traits/FixturesTrait.php @@ -134,10 +134,10 @@ public function clearDatabase(array $tables, array $except): void public function getClearPsqlDatabaseQuery(array $tables, array $except = ['migrations']): string { return array_concat($tables, function ($table) use ($except) { - if (in_array($table['table_name'], $except)) { + if (in_array($table->table_name, $except)) { return ''; } else { - return "TRUNCATE {$table['table_name']} RESTART IDENTITY CASCADE; \n"; + return "TRUNCATE {$table->table_name} RESTART IDENTITY CASCADE; \n"; } }); } @@ -147,10 +147,10 @@ public function getClearMySQLDatabaseQuery(array $tables, array $except = ['migr $query = "SET FOREIGN_KEY_CHECKS = 0;\n"; $query .= array_concat($tables, function ($table) use ($except) { - if (in_array($table['table_name'], $except)) { + if (in_array($table->table_name, $except)) { return ''; } else { - return "TRUNCATE TABLE {$table['table_name']}; \n"; + return "TRUNCATE TABLE {$table->table_name}; \n"; } }); @@ -162,13 +162,13 @@ public function prepareSequences(array $except = []): void $except = array_merge($this->postgisTables, $this->prepareSequencesExceptTables, $except); $query = array_concat($this->getTables(), function ($item) use ($except) { - if (in_array($item['table_name'], $except)) { + if (in_array($item->table_name, $except)) { return ''; } else { - $sequenceName = str_replace(["nextval('", "'::regclass)"], '', $item['column_default']); + $sequenceName = str_replace(["nextval('", "'::regclass)"], '', $item->column_default); - return "SELECT setval('{$sequenceName}', (select coalesce(max({$item['column_name']}), 1) from " . - "{$item['table_name']}), (case when (select max({$item['column_name']}) from {$item['table_name']}) " . + return "SELECT setval('{$sequenceName}', (select coalesce(max({$item->column_name}), 1) from " . + "{$item->table_name}), (case when (select max({$item->column_name}) from {$item->table_name}) " . "is NULL then false else true end));\n"; } }); @@ -194,7 +194,7 @@ protected function getTables(): array ->getDoctrineSchemaManager() ->listTableNames(); - self::$tables = array_map(fn($value) => ['table_name' => $value], $tables); + self::$tables = array_map(fn($value) => (object) ['table_name' => $value], $tables); } elseif ($scheme === 'pgsql') { self::$tables = app('db.connection') ->table('information_schema.columns') From 52de1c64dd085960611ce4d5c749815faa50c491 Mon Sep 17 00:00:00 2001 From: Vitaly Iskrin Date: Sun, 3 Mar 2024 05:39:49 -0600 Subject: [PATCH 8/8] fix: use separate method for sequences --- src/Traits/FixturesTrait.php | 44 ++++++++++--------- tests/FixturesTraitTest.php | 29 ++++-------- .../clear_database/tables.json | 12 ++--- .../get_tables/information_schema.json | 37 ---------------- .../FixturesTraitTest/get_tables/mysql.json | 11 ----- .../FixturesTraitTest/get_tables/pgsql.json | 37 ---------------- 6 files changed, 34 insertions(+), 136 deletions(-) delete mode 100644 tests/fixtures/FixturesTraitTest/get_tables/information_schema.json delete mode 100644 tests/fixtures/FixturesTraitTest/get_tables/mysql.json delete mode 100644 tests/fixtures/FixturesTraitTest/get_tables/pgsql.json diff --git a/src/Traits/FixturesTrait.php b/src/Traits/FixturesTrait.php index 1b8b1f85..a3446930 100644 --- a/src/Traits/FixturesTrait.php +++ b/src/Traits/FixturesTrait.php @@ -9,6 +9,7 @@ trait FixturesTrait { protected static $tables; + protected static $sequences; protected $postgisTables = [ 'tiger.addrfeat', 'tiger.edges', @@ -134,10 +135,10 @@ public function clearDatabase(array $tables, array $except): void public function getClearPsqlDatabaseQuery(array $tables, array $except = ['migrations']): string { return array_concat($tables, function ($table) use ($except) { - if (in_array($table->table_name, $except)) { + if (in_array($table, $except)) { return ''; } else { - return "TRUNCATE {$table->table_name} RESTART IDENTITY CASCADE; \n"; + return "TRUNCATE {$table} RESTART IDENTITY CASCADE; \n"; } }); } @@ -147,10 +148,10 @@ public function getClearMySQLDatabaseQuery(array $tables, array $except = ['migr $query = "SET FOREIGN_KEY_CHECKS = 0;\n"; $query .= array_concat($tables, function ($table) use ($except) { - if (in_array($table->table_name, $except)) { + if (in_array($table, $except)) { return ''; } else { - return "TRUNCATE TABLE {$table->table_name}; \n"; + return "TRUNCATE TABLE {$table}; \n"; } }); @@ -161,7 +162,7 @@ public function prepareSequences(array $except = []): void { $except = array_merge($this->postgisTables, $this->prepareSequencesExceptTables, $except); - $query = array_concat($this->getTables(), function ($item) use ($except) { + $query = array_concat($this->getSequences(), function ($item) use ($except) { if (in_array($item->table_name, $except)) { return ''; } else { @@ -186,28 +187,29 @@ public function exportFile(TestResponse $response, string $fixture): void protected function getTables(): array { - $scheme = config('database.default'); - if (empty(self::$tables)) { - if ($scheme === 'mysql') { - $tables = app('db.connection') - ->getDoctrineSchemaManager() - ->listTableNames(); - - self::$tables = array_map(fn($value) => (object) ['table_name' => $value], $tables); - } elseif ($scheme === 'pgsql') { - self::$tables = app('db.connection') - ->table('information_schema.columns') - ->select('table_name', 'column_name', 'column_default') - ->where('column_default', 'LIKE', 'nextval%') - ->get() - ->toArray(); - } + self::$tables = app('db.connection') + ->getDoctrineSchemaManager() + ->listTableNames(); } return self::$tables; } + protected function getSequences() + { + if (empty(self::$sequences)) { + self::$sequences = app('db.connection') + ->table('information_schema.columns') + ->select('table_name', 'column_name', 'column_default') + ->where('column_default', 'LIKE', 'nextval%') + ->get() + ->toArray(); + } + + return self::$sequences; + } + protected function exportContent($content, string $fixture): void { if (env('FAIL_EXPORT_JSON', true)) { diff --git a/tests/FixturesTraitTest.php b/tests/FixturesTraitTest.php index 987a7a03..ad0c0f7c 100644 --- a/tests/FixturesTraitTest.php +++ b/tests/FixturesTraitTest.php @@ -153,24 +153,7 @@ public function testLoadTestDumpForPgsql() $this->loadTestDump(); } - public function testGetTablesPgsql() - { - $connection = $this->mockClass(Connection::class, [ - $this->functionCall('getQueryGrammar', [], new Grammar), - $this->functionCall('getPostProcessor', [], new Processor), - $this->functionCall('select', [], collect($this->getJsonFixture('get_tables/information_schema.json'))), - ], true); - - $this->app->instance('db.connection', $connection); - - Config::set('database.default', 'pgsql'); - - $this->getTables(); - - $this->assertEqualsFixture('get_tables/pgsql.json', self::$tables); - } - - public function testGetTablesMysql() + public function testGetTables() { $mock = $this->mockClass(MySQLSchemaManager::class, [ $this->functionCall('listTableNames', [], $this->getJsonFixture('get_tables/tables.json')), @@ -186,12 +169,18 @@ public function testGetTablesMysql() $this->getTables(); - $this->assertEqualsFixture('get_tables/mysql.json', self::$tables); + $this->assertEqualsFixture('get_tables/tables.json', self::$tables); } public function testPrepareSequences() { + $sequences = collect($this->getJsonFixture('prepare_sequences/information_schema.json')) + ->map(fn($item) => (object) $item); + $connection = $this->mockClass(Connection::class, [ + $this->functionCall('getQueryGrammar', [], new Grammar), + $this->functionCall('getPostProcessor', [], new Processor), + $this->functionCall('select', [], $sequences), $this->functionCall('unprepared', [$this->getFixture('prepare_sequences/sequences.sql')]), ], true); @@ -199,8 +188,6 @@ public function testPrepareSequences() Config::set('database.default', 'pgsql'); - self::$tables = $this->getJsonFixture('prepare_sequences/information_schema.json'); - $this->prepareSequences(['roles']); } diff --git a/tests/fixtures/FixturesTraitTest/clear_database/tables.json b/tests/fixtures/FixturesTraitTest/clear_database/tables.json index 1844e9bc..48556aa5 100644 --- a/tests/fixtures/FixturesTraitTest/clear_database/tables.json +++ b/tests/fixtures/FixturesTraitTest/clear_database/tables.json @@ -1,11 +1,5 @@ [ - { - "table_name": "users" - }, - { - "table_name": "migrations" - }, - { - "table_name": "groups" - } + "users", + "migrations", + "groups" ] diff --git a/tests/fixtures/FixturesTraitTest/get_tables/information_schema.json b/tests/fixtures/FixturesTraitTest/get_tables/information_schema.json deleted file mode 100644 index 26c78230..00000000 --- a/tests/fixtures/FixturesTraitTest/get_tables/information_schema.json +++ /dev/null @@ -1,37 +0,0 @@ -[ - { - "table_name": "articles", - "column_name": "id", - "column_default": "nextval('articles_id_seq'::regclass)" - }, - { - "table_name": "workers", - "column_name": "id", - "column_default": "nextval('workers_id_seq'::regclass)" - }, - { - "table_name": "groups", - "column_name": "id", - "column_default": "nextval('groups_id_seq'::regclass)" - }, - { - "table_name": "homes", - "column_name": "id", - "column_default": "nextval('homes_id_seq'::regclass)" - }, - { - "table_name": "users", - "column_name": "id", - "column_default": "nextval('users_id_seq'::regclass)" - }, - { - "table_name": "roles", - "column_name": "id", - "column_default": "nextval('roles_id_seq'::regclass)" - }, - { - "table_name": "telescope_entries", - "column_name": "sequence", - "column_default": "nextval('telescope_entries_sequence_seq'::regclass)" - } -] \ No newline at end of file diff --git a/tests/fixtures/FixturesTraitTest/get_tables/mysql.json b/tests/fixtures/FixturesTraitTest/get_tables/mysql.json deleted file mode 100644 index 3a974371..00000000 --- a/tests/fixtures/FixturesTraitTest/get_tables/mysql.json +++ /dev/null @@ -1,11 +0,0 @@ -[ - { - "table_name": "users" - }, - { - "table_name": "migrations" - }, - { - "table_name": "groups" - } -] \ No newline at end of file diff --git a/tests/fixtures/FixturesTraitTest/get_tables/pgsql.json b/tests/fixtures/FixturesTraitTest/get_tables/pgsql.json deleted file mode 100644 index 5dc13090..00000000 --- a/tests/fixtures/FixturesTraitTest/get_tables/pgsql.json +++ /dev/null @@ -1,37 +0,0 @@ -[ - { - "table_name": "articles", - "column_name": "id", - "column_default": "nextval('articles_id_seq'::regclass)" - }, - { - "table_name": "workers", - "column_name": "id", - "column_default": "nextval('workers_id_seq'::regclass)" - }, - { - "table_name": "groups", - "column_name": "id", - "column_default": "nextval('groups_id_seq'::regclass)" - }, - { - "table_name": "homes", - "column_name": "id", - "column_default": "nextval('homes_id_seq'::regclass)" - }, - { - "table_name": "users", - "column_name": "id", - "column_default": "nextval('users_id_seq'::regclass)" - }, - { - "table_name": "roles", - "column_name": "id", - "column_default": "nextval('roles_id_seq'::regclass)" - }, - { - "table_name": "telescope_entries", - "column_name": "sequence", - "column_default": "nextval('telescope_entries_sequence_seq'::regclass)" - } -] \ No newline at end of file