ihp-1.4.0: Haskell Web Framework
Copyright(c) digitally induced GmbH 2020
Safe HaskellNone
LanguageGHC2021

IHP.QueryBuilder

Description

QueryBuilder is mainly used for doing simple SELECT sql queries. It allows dynamic creation of sql queries in a type safe way.

For more complex sql queries, use sqlQuery.

This module re-exports all QueryBuilder submodules for backward compatibility.

Synopsis

Starting a Query

query :: forall model (table :: Symbol). (table ~ GetTableName model, Table model, DefaultScope table) => QueryBuilder table Source #

Represent's a SELECT * FROM .. query. It's the starting point to build a query. Used together with the other functions to compose a sql query.

Example: Fetching all users

allUsers <- query @User |> fetch
-- Runs a 'SELECT * FROM users' query

You can use it together with filterWhere:

activeUsers :: [User] <-
   query @User
    |> filterWhere (#active, True)
    |> fetch

Core Types

data QueryBuilder (table :: Symbol) Source #

The main QueryBuilder data type, representing different query operations

Instances

Instances details
HasQueryBuilder QueryBuilder EmptyModelList Source #

QueryBuilders have query builders and the join register is empty.

Instance details

Defined in IHP.QueryBuilder.Types

Methods

getQueryBuilder :: forall (table :: Symbol). QueryBuilder table -> QueryBuilder table Source #

injectQueryBuilder :: forall (table :: Symbol). QueryBuilder table -> QueryBuilder table Source #

getQueryIndex :: forall (table :: Symbol). QueryBuilder table -> Maybe Text Source #

Table (GetModelByTableName table) => Default (QueryBuilder table) Source # 
Instance details

Defined in IHP.QueryBuilder.Types

Methods

def :: QueryBuilder table Source #

Show (QueryBuilder table) Source # 
Instance details

Defined in IHP.QueryBuilder.Types

Methods

showsPrec :: Int -> QueryBuilder table -> ShowS #

show :: QueryBuilder table -> String #

showList :: [QueryBuilder table] -> ShowS #

Eq (QueryBuilder table) Source # 
Instance details

Defined in IHP.QueryBuilder.Types

Methods

(==) :: QueryBuilder table -> QueryBuilder table -> Bool #

(/=) :: QueryBuilder table -> QueryBuilder table -> Bool #

KnownSymbol table => ToHtml (QueryBuilder table) Source #

Display QueryBuilder's as their sql query inside HSX

Instance details

Defined in IHP.QueryBuilder.Types

Methods

toHtml :: QueryBuilder table -> Html

(model ~ GetModelByTableName table, KnownSymbol table) => Fetchable (QueryBuilder table) model Source # 
Instance details

Defined in IHP.Fetch

Associated Types

type FetchResult (QueryBuilder table) model 
Instance details

Defined in IHP.Fetch

type FetchResult (QueryBuilder table) model = [model]

Methods

fetch :: QueryBuilder table -> IO (FetchResult (QueryBuilder table) model) Source #

fetchOneOrNothing :: QueryBuilder table -> IO (Maybe model) Source #

fetchOne :: QueryBuilder table -> IO model Source #

type FetchResult (QueryBuilder table) model Source # 
Instance details

Defined in IHP.Fetch

type FetchResult (QueryBuilder table) model = [model]

data Condition Source #

Represents a WHERE condition

Instances

Instances details
Show Condition Source # 
Instance details

Defined in IHP.QueryBuilder.Types

Eq Condition Source # 
Instance details

Defined in IHP.QueryBuilder.Types

SetField "whereCondition" SQLQuery (Maybe Condition) Source # 
Instance details

Defined in IHP.QueryBuilder.Types

data Join Source #

Represents a JOIN clause

Constructors

Join 

Instances

Instances details
Show Join Source # 
Instance details

Defined in IHP.QueryBuilder.Types

Methods

showsPrec :: Int -> Join -> ShowS #

show :: Join -> String #

showList :: [Join] -> ShowS #

Eq Join Source # 
Instance details

Defined in IHP.QueryBuilder.Types

Methods

(==) :: Join -> Join -> Bool #

(/=) :: Join -> Join -> Bool #

data OrderByClause Source #

Represents an ORDER BY clause component

Instances

Instances details
NFData OrderByClause Source # 
Instance details

Defined in IHP.QueryBuilder.Types

Methods

rnf :: OrderByClause -> () #

Generic OrderByClause Source # 
Instance details

Defined in IHP.QueryBuilder.Types

Associated Types

type Rep OrderByClause 
Instance details

Defined in IHP.QueryBuilder.Types

type Rep OrderByClause = D1 ('MetaData "OrderByClause" "IHP.QueryBuilder.Types" "ihp-1.4.0-43TSTr8sXn3AQow4erFGsr" 'False) (C1 ('MetaCons "OrderByClause" 'PrefixI 'True) (S1 ('MetaSel ('Just "orderByColumn") 'NoSourceUnpackedness 'SourceStrict 'DecidedStrict) (Rec0 Text) :*: S1 ('MetaSel ('Just "orderByDirection") 'NoSourceUnpackedness 'SourceStrict 'DecidedStrict) (Rec0 OrderByDirection)))
Show OrderByClause Source # 
Instance details

Defined in IHP.QueryBuilder.Types

Eq OrderByClause Source # 
Instance details

Defined in IHP.QueryBuilder.Types

SetField "orderByClause" SQLQuery [OrderByClause] Source # 
Instance details

Defined in IHP.QueryBuilder.Types

type Rep OrderByClause Source # 
Instance details

Defined in IHP.QueryBuilder.Types

type Rep OrderByClause = D1 ('MetaData "OrderByClause" "IHP.QueryBuilder.Types" "ihp-1.4.0-43TSTr8sXn3AQow4erFGsr" 'False) (C1 ('MetaCons "OrderByClause" 'PrefixI 'True) (S1 ('MetaSel ('Just "orderByColumn") 'NoSourceUnpackedness 'SourceStrict 'DecidedStrict) (Rec0 Text) :*: S1 ('MetaSel ('Just "orderByDirection") 'NoSourceUnpackedness 'SourceStrict 'DecidedStrict) (Rec0 OrderByDirection)))

data OrderByDirection Source #

ORDER BY direction

Constructors

Asc 
Desc 

Instances

Instances details
NFData OrderByDirection Source # 
Instance details

Defined in IHP.QueryBuilder.Types

Methods

rnf :: OrderByDirection -> () #

Generic OrderByDirection Source # 
Instance details

Defined in IHP.QueryBuilder.Types

Associated Types

type Rep OrderByDirection 
Instance details

Defined in IHP.QueryBuilder.Types

type Rep OrderByDirection = D1 ('MetaData "OrderByDirection" "IHP.QueryBuilder.Types" "ihp-1.4.0-43TSTr8sXn3AQow4erFGsr" 'False) (C1 ('MetaCons "Asc" 'PrefixI 'False) (U1 :: Type -> Type) :+: C1 ('MetaCons "Desc" 'PrefixI 'False) (U1 :: Type -> Type))
Show OrderByDirection Source # 
Instance details

Defined in IHP.QueryBuilder.Types

Eq OrderByDirection Source # 
Instance details

Defined in IHP.QueryBuilder.Types

type Rep OrderByDirection Source # 
Instance details

Defined in IHP.QueryBuilder.Types

type Rep OrderByDirection = D1 ('MetaData "OrderByDirection" "IHP.QueryBuilder.Types" "ihp-1.4.0-43TSTr8sXn3AQow4erFGsr" 'False) (C1 ('MetaCons "Asc" 'PrefixI 'False) (U1 :: Type -> Type) :+: C1 ('MetaCons "Desc" 'PrefixI 'False) (U1 :: Type -> Type))

data FilterOperator Source #

Operators used in WHERE clause conditions

Constructors

EqOp
col = val
NotEqOp
col != val
InOp
col IN (set)
NotInOp
col NOT IN (set)
IsOp
col IS val
IsNotOp
col IS NOT val
LikeOp !MatchSensitivity
col LIKE val
NotLikeOp !MatchSensitivity
col NOT LIKE val
MatchesOp !MatchSensitivity
col ~ pattern
GreaterThanOp
col > val
GreaterThanOrEqualToOp
col >= val
LessThanOp
col < val
LessThanOrEqualToOp
col <= val
SqlOp

Used by filterWhereSql

data MatchSensitivity Source #

Represents whether string matching should be case-sensitive or not

Type Classes

class DefaultScope (table :: Symbol) where Source #

Type class for default scoping of queries

Methods

defaultScope :: QueryBuilder table -> QueryBuilder table Source #

Instances

Instances details
DefaultScope table Source # 
Instance details

Defined in IHP.QueryBuilder.Types

Methods

defaultScope :: QueryBuilder table -> QueryBuilder table Source #

class HasQueryBuilder (queryBuilderProvider :: Symbol -> Type) (joinRegister :: k) | queryBuilderProvider -> joinRegister Source #

Class to generalise over different QueryBuilder-providing types. The actual query builder can be extracted with getQueryBuilder and injected with injectQueryBuilder. Also assigns a join register to a queryBuilderProvider.

Minimal complete definition

getQueryBuilder, injectQueryBuilder

Instances

Instances details
HasQueryBuilder NoJoinQueryBuilderWrapper NoJoins Source #

NoJoinQueryBuilderWrapper have query builders and the join register does not allow any joins

Instance details

Defined in IHP.QueryBuilder.Types

HasQueryBuilder QueryBuilder EmptyModelList Source #

QueryBuilders have query builders and the join register is empty.

Instance details

Defined in IHP.QueryBuilder.Types

Methods

getQueryBuilder :: forall (table :: Symbol). QueryBuilder table -> QueryBuilder table Source #

injectQueryBuilder :: forall (table :: Symbol). QueryBuilder table -> QueryBuilder table Source #

getQueryIndex :: forall (table :: Symbol). QueryBuilder table -> Maybe Text Source #

HasQueryBuilder (JoinQueryBuilderWrapper joinRegister) (joinRegister :: k) Source #

JoinQueryBuilderWrappers have query builders

Instance details

Defined in IHP.QueryBuilder.Types

Methods

getQueryBuilder :: forall (table :: Symbol). JoinQueryBuilderWrapper joinRegister table -> QueryBuilder table Source #

injectQueryBuilder :: forall (table :: Symbol). QueryBuilder table -> JoinQueryBuilderWrapper joinRegister table Source #

getQueryIndex :: forall (table :: Symbol). JoinQueryBuilderWrapper joinRegister table -> Maybe Text Source #

(KnownSymbol foreignTable, foreignModel ~ GetModelByTableName foreignTable, KnownSymbol indexColumn, HasField indexColumn foreignModel indexValue) => HasQueryBuilder (LabeledQueryBuilderWrapper foreignTable indexColumn indexValue) NoJoins Source # 
Instance details

Defined in IHP.QueryBuilder.Types

Methods

getQueryBuilder :: forall (table :: Symbol). LabeledQueryBuilderWrapper foreignTable indexColumn indexValue table -> QueryBuilder table Source #

injectQueryBuilder :: forall (table :: Symbol). QueryBuilder table -> LabeledQueryBuilderWrapper foreignTable indexColumn indexValue table Source #

getQueryIndex :: forall (table :: Symbol). LabeledQueryBuilderWrapper foreignTable indexColumn indexValue table -> Maybe Text Source #

class EqOrIsOperator value Source #

Helper to deal with some_field IS NULL and some_field = 'some value'

Minimal complete definition

toEqOrIsOperator

Instances

Instances details
EqOrIsOperator otherwise Source # 
Instance details

Defined in IHP.QueryBuilder.Types

Methods

toEqOrIsOperator :: otherwise -> FilterOperator Source #

EqOrIsOperator (Maybe something) Source # 
Instance details

Defined in IHP.QueryBuilder.Types

class FilterPrimaryKey (table :: Symbol) where Source #

Type class for filtering by primary key

Methods

filterWhereId :: Id' table -> QueryBuilder table -> QueryBuilder table Source #

QueryBuilder Wrappers

data JoinQueryBuilderWrapper (joinRegister :: k) (table :: Symbol) Source #

Wrapper for QueryBuilders resulting from joins. Associates a joinRegister type.

Instances

Instances details
HasQueryBuilder (JoinQueryBuilderWrapper joinRegister) (joinRegister :: k) Source #

JoinQueryBuilderWrappers have query builders

Instance details

Defined in IHP.QueryBuilder.Types

Methods

getQueryBuilder :: forall (table :: Symbol). JoinQueryBuilderWrapper joinRegister table -> QueryBuilder table Source #

injectQueryBuilder :: forall (table :: Symbol). QueryBuilder table -> JoinQueryBuilderWrapper joinRegister table Source #

getQueryIndex :: forall (table :: Symbol). JoinQueryBuilderWrapper joinRegister table -> Maybe Text Source #

(model ~ GetModelByTableName table, KnownSymbol table) => Fetchable (JoinQueryBuilderWrapper r table) model Source # 
Instance details

Defined in IHP.Fetch

Associated Types

type FetchResult (JoinQueryBuilderWrapper r table) model 
Instance details

Defined in IHP.Fetch

type FetchResult (JoinQueryBuilderWrapper r table) model = [model]
type FetchResult (JoinQueryBuilderWrapper r table) model Source # 
Instance details

Defined in IHP.Fetch

type FetchResult (JoinQueryBuilderWrapper r table) model = [model]

data NoJoinQueryBuilderWrapper (table :: Symbol) Source #

Wrapper for QueryBuilder that must not joins, e.g. queryUnion.

Instances

Instances details
HasQueryBuilder NoJoinQueryBuilderWrapper NoJoins Source #

NoJoinQueryBuilderWrapper have query builders and the join register does not allow any joins

Instance details

Defined in IHP.QueryBuilder.Types

(model ~ GetModelByTableName table, KnownSymbol table) => Fetchable (NoJoinQueryBuilderWrapper table) model Source # 
Instance details

Defined in IHP.Fetch

Associated Types

type FetchResult (NoJoinQueryBuilderWrapper table) model 
Instance details

Defined in IHP.Fetch

type FetchResult (NoJoinQueryBuilderWrapper table) model = [model]
type FetchResult (NoJoinQueryBuilderWrapper table) model Source # 
Instance details

Defined in IHP.Fetch

type FetchResult (NoJoinQueryBuilderWrapper table) model = [model]

data LabeledQueryBuilderWrapper (foreignTable :: k) (indexColumn :: k1) (indexValue :: k2) (table :: Symbol) Source #

Wrapper for QueryBuilders with indexed results.

Instances

Instances details
(KnownSymbol foreignTable, foreignModel ~ GetModelByTableName foreignTable, KnownSymbol indexColumn, HasField indexColumn foreignModel indexValue) => HasQueryBuilder (LabeledQueryBuilderWrapper foreignTable indexColumn indexValue) NoJoins Source # 
Instance details

Defined in IHP.QueryBuilder.Types

Methods

getQueryBuilder :: forall (table :: Symbol). LabeledQueryBuilderWrapper foreignTable indexColumn indexValue table -> QueryBuilder table Source #

injectQueryBuilder :: forall (table :: Symbol). QueryBuilder table -> LabeledQueryBuilderWrapper foreignTable indexColumn indexValue table Source #

getQueryIndex :: forall (table :: Symbol). LabeledQueryBuilderWrapper foreignTable indexColumn indexValue table -> Maybe Text Source #

(model ~ GetModelByTableName table, KnownSymbol table, HasqlDecodeColumn value, KnownSymbol foreignTable, foreignModel ~ GetModelByTableName foreignTable, KnownSymbol columnName, HasField columnName foreignModel value, HasQueryBuilder (LabeledQueryBuilderWrapper foreignTable columnName value) NoJoins) => Fetchable (LabeledQueryBuilderWrapper foreignTable columnName value table) model Source # 
Instance details

Defined in IHP.Fetch

Associated Types

type FetchResult (LabeledQueryBuilderWrapper foreignTable columnName value table) model 
Instance details

Defined in IHP.Fetch

type FetchResult (LabeledQueryBuilderWrapper foreignTable columnName value table) model = [LabeledData value model]

Methods

fetch :: LabeledQueryBuilderWrapper foreignTable columnName value table -> IO (FetchResult (LabeledQueryBuilderWrapper foreignTable columnName value table) model) Source #

fetchOneOrNothing :: LabeledQueryBuilderWrapper foreignTable columnName value table -> IO (Maybe model) Source #

fetchOne :: LabeledQueryBuilderWrapper foreignTable columnName value table -> IO model Source #

type FetchResult (LabeledQueryBuilderWrapper foreignTable columnName value table) model Source # 
Instance details

Defined in IHP.Fetch

type FetchResult (LabeledQueryBuilderWrapper foreignTable columnName value table) model = [LabeledData value model]

getQueryBuilder :: forall (table :: Symbol). HasQueryBuilder queryBuilderProvider joinRegister => queryBuilderProvider table -> QueryBuilder table Source #

injectQueryBuilder :: forall (table :: Symbol). HasQueryBuilder queryBuilderProvider joinRegister => QueryBuilder table -> queryBuilderProvider table Source #

Type-level Join Tracking

data NoJoins Source #

Type-level marker indicating no joins are allowed

Instances

Instances details
HasQueryBuilder NoJoinQueryBuilderWrapper NoJoins Source #

NoJoinQueryBuilderWrapper have query builders and the join register does not allow any joins

Instance details

Defined in IHP.QueryBuilder.Types

(KnownSymbol foreignTable, foreignModel ~ GetModelByTableName foreignTable, KnownSymbol indexColumn, HasField indexColumn foreignModel indexValue) => HasQueryBuilder (LabeledQueryBuilderWrapper foreignTable indexColumn indexValue) NoJoins Source # 
Instance details

Defined in IHP.QueryBuilder.Types

Methods

getQueryBuilder :: forall (table :: Symbol). LabeledQueryBuilderWrapper foreignTable indexColumn indexValue table -> QueryBuilder table Source #

injectQueryBuilder :: forall (table :: Symbol). QueryBuilder table -> LabeledQueryBuilderWrapper foreignTable indexColumn indexValue table Source #

getQueryIndex :: forall (table :: Symbol). LabeledQueryBuilderWrapper foreignTable indexColumn indexValue table -> Maybe Text Source #

SQL Compilation

buildQuery :: forall {k} (table :: Symbol) queryBuilderProvider (joinRegister :: k). (KnownSymbol table, HasQueryBuilder queryBuilderProvider joinRegister) => queryBuilderProvider table -> SQLQuery Source #

Hasql Compilation

toSnippet :: forall {k} (table :: Symbol) queryBuilderProvider (joinRegister :: k). (KnownSymbol table, HasQueryBuilder queryBuilderProvider joinRegister) => queryBuilderProvider table -> Snippet Source #

Compile a QueryBuilder to a Hasql Snippet

snippetToSQL :: Snippet -> Text Source #

Extract the SQL ByteString from a Snippet (for testing purposes)

This converts a Snippet to a Statement and extracts the SQL text. Useful for verifying the hasql compilation path in tests.

Filtering

filterWhere :: forall {k} (name :: Symbol) (table :: Symbol) model value queryBuilderProvider (joinRegister :: k). (KnownSymbol table, KnownSymbol name, DefaultParamEncoder value, HasField name model value, EqOrIsOperator value, model ~ GetModelByTableName table, HasQueryBuilder queryBuilderProvider joinRegister, Table model) => (Proxy name, value) -> queryBuilderProvider table -> queryBuilderProvider table Source #

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 sqlQuery.

filterWhereCaseInsensitive :: forall {k} (name :: Symbol) (table :: Symbol) model value queryBuilderProvider (joinRegister :: k). (KnownSymbol table, KnownSymbol name, DefaultParamEncoder value, HasField name model value, EqOrIsOperator value, model ~ GetModelByTableName table, HasQueryBuilder queryBuilderProvider joinRegister, Table model) => (Proxy name, value) -> queryBuilderProvider table -> queryBuilderProvider table Source #

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)));

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 Source #

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'

filterWhereIn :: forall (name :: Symbol) (table :: Symbol) model value queryBuilderProvider joinRegister. (KnownSymbol table, KnownSymbol name, DefaultParamEncoder [value], DefaultParamEncoder value, HasField name model value, model ~ GetModelByTableName table, HasQueryBuilder queryBuilderProvider joinRegister, EqOrIsOperator value, Table model) => (Proxy name, [value]) -> queryBuilderProvider table -> queryBuilderProvider table Source #

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

filterWhereInCaseInsensitive :: forall (name :: Symbol) (table :: Symbol) model value queryBuilderProvider joinRegister. (KnownSymbol table, KnownSymbol name, DefaultParamEncoder value, HasField name model value, model ~ GetModelByTableName table, HasQueryBuilder queryBuilderProvider joinRegister, EqOrIsOperator value, Table model) => (Proxy name, [Text]) -> queryBuilderProvider table -> queryBuilderProvider table Source #

filterWhereIdIn :: forall (table :: Symbol) model queryBuilderProvider joinRegister. (KnownSymbol table, Table model, model ~ GetModelByTableName table, HasQueryBuilder queryBuilderProvider joinRegister, DefaultParamEncoder [PrimaryKey (GetTableName model)]) => [Id model] -> queryBuilderProvider table -> queryBuilderProvider table Source #

filterWhereNotIn :: forall {k} (name :: Symbol) (table :: Symbol) model value queryBuilderProvider (joinRegister :: k). (KnownSymbol table, KnownSymbol name, DefaultParamEncoder [value], DefaultParamEncoder value, HasField name model value, model ~ GetModelByTableName table, HasQueryBuilder queryBuilderProvider joinRegister, EqOrIsOperator value) => (Proxy name, [value]) -> queryBuilderProvider table -> queryBuilderProvider table Source #

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.

filterWhereLike :: forall {k} (name :: Symbol) (table :: Symbol) model value queryBuilderProvider (joinRegister :: k). (KnownSymbol table, KnownSymbol name, DefaultParamEncoder value, HasField name model value, model ~ GetModelByTableName table, HasQueryBuilder queryBuilderProvider joinRegister, Table model) => (Proxy name, value) -> queryBuilderProvider table -> queryBuilderProvider table Source #

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 '%..%'

filterWhereILike :: forall {k} (name :: Symbol) (table :: Symbol) model value queryBuilderProvider (joinRegister :: k). (KnownSymbol table, KnownSymbol name, DefaultParamEncoder value, HasField name model value, model ~ GetModelByTableName table, HasQueryBuilder queryBuilderProvider joinRegister, Table model) => (Proxy name, value) -> queryBuilderProvider table -> queryBuilderProvider table Source #

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 '%..%'

filterWhereMatches :: forall {k} (name :: Symbol) (table :: Symbol) model value queryBuilderProvider (joinRegister :: k). (KnownSymbol table, KnownSymbol name, DefaultParamEncoder value, HasField name model value, table ~ GetTableName model, HasQueryBuilder queryBuilderProvider joinRegister, Table model) => (Proxy name, value) -> queryBuilderProvider table -> queryBuilderProvider table Source #

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). '

filterWhereIMatches :: forall {k} (name :: Symbol) (table :: Symbol) model value queryBuilderProvider (joinRegister :: k). (KnownSymbol table, KnownSymbol name, DefaultParamEncoder value, HasField name model value, model ~ GetModelByTableName table, HasQueryBuilder queryBuilderProvider joinRegister, Table model) => (Proxy name, value) -> queryBuilderProvider table -> queryBuilderProvider table Source #

Adds a WHERE x ~* y condition to the query. Case-insensitive version of filterWhereMatches.

filterWherePast :: forall {k} (table :: Symbol) (name :: Symbol) value queryBuilderProvider (joinRegister :: k). (KnownSymbol table, KnownSymbol name, HasField name (GetModelByTableName table) value, HasQueryBuilder queryBuilderProvider joinRegister, Table (GetModelByTableName table)) => Proxy name -> queryBuilderProvider table -> queryBuilderProvider table Source #

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()

filterWhereFuture :: forall {k} (table :: Symbol) (name :: Symbol) value queryBuilderProvider (joinRegister :: k). (KnownSymbol table, KnownSymbol name, HasField name (GetModelByTableName table) value, HasQueryBuilder queryBuilderProvider joinRegister, Table (GetModelByTableName table)) => Proxy name -> queryBuilderProvider table -> queryBuilderProvider table Source #

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()

filterWhereGreaterThan :: forall {k} (name :: Symbol) (table :: Symbol) model value queryBuilderProvider (joinRegister :: k). (KnownSymbol table, KnownSymbol name, DefaultParamEncoder value, HasField name model value, model ~ GetModelByTableName table, HasQueryBuilder queryBuilderProvider joinRegister, Table model) => (Proxy name, value) -> queryBuilderProvider table -> queryBuilderProvider table Source #

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

filterWhereLarger :: forall {k} (name :: Symbol) (table :: Symbol) model value queryBuilderProvider (joinRegister :: k). (KnownSymbol table, KnownSymbol name, DefaultParamEncoder value, HasField name model value, model ~ GetModelByTableName table, HasQueryBuilder queryBuilderProvider joinRegister, Table model) => (Proxy name, value) -> queryBuilderProvider table -> queryBuilderProvider table Source #

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

filterWhereGreaterThanOrEqualTo :: forall {k} (name :: Symbol) (table :: Symbol) model value queryBuilderProvider (joinRegister :: k). (KnownSymbol table, KnownSymbol name, DefaultParamEncoder value, HasField name model value, model ~ GetModelByTableName table, HasQueryBuilder queryBuilderProvider joinRegister, Table model) => (Proxy name, value) -> queryBuilderProvider table -> queryBuilderProvider table Source #

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

filterWhereAtLeast :: forall {k} (name :: Symbol) (table :: Symbol) model value queryBuilderProvider (joinRegister :: k). (KnownSymbol table, KnownSymbol name, DefaultParamEncoder value, HasField name model value, model ~ GetModelByTableName table, HasQueryBuilder queryBuilderProvider joinRegister, Table model) => (Proxy name, value) -> queryBuilderProvider table -> queryBuilderProvider table Source #

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

filterWhereLessThan :: forall {k} (name :: Symbol) (table :: Symbol) model value queryBuilderProvider (joinRegister :: k). (KnownSymbol table, KnownSymbol name, DefaultParamEncoder value, HasField name model value, model ~ GetModelByTableName table, HasQueryBuilder queryBuilderProvider joinRegister, Table model) => (Proxy name, value) -> queryBuilderProvider table -> queryBuilderProvider table Source #

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

filterWhereSmaller :: forall {k} (name :: Symbol) (table :: Symbol) model value queryBuilderProvider (joinRegister :: k). (KnownSymbol table, KnownSymbol name, DefaultParamEncoder value, HasField name model value, model ~ GetModelByTableName table, HasQueryBuilder queryBuilderProvider joinRegister, Table model) => (Proxy name, value) -> queryBuilderProvider table -> queryBuilderProvider table Source #

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

filterWhereLessThanOrEqualTo :: forall {k} (name :: Symbol) (table :: Symbol) model value queryBuilderProvider (joinRegister :: k). (KnownSymbol table, KnownSymbol name, DefaultParamEncoder value, HasField name model value, model ~ GetModelByTableName table, HasQueryBuilder queryBuilderProvider joinRegister, Table model) => (Proxy name, value) -> queryBuilderProvider table -> queryBuilderProvider table Source #

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

filterWhereAtMost :: forall {k} (name :: Symbol) (table :: Symbol) model value queryBuilderProvider (joinRegister :: k). (KnownSymbol table, KnownSymbol name, DefaultParamEncoder value, HasField name model value, model ~ GetModelByTableName table, HasQueryBuilder queryBuilderProvider joinRegister, Table model) => (Proxy name, value) -> queryBuilderProvider table -> queryBuilderProvider table Source #

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

filterWhereSql :: forall {k} (name :: Symbol) (table :: Symbol) model value queryBuilderProvider (joinRegister :: k). (KnownSymbol table, KnownSymbol name, HasField name model value, model ~ GetModelByTableName table, HasQueryBuilder queryBuilderProvider joinRegister, Table model) => (Proxy name, Text) -> queryBuilderProvider table -> queryBuilderProvider table Source #

Allows to add a custom raw sql where condition

If your query cannot be represented with filterWhereSql, take a look at 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'

Filtering on Joined Tables

filterWhereJoinedTable :: forall {k1} model (name :: Symbol) (table :: Symbol) value queryBuilderProvider (joinRegister :: k1) (table' :: Symbol). (KnownSymbol table, KnownSymbol name, DefaultParamEncoder value, HasField name model value, EqOrIsOperator value, table ~ GetTableName model, HasQueryBuilder queryBuilderProvider joinRegister, IsJoined model joinRegister, Table model) => (Proxy name, value) -> queryBuilderProvider table' -> queryBuilderProvider table' Source #

Like filterWhere, but takes a type argument specifying the table which holds the column that is to be compared. The column must have been joined before using innerJoin or innerJoinThirdTable. Example:

Example: get posts by user Tom.

tomPosts <- query @Post
                   |> innerJoin @User (#createdBy, #id)
                   |> filterWhereJoinedTable @User (#name, "Tom" :: Text)
                   |> fetch
-- SELECT posts.* FROM posts INNER JOIN users ON posts.created_by = users.id WHERE users.name = 'Tom'

filterWhereCaseInsensitiveJoinedTable :: forall {k1} model (name :: Symbol) (table :: Symbol) value queryBuilderProvider (joinRegister :: k1) (table' :: Symbol). (KnownSymbol table, KnownSymbol name, DefaultParamEncoder value, HasField name model value, EqOrIsOperator value, table ~ GetTableName model, HasQueryBuilder queryBuilderProvider joinRegister, IsJoined model joinRegister, Table model) => (Proxy name, value) -> queryBuilderProvider table' -> queryBuilderProvider table' Source #

Like filterWhereJoinedTable, but adds a WHERE LOWER(x) = LOWER(y) condition to the query. Example:

Example: get posts by user Tom, ignoring case.

tomPosts <- query @Post
                   |> innerJoin @User (#createdBy, #id)
                   |> filterWhereCaseInsensitiveJoinedTable @User (#name, "Tom" :: Text)
                   |> fetch
-- SELECT posts.* FROM posts INNER JOIN users ON posts.created_by = users.id WHERE LOWER(users.name) = LOWER('Tom')

filterWhereNotJoinedTable :: forall {k1} model (name :: Symbol) (table :: Symbol) value queryBuilderProvider (joinRegister :: k1) (table' :: Symbol). (KnownSymbol table, KnownSymbol name, DefaultParamEncoder value, HasField name model value, EqOrIsOperator value, table ~ GetTableName model, HasQueryBuilder queryBuilderProvider joinRegister, IsJoined model joinRegister, Table model) => (Proxy name, value) -> queryBuilderProvider table' -> queryBuilderProvider table' Source #

Like filterWhereNotJoinedTable but negates the condition.

Example: Only show projects not created by user Tom.

tomPosts <- query @Post
                   |> innerJoin @User (#createdBy, #id)
                   |> filterWhereNotJoinedTable @User (#name, "Tom" :: Text)
                   |> fetch
-- SELECT posts.* FROM posts INNER JOIN users ON posts.created_by = users.id WHERE users.name = 'Tom'

filterWhereInJoinedTable :: forall {k1} model (name :: Symbol) (table :: Symbol) value queryBuilderProvider (joinRegister :: k1) (table' :: Symbol). (KnownSymbol table, KnownSymbol name, DefaultParamEncoder [value], HasField name model value, table ~ GetTableName model, HasQueryBuilder queryBuilderProvider joinRegister, IsJoined model joinRegister, Table model) => (Proxy name, [value]) -> queryBuilderProvider table' -> queryBuilderProvider table' Source #

Like filterWhereIn, but takes a type argument specifying the table which holds the column that is compared. The table needs to have been joined before using innerJoin or innerJoinThirdTable.

Example: get posts by Tom and Tim.

tomOrTimPosts <- query @Post
   |> innerJoin @User (#createdBy, #id)
   |> filterWhereInJoinedTable @User (#name, ["Tom","Tim"])
   |> fetch
-- SELECT posts.* FROM posts INNER JOIN users ON posts.created_by = users.id WHERE users.name IN ('Tom', 'Tim')

filterWhereNotInJoinedTable :: forall {k1} model (name :: Symbol) (table :: Symbol) value queryBuilderProvider (joinRegister :: k1) (table' :: Symbol). (KnownSymbol table, KnownSymbol name, DefaultParamEncoder [value], HasField name model value, table ~ GetTableName model, HasQueryBuilder queryBuilderProvider joinRegister, IsJoined model joinRegister, Table model) => (Proxy name, [value]) -> queryBuilderProvider table' -> queryBuilderProvider table' Source #

Like filterWhereNotIn, but takes a type argument specifying the table which holds the column that is compared. The table needs to have been joined before using innerJoin or innerJoinThirdTable.

Example: get posts by users not named Tom or Tim.

notTomOrTimPosts <- query @Post
   |> innerJoin @User (#createdBy, #id)
   |> filterWhereNotInJoinedTable @User (#name, ["Tom","Tim"])
   |> fetch
-- SELECT posts.* FROM posts INNER JOIN users ON posts.created_by = users.id WHERE users.name NOT IN ('Tom', 'Tim')

filterWhereLikeJoinedTable :: forall {k1} model (name :: Symbol) (table :: Symbol) value queryBuilderProvider (joinRegister :: k1) (table' :: Symbol). (KnownSymbol name, KnownSymbol table, table ~ GetTableName model, DefaultParamEncoder value, HasField name model value, model ~ GetModelByTableName table, HasQueryBuilder queryBuilderProvider joinRegister, IsJoined model joinRegister, Table model) => (Proxy name, value) -> queryBuilderProvider table' -> queryBuilderProvider table' Source #

Like filterWhereLike, but takes a type argument specifying the table which holds the column that is compared. The table needs to have been joined before using innerJoin or innerJoinThirdTable.

Example: Serach for Posts by users whose name contains "olaf" (case insensitive)

olafPosts <- query @Post
               |> innerJoin @User (#createdBy, #id)
               |> filterWhereLikeJoinedTable @User (#name, "%Olaf%")
               |> fetch
-- SELECT posts.* FROM posts INNER JOIN users ON posts.created_by = users.id WHERE users.name LIKE '%Olaf%'

filterWhereILikeJoinedTable :: forall {k1} model (table :: Symbol) (name :: Symbol) (table' :: Symbol) model' value queryBuilderProvider (joinRegister :: k1). (KnownSymbol table, KnownSymbol name, DefaultParamEncoder value, HasField name model value, table ~ GetTableName model, model' ~ GetModelByTableName table', HasQueryBuilder queryBuilderProvider joinRegister, IsJoined model joinRegister, Table model) => (Proxy name, value) -> queryBuilderProvider table' -> queryBuilderProvider table' Source #

Like filterWhereILike; case-insensitive version of filterWhereLikeJoinedTable, takes a type argument specifying the table which holds the column that is compared. The table needs to have been joined before using innerJoin or innerJoinThirdTable.

Example: Serach for Posts by users whose name contains "olaf" (case insensitive)

olafPosts <-
   query @Post

|> innerJoin User (#createdBy, #id) |> filterWhereILikeJoinedTable User (#name, "%Olaf%") > -- SELECT posts.* FROM posts INNER JOIN users ON posts.created_by = users.id WHERE users.name ILIKE '%Olaf%'

filterWhereMatchesJoinedTable :: forall {k1} model (table :: Symbol) (name :: Symbol) value queryBuilderProvider (joinRegister :: k1) (table' :: Symbol). (KnownSymbol table, KnownSymbol name, DefaultParamEncoder value, HasField name model value, table ~ GetTableName model, HasQueryBuilder queryBuilderProvider joinRegister, IsJoined model joinRegister, Table model) => (Proxy name, value) -> queryBuilderProvider table' -> queryBuilderProvider table' Source #

Adds a WHERE x ~ y condition to the query, where the column x is held by a joined table.

Example: Find Posts by people with names with titles in front.

articles <- query @Post
    |> innerJoin @User (#createdBy, #id)
    |> filterWhereMatchesJoinedTable (#title, "^(M(rs|r|iss|s)|Dr|Sir). ")
    |> fetch
-- SELECT posts.* FROM posts INNER JOIN users ON posts.created_by = users.id WHERE users.title ~ '^(M(rs|r|iss|s)|Dr|Sir). '

filterWhereIMatchesJoinedTable :: forall {k1} model (table :: Symbol) (name :: Symbol) value queryBuilderProvider (joinRegister :: k1) (table' :: Symbol). (KnownSymbol table, KnownSymbol name, DefaultParamEncoder value, HasField name model value, table ~ GetTableName model, HasQueryBuilder queryBuilderProvider joinRegister, IsJoined model joinRegister, Table model) => (Proxy name, value) -> queryBuilderProvider table' -> queryBuilderProvider table' Source #

Case-insensitive version of filterWhereMatchesJoinedTable

Joins

innerJoin :: forall {k1} model' (table' :: Symbol) (name' :: Symbol) value' model (table :: Symbol) (name :: Symbol) value queryBuilderProvider (joinRegister :: k1). (KnownSymbol name, KnownSymbol table, HasField name model value, KnownSymbol name', KnownSymbol table', HasQueryBuilder queryBuilderProvider joinRegister, ModelList joinRegister, HasField name' model' value', value ~ value', model ~ GetModelByTableName table, table' ~ GetTableName model') => (Proxy name, Proxy name') -> queryBuilderProvider table -> JoinQueryBuilderWrapper (ConsModelList model' joinRegister) table Source #

Joins a table to an existing QueryBuilder (or something holding a QueryBuilder) on the specified columns. Example: > query Posts > |> innerJoin Users (#author, #id) > -- SELECT users.* FROM users INNER JOIN posts ON users.id = posts.author ...

innerJoinThirdTable :: forall {k1} model model' (name :: Symbol) (name' :: Symbol) value value' (table :: Symbol) (table' :: Symbol) (baseTable :: Symbol) baseModel queryBuilderProvider (joinRegister :: k1). (KnownSymbol name, KnownSymbol table, HasField name model value, KnownSymbol name', KnownSymbol table', HasQueryBuilder queryBuilderProvider joinRegister, ModelList joinRegister, HasField name' model' value', value ~ value', table ~ GetTableName model, table' ~ GetTableName model', baseModel ~ GetModelByTableName baseTable) => (Proxy name, Proxy name') -> queryBuilderProvider baseTable -> JoinQueryBuilderWrapper (ConsModelList model joinRegister) baseTable Source #

Joins a table on a column held by a previously joined table. Example: > query Posts > |> innerJoin Users (#author, #id) > |> innerJoinThirdTable City Users (#id, #homeTown) > -- SELECT posts.* FROM posts INNER JOIN users ON posts.author = users.id INNER JOIN cities ON user.home_town = cities.id

labelResults :: forall {k1} foreignModel baseModel (foreignTable :: Symbol) (baseTable :: Symbol) (name :: Symbol) value queryBuilderProvider (joinRegister :: k1). (KnownSymbol foreignTable, KnownSymbol baseTable, foreignTable ~ GetTableName foreignModel, baseModel ~ GetModelByTableName baseTable, HasField name foreignModel value, HasQueryBuilder queryBuilderProvider joinRegister, KnownSymbol name, IsJoined foreignModel joinRegister) => Proxy name -> queryBuilderProvider baseTable -> LabeledQueryBuilderWrapper foreignTable name value baseTable Source #

Index the values from a table with values of a field from a table joined by innerJoin or innerJoinThirdTable. Useful to get, e.g., the tags to a set of posts in such a way that the assignment of tags to posts is preserved.

Example: Fetch a list of all comments, each paired with the id of the post it belongs to.

labeledTags <-
 query @Tag
    |> innerJoin @Tagging (#id, #tagId)
    |> innerJoinThirdTable @Post @Tagging (#id, #postId)
    |> labelResults @Post #id
    |> fetch
-- SELECT posts.id, tags.* FROM comments INNER JOIN taggings ON tags.id = taggings.tagId INNER JOIN posts ON posts.id = taggings.postId

labeledTags is then a list of type [LabeledData (Id' "posts") Tag] such that "LabeledData postId tag" is contained in that list if "tag" is a tag of the post with id postId.

Ordering

orderBy :: forall {k} (table :: Symbol) (name :: Symbol) model value queryBuilderProvider (joinRegister :: k). (KnownSymbol table, KnownSymbol name, HasField name model value, model ~ GetModelByTableName table, HasQueryBuilder queryBuilderProvider joinRegister, Table model) => Proxy name -> queryBuilderProvider table -> queryBuilderProvider table Source #

Alias for orderByAsc

orderByAsc :: forall {k} (name :: Symbol) model (table :: Symbol) value queryBuilderProvider (joinRegister :: k). (KnownSymbol table, KnownSymbol name, HasField name model value, model ~ GetModelByTableName table, HasQueryBuilder queryBuilderProvider joinRegister, Table model) => Proxy name -> queryBuilderProvider table -> queryBuilderProvider table Source #

Adds an ORDER BY .. ASC to your query.

Use orderByDesc for descending order.

Example: Fetch the 10 oldest books.

query @Book
    |> orderBy #createdAt -- >     |> limit 10
    |> fetch
-- SELECT * FROM books LIMIT 10 ORDER BY created_at ASC

orderByDesc :: forall {k} (name :: Symbol) model (table :: Symbol) value queryBuilderProvider (joinRegister :: k). (KnownSymbol table, KnownSymbol name, HasField name model value, model ~ GetModelByTableName table, HasQueryBuilder queryBuilderProvider joinRegister, Table model) => Proxy name -> queryBuilderProvider table -> queryBuilderProvider table Source #

Adds an ORDER BY .. DESC to your query.

Use orderBy for ascending order.

Example: Fetch the 10 newest projects (ordered by creation time).

query @Project
    |> orderByDesc #createdAt
    |> limit 10
    |> fetch
-- SELECT * FROM projects LIMIT 10 ORDER BY created_at DESC

orderByJoinedTable :: forall {k1} model (name :: Symbol) (table :: Symbol) value queryBuilderProvider (joinRegister :: k1) (table' :: Symbol). (KnownSymbol table, KnownSymbol name, HasField name model value, table ~ GetTableName model, HasQueryBuilder queryBuilderProvider joinRegister, IsJoined model joinRegister, Table model) => Proxy name -> queryBuilderProvider table' -> queryBuilderProvider table' Source #

orderByAscJoinedTable :: forall {k1} model (name :: Symbol) (table :: Symbol) value queryBuilderProvider (joinRegister :: k1) (table' :: Symbol). (KnownSymbol table, KnownSymbol name, HasField name model value, table ~ GetTableName model, HasQueryBuilder queryBuilderProvider joinRegister, IsJoined model joinRegister, Table model) => Proxy name -> queryBuilderProvider table' -> queryBuilderProvider table' Source #

Adds an ORDER BY .. ASC on a joined table column to your query.

Use orderByDescJoinedTable for descending order.

Example: Order joined User records by username ascending.

query @Project
    |> innerJoin @User (#id, #projectId)
    |> orderByAscJoinedTable #username
    |> fetch
-- SELECT ... FROM projects
-- INNER JOIN users ON projects.id = users.project_id
-- ORDER BY users.username ASC

orderByDescJoinedTable :: forall {k1} model (name :: Symbol) (table :: Symbol) value queryBuilderProvider (joinRegister :: k1) (table' :: Symbol). (KnownSymbol table, KnownSymbol name, HasField name model value, table ~ GetTableName model, HasQueryBuilder queryBuilderProvider joinRegister, IsJoined model joinRegister, Table model) => Proxy name -> queryBuilderProvider table' -> queryBuilderProvider table' Source #

Adds an ORDER BY .. DESC on a joined table column to your query.

Use orderByAscJoinedTable for ascending order.

Example: Order joined User records by username descending.

query @Project
    |> innerJoin @User (#id, #projectId)
    |> orderByDescJoinedTable #username
    |> fetch
-- SELECT ... FROM projects
-- INNER JOIN users ON projects.id = users.project_id
-- ORDER BY users.username DESC

Pagination

limit :: forall {k} queryBuilderProvider (joinRegister :: k) (model :: Symbol). HasQueryBuilder queryBuilderProvider joinRegister => Int -> queryBuilderProvider model -> queryBuilderProvider model Source #

Adds an LIMIT .. to your query.

Example: Fetch 10 posts

query @Post
    |> limit 10
    |> fetch
-- SELECT * FROM posts LIMIT 10

offset :: forall {k} queryBuilderProvider (joinRegister :: k) (model :: Symbol). HasQueryBuilder queryBuilderProvider joinRegister => Int -> queryBuilderProvider model -> queryBuilderProvider model Source #

Adds an OFFSET .. to your query. Most often used together with LIMIT...

Example: Fetch posts 10-20

query @Post
    |> limit 10
    |> offset 10
    |> fetch
-- SELECT * FROM posts LIMIT 10 OFFSET 10

Deduplication

distinct :: forall {k} queryBuilderProvider (joinRegister :: k) (table :: Symbol). HasQueryBuilder queryBuilderProvider joinRegister => queryBuilderProvider table -> queryBuilderProvider table Source #

Adds a DISTINCT to your query.

Use distinct to remove all duplicate rows from the result

Example: Fetch distinct books

query @Book
    |> distinct
    |> fetch
-- SELECT DISTINCT * FROM books

distinctOn :: forall {k} (name :: Symbol) model value (table :: Symbol) queryBuilderProvider (joinRegister :: k). (KnownSymbol table, KnownSymbol name, HasField name model value, model ~ GetModelByTableName table, HasQueryBuilder queryBuilderProvider joinRegister, Table model) => Proxy name -> queryBuilderProvider table -> queryBuilderProvider table Source #

Adds an @DISTINCT ON .. to your query.

Use distinctOn to return a single row for each distinct value provided.

Example: Fetch one book for each categoryId field

query @Book
    |> distinctOn #categoryId
    |> fetch
-- SELECT DISTINCT ON (category_id) * FROM books

Unions

queryUnion :: forall {k1} {k2} queryBuilderProvider (joinRegister :: k1) r (joinRegister' :: k2) (model :: Symbol). (HasQueryBuilder queryBuilderProvider joinRegister, HasQueryBuilder r joinRegister') => queryBuilderProvider model -> r model -> NoJoinQueryBuilderWrapper model Source #

Merges the results of two query builders.

Take a look at queryOr as well, as this might be a bit shorter.

Example: Return all pages owned by the user or owned by the users team.

let userPages = query @Page |> filterWhere (#ownerId, currentUserId)
let teamPages = query @Page |> filterWhere (#teamId, currentTeamId)
pages <- queryUnion userPages teamPages |> fetch
-- (SELECT * FROM pages WHERE owner_id = '..') UNION (SELECT * FROM pages WHERE team_id = '..')

queryUnionList :: forall (table :: Symbol). (Table (GetModelByTableName table), KnownSymbol table, GetTableName (GetModelByTableName table) ~ table) => [QueryBuilder table] -> QueryBuilder table Source #

Like queryUnion, but applied on all the elements on the list

 action ProjectsAction = do
     let values :: [(ProjectType, Int)] = [(ProjectTypeOngoing, 3), (ProjectTypeNotStarted, 2)]

         valuePairToCondition :: (ProjectType, Int) -> QueryBuilder "projects"
         valuePairToCondition (projectType, participants) =
             query @Project
                 |> filterWhere (#projectType, projectType)
                 |> filterWhere (#participants, participants)

         theQuery = queryUnionList (map valuePairToCondition values)

     projects <- fetch theQuery
     render IndexView { .. }

queryOr :: forall {k1} {k2} {k3} queryBuilderProvider (joinRegister :: k1) queryBuilderProvider'' (joinRegister'' :: k2) queryBuilderProvider''' (joinRegister''' :: k3) (model :: Symbol). (HasQueryBuilder queryBuilderProvider joinRegister, HasQueryBuilder queryBuilderProvider'' joinRegister'', HasQueryBuilder queryBuilderProvider''' joinRegister''') => (queryBuilderProvider model -> queryBuilderProvider''' model) -> (queryBuilderProvider model -> queryBuilderProvider'' model) -> queryBuilderProvider model -> queryBuilderProvider model Source #

Adds an a OR b condition

Example: Return all pages owned by the user or public.

query @Page
    |> queryOr
        (filterWhere (#createdBy, currentUserId))
        (filterWhere (#public, True))
    |> fetch
-- SELECT * FROM pages WHERE created_by = '..' OR public = True

Operators

compileOperator :: FilterOperator -> Text Source #

Compiles a FilterOperator to its SQL representation

negateFilterOperator :: FilterOperator -> FilterOperator Source #

Returns the NOT version of an operator

>>> negateFilterOperator EqOp
NotEqOp