setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); // Create test table with indexes $pdo->exec(' CREATE TABLE users ( id INTEGER PRIMARY KEY AUTOINCREMENT, email TEXT NOT NULL UNIQUE, name TEXT NOT NULL, status TEXT, created_at TEXT ) '); $pdo->exec('CREATE INDEX idx_users_status ON users(status)'); $pdo->exec('CREATE INDEX idx_users_created_at ON users(created_at)'); $pdo->exec('CREATE INDEX idx_users_email_status ON users(email, status)'); $this->connection = new PdoConnection($pdo, 'sqlite'); $this->analyzer = new IndexAnalyzer($this->connection); }); it('can get all indexes for a table', function () { $indexes = $this->analyzer->getTableIndexes('users'); expect($indexes)->toBeArray(); expect(count($indexes))->toBeGreaterThan(0); // Should have at least: PRIMARY, UNIQUE, and our custom indexes $indexNames = array_column($indexes, 'name'); expect($indexNames)->toContain('idx_users_status'); expect($indexNames)->toContain('idx_users_created_at'); }); it('detects index usage in query', function () { $sql = 'SELECT * FROM users WHERE status = "active"'; $analysis = $this->analyzer->analyzeQuery($sql); expect($analysis)->toBeArray(); expect($analysis)->toHaveKey('query'); expect($analysis)->toHaveKey('indexes_used'); expect($analysis)->toHaveKey('key_type'); expect($analysis['query'])->toBe($sql); }); it('detects composite index columns correctly', function () { $indexes = $this->analyzer->getTableIndexes('users'); $compositeIndex = array_values(array_filter($indexes, function ($index) { return $index['name'] === 'idx_users_email_status'; }))[0] ?? null; expect($compositeIndex)->not->toBeNull(); expect($compositeIndex['columns'])->toBe(['email', 'status']); }); it('identifies index types correctly', function () { $indexes = $this->analyzer->getTableIndexes('users'); foreach ($indexes as $index) { expect($index['type'])->toBeInstanceOf(IndexType::class); } }); it('marks unique indexes correctly', function () { $indexes = $this->analyzer->getTableIndexes('users'); $uniqueIndex = array_values(array_filter($indexes, function ($index) { return str_contains($index['name'], 'email'); }))[0] ?? null; expect($uniqueIndex)->not->toBeNull(); expect($uniqueIndex['is_unique'])->toBeTrue(); }); it('analyzes queries without indexes', function () { $sql = 'SELECT * FROM users WHERE name LIKE "%John%"'; $analysis = $this->analyzer->analyzeQuery($sql); expect($analysis['indexes_used'])->toBeArray(); // SQLite might use table scan for LIKE queries expect($analysis['key_type'])->toBeIn(['scan', 'ALL', 'index']); }); });