| Copyright | (c) Dmitry Olshansky |
|---|---|
| License | BSD-3-Clause |
| Maintainer | olshanskydr@gmail.com, dima@typeable.io |
| Stability | experimental |
| Safe Haskell | None |
| Language | GHC2021 |
PgSchema.DML
Description
A module to generate and safely execute SQL statements.
Among pg-schema’s library modules, this is the one meant for ordinary application
imports for database access (alongside your generated schema module).
TLDR; Example:
data Order = Order { num :: Text, createdAt :: Day, items :: [OrdPos] } deriving Generic
data OrdPos = OrdPos { id :: Int32, num :: Int32, article :: Article, price :: Double } deriving Generic
data Article = Article { id :: Int32, name :: Text } deriving Generic
type MyAnn tabName = 'Ann 5 CamelToSnake MySch ("dbSchema" ->> tabName)
...
do
void $ insertJSON_ (MyAnn "orders") conn
[ "num" =: "num1" :. "ord__ord_pos" =:
[ "num" =: 1 :. "articleId" =: 42 :. "price" =: 10
, "num" =: 2 :. "articleId" =: 41 :. "price" =: 15 ] ]
(xs :: [Order]) <- selectSch (MyAnn "orders") conn $ qRoot do
qWhere $ "created_at" >? someDay
&&& pchild "ord__ord_pos" defTabParam
(pparent "ord_pos__article" $ "name" ~~? "%pencil%")
qOrderBy [descf "created_at", descf "num"]
qPath "ord__ord_pos" do
qWhere $ pparent "ord_pos__article" $ "name" ~~? "%pencil%"
qOrderBy [ascf "num"]
qLimit 20
Here we get all orders created after someDay that have positions with articles like "%pencil%",
and return only those order items that relate to "pencil", with article info.
The preceding insertJSON_ call inserts one root row (here an order) and nested
child rows (here order positions) in a single database operation, again using
JSON internally. Child data is carried in list fields: the field’s name (after Renamer) names
the FK constraint in the database and thus selects the child table and link;
each list element supplies one child row’s columns, with nested lists for further
children in the same way. For strict inserts,
insertJSON and insertJSON_ require every mandatory column at each node;
upsertJSON / upsertJSON_ relax that so each row can be resolved by keys and
optional columns (see their Haddock). Plain insertSch / insertSch_ follow the
same safety story for flat (non-tree) rows.
selectSch decodes each row into a Haskell type r whose fields describe the
root table columns and nested data for relations (multiple list-shaped children
and nested parents/Maybe as appropriate). The type drives the generated SQL
shape; monadic QueryParam only adds what this call needs—filters, ordering on a
branch, limits, and so on.
We can use both Generic-based and PgTag-based ((=:)) interfaces and mix them in any way.
All string literals at the type level are Symbol thanks to RequiredTypeArguments.
Operations are safe when the live database schema matches the generated schema types.
The INSERT and SELECT shown here each run as a single, fast database round-trip (JSON inside PostgreSQL).
We use a Renamer (e.g. CamelToSnake) to map Haskell field names to snake_case in the database.
In conditions and QueryParams, column names are the original database names.
It can be changed in the future.
Synopsis
- selectSch :: forall (ren :: Renamer) sch (d :: Nat) (tab :: NameNSK). forall (ann :: Ann) -> forall r. (Selectable ann r, ann ~ 'Ann ren sch d tab) => Connection -> QueryParam sch tab -> IO ([r], (Text, [SomeToField]))
- selectText :: forall (ren :: Renamer) sch (d :: Nat) (tab :: NameNSK). forall (ann :: Ann) -> forall r. (CRecInfo ann r, ann ~ 'Ann ren sch d tab) => QueryParam sch tab -> (Text, [SomeToField])
- type Selectable (ann :: Ann) r = (CRecInfo ann r, FromRow (PgTag ann r))
- type MonadQP sch (t :: NameNSK) (path :: [Symbol]) = (TabPath sch t path, ToStar path) => RWS (Proxy path) () (QueryParam sch t) ()
- qpEmpty :: forall sch (t :: NameNSK). QueryParam sch t
- qRoot :: forall {a} sch (t :: NameNSK). RWS (Proxy ('[] :: [a])) () (QueryParam sch t) () -> QueryParam sch t
- qPath :: forall sch (t :: NameNSK) (path :: [Symbol]) (path' :: [Symbol]). forall (p :: Symbol) -> (TabPath sch t path', ToStar path', path' ~ (path ++ '[p])) => MonadQP sch t path' -> MonadQP sch t path
- qWhere :: forall sch (t :: NameNSK) (path :: [Symbol]). Cond sch (TabOnPath sch t path) -> MonadQP sch t path
- qOrderBy :: forall sch (t :: NameNSK) (path :: [Symbol]). [OrdFld sch (TabOnPath sch t path)] -> MonadQP sch t path
- qDistinct :: forall sch (t :: NameNSK) (path :: [Symbol]) (t' :: NameNSK). TabOnPath2 sch t path ~ '(t', 'RelMany) => MonadQP sch t path
- qDistinctOn :: forall sch (t :: NameNSK) (path :: [Symbol]). [OrdFld sch (TabOnPath sch t path)] -> MonadQP sch t path
- qLimit :: forall sch (t :: NameNSK) (path :: [Symbol]). Snd (TabOnPath2 sch t path) ~ 'RelMany => Natural -> MonadQP sch t path
- qOffset :: forall sch (t :: NameNSK) (path :: [Symbol]). Snd (TabOnPath2 sch t path) ~ 'RelMany => Natural -> MonadQP sch t path
- data QueryParam sch (t :: NameNSK) = QueryParam {
- qpConds :: ![CondWithPath sch t]
- qpOrds :: ![OrdWithPath sch t]
- qpLOs :: ![LimOffWithPath sch t]
- qpDistinct :: ![DistWithPath sch t]
- data CondWithPath sch (t :: NameNSK) where
- CondWithPath :: forall (path :: [Symbol]) sch (t :: NameNSK). ToStar path => Cond sch (TabOnPath sch t path) -> CondWithPath sch t
- data OrdWithPath (sch :: k) (t :: NameNSK) where
- OrdWithPath :: forall {k} (path :: [Symbol]) (sch :: k) (t :: NameNSK). ToStar path => [OrdFld sch (TabOnPath sch t path)] -> OrdWithPath sch t
- data LimOffWithPath (sch :: k) (t :: NameNSK) where
- LimOffWithPath :: forall {k} (path :: [Symbol]) (sch :: k) (t :: NameNSK). (TabPath sch t path, ToStar path, Snd (TabOnPath2 sch t path) ~ 'RelMany) => LO -> LimOffWithPath sch t
- data DistWithPath (sch :: k) (t :: NameNSK) where
- DistWithPath :: forall {k} (path :: [Symbol]) (sch :: k) (t :: NameNSK). ToStar path => Dist sch (TabOnPath sch t path) -> DistWithPath sch t
- (<?) :: forall (fld :: Symbol) -> forall sch (tab :: NameNSK) (fd :: FldDef' Symbol) v. CDBValue sch tab fld fd v => v -> Cond sch tab
- (>?) :: forall (fld :: Symbol) -> forall sch (tab :: NameNSK) (fd :: FldDef' Symbol) v. CDBValue sch tab fld fd v => v -> Cond sch tab
- (<=?) :: forall (fld :: Symbol) -> forall sch (tab :: NameNSK) (fd :: FldDef' Symbol) v. CDBValue sch tab fld fd v => v -> Cond sch tab
- (>=?) :: forall (fld :: Symbol) -> forall sch (tab :: NameNSK) (fd :: FldDef' Symbol) v. CDBValue sch tab fld fd v => v -> Cond sch tab
- (=?) :: forall (fld :: Symbol) -> forall sch (tab :: NameNSK) (fd :: FldDef' Symbol) v. CDBValue sch tab fld fd v => v -> Cond sch tab
- (~=?) :: forall (fld :: Symbol) -> forall sch (tab :: NameNSK) (fd :: FldDef' Symbol) v. CDBValue sch tab fld fd v => v -> Cond sch tab
- (~~?) :: forall (fld :: Symbol) -> forall sch (tab :: NameNSK) (fd :: FldDef' Symbol) v. CDBValue sch tab fld fd v => v -> Cond sch tab
- (|||) :: forall sch (tab :: NameNSK). Cond sch tab -> Cond sch tab -> Cond sch tab
- (&&&) :: forall sch (tab :: NameNSK). Cond sch tab -> Cond sch tab -> Cond sch tab
- pnot :: forall sch (tab :: NameNSK). Cond sch tab -> Cond sch tab
- pnull :: forall sch (tab :: NameNSK) (fd :: FldDef' Symbol). forall (name :: Symbol) -> CDBFieldNullable sch tab name fd => Cond sch tab
- pin :: forall (name :: Symbol) -> forall sch (tab :: NameNSK) (fd :: FldDef' Symbol) v. CDBValue sch tab name fd v => NonEmpty v -> Cond sch tab
- pinArr :: forall (name :: Symbol) -> forall sch (tab :: NameNSK) (fd :: FldDef' Symbol) v. CDBValue sch tab name fd v => [v] -> Cond sch tab
- pparent :: forall (ref :: NameNSK) -> CRelDef sch ref => Cond sch (RdTo (TRelDef sch ref)) -> Cond sch (RdFrom (TRelDef sch ref))
- pchild :: forall (ref :: NameNSK) -> CRelDef sch ref => TabParam sch (RdFrom (TRelDef sch ref)) -> Cond sch (RdFrom (TRelDef sch ref)) -> Cond sch (RdTo (TRelDef sch ref))
- data TabParam sch (tab :: NameNSK) = TabParam {}
- defTabParam :: forall sch (tab :: NameNSK). TabParam sch tab
- pUnsafeCond :: forall sch (tab :: NameNSK). CondMonad Text -> Cond sch tab
- data Cond sch (tab :: NameNSK) where
- EmptyCond :: forall sch (tab :: NameNSK). Cond sch tab
- Cmp :: forall (fld :: Symbol) v sch (tab :: NameNSK) (fd :: FldDef' Symbol). CDBValue sch tab fld fd v => Cmp -> v -> Cond sch tab
- In :: forall (fld :: Symbol) v sch (tab :: NameNSK) (fd :: FldDef' Symbol). CDBValue sch tab fld fd v => NonEmpty v -> Cond sch tab
- InArr :: forall (fld :: Symbol) v sch (tab :: NameNSK) (fd :: FldDef' Symbol). CDBValue sch tab fld fd v => [v] -> Cond sch tab
- Null :: forall (fld :: Symbol) sch (tab :: NameNSK) (fd :: FldDef' Symbol). CDBFieldNullable sch tab fld fd => Cond sch tab
- Not :: forall sch (tab :: NameNSK). Cond sch tab -> Cond sch tab
- BoolOp :: forall sch (tab :: NameNSK). BoolOp -> Cond sch tab -> Cond sch tab -> Cond sch tab
- Child :: forall sch (ref :: NameNSK). CRelDef sch ref => TabParam sch (RdFrom (TRelDef sch ref)) -> Cond sch (RdFrom (TRelDef sch ref)) -> Cond sch (RdTo (TRelDef sch ref))
- Parent :: forall sch (ref :: NameNSK). CRelDef sch ref => Cond sch (RdTo (TRelDef sch ref)) -> Cond sch (RdFrom (TRelDef sch ref))
- UnsafeCond :: forall sch (tab :: NameNSK). CondMonad Text -> Cond sch tab
- data Cmp
- data BoolOp
- type CondMonad = RWS (Text, NonEmpty Int) [SomeToField] Int
- data SomeToField where
- SomeToField :: forall a. (ToField a, Show a) => a -> SomeToField
- showCmp :: IsString s => Cmp -> s
- tabPref :: CondMonad Text
- qual :: forall (fld :: Symbol). ToStar fld => CondMonad Text
- type CDBField (sch :: k) (tab :: NameNSK) (fld :: Symbol) (fd :: FldDef' Symbol) = (CDBFieldInfo sch tab fld, TDBFieldInfo sch tab fld ~ ('RFPlain fd :: RecField' Symbol NameNSK))
- type CDBValue sch (tab :: NameNSK) (fld :: Symbol) (fd :: FldDef' Symbol) v = (CDBField sch tab fld fd, ToField v, Show v, CanConvert sch tab fld fd v)
- type CDBFieldNullable (sch :: k) (tab :: NameNSK) (fld :: Symbol) (fd :: FldDef' Symbol) = (CDBField sch tab fld fd, FdNullable fd ~ 'True)
- class (ToStar (TRelDef sch ref), CTabDef sch (RdFrom (TRelDef sch ref)), CTabDef sch (RdTo (TRelDef sch ref))) => CRelDef (sch :: k) (ref :: NameNSK)
- ordf :: forall (fld :: Symbol) -> forall (sch :: k) (tab :: NameNSK) (fd :: FldDef' Symbol). CDBField sch tab fld fd => OrdDirection -> OrdFld sch tab
- ascf :: forall (fld :: Symbol) -> forall (sch :: k) (tab :: NameNSK) (fd :: FldDef' Symbol). CDBField sch tab fld fd => OrdFld sch tab
- descf :: forall (fld :: Symbol) -> forall (sch :: k) (tab :: NameNSK) (fd :: FldDef' Symbol). CDBField sch tab fld fd => OrdFld sch tab
- defLO :: LO
- lo1 :: LO
- data OrdDirection
- data OrdFld (sch :: k) (tab :: NameNSK) where
- data Dist (sch :: k) (tab :: NameNSK) where
- data LO = LO {}
- insertSch :: forall (ann :: Ann) -> forall r r'. InsertReturning ann r r' => Connection -> [r] -> IO ([r'], Text)
- insertSch_ :: forall (ann :: Ann) -> forall r. InsertNonReturning ann r => Connection -> [r] -> IO (Int64, Text)
- insertText :: forall (ann :: Ann) -> forall r r' s. (CRecInfo ann r, CRecInfo ann r', IsString s, Monoid s) => s
- insertText_ :: forall (ann :: Ann) -> forall r s. (IsString s, Monoid s, CRecInfo ann r) => s
- type family AllPlain (ann :: Ann) r where ...
- type InsertNonReturning (ann :: Ann) r = (PlainIn ann r, CheckAllMandatory ann (ColsDbNames (Cols ann r)))
- type InsertReturning (ann :: Ann) r r' = (InsertNonReturning ann r, PlainOut ann r')
- updateByCond :: forall (ren :: Renamer) sch (d :: Nat) (t :: NameNSK). forall (ann :: Ann) -> forall r r'. (ann ~ 'Ann ren sch d t, UpdateReturning ann r r') => Connection -> r -> Cond sch t -> IO [r']
- updateByCond_ :: forall (ren :: Renamer) sch (d :: Nat) (t :: NameNSK). forall (ann :: Ann) -> forall r. (ann ~ 'Ann ren sch d t, UpdateNonReturning ann r) => Connection -> r -> Cond sch t -> IO Int64
- updateText :: forall (ren :: Renamer) sch (d :: Nat) (t :: NameNSK). forall (ann :: Ann) -> forall r r' s. (CRecInfo ann r, CRecInfo ann r', IsString s, Monoid s, ann ~ 'Ann ren sch d t) => Cond sch t -> (s, [SomeToField])
- updateText_ :: forall sch (t :: NameNSK). forall (ann :: Ann) -> forall r s. (IsString s, Monoid s, CRecInfo ann r) => Cond sch t -> (s, [SomeToField])
- type UpdateReturning (ann :: Ann) r r' = (UpdateNonReturning ann r, PlainOut ann r')
- type UpdateNonReturning (ann :: Ann) r = PlainIn ann r
- class CRecInfo (ann :: Ann) r where
- getRecordInfo :: RecordInfo Text
- insertJSON :: forall (ann :: Ann) -> forall r r'. InsertTreeReturning ann r r' => Connection -> [r] -> IO ([r'], Text)
- insertJSON_ :: forall (ann :: Ann) -> forall r. InsertTreeNonReturning ann r => Connection -> [r] -> IO Text
- upsertJSON :: forall (ann :: Ann) -> forall r r'. UpsertTreeReturning ann r r' => Connection -> [r] -> IO ([r'], Text)
- upsertJSON_ :: forall (ann :: Ann) -> forall r. UpsertTreeNonReturning ann r => Connection -> [r] -> IO Text
- insertJSONText :: forall (ann :: Ann) -> forall r r'. (TreeSch ann, CRecInfo ann r, CRecInfo ann r', IsString s, Monoid s, Ord s) => s
- insertJSONText_ :: forall (ann :: Ann) -> forall r s. (IsString s, Monoid s, Ord s, TreeSch ann, CRecInfo ann r) => s
- type TreeIn (ann :: Ann) r = (CRecInfo ann r, ToJSON (PgTag ann r))
- type TreeOut (ann :: Ann) r' = (CRecInfo ann r', FromJSON (PgTag ann r'), Typeable ann, Typeable r')
- type family AllMandatoryTree (ann :: Ann) r (rFlds :: [Symbol]) where ...
- type family AllMandatoryOrHasPKTree (ann :: Ann) r (rFlds :: [Symbol]) where ...
- type TreeSch (ann :: Ann) = CSchema (AnnSch ann)
- type InsertTreeNonReturning (ann :: Ann) r = (TreeSch ann, TreeIn ann r, AllMandatoryTree ann r ('[] :: [Symbol]))
- type InsertTreeReturning (ann :: Ann) r r' = (InsertTreeNonReturning ann r, TreeOut ann r', ReturningIsSubtree ann r r')
- type UpsertTreeNonReturning (ann :: Ann) r = (TreeSch ann, TreeIn ann r, AllMandatoryOrHasPKTree ann r ('[] :: [Symbol]))
- type UpsertTreeReturning (ann :: Ann) r r' = (UpsertTreeNonReturning ann r, TreeOut ann r', ReturningIsSubtree ann r r')
- type family TRecordInfo (ann :: Ann) r :: [FieldInfo Symbol] where ...
- deleteByCond :: forall sch (t :: NameNSK) -> SingI t => Connection -> Cond sch t -> IO (Int64, (Text, [SomeToField]))
- deleteText :: forall sch (t :: NameNSK) s. (IsString s, Monoid s, SingI t) => Cond sch t -> (s, [SomeToField])
- data Ann = Ann {}
- type ToStar (a :: k) = (SingKind (KindOf a), SingI a)
- data RenamerId (a :: TyFun Symbol Symbol)
- type CamelToSnake (s :: Symbol) = CamelToSnakeInternal (UnconsSymbol s)
- type Renamer = Symbol ~> Symbol
- type family ApplyRenamer (renamer :: Renamer) (s :: Symbol) :: Symbol
- type (:=) (s :: k) t = PgTag s t
- (=:) :: forall (a :: k) -> b -> a := b
- newtype PgTag (s :: k) t = PgTag {
- unPgTag :: t
- data h :. t = h :. t
- data family PGEnum sch (name :: NameNSK)
- newtype Aggr' (f :: AggrFun) t = Aggr' {
- unAggr' :: t
- newtype Aggr (f :: AggrFun) t = Aggr {
- unAggr :: t
- data AggrFun
- newtype PgArr a = PgArr {}
- pgArr' :: [a] -> PgArr a
- unPgArr' :: PgArr a -> [a]
- type family CanConvert sch (tab :: NameNSK) (fld :: Symbol) (fd :: FldDefK) t where ...
- type family CanConvert1 sch (tab :: NameNSK) (fld :: Symbol) (tn :: NameNSK) (td :: TypDefK) t
- data TypDef' s = TypDef {
- typCategory :: s
- typElem :: Maybe (NameNS' s)
- typEnum :: [s]
- newtype PgChar = PgChar {}
- newtype PgOid = PgOid {}
- data NameNS' s = NameNS {
- nnsNamespace :: s
- nnsName :: s
- type (->>) (ns :: s) (name :: s) = 'NameNS ns name
- type NameNSK = NameNS' Symbol
- (->>) :: Text -> Text -> NameNS
- type family TRelDef (sch :: k) (ref :: NameNSK) :: RelDefK
- data RelDef' s = RelDef {}
- type family RdFrom (a :: RelDef' s) :: NameNS' s where ...
- type family RdTo (a :: RelDef' s) :: NameNS' s where ...
- type family FdType (a :: FldDef' s) :: NameNS' s where ...
- type family FdNullable (a :: FldDef' s) :: Bool where ...
- class (ToStar name, ToStar (TTabDef sch name)) => CTabDef (sch :: k) (name :: NameNSK) where
DML
Select
Execute SQL
selectSch :: forall (ren :: Renamer) sch (d :: Nat) (tab :: NameNSK). forall (ann :: Ann) -> forall r. (Selectable ann r, ann ~ 'Ann ren sch d tab) => Connection -> QueryParam sch tab -> IO ([r], (Text, [SomeToField])) Source #
Run a single SELECT for root table tab (see annotation ann with schema
sch and Renamer ren) and decode rows into [r], also returning the SQL
text and bind parameters (for tracing or debugging).
The desired result type r fixes the shape of each row: typically a record
with columns of the root table and nested Haskell values for relations along the
schema graph. There may be several child-side fields (often lists of nested
records) and several parent-side fields (nested records; wrapped in Maybe
when the foreign-key side you join from allows NULL).
What actually appears in the generated SQL beyond that shape is controlled by
the QueryParam: filters, which paths are traversed, ordering on a branch
(e.g. child rows sorted by their position number), limits, and similar options.
You only configure in QueryParam what you need for this query—not every
possible relation field in r.
Build QueryParam with the MonadQP API.
selectText :: forall (ren :: Renamer) sch (d :: Nat) (tab :: NameNSK). forall (ann :: Ann) -> forall r. (CRecInfo ann r, ann ~ 'Ann ren sch d tab) => QueryParam sch tab -> (Text, [SomeToField]) Source #
Return the generated SELECT SQL text (and bind parameters), e.g. for debugging.
Monad to set Query Params
type MonadQP sch (t :: NameNSK) (path :: [Symbol]) = (TabPath sch t path, ToStar path) => RWS (Proxy path) () (QueryParam sch t) () Source #
qpEmpty :: forall sch (t :: NameNSK). QueryParam sch t Source #
Empty QueryParam.
It means that SELECT is defined only by structure of output type
qRoot :: forall {a} sch (t :: NameNSK). RWS (Proxy ('[] :: [a])) () (QueryParam sch t) () -> QueryParam sch t Source #
Execute MonadQP and get QueryParam.
The table t defines a context and becomes the "current" table
qPath :: forall sch (t :: NameNSK) (path :: [Symbol]) (path' :: [Symbol]). forall (p :: Symbol) -> (TabPath sch t path', ToStar path', path' ~ (path ++ '[p])) => MonadQP sch t path' -> MonadQP sch t path Source #
Change context (current table) to parent or child table.
The Symbol must name the foreign-key constraint (edge to the parent or from the child)
for the step away from the current table.
qWhere :: forall sch (t :: NameNSK) (path :: [Symbol]). Cond sch (TabOnPath sch t path) -> MonadQP sch t path Source #
qOrderBy :: forall sch (t :: NameNSK) (path :: [Symbol]). [OrdFld sch (TabOnPath sch t path)] -> MonadQP sch t path Source #
Add ORDER BY condition for the current table
Several qOrderBy are possible and they are composed together.
Ordering can span the current table and joined parents. For example:
qOrderBy [ascf "f1"] qPath "ref-to-parent" do qOrderBy [descf "f2"] qOrderBy [ascf "f3"]
we get ORDER BY t1.f1, t2.f2 DESC, t1.f3
qDistinct :: forall sch (t :: NameNSK) (path :: [Symbol]) (t' :: NameNSK). TabOnPath2 sch t path ~ '(t', 'RelMany) => MonadQP sch t path Source #
Add DISTINCT condition for the current table.
It is applied only to "root" or "children" tables.
qDistinctOn :: forall sch (t :: NameNSK) (path :: [Symbol]). [OrdFld sch (TabOnPath sch t path)] -> MonadQP sch t path Source #
Add DISTINCT ON condition for the current table.
It can also be applied on a parent table because that parent is joined to the current table.
qDistinctOn automatically adds fields to the ORDER BY clause (as PostgreSQL requires).
(That's why OrdDirection is needed)
So having
qOrderBy [descf "f0"] qDistinctOn [ascf "f1"] qPath "ref-to-parent" do qDistinctOn [descf "f2"] qDistinctOn [ascf "f3"]
we get DISTINCT ON (t1.f1, t2.f2, t1.f3) ... ORDER BY t1.f1, t2.f2 DESC, t1.f3, t1.f0 DESC
qLimit :: forall sch (t :: NameNSK) (path :: [Symbol]). Snd (TabOnPath2 sch t path) ~ 'RelMany => Natural -> MonadQP sch t path Source #
Add LIMIT condition for the current table.
It is applied only to "root" or "children" tables.
If qLimit is applied several times on the same path, only the last one is used
qOffset :: forall sch (t :: NameNSK) (path :: [Symbol]). Snd (TabOnPath2 sch t path) ~ 'RelMany => Natural -> MonadQP sch t path Source #
Add OFFSET condition for the current table.
It is applied only to "root" or "children" tables.
If qOffset is applied several times on the same path, only the last one is used
Internals
data QueryParam sch (t :: NameNSK) Source #
Parameters that are used to describe SELECT.
You don't need to make it directly. Use MonadQP to define QueryParam instead.
Constructors
| QueryParam | |
Fields
| |
data CondWithPath sch (t :: NameNSK) where Source #
GADT to safely set `where` condition
Constructors
| CondWithPath :: forall (path :: [Symbol]) sch (t :: NameNSK). ToStar path => Cond sch (TabOnPath sch t path) -> CondWithPath sch t |
data OrdWithPath (sch :: k) (t :: NameNSK) where Source #
GADT to safely set `order by` clauses
Constructors
| OrdWithPath :: forall {k} (path :: [Symbol]) (sch :: k) (t :: NameNSK). ToStar path => [OrdFld sch (TabOnPath sch t path)] -> OrdWithPath sch t |
data LimOffWithPath (sch :: k) (t :: NameNSK) where Source #
GADT to safely set `limit/offset` clauses
Constructors
| LimOffWithPath :: forall {k} (path :: [Symbol]) (sch :: k) (t :: NameNSK). (TabPath sch t path, ToStar path, Snd (TabOnPath2 sch t path) ~ 'RelMany) => LO -> LimOffWithPath sch t |
data DistWithPath (sch :: k) (t :: NameNSK) where Source #
GADT to safely set `distinct/distinct on` clauses
Constructors
| DistWithPath :: forall {k} (path :: [Symbol]) (sch :: k) (t :: NameNSK). ToStar path => Dist sch (TabOnPath sch t path) -> DistWithPath sch t |
Conditions
Example: "name" =? John
(<?) :: forall (fld :: Symbol) -> forall sch (tab :: NameNSK) (fd :: FldDef' Symbol) v. CDBValue sch tab fld fd v => v -> Cond sch tab infix 4 Source #
(>?) :: forall (fld :: Symbol) -> forall sch (tab :: NameNSK) (fd :: FldDef' Symbol) v. CDBValue sch tab fld fd v => v -> Cond sch tab infix 4 Source #
(<=?) :: forall (fld :: Symbol) -> forall sch (tab :: NameNSK) (fd :: FldDef' Symbol) v. CDBValue sch tab fld fd v => v -> Cond sch tab infix 4 Source #
(>=?) :: forall (fld :: Symbol) -> forall sch (tab :: NameNSK) (fd :: FldDef' Symbol) v. CDBValue sch tab fld fd v => v -> Cond sch tab infix 4 Source #
(=?) :: forall (fld :: Symbol) -> forall sch (tab :: NameNSK) (fd :: FldDef' Symbol) v. CDBValue sch tab fld fd v => v -> Cond sch tab infix 4 Source #
Example: "name" ~~? "%joh%"
(~=?) :: forall (fld :: Symbol) -> forall sch (tab :: NameNSK) (fd :: FldDef' Symbol) v. CDBValue sch tab fld fd v => v -> Cond sch tab infix 4 Source #
(~~?) :: forall (fld :: Symbol) -> forall sch (tab :: NameNSK) (fd :: FldDef' Symbol) v. CDBValue sch tab fld fd v => v -> Cond sch tab infix 4 Source #
(|||) :: forall sch (tab :: NameNSK). Cond sch tab -> Cond sch tab -> Cond sch tab infixl 2 Source #
Disjunction
(&&&) :: forall sch (tab :: NameNSK). Cond sch tab -> Cond sch tab -> Cond sch tab infixl 3 Source #
Conjunction
pnull :: forall sch (tab :: NameNSK) (fd :: FldDef' Symbol). forall (name :: Symbol) -> CDBFieldNullable sch tab name fd => Cond sch tab Source #
Check that field value is NULL
pin :: forall (name :: Symbol) -> forall sch (tab :: NameNSK) (fd :: FldDef' Symbol) v. CDBValue sch tab name fd v => NonEmpty v -> Cond sch tab Source #
Check that field value belongs to non-empty list of values
pinArr :: forall (name :: Symbol) -> forall sch (tab :: NameNSK) (fd :: FldDef' Symbol) v. CDBValue sch tab name fd v => [v] -> Cond sch tab Source #
Check that field value belongs to the list of values.
If the list is empty, the condition evaluates to false.
pparent :: forall (ref :: NameNSK) -> CRelDef sch ref => Cond sch (RdTo (TRelDef sch ref)) -> Cond sch (RdFrom (TRelDef sch ref)) Source #
Check that condition is satisfied in parent table
pchild :: forall (ref :: NameNSK) -> CRelDef sch ref => TabParam sch (RdFrom (TRelDef sch ref)) -> Cond sch (RdFrom (TRelDef sch ref)) -> Cond sch (RdTo (TRelDef sch ref)) Source #
True when related rows exist in the child table and satisfy the nested condition there
TabParam is used to limit child dataset (usually with ORDER BY and LIMIT) before applying
condition on child table
data TabParam sch (tab :: NameNSK) Source #
Parameters for child table.
It is used to limit child dataset (usually with ORDER BY and LIMIT) before applying
condition on child table
data Cond sch (tab :: NameNSK) where Source #
GADT to safely set `where` condition for table tab based on definition of schema sch
Constructors
| EmptyCond | |
| Cmp | |
| In | |
| InArr | |
| Null | |
| Not | |
| BoolOp | |
| Child | |
Fields
| |
| Parent | |
| UnsafeCond | |
Instances
Just boolean operations
type CondMonad = RWS (Text, NonEmpty Int) [SomeToField] Int Source #
RWS-Monad to generate condition. * Read: Stack of numbers of parent tables. The top is "current table" * Write: List of placeholder-values.
Note: SQL is generated top-down so placeholder values appear in the correct order.
- State: Last number of table "in use"
data SomeToField where Source #
Constructors
| SomeToField :: forall a. (ToField a, Show a) => a -> SomeToField |
Instances
| Show SomeToField Source # | |
Defined in PgSchema.DML.Select.Types Methods showsPrec :: Int -> SomeToField -> ShowS # show :: SomeToField -> String # showList :: [SomeToField] -> ShowS # | |
| ToField SomeToField Source # | |
Defined in PgSchema.DML.Select.Types Methods toField :: SomeToField -> Action # | |
type CDBField (sch :: k) (tab :: NameNSK) (fld :: Symbol) (fd :: FldDef' Symbol) = (CDBFieldInfo sch tab fld, TDBFieldInfo sch tab fld ~ ('RFPlain fd :: RecField' Symbol NameNSK)) Source #
type CDBValue sch (tab :: NameNSK) (fld :: Symbol) (fd :: FldDef' Symbol) v = (CDBField sch tab fld fd, ToField v, Show v, CanConvert sch tab fld fd v) Source #
type CDBFieldNullable (sch :: k) (tab :: NameNSK) (fld :: Symbol) (fd :: FldDef' Symbol) = (CDBField sch tab fld fd, FdNullable fd ~ 'True) Source #
class (ToStar (TRelDef sch ref), CTabDef sch (RdFrom (TRelDef sch ref)), CTabDef sch (RdTo (TRelDef sch ref))) => CRelDef (sch :: k) (ref :: NameNSK) Source #
Relation definition for relation name ref.
Instances
| CRelDef PgCatalog (PGC "attribute__class") Source # | |
| CRelDef PgCatalog (PGC "attribute__type") Source # | |
| CRelDef PgCatalog (PGC "class__namespace") Source # | |
| CRelDef PgCatalog (PGC "constraint__class") Source # | |
| CRelDef PgCatalog (PGC "constraint__fclass") Source # | |
| CRelDef PgCatalog (PGC "constraint__namespace") Source # | |
| CRelDef PgCatalog (PGC "enum__type") Source # | |
| CRelDef PgCatalog (PGC "type__namespace") Source # | |
Order By and others
ordf :: forall (fld :: Symbol) -> forall (sch :: k) (tab :: NameNSK) (fd :: FldDef' Symbol). CDBField sch tab fld fd => OrdDirection -> OrdFld sch tab Source #
ascf :: forall (fld :: Symbol) -> forall (sch :: k) (tab :: NameNSK) (fd :: FldDef' Symbol). CDBField sch tab fld fd => OrdFld sch tab Source #
descf :: forall (fld :: Symbol) -> forall (sch :: k) (tab :: NameNSK) (fd :: FldDef' Symbol). CDBField sch tab fld fd => OrdFld sch tab Source #
data OrdDirection Source #
Instances
| Show OrdDirection Source # | |
Defined in PgSchema.DML.Select.Types Methods showsPrec :: Int -> OrdDirection -> ShowS # show :: OrdDirection -> String # showList :: [OrdDirection] -> ShowS # | |
data Dist (sch :: k) (tab :: NameNSK) where Source #
Constructors
| Distinct :: forall {k} (sch :: k) (tab :: NameNSK). Dist sch tab | |
| DistinctOn :: forall {k} (sch :: k) (tab :: NameNSK). [OrdFld sch tab] -> Dist sch tab | Having That's why we use Beside that |
Plain Insert
insertSch :: forall (ann :: Ann) -> forall r r'. InsertReturning ann r r' => Connection -> [r] -> IO ([r'], Text) Source #
Insert records into a table. You can request any subset of columns from the inserted row via the result type.
All mandatory fields having no defaults should be present.
insertSch_ :: forall (ann :: Ann) -> forall r. InsertNonReturning ann r => Connection -> [r] -> IO (Int64, Text) Source #
Insert records into a table without RETURNING.
insertText :: forall (ann :: Ann) -> forall r r' s. (CRecInfo ann r, CRecInfo ann r', IsString s, Monoid s) => s Source #
Construct SQL text for inserting records into a table and returning some fields.
insertText_ :: forall (ann :: Ann) -> forall r s. (IsString s, Monoid s, CRecInfo ann r) => s Source #
Construct SQL text for inserting records into a table without RETURNING.
type InsertNonReturning (ann :: Ann) r = (PlainIn ann r, CheckAllMandatory ann (ColsDbNames (Cols ann r))) Source #
Plain insert without RETURNING.
Check that all fields belong to the root table and all mandatory fields are present.
type InsertReturning (ann :: Ann) r r' = (InsertNonReturning ann r, PlainOut ann r') Source #
Plain insert with RETURNING.
Check that all inserted and returned fields belong to the root table
and all mandatory fields are present.
Update
updateByCond :: forall (ren :: Renamer) sch (d :: Nat) (t :: NameNSK). forall (ann :: Ann) -> forall r r'. (ann ~ 'Ann ren sch d t, UpdateReturning ann r r') => Connection -> r -> Cond sch t -> IO [r'] Source #
Update rows matching a condition; the result type selects which columns are returned.
updateByCond_ :: forall (ren :: Renamer) sch (d :: Nat) (t :: NameNSK). forall (ann :: Ann) -> forall r. (ann ~ 'Ann ren sch d t, UpdateNonReturning ann r) => Connection -> r -> Cond sch t -> IO Int64 Source #
Update records by condition without RETURNING.
updateText :: forall (ren :: Renamer) sch (d :: Nat) (t :: NameNSK). forall (ann :: Ann) -> forall r r' s. (CRecInfo ann r, CRecInfo ann r', IsString s, Monoid s, ann ~ 'Ann ren sch d t) => Cond sch t -> (s, [SomeToField]) Source #
Construct SQL text for updating records by condition and returning some fields.
updateText_ :: forall sch (t :: NameNSK). forall (ann :: Ann) -> forall r s. (IsString s, Monoid s, CRecInfo ann r) => Cond sch t -> (s, [SomeToField]) Source #
Construct SQL text for updating records by condition without RETURNING.
type UpdateReturning (ann :: Ann) r r' = (UpdateNonReturning ann r, PlainOut ann r') Source #
Plain update with RETURNING.
Check that all updated and returned fields belong to the root table.
type UpdateNonReturning (ann :: Ann) r = PlainIn ann r Source #
Plain update without RETURNING.
Check that all updated fields belong to the root table.
Tree-base Insert/Upsert
insertJSON :: forall (ann :: Ann) -> forall r r'. InsertTreeReturning ann r r' => Connection -> [r] -> IO ([r'], Text) Source #
Insert records into a table and its children using JSON data internally.
Like upsertJSON, but requires all mandatory columns at every node (insert-only constraint).
insertJSON_ :: forall (ann :: Ann) -> forall r. InsertTreeNonReturning ann r => Connection -> [r] -> IO Text Source #
Like insertJSON, but does not return rows.
upsertJSON :: forall (ann :: Ann) -> forall r r'. UpsertTreeReturning ann r r' => Connection -> [r] -> IO ([r'], Text) Source #
Upsert a forest of rows into the root table and its child tables in one
round-trip, using JSON inside PostgreSQL (same pipeline as insertJSON).
Input shape (r): a record tree that may contain the root table’s columns
and nested child branches (one-to-many from the root downward). There are no
nested parent branches: parent keys are implied by the tree you send, not by
embedding parent rows inside children.
Output shape (r'): a record tree whose graph of nested tables is a
subgraph of the input: the same tables can appear, but you choose which
columns (and which levels) appear in the result—whatever is available through
the generated RETURNING/result projection. Field sets may differ from r;
relation structure cannot grow beyond what you sent in.
What to supply at each node: at every level, each row must either include all mandatory columns (for columns that are mandatory in the schema /sense of this API/) or, alternatively, enough primary-key columns to identify an existing row. Foreign-key columns that are filled in by the parent level (for example after an auto-generated id on insert) do not need to be present on the child payload.
Insert vs update vs upsert per row: the engine picks one of INSERT,
UPDATE, or UPSERT from the keys and mandatory fields you provide:
- all mandatory fields present and no primary key →
INSERT - primary key present, not all mandatory fields →
UPDATE - primary key present and all mandatory fields →
UPSERT
insertJSON is the same execution path but adds a stricter type-level
constraint: every mandatory field must be present (pure inserts). upsertJSON
relaxes that so updates and upserts are expressible as in the rules above.
upsertJSON_ :: forall (ann :: Ann) -> forall r. UpsertTreeNonReturning ann r => Connection -> [r] -> IO Text Source #
Like upsertJSON, but does not return rows.
insertJSONText :: forall (ann :: Ann) -> forall r r'. (TreeSch ann, CRecInfo ann r, CRecInfo ann r', IsString s, Monoid s, Ord s) => s Source #
insertJSONText_ :: forall (ann :: Ann) -> forall r s. (IsString s, Monoid s, Ord s, TreeSch ann, CRecInfo ann r) => s Source #
type TreeOut (ann :: Ann) r' = (CRecInfo ann r', FromJSON (PgTag ann r'), Typeable ann, Typeable r') Source #
type family AllMandatoryTree (ann :: Ann) r (rFlds :: [Symbol]) where ... Source #
Equations
| AllMandatoryTree ann [r] rFlds = AllMandatoryTree ann r rFlds | |
| AllMandatoryTree ann r rFlds = WalkLevelAnn CheckAllMandatorySym0 ann (TRecordInfo ann r) rFlds |
type family AllMandatoryOrHasPKTree (ann :: Ann) r (rFlds :: [Symbol]) where ... Source #
Equations
| AllMandatoryOrHasPKTree ann [r] rFlds = AllMandatoryOrHasPKTree ann r rFlds | |
| AllMandatoryOrHasPKTree ann r rFlds = WalkLevelAnn CheckAllMandatoryOrHasPKSym0 ann (TRecordInfo ann r) rFlds |
type InsertTreeNonReturning (ann :: Ann) r = (TreeSch ann, TreeIn ann r, AllMandatoryTree ann r ('[] :: [Symbol])) Source #
Insert tree without RETURNING.
Check that all mandatory fields are present in all tables in tree. Reference fields in the child tables are not checked - they are inserted automatically.
type InsertTreeReturning (ann :: Ann) r r' = (InsertTreeNonReturning ann r, TreeOut ann r', ReturningIsSubtree ann r r') Source #
Insert tree with RETURNING.
Check that all mandatory fields are present in all tables in tree. Reference fields in the child tables are not checked - they are inserted automatically.
It also checks that we get returnings only from the tables we inserted into.
type UpsertTreeNonReturning (ann :: Ann) r = (TreeSch ann, TreeIn ann r, AllMandatoryOrHasPKTree ann r ('[] :: [Symbol])) Source #
Upsert tree without RETURNING.
Check that all mandatory fields or primary keys are present in all tables in tree. Reference fields in the child tables are not checked - they are inserted automatically.
type UpsertTreeReturning (ann :: Ann) r r' = (UpsertTreeNonReturning ann r, TreeOut ann r', ReturningIsSubtree ann r r') Source #
Upsert tree with RETURNING.
Check that all mandatory fields or primary keys are present in all tables in tree. Reference fields in the child tables are not checked - they are inserted automatically.
It also checks that we get returnings only from the tables we upserted into.
type family TRecordInfo (ann :: Ann) r :: [FieldInfo Symbol] where ... Source #
Equations
| TRecordInfo ann r = TRecordInfoCols ann (Cols ann r) |
Delete
deleteByCond :: forall sch (t :: NameNSK) -> SingI t => Connection -> Cond sch t -> IO (Int64, (Text, [SomeToField])) Source #
Delete records in table by condition.
deleteText :: forall sch (t :: NameNSK) s. (IsString s, Monoid s, SingI t) => Cond sch t -> (s, [SomeToField]) Source #
Construct SQL text for deleting records by condition.
Types
Type-level annotation: enforce constraints at compile time
and drive demoted types used to generate correct SQL.
annRen and annSch are fixed for the whole DML-operation.
annDepth and annTab are changed while traversing the structure of the ADT.
Constructors
| Ann | |
Instances
| (FromJSON (PgTag ann r), Typeable ann, Typeable r) => FromField [PgTag ann r] Source # | |
Defined in PgSchema.Ann Methods fromField :: FieldParser [PgTag ann r] # | |
| ToJSON (PgTag ann r) => ToField [PgTag ann r] Source # | |
Defined in PgSchema.Ann | |
| (cols ~ Cols ann r, colsCase ~ ColsCaseOf r, FromJSONCols ann colsCase cols r) => FromJSON (PgTag ann r) Source # | |
Defined in PgSchema.Ann | |
| (cols ~ Cols ann r, colsCase ~ ColsCaseOf r, ToJSONCols ann colsCase cols r) => ToJSON (PgTag ann r) Source # | |
| (FromJSON (PgTag ann r), Typeable ann, Typeable r) => FromField (PgTag ann r) Source # | |
Defined in PgSchema.Ann Methods fromField :: FieldParser (PgTag ann r) # | |
| (cols ~ Cols ann r, colsCase ~ ColsCaseOf r, FromRowCols ann colsCase cols r) => FromRow (PgTag ann r) Source # | |
Defined in PgSchema.Ann | |
| ToJSON (PgTag ann r) => ToField (PgTag ann r) Source # | |
Defined in PgSchema.Ann | |
| (cols ~ Cols ann r, colsCase ~ ColsCaseOf r, ToRowCols ann colsCase cols r) => ToRow (PgTag ann r) Source # | |
Defined in PgSchema.Ann | |
Renamers
data RenamerId (a :: TyFun Symbol Symbol) Source #
Renamer that does not change the symbol.
Instances
| type ApplyRenamer RenamerId s Source # | |
Defined in PgSchema.Ann | |
type CamelToSnake (s :: Symbol) = CamelToSnakeInternal (UnconsSymbol s) Source #
Closed type family to convert CamelCase to snake_case that can be used in Renamer.
>>> import Data.Proxy >>> symbolVal (Proxy @(CamelToSnake TESTCamelTo_snake_Case)) "t_e_s_t_camel_to_snake__case"
type family ApplyRenamer (renamer :: Renamer) (s :: Symbol) :: Symbol Source #
Apply renamer to symbol.
Like Apply but specialized for Symbol.
To make your own Renamer, typically you make
- data MyRenamer :: Renamer
- closed type family: `type family MyRenamerImpl (s :: Symbol) :: Symbol where ... `
- type instance ApplyRenamer MyRenamer s = MyRenamerImpl s
Instances
| type ApplyRenamer RenamerId s Source # | |
Defined in PgSchema.Ann | |
PgTag types
newtype PgTag (s :: k) t Source #
Annotates a value with schema/type information for DML codecs.
You can describe rows in two ways:
- Ordinary Haskell records with a
Genericinstance. - Symbol-labelled rows built from
(=:)and chained with(:.)frompostgresql-simple(re-exported from PgSchema.DML).
PgTag is analogous to Tagged from the tagged package, but
carries JSON (and related) instances suited to pg-schema.
Both representations can be mixed in one row.
Two pieces of syntax cooperate with PgTag:
Instances
| (FromJSON (PgTag ann r), Typeable ann, Typeable r) => FromField [PgTag ann r] Source # | |
Defined in PgSchema.Ann Methods fromField :: FieldParser [PgTag ann r] # | |
| ToJSON (PgTag ann r) => ToField [PgTag ann r] Source # | |
Defined in PgSchema.Ann | |
| Functor (PgTag s) Source # | |
| Foldable (PgTag s) Source # | |
Defined in PgSchema.Types Methods fold :: Monoid m => PgTag s m -> m # foldMap :: Monoid m => (a -> m) -> PgTag s a -> m # foldMap' :: Monoid m => (a -> m) -> PgTag s a -> m # foldr :: (a -> b -> b) -> b -> PgTag s a -> b # foldr' :: (a -> b -> b) -> b -> PgTag s a -> b # foldl :: (b -> a -> b) -> b -> PgTag s a -> b # foldl' :: (b -> a -> b) -> b -> PgTag s a -> b # foldr1 :: (a -> a -> a) -> PgTag s a -> a # foldl1 :: (a -> a -> a) -> PgTag s a -> a # elem :: Eq a => a -> PgTag s a -> Bool # maximum :: Ord a => PgTag s a -> a # minimum :: Ord a => PgTag s a -> a # | |
| Traversable (PgTag s) Source # | |
| (cols ~ Cols ann r, colsCase ~ ColsCaseOf r, FromJSONCols ann colsCase cols r) => FromJSON (PgTag ann r) Source # | |
Defined in PgSchema.Ann | |
| FromJSON a => FromJSON (PgTag s (PgArr a)) Source # | |
| (cols ~ Cols ann r, colsCase ~ ColsCaseOf r, ToJSONCols ann colsCase cols r) => ToJSON (PgTag ann r) Source # | |
| ToJSON a => ToJSON (PgTag s (PgArr a)) Source # | |
| Monoid t => Monoid (PgTag s t) Source # | |
| Semigroup t => Semigroup (PgTag s t) Source # | |
| Read t => Read (PgTag s t) Source # | |
| Show t => Show (PgTag s t) Source # | |
| Eq t => Eq (PgTag s t) Source # | |
| Ord t => Ord (PgTag s t) Source # | |
| (FromJSON (PgTag ann r), Typeable ann, Typeable r) => FromField (PgTag ann r) Source # | |
Defined in PgSchema.Ann Methods fromField :: FieldParser (PgTag ann r) # | |
| (FromField a, Typeable a) => FromField (PgTag s (PgArr a)) Source # | |
Defined in PgSchema.Types Methods fromField :: FieldParser (PgTag s (PgArr a)) # | |
| (cols ~ Cols ann r, colsCase ~ ColsCaseOf r, FromRowCols ann colsCase cols r) => FromRow (PgTag ann r) Source # | |
Defined in PgSchema.Ann | |
| ToJSON (PgTag ann r) => ToField (PgTag ann r) Source # | |
Defined in PgSchema.Ann | |
| (ToField a, ToStar s) => ToField (PgTag s (PgArr a)) Source # | |
| (cols ~ Cols ann r, colsCase ~ ColsCaseOf r, ToRowCols ann colsCase cols r) => ToRow (PgTag ann r) Source # | |
Defined in PgSchema.Ann | |
Re-export from postgresql-simple
A composite type to parse your custom data structures without having to define dummy newtype wrappers every time.
instance FromRow MyData where ...
instance FromRow MyData2 where ...
then I can do the following for free:
res <- query' c "..."
forM res $ \(MyData{..} :. MyData2{..}) -> do
....
Constructors
| h :. t infixr 3 |
Instances
| (Read h, Read t) => Read (h :. t) # | |
| (Show h, Show t) => Show (h :. t) # | |
| (Eq h, Eq t) => Eq (h :. t) # | |
| (Ord h, Ord t) => Ord (h :. t) # | |
Defined in Database.PostgreSQL.Simple.Types | |
| (FromRow a, FromRow b) => FromRow (a :. b) # | |
Defined in Database.PostgreSQL.Simple.FromRow | |
| (ToRow a, ToRow b) => ToRow (a :. b) # | |
Defined in Database.PostgreSQL.Simple.ToRow | |
Enum
data family PGEnum sch (name :: NameNSK) Source #
Introduce enum database types.
Data instances are produced by schema generation.
You can use these data instances in you records to SELECTINSERTUPSERT data
Instances
| (Read (PGEnum sch t), ToStar t) => FromJSON (PGEnum sch t) Source # | |
Defined in PgSchema.Types | |
| (Show (PGEnum sch t), ToStar t) => ToJSON (PGEnum sch t) Source # | |
| (Read (PGEnum sch n), ToStar n, Typeable sch, Typeable n) => FromField (PGEnum sch n) Source # | |
Defined in PgSchema.Types Methods fromField :: FieldParser (PGEnum sch n) # | |
| (Show (PGEnum sch n), ToStar n) => ToField (PGEnum sch n) Source # | |
Defined in PgSchema.Types | |
| type CanConvert1 sch tab fld n ('TypDef "E" ('Nothing :: Maybe (NameNS' Symbol)) es) (PGEnum sch n) Source # | |
Defined in PgSchema.Types | |
Aggregates
newtype Aggr' (f :: AggrFun) t Source #
All aggregate functions except count can return NULL.
But if field under aggregate is mandatory they return NULL only on empty set
if there is no group by clause. E.g. `select min(a) from t where false`
So we require Nullable for Aggr.
Aggr' is like Aggr but cannot be used in SELECT without `group by`.
So it is mandatory if field is mandatory.
Instances
| FromJSON t => FromJSON (Aggr' f t) Source # | |
Defined in PgSchema.Types | |
| ToJSON t => ToJSON (Aggr' f t) Source # | |
| Show t => Show (Aggr' f t) Source # | |
| Eq t => Eq (Aggr' f t) Source # | |
| Ord t => Ord (Aggr' f t) Source # | |
| FromField t => FromField (Aggr' f t) Source # | |
Defined in PgSchema.Types Methods fromField :: FieldParser (Aggr' f t) # | |
| ToField t => ToField (Aggr' f t) Source # | |
Defined in PgSchema.Types | |
newtype Aggr (f :: AggrFun) t Source #
Introduce aggregate functions.
I.e. "fld" := Aggr AMin (Maybe Int32) means "minimum value of the field fld"
Aggr requires a Maybe argument for all functions except count.
Only a small set of aggregations are supported currently: count, min, max, sum, avg.
Instances
| FromJSON t => FromJSON (Aggr f t) Source # | |
Defined in PgSchema.Types | |
| ToJSON t => ToJSON (Aggr f t) Source # | |
| Show t => Show (Aggr f t) Source # | |
| Eq t => Eq (Aggr f t) Source # | |
| Ord t => Ord (Aggr f t) Source # | |
Defined in PgSchema.Types | |
| FromField t => FromField (Aggr f t) Source # | |
Defined in PgSchema.Types Methods fromField :: FieldParser (Aggr f t) # | |
| ToField t => ToField (Aggr f t) Source # | |
Defined in PgSchema.Types | |
Supported SQL aggregate functions
Instances
| Show AggrFun Source # | |
| SingKind AggrFun Source # | |
| SingI 'AAvg Source # | |
Defined in PgSchema.Schema | |
| SingI 'ACount Source # | |
Defined in PgSchema.Schema | |
| SingI 'AMax Source # | |
Defined in PgSchema.Schema | |
| SingI 'AMin Source # | |
Defined in PgSchema.Schema | |
| SingI 'ASum Source # | |
Defined in PgSchema.Schema | |
| SingI n => SingI2 ('RFAggr n :: AggrFun -> Bool -> RecField' s p) Source # | |
| type Demote AggrFun Source # | |
Defined in PgSchema.Schema | |
| type Sing Source # | |
Defined in PgSchema.Schema type Sing | |
Arrays
PGArray has no JSON instances. '[]' has JSON, but no PG instances.
This one has both.
Use this type to work with arrays in database.
All elements are Maybe because PostgreSQL does not guarantee that all elements are present.
PgTag typeName PgArr can be safely converted to ToField with type information (e.g. val::int[]).
This instance is used internally in the generation of SQL.
Instances
| FromJSON a => FromJSON (PgArr a) Source # | |
Defined in PgSchema.Types | |
| ToJSON a => ToJSON (PgArr a) Source # | |
| Monoid (PgArr a) Source # | |
| Semigroup (PgArr a) Source # | |
| Read a => Read (PgArr a) Source # | |
| Show a => Show (PgArr a) Source # | |
| Eq a => Eq (PgArr a) Source # | |
| Ord a => Ord (PgArr a) Source # | |
| FromJSON a => FromJSON (PgTag s (PgArr a)) Source # | |
| ToJSON a => ToJSON (PgTag s (PgArr a)) Source # | |
| (FromField a, Typeable a) => FromField (PgTag s (PgArr a)) Source # | |
Defined in PgSchema.Types Methods fromField :: FieldParser (PgTag s (PgArr a)) # | |
| (ToField a, ToStar s) => ToField (PgTag s (PgArr a)) Source # | |
| type CanConvert1 sch tab fld tn ('TypDef "A" ('Just n) y) (PgArr t) Source # | |
Defined in PgSchema.Types type CanConvert1 sch tab fld tn ('TypDef "A" ('Just n) y) (PgArr t) = CanConvert1 sch tab fld n (TTypDef sch n) t | |
Conversion checks
type family CanConvert sch (tab :: NameNSK) (fld :: Symbol) (fd :: FldDefK) t where ... Source #
Closed type family to check that field can be converted to or from Haskell type.
To make your types convertible to some database type use open type family CanConvert1.
Equations
| CanConvert sch tab fld fd t = CanConvertMaybe sch tab fld (FdType fd) (FdNullable fd) (TTypDef sch (FdType fd)) t |
type family CanConvert1 sch (tab :: NameNSK) (fld :: Symbol) (tn :: NameNSK) (td :: TypDefK) t Source #
Open mapping from a PostgreSQL type (non-nullable) to a Haskell type. Add your own equations to this family to support extra pairings.
Instances
| type CanConvert1 sch tab fld tn ('TypDef "B" x y) Bool Source # | |
Defined in PgSchema.Types | |
| type CanConvert1 sch tab fld tn ('TypDef "A" ('Just n) y) (PgArr t) Source # | |
Defined in PgSchema.Types type CanConvert1 sch tab fld tn ('TypDef "A" ('Just n) y) (PgArr t) = CanConvert1 sch tab fld n (TTypDef sch n) t | |
| type CanConvert1 sch tab fld n ('TypDef "E" ('Nothing :: Maybe (NameNS' Symbol)) es) (PGEnum sch n) Source # | |
Defined in PgSchema.Types | |
| type CanConvert1 sch tab fld (PGC "char") ('TypDef "S" x y) PgChar Source # | |
Defined in PgSchema.Types | |
| type CanConvert1 sch tab fld (PGC "date") ('TypDef "D" x y) Day Source # | |
Defined in PgSchema.Types | |
| type CanConvert1 sch tab fld (PGC "float4") ('TypDef "N" x y) Scientific Source # | |
Defined in PgSchema.Types | |
| type CanConvert1 sch tab fld (PGC "float4") ('TypDef "N" x y) Double Source # | |
Defined in PgSchema.Types | |
| type CanConvert1 sch tab fld (PGC "float8") ('TypDef "N" x y) Scientific Source # | |
Defined in PgSchema.Types | |
| type CanConvert1 sch tab fld (PGC "float8") ('TypDef "N" x y) Double Source # | |
Defined in PgSchema.Types | |
| type CanConvert1 sch tab fld (PGC "int2") ('TypDef "N" x y) Int16 Source # | |
Defined in PgSchema.Types | |
| type CanConvert1 sch tab fld (PGC "int2") ('TypDef "N" x y) Scientific Source # | |
Defined in PgSchema.Types | |
| type CanConvert1 sch tab fld (PGC "int4") ('TypDef "N" x y) Int32 Source # | |
Defined in PgSchema.Types | |
| type CanConvert1 sch tab fld (PGC "int4") ('TypDef "N" x y) Scientific Source # | |
Defined in PgSchema.Types | |
| type CanConvert1 sch tab fld (PGC "int8") ('TypDef "N" x y) Int64 Source # | |
Defined in PgSchema.Types | |
| type CanConvert1 sch tab fld (PGC "int8") ('TypDef "N" x y) Scientific Source # | |
Defined in PgSchema.Types | |
| type CanConvert1 sch tab fld (PGC "json") ('TypDef "U" x y) a Source # | |
Defined in PgSchema.Types | |
| type CanConvert1 sch tab fld (PGC "jsonb") ('TypDef "U" x y) a Source # | |
Defined in PgSchema.Types | |
| type CanConvert1 sch tab fld (PGC "name") ('TypDef "S" x y) Text Source # | |
Defined in PgSchema.Types | |
| type CanConvert1 sch tab fld (PGC "numeric") ('TypDef "N" x y) Scientific Source # | |
Defined in PgSchema.Types | |
| type CanConvert1 sch tab fld (PGC "oid") ('TypDef "N" x y) PgOid Source # | |
Defined in PgSchema.Types | |
| type CanConvert1 sch tab fld (PGC "oid") ('TypDef "N" x y) Int Source # | |
Defined in PgSchema.Types | |
| type CanConvert1 sch tab fld (PGC "text") ('TypDef "S" x y) Text Source # | |
Defined in PgSchema.Types | |
| type CanConvert1 sch tab fld (PGC "time") ('TypDef "D" x y) TimeOfDay Source # | |
Defined in PgSchema.Types | |
| type CanConvert1 sch tab fld (PGC "timestamp") ('TypDef "D" x y) LocalTime Source # | |
Defined in PgSchema.Types | |
| type CanConvert1 sch tab fld (PGC "timestamptz") ('TypDef "D" x y) UTCTime Source # | |
Defined in PgSchema.Types | |
| type CanConvert1 sch tab fld (PGC "timestamptz") ('TypDef "D" x y) ZonedTime Source # | |
Defined in PgSchema.Types | |
| type CanConvert1 sch tab fld (PGC "uuid") ('TypDef "U" x y) UUID Source # | |
Defined in PgSchema.Types | |
| type CanConvert1 sch tab fld (PGC "varchar") ('TypDef "S" x y) Text Source # | |
Defined in PgSchema.Types | |
| type CanConvert1 sch tab fld (PGC "bytea") ('TypDef "U" x y) (Binary ByteString) Source # | |
Defined in PgSchema.Types | |
| type CanConvert1 sch tab fld (PGC "bytea") ('TypDef "U" x y) (Binary ByteString) Source # | Binary ByteString has no |
Defined in PgSchema.Types | |
| type CanConvert1 sch tab fld (PGC "citext") ('TypDef "S" ('Nothing :: Maybe (NameNS' Symbol)) ('[] :: [Symbol])) (CI Text) Source # | |
| type CanConvert1 sch tab fld (PGC "numeric") ('TypDef "N" x y) (Fixed k2) Source # | |
Defined in PgSchema.Types | |
| type CanConvert1 sch tab fld ("public" ->> "citext") ('TypDef "S" ('Nothing :: Maybe (NameNS' Symbol)) ('[] :: [Symbol])) (CI Text) Source # | |
Description of a PostgreSQL type (category, array element, enum labels).
Constructors
| TypDef | |
Instances
| Show s => Show (TypDef' s) Source # | |
| SingKind s => SingKind (TypDef' s) Source # | |
| SingI n => SingI2 ('TypDef n :: Maybe (NameNS' s) -> [s] -> TypDef' s) Source # | |
| (SingI n1, SingI n2) => SingI1 ('TypDef n1 n2 :: [s] -> TypDef' s) Source # | |
| (SingI n1, SingI n2, SingI n3) => SingI ('TypDef n1 n2 n3 :: TypDef' s) Source # | |
Defined in PgSchema.Schema | |
| type Demote (TypDef' s) Source # | |
Defined in PgSchema.Schema | |
| type Sing Source # | |
Defined in PgSchema.Schema type Sing | |
Other types
Instances
| FromJSON PgChar Source # | |
Defined in PgSchema.Types | |
| ToJSON PgChar Source # | |
| Bounded PgChar Source # | |
| Enum PgChar Source # | |
Defined in PgSchema.Types | |
| Read PgChar Source # | |
| Show PgChar Source # | |
| Eq PgChar Source # | |
| Ord PgChar Source # | |
| FromField PgChar Source # | |
Defined in PgSchema.Types Methods | |
| ToField PgChar Source # | |
Defined in PgSchema.Types | |
| type CanConvert1 sch tab fld (PGC "char") ('TypDef "S" x y) PgChar Source # | |
Defined in PgSchema.Types | |
Oid but with JSON instances
Instances
| FromJSON PgOid Source # | |
Defined in PgSchema.Types | |
| ToJSON PgOid Source # | |
| Read PgOid Source # | |
| Show PgOid Source # | |
| Eq PgOid Source # | |
| FromField PgOid Source # | |
Defined in PgSchema.Types Methods | |
| ToField PgOid Source # | |
Defined in PgSchema.Types | |
| type CanConvert1 sch tab fld (PGC "oid") ('TypDef "N" x y) PgOid Source # | |
Defined in PgSchema.Types | |
Qualified PostgreSQL name: namespace (schema) + local name.
Constructors
| NameNS | |
Fields
| |
Instances
| SingI2 ('NameNS :: k2 -> k2 -> NameNS' k2) Source # | |
| SingI n => SingI1 ('NameNS n :: s -> NameNS' s) Source # | |
| Show s => Show (NameNS' s) Source # | |
| Eq s => Eq (NameNS' s) Source # | |
| Ord s => Ord (NameNS' s) Source # | |
| SingKind s => SingKind (NameNS' s) Source # | |
| SingI n => SingI2 ('RelDef n :: NameNS' s -> [(s, s)] -> RelDef' s) Source # | |
| SingI n => SingI2 ('TypDef n :: Maybe (NameNS' s) -> [s] -> TypDef' s) Source # | |
| (SingI n1, SingI n2) => SingI ('NameNS n1 n2 :: NameNS' s) Source # | |
Defined in PgSchema.Schema | |
| FromJSON a => FromJSON (PgTag s (PgArr a)) Source # | |
| ToJSON a => ToJSON (PgTag s (PgArr a)) Source # | |
| (ToField a, ToStar s) => ToField (PgTag s (PgArr a)) Source # | |
| type CanConvert1 sch tab fld tn ('TypDef "A" ('Just n) y) (PgArr t) Source # | |
Defined in PgSchema.Types type CanConvert1 sch tab fld tn ('TypDef "A" ('Just n) y) (PgArr t) = CanConvert1 sch tab fld n (TTypDef sch n) t | |
| type CanConvert1 sch tab fld n ('TypDef "E" ('Nothing :: Maybe (NameNS' Symbol)) es) (PGEnum sch n) Source # | |
Defined in PgSchema.Types | |
| type CanConvert1 sch tab fld (PGC "citext") ('TypDef "S" ('Nothing :: Maybe (NameNS' Symbol)) ('[] :: [Symbol])) (CI Text) Source # | |
| type CanConvert1 sch tab fld ("public" ->> "citext") ('TypDef "S" ('Nothing :: Maybe (NameNS' Symbol)) ('[] :: [Symbol])) (CI Text) Source # | |
| type Demote (NameNS' s) Source # | |
Defined in PgSchema.Schema | |
| type Sing Source # | |
Defined in PgSchema.Schema type Sing | |
type family TRelDef (sch :: k) (ref :: NameNSK) :: RelDefK Source #
Instances
| type TRelDef PgCatalog (PGC "attribute__class") Source # | |
| type TRelDef PgCatalog (PGC "attribute__type") Source # | |
| type TRelDef PgCatalog (PGC "class__namespace") Source # | |
| type TRelDef PgCatalog (PGC "constraint__class") Source # | |
| type TRelDef PgCatalog (PGC "constraint__fclass") Source # | |
| type TRelDef PgCatalog (PGC "constraint__namespace") Source # | |
| type TRelDef PgCatalog (PGC "enum__type") Source # | |
| type TRelDef PgCatalog (PGC "type__namespace") Source # | |
Foreign-key-style link between two qualified tables and column mapping.
Constructors
| RelDef | |
Instances
| Show s => Show (RelDef' s) Source # | |
| SingKind s => SingKind (RelDef' s) Source # | |
| SingI n => SingI2 ('RelDef n :: NameNS' s -> [(s, s)] -> RelDef' s) Source # | |
| (SingI n1, SingI n2) => SingI1 ('RelDef n1 n2 :: [(s, s)] -> RelDef' s) Source # | |
| (SingI n1, SingI n2, SingI n3) => SingI ('RelDef n1 n2 n3 :: RelDef' s) Source # | |
Defined in PgSchema.Schema | |
| type Demote (RelDef' s) Source # | |
Defined in PgSchema.Schema | |
| type Sing Source # | |
Defined in PgSchema.Schema type Sing | |
type family FdNullable (a :: FldDef' s) :: Bool where ... Source #
Equations
| FdNullable ('FldDef _1 field _2 :: FldDef' s) = field |
class (ToStar name, ToStar (TTabDef sch name)) => CTabDef (sch :: k) (name :: NameNSK) Source #
instances will be generated by code generation
Instances
| CTabDef PgCatalog (PGC "pg_attribute") Source # | |||||
Defined in PgSchema.Schema.Catalog | |||||
| CTabDef PgCatalog (PGC "pg_class") Source # | |||||
Defined in PgSchema.Schema.Catalog | |||||
| CTabDef PgCatalog (PGC "pg_constraint") Source # | |||||
Defined in PgSchema.Schema.Catalog Associated Types
| |||||
| CTabDef PgCatalog (PGC "pg_enum") Source # | |||||
Defined in PgSchema.Schema.Catalog | |||||
| CTabDef PgCatalog (PGC "pg_namespace") Source # | |||||
Defined in PgSchema.Schema.Catalog | |||||
| CTabDef PgCatalog (PGC "pg_type") Source # | |||||
Defined in PgSchema.Schema.Catalog | |||||