{-# LANGUAGE BangPatterns, TypeFamilies, DataKinds, PolyKinds, TypeApplications, ScopedTypeVariables, ConstraintKinds, TypeOperators, GADTs, UndecidableInstances, StandaloneDeriving, FunctionalDependencies, FlexibleContexts, InstanceSigs, AllowAmbiguousTypes, DeriveAnyClass #-}
{-|
Module: IHP.QueryBuilder.Filter
Description: WHERE clause filtering functions for QueryBuilder
Copyright: (c) digitally induced GmbH, 2020

This module provides all the filterWhere* functions for building WHERE clauses.
-}
module IHP.QueryBuilder.Filter
( filterWhere
, filterWhereCaseInsensitive
, filterWhereNot
, filterWhereIn
, filterWhereInCaseInsensitive
, filterWhereIdIn
, filterWhereNotIn
, filterWhereLike
, filterWhereILike
, filterWhereMatches
, filterWhereIMatches
, filterWherePast
, filterWhereFuture
, filterWhereGreaterThan
, filterWhereLarger
, filterWhereGreaterThanOrEqualTo
, filterWhereAtLeast
, filterWhereLessThan
, filterWhereSmaller
, filterWhereLessThanOrEqualTo
, filterWhereAtMost
, filterWhereSql
) where

import IHP.Prelude
import IHP.ModelSupport
import IHP.QueryBuilder.Types
import IHP.QueryBuilder.Compiler (negateFilterOperator)
import qualified Hasql.Encoders as Encoders
import Hasql.Implicits.Encoders (DefaultParamEncoder(..))
import IHP.Hasql.Encoders () -- Import for DefaultParamEncoder instances
import IHP.QueryBuilder.Compiler (qualifiedColumnName)
import Data.Functor.Contravariant (contramap)

-- | Build a 'ConditionValue' from any 'DefaultParamEncoder' value.
paramValue :: DefaultParamEncoder a => a -> ConditionValue
paramValue :: forall a. DefaultParamEncoder a => a -> ConditionValue
paramValue a
value = Params () -> ConditionValue
Param ((() -> a) -> Params a -> Params ()
forall a' a. (a' -> a) -> Params a -> Params a'
forall (f :: * -> *) a' a.
Contravariant f =>
(a' -> a) -> f a -> f a'
contramap (a -> () -> a
forall a b. a -> b -> a
const a
value) (NullableOrNot Value a -> Params a
forall a. NullableOrNot Value a -> Params a
Encoders.param NullableOrNot Value a
forall a. DefaultParamEncoder a => NullableOrNot Value a
defaultParam))
{-# INLINE paramValue #-}

-- | Build the appropriate 'ConditionValue' based on the operator.
-- For 'IsOp'/'IsNotOp', returns @Literal "NULL"@ (no parameter consumed).
-- For all other operators, returns @Param encoder@.
condValueForOp :: DefaultParamEncoder a => FilterOperator -> a -> ConditionValue
condValueForOp :: forall a.
DefaultParamEncoder a =>
FilterOperator -> a -> ConditionValue
condValueForOp FilterOperator
IsOp a
_ = Text -> ConditionValue
Literal Text
"NULL"
condValueForOp FilterOperator
IsNotOp a
_ = Text -> ConditionValue
Literal Text
"NULL"
condValueForOp FilterOperator
_ a
value = a -> ConditionValue
forall a. DefaultParamEncoder a => a -> ConditionValue
paramValue a
value
{-# INLINE condValueForOp #-}

-- | Adds a simple @WHERE x = y@ condition to the query.
--
-- __Example:__ Only show projects where @active@ is @True@.
--
-- > activeProjects <- query @Project
-- >     |> filterWhere (#active, True)
-- >     |> fetch
-- > -- SELECT * FROM projects WHERE active = True
--
-- __Example:__ Find book with title @Learn you a Haskell@.
--
-- > book <- query @Book
-- >     |> filterWhere (#title, "Learn you a Haskell")
-- >     |> fetchOne
-- > -- SELECT * FROM books WHERE name = 'Learn you a Haskell' LIMIT 1
--
--
-- __Example:__ Find active projects owned by the current user.
--
-- > projects <- query @Project
-- >     |> filterWhere (#active, True)
-- >     |> filterWhere (#currentUserId, currentUserId)
-- >     |> fetch
-- > -- SELECT * FROM projects WHERE active = true AND current_user_id = '..'
--
--
-- For dynamic conditions (e.g. involving @NOW()@), see 'filterWhereSql'.
--
-- For @WHERE x IN (a, b, c)@ conditions, take a look at 'filterWhereIn' and 'filterWhereNotIn'.
--
-- For @WHERE x LIKE a@ or @WHERE x ~ a@  conditions, see 'filterWhereLike' and 'filterWhereMatches' respectively.
-- For case-insensitive versions of these operators, see 'filterWhereILike' and 'filterWhereIMatches'.
--
-- When your condition is too complex, use a raw sql query with 'IHP.ModelSupport.sqlQuery'.
filterWhere :: forall name table model value. (KnownSymbol table, KnownSymbol name, DefaultParamEncoder value, HasField name model value, EqOrIsOperator value, model ~ GetModelByTableName table, Table model) => (Proxy name, value) -> QueryBuilder table -> QueryBuilder table
filterWhere :: forall (name :: Symbol) (table :: Symbol) model value.
(KnownSymbol table, KnownSymbol name, DefaultParamEncoder value,
 HasField name model value, EqOrIsOperator value,
 model ~ GetModelByTableName table, Table model) =>
(Proxy name, value) -> QueryBuilder table -> QueryBuilder table
filterWhere (Proxy name
name, value
value) QueryBuilder table
queryBuilder = Condition -> QueryBuilder table -> QueryBuilder table
forall (table :: Symbol).
Condition -> QueryBuilder table -> QueryBuilder table
addCondition Condition
condition QueryBuilder table
queryBuilder
    where
        condition :: Condition
condition = let op :: FilterOperator
op = value -> FilterOperator
forall value. EqOrIsOperator value => value -> FilterOperator
toEqOrIsOperator value
value in Text
-> FilterOperator
-> ConditionValue
-> Maybe Text
-> Maybe Text
-> Condition
ColumnCondition Text
columnName FilterOperator
op (FilterOperator -> value -> ConditionValue
forall a.
DefaultParamEncoder a =>
FilterOperator -> a -> ConditionValue
condValueForOp FilterOperator
op value
value) Maybe Text
forall a. Maybe a
Nothing Maybe Text
forall a. Maybe a
Nothing
        columnName :: Text
columnName = Text -> Text -> Text
qualifiedColumnName (forall record. Table record => Text
tableName @model) (forall (symbol :: Symbol). KnownSymbol symbol => Text
symbolToText @name)
{-# INLINE filterWhere #-}

-- | Like 'filterWhere' but negates the condition.
--
-- __Example:__ Only show projects created by other users.
--
-- > activeProjects <- query @Project
-- >     |> filterWhereNot (#userId, currentUserId)
-- >     |> fetch
-- > -- SELECT * FROM projects WHERE user_id != '23d5ea33-b28e-4f0a-99b3-77a3564a2546'
--
filterWhereNot :: forall name table model value. (KnownSymbol table, KnownSymbol name, DefaultParamEncoder value, HasField name model value, EqOrIsOperator value, model ~ GetModelByTableName table, Table model) => (Proxy name, value) -> QueryBuilder table -> QueryBuilder table
filterWhereNot :: forall (name :: Symbol) (table :: Symbol) model value.
(KnownSymbol table, KnownSymbol name, DefaultParamEncoder value,
 HasField name model value, EqOrIsOperator value,
 model ~ GetModelByTableName table, Table model) =>
(Proxy name, value) -> QueryBuilder table -> QueryBuilder table
filterWhereNot (Proxy name
name, value
value) QueryBuilder table
queryBuilder = Condition -> QueryBuilder table -> QueryBuilder table
forall (table :: Symbol).
Condition -> QueryBuilder table -> QueryBuilder table
addCondition Condition
condition QueryBuilder table
queryBuilder
    where
        condition :: Condition
condition = let op :: FilterOperator
op = FilterOperator -> FilterOperator
negateFilterOperator (value -> FilterOperator
forall value. EqOrIsOperator value => value -> FilterOperator
toEqOrIsOperator value
value) in Text
-> FilterOperator
-> ConditionValue
-> Maybe Text
-> Maybe Text
-> Condition
ColumnCondition Text
columnName FilterOperator
op (FilterOperator -> value -> ConditionValue
forall a.
DefaultParamEncoder a =>
FilterOperator -> a -> ConditionValue
condValueForOp FilterOperator
op value
value) Maybe Text
forall a. Maybe a
Nothing Maybe Text
forall a. Maybe a
Nothing
        columnName :: Text
columnName = Text -> Text -> Text
qualifiedColumnName (forall record. Table record => Text
tableName @model) (forall (symbol :: Symbol). KnownSymbol symbol => Text
symbolToText @name)
{-# INLINE filterWhereNot #-}

-- | Adds a @WHERE x IN (y)@ condition to the query.
--
-- __Example:__ Only show projects where @status@ is @Draft@ or @Active@.
--
-- > visibleProjects <- query @Project
-- >     |> filterWhereIn (#status, [Draft, Active])
-- >     |> fetch
-- > -- SELECT * FROM projects WHERE status IN ('draft', 'active')
--
-- For negation use 'filterWhereNotIn'
--
filterWhereIn :: forall name table model value. (KnownSymbol table, KnownSymbol name, DefaultParamEncoder [value], DefaultParamEncoder value, HasField name model value, model ~ GetModelByTableName table, EqOrIsOperator value, Table model) => (Proxy name, [value]) -> QueryBuilder table -> QueryBuilder table
filterWhereIn :: forall (name :: Symbol) (table :: Symbol) model value.
(KnownSymbol table, KnownSymbol name, DefaultParamEncoder [value],
 DefaultParamEncoder value, HasField name model value,
 model ~ GetModelByTableName table, EqOrIsOperator value,
 Table model) =>
(Proxy name, [value]) -> QueryBuilder table -> QueryBuilder table
filterWhereIn (Proxy name
name, [value]
value) QueryBuilder table
queryBuilder =
        case [value] -> Maybe value
forall a. [a] -> Maybe a
head [value]
nullValues of
            Maybe value
Nothing -> Condition -> QueryBuilder table -> QueryBuilder table
forall (table :: Symbol).
Condition -> QueryBuilder table -> QueryBuilder table
addCondition Condition
inCondition QueryBuilder table
queryBuilder -- All values non null
            Just value
nullValue ->
                let
                    isNullCondition :: Condition
isNullCondition = Text
-> FilterOperator
-> ConditionValue
-> Maybe Text
-> Maybe Text
-> Condition
ColumnCondition Text
columnName FilterOperator
IsOp (Text -> ConditionValue
Literal Text
"NULL") Maybe Text
forall a. Maybe a
Nothing Maybe Text
forall a. Maybe a
Nothing
                in
                    case [value] -> Maybe value
forall a. [a] -> Maybe a
head [value]
nonNullValues of
                        Just value
nonNullValue -> -- Some non null values, some null values
                            Condition -> QueryBuilder table -> QueryBuilder table
forall (table :: Symbol).
Condition -> QueryBuilder table -> QueryBuilder table
addCondition (Condition -> Condition -> Condition
OrCondition Condition
inCondition Condition
isNullCondition) QueryBuilder table
queryBuilder
                        Maybe value
Nothing -> Condition -> QueryBuilder table -> QueryBuilder table
forall (table :: Symbol).
Condition -> QueryBuilder table -> QueryBuilder table
addCondition Condition
isNullCondition QueryBuilder table
queryBuilder -- All values null
    where
        -- Only NOT NULL values can be compares inside the IN expression, NULL values have to be compares using a manual appended IS expression
        -- https://github.com/digitallyinduced/ihp/issues/906
        --
        ([value]
nonNullValues, [value]
nullValues) = [value]
value [value] -> ([value] -> ([value], [value])) -> ([value], [value])
forall a b. a -> (a -> b) -> b
|> (value -> Bool) -> [value] -> ([value], [value])
forall a. (a -> Bool) -> [a] -> ([a], [a])
partition (\value
v -> value -> FilterOperator
forall value. EqOrIsOperator value => value -> FilterOperator
toEqOrIsOperator value
v FilterOperator -> FilterOperator -> Bool
forall a. Eq a => a -> a -> Bool
== FilterOperator
EqOp)

        inCondition :: Condition
inCondition = Text
-> FilterOperator
-> ConditionValue
-> Maybe Text
-> Maybe Text
-> Condition
ColumnCondition Text
columnName FilterOperator
InOp ([value] -> ConditionValue
forall a. DefaultParamEncoder a => a -> ConditionValue
paramValue [value]
nonNullValues) Maybe Text
forall a. Maybe a
Nothing Maybe Text
forall a. Maybe a
Nothing

        columnName :: Text
columnName = Text -> Text -> Text
qualifiedColumnName (forall record. Table record => Text
tableName @model) (forall (symbol :: Symbol). KnownSymbol symbol => Text
symbolToText @name)
{-# INLINE filterWhereIn #-}

-- Like 'filterWhereIn', but case insensitive.
--
-- __Example:__ Only show users where @email@ is @User1@example.com@ or @User2@example.com@.
--
-- > users <- query @User
-- >     |> filterWhereInCaseInsensitive (#email, ['User1@example.com', 'User2@example.com'])
-- >     |> fetch
-- > -- SELECT * FROM users WHERE LOWER(email) IN ('user1@example.com', 'user2@example.com')
--
filterWhereInCaseInsensitive :: forall name table model value. ( KnownSymbol table, KnownSymbol name, DefaultParamEncoder value, HasField name model value, model ~ GetModelByTableName table, EqOrIsOperator value, Table model) => (Proxy name, [Text]) -> QueryBuilder table -> QueryBuilder table
filterWhereInCaseInsensitive :: forall (name :: Symbol) (table :: Symbol) model value.
(KnownSymbol table, KnownSymbol name, DefaultParamEncoder value,
 HasField name model value, model ~ GetModelByTableName table,
 EqOrIsOperator value, Table model) =>
(Proxy name, [Text]) -> QueryBuilder table -> QueryBuilder table
filterWhereInCaseInsensitive (Proxy name
name, [Text]
values) QueryBuilder table
queryBuilder =
        case [Text] -> Maybe Text
forall a. [a] -> Maybe a
head [Text]
nullValues of
            Maybe Text
Nothing -> Condition -> QueryBuilder table -> QueryBuilder table
forall (table :: Symbol).
Condition -> QueryBuilder table -> QueryBuilder table
addCondition Condition
inCondition QueryBuilder table
queryBuilder
            Just Text
nullValue ->
                let
                    isNullCondition :: Condition
isNullCondition = Text
-> FilterOperator
-> ConditionValue
-> Maybe Text
-> Maybe Text
-> Condition
ColumnCondition Text
columnName FilterOperator
IsOp (Text -> ConditionValue
Literal Text
"NULL") Maybe Text
forall a. Maybe a
Nothing Maybe Text
forall a. Maybe a
Nothing
                in
                    case [Text] -> Maybe Text
forall a. [a] -> Maybe a
head [Text]
nonNullValues of
                        Just Text
_ ->
                            Condition -> QueryBuilder table -> QueryBuilder table
forall (table :: Symbol).
Condition -> QueryBuilder table -> QueryBuilder table
addCondition (Condition -> Condition -> Condition
OrCondition Condition
inCondition Condition
isNullCondition) QueryBuilder table
queryBuilder
                        Maybe Text
Nothing -> Condition -> QueryBuilder table -> QueryBuilder table
forall (table :: Symbol).
Condition -> QueryBuilder table -> QueryBuilder table
addCondition Condition
isNullCondition QueryBuilder table
queryBuilder
    where
        ([Text]
nonNullValues, [Text]
nullValues) = [Text]
values [Text] -> ([Text] -> ([Text], [Text])) -> ([Text], [Text])
forall a b. a -> (a -> b) -> b
|> (Text -> Bool) -> [Text] -> ([Text], [Text])
forall a. (a -> Bool) -> [a] -> ([a], [a])
partition (\Text
v -> Text -> FilterOperator
forall value. EqOrIsOperator value => value -> FilterOperator
toEqOrIsOperator Text
v FilterOperator -> FilterOperator -> Bool
forall a. Eq a => a -> a -> Bool
== FilterOperator
EqOp)

        lowerValues :: [Text]
lowerValues = (Text -> Text) -> [Text] -> [Text]
forall a b. (a -> b) -> [a] -> [b]
map Text -> Text
toLower [Text]
nonNullValues

        inCondition :: Condition
inCondition = Text
-> FilterOperator
-> ConditionValue
-> Maybe Text
-> Maybe Text
-> Condition
ColumnCondition Text
lowerColumnName FilterOperator
InOp ([Text] -> ConditionValue
forall a. DefaultParamEncoder a => a -> ConditionValue
paramValue [Text]
lowerValues) Maybe Text
forall a. Maybe a
Nothing Maybe Text
forall a. Maybe a
Nothing

        lowerColumnName :: Text
lowerColumnName = Text
"LOWER(" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
columnName Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
")"
        columnName :: Text
columnName = Text -> Text -> Text
qualifiedColumnName (forall record. Table record => Text
tableName @model) (forall (symbol :: Symbol). KnownSymbol symbol => Text
symbolToText @name)

{-# INLINE filterWhereInCaseInsensitive #-}


-- | Adds a @WHERE x NOT IN (y)@ condition to the query.
--
-- __Example:__ Only show projects where @status@ is not @Archived@
--
-- > visibleProjects <- query @Project
-- >     |> filterWhereNotIn (#status, [Archived])
-- >     |> fetch
-- > -- SELECT * FROM projects WHERE status NOT IN ('archived')
--
-- The inclusive version of this function is called 'filterWhereIn'.
--
filterWhereNotIn :: forall name table model value. (KnownSymbol table, KnownSymbol name, DefaultParamEncoder [value], DefaultParamEncoder value, HasField name model value, model ~ GetModelByTableName table, EqOrIsOperator value) => (Proxy name, [value]) -> QueryBuilder table -> QueryBuilder table
filterWhereNotIn :: forall (name :: Symbol) (table :: Symbol) model value.
(KnownSymbol table, KnownSymbol name, DefaultParamEncoder [value],
 DefaultParamEncoder value, HasField name model value,
 model ~ GetModelByTableName table, EqOrIsOperator value) =>
(Proxy name, [value]) -> QueryBuilder table -> QueryBuilder table
filterWhereNotIn (Proxy name
_, []) QueryBuilder table
queryBuilder = QueryBuilder table
queryBuilder -- Handle empty case by ignoring query part: `WHERE x NOT IN ()`
filterWhereNotIn (Proxy name
name, [value]
value) QueryBuilder table
queryBuilder =
        case [value] -> Maybe value
forall a. [a] -> Maybe a
head [value]
nullValues of
            Maybe value
Nothing -> Condition -> QueryBuilder table -> QueryBuilder table
forall (table :: Symbol).
Condition -> QueryBuilder table -> QueryBuilder table
addCondition Condition
notInCondition QueryBuilder table
queryBuilder -- All values non null
            Just value
nullValue ->
                case [value] -> Maybe value
forall a. [a] -> Maybe a
head [value]
nonNullValues of
                    Just value
nonNullValue -> Condition -> QueryBuilder table -> QueryBuilder table
forall (table :: Symbol).
Condition -> QueryBuilder table -> QueryBuilder table
addCondition (Text
-> FilterOperator
-> ConditionValue
-> Maybe Text
-> Maybe Text
-> Condition
ColumnCondition Text
columnName FilterOperator
IsNotOp (Text -> ConditionValue
Literal Text
"NULL") Maybe Text
forall a. Maybe a
Nothing Maybe Text
forall a. Maybe a
Nothing) (Condition -> QueryBuilder table -> QueryBuilder table
forall (table :: Symbol).
Condition -> QueryBuilder table -> QueryBuilder table
addCondition Condition
notInCondition QueryBuilder table
queryBuilder) -- Some non null values, some null values
                    Maybe value
Nothing -> Condition -> QueryBuilder table -> QueryBuilder table
forall (table :: Symbol).
Condition -> QueryBuilder table -> QueryBuilder table
addCondition (Text
-> FilterOperator
-> ConditionValue
-> Maybe Text
-> Maybe Text
-> Condition
ColumnCondition Text
columnName FilterOperator
IsNotOp (Text -> ConditionValue
Literal Text
"NULL") Maybe Text
forall a. Maybe a
Nothing Maybe Text
forall a. Maybe a
Nothing) QueryBuilder table
queryBuilder -- All values null
    where
        -- Only NOT NULL values can be compares inside the IN expression, NULL values have to be compares using a manual appended IS expression
        -- https://github.com/digitallyinduced/ihp/issues/906
        --
        ([value]
nonNullValues, [value]
nullValues) = [value]
value [value] -> ([value] -> ([value], [value])) -> ([value], [value])
forall a b. a -> (a -> b) -> b
|> (value -> Bool) -> [value] -> ([value], [value])
forall a. (a -> Bool) -> [a] -> ([a], [a])
partition (\value
v -> value -> FilterOperator
forall value. EqOrIsOperator value => value -> FilterOperator
toEqOrIsOperator value
v FilterOperator -> FilterOperator -> Bool
forall a. Eq a => a -> a -> Bool
== FilterOperator
EqOp)

        notInCondition :: Condition
notInCondition = Text
-> FilterOperator
-> ConditionValue
-> Maybe Text
-> Maybe Text
-> Condition
ColumnCondition Text
columnName FilterOperator
NotInOp ([value] -> ConditionValue
forall a. DefaultParamEncoder a => a -> ConditionValue
paramValue [value]
nonNullValues) Maybe Text
forall a. Maybe a
Nothing Maybe Text
forall a. Maybe a
Nothing

        columnName :: Text
columnName = Text -> Text -> Text
qualifiedColumnName (forall (symbol :: Symbol). KnownSymbol symbol => Text
symbolToText @table) (forall (symbol :: Symbol). KnownSymbol symbol => Text
symbolToText @name)
{-# INLINE filterWhereNotIn #-}


-- | Adds a @WHERE x LIKE y@ condition to the query.
--
-- __Example:__ Find titles matching search term.
--
-- > articles <- query @Article
-- >     |> filterWhereLike (#title, "%" <> searchTerm <> "%")
-- >     |> fetch
-- > -- SELECT * FROM articles WHERE title LIKE '%..%'
filterWhereLike :: forall name table model value. (KnownSymbol table, KnownSymbol name, DefaultParamEncoder value, HasField name model value, model ~ GetModelByTableName table, Table model) => (Proxy name, value) -> QueryBuilder table -> QueryBuilder table
filterWhereLike :: forall (name :: Symbol) (table :: Symbol) model value.
(KnownSymbol table, KnownSymbol name, DefaultParamEncoder value,
 HasField name model value, model ~ GetModelByTableName table,
 Table model) =>
(Proxy name, value) -> QueryBuilder table -> QueryBuilder table
filterWhereLike (Proxy name
name, value
value) QueryBuilder table
queryBuilder = Condition -> QueryBuilder table -> QueryBuilder table
forall (table :: Symbol).
Condition -> QueryBuilder table -> QueryBuilder table
addCondition Condition
condition QueryBuilder table
queryBuilder
    where
        condition :: Condition
condition = Text
-> FilterOperator
-> ConditionValue
-> Maybe Text
-> Maybe Text
-> Condition
ColumnCondition Text
columnName (MatchSensitivity -> FilterOperator
LikeOp MatchSensitivity
CaseSensitive) (value -> ConditionValue
forall a. DefaultParamEncoder a => a -> ConditionValue
paramValue value
value) Maybe Text
forall a. Maybe a
Nothing Maybe Text
forall a. Maybe a
Nothing
        columnName :: Text
columnName = Text -> Text -> Text
qualifiedColumnName (forall record. Table record => Text
tableName @model) (forall (symbol :: Symbol). KnownSymbol symbol => Text
symbolToText @name)
{-# INLINE filterWhereLike #-}


-- | Adds a @WHERE x ILIKE y@ condition to the query. Case-insensitive version of 'filterWhereLike'.
--
-- __Example:__ Find titles matching search term.
--
-- > articles <- query @Article
-- >     |> filterWhereILike (#title, "%" <> searchTerm <> "%")
-- >     |> fetch
-- > -- SELECT * FROM articles WHERE title ILIKE '%..%'
filterWhereILike :: forall name table model value. (KnownSymbol table, KnownSymbol name, DefaultParamEncoder value, HasField name model value, model ~ GetModelByTableName table, Table model) => (Proxy name, value) -> QueryBuilder table -> QueryBuilder table
filterWhereILike :: forall (name :: Symbol) (table :: Symbol) model value.
(KnownSymbol table, KnownSymbol name, DefaultParamEncoder value,
 HasField name model value, model ~ GetModelByTableName table,
 Table model) =>
(Proxy name, value) -> QueryBuilder table -> QueryBuilder table
filterWhereILike (Proxy name
name, value
value) QueryBuilder table
queryBuilder = Condition -> QueryBuilder table -> QueryBuilder table
forall (table :: Symbol).
Condition -> QueryBuilder table -> QueryBuilder table
addCondition Condition
condition QueryBuilder table
queryBuilder
    where
        condition :: Condition
condition = Text
-> FilterOperator
-> ConditionValue
-> Maybe Text
-> Maybe Text
-> Condition
ColumnCondition Text
columnName (MatchSensitivity -> FilterOperator
LikeOp MatchSensitivity
CaseInsensitive) (value -> ConditionValue
forall a. DefaultParamEncoder a => a -> ConditionValue
paramValue value
value) Maybe Text
forall a. Maybe a
Nothing Maybe Text
forall a. Maybe a
Nothing
        columnName :: Text
columnName = Text -> Text -> Text
qualifiedColumnName (forall record. Table record => Text
tableName @model) (forall (symbol :: Symbol). KnownSymbol symbol => Text
symbolToText @name)
{-# INLINE filterWhereILike #-}


-- | Adds a @WHERE x ~ y@ condition to the query.
--
-- __Example:__ Find names with titles in front.
--
-- > articles <- query @User
-- >     |> filterWhereMatches (#name, "^(M(rs|r|iss)|Dr|Sir). ")
-- >     |> fetch
-- > -- SELECT * FROM articles WHERE title ~ '^(M(rs|r|iss)|Dr|Sir). '
filterWhereMatches :: forall name table model value. (KnownSymbol table, KnownSymbol name, DefaultParamEncoder value, HasField name model value, table ~ GetTableName model, Table model) => (Proxy name, value) -> QueryBuilder table -> QueryBuilder table
filterWhereMatches :: forall (name :: Symbol) (table :: Symbol) model value.
(KnownSymbol table, KnownSymbol name, DefaultParamEncoder value,
 HasField name model value, table ~ GetTableName model,
 Table model) =>
(Proxy name, value) -> QueryBuilder table -> QueryBuilder table
filterWhereMatches (Proxy name
name, value
value) QueryBuilder table
queryBuilder = Condition -> QueryBuilder table -> QueryBuilder table
forall (table :: Symbol).
Condition -> QueryBuilder table -> QueryBuilder table
addCondition Condition
condition QueryBuilder table
queryBuilder
    where
        condition :: Condition
condition = Text
-> FilterOperator
-> ConditionValue
-> Maybe Text
-> Maybe Text
-> Condition
ColumnCondition Text
columnName (MatchSensitivity -> FilterOperator
MatchesOp MatchSensitivity
CaseSensitive) (value -> ConditionValue
forall a. DefaultParamEncoder a => a -> ConditionValue
paramValue value
value) Maybe Text
forall a. Maybe a
Nothing Maybe Text
forall a. Maybe a
Nothing
        columnName :: Text
columnName = Text -> Text -> Text
qualifiedColumnName (forall record. Table record => Text
tableName @model) (forall (symbol :: Symbol). KnownSymbol symbol => Text
symbolToText @name)
{-# INLINE filterWhereMatches #-}


-- | Adds a @WHERE x ~* y@ condition to the query. Case-insensitive version of 'filterWhereMatches'.
filterWhereIMatches :: forall name table model value. (KnownSymbol table, KnownSymbol name, DefaultParamEncoder value, HasField name model value, model ~ GetModelByTableName table, Table model) => (Proxy name, value) -> QueryBuilder table -> QueryBuilder table
filterWhereIMatches :: forall (name :: Symbol) (table :: Symbol) model value.
(KnownSymbol table, KnownSymbol name, DefaultParamEncoder value,
 HasField name model value, model ~ GetModelByTableName table,
 Table model) =>
(Proxy name, value) -> QueryBuilder table -> QueryBuilder table
filterWhereIMatches (Proxy name
name, value
value) QueryBuilder table
queryBuilder = Condition -> QueryBuilder table -> QueryBuilder table
forall (table :: Symbol).
Condition -> QueryBuilder table -> QueryBuilder table
addCondition Condition
condition QueryBuilder table
queryBuilder
    where
        condition :: Condition
condition = Text
-> FilterOperator
-> ConditionValue
-> Maybe Text
-> Maybe Text
-> Condition
ColumnCondition Text
columnName (MatchSensitivity -> FilterOperator
MatchesOp MatchSensitivity
CaseInsensitive) (value -> ConditionValue
forall a. DefaultParamEncoder a => a -> ConditionValue
paramValue value
value) Maybe Text
forall a. Maybe a
Nothing Maybe Text
forall a. Maybe a
Nothing
        columnName :: Text
columnName = Text -> Text -> Text
qualifiedColumnName (forall record. Table record => Text
tableName @model) (forall (symbol :: Symbol). KnownSymbol symbol => Text
symbolToText @name)
{-# INLINE filterWhereIMatches #-}


-- | Filter all rows by whether a field is in the past, determined by comparing 'NOW()' to the field's value.
--
-- Opposite of 'filterWhereFuture'
--
-- __Example:__ Fetch all posts scheduled for the past.
--
-- > publicPosts <- query @Post
-- >     |> filterWherePast #scheduledAt
-- >     |> fetch
-- > -- SELECT * FROM posts WHERE scheduled_at <= NOW()
filterWherePast
    :: ( KnownSymbol table
       , KnownSymbol name
       , HasField name (GetModelByTableName table) value
       , Table (GetModelByTableName table)
       )
    => Proxy name -> QueryBuilder table -> QueryBuilder table
filterWherePast :: forall (table :: Symbol) (name :: Symbol) value.
(KnownSymbol table, KnownSymbol name,
 HasField name (GetModelByTableName table) value,
 Table (GetModelByTableName table)) =>
Proxy name -> QueryBuilder table -> QueryBuilder table
filterWherePast Proxy name
name = (Proxy name, Text) -> QueryBuilder table -> QueryBuilder table
forall (name :: Symbol) (table :: Symbol) model value.
(KnownSymbol table, KnownSymbol name, HasField name model value,
 model ~ GetModelByTableName table, Table model) =>
(Proxy name, Text) -> QueryBuilder table -> QueryBuilder table
filterWhereSql (Proxy name
name, Text
"<= NOW()")
{-# INLINE filterWherePast #-}

-- | Filter all rows by whether a field is in the future, determined by comparing 'NOW()' to the field's value.
--
-- Opposite of 'filterWherePast'
--
-- __Example:__ Fetch all posts scheduled for the future.
--
-- > hiddenPosts <- query @Post
-- >     |> filterWhereFuture #scheduledAt
-- >     |> fetch
-- > -- SELECT * FROM posts WHERE scheduled_at > NOW()
filterWhereFuture
    :: ( KnownSymbol table
       , KnownSymbol name
       , HasField name (GetModelByTableName table) value
       , Table (GetModelByTableName table)
       )
    => Proxy name -> QueryBuilder table -> QueryBuilder table
filterWhereFuture :: forall (table :: Symbol) (name :: Symbol) value.
(KnownSymbol table, KnownSymbol name,
 HasField name (GetModelByTableName table) value,
 Table (GetModelByTableName table)) =>
Proxy name -> QueryBuilder table -> QueryBuilder table
filterWhereFuture Proxy name
name = (Proxy name, Text) -> QueryBuilder table -> QueryBuilder table
forall (name :: Symbol) (table :: Symbol) model value.
(KnownSymbol table, KnownSymbol name, HasField name model value,
 model ~ GetModelByTableName table, Table model) =>
(Proxy name, Text) -> QueryBuilder table -> QueryBuilder table
filterWhereSql (Proxy name
name, Text
"> NOW()")
{-# INLINE filterWhereFuture #-}

-- | Adds a @WHERE x > y@ condition to the query.
--
-- __Example:__ Find assignments with grade greater than 80.
--
-- > greatAssignments <- query @Assignment
-- >     |> filterWhereGreaterThan (#grade, 80)
-- >     |> fetch
-- > -- SELECT * FROM assignments WHERE grade > 80
--
-- See also: 'filterWhereLarger', 'filterWhereGreaterThanOrEqualTo', 'filterWhereAtLeast'
filterWhereGreaterThan :: forall name table model value. (KnownSymbol table, KnownSymbol name, DefaultParamEncoder value, HasField name model value, model ~ GetModelByTableName table, Table model) => (Proxy name, value) -> QueryBuilder table -> QueryBuilder table
filterWhereGreaterThan :: forall (name :: Symbol) (table :: Symbol) model value.
(KnownSymbol table, KnownSymbol name, DefaultParamEncoder value,
 HasField name model value, model ~ GetModelByTableName table,
 Table model) =>
(Proxy name, value) -> QueryBuilder table -> QueryBuilder table
filterWhereGreaterThan (Proxy name
name, value
value) QueryBuilder table
queryBuilder = Condition -> QueryBuilder table -> QueryBuilder table
forall (table :: Symbol).
Condition -> QueryBuilder table -> QueryBuilder table
addCondition Condition
condition QueryBuilder table
queryBuilder
    where
        condition :: Condition
condition = Text
-> FilterOperator
-> ConditionValue
-> Maybe Text
-> Maybe Text
-> Condition
ColumnCondition Text
columnName FilterOperator
GreaterThanOp (value -> ConditionValue
forall a. DefaultParamEncoder a => a -> ConditionValue
paramValue value
value) Maybe Text
forall a. Maybe a
Nothing Maybe Text
forall a. Maybe a
Nothing
        columnName :: Text
columnName = Text -> Text -> Text
qualifiedColumnName (forall record. Table record => Text
tableName @model) (forall (symbol :: Symbol). KnownSymbol symbol => Text
symbolToText @name)
{-# INLINE filterWhereGreaterThan #-}

-- | Alias for 'filterWhereGreaterThan'. Adds a @WHERE x > y@ condition to the query.
--
-- __Example:__ Find assignments with grade larger than 80.
--
-- > greatAssignments <- query @Assignment
-- >     |> filterWhereLarger (#grade, 80)
-- >     |> fetch
-- > -- SELECT * FROM assignments WHERE grade > 80
filterWhereLarger :: forall name table model value. (KnownSymbol table, KnownSymbol name, DefaultParamEncoder value, HasField name model value, model ~ GetModelByTableName table, Table model) => (Proxy name, value) -> QueryBuilder table -> QueryBuilder table
filterWhereLarger :: forall (name :: Symbol) (table :: Symbol) model value.
(KnownSymbol table, KnownSymbol name, DefaultParamEncoder value,
 HasField name model value, model ~ GetModelByTableName table,
 Table model) =>
(Proxy name, value) -> QueryBuilder table -> QueryBuilder table
filterWhereLarger = (Proxy name, value) -> QueryBuilder table -> QueryBuilder table
forall (name :: Symbol) (table :: Symbol) model value.
(KnownSymbol table, KnownSymbol name, DefaultParamEncoder value,
 HasField name model value, model ~ GetModelByTableName table,
 Table model) =>
(Proxy name, value) -> QueryBuilder table -> QueryBuilder table
filterWhereGreaterThan
{-# INLINE filterWhereLarger #-}

-- | Adds a @WHERE x >= y@ condition to the query.
--
-- __Example:__ Find assignments with grade at least 80.
--
-- > greatAssignments <- query @Assignment
-- >     |> filterWhereGreaterThanOrEqualTo (#grade, 80)
-- >     |> fetch
-- > -- SELECT * FROM assignments WHERE grade >= 80
--
-- See also: 'filterWhereAtLeast', 'filterWhereGreaterThan', 'filterWhereLarger'
filterWhereGreaterThanOrEqualTo :: forall name table model value. (KnownSymbol table, KnownSymbol name, DefaultParamEncoder value, HasField name model value, model ~ GetModelByTableName table, Table model) => (Proxy name, value) -> QueryBuilder table -> QueryBuilder table
filterWhereGreaterThanOrEqualTo :: forall (name :: Symbol) (table :: Symbol) model value.
(KnownSymbol table, KnownSymbol name, DefaultParamEncoder value,
 HasField name model value, model ~ GetModelByTableName table,
 Table model) =>
(Proxy name, value) -> QueryBuilder table -> QueryBuilder table
filterWhereGreaterThanOrEqualTo (Proxy name
name, value
value) QueryBuilder table
queryBuilder = Condition -> QueryBuilder table -> QueryBuilder table
forall (table :: Symbol).
Condition -> QueryBuilder table -> QueryBuilder table
addCondition Condition
condition QueryBuilder table
queryBuilder
    where
        condition :: Condition
condition = Text
-> FilterOperator
-> ConditionValue
-> Maybe Text
-> Maybe Text
-> Condition
ColumnCondition Text
columnName FilterOperator
GreaterThanOrEqualToOp (value -> ConditionValue
forall a. DefaultParamEncoder a => a -> ConditionValue
paramValue value
value) Maybe Text
forall a. Maybe a
Nothing Maybe Text
forall a. Maybe a
Nothing
        columnName :: Text
columnName = Text -> Text -> Text
qualifiedColumnName (forall record. Table record => Text
tableName @model) (forall (symbol :: Symbol). KnownSymbol symbol => Text
symbolToText @name)
{-# INLINE filterWhereGreaterThanOrEqualTo #-}

-- | Alias for 'filterWhereGreaterThanOrEqualTo'. Adds a @WHERE x >= y@ condition to the query.
--
-- __Example:__ Find assignments with grade at least 80.
--
-- > greatAssignments <- query @Assignment
-- >     |> filterWhereAtLeast (#grade, 80)
-- >     |> fetch
-- > -- SELECT * FROM assignments WHERE grade >= 80
filterWhereAtLeast :: forall name table model value. (KnownSymbol table, KnownSymbol name, DefaultParamEncoder value, HasField name model value, model ~ GetModelByTableName table, Table model) => (Proxy name, value) -> QueryBuilder table -> QueryBuilder table
filterWhereAtLeast :: forall (name :: Symbol) (table :: Symbol) model value.
(KnownSymbol table, KnownSymbol name, DefaultParamEncoder value,
 HasField name model value, model ~ GetModelByTableName table,
 Table model) =>
(Proxy name, value) -> QueryBuilder table -> QueryBuilder table
filterWhereAtLeast = (Proxy name, value) -> QueryBuilder table -> QueryBuilder table
forall (name :: Symbol) (table :: Symbol) model value.
(KnownSymbol table, KnownSymbol name, DefaultParamEncoder value,
 HasField name model value, model ~ GetModelByTableName table,
 Table model) =>
(Proxy name, value) -> QueryBuilder table -> QueryBuilder table
filterWhereGreaterThanOrEqualTo
{-# INLINE filterWhereAtLeast #-}

-- | Adds a @WHERE x < y@ condition to the query.
--
-- __Example:__ Find assignments with grade less than 60.
--
-- > poorAssignments <- query @Assignment
-- >     |> filterWhereLessThan (#grade, 60)
-- >     |> fetch
-- > -- SELECT * FROM assignments WHERE grade < 60
--
-- See also: 'filterWhereSmaller', 'filterWhereLessThanOrEqualTo', 'filterWhereAtMost'
filterWhereLessThan :: forall name table model value. (KnownSymbol table, KnownSymbol name, DefaultParamEncoder value, HasField name model value, model ~ GetModelByTableName table, Table model) => (Proxy name, value) -> QueryBuilder table -> QueryBuilder table
filterWhereLessThan :: forall (name :: Symbol) (table :: Symbol) model value.
(KnownSymbol table, KnownSymbol name, DefaultParamEncoder value,
 HasField name model value, model ~ GetModelByTableName table,
 Table model) =>
(Proxy name, value) -> QueryBuilder table -> QueryBuilder table
filterWhereLessThan (Proxy name
name, value
value) QueryBuilder table
queryBuilder = Condition -> QueryBuilder table -> QueryBuilder table
forall (table :: Symbol).
Condition -> QueryBuilder table -> QueryBuilder table
addCondition Condition
condition QueryBuilder table
queryBuilder
    where
        condition :: Condition
condition = Text
-> FilterOperator
-> ConditionValue
-> Maybe Text
-> Maybe Text
-> Condition
ColumnCondition Text
columnName FilterOperator
LessThanOp (value -> ConditionValue
forall a. DefaultParamEncoder a => a -> ConditionValue
paramValue value
value) Maybe Text
forall a. Maybe a
Nothing Maybe Text
forall a. Maybe a
Nothing
        columnName :: Text
columnName = Text -> Text -> Text
qualifiedColumnName (forall record. Table record => Text
tableName @model) (forall (symbol :: Symbol). KnownSymbol symbol => Text
symbolToText @name)
{-# INLINE filterWhereLessThan #-}

-- | Alias for 'filterWhereLessThan'. Adds a @WHERE x < y@ condition to the query.
--
-- __Example:__ Find assignments with grade smaller than 60.
--
-- > poorAssignments <- query @Assignment
-- >     |> filterWhereSmaller (#grade, 60)
-- >     |> fetch
-- > -- SELECT * FROM assignments WHERE grade < 60
filterWhereSmaller :: forall name table model value. (KnownSymbol table, KnownSymbol name, DefaultParamEncoder value, HasField name model value, model ~ GetModelByTableName table, Table model) => (Proxy name, value) -> QueryBuilder table -> QueryBuilder table
filterWhereSmaller :: forall (name :: Symbol) (table :: Symbol) model value.
(KnownSymbol table, KnownSymbol name, DefaultParamEncoder value,
 HasField name model value, model ~ GetModelByTableName table,
 Table model) =>
(Proxy name, value) -> QueryBuilder table -> QueryBuilder table
filterWhereSmaller = (Proxy name, value) -> QueryBuilder table -> QueryBuilder table
forall (name :: Symbol) (table :: Symbol) model value.
(KnownSymbol table, KnownSymbol name, DefaultParamEncoder value,
 HasField name model value, model ~ GetModelByTableName table,
 Table model) =>
(Proxy name, value) -> QueryBuilder table -> QueryBuilder table
filterWhereLessThan
{-# INLINE filterWhereSmaller #-}

-- | Adds a @WHERE x <= y@ condition to the query.
--
-- __Example:__ Find assignments with grade at most 60.
--
-- > poorAssignments <- query @Assignment
-- >     |> filterWhereLessThanOrEqualTo (#grade, 60)
-- >     |> fetch
-- > -- SELECT * FROM assignments WHERE grade <= 60
--
-- See also: 'filterWhereAtMost', 'filterWhereLessThan', 'filterWhereSmaller'
filterWhereLessThanOrEqualTo :: forall name table model value. (KnownSymbol table, KnownSymbol name, DefaultParamEncoder value, HasField name model value, model ~ GetModelByTableName table, Table model) => (Proxy name, value) -> QueryBuilder table -> QueryBuilder table
filterWhereLessThanOrEqualTo :: forall (name :: Symbol) (table :: Symbol) model value.
(KnownSymbol table, KnownSymbol name, DefaultParamEncoder value,
 HasField name model value, model ~ GetModelByTableName table,
 Table model) =>
(Proxy name, value) -> QueryBuilder table -> QueryBuilder table
filterWhereLessThanOrEqualTo (Proxy name
name, value
value) QueryBuilder table
queryBuilder = Condition -> QueryBuilder table -> QueryBuilder table
forall (table :: Symbol).
Condition -> QueryBuilder table -> QueryBuilder table
addCondition Condition
condition QueryBuilder table
queryBuilder
    where
        condition :: Condition
condition = Text
-> FilterOperator
-> ConditionValue
-> Maybe Text
-> Maybe Text
-> Condition
ColumnCondition Text
columnName FilterOperator
LessThanOrEqualToOp (value -> ConditionValue
forall a. DefaultParamEncoder a => a -> ConditionValue
paramValue value
value) Maybe Text
forall a. Maybe a
Nothing Maybe Text
forall a. Maybe a
Nothing
        columnName :: Text
columnName = Text -> Text -> Text
qualifiedColumnName (forall record. Table record => Text
tableName @model) (forall (symbol :: Symbol). KnownSymbol symbol => Text
symbolToText @name)
{-# INLINE filterWhereLessThanOrEqualTo #-}

-- | Alias for 'filterWhereLessThanOrEqualTo'. Adds a @WHERE x <= y@ condition to the query.
--
-- __Example:__ Find assignments with grade at most 60.
--
-- > poorAssignments <- query @Assignment
-- >     |> filterWhereAtMost (#grade, 60)
-- >     |> fetch
-- > -- SELECT * FROM assignments WHERE grade <= 60
filterWhereAtMost :: forall name table model value. (KnownSymbol table, KnownSymbol name, DefaultParamEncoder value, HasField name model value, model ~ GetModelByTableName table, Table model) => (Proxy name, value) -> QueryBuilder table -> QueryBuilder table
filterWhereAtMost :: forall (name :: Symbol) (table :: Symbol) model value.
(KnownSymbol table, KnownSymbol name, DefaultParamEncoder value,
 HasField name model value, model ~ GetModelByTableName table,
 Table model) =>
(Proxy name, value) -> QueryBuilder table -> QueryBuilder table
filterWhereAtMost = (Proxy name, value) -> QueryBuilder table -> QueryBuilder table
forall (name :: Symbol) (table :: Symbol) model value.
(KnownSymbol table, KnownSymbol name, DefaultParamEncoder value,
 HasField name model value, model ~ GetModelByTableName table,
 Table model) =>
(Proxy name, value) -> QueryBuilder table -> QueryBuilder table
filterWhereLessThanOrEqualTo
{-# INLINE filterWhereAtMost #-}


-- | Allows to add a custom raw sql where condition
--
-- If your query cannot be represented with 'filterWhereSql', take a look at 'IHP.ModelSupport.sqlQuery'.
--
-- __Example:__ Fetching all projects created in the last 24 hours.
--
-- > latestProjects <- query @Project
-- >     |> filterWhereSql (#startedAt, "< current_timestamp - interval '1 day'")
-- >     |> fetch
-- > -- SELECT * FROM projects WHERE started_at < current_timestamp - interval '1 day'
--
filterWhereSql :: forall name table model value. (KnownSymbol table, KnownSymbol name, HasField name model value, model ~ GetModelByTableName table, Table model) => (Proxy name, Text) -> QueryBuilder table -> QueryBuilder table
filterWhereSql :: forall (name :: Symbol) (table :: Symbol) model value.
(KnownSymbol table, KnownSymbol name, HasField name model value,
 model ~ GetModelByTableName table, Table model) =>
(Proxy name, Text) -> QueryBuilder table -> QueryBuilder table
filterWhereSql (Proxy name
name, Text
sqlCondition) QueryBuilder table
queryBuilder = Condition -> QueryBuilder table -> QueryBuilder table
forall (table :: Symbol).
Condition -> QueryBuilder table -> QueryBuilder table
addCondition Condition
condition QueryBuilder table
queryBuilder
    where
        condition :: Condition
condition = Text
-> FilterOperator
-> ConditionValue
-> Maybe Text
-> Maybe Text
-> Condition
ColumnCondition Text
columnName FilterOperator
SqlOp (Text -> ConditionValue
Literal Text
sqlCondition) Maybe Text
forall a. Maybe a
Nothing Maybe Text
forall a. Maybe a
Nothing
        columnName :: Text
columnName = Text -> Text -> Text
qualifiedColumnName (forall record. Table record => Text
tableName @model) (forall (symbol :: Symbol). KnownSymbol symbol => Text
symbolToText @name)
{-# INLINE filterWhereSql #-}

-- | Adds a @WHERE LOWER(x) = LOWER(y)@ condition to the query.
--
-- __Example:__ Get a user by an email address, ignoring case
--
-- > user <- query @User
-- >     |> filterWhereCaseInsensitive (#email, "marc@digitallyinduced.com")
-- >     |> fetchOne
-- > -- SELECT * FROM users WHERE LOWER(email) = 'marc@digitallyinduced.com'
--
-- For high performance it's best to have an index for @LOWER(field)@ in your Schema.sql
--
-- >>> CREATE UNIQUE INDEX users_email_index ON users ((LOWER(email)));
--
filterWhereCaseInsensitive :: forall name table model value. (KnownSymbol table, KnownSymbol name, DefaultParamEncoder value, HasField name model value, EqOrIsOperator value, model ~ GetModelByTableName table, Table model) => (Proxy name, value) -> QueryBuilder table -> QueryBuilder table
filterWhereCaseInsensitive :: forall (name :: Symbol) (table :: Symbol) model value.
(KnownSymbol table, KnownSymbol name, DefaultParamEncoder value,
 HasField name model value, EqOrIsOperator value,
 model ~ GetModelByTableName table, Table model) =>
(Proxy name, value) -> QueryBuilder table -> QueryBuilder table
filterWhereCaseInsensitive (Proxy name
name, value
value) QueryBuilder table
queryBuilder = Condition -> QueryBuilder table -> QueryBuilder table
forall (table :: Symbol).
Condition -> QueryBuilder table -> QueryBuilder table
addCondition Condition
condition QueryBuilder table
queryBuilder
    where
        condition :: Condition
condition = let op :: FilterOperator
op = value -> FilterOperator
forall value. EqOrIsOperator value => value -> FilterOperator
toEqOrIsOperator value
value in Text
-> FilterOperator
-> ConditionValue
-> Maybe Text
-> Maybe Text
-> Condition
ColumnCondition Text
columnName FilterOperator
op (FilterOperator -> value -> ConditionValue
forall a.
DefaultParamEncoder a =>
FilterOperator -> a -> ConditionValue
condValueForOp FilterOperator
op value
value) (Text -> Maybe Text
forall a. a -> Maybe a
Just Text
"LOWER") (Text -> Maybe Text
forall a. a -> Maybe a
Just Text
"LOWER")
        columnName :: Text
columnName = Text -> Text -> Text
qualifiedColumnName (forall record. Table record => Text
tableName @model) (forall (symbol :: Symbol). KnownSymbol symbol => Text
symbolToText @name)
{-# INLINE filterWhereCaseInsensitive #-}


filterWhereIdIn :: forall table model. (KnownSymbol table, Table model, model ~ GetModelByTableName table, DefaultParamEncoder [PrimaryKey (GetTableName model)]) => [Id model] -> QueryBuilder table -> QueryBuilder table
filterWhereIdIn :: forall (table :: Symbol) model.
(KnownSymbol table, Table model, model ~ GetModelByTableName table,
 DefaultParamEncoder [PrimaryKey (GetTableName model)]) =>
[Id model] -> QueryBuilder table -> QueryBuilder table
filterWhereIdIn [Id model]
values QueryBuilder table
queryBuilder =
    -- We don't need to treat null values differently here, because primary keys imply not-null
    -- Extract the raw primary key values from the Id wrappers
    let
        rawPrimaryKeys :: [PrimaryKey (GetTableName model)]
rawPrimaryKeys = (Id model -> PrimaryKey (GetTableName model))
-> [Id model] -> [PrimaryKey (GetTableName model)]
forall a b. (a -> b) -> [a] -> [b]
map (\(Id PrimaryKey (GetTableName model)
pk) -> PrimaryKey (GetTableName model)
pk) [Id model]
values
        condition :: Condition
condition = Text
-> FilterOperator
-> ConditionValue
-> Maybe Text
-> Maybe Text
-> Condition
ColumnCondition (forall record. Table record => Text
primaryKeyConditionColumnSelector @model) FilterOperator
InOp ([PrimaryKey (GetTableName model)] -> ConditionValue
forall a. DefaultParamEncoder a => a -> ConditionValue
paramValue [PrimaryKey (GetTableName model)]
rawPrimaryKeys) Maybe Text
forall a. Maybe a
Nothing Maybe Text
forall a. Maybe a
Nothing
     in
        Condition -> QueryBuilder table -> QueryBuilder table
forall (table :: Symbol).
Condition -> QueryBuilder table -> QueryBuilder table
addCondition Condition
condition QueryBuilder table
queryBuilder
{-# INLINE filterWhereIdIn #-}