name)->toBe('idx_users_email'); expect($index->columns)->toBe(['email']); expect($index->type)->toBe(AdvancedIndexType::INDEX); expect($index->whereClause)->toBeNull(); expect($index->options)->toBeEmpty(); expect($index->isFunctional)->toBeFalse(); }); test('creates a partial index definition', function () { $index = AdvancedIndexDefinition::partial( 'idx_users_email', ['email'], AdvancedIndexType::INDEX, 'active = true' ); expect($index->name)->toBe('idx_users_email'); expect($index->columns)->toBe(['email']); expect($index->type)->toBe(AdvancedIndexType::INDEX); expect($index->whereClause)->toBe('active = true'); expect($index->options)->toBeEmpty(); }); test('creates a functional index definition', function () { $index = AdvancedIndexDefinition::functional( 'idx_users_lower_email', AdvancedIndexType::INDEX, ['LOWER(email)'] ); expect($index->name)->toBe('idx_users_lower_email'); expect($index->columns)->toBeEmpty(); expect($index->type)->toBe(AdvancedIndexType::INDEX); expect($index->isFunctional)->toBeTrue(); expect($index->expressions)->toBe(['LOWER(email)']); }); test('creates a GIN index definition', function () { $index = AdvancedIndexDefinition::gin( 'idx_documents_content', ['content'] ); expect($index->name)->toBe('idx_documents_content'); expect($index->columns)->toBe(['content']); expect($index->type)->toBe(AdvancedIndexType::GIN); }); test('creates a GiST index definition', function () { $index = AdvancedIndexDefinition::gist( 'idx_locations_position', ['position'] ); expect($index->name)->toBe('idx_locations_position'); expect($index->columns)->toBe(['position']); expect($index->type)->toBe(AdvancedIndexType::GIST); }); test('creates a BTREE index definition with options', function () { $index = AdvancedIndexDefinition::btree( 'idx_users_name', ['first_name', 'last_name'], ['fillfactor' => 70] ); expect($index->name)->toBe('idx_users_name'); expect($index->columns)->toBe(['first_name', 'last_name']); expect($index->type)->toBe(AdvancedIndexType::BTREE); expect($index->options)->toBe(['fillfactor' => 70]); }); test('generates PostgreSQL partial index SQL', function () { $index = AdvancedIndexDefinition::partial( 'idx_users_email', ['email'], AdvancedIndexType::INDEX, 'active = true' ); $sql = $index->toSql('pgsql', 'users'); expect($sql)->toBe('CREATE INDEX "idx_users_email" ON "users" ("email") WHERE active = true'); }); test('generates PostgreSQL functional index SQL', function () { $index = AdvancedIndexDefinition::functional( 'idx_users_lower_email', AdvancedIndexType::INDEX, ['LOWER(email)'] ); $sql = $index->toSql('pgsql', 'users'); expect($sql)->toBe('CREATE INDEX "idx_users_lower_email" ON "users" (LOWER(email))'); }); test('generates PostgreSQL GIN index SQL', function () { $index = AdvancedIndexDefinition::gin( 'idx_documents_content', ['content'] ); $sql = $index->toSql('pgsql', 'documents'); expect($sql)->toBe('CREATE INDEX "idx_documents_content" ON "documents" USING gin ("content")'); }); test('generates PostgreSQL GiST index SQL', function () { $index = AdvancedIndexDefinition::gist( 'idx_locations_position', ['position'] ); $sql = $index->toSql('pgsql', 'locations'); expect($sql)->toBe('CREATE INDEX "idx_locations_position" ON "locations" USING gist ("position")'); }); test('generates PostgreSQL index SQL with options', function () { $index = AdvancedIndexDefinition::btree( 'idx_users_email', ['email'], ['fillfactor' => 70] ); $sql = $index->toSql('pgsql', 'users'); // Note: PostgreSQL doesn't use USING btree by default, so it's not in the SQL expect($sql)->toBe('CREATE INDEX "idx_users_email" ON "users" ("email")'); }); test('throws exception for partial index in MySQL', function () { $index = AdvancedIndexDefinition::partial( 'idx_users_email', ['email'], AdvancedIndexType::INDEX, 'active = true' ); expect(fn () => $index->toSql('mysql', 'users')) ->toThrow(\InvalidArgumentException::class, 'MySQL does not support partial indexes'); }); test('generates MySQL functional index SQL', function () { $index = AdvancedIndexDefinition::functional( 'idx_users_lower_email', AdvancedIndexType::INDEX, ['LOWER(email)'] ); $sql = $index->toSql('mysql', 'users'); // MySQL 8.0+ supports functional indexes with ALTER TABLE expect($sql)->toBe('ALTER TABLE `users` ADD INDEX `idx_users_lower_email` (LOWER(email))'); }); test('throws exception for unsupported index type in MySQL', function () { $index = AdvancedIndexDefinition::gin( 'idx_documents_content', ['content'] ); expect(fn () => $index->toSql('mysql', 'documents')) ->toThrow(\InvalidArgumentException::class, 'Index type gin is not supported by mysql'); }); test('throws exception for unsupported database driver', function () { $index = AdvancedIndexDefinition::btree( 'idx_users_email', ['email'] ); expect(fn () => $index->toSql('unsupported_driver', 'users')) ->toThrow(\InvalidArgumentException::class, 'Unsupported driver: unsupported_driver'); });