Module

Droplet.Language.Internal.Syntax

Package
purescript-droplet
Repository
easafe/purescript-droplet

This module defines the entire SQL eDSL, mostly because it'd be a pain to split it

Do not import this module directly, it will break your code and make it not type safe. Use the sanitized Droplet.Language instead

#Join Source

data Join :: Side -> Row Type -> Type -> Type -> RowList Symbol -> Type -> Typedata Join (k :: Side) (fields :: Row Type) q r (aliases :: SymbolList) rest

Constructors

Instances

#Inclusion Source

data Inclusion

Constructors

#Side Source

data Side

Kind for OUTER and INNER joins

#Inner Source

data Inner :: Sidedata Inner

Instances

#Create Source

newtype Create rest

Constructors

Instances

#Outer Source

data Outer :: Sidedata Outer

Instances

#On Source

data On c rest

Constructors

Instances

#Union Source

data Union q r

Constructors

Instances

#As Source

newtype As :: Symbol -> Type -> Typenewtype As (alias :: Symbol) rest

Constructors

Instances

#Delete Source

newtype Delete rest

Constructors

Instances

#From Source

data From :: Type -> Row Type -> Type -> Typedata From f (fields :: Row Type) rest

Constructors

Instances

#Insert Source

newtype Insert rest

Constructors

Instances

#OrderBy Source

data OrderBy f rest

Constructors

Instances

#Limit Source

data Limit :: Int -> Type -> Typedata Limit (n :: Int) rest

Constructors

Instances

#GroupBy Source

data GroupBy f rest

Constructors

Instances

#DefaultValues Source

data DefaultValues

Constructors

Instances

#Into Source

data Into :: Symbol -> Row Type -> Type -> Type -> Typedata Into (name :: Symbol) (fields :: Row Type) fieldNames rest

Constructors

  • Into fieldNames rest

Instances

#Plan Source

newtype Plan

Name of this prepared statement

Constructors

#Distinct Source

newtype Distinct s

Constructors

Instances

#Where Source

data Where c rest

Constructors

Instances

#Sort Source

data Sort (f :: Type)

Constructors

Instances

#Prepare Source

data Prepare q

Constructors

#Select Source

data Select :: Type -> Row Type -> Type -> Typedata Select s (projection :: Row Type) rest

SELECT representation. projection refers to the final output of this statement

Constructors

Instances

#Returning Source

newtype Returning f

Constructors

#T Source

newtype T (t :: Type) rest

Helper data type for extending TABLE syntax

Constructors

  • T rest

#Set Source

data Set pairs rest

Constructors

Instances

#Drop Source

newtype Drop rest

Constructors

Instances

#Alter Source

newtype Alter rest

Constructors

Instances

#Add Source

newtype Add :: Symbol -> Type -> Typenewtype Add (name :: Symbol) rest

Constructors

#Update Source

newtype Update :: Symbol -> Row Type -> Type -> Typenewtype Update (name :: Symbol) (fields :: Row Type) rest

Constructors

Instances

#Values Source

data Values fieldValues rest

Constructors

Instances

#Offset Source

data Offset rest

Constructors

Instances

#SymbolList Source

type SymbolList = RowList Symbol

A RowList of Symbols

#ToOffset Source

class ToOffset (q :: Type) 

Instances

#SingleTypeComposite Source

class SingleTypeComposite (constraints :: Type) 

Instances

#SortColumnsSource Source

class SortColumnsSource :: Type -> Row Type -> Type -> Row Type -> Row Type -> Constraintclass SortColumnsSource (s :: Type) (projection :: Row Type) (f :: Type) (columns :: Row Type) (available :: Row Type) | s -> available

Columns available for sorting this query

N.B: SELECT DISTINCT queries can only be sorted by columns in the projection

Instances

#ValidColumnNames Source

class ValidColumnNames :: RowList Type -> Constraintclass ValidColumnNames (columns :: RowList Type) 

Fails on repeated column names

Instances

#IncludeColumn Source

class IncludeColumn :: Symbol -> Type -> RowList Symbol -> RowList Type -> Constraintclass IncludeColumn (name :: Symbol) (t :: Type) (aliases :: SymbolList) (included :: RowList Type) | name -> included

Build a RowList of the given name and type qualified with each alias

Instances

#ColumnCannotBeSet Source

class ColumnCannotBeSet (t :: Type) 

Fields that cannot be inserted or updated

Instances

#MultipleInsert Source

class MultipleInsert (t :: Type) 

Instances

#SingleInsert Source

class SingleInsert (t :: Type) 

Instances

#OnlyAggregations Source

class OnlyAggregations :: Type -> Boolean -> Constraintclass OnlyAggregations (q :: Type) (is :: Boolean) | q -> is

Are all columns aggregated?

Instances

#ConsistentArity Source

class ConsistentArity (values :: Type) 

Makes sure single and multiple insert syntax is not mixed

Instances

#LimitedResults Source

class LimitedResults (q :: Type) 

Subqueries must return a single result

Instances

#ToAdd Source

class ToAdd (q :: Type) 

ALTER table ADD objects

Instances

#ColumnNames Source

class ColumnNames :: RowList Type -> RowList Symbol -> Constraintclass ColumnNames (columns :: RowList Type) (names :: SymbolList) | columns -> names

List of all column names in a table

Instances

#UnwrapAll Source

class UnwrapAll :: RowList Type -> Row Type -> Constraintclass UnwrapAll (list :: RowList Type) (projection :: Row Type) | list -> projection

Recursively remove source field wrappers

Instances

#UniqueColumnNames Source

class UniqueColumnNames :: Row Type -> Row Type -> Constraintclass UniqueColumnNames (some :: Row Type) (more :: Row Type) 

Query projections should not repeat column names

Instances

#UniqueTableColumnNames Source

#IsRequiredColumn Source

class IsRequiredColumn :: Type -> Boolean -> Constraintclass IsRequiredColumn (t :: Type) (required :: Boolean) | t -> required

Instances

#TableChecks Source

class TableChecks (t :: Type) 

Reused by CREATE and ALTER

Instances

#ColumHasType Source

class ColumHasType (column :: Type) 

Constraints must be paired with Column

Instances

#IncludeConstraint Source

class IncludeConstraint :: Symbol -> Type -> RowList Type -> Constraintclass IncludeConstraint (name :: Symbol) (constraints :: Type) (list :: RowList Type) | constraints -> list

Constraints that have to be checked across columns

Instances

#ToOrderBy Source

class ToOrderBy (f :: Type) (q :: Type) 

ORDER BY

Instances

#SortColumns Source

class SortColumns :: Type -> Row Type -> Constraintclass SortColumns (f :: Type) (columns :: Row Type) | f -> columns

Instances

#ConstraintsToRowList Source

class ConstraintsToRowList :: RowList Type -> RowList Type -> Constraintclass ConstraintsToRowList (source :: RowList Type) (constraints :: RowList Type) | source -> constraints

Flatten constraints into a list

Instances

#CheckComposite Source

class CheckComposite :: Symbol -> Symbol -> Type -> RowList Type -> Constraintclass CheckComposite (tableName :: Symbol) (name :: Symbol) (c :: Type) (rest :: RowList Type) 

Instances

#ValidComposites Source

class ValidComposites :: Symbol -> RowList Type -> Constraintclass ValidComposites (columnName :: Symbol) (constraints :: RowList Type) 

Check constraints across columns

Instances

#ValidConstraints Source

class ValidConstraints :: RowList Type -> Constraintclass ValidConstraints (columns :: RowList Type) 

Fail on invalid constraints

Instances

#ToLimit Source

class ToLimit (q :: Type) 

Instances

#Resume Source

class Resume a b c | a -> b, a b -> c where

Most SQL statement constructors accept a rest type parameter that refers to next statements

Such parameter is initially filled with E, meaning that the query ends there

This type class replaces the (nested) final E for the next statement

Members

Instances

#UniqueConstraints Source

class UniqueConstraints :: Symbol -> Type -> Constraintclass UniqueConstraints (name :: Symbol) (constraints :: Type) 

Constraints must be unique per column

Instances

#IsRepeated Source

class IsRepeated :: Symbol -> Type -> Type -> Constraintclass IsRepeated (name :: Symbol) (t :: Type) (constraints :: Type) 

If a constraint appears more than once in a column

Instances

#ToTable Source

class ToTable (q :: Type) (t :: Type) | q -> t

Acceptable table operations

Instances

#MatchingForeignKey Source

class MatchingForeignKey (t :: Type) (constraints :: Type) 

Foreign key name and type must match

Instances

#ValidNullableConstraints Source

class ValidNullableConstraints :: Symbol -> Type -> Type -> Constraintclass ValidNullableConstraints (name :: Symbol) (t :: Type) (constraints :: Type) 

Nullable constraints can only be unique or foreign key

Instances

#StarProjection Source

class StarProjection :: RowList Type -> Row Type -> RowList Symbol -> Row Type -> Constraintclass StarProjection (list :: RowList Type) (fields :: Row Type) (aliases :: SymbolList) (projection :: Row Type) | list -> projection

SELECT * FROM should:

  • Display column unqualified if it appear both as qualified and unqualified
  • Display column qualified if is projected with Path

Instances

#IsValidNullableConstraint Source

class IsValidNullableConstraint :: Symbol -> Type -> Constraintclass IsValidNullableConstraint (name :: Symbol) (constraints :: Type) 

Instances

#IsDefault Source

class IsDefault :: Type -> Symbol -> Constraintclass IsDefault (t :: Type) (name :: Symbol) | t -> name

Clearer error message in case of misplaced default value

Instances

#SymbolListSingleton Source

class SymbolListSingleton :: Symbol -> RowList Symbol -> Constraintclass SymbolListSingleton (alias :: Symbol) (list :: SymbolList) | alias -> list

Creates a SymbolList single with a single entry

Instances

#SourceAlias Source

class SourceAlias :: Type -> Symbol -> Constraintclass SourceAlias (f :: Type) (alias :: Symbol) | f -> alias

Table/subquery alias or Empty

Instances

#MissingRequiredColumns Source

class MissingRequiredColumns :: Row Type -> Row Type -> Constraintclass MissingRequiredColumns (required :: Row Type) (inserted :: Row Type) 

Slightly clearer type errors for missing columns

Instances

#ToPath Source

class ToPath :: Symbol -> Symbol -> Constraintclass ToPath (alias :: Symbol) (path :: Symbol) | alias -> path

Optionally add source field alias

Instances

#QueryMustBeAliased Source

class QueryMustBeAliased :: Type -> Symbol -> Constraintclass QueryMustBeAliased (q :: Type) (alias :: Symbol) | q -> alias

Find this query's alias, or fail at compile time if query is not aliased

Instances

#UniqueSources Source

class UniqueSources :: Row Type -> Row Type -> Constraintclass UniqueSources (some :: Row Type) (more :: Row Type) 

Joined tables should not be the same

Instances

#OuterScopeAlias Source

class OuterScopeAlias :: RowList Symbol -> RowList Symbol -> Boolean -> Constraintclass OuterScopeAlias (all :: SymbolList) (unique :: SymbolList) (y :: Boolean) | all unique -> y

Is this column present in the current field source?

Instances

#OnCondition Source

class OnCondition :: Type -> Row Type -> RowList Symbol -> Constraintclass OnCondition (c :: Type) (fields :: Row Type) (aliases :: SymbolList) 

Comparison logic for ON statements

Instances

#QueryOptionallyAliased Source

class QueryOptionallyAliased :: Type -> Symbol -> Symbol -> Constraintclass QueryOptionallyAliased (q :: Type) (name :: Symbol) (alias :: Symbol) | q -> name alias

If this query is in the form of (SELECT ...) AS alias, return alias, otherwise keep name

Instances

#ToJoin Source

class ToJoin :: Type -> Row Type -> RowList Symbol -> Constraintclass ToJoin (q :: Type) (fields :: Row Type) (aliases :: SymbolList) | q -> fields aliases

Given a source q, compute its joined (non and qualified) fields

Instances

#QualifiedColumn Source

class QualifiedColumn :: Boolean -> Symbol -> Row Type -> Type -> Constraintclass QualifiedColumn (unscoped :: Boolean) (fullPath :: Symbol) (fields :: Row Type) (t :: Type) | unscoped -> fullPath fields t

The type of a qualified column

Instances

#OnComparision Source

class OnComparision :: Type -> Row Type -> RowList Symbol -> Type -> Constraintclass OnComparision (a :: Type) (fields :: Row Type) (aliases :: SymbolList) (t :: Type) | a -> t

Instances

#ValidGroupByProjection Source

class ValidGroupByProjection :: Type -> Row Type -> Constraintclass ValidGroupByProjection (s :: Type) (grouped :: Row Type) | s -> grouped

Asserts that a SELECT ... GROUP BY projection contains only grouped columns or aggregate functions

Instances

#GroupedColumns Source

class GroupedColumns :: Type -> Row Type -> Row Type -> Constraintclass GroupedColumns (f :: Type) (columns :: Row Type) (grouped :: Row Type) | f -> columns grouped

Instances

#ToGroupBy Source

class ToGroupBy :: Type -> Type -> Row Type -> Constraintclass ToGroupBy (q :: Type) (s :: Type) (columns :: Row Type) | q -> s columns

GROUP BY can only follow FROM or WHERE

Instances

#ToOuterColumns Source

class ToOuterColumns :: RowList Type -> Row Type -> Constraintclass ToOuterColumns (list :: RowList Type) (fields :: Row Type) | list -> fields

OUTER JOINs make one side nullable, as a corresponding record may not be found

For ease of use, this class marks the nullable side fields with Joined, later on ToProjection will flatten it to Maybe

Instances

#ToWhere Source

class ToWhere (c :: Type) (q :: Type) 

WHERE can only follow FROM, UPDATE and DELETE

Instances

#JoinedToMaybe Source

class JoinedToMaybe (t :: Type) (v :: Type) | t -> v

Joined fields appear as Maybe in projections

Instances

#CompatibleProjection Source

class CompatibleProjection :: RowList Type -> RowList Type -> Constraintclass CompatibleProjection (pro :: RowList Type) (jection :: RowList Type) 

Instances

#ToUnion Source

class ToUnion (q :: Type) (r :: Type) 

Instances

#RequiredColumns Source

class RequiredColumns :: RowList Type -> Row Type -> Constraintclass RequiredColumns (fieldList :: RowList Type) (required :: Row Type) | fieldList -> required

Compute list of required fields

Instances

#ToAs Source

class ToAs :: Type -> Symbol -> Constraintclass ToAs (q :: Type) (alias :: Symbol) | q -> alias

Acceptable alias targets

Instances

#ToFrom Source

class ToFrom :: Type -> Type -> Row Type -> Constraintclass ToFrom (f :: Type) (q :: Type) (fields :: Row Type) | q f -> fields

Acceptable sources for FROM statements

Instances

#GroupBySource Source

class GroupBySource :: Type -> Row Type -> Constraintclass GroupBySource (f :: Type) (columns :: Row Type) | f -> columns

Instances

#InsertList Source

class InsertList :: Row Type -> Type -> Row Type -> Constraintclass InsertList (fields :: Row Type) (fieldNames :: Type) (inserted :: Row Type) | fieldNames -> fields inserted

Compute list of inserted fields

Instances

#InsertValues Source

class InsertValues :: Row Type -> Type -> Type -> Constraintclass InsertValues (fields :: Row Type) (names :: Type) (t :: Type) 

Instances

#ToPrepare Source

class ToPrepare (q :: Type) 

Only complete statements are accepted by PREPARE

Instances

#ToProjection Source

class ToProjection :: Type -> Row Type -> RowList Symbol -> Row Type -> Constraintclass ToProjection (s :: Type) (fields :: Row Type) (aliases :: SymbolList) (projection :: Row Type) | s -> fields projection

Computes SELECT projection as a Row Type

Instances

#ToSelect Source

class ToSelect (s :: Type) 

Acceptable column types for SELECT statements

Instances

#ToSingleColumn Source

class ToSingleColumn :: RowList Type -> Symbol -> Type -> Constraintclass ToSingleColumn (fields :: RowList Type) (name :: Symbol) (t :: Type) | fields -> name t

Instances

#ToSubExpression Source

class ToSubExpression (f :: Type) 

Only single columns can be projected by subqueries

Instances

#IncludeAllColumns Source

class IncludeAllColumns :: RowList Type -> RowList Symbol -> RowList Type -> Constraintclass IncludeAllColumns (list :: RowList Type) (aliases :: SymbolList) (all :: RowList Type) | list -> all

Recursively call IncludeColumn on the given list

Instances

#SourceColumns Source

class SourceColumns :: Type -> Row Type -> RowList Symbol -> Constraintclass SourceColumns (f :: Type) (fields :: Row Type) (aliases :: SymbolList) | f -> fields aliases

Given a source f, compute its (non and qualified) fields

Instances

#ToUpdatePairs Source

class ToUpdatePairs :: Row Type -> Type -> Constraintclass ToUpdatePairs (fields :: Row Type) (pairs :: Type) 

Instances

#ToReturning Source

class ToReturning (f :: Type) (q :: Type) | q -> f

Instances

#ReturningColumns Source

class ReturningColumns :: Type -> Row Type -> Constraintclass ReturningColumns (f :: Type) (fields :: Row Type) | f -> fields

Instances

#UniqueAliases Source

class UniqueAliases :: RowList Symbol -> RowList Symbol -> Constraintclass UniqueAliases (some :: SymbolList) (more :: SymbolList) 

Joined tables should not repeat table aliases

Instances

#QualifiedColumns Source

class QualifiedColumns :: RowList Type -> Symbol -> Row Type -> Constraintclass QualifiedColumns (list :: RowList Type) (alias :: Symbol) (fields :: Row Type) | list alias -> fields

Computes all source fields with their alias

Instances

#join Source

join :: forall r l aliases unique las ras right rf lf left all source fields. ToJoin l left las => ToJoin r right ras => UniqueSources left right => RowListAppend las ras aliases => RowListNub aliases unique => UniqueAliases aliases unique => Union right left all => Nub all source => Union left lf source => Union right rf source => Union lf rf fields => l -> r -> Join Inner fields l r aliases E

INNER JOIN statement

JOIN sources are the same as FROM

#create Source

create :: Create E

CREATE ...

#table Source

table :: forall name q fields sql. ToTable q (Table name fields) => Resume q (Table name fields) sql => Table name fields -> q -> sql

Table up for modification

#leftJoin Source

leftJoin :: forall r l las ras list out aliases unique rf lf right left all fields source. ToJoin l left las => ToJoin r right ras => UniqueSources left right => RowListAppend las ras aliases => RowListNub aliases unique => UniqueAliases aliases unique => Union left right all => Nub all source => Union left lf source => Union right rf source => RowToList lf list => ToOuterColumns list out => Union rf out fields => l -> r -> Join Outer fields l r aliases E

LEFT OUTER JOIN statement

JOIN sources are the same as FROM

#exists Source

exists :: forall s projection f fields rest. Select s projection (From f fields rest) -> Op Exists (Select s projection (From f fields rest))

#on Source

on :: forall k l r c fields aliases. OnCondition c fields aliases => c -> Join k fields l r aliases E -> Join k fields l r aliases (On c E)

JOIN ... ON statement

#union Source

union :: forall q r. ToUnion q r => q -> r -> Union q r

#groupBy Source

groupBy :: forall f s q sql grouped columns. ToGroupBy q s columns => GroupedColumns f columns grouped => ValidGroupByProjection s grouped => Resume q (GroupBy f E) sql => f -> q -> sql

GROUP BY statement

#drop Source

drop :: Drop E

DROP ...

#unionAll Source

unionAll :: forall q r. ToUnion q r => q -> r -> Union q r

#distinct Source

distinct :: forall s. ToSelect s => s -> Distinct s

#orderBy Source

orderBy :: forall f q sql. ToOrderBy f q => Resume q (OrderBy f E) sql => f -> q -> sql

ORDER BY statement

#offset Source

offset :: forall q sql. ToOffset q => Resume q (Offset E) sql => Int -> q -> sql

OFFSET statement

Note: OFFSET must always follow after LIMIT or ORDER BY

#as Source

as :: forall q alias sql. ToAs q alias => Resume q (As alias E) sql => Proxy alias -> q -> sql

AS statement

#add Source

add :: forall q name object columns extended. ToAdd q => Cons object q columns extended => TableChecks (Table name extended) => Proxy object -> q -> Alter (Table name columns) -> Alter (T (Table name columns) (Add object q))

#asc Source

asc :: forall name. name -> Sort name

ASC

#desc Source

desc :: forall name. name -> Sort name

DESC

#from Source

from :: forall f q fields sql. ToFrom f q fields => Resume q (From f fields E) sql => f -> q -> sql

FROM accepts the following sources

  • Tables
  • Inner and outer joins
  • Aliased tables
  • Aliased SELECT statements

Due to how SQL binding works, joins and subqueries require brackets to be parsed correctly. For example:

  • SELECT column FROM (SELECT column FROM table) AS alias should be select column # from (select column # from table # as alias))
  • SELECT column FROM table alias JOIN other_table other_alias should be select column # from ((table # as alias)join(other_table # as other_alias)))

To aid composition, SELECT projections are only validated on FROM

#limit Source

limit :: forall n q sql. ToLimit q => Resume q (Limit n E) sql => Proxy n -> q -> sql

LIMIT statement

Note: LIMIT must always follow after ORDER BY

#into Source

into :: forall tableName fields fieldNames fieldList required inserted. RowToList fields fieldList => RequiredColumns fieldList required => InsertList fields fieldNames inserted => MissingRequiredColumns required inserted => Table tableName fields -> fieldNames -> Insert E -> Insert (Into tableName fields fieldNames E)

#prepare Source

prepare :: forall q. ToPrepare q => Plan -> q -> Prepare q

https://www.postgresql.org/docs/current/sql-prepare.html

PREPARE statements can be employed to reuse execution plans, and thus optimize performance

Note: droplet always creates server-side parameters for literal values in queries. In the case of PREPARE, however, literals will be parsed as statement parameters

#select Source

select :: forall s projection. ToSelect s => s -> Select s projection E

SELECT can project literals, columns and subqueries with the following considerations:

  • Multiple columns are represented by tuples. Data.Tuple.Nested./\ is convenient for this
  • Literal values (e.g., numbers) must be aliased (with AS)
  • Columns names in projections must be unique, or referenced by different table aliases (e.g., u.name, t.name)
  • Subqueries must return a single column

#set Source

set :: forall name fields pairs. ToUpdatePairs fields pairs => pairs -> Update name fields E -> Update name fields (Set pairs E)

#update Source

update :: forall name fields. Table name fields -> Update name fields E

#values Source

values :: forall tableName fields names fieldValues. ConsistentArity fieldValues => InsertValues fields names fieldValues => fieldValues -> Insert (Into tableName fields names E) -> Insert (Into tableName fields names (Values fieldValues E))

#returning Source

returning :: forall f q sql. ToReturning f q => Resume q (Returning f) sql => f -> q -> sql

#wher Source

wher :: forall c q sql. ToWhere c q => Resume q (Where c E) sql => c -> q -> sql

WHERE statement