Skip to content

Commit

Permalink
Hstore query support
Browse files Browse the repository at this point in the history
Fixes #212
  • Loading branch information
yinzara committed Oct 5, 2024
1 parent 30cebf0 commit 33ed270
Show file tree
Hide file tree
Showing 10 changed files with 1,491 additions and 4 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,214 @@
// ReSharper disable once CheckNamespace

namespace Microsoft.EntityFrameworkCore;

/// <summary>
/// Provides extension methods supporting `hstore` function translation for PostgreSQL.
/// </summary>
public static class StringKeyValuePairDbFunctionsExtensions
{
/// <summary>
/// Returns values associated with given keys, or NULL if not present.
///
/// Works with `hstore`, `json` and `jsonb` type columns
/// <br/>
/// SQL translation: input -> keys
/// Note: input will automatically translate to `hstore` if `jsonb` or `json`
/// </summary>
/// <param name="_">The <see cref="DbFunctions" /> instance.</param>
/// <param name="input">The input hstore.</param>
/// <param name="keys">The keys to return the values of from the input hstore.</param>
/// <seealso href="https://www.postgresql.org/docs/current/hstore.html#HSTORE-OPS-FUNCS">PostgreSQL documentation for 'hstore' functions.</seealso>
public static List<string> ValuesForKeys(this DbFunctions _, IEnumerable<KeyValuePair<string, string>> input, IList<string> keys)
=> throw new InvalidOperationException(CoreStrings.FunctionOnClient(nameof(ValuesForKeys)));

/// <summary>
/// Does dictionary contain all the specified keys?
///
/// Works with `hstore`, `json` and `jsonb` type columns
/// <br/>
/// SQL translation: input ?&amp; keys
/// </summary>
/// <param name="_">The <see cref="DbFunctions" /> instance.</param>
/// <param name="input">The input hstore.</param>
/// <param name="keys">The keys to check if the input store contains all of.</param>
/// <seealso href="https://www.postgresql.org/docs/current/hstore.html#HSTORE-OPS-FUNCS">PostgreSQL documentation for 'hstore' functions.</seealso>
public static bool ContainsAllKeys(this DbFunctions _, IEnumerable<KeyValuePair<string, string>> input, IList<string> keys)
=> throw new InvalidOperationException(CoreStrings.FunctionOnClient(nameof(ContainsAllKeys)));

/// <summary>
/// Does dictionary contain any of the specified keys?
///
/// Works with `hstore`, `json` and `jsonb` type columns
/// <br/>
/// SQL translation: input ?| keys
/// </summary>
/// <param name="_">The <see cref="DbFunctions" /> instance.</param>
/// <param name="input">The input hstore.</param>
/// <param name="keys">The keys to check if the input store contains any of.</param>
/// <seealso href="https://www.postgresql.org/docs/current/hstore.html#HSTORE-OPS-FUNCS">PostgreSQL documentation for 'hstore' functions.</seealso>
public static bool ContainsAnyKeys(this DbFunctions _, IEnumerable<KeyValuePair<string, string>> input, IList<string> keys)
=> throw new InvalidOperationException(CoreStrings.FunctionOnClient(nameof(ContainsAnyKeys)));

/// <summary>
/// Does left operand contain right?
///
/// Works with `hstore`, `json` and `jsonb` type columns
/// <br/>
/// SQL translation: left @> right
/// </summary>
/// <param name="_">The <see cref="DbFunctions" /> instance.</param>
/// <param name="left">The input left hstore.</param>
/// <param name="right">The input right hstore.</param>
/// <seealso href="https://www.postgresql.org/docs/current/hstore.html#HSTORE-OPS-FUNCS">PostgreSQL documentation for 'hstore' functions.</seealso>
public static bool Contains(this DbFunctions _, IEnumerable<KeyValuePair<string, string>> left, IEnumerable<KeyValuePair<string, string>> right)
=> throw new InvalidOperationException(CoreStrings.FunctionOnClient(nameof(Contains)));

/// <summary>
/// Is left operand contained by right?
/// <br/>
/// SQL translation: left &lt;@ right
/// </summary>
/// <param name="_">The <see cref="DbFunctions" /> instance.</param>
/// <param name="left">The input left hstore.</param>
/// <param name="right">The input right hstore.</param>
/// <seealso href="https://www.postgresql.org/docs/current/hstore.html#HSTORE-OPS-FUNCS">PostgreSQL documentation for 'hstore' functions.</seealso>
public static bool ContainedBy(this DbFunctions _, IEnumerable<KeyValuePair<string, string>> left, IEnumerable<KeyValuePair<string, string>> right)
=> throw new InvalidOperationException(CoreStrings.FunctionOnClient(nameof(ContainedBy)));

/// <summary>
/// Deletes keys from input operand.
///
/// Works with `hstore`, `json` and `jsonb` type columns
/// <br/>
/// SQL translation: input - key
/// </summary>
/// <param name="_">The <see cref="DbFunctions" /> instance.</param>
/// <param name="input">The input hstore.</param>
/// <param name="key">The key to remove.</param>
/// <seealso href="https://www.postgresql.org/docs/current/hstore.html#HSTORE-OPS-FUNCS">PostgreSQL documentation for 'hstore' functions.</seealso>
public static T Remove<T>(this DbFunctions _, T input, string key)
where T : IEnumerable<KeyValuePair<string, string>>
=> throw new InvalidOperationException(CoreStrings.FunctionOnClient(nameof(Remove)));

/// <summary>
/// Extracts a subset of a dictionary containing only the specified keys.
///
/// For `jsonb` and `json` input they will be automatically converted to `hstore` but
/// the result will always be an `hstore` type
/// <br/>
/// SQL translation: slice(input, keys)
/// </summary>
/// <param name="_">The <see cref="DbFunctions" /> instance.</param>
/// <param name="input">The input hstore.</param>
/// <param name="keys">The keys to extract the subset of.</param>
/// <seealso href="https://www.postgresql.org/docs/current/hstore.html#HSTORE-OPS-FUNCS">PostgreSQL documentation for 'hstore' functions.</seealso>
public static T Slice<T>(this DbFunctions _, T input, IList<string> keys)
where T : IEnumerable<KeyValuePair<string, string>>
=> throw new InvalidOperationException(CoreStrings.FunctionOnClient(nameof(Slice)));

/// <summary>
/// Converts hstore to an array of alternating keys and values.
/// <br/>
/// SQL translation: hstore_to_array(input)
/// </summary>
/// <param name="_">The <see cref="DbFunctions" /> instance.</param>
/// <param name="input">The input hstore.</param>
/// <seealso href="https://www.postgresql.org/docs/current/hstore.html#HSTORE-OPS-FUNCS">PostgreSQL documentation for 'hstore' functions.</seealso>
public static List<string> ToKeysAndValues(this DbFunctions _, IEnumerable<KeyValuePair<string, string>> input)
=> throw new InvalidOperationException(CoreStrings.FunctionOnClient(nameof(ToKeysAndValues)));

/// <summary>
/// Constructs an hstore from a key/value pair string array
/// <br/>
/// SQL translation: hstore(input)
/// </summary>
/// <param name="_">The <see cref="DbFunctions" /> instance.</param>
/// <param name="input">The input string array of key value pairs.</param>
/// <seealso href="https://www.postgresql.org/docs/current/hstore.html#HSTORE-OPS-FUNCS">PostgreSQL documentation for 'hstore' functions.</seealso>
public static Dictionary<string, string> FromKeysAndValues(this DbFunctions _, IList<string> input)
=> throw new InvalidOperationException(CoreStrings.FunctionOnClient(nameof(FromKeysAndValues)));

/// <summary>
/// Constructs an hstore from a string array of keys and a string array of values
/// <br/>
/// SQL translation: hstore(keys, values)
/// </summary>
/// <param name="_">The <see cref="DbFunctions" /> instance.</param>
/// <param name="keys">The input string array of keys.</param>
/// <param name="values">The input string array of values.</param>
/// <seealso href="https://www.postgresql.org/docs/current/hstore.html#HSTORE-OPS-FUNCS">PostgreSQL documentation for 'hstore' functions.</seealso>
public static Dictionary<string, string> FromKeysAndValues(this DbFunctions _, IList<string> keys, IList<string> values)
=> throw new InvalidOperationException(CoreStrings.FunctionOnClient(nameof(FromKeysAndValues)));

/// <summary>
/// Converts an hstore to a `json` type `Dictionary&lt;string, string>`
/// <br/>
/// Can be used during a migration of changing a column's StoreType from 'hstore' to a 'json' with the `Using` clause
/// SQL translation: hstore_to_json(input)
/// </summary>
/// <param name="_">The <see cref="DbFunctions" /> instance.</param>
/// <param name="input">The input hstore.</param>
/// <seealso href="https://www.postgresql.org/docs/current/hstore.html#HSTORE-OPS-FUNCS">PostgreSQL documentation for 'hstore' functions.</seealso>
public static Dictionary<string, string> ToJson(this DbFunctions _, IEnumerable<KeyValuePair<string, string>> input)
=> throw new InvalidOperationException(CoreStrings.FunctionOnClient(nameof(ToJson)));

/// <summary>
/// Converts a `json` type `IEnumerable&lt;KeyValuePair&lt;string, string>>` (i.e. Dictionary&lt;string, string>> or related type) to an hstore type `Dictionary&lt;string, string>>`
/// <br/>
/// Can be used during a migration of changing a column's StoreType from 'json' to 'hstore' with the `Using` clause
/// SQL translation: select hstore(array_agg(key), array_agg(value)) FROM json_each_text(json)
/// </summary>
/// <param name="_">The <see cref="DbFunctions" /> instance.</param>
/// <param name="input">The input hstore.</param>
/// <seealso href="https://www.postgresql.org/docs/current/hstore.html#HSTORE-OPS-FUNCS">PostgreSQL documentation for 'hstore' functions.</seealso>
public static Dictionary<string, string> FromJson(this DbFunctions _, IEnumerable<KeyValuePair<string, string>> input)
=> throw new InvalidOperationException(CoreStrings.FunctionOnClient(nameof(FromJson)));

/// <summary>
/// Converts an hstore to a `jsonb` type `Dictionary&lt;string, string>`
///
/// Can be used during a migration of changing a column's StoreType from 'hstore' to 'jsonb' with the `Using` clause
/// <br/>
/// SQL translation: hstore_to_jsonb(input)
/// </summary>
/// <param name="_">The <see cref="DbFunctions" /> instance.</param>
/// <param name="input">The input hstore.</param>
/// <seealso href="https://www.postgresql.org/docs/current/hstore.html#HSTORE-OPS-FUNCS">PostgreSQL documentation for 'hstore' functions.</seealso>
public static Dictionary<string, string> ToJsonb(this DbFunctions _, IEnumerable<KeyValuePair<string, string>> input)
=> throw new InvalidOperationException(CoreStrings.FunctionOnClient(nameof(ToJsonb)));

/// <summary>
/// Converts a `jsonb` type `IEnumerable&lt;KeyValuePair&lt;string, string>>` (i.e. Dictionary&lt;string, string>> or related type) to an hstore type `Dictionary&lt;string, string>>`
/// <br/>
/// Can be used during a migration of changing a column's StoreType from 'jsonb' to 'hstore' with the `Using` clause
/// SQL translation: select hstore(array_agg(key), array_agg(value)) FROM jsonb_each_text(json)
/// </summary>
/// <param name="_">The <see cref="DbFunctions" /> instance.</param>
/// <param name="input">The input hstore.</param>
/// <seealso href="https://www.postgresql.org/docs/current/hstore.html#HSTORE-OPS-FUNCS">PostgreSQL documentation for 'hstore' functions.</seealso>
public static Dictionary<string, string> FromJsonb(this DbFunctions _, IEnumerable<KeyValuePair<string, string>> input)
=> throw new InvalidOperationException(CoreStrings.FunctionOnClient(nameof(FromJsonb)));

/// <summary>
/// Converts an hstore to a `json` value type `Dictionary&lt;string, object?>`, but attempts to distinguish numerical and Boolean values so they are unquoted in the JSON.
/// <br/>
/// SQL translation: hstore_to_json_loose(input)
/// </summary>
/// <param name="_">The <see cref="DbFunctions" /> instance.</param>
/// <param name="input">The input hstore.</param>
/// <seealso href="https://www.postgresql.org/docs/current/hstore.html#HSTORE-OPS-FUNCS">PostgreSQL documentation for 'hstore' functions.</seealso>
public static Dictionary<string, object?> ToJsonLoose(this DbFunctions _, IEnumerable<KeyValuePair<string, string>> input)
=> throw new InvalidOperationException(CoreStrings.FunctionOnClient(nameof(ToJsonLoose)));

/// <summary>
/// Converts an hstore to a `jsonb` value type `Dictionary&lt;string, object?>`, but attempts to distinguish numerical and Boolean values so they are unquoted in the JSON.
/// <br/>
/// SQL translation: hstore_to_jsonb_loose(input)
/// </summary>
/// <param name="_">The <see cref="DbFunctions" /> instance.</param>
/// <param name="input">The input hstore.</param>
/// <seealso href="https://www.postgresql.org/docs/current/hstore.html#HSTORE-OPS-FUNCS">PostgreSQL documentation for 'hstore' functions.</seealso>
public static Dictionary<string, object?> ToJsonbLoose(this DbFunctions _, IEnumerable<KeyValuePair<string, string>> input)
=> throw new InvalidOperationException(CoreStrings.FunctionOnClient(nameof(ToJsonbLoose)));
}
Loading

0 comments on commit 33ed270

Please sign in to comment.