Skip to content
Merged
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
73 changes: 73 additions & 0 deletions docs/fluent-operation-coverage.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
{
"AddTable": "Create.Table(...).WithFields(...) / WithEngine(...)",
"AddColumn": "Create.Column(...).OfType(...).WithPrecision(...)",
"ChangeColumn": "Alter.Column(...).OfType(...).WithPrecision(...)",
"AddPrimaryKey": "Create.PrimaryKey(...) / Create.NonClusteredPrimaryKey(...)",
"AddPrimaryKeyNonClustered": "Create.PrimaryKey(...) / Create.NonClusteredPrimaryKey(...)",
"AddForeignKey": "Create.ForeignKey(...); supply a generated name for GenerateForeignKey convenience overloads",
"GenerateForeignKey": "Create.ForeignKey(...); supply a generated name for GenerateForeignKey convenience overloads",
"AddUniqueConstraint": "Create.Unique(...) / Create.Check(...)",
"AddCheckConstraint": "Create.Unique(...) / Create.Check(...)",
"AddIndex": "Create.Index(table, Index)",
"AddView": "Create.View(...), both view-definition forms",
"RemoveTable": "Delete.Table/Column/ForeignKey/Constraint/PrimaryKey/Default/Index/AllIndexes/AllConstraints/ForeignKeysForColumn",
"RemoveColumn": "Delete.Table/Column/ForeignKey/Constraint/PrimaryKey/Default/Index/AllIndexes/AllConstraints/ForeignKeysForColumn",
"RemoveForeignKey": "Delete.Table/Column/ForeignKey/Constraint/PrimaryKey/Default/Index/AllIndexes/AllConstraints/ForeignKeysForColumn",
"RemoveConstraint": "Delete.Table/Column/ForeignKey/Constraint/PrimaryKey/Default/Index/AllIndexes/AllConstraints/ForeignKeysForColumn",
"RemovePrimaryKey": "Delete.Table/Column/ForeignKey/Constraint/PrimaryKey/Default/Index/AllIndexes/AllConstraints/ForeignKeysForColumn",
"RemoveColumnDefaultValue": "Delete.Table/Column/ForeignKey/Constraint/PrimaryKey/Default/Index/AllIndexes/AllConstraints/ForeignKeysForColumn",
"RemoveIndex": "Delete.Table/Column/ForeignKey/Constraint/PrimaryKey/Default/Index/AllIndexes/AllConstraints/ForeignKeysForColumn",
"RemoveAllIndexes": "Delete.Table/Column/ForeignKey/Constraint/PrimaryKey/Default/Index/AllIndexes/AllConstraints/ForeignKeysForColumn",
"RemoveAllConstraints": "Delete.Table/Column/ForeignKey/Constraint/PrimaryKey/Default/Index/AllIndexes/AllConstraints/ForeignKeysForColumn",
"RemoveAllForeignKeys": "Delete.Table/Column/ForeignKey/Constraint/PrimaryKey/Default/Index/AllIndexes/AllConstraints/ForeignKeysForColumn",
"RenameTable": "Rename.Table(...) / Rename.Column(...)",
"RenameColumn": "Rename.Table(...) / Rename.Column(...)",
"Insert": "Insert.IntoTable(...).Row(...)[.IfNotExists(...)]",
"InsertIfNotExists": "Insert.IntoTable(...).Row(...)[.IfNotExists(...)]",
"Update": "Update.Table(...).Set(...).Where(...) / WhereSql(...)",
"Delete": "Delete.FromTable(...).Where(...)",
"TruncateTable": "Execute.Truncate(...)",
"CopyDataFromTableToTable": "Execute.CopyData(...) / Execute.UpdateFrom(...)",
"UpdateTargetFromSource": "Execute.CopyData(...) / Execute.UpdateFrom(...)",
"ExecuteNonQuery": "Execute.Sql(...) / Script(...) / EmbeddedScript(...)",
"ExecuteQuery": "Schema.Query(...) / Strings(...) / Scalar(...) / NullableScalar<T>(...)",
"ExecuteStringQuery": "Schema.Query(...) / Strings(...) / Scalar(...) / NullableScalar<T>(...)",
"ExecuteScalar": "Schema.Query(...) / Strings(...) / Scalar(...) / NullableScalar<T>(...)",
"Select": "Schema.Select(...) / SelectScalar(...); raw selection overloads through explicit Context",
"SelectComplex": "Schema.Select(...) / SelectScalar(...); raw selection overloads through explicit Context",
"SelectScalar": "Schema.Select(...) / SelectScalar(...); raw selection overloads through explicit Context",
"GetColumns": "Schema.Table(...).Columns/Column/Indexes/ForeignKeys/ContentSize/NullableContentSize",
"GetColumnByName": "Schema.Table(...).Columns/Column/Indexes/ForeignKeys/ContentSize/NullableContentSize",
"GetIndexes": "Schema.Table(...).Columns/Column/Indexes/ForeignKeys/ContentSize/NullableContentSize",
"GetForeignKeyConstraints": "Schema.Table(...).Columns/Column/Indexes/ForeignKeys/ContentSize/NullableContentSize",
"GetColumnContentSize": "Schema.Table(...).Columns/Column/Indexes/ForeignKeys/ContentSize/NullableContentSize",
"TableExists": "Schema.Table(...).Exists/ColumnExists/ConstraintExists/IndexExists/PrimaryKeyExists",
"ColumnExists": "Schema.Table(...).Exists/ColumnExists/ConstraintExists/IndexExists/PrimaryKeyExists",
"ConstraintExists": "Schema.Table(...).Exists/ColumnExists/ConstraintExists/IndexExists/PrimaryKeyExists",
"IndexExists": "Schema.Table(...).Exists/ColumnExists/ConstraintExists/IndexExists/PrimaryKeyExists",
"PrimaryKeyExists": "Schema.Table(...).Exists/ColumnExists/ConstraintExists/IndexExists/PrimaryKeyExists",
"ViewExists": "Schema.ViewExists/DatabaseExists/Databases/Tables",
"DatabaseExists": "Schema.ViewExists/DatabaseExists/Databases/Tables",
"GetDatabases": "Schema.ViewExists/DatabaseExists/Databases/Tables",
"GetTables": "Schema.ViewExists/DatabaseExists/Databases/Tables",
"QuoteColumnNameIfRequired": "Schema.QuoteColumn/QuoteColumns/QuoteTable/ParameterName/Encode/Concatenate",
"QuoteColumnNamesIfRequired": "Schema.QuoteColumn/QuoteColumns/QuoteTable/ParameterName/Encode/Concatenate",
"QuoteTableNameIfRequired": "Schema.QuoteColumn/QuoteColumns/QuoteTable/ParameterName/Encode/Concatenate",
"GenerateParameterName": "Schema.QuoteColumn/QuoteColumns/QuoteTable/ParameterName/Encode/Concatenate",
"Encode": "Schema.QuoteColumn/QuoteColumns/QuoteTable/ParameterName/Encode/Concatenate",
"Concatenate": "Schema.QuoteColumn/QuoteColumns/QuoteTable/ParameterName/Encode/Concatenate",
"CreateDatabases": "Administration.CreateDatabase/DropDatabase/SwitchDatabase/KillConnections",
"DropDatabases": "Administration.CreateDatabase/DropDatabase/SwitchDatabase/KillConnections",
"SwitchDatabase": "Administration.CreateDatabase/DropDatabase/SwitchDatabase/KillConnections",
"KillDatabaseConnections": "Administration.CreateDatabase/DropDatabase/SwitchDatabase/KillConnections",
"IsThisProvider": "IfDatabase(...); Context.IsThisProvider(...) for imperative branching",
"CreateCommand": "Execute.WithCommand(...); explicit Context for advanced command lifetime",
"GetCommand": "Execute.WithCommand(...); explicit Context for advanced command lifetime",
"BeginTransaction": "Explicit Context history/transaction APIs; not schema expressions",
"Commit": "Explicit Context history/transaction APIs; not schema expressions",
"Rollback": "Explicit Context history/transaction APIs; not schema expressions",
"MigrationApplied": "Explicit Context history/transaction APIs; not schema expressions",
"MigrationUnApplied": "Explicit Context history/transaction APIs; not schema expressions",
"IsMigrationApplied": "Explicit Context history/transaction APIs; not schema expressions",
"ExecuteSchemaBuilder": "Execute.WithProvider(p => p.ExecuteSchemaBuilder(legacyBuilder))"
}
20 changes: 20 additions & 0 deletions docs/fluent-operation-coverage.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Imperative/fluent capability inventory

The machine-readable [inventory](fluent-operation-coverage.json) maps every named method family on `ITransformationProvider` to fluent authoring, schema inspection or an explicit context API. `FluentCoverageTests` checks this inventory against reflection so new normal-API methods require an entry. Overload convenience is consolidated into typed definitions; this does not promise FluentMigrator source compatibility.

| Capability | Authoring / inspection | Validation evidence |
| --- | --- | --- |
| Complete tables, columns, types, defaults, identity, nullability and precision | `Create.Table`, `Create.Column`, `Alter.Column` | Complete table snapshot, SQLite schema/data, provider precision tests |
| Keys, foreign-key actions, unique/check constraints | `Create.PrimaryKey`, `ForeignKey`, `Unique`, `Check` | Provider constraint/action suites; unsupported providers throw |
| Index keys, include/filter/cluster options | `Create.Index` with the existing `Index` model | Provider index suites; preview rejects unsupported options |
| Views and joins | `Create.View` with either normal definition model | Definitions snapshot caller input; provider implementations retain their own limitations |
| Drop/rename operations | `Delete` / `Rename` | SQLite schema tests, reversal tests; destructive changes need explicit reverse definitions |
| Inserts, conditional insert, update, delete | `Insert`, `Update`, `Delete.FromTable` | FluentDataChangesAndSchemaReadsPersistExpectedRows |
| Truncate, data copy, update from another table | `Execute.Truncate/CopyData/UpdateFrom` | Normal provider tests; mutable pair snapshot regression |
| SQL, files, resources | `Execute.Sql/Script/EmbeddedScript` | SQL execution/preview tests; provider-specific batch splitting is separate work |
| Scalars/readers/existence/metadata | `Schema`, `Schema.Table`, `Select`, `SelectScalar` | Reader disposal and persisted-data assertions; nullable helpers are additive |
| Database administration | `Administration` | Typed operations flag transaction incompatibility; backend capabilities still apply |
| Provider conditions, commands/connections | `IfDatabase`, `Execute.WithCommand/WithConnection/WithProvider` | Inactive reversal, explicit preview rejection; callbacks execute trusted code |
| History and transaction administration | Explicit `Context` | Runner transaction/scope/history regressions; not schema expressions |

Execution coverage is broader than SQL-generation and automatic-reversal coverage. Unsupported preview/reversal operations fail explicitly. The inventory is an API coverage check, not a claim that every overload has an independent live test on every engine. Continue adding behavioral provider tests when changing an operation's semantics.
17 changes: 17 additions & 0 deletions src/Migrator.Tests/FluentCoverageTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text.Json;
using DotNetProjects.Migrator.Framework;
using NUnit.Framework;
namespace Migrator.Tests;
public class FluentCoverageTests
{
[Test] public void EveryNormalApiMethodFamilyHasAnExplicitFluentOrContextMapping()
{
var inventory = JsonSerializer.Deserialize<Dictionary<string, string>>(File.ReadAllText(Path.Combine(System.AppContext.BaseDirectory, "fluent-operation-coverage.json")));
var methods = typeof(ITransformationProvider).GetMethods().Where(m => !m.IsSpecialName).Select(m => m.Name).Distinct().ToArray();
Assert.That(inventory.Keys, Is.EquivalentTo(methods));
Assert.That(inventory.Values.All(v => !string.IsNullOrWhiteSpace(v)), Is.True);
}
}
Loading
Loading