Skip to content

Commit

Permalink
Merge pull request #1386 from lillo42/postgres-add-support-for-partia…
Browse files Browse the repository at this point in the history
…l-index

Postgres add support for partial index
  • Loading branch information
jzabroski committed Dec 18, 2020
2 parents 912e669 + 28b642c commit e4b381b
Show file tree
Hide file tree
Showing 5 changed files with 106 additions and 64 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
#region License
// Copyright (c) 2020, FluentMigrator Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#endregion

using FluentMigrator.Builders.Create.Index;
using FluentMigrator.Infrastructure;
using FluentMigrator.Infrastructure.Extensions;

namespace FluentMigrator.Postgres
{
public static partial class PostgresExtensions
{
public const string IndexFilter = "PostgresIndexFilter";

/// <summary>
/// The constraint expression for a partial index.
/// </summary>
/// <param name="expression"></param>
/// <param name="filter">The constraint expression</param>
/// <returns>The next step</returns>
public static ICreateIndexOptionsSyntax Filter(this ICreateIndexOptionsSyntax expression, string filter)
{
var additionalFeatures = expression as ISupportAdditionalFeatures;
additionalFeatures.SetAdditionalFeature(IndexFilter, filter);
return expression;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -34,97 +34,48 @@ public static ICreateIndexOptionsSyntax UsingBTree(this ICreateIndexOptionsSynta
return expression;
}

public static ICreateIndexNonKeyColumnSyntax UsingBTree(this ICreateIndexOnColumnSyntax expression)
{
var additionalFeatures = expression as ISupportAdditionalFeatures;
additionalFeatures.Using(Algorithm.BTree);
return new CreateIndexExpressionNonKeyBuilder(expression, additionalFeatures);
}

public static ICreateIndexOptionsSyntax UsingHash(this ICreateIndexOptionsSyntax expression)
{
var additionalFeatures = expression as ISupportAdditionalFeatures;
additionalFeatures.Using(Algorithm.Hash);
return expression;
}

public static ICreateIndexNonKeyColumnSyntax UsingHash(this ICreateIndexOnColumnSyntax expression)
{
var additionalFeatures = expression as ISupportAdditionalFeatures;
additionalFeatures.Using(Algorithm.Hash);
return new CreateIndexExpressionNonKeyBuilder(expression, additionalFeatures);
}

public static ICreateIndexOptionsSyntax UsingGist(this ICreateIndexOptionsSyntax expression)
{
var additionalFeatures = expression as ISupportAdditionalFeatures;
additionalFeatures.Using(Algorithm.Gist);
return expression;
}

public static ICreateIndexNonKeyColumnSyntax UsingGist(this ICreateIndexOnColumnSyntax expression)
{
var additionalFeatures = expression as ISupportAdditionalFeatures;
additionalFeatures.Using(Algorithm.Gist);
return new CreateIndexExpressionNonKeyBuilder(expression, additionalFeatures);
}

public static ICreateIndexOptionsSyntax UsingSpgist(this ICreateIndexOptionsSyntax expression)
{
var additionalFeatures = expression as ISupportAdditionalFeatures;
additionalFeatures.Using(Algorithm.Spgist);
return expression;
}

public static ICreateIndexNonKeyColumnSyntax UsingSpgist(this ICreateIndexOnColumnSyntax expression)
{
var additionalFeatures = expression as ISupportAdditionalFeatures;
additionalFeatures.Using(Algorithm.Spgist);
return new CreateIndexExpressionNonKeyBuilder(expression, additionalFeatures);
}

public static ICreateIndexOptionsSyntax UsingGin(this ICreateIndexOptionsSyntax expression)
{
var additionalFeatures = expression as ISupportAdditionalFeatures;
additionalFeatures.Using(Algorithm.Gin);
return expression;
}

public static ICreateIndexNonKeyColumnSyntax UsingGin(this ICreateIndexOnColumnSyntax expression)
{
var additionalFeatures = expression as ISupportAdditionalFeatures;
additionalFeatures.Using(Algorithm.Gin);
return new CreateIndexExpressionNonKeyBuilder(expression, additionalFeatures);
}

public static ICreateIndexOptionsSyntax UsingBrin(this ICreateIndexOptionsSyntax expression)
{
var additionalFeatures = expression as ISupportAdditionalFeatures;
additionalFeatures.Using(Algorithm.Brin);
return expression;
}

public static ICreateIndexNonKeyColumnSyntax UsingBrin(this ICreateIndexOnColumnSyntax expression)
{
var additionalFeatures = expression as ISupportAdditionalFeatures;
additionalFeatures.Using(Algorithm.Brin);
return new CreateIndexExpressionNonKeyBuilder(expression, additionalFeatures);
}

public static ICreateIndexOptionsSyntax Using(this ICreateIndexOptionsSyntax expression, Algorithm algorithm)
{
var additionalFeatures = expression as ISupportAdditionalFeatures;
additionalFeatures.Using(algorithm);
return expression;
}

public static ICreateIndexNonKeyColumnSyntax Using(this ICreateIndexOnColumnSyntax expression, Algorithm algorithm)
{
var additionalFeatures = expression as ISupportAdditionalFeatures;
additionalFeatures.Using(algorithm);
return new CreateIndexExpressionNonKeyBuilder(expression, additionalFeatures);
}

public static void Using(this ISupportAdditionalFeatures additionalFeatures, Algorithm algorithm)
{
if (additionalFeatures == null)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,17 @@ protected virtual string GetUsingAlgorithm(CreateIndexExpression expression)
return $" USING {algorithm.Algorithm.ToString().ToUpper()}";
}

protected virtual string GetFilter(CreateIndexExpression expression)
{
var filter = expression.Index.GetAdditionalFeature<string>(PostgresExtensions.IndexFilter);
if (!string.IsNullOrWhiteSpace(filter))
{
return " WHERE " + filter;
}

return string.Empty;
}

protected virtual string GetAsConcurrently(CreateIndexExpression expression)
{
var asConcurrently = expression.GetAdditionalFeature<PostgresIndexConcurrentlyDefinition>(PostgresExtensions.Concurrently);
Expand Down Expand Up @@ -264,6 +275,7 @@ public override string Generate(CreateIndexExpression expression)

result.Append(")")
.Append(GetIncludeString(expression))
.Append(GetFilter(expression))
.Append(";");

return result.ToString();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@
using FluentMigrator.Expressions;
using FluentMigrator.Model;
using FluentMigrator.Postgres;
using FluentMigrator.SqlServer;

using Moq;

Expand Down Expand Up @@ -104,7 +103,7 @@ public void CallingIncludeAddsNewIncludeToExpression()

var additionalFeatures = new Dictionary<string, object>()
{
[SqlServerExtensions.IncludesList] = collectionMock.Object
[SqlServer.SqlServerExtensions.IncludesList] = collectionMock.Object
};

var indexMock = new Mock<IndexDefinition>();
Expand All @@ -114,7 +113,7 @@ public void CallingIncludeAddsNewIncludeToExpression()
expressionMock.SetupGet(e => e.Index).Returns(indexMock.Object);

ICreateIndexOnColumnOrInSchemaSyntax builder = new CreateIndexExpressionBuilder(expressionMock.Object);
SqlServerExtensions.Include(builder, "BaconId");
SqlServer.SqlServerExtensions.Include(builder, "BaconId");

collectionMock.Verify(x => x.Add(It.Is<IndexIncludeDefinition>(c => c.Name.Equals("BaconId"))));
indexMock.VerifyGet(x => x.AdditionalFeatures);
Expand Down Expand Up @@ -171,22 +170,22 @@ public void CallingUsingIndexAlgorithmToExpressionInPostgres(Algorithm algorithm
switch (algorithm)
{
case Algorithm.BTree:
PostgresExtensions.UsingBTree(builder);
builder.WithOptions().UsingBTree();
break;
case Algorithm.Hash:
PostgresExtensions.UsingHash(builder);
builder.WithOptions().UsingHash();
break;
case Algorithm.Gist:
PostgresExtensions.UsingGist(builder);
builder.WithOptions().UsingGist();
break;
case Algorithm.Spgist:
PostgresExtensions.UsingSpgist(builder);
builder.WithOptions().UsingSpgist();
break;
case Algorithm.Gin:
PostgresExtensions.UsingGin(builder);
builder.WithOptions().UsingGin();
break;
case Algorithm.Brin:
PostgresExtensions.UsingBrin(builder);
builder.WithOptions().UsingBrin();
break;
default:
throw new ArgumentOutOfRangeException(nameof(algorithm), algorithm, null);
Expand All @@ -197,6 +196,31 @@ public void CallingUsingIndexAlgorithmToExpressionInPostgres(Algorithm algorithm
expressionMock.VerifyGet(e => e.Index);
}

[Test]
public void CallingFilterExpressingInPostgres()
{
var additionalFeatures = new Dictionary<string, object>()
{
[PostgresExtensions.IndexFilter] = ""
};

var indexMock = new Mock<IndexDefinition>();
indexMock.Setup(x => x.AdditionalFeatures).Returns(additionalFeatures);

var expressionMock = new Mock<CreateIndexExpression>();
expressionMock.SetupGet(e => e.Index).Returns(indexMock.Object);

ICreateIndexOnColumnOrInSchemaSyntax builder = new CreateIndexExpressionBuilder(expressionMock.Object);

builder.WithOptions().Filter("someColumn = 'test'");
indexMock.VerifyGet(x => x.AdditionalFeatures);
expressionMock.VerifyGet(e => e.Index);

Assert.AreEqual("someColumn = 'test'", additionalFeatures[PostgresExtensions.IndexFilter]);


}

[TestCase(arguments: true)]
[TestCase(arguments: false)]
[TestCase(arguments: null)]
Expand All @@ -209,15 +233,14 @@ public void CallingUsingAsConcurrentlyToExpressionInPostgres(bool? isConcurrentl
[PostgresExtensions.Concurrently] = collectionMock.Object
};


var indexMock = new Mock<IndexDefinition>();
indexMock.Setup(x => x.AdditionalFeatures).Returns(additionalFeatures);

var expressionMock = new Mock<CreateIndexExpression>();
expressionMock.SetupGet(e => e.Index).Returns(indexMock.Object);

ICreateIndexOnColumnOrInSchemaSyntax builder = new CreateIndexExpressionBuilder(expressionMock.Object);


if (isConcurrently == null)
{
builder.WithOptions().AsConcurrently();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -133,13 +133,30 @@ public override void CanDropIndexWithDefaultSchema()
[TestCase(Algorithm.Spgist)]
public void CanCreateIndexUsingIndexAlgorithm(Algorithm algorithm)
{
var expression = GetCreateIndexExpression(algorithm);
var expression = GetCreateIndexWithExpression(x =>
{
var definition = x.Index.GetAdditionalFeature(PostgresExtensions.IndexAlgorithm, () => new PostgresIndexAlgorithmDefinition());
definition.Algorithm = algorithm;
});


var result = Generator.Generate(expression);
result.ShouldBe($"CREATE INDEX \"TestIndex\" ON \"public\".\"TestTable1\" USING {algorithm.ToString().ToUpper()} (\"TestColumn1\" ASC);");
}

private static CreateIndexExpression GetCreateIndexExpression(Algorithm algorithm)
[Test]
public void CanCreateIndexWithFilter()
{
var expression = GetCreateIndexWithExpression(x =>
{
x.Index.GetAdditionalFeature(PostgresExtensions.IndexFilter, () => "\"TestColumn1\" > 100");
});

var result = Generator.Generate(expression);
result.ShouldBe("CREATE INDEX \"TestIndex\" ON \"public\".\"TestTable1\" (\"TestColumn1\" ASC) WHERE \"TestColumn1\" > 100;");
}

private static CreateIndexExpression GetCreateIndexWithExpression(Action<CreateIndexExpression> additionalFeature)
{
var expression = new CreateIndexExpression
{
Expand All @@ -152,8 +169,7 @@ private static CreateIndexExpression GetCreateIndexExpression(Algorithm algorith

expression.Index.Columns.Add(new IndexColumnDefinition { Direction = Direction.Ascending, Name = GeneratorTestHelper.TestColumnName1 });

var definition = expression.Index.GetAdditionalFeature(PostgresExtensions.IndexAlgorithm, () => new PostgresIndexAlgorithmDefinition());
definition.Algorithm = algorithm;
additionalFeature(expression);

return expression;
}
Expand Down

0 comments on commit e4b381b

Please sign in to comment.