Skip to content

Commit 83524bd

Browse files
masterbaterGromNaN
authored andcommitted
feat: exclude system collections, add engine collection type to getTables
1 parent c49a73f commit 83524bd

File tree

2 files changed

+108
-11
lines changed

2 files changed

+108
-11
lines changed

src/Schema/Builder.php

Lines changed: 33 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
use function sort;
3030
use function sprintf;
3131
use function str_ends_with;
32+
use function str_starts_with;
3233
use function substr;
3334
use function usort;
3435

@@ -148,11 +149,25 @@ public function getTables($schema = null)
148149
$db = $this->connection->getDatabase($schema);
149150
$collections = [];
150151

151-
foreach ($db->listCollectionNames() as $collectionName) {
152-
$stats = $db->selectCollection($collectionName)->aggregate([
153-
['$collStats' => ['storageStats' => ['scale' => 1]]],
154-
['$project' => ['storageStats.totalSize' => 1]],
155-
])->toArray();
152+
foreach ($db->listCollections() as $collectionInfo) {
153+
$collectionName = $collectionInfo->getName();
154+
155+
// Skip system collections
156+
if (str_starts_with($collectionName, 'system.')) {
157+
continue;
158+
}
159+
160+
// Skip views it doesnt suport aggregate
161+
$isView = ($collectionInfo['type'] ?? '') === 'view';
162+
$stats = null;
163+
164+
if (! $isView) {
165+
// Only run aggregation if it's a normal collection
166+
$stats = $db->selectCollection($collectionName)->aggregate([
167+
['$collStats' => ['storageStats' => ['scale' => 1]]],
168+
['$project' => ['storageStats.totalSize' => 1]],
169+
])->toArray();
170+
}
156171

157172
$collections[] = [
158173
'name' => $collectionName,
@@ -161,13 +176,11 @@ public function getTables($schema = null)
161176
'size' => $stats[0]?->storageStats?->totalSize ?? null,
162177
'comment' => null,
163178
'collation' => null,
164-
'engine' => null,
179+
'engine' => $isView ? 'view' : 'collection',
165180
];
166181
}
167182

168-
usort($collections, function ($a, $b) {
169-
return $a['name'] <=> $b['name'];
170-
});
183+
usort($collections, fn ($a, $b) => $a['name'] <=> $b['name']);
171184

172185
return $collections;
173186
}
@@ -196,6 +209,9 @@ public function getTableListing($schema = null, $schemaQualified = false)
196209

197210
$collections = array_merge(...array_values($collections));
198211

212+
// Exclude system collections before sorting
213+
$collections = array_filter($collections, fn ($name) => ! str_starts_with($name, 'system.'));
214+
199215
sort($collections);
200216

201217
return $collections;
@@ -346,7 +362,14 @@ protected function getAllCollections()
346362
{
347363
$collections = [];
348364
foreach ($this->connection->getDatabase()->listCollections() as $collection) {
349-
$collections[] = $collection->getName();
365+
$name = $collection->getName();
366+
367+
// Skip system collections
368+
if (str_starts_with($name, 'system.')) {
369+
continue;
370+
}
371+
372+
$collections[] = $name;
350373
}
351374

352375
return $collections;

tests/SchemaTest.php

Lines changed: 75 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,15 +17,17 @@
1717
use function collect;
1818
use function count;
1919
use function sprintf;
20+
use function str_starts_with;
2021

2122
class SchemaTest extends TestCase
2223
{
2324
public function tearDown(): void
2425
{
25-
$database = $this->getConnection('mongodb')->getMongoDB();
26+
$database = $this->getConnection('mongodb')->getDatabase();
2627
assert($database instanceof Database);
2728
$database->dropCollection('newcollection');
2829
$database->dropCollection('newcollection_two');
30+
$database->dropCollection('test_view');
2931

3032
parent::tearDown();
3133
}
@@ -397,6 +399,13 @@ public function testGetTables()
397399
DB::connection('mongodb')->table('newcollection_two')->insert(['test' => 'value']);
398400
$dbName = DB::connection('mongodb')->getDatabaseName();
399401

402+
// Create a view (this creates system.views)
403+
DB::connection('mongodb')->getDatabase()->command([
404+
'create' => 'test_view',
405+
'viewOn' => 'newcollection',
406+
'pipeline' => [],
407+
]);
408+
400409
$tables = Schema::getTables();
401410
$this->assertIsArray($tables);
402411
$this->assertGreaterThanOrEqual(2, count($tables));
@@ -413,6 +422,9 @@ public function testGetTables()
413422
$this->assertEquals($dbName . '.newcollection', $table['schema_qualified_name']);
414423
$found = true;
415424
}
425+
426+
// Ensure system collections are excluded
427+
$this->assertFalse(str_starts_with($table['name'], 'system.'));
416428
}
417429

418430
if (! $found) {
@@ -425,12 +437,22 @@ public function testGetTableListing()
425437
DB::connection('mongodb')->table('newcollection')->insert(['test' => 'value']);
426438
DB::connection('mongodb')->table('newcollection_two')->insert(['test' => 'value']);
427439

440+
// Create a view (this creates system.views)
441+
DB::connection('mongodb')->getDatabase()->command([
442+
'create' => 'test_view',
443+
'viewOn' => 'newcollection',
444+
'pipeline' => [],
445+
]);
446+
428447
$tables = Schema::getTableListing();
429448

430449
$this->assertIsArray($tables);
431450
$this->assertGreaterThanOrEqual(2, count($tables));
432451
$this->assertContains('newcollection', $tables);
433452
$this->assertContains('newcollection_two', $tables);
453+
454+
// Ensure system collections are excluded
455+
$this->assertNotContains('system.views', $tables);
434456
}
435457

436458
public function testGetTableListingBySchema()
@@ -453,6 +475,58 @@ public function testGetTableListingBySchema()
453475
$this->assertContains('newcollection', $tables);
454476
$this->assertContains('newcollection_two', $tables);
455477
}
478+
// Protected method cannot test
479+
// public function testGetAllCollections()
480+
// {
481+
// // Insert test data into normal collections
482+
// DB::connection('mongodb')->table('newcollection')->insert(['test' => 'value']);
483+
// DB::connection('mongodb')->table('newcollection_two')->insert(['test' => 'value']);
484+
485+
// // Create a view (this creates system.views)
486+
// DB::connection('mongodb')->getDatabase()->command([
487+
// 'create' => 'test_view',
488+
// 'viewOn' => 'newcollection',
489+
// 'pipeline' => [],
490+
// ]);
491+
492+
// $collections = Schema::getAllCollections();
493+
494+
// $this->assertIsArray($collections);
495+
// $this->assertGreaterThanOrEqual(2, count($collections));
496+
497+
// // Ensure normal collections are present
498+
// $this->assertContains('newcollection', $collections);
499+
// $this->assertContains('newcollection_two', $collections);
500+
501+
// // Ensure system collections are excluded
502+
// $this->assertNotContains('system.views', $collections);
503+
// }
504+
505+
public function testSystemCollectionsArePresentButFiltered()
506+
{
507+
// Create a view to trigger system.views collection
508+
DB::connection('mongodb')->getDatabase()->command([
509+
'create' => 'test_view',
510+
'viewOn' => 'newcollection',
511+
'pipeline' => [],
512+
]);
513+
514+
// Get all collections directly from MongoDB
515+
$allCollections = DB::connection('mongodb')->getDatabase()->listCollectionNames();
516+
517+
// Ensure the system.views collection exists in MongoDB
518+
$this->assertContains('system.views', $allCollections);
519+
520+
// Ensure Schema::getTables does NOT include system collections
521+
$tables = Schema::getTables();
522+
foreach ($tables as $table) {
523+
$this->assertFalse(str_starts_with($table['name'], 'system.'));
524+
}
525+
526+
// Ensure Schema::getTableListing does NOT include system collections
527+
$tableListing = Schema::getTableListing();
528+
$this->assertNotContains('system.views', $tableListing);
529+
}
456530

457531
public function testGetColumns()
458532
{

0 commit comments

Comments
 (0)