Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/_src/content.py
Original file line number Diff line number Diff line change
Expand Up @@ -324,7 +324,7 @@ def page(group, slug, title, summary, *sections, source="src/Migrator/Framework/
''', '''
migration.Delete.Index("IX_Users_Name").FromTable("Users");
''')),
section("Provider options", '<p>Index definitions also expose IncludeColumns, FilterItems and Clustered. These options are provider-specific. Oracle rejects included and clustered index requests; SQLite reconstruction rejects existing index SQL with explicit COLLATE clauses. Preview handles simple indexes and rejects unsupported options.</p>'),
section("Provider options", '<p>Index definitions also expose IncludeColumns, FilterItems and Clustered. SQL Server (2008+), PostgreSQL and SQLite support filters on any table column, including columns outside KeyColumns. EqualTo or NotEqualTo with null (or DBNull.Value) becomes IS NULL or IS NOT NULL. GetIndexes(table), also available as Schema.Table(table).Indexes() in fluent migrations, reads back the keys, included columns, flags and supported FilterItems. Filters preserve null checks and escaped string values.</p><p>UnsupportedFilterBehavior defaults to UnsupportedIndexFilterBehavior.Throw. Set it to Ignore, or append OnUnsupportedFilter(UnsupportedIndexFilterBehavior.Ignore) in fluent code, to create an unfiltered index on a provider that cannot apply the filters. For unique indexes this enforces uniqueness across all rows. This option only affects unsupported filters; it does not suppress other invalid options or execution failures.</p><p>Oracle retains its limited non-unique, key-column expression emulation and cannot read those expressions back as FilterItems; non-key filters and unique filtered indexes use the chosen unsupported behavior. Oracle rejects included and clustered index requests; SQLite reconstruction rejects existing index SQL with explicit COLLATE clauses.</p><p>The fallback policy is an authoring option and is not stored in database metadata. Preview handles simple indexes and rejects filtered indexes even in Ignore mode.</p>'),
section("Unique index or unique constraint?", '<p>Use UniqueConstraint for a table-level invariant and an Index with Unique for an index definition. Do not infer ownership from a generated name. SQLite RemoveAllIndexes preserves declared table UNIQUE constraints; remove those through the constraint APIs. Check query plans and data cardinality when choosing index keys.</p>'), source="src/Migrator/Framework/Index.cs")

page("Schema basics", "constraints", "Keys and constraints", "Declare table invariants independently of column attributes.",
Expand Down
2 changes: 1 addition & 1 deletion docs/assets/search-index.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion docs/guide/indexes.html

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

30 changes: 30 additions & 0 deletions docs/runner-guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,36 @@ migration.Create.Index("IX_Users_Email").OnTable("Users").WithColumns("Email");
migration.Delete.Index("IX_Users_Email").FromTable("Users");
migration.Delete.Column("Email").FromTable("Users");
```

Filtered indexes can use columns outside the index keys on SQL Server (2008+), PostgreSQL and SQLite. For example, enforce unique identifiers only for active users with a non-null identifier:

```csharp
// FilterItem and FilterType are in Providers.Models.Indexes and its Enums namespace.
migration.Create.Index("UX_ActiveUsers").OnTable("Users")
.WithColumns("IpaUserIdentifier").Unique()
.WithFilter(
new FilterItem { ColumnName = "IpaUserIdentifier", Filter = FilterType.NotEqualTo, Value = null },
new FilterItem { ColumnName = "Archive", Filter = FilterType.EqualTo, Value = 0 })
.OnUnsupportedFilter(UnsupportedIndexFilterBehavior.Throw);
```

Classic migrations use the same `FilterItems` list on `Index`, with
`UnsupportedFilterBehavior = UnsupportedIndexFilterBehavior.Throw` (the default).
Choose `Ignore` to omit all filters when the provider cannot apply them. The resulting
index is unfiltered; a unique index then constrains all rows. Supported providers
still apply the filters in Ignore mode, and database errors are never swallowed.
Oracle retains its limited non-unique, key-column expression emulation; unique or
non-key filters use the unsupported behavior. Other providers without implemented
filter support, including the SQL Server 2005 dialect, also use that behavior.

Read the definition back with `Database.GetIndexes("Users")` or
`Schema.Table("Users").Indexes()` inside a fluent migration. SQL Server, PostgreSQL
and SQLite return supported filter predicates, including null checks, together with
the index name, key order, included columns and flags. Those definitions can be used
to recreate the index. Predicates outside the `FilterItems` model (such as `OR`) fail
explicitly. Oracle expression-index metadata remains outside this read-back support.
The unsupported-filter policy is not stored in the database and reads back as the
default. SQL preview still rejects filtered indexes, including Ignore mode.

Table definitions, column additions and column alterations share the same type
and option methods. Each named column must specify its type. `AsDateTime()` maps
Expand Down
Loading
Loading