Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
55 commits
Select commit Hold shift + click to select a range
b9f1fba
Working on AddIndex Fix
Aug 21, 2025
9c048e0
Added AddIndex UNIQUE test
Aug 21, 2025
1cfc9bc
SQLite does not support named primary keys - we check if there is a p…
Aug 22, 2025
4d561f8
Add comparison for filter items
Aug 22, 2025
f922548
Add interval for Oracle
Aug 22, 2025
f6d9ccc
Add filter items implementation in Transformation Provider
Aug 22, 2025
75222cd
Interval Oracle
Aug 22, 2025
545e024
Rewrite AddIndex in SqlServer
Aug 22, 2025
ed8112d
Added FilterItem
Aug 22, 2025
f9ff212
Added FilterType
Aug 22, 2025
f131a67
Minor changes in integration tests
Aug 22, 2025
d802a51
Small refactoring
Aug 22, 2025
33e94ce
Added SQL Server implementation of filtered index
Aug 22, 2025
53665eb
Added Postgre AddIndex UNIQUE test
Aug 22, 2025
db4b0ad
Added SQL AddIndex UNIQUE test
Aug 22, 2025
30cb42c
Oracle unique test
Aug 22, 2025
d25394e
SQLite Unique test
Aug 22, 2025
831c7ee
SQLite Unique index
Aug 22, 2025
b8ee6e6
Renaming
Aug 22, 2025
df5bbf1
Changes due to index changes.
Aug 22, 2025
c3eb4ca
Added SQLite Test AddIndex filtered
Aug 22, 2025
00da295
AddTableTest changes
Aug 25, 2025
ff642bd
Added filtered/partial indexes to SQLite
Aug 25, 2025
eb0b4e0
Tests for partial indexes
Aug 25, 2025
5d32ebd
Added validation of index instance
Aug 25, 2025
c4c867f
Updated documentation of index
Aug 25, 2025
60278bc
Added GetComparisonStrings
Aug 25, 2025
ab53779
Minor changes
Aug 25, 2025
30ab79f
Replaced old getindex in postgre. New includes "include" and "filtered"
Aug 25, 2025
7c80283
SQLServer added FilterItems - partial index
Aug 26, 2025
9ec8769
Partial Index tests
Aug 26, 2025
5158295
Added include columns tests for SQL Server
Aug 26, 2025
c555953
Update
Aug 27, 2025
76120fd
Added sql assertion in tests for AddIndex
Aug 27, 2025
b708ea1
Add value. Just to be safe.
Aug 27, 2025
5954416
Minor changes
Aug 27, 2025
a16bd46
Minor changes
Aug 27, 2025
08afa05
Minor changes
Aug 27, 2025
fd6c48e
added sql statement equality check for SQL Server
Aug 27, 2025
a1f19e4
Minor changes
Aug 27, 2025
4e899cc
Minor changes
Aug 27, 2025
cc84015
Minor change
Aug 27, 2025
ed1b1b5
Extended comments
Aug 27, 2025
73ac90f
Added some validation tests
Aug 27, 2025
f2dee95
Dispose provider in tests
Aug 28, 2025
763ac99
Dispose Postgre connection
Aug 28, 2025
a546cfc
Pooling for Postgres
Aug 28, 2025
bff8418
Extended Postgre max connections
Aug 28, 2025
d8d385f
Min pool size postgre
Aug 28, 2025
7b1788d
postgre max connections in env var
Aug 28, 2025
4722a16
Workaround for Postgre 13
Aug 28, 2025
b1061d9
16 => 13
Aug 28, 2025
833474f
Workaround 2: use psql
Aug 28, 2025
52943af
Password for psql
Aug 28, 2025
2c9acb5
Use postgres as initial db
Aug 28, 2025
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
9 changes: 2 additions & 7 deletions .github/workflows/dotnetpull.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,9 @@ on:
branches: [master]
pull_request:
branches: [master]

jobs:
build:
runs-on: ubuntu-latest

services:
sqlserver:
image: mcr.microsoft.com/mssql/server:2019-latest
Expand All @@ -23,21 +21,20 @@ jobs:
--health-interval=10s
--health-timeout=5s
--health-retries=10

postgres:
image: postgres:13
ports:
- 5432:5432
env:
POSTGRES_USER: testuser
POSTGRES_PASSWORD: testpass
POSTGRES_DB: testdb
# As of v16 we can use:
# POSTGRES_INITDB_ARGS: "-c max_connections=300"
options: >-
--health-cmd="pg_isready -U testuser"
--health-interval=10s
--health-timeout=5s
--health-retries=5

oracle:
image: gvenzl/oracle-free:latest
ports:
Expand All @@ -49,7 +46,6 @@ jobs:
--health-interval 10s
--health-timeout 5s
--health-retries 10

mysql:
image: mysql:8.0
ports:
Expand All @@ -64,7 +60,6 @@ jobs:
--health-interval=10s
--health-timeout=5s
--health-retries=10

steps:
- uses: actions/checkout@v4
- uses: gvenzl/setup-oracle-sqlcl@v1
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,9 +54,8 @@ public override async Task<DatabaseInfo> CreateTestDatabaseAsync(DatabaseConnect
await context.ExecuteAsync($"CREATE DATABASE \"{newDatabaseName}\"", cancellationToken);
}

var connectionStringBuilder2 = new NpgsqlConnectionStringBuilder
var connectionStringBuilder2 = new NpgsqlConnectionStringBuilder(clonedDatabaseConnectionConfig.ConnectionString)
{
ConnectionString = clonedDatabaseConnectionConfig.ConnectionString,
Database = newDatabaseName
};

Expand Down
45 changes: 45 additions & 0 deletions src/Migrator.Tests/Dialects/PostgreSQLDialectTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
using DotNetProjects.Migrator.Providers.Impl.PostgreSQL;
using DotNetProjects.Migrator.Providers.Models.Indexes.Enums;
using NUnit.Framework;

namespace Migrator.Tests.Dialects;

[TestFixture]
[Category("Postgre")]
public class PostgreDialectTests
{
private PostgreSQLDialect _postgreSQLDialect;

[SetUp]
public void SetUp()
{
// Since Dialect is abstract we use PostgreSQLDialect
_postgreSQLDialect = new PostgreSQLDialect();
}

[TestCase(FilterType.EqualTo, "=")]
[TestCase(FilterType.GreaterThanOrEqualTo, ">=")]
[TestCase(FilterType.SmallerThanOrEqualTo, "<=")]
[TestCase(FilterType.SmallerThan, "<")]
[TestCase(FilterType.GreaterThan, ">")]
[TestCase(FilterType.NotEqualTo, "<>")]
public void GetComparisonStringByFilterType_Success(FilterType filterType, string expectedString)
{
var result = _postgreSQLDialect.GetComparisonStringByFilterType(filterType);

Assert.That(result, Is.EqualTo(expectedString));
}

[TestCase("=", FilterType.EqualTo)]
[TestCase(">=", FilterType.GreaterThanOrEqualTo)]
[TestCase("<=", FilterType.SmallerThanOrEqualTo)]
[TestCase("<", FilterType.SmallerThan)]
[TestCase(">", FilterType.GreaterThan)]
[TestCase("<>", FilterType.NotEqualTo)]
public void GetFilterTypeByComparisonString_Success(string comparisonString, FilterType expectedFilterType)
{
var result = _postgreSQLDialect.GetFilterTypeByComparisonString(comparisonString);

Assert.That(result, Is.EqualTo(expectedFilterType));
}
}
19 changes: 18 additions & 1 deletion src/Migrator.Tests/Providers/Base/TransformationProviderBase.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using System.Data;
using System.Threading;
using System.Threading.Tasks;
using DotNetProjects.Migrator.Framework;
Expand All @@ -13,6 +14,7 @@
using Migrator.Tests.Settings;
using Migrator.Tests.Settings.Config;
using Migrator.Tests.Settings.Models;
using Npgsql;
using NUnit.Framework;

namespace Migrator.Tests.Providers.Base;
Expand All @@ -22,12 +24,24 @@ namespace Migrator.Tests.Providers.Base;
/// </summary>
public abstract class TransformationProviderBase
{
private IDbConnection _dbConnection;

[TearDown]
public virtual void TearDown()
{
DropTestTables();

Provider?.Rollback();

if (_dbConnection != null)
{
if (_dbConnection.State == ConnectionState.Open)
{
_dbConnection.Close();
}

_dbConnection.Dispose();
}
}

protected void DropTestTables()
Expand Down Expand Up @@ -108,7 +122,10 @@ protected async Task BeginPostgreSQLTransactionAsync()
var postgreIntegrationTestService = databaseIntegrationTestServiceFactory.Create(DatabaseProviderType.Postgres);
var databaseInfo = await postgreIntegrationTestService.CreateTestDatabaseAsync(databaseConnectionConfig, cts.Token);

Provider = new PostgreSQLTransformationProvider(new PostgreSQLDialect(), databaseInfo.DatabaseConnectionConfig.ConnectionString, null, "default", "Npgsql");

_dbConnection = new NpgsqlConnection(databaseInfo.DatabaseConnectionConfig.ConnectionString);

Provider = new PostgreSQLTransformationProvider(new PostgreSQLDialect(), _dbConnection, null, "default", "Npgsql");
Provider.BeginTransaction();

await Task.CompletedTask;
Expand Down
126 changes: 126 additions & 0 deletions src/Migrator.Tests/Providers/Generic/Generic_AddIndexTestsBase.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
using System;
using System.Collections.Generic;
using System.Data;
using System.Globalization;
using System.Linq;
using DotNetProjects.Migrator.Framework;
using DotNetProjects.Migrator.Providers.Models.Indexes;
using DotNetProjects.Migrator.Providers.Models.Indexes.Enums;
using Migrator.Tests.Providers.Base;
using NUnit.Framework;
using Index = DotNetProjects.Migrator.Framework.Index;

namespace Migrator.Tests.Providers.Generic;

public abstract class Generic_AddIndexTestsBase : TransformationProviderBase
{
[Test]
public void AddIndex_TableDoesNotExist()
{
// Act
Assert.Throws<MigrationException>(() => Provider.AddIndex("NotExistingTable", new Index()));
Assert.Throws<MigrationException>(() => Provider.AddIndex("NotExistingIndex", "NotExistingTable", "column"));
}

[Test]
public void AddIndex_AddAlreadyExistingIndex_Throws()
{
// Arrange
const string tableName = "TestTable";
const string columnName = "TestColumn";
const string indexName = "TestIndexName";

Provider.AddTable(tableName, new Column(columnName, DbType.Int32));
Provider.AddIndex(tableName, new Index { Name = indexName, KeyColumns = [columnName] });

// Act/Assert
// Add already existing index
Assert.Throws<MigrationException>(() => Provider.AddIndex(tableName, new Index { Name = indexName, KeyColumns = [columnName] }));
}

[Test]
public void AddIndex_IncludeColumnsContainsColumnThatExistInKeyColumns_Throws()
{
// Arrange
const string tableName = "TestTable";
const string columnName1 = "TestColumn1";
const string indexName = "TestIndexName";

Provider.AddTable(tableName, new Column(columnName1, DbType.Int32));

Assert.Throws<MigrationException>(() => Provider.AddIndex(tableName,
new Index
{
Name = indexName,
KeyColumns = [columnName1],
IncludeColumns = [columnName1]
}));
}

[Test]
public void AddIndex_ColumnNameUsedInFilterItemDoesNotExistInKeyColumns_Throws()
{
// Arrange
const string tableName = "TestTable";
const string columnName1 = "TestColumn1";
const string columnName2 = "TestColumn2";
const string indexName = "TestIndexName";

Provider.AddTable(tableName,
new Column(columnName1, DbType.Int32),
new Column(columnName2, DbType.Int32)
);

Assert.Throws<MigrationException>(() => Provider.AddIndex(tableName,
new Index
{
Name = indexName,
KeyColumns = [columnName1],
FilterItems = [new FilterItem { Filter = FilterType.GreaterThan, ColumnName = columnName2, Value = 12 }]
}));
}

[Test]
public void AddIndex_UsingIndexInstanceOverload_NonUnique_ShouldBeReadable()
{
// Arrange
const string tableName = "TestTable";
const string columnName = "TestColumn";
const string indexName = "TestIndexName";

Provider.AddTable(tableName, new Column(columnName, DbType.Int32));

// Act
Provider.AddIndex(tableName, new Index { Name = indexName, KeyColumns = [columnName] });

// Assert
var indexes = Provider.GetIndexes(tableName);

var index = indexes.Single();

Assert.That(index.Name, Is.EqualTo(indexName).IgnoreCase);
Assert.That(index.KeyColumns.Single(), Is.EqualTo(columnName).IgnoreCase);
}

[Test]
public void AddIndex_UsingNonIndexInstanceOverload_NonUnique_ShouldBeReadable()
{
// Arrange
const string tableName = "TestTable";
const string columnName = "TestColumn";
const string indexName = "TestIndexName";

Provider.AddTable(tableName, new Column(columnName, DbType.Int32));

// Act
Provider.AddIndex(indexName, tableName, columnName);

// Assert
var indexes = Provider.GetIndexes(tableName);

var index = indexes.Single();

Assert.That(index.Name, Is.EqualTo(indexName).IgnoreCase);
Assert.That(index.KeyColumns.Single(), Is.EqualTo(columnName).IgnoreCase);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
using System.Data;
using System.Linq;
using DotNetProjects.Migrator.Framework;
using DotNetProjects.Migrator.Providers.Models.Indexes.Enums;
using Migrator.Tests.Providers.Base;
using NUnit.Framework;
using Index = DotNetProjects.Migrator.Framework.Index;

namespace Migrator.Tests.Providers.Generic;

public abstract class Generic_GetIndexesTestsBase : TransformationProviderBase
{
[Test]
public void AddIndex_FilteredIndexGreaterOrEqualThanNumber_Success()
{
// Arrange
const string tableName = "TestTable";
const string columnName = "TestColumn";
const string columnName2 = "TestColumn2";
const string columnName3 = "TestColumn3";
const string indexName = "TestIndexName";

Provider.AddTable(tableName,
new Column(columnName, DbType.Int32),
new Column(columnName2, DbType.String),
new Column(columnName3, DbType.Int32)
);

Provider.AddIndex(tableName,
new Index
{
Name = indexName,
KeyColumns = [columnName, columnName2],
Unique = true,
FilterItems = [
new() { Filter = FilterType.GreaterThanOrEqualTo, ColumnName = columnName, Value = 100 },
new() { Filter = FilterType.EqualTo, ColumnName = columnName2, Value = "Hello" },
]
});

// Act
var indexes = Provider.GetIndexes(table: tableName);

var index = indexes.Single();

var filterItem1 = index.FilterItems.Single(x => x.ColumnName == columnName);
var filterItem2 = index.FilterItems.Single(x => x.ColumnName == columnName2);

Assert.That(filterItem1.Filter, Is.EqualTo(FilterType.GreaterThanOrEqualTo));
Assert.That((long)filterItem1.Value, Is.EqualTo(100));

Assert.That(filterItem2.Filter, Is.EqualTo(FilterType.EqualTo));
Assert.That((string)filterItem2.Value, Is.EqualTo("Hello"));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -44,14 +44,7 @@ public void CanAddPrimaryKey()
{
AddPrimaryKey();

if (Provider is SQLiteTransformationProvider)
{
Assert.Throws<NotSupportedException>(() => Provider.PrimaryKeyExists("Test", "PK_Test"));
}
else
{
Assert.That(Provider.PrimaryKeyExists("Test", "PK_Test"), Is.True);
}
Assert.That(Provider.PrimaryKeyExists("Test", "PK_Test"), Is.True);
}

// [Test]
Expand Down
Loading
Loading