Skip to content

Commit

Permalink
Add support for index sort options
Browse files Browse the repository at this point in the history
  • Loading branch information
khellang committed Mar 15, 2019
1 parent 576e1db commit e1cba6a
Show file tree
Hide file tree
Showing 13 changed files with 526 additions and 35 deletions.
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using System;
using System;
using System.Diagnostics;
using JetBrains.Annotations;
using Microsoft.EntityFrameworkCore;
Expand Down Expand Up @@ -163,6 +163,12 @@ public override MethodCallCodeFragment GenerateFluentApi(IIndex index, IAnnotati
return new MethodCallCodeFragment(nameof(NpgsqlIndexBuilderExtensions.ForNpgsqlHasMethod), annotation.Value);
if (annotation.Name == NpgsqlAnnotationNames.IndexOperators)
return new MethodCallCodeFragment(nameof(NpgsqlIndexBuilderExtensions.ForNpgsqlHasOperators), annotation.Value);
if (annotation.Name == NpgsqlAnnotationNames.IndexCollation)
return new MethodCallCodeFragment(nameof(NpgsqlIndexBuilderExtensions.ForNpgsqlHasCollation), annotation.Value);
if (annotation.Name == NpgsqlAnnotationNames.IndexSortOrder)
return new MethodCallCodeFragment(nameof(NpgsqlIndexBuilderExtensions.ForNpgsqlHasSortOrder), annotation.Value);
if (annotation.Name == NpgsqlAnnotationNames.IndexNullSortOrder)
return new MethodCallCodeFragment(nameof(NpgsqlIndexBuilderExtensions.ForNpgsqlHasNullSortOrder), annotation.Value);
if (annotation.Name == NpgsqlAnnotationNames.IndexInclude)
return new MethodCallCodeFragment(nameof(NpgsqlIndexBuilderExtensions.ForNpgsqlInclude), annotation.Value);

Expand Down
70 changes: 69 additions & 1 deletion src/EFCore.PG/Extensions/NpgsqlIndexBuilderExtensions.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
using System;
using System;
using System.Linq;
using System.Linq.Expressions;
using JetBrains.Annotations;
using Microsoft.EntityFrameworkCore.Internal;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
using Npgsql.EntityFrameworkCore.PostgreSQL.Utilities;

// ReSharper disable once CheckNamespace
Expand Down Expand Up @@ -56,6 +57,73 @@ public static IndexBuilder ForNpgsqlHasOperators(
return indexBuilder;
}

/// <summary>
/// The PostgreSQL index collation to be used.
/// </summary>
/// <remarks>
/// https://www.postgresql.org/docs/current/static/indexes-collations.html
/// </remarks>
/// <param name="indexBuilder"> The builder for the index being configured. </param>
/// <param name="values"> The sort options to use for each column. </param>
/// <returns> A builder to further configure the index. </returns>
public static IndexBuilder ForNpgsqlHasCollation(
[NotNull] this IndexBuilder indexBuilder,
[CanBeNull, ItemNotNull] params string[] values)
{
Check.NotNull(indexBuilder, nameof(indexBuilder));
Check.NullButNotEmpty(values, nameof(values));

indexBuilder.Metadata.Npgsql().Collation = values;

return indexBuilder;
}

/// <summary>
/// The PostgreSQL index sort ordering to be used.
/// </summary>
/// <remarks>
/// https://www.postgresql.org/docs/current/static/indexes-ordering.html
/// </remarks>
/// <param name="indexBuilder"> The builder for the index being configured. </param>
/// <param name="values"> The sort order to use for each column. </param>
/// <returns> A builder to further configure the index. </returns>
public static IndexBuilder ForNpgsqlHasSortOrder(
[NotNull] this IndexBuilder indexBuilder,
[CanBeNull] params SortOrder[] values)
{
Check.NotNull(indexBuilder, nameof(indexBuilder));
Check.NullButNotEmpty(values, nameof(values));

if (!SortOrderHelper.IsDefaultSortOrder(values))
indexBuilder.Metadata.Npgsql().SortOrder = values;

return indexBuilder;
}

/// <summary>
/// The PostgreSQL index NULL sort ordering to be used.
/// </summary>
/// <remarks>
/// https://www.postgresql.org/docs/current/static/indexes-ordering.html
/// </remarks>
/// <param name="indexBuilder"> The builder for the index being configured. </param>
/// <param name="values"> The sort order to use for each column. </param>
/// <returns> A builder to further configure the index. </returns>
public static IndexBuilder ForNpgsqlHasNullSortOrder(
[NotNull] this IndexBuilder indexBuilder,
[CanBeNull] params NullSortOrder[] values)
{
Check.NotNull(indexBuilder, nameof(indexBuilder));
Check.NullButNotEmpty(values, nameof(values));

var sortOrders = indexBuilder.Metadata.Npgsql().SortOrder;

if (!SortOrderHelper.IsDefaultNullSortOrder(values, sortOrders))
indexBuilder.Metadata.Npgsql().NullSortOrder = values;

return indexBuilder;
}

/// <summary>
/// Adds an INCLUDE clause to the index definition with the specified property names.
/// This clause specifies a list of columns which will be included as a non-key part in the index.
Expand Down
34 changes: 29 additions & 5 deletions src/EFCore.PG/Metadata/INpgsqlIndexAnnotations.cs
Original file line number Diff line number Diff line change
@@ -1,31 +1,55 @@
using System.Collections.Generic;
using System.Collections.Generic;
using Microsoft.EntityFrameworkCore.Metadata;

namespace Npgsql.EntityFrameworkCore.PostgreSQL.Metadata
{
public interface INpgsqlIndexAnnotations : IRelationalIndexAnnotations
{
/// <summary>
/// The PostgreSQL index method to be used. Null selects the default (currently btree).
/// The method to be used, or <c>null</c> if it hasn't been specified. <c>null</c> selects the default (currently <c>btree</c>).
/// </summary>
/// <remarks>
/// http://www.postgresql.org/docs/current/static/sql-createindex.html
/// </remarks>
string Method { get; }

/// <summary>
/// The PostgreSQL index operators to be used, or <c>null</c> if they have not been specified.
/// The column operators to be used, or <c>null</c> if they have not been specified.
/// </summary>
/// <remarks>
/// https://www.postgresql.org/docs/current/static/indexes-opclass.html
/// </remarks>
IReadOnlyList<string> Operators { get; }

/// <summary>
/// The PostgreSQL included property names, or <c>null</c> if they have not been specified.
/// The column collations to be used, or <c>null</c> if they have not been specified.
/// </summary>
/// <remarks>
/// https://www.postgresql.org/docs/current/sql-createindex.html
/// https://www.postgresql.org/docs/current/static/indexes-collations.html
/// </remarks>
IReadOnlyList<string> Collation { get; }

/// <summary>
/// The column sort orders to be used, or <c>null</c> if they have not been specified.
/// </summary>
/// <remarks>
/// https://www.postgresql.org/docs/current/static/indexes-ordering.html
/// </remarks>
IReadOnlyList<SortOrder> SortOrder { get; }

/// <summary>
/// The column NULL sort orders to be used, or <c>null</c> if they have not been specified.
/// </summary>
/// <remarks>
/// https://www.postgresql.org/docs/current/static/indexes-ordering.html
/// </remarks>
IReadOnlyList<NullSortOrder> NullSortOrder { get; }

/// <summary>
/// The included property names, or <c>null</c> if they have not been specified.
/// </summary>
/// <remarks>
/// https://www.postgresql.org/docs/current/static/sql-createindex.html
/// </remarks>
IReadOnlyList<string> IncludeProperties { get; }
}
Expand Down
5 changes: 4 additions & 1 deletion src/EFCore.PG/Metadata/Internal/NpgsqlAnnotationNames.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using System;
using System;

namespace Npgsql.EntityFrameworkCore.PostgreSQL.Metadata.Internal
{
Expand All @@ -11,6 +11,9 @@ public static class NpgsqlAnnotationNames
public const string HiLoSequenceSchema = Prefix + "HiLoSequenceSchema";
public const string IndexMethod = Prefix + "IndexMethod";
public const string IndexOperators = Prefix + "IndexOperators";
public const string IndexCollation = Prefix + "IndexCollation";
public const string IndexSortOrder = Prefix + "IndexSortOrder";
public const string IndexNullSortOrder = Prefix + "IndexNullSortOrder";
public const string IndexInclude = Prefix + "IndexInclude";
public const string PostgresExtensionPrefix = Prefix + "PostgresExtension:";
public const string EnumPrefix = Prefix + "Enum:";
Expand Down
61 changes: 56 additions & 5 deletions src/EFCore.PG/Metadata/NpgsqlIndexAnnotations.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using System.Collections.Generic;
using System.Collections.Generic;
using JetBrains.Annotations;
using Microsoft.EntityFrameworkCore.Metadata;
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata.Internal;
Expand All @@ -18,7 +18,7 @@ protected NpgsqlIndexAnnotations([NotNull] RelationalAnnotations annotations)
}

/// <summary>
/// The PostgreSQL index method to be used. Null selects the default (currently btree).
/// The method to be used, or <c>null</c> if it hasn't been specified. <c>null</c> selects the default (currently <c>btree</c>).
/// </summary>
/// <remarks>
/// http://www.postgresql.org/docs/current/static/sql-createindex.html
Expand All @@ -30,7 +30,7 @@ public string Method
}

/// <summary>
/// The PostgreSQL index operators to be used, or <c>null</c> if they have not been specified.
/// The column operators to be used, or <c>null</c> if they have not been specified.
/// </summary>
/// <remarks>
/// https://www.postgresql.org/docs/current/static/indexes-opclass.html
Expand All @@ -44,10 +44,52 @@ public string[] Operators
IReadOnlyList<string> INpgsqlIndexAnnotations.Operators => Operators;

/// <summary>
/// The PostgreSQL included property names, or <c>null</c> if they have not been specified.
/// The column collations to be used, or <c>null</c> if they have not been specified.
/// </summary>
/// <remarks>
/// https://www.postgresql.org/docs/current/sql-createindex.html
/// https://www.postgresql.org/docs/current/static/indexes-collations.html
/// </remarks>
public string[] Collation
{
get => (string[])Annotations.Metadata[NpgsqlAnnotationNames.IndexCollation];
set => SetCollation(value);
}

IReadOnlyList<string> INpgsqlIndexAnnotations.Collation => Collation;

/// <summary>
/// The column sort orders to be used, or <c>null</c> if they have not been specified.
/// </summary>
/// <remarks>
/// https://www.postgresql.org/docs/current/static/indexes-ordering.html
/// </remarks>
public SortOrder[] SortOrder
{
get => (SortOrder[])Annotations.Metadata[NpgsqlAnnotationNames.IndexSortOrder];
set => SetSortOrder(value);
}

IReadOnlyList<SortOrder> INpgsqlIndexAnnotations.SortOrder => SortOrder;

/// <summary>
/// The column NULL sort orders to be used, or <c>null</c> if they have not been specified.
/// </summary>
/// <remarks>
/// https://www.postgresql.org/docs/current/static/indexes-ordering.html
/// </remarks>
public NullSortOrder[] NullSortOrder
{
get => (NullSortOrder[])Annotations.Metadata[NpgsqlAnnotationNames.IndexNullSortOrder];
set => SetNullSortOrder(value);
}

IReadOnlyList<NullSortOrder> INpgsqlIndexAnnotations.NullSortOrder => NullSortOrder;

/// <summary>
/// The included property names, or <c>null</c> if they have not been specified.
/// </summary>
/// <remarks>
/// https://www.postgresql.org/docs/current/static/sql-createindex.html
/// </remarks>
public string[] IncludeProperties
{
Expand All @@ -63,6 +105,15 @@ protected virtual bool SetMethod(string value)
protected virtual bool SetOperators(string[] value)
=> Annotations.SetAnnotation(NpgsqlAnnotationNames.IndexOperators, value);

protected virtual bool SetCollation(string[] value)
=> Annotations.SetAnnotation(NpgsqlAnnotationNames.IndexCollation, value);

protected virtual bool SetSortOrder(SortOrder[] value)
=> Annotations.SetAnnotation(NpgsqlAnnotationNames.IndexSortOrder, value);

protected virtual bool SetNullSortOrder(NullSortOrder[] value)
=> Annotations.SetAnnotation(NpgsqlAnnotationNames.IndexNullSortOrder, value);

protected virtual bool SetIncludeProperties(string[] value)
=> Annotations.SetAnnotation(NpgsqlAnnotationNames.IndexInclude, value);
}
Expand Down
29 changes: 29 additions & 0 deletions src/EFCore.PG/Metadata/NullSortOrder.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
namespace Npgsql.EntityFrameworkCore.PostgreSQL.Metadata
{
/// <summary>
/// Options for modifying sort ordering of <c>NULL</c>-values in indexes.
/// </summary>
public enum NullSortOrder
{
/// <summary>
/// Represents an unspecified sort order. The database default will be used.
/// </summary>
Unspecified = 0,

/// <summary>
/// Specifies that nulls sort before non-nulls.
/// </summary>
/// <remarks>
/// This is the default when <see cref="SortOrder.Descending"/> is specified.
/// </remarks>
NullsFirst = 1,

/// <summary>
/// Specifies that nulls sort after non-nulls.
/// </summary>
/// <remarks>
/// This is the default when <see cref="SortOrder.Descending"/> is not specified.
/// </remarks>
NullsLast = 2,
}
}
18 changes: 18 additions & 0 deletions src/EFCore.PG/Metadata/SortOrder.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
namespace Npgsql.EntityFrameworkCore.PostgreSQL.Metadata
{
/// <summary>
/// Options for modifying sort ordering of index values.
/// </summary>
public enum SortOrder
{
/// <summary>
/// Specifies ascending sort order, which is the default.
/// </summary>
Ascending = 0,

/// <summary>
/// Specifies descending sort order.
/// </summary>
Descending = 1,
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using System;
using System;
using System.Collections.Generic;
using System.Linq;
using JetBrains.Annotations;
Expand Down Expand Up @@ -45,6 +45,12 @@ public override IEnumerable<IAnnotation> For(IIndex index)
yield return new Annotation(NpgsqlAnnotationNames.IndexMethod, index.Npgsql().Method);
if (index.Npgsql().Operators != null)
yield return new Annotation(NpgsqlAnnotationNames.IndexOperators, index.Npgsql().Operators);
if (index.Npgsql().Collation != null)
yield return new Annotation(NpgsqlAnnotationNames.IndexCollation, index.Npgsql().Collation);
if (index.Npgsql().SortOrder != null)
yield return new Annotation(NpgsqlAnnotationNames.IndexSortOrder, index.Npgsql().SortOrder);
if (index.Npgsql().NullSortOrder != null)
yield return new Annotation(NpgsqlAnnotationNames.IndexNullSortOrder, index.Npgsql().NullSortOrder);
if (index.Npgsql().IncludeProperties != null)
yield return new Annotation(NpgsqlAnnotationNames.IndexInclude, index.Npgsql().IncludeProperties);
}
Expand Down
Loading

0 comments on commit e1cba6a

Please sign in to comment.