-- Hoogle documentation, generated by Haddock -- See Hoogle, http://www.haskell.org/hoogle/ -- | An API binding Web.Spock to Database.Beam -- -- An API binding Web.Spock to Database.Beam @package tsweb @version 0.1.2 module TsWeb.Db.Beam -- | The class Typeable allows a concrete representation of a type -- to be calculated. class Typeable (a :: k) -- | Representable types of kind *. This class is derivable in GHC -- with the DeriveGeneric flag on. -- -- A Generic instance must satisfy the following laws: -- --
-- from . to ≡ id -- to . from ≡ id --class Generic a -- | Monads in which IO computations may be embedded. Any monad -- built by applying a sequence of monad transformers to the IO -- monad will be an instance of this class. -- -- Instances should satisfy the following laws, which state that -- liftIO is a transformer of monads: -- -- class Monad m => MonadIO (m :: Type -> Type) -- | Lift a computation from the IO monad. liftIO :: MonadIO m => IO a -> m a -- | Identity functor and monad. (a non-strict monad) data Identity a -- | Run a SqlDelete in a MonadBeam runDelete :: (BeamSqlBackend be, MonadBeam be m) => SqlDelete be table -> m () -- | Build a SqlDelete from a table and a way to build a -- WHERE clause delete :: BeamSqlBackend be => DatabaseEntity be db (TableEntity table) -> (forall s. () => (forall s'. () => table (QExpr be s')) -> QExpr be s Bool) -> SqlDelete be table -- | Run a SqlUpdate in a MonadBeam. runUpdate :: (BeamSqlBackend be, MonadBeam be m) => SqlUpdate be tbl -> m () -- | Generate a SqlUpdate that will update the given table row with -- the given value. -- -- The SQL UPDATE that is generated will set every non-primary -- key field for the row where each primary key field is exactly what is -- given. -- -- Note: This is a pure SQL UPDATE command. This does not upsert -- or merge values. save :: (Table table, BeamSqlBackend be, SqlValableTable be (PrimaryKey table), SqlValableTable be table, HasTableEquality be (PrimaryKey table)) => DatabaseEntity be db (TableEntity table) -> table Identity -> SqlUpdate be table -- | Use with set to optionally set a fiield to a new value, -- calculated based on one or more fields from the existing row toUpdatedValueMaybe :: () => (forall s. () => table (QExpr be s) -> Maybe (QExpr be s a)) -> QFieldAssignment be table a -- | Use with set to set a field to a new value that is calculated -- based on one or more fields from the existing row toUpdatedValue :: () => (forall s. () => table (QExpr be s) -> QExpr be s a) -> QFieldAssignment be table a -- | Use with set to not modify the field toOldValue :: () => QFieldAssignment be table a -- | Use with set to set a field to an explicit new value that does -- not depend on any other value toNewValue :: () => (forall s. () => QExpr be s a) -> QFieldAssignment be table a setFieldsTo :: Table table => (forall s. () => table (QExpr be s)) -> table (QFieldAssignment be table') set :: Beamable table => table (QFieldAssignment be table') -- | Convenience form of updateTable that generates a WHERE -- clause that matches only the already existing entity updateTableRow :: (BeamSqlBackend be, Table table, HasTableEquality be (PrimaryKey table), SqlValableTable be (PrimaryKey table)) => DatabaseEntity be db (TableEntity table) -> table Identity -> table (QFieldAssignment be table) -> SqlUpdate be table -- | A specialization of update that is more convenient for normal -- tables. updateTable :: (BeamSqlBackend be, Beamable table) => DatabaseEntity be db (TableEntity table) -> table (QFieldAssignment be table) -> (forall s. () => table (QExpr be s) -> QExpr be s Bool) -> SqlUpdate be table -- | A specialization of update that matches the given (already -- existing) row updateRow :: (BeamSqlBackend be, Table table, HasTableEquality be (PrimaryKey table), SqlValableTable be (PrimaryKey table)) => DatabaseEntity be db (TableEntity table) -> table Identity -> (forall s. () => table (QField s) -> QAssignment be s) -> SqlUpdate be table -- | Build a SqlUpdate given a table, a list of assignments, and a -- way to build a WHERE clause. -- -- See the '(<-.)' operator for ways to build assignments. The -- argument to the second argument is a the table parameterized over -- QField, which represents the left hand side of assignments. -- Sometimes, you'd like to also get the current value of a particular -- column. You can use the current_ function to convert a -- QField to a QGenExpr. update :: (BeamSqlBackend be, Beamable table) => DatabaseEntity be db (TableEntity table) -> (forall s. () => table (QField s) -> QAssignment be s) -> (forall s. () => table (QExpr be s) -> QExpr be s Bool) -> SqlUpdate be table -- | Build a SqlInsertValues from a SqlSelect that returns -- the same table insertFrom :: (BeamSqlBackend be, HasQBuilder be, Projectible be r) => Q be db QBaseScope r -> SqlInsertValues be r -- | Build a SqlInsertValues from arbitrarily shaped data containing -- expressions insertData :: (Projectible be r, BeamSqlBackend be) => [r] -> SqlInsertValues be r -- | Build a SqlInsertValues from concrete table values insertValues :: (BeamSqlBackend be, Beamable table, FieldsFulfillConstraint (BeamSqlBackendCanSerialize be) table) => [table Identity] -> SqlInsertValues be (table (QExpr be s)) -- | Build a SqlInsertValues from series of expressions in tables insertExpressions :: (BeamSqlBackend be, Beamable table) => (forall s'. () => [table (QExpr be s')]) -> SqlInsertValues be (table (QExpr be s)) -- | Run a SqlInsert in a MonadBeam runInsert :: (BeamSqlBackend be, MonadBeam be m) => SqlInsert be table -> m () -- | Generate a SqlInsert given a table and a source of values. insert :: (BeamSqlBackend be, ProjectibleWithPredicate AnyType () Text (table (QField s))) => DatabaseEntity be db (TableEntity table) -> SqlInsertValues be (table (QExpr be s)) -> SqlInsert be table -- | Generate a SqlInsert over only certain fields of a table insertOnly :: (BeamSqlBackend be, ProjectibleWithPredicate AnyType () Text (QExprToField r)) => DatabaseEntity be db (TableEntity table) -> (table (QField s) -> QExprToField r) -> SqlInsertValues be r -> SqlInsert be table -- | Use a special debug syntax to print out an ANSI Standard -- SELECT statement that may be generated for a given Q. dumpSqlSelect :: Projectible (MockSqlBackend SqlSyntaxBuilder) res => Q (MockSqlBackend SqlSyntaxBuilder) db QBaseScope res -> IO () -- | Convenience function to generate a SqlSelect that looks up a -- table row given a primary key. lookup_ :: (Database be db, Table table, BeamSqlBackend be, HasQBuilder be, SqlValableTable be (PrimaryKey table), HasTableEquality be (PrimaryKey table)) => DatabaseEntity be db (TableEntity table) -> PrimaryKey table Identity -> SqlSelect be (table Identity) -- | Create a SqlSelect for a query which may have common table -- expressions. See the documentation of With for more details. selectWith :: (BeamSqlBackend be, BeamSql99CommonTableExpressionBackend be, HasQBuilder be, Projectible be res) => With be db (Q be db QBaseScope res) -> SqlSelect be (QExprToIdentity res) -- | Build a SqlSelect for the given Q. select :: (BeamSqlBackend be, HasQBuilder be, Projectible be res) => Q be db QBaseScope res -> SqlSelect be (QExprToIdentity res) data QBaseScope -- | A version of the table where each field is a QGenExpr type QGenExprTable ctxt be s (tbl :: Type -> Type -> Type) = tbl QGenExpr ctxt be s type QExprTable be s (tbl :: Type -> Type -> Type) = QGenExprTable QValueContext be s tbl -- | Represents a select statement in the given backend, returning rows of -- type a. newtype SqlSelect be a SqlSelect :: BeamSqlBackendSelectSyntax be -> SqlSelect be a -- | Represents a SQL INSERT command that has not yet been run data SqlInsert be (table :: Type -> Type -> Type) SqlInsert :: !TableSettings table -> !BeamSqlBackendInsertSyntax be -> SqlInsert be SqlInsertNoRows :: SqlInsert be -- | Represents a source of values that can be inserted into a table shaped -- like tbl. data SqlInsertValues be proj SqlInsertValues :: BeamSqlBackendInsertValuesSyntax be -> SqlInsertValues be proj SqlInsertValuesEmpty :: SqlInsertValues be proj -- | Represents a SQL UPDATE statement for the given -- table. data SqlUpdate be (table :: Type -> Type -> Type) SqlUpdate :: !TableSettings table -> !BeamSqlBackendUpdateSyntax be -> SqlUpdate be SqlIdentityUpdate :: SqlUpdate be -- | Represents a SQL DELETE statement for the given -- table data SqlDelete be (table :: Type -> Type -> Type) SqlDelete :: !TableSettings table -> !BeamSqlBackendDeleteSyntax be -> SqlDelete be regrSXY_ :: (Num a, Floating b, BeamSqlBackend be, BeamSqlT621Backend be) => QExpr be s a -> QExpr be s a -> QExpr be s b regrSYY_ :: (Num a, Floating b, BeamSqlBackend be, BeamSqlT621Backend be) => QExpr be s a -> QExpr be s a -> QExpr be s b regrSXX_ :: (Num a, Floating b, BeamSqlBackend be, BeamSqlT621Backend be) => QExpr be s a -> QExpr be s a -> QExpr be s b regrAvgX_ :: (Num a, Floating b, BeamSqlBackend be, BeamSqlT621Backend be) => QExpr be s a -> QExpr be s a -> QExpr be s b regrAvgY_ :: (Num a, Floating b, BeamSqlBackend be, BeamSqlT621Backend be) => QExpr be s a -> QExpr be s a -> QExpr be s b regrRSquared_ :: (Num a, Floating b, BeamSqlBackend be, BeamSqlT621Backend be) => QExpr be s a -> QExpr be s a -> QExpr be s b regrCount_ :: (Num a, Floating b, BeamSqlBackend be, BeamSqlT621Backend be) => QExpr be s a -> QExpr be s a -> QExpr be s b regrIntercept_ :: (Num a, Floating b, BeamSqlBackend be, BeamSqlT621Backend be) => QExpr be s a -> QExpr be s a -> QExpr be s b regrSlope_ :: (Num a, Floating b, BeamSqlBackend be, BeamSqlT621Backend be) => QExpr be s a -> QExpr be s a -> QExpr be s b corr_ :: (Num a, Floating b, BeamSqlBackend be, BeamSqlT621Backend be) => QExpr be s a -> QExpr be s a -> QExpr be s b covarSamp_ :: (Num a, Floating b, BeamSqlBackend be, BeamSqlT621Backend be) => QExpr be s a -> QExpr be s a -> QExpr be s b covarPop_ :: (Num a, Floating b, BeamSqlBackend be, BeamSqlT621Backend be) => QExpr be s a -> QExpr be s a -> QExpr be s b regrSXYOver_ :: (Num a, Floating b, BeamSqlBackend be, BeamSqlT621Backend be) => Maybe (BeamSqlBackendAggregationQuantifierSyntax be) -> QExpr be s a -> QExpr be s a -> QExpr be s b regrSYYOver_ :: (Num a, Floating b, BeamSqlBackend be, BeamSqlT621Backend be) => Maybe (BeamSqlBackendAggregationQuantifierSyntax be) -> QExpr be s a -> QExpr be s a -> QExpr be s b regrSXXOver_ :: (Num a, Floating b, BeamSqlBackend be, BeamSqlT621Backend be) => Maybe (BeamSqlBackendAggregationQuantifierSyntax be) -> QExpr be s a -> QExpr be s a -> QExpr be s b regrAvgXOver_ :: (Num a, Floating b, BeamSqlBackend be, BeamSqlT621Backend be) => Maybe (BeamSqlBackendAggregationQuantifierSyntax be) -> QExpr be s a -> QExpr be s a -> QExpr be s b regrAvgYOver_ :: (Num a, Floating b, BeamSqlBackend be, BeamSqlT621Backend be) => Maybe (BeamSqlBackendAggregationQuantifierSyntax be) -> QExpr be s a -> QExpr be s a -> QExpr be s b regrRSquaredOver_ :: (Num a, Floating b, BeamSqlBackend be, BeamSqlT621Backend be) => Maybe (BeamSqlBackendAggregationQuantifierSyntax be) -> QExpr be s a -> QExpr be s a -> QExpr be s b regrCountOver_ :: (Num a, Floating b, BeamSqlBackend be, BeamSqlT621Backend be) => Maybe (BeamSqlBackendAggregationQuantifierSyntax be) -> QExpr be s a -> QExpr be s a -> QExpr be s b regrInterceptOver_ :: (Num a, Floating b, BeamSqlBackend be, BeamSqlT621Backend be) => Maybe (BeamSqlBackendAggregationQuantifierSyntax be) -> QExpr be s a -> QExpr be s a -> QExpr be s b regrSlopeOver_ :: (Num a, Floating b, BeamSqlBackend be, BeamSqlT621Backend be) => Maybe (BeamSqlBackendAggregationQuantifierSyntax be) -> QExpr be s a -> QExpr be s a -> QExpr be s b corrOver_ :: (Num a, Floating b, BeamSqlBackend be, BeamSqlT621Backend be) => Maybe (BeamSqlBackendAggregationQuantifierSyntax be) -> QExpr be s a -> QExpr be s a -> QExpr be s b covarSampOver_ :: (Num a, Floating b, BeamSqlBackend be, BeamSqlT621Backend be) => Maybe (BeamSqlBackendAggregationQuantifierSyntax be) -> QExpr be s a -> QExpr be s a -> QExpr be s b covarPopOver_ :: (Num a, Floating b, BeamSqlBackend be, BeamSqlT621Backend be) => Maybe (BeamSqlBackendAggregationQuantifierSyntax be) -> QExpr be s a -> QExpr be s a -> QExpr be s b varSamp_ :: (Num a, Floating b, BeamSqlBackend be, BeamSqlT621Backend be) => QExpr be s a -> QAgg be s b varPop_ :: (Num a, Floating b, BeamSqlBackend be, BeamSqlT621Backend be) => QExpr be s a -> QAgg be s b stddevSamp_ :: (Num a, Floating b, BeamSqlBackend be, BeamSqlT621Backend be) => QExpr be s a -> QAgg be s b stddevPop_ :: (Num a, Floating b, BeamSqlBackend be, BeamSqlT621Backend be) => QExpr be s a -> QAgg be s b varSampOver_ :: (Num a, Floating b, BeamSqlBackend be, BeamSqlT621Backend be) => Maybe (BeamSqlBackendAggregationQuantifierSyntax be) -> QExpr be s a -> QAgg be s b varPopOver_ :: (Num a, Floating b, BeamSqlBackend be, BeamSqlT621Backend be) => Maybe (BeamSqlBackendAggregationQuantifierSyntax be) -> QExpr be s a -> QAgg be s b stddevSampOver_ :: (Num a, Floating b, BeamSqlBackend be, BeamSqlT621Backend be) => Maybe (BeamSqlBackendAggregationQuantifierSyntax be) -> QExpr be s a -> QAgg be s b stddevPopOver_ :: (Num a, Floating b, BeamSqlBackend be, BeamSqlT621Backend be) => Maybe (BeamSqlBackendAggregationQuantifierSyntax be) -> QExpr be s a -> QAgg be s b (**.) :: (Floating a, BeamSqlBackend be, BeamSqlT621Backend be) => QGenExpr ctxt be s a -> QGenExpr ctxt be s a -> QGenExpr ctxt be s a infixr 8 **. floor_ :: (RealFrac a, Integral b, BeamSqlBackend be, BeamSqlT621Backend be) => QGenExpr ctxt be s a -> QGenExpr ctxt be s b ceiling_ :: (RealFrac a, Integral b, BeamSqlBackend be, BeamSqlT621Backend be) => QGenExpr ctxt be s a -> QGenExpr ctxt be s b sqrt_ :: (Floating a, BeamSqlBackend be, BeamSqlT621Backend be) => QGenExpr ctxt be s a -> QGenExpr ctxt be s a exp_ :: (Floating a, BeamSqlBackend be, BeamSqlT621Backend be) => QGenExpr ctxt be s a -> QGenExpr ctxt be s a ln_ :: (Floating a, BeamSqlBackend be, BeamSqlT621Backend be) => QGenExpr ctxt be s a -> QGenExpr ctxt be s a nthValue_ :: (BeamSqlBackend be, BeamSqlT618Backend be) => QExpr be s a -> QExpr be s Int -> QAgg be s a lastValue_ :: (BeamSqlBackend be, BeamSqlT616Backend be) => QExpr be s a -> QAgg be s a firstValue_ :: (BeamSqlBackend be, BeamSqlT616Backend be) => QExpr be s a -> QAgg be s a lagWithDefault_ :: (BeamSqlBackend be, BeamSqlT615Backend be) => QExpr be s a -> QExpr be s Int -> QExpr be s a -> QAgg be s a leadWithDefault_ :: (BeamSqlBackend be, BeamSqlT615Backend be) => QExpr be s a -> QExpr be s Int -> QExpr be s a -> QAgg be s a lag_ :: (BeamSqlBackend be, BeamSqlT615Backend be) => QExpr be s a -> QExpr be s Int -> QAgg be s a lead_ :: (BeamSqlBackend be, BeamSqlT615Backend be) => QExpr be s a -> QExpr be s Int -> QAgg be s a lag1_ :: (BeamSqlBackend be, BeamSqlT615Backend be) => QExpr be s a -> QAgg be s a lead1_ :: (BeamSqlBackend be, BeamSqlT615Backend be) => QExpr be s a -> QAgg be s a ntile_ :: (BeamSqlBackend be, BeamSqlT614Backend be) => QExpr be s Int -> QAgg be s a -- | SQL99 ANY(ALL ..) function (but without the explicit ALL) any_ :: BeamSql99AggregationBackend be => QExpr be s SqlBool -> QAgg be s SqlBool -- | SQL99 SOME(ALL ..) function (but without the explicit ALL) some_ :: BeamSql99AggregationBackend be => QExpr be s SqlBool -> QAgg be s SqlBool -- | SQL99 EVERY(ALL ..) function (but without the explicit ALL) every_ :: BeamSql99AggregationBackend be => QExpr be s SqlBool -> QAgg be s SqlBool -- | Like filterWhere_ but accepting SqlBool. filterWhere_' :: BeamSqlT611Backend be => QAgg be s a -> QExpr be s SqlBool -> QAgg be s a -- | Support for FILTER (WHERE ...) syntax for aggregates. Part of SQL2003 -- Elementary OLAP operations feature (T611). -- -- See filterWhere_' for a version that accepts SqlBool. filterWhere_ :: BeamSqlT611Backend be => QAgg be s a -> QExpr be s Bool -> QAgg be s a -- | SQL EVERY, SOME, and ANY aggregates. -- Operates over SqlBool only, as the result can be NULL, -- even if all inputs are known (no input rows). anyOver_ :: BeamSql99AggregationBackend be => Maybe (BeamSqlBackendAggregationQuantifierSyntax be) -> QExpr be s SqlBool -> QAgg be s SqlBool -- | SQL EVERY, SOME, and ANY aggregates. -- Operates over SqlBool only, as the result can be NULL, -- even if all inputs are known (no input rows). someOver_ :: BeamSql99AggregationBackend be => Maybe (BeamSqlBackendAggregationQuantifierSyntax be) -> QExpr be s SqlBool -> QAgg be s SqlBool -- | SQL EVERY, SOME, and ANY aggregates. -- Operates over SqlBool only, as the result can be NULL, -- even if all inputs are known (no input rows). everyOver_ :: BeamSql99AggregationBackend be => Maybe (BeamSqlBackendAggregationQuantifierSyntax be) -> QExpr be s SqlBool -> QAgg be s SqlBool countOver_ :: (BeamSqlBackend be, Integral b) => Maybe (BeamSqlBackendAggregationQuantifierSyntax be) -> QExpr be s a -> QAgg be s b sumOver_ :: (BeamSqlBackend be, Num a) => Maybe (BeamSqlBackendAggregationQuantifierSyntax be) -> QExpr be s a -> QAgg be s (Maybe a) avgOver_ :: (BeamSqlBackend be, Num a) => Maybe (BeamSqlBackendAggregationQuantifierSyntax be) -> QExpr be s a -> QAgg be s (Maybe a) maxOver_ :: BeamSqlBackend be => Maybe (BeamSqlBackendAggregationQuantifierSyntax be) -> QExpr be s a -> QAgg be s (Maybe a) minOver_ :: BeamSqlBackend be => Maybe (BeamSqlBackendAggregationQuantifierSyntax be) -> QExpr be s a -> QAgg be s (Maybe a) -- | SQL2003 RANK function (Requires T611 Elementary OLAP -- operations support) rank_ :: BeamSqlT611Backend be => QAgg be s Int -- | SQL2003 ROW_NUMBER function rowNumber_ :: BeamSql2003ExpressionBackend be => QAgg be s Int -- | SQL2003 DENSE_RANK function (Requires T612 Advanced OLAP -- operations support) denseRank_ :: BeamSqlT612Backend be => QAgg be s Int -- | SQL2003 PERCENT_RANK function (Requires T612 Advanced OLAP -- operations support) percentRank_ :: BeamSqlT612Backend be => QAgg be s Double -- | SQL2003 CUME_DIST function (Requires T612 Advanced OLAP -- operations support) cumeDist_ :: BeamSqlT612Backend be => QAgg be s Double -- | SQL COUNT(ALL ..) function (but without the explicit ALL) count_ :: (BeamSqlBackend be, Integral b) => QExpr be s a -> QAgg be s b -- | SQL COUNT(*) function countAll_ :: BeamSqlBackend be => QAgg be s Int -- | SQL SUM(ALL ..) function (but without the explicit ALL) sum_ :: (BeamSqlBackend be, Num a) => QExpr be s a -> QAgg be s (Maybe a) -- | SQL AVG(ALL ..) function (but without the explicit ALL) avg_ :: (BeamSqlBackend be, Num a) => QExpr be s a -> QAgg be s (Maybe a) -- | SQL MAX(ALL ..) function (but without the explicit ALL) max_ :: BeamSqlBackend be => QExpr be s a -> QAgg be s (Maybe a) -- | SQL MIN(ALL ..) function (but without the explicit ALL) min_ :: BeamSqlBackend be => QExpr be s a -> QAgg be s (Maybe a) -- | Compute an aggregate over all values in a group. Corresponds to the -- AGG(ALL ..) syntax. Note that ALL is the default for -- most aggregations, so you don't normally explicitly specify -- ALL. However, if you need to, you can use this function. To -- be explicit about quantification in the beam query DSL, but not -- produce an explicit ALL, use allInGroup_. -- allInGroup_ has the same semantic meaning, but does not produce -- an explicit ALL. allInGroupExplicitly_ :: IsSql92AggregationSetQuantifierSyntax s => Maybe s -- | Compute an aggregate only over distinct values in a group. Corresponds -- to the AGG(DISTINCT ..) syntax. distinctInGroup_ :: IsSql92AggregationSetQuantifierSyntax s => Maybe s -- | Compute an aggregate over all values in a group. Corresponds -- semantically to the AGG(ALL ..) syntax, but doesn't produce -- an explicit ALL. To produce ALL expicitly, see -- allInGroupExplicitly_. allInGroup_ :: IsSql92AggregationSetQuantifierSyntax s => Maybe s -- | Compute an aggregate over a query. -- -- The supplied aggregate projection should return an aggregate -- expression (an expression containing an aggregate function such as -- count_, sum_, countAll_, etc), a grouping key -- (specified with the group_ function), or a combination of -- tuples of the above. -- -- Appropriate instances are provided up to 8-tuples. -- -- Semantically, all grouping expressions in the projection will be added -- to a SQL GROUP BY clause and all aggregate expressions will -- be computed. -- -- The return value will be the type of the aggregate projection, but -- transformed to be in the normal value context (i.e., everything will -- become QGenExprs). -- -- For usage examples, see the manual. aggregate_ :: (BeamSqlBackend be, Aggregable be a, Projectible be r, Projectible be a, ContextRewritable a, ThreadRewritable (QNested s) (WithRewrittenContext a QValueContext)) => (r -> a) -> Q be db (QNested s) r -> Q be db s (WithRewrittenThread (QNested s) s (WithRewrittenContext a QValueContext)) -- | Type class for grouping keys. expr is the type of the -- grouping key after projection. grouped is the type of the -- grouping key in the aggregate expression (usually something that -- contains QGenExprs in the QGroupingContext). class QGroupable expr grouped | expr -> grouped, grouped -> expr group_ :: QGroupable expr grouped => expr -> grouped -- | Used to define many-to-many relationships with additional data. Takes -- the join table and two key extraction functions from that table to the -- related tables. Also takes two Qs representing the table -- sources to relate. -- -- See the manual for more indformation. manyToManyPassthrough_ :: (Database be db, Table joinThrough, Table left, Table right, BeamSqlBackend be, SqlEq (QExpr be s) (PrimaryKey left (QExpr be s)), SqlEq (QExpr be s) (PrimaryKey right (QExpr be s))) => DatabaseEntity be db (TableEntity joinThrough) -> (joinThrough (QExpr be s) -> PrimaryKey left (QExpr be s)) -> (joinThrough (QExpr be s) -> PrimaryKey right (QExpr be s)) -> Q be db s (left (QExpr be s)) -> Q be db s (right (QExpr be s)) -> Q be db s (joinThrough (QExpr be s), left (QExpr be s), right (QExpr be s)) -- | Used to define many-to-many relationships without any additional data. -- Takes the join table and two key extraction functions from that table -- to the related tables. Also takes two Qs representing the table -- sources to relate. -- -- See the manual for more indformation. manyToMany_ :: (Database be db, Table joinThrough, Table left, Table right, BeamSqlBackend be, SqlEq (QExpr be s) (PrimaryKey left (QExpr be s)), SqlEq (QExpr be s) (PrimaryKey right (QExpr be s))) => DatabaseEntity be db (TableEntity joinThrough) -> (joinThrough (QExpr be s) -> PrimaryKey left (QExpr be s)) -> (joinThrough (QExpr be s) -> PrimaryKey right (QExpr be s)) -> Q be db s (left (QExpr be s)) -> Q be db s (right (QExpr be s)) -> Q be db s (left (QExpr be s), right (QExpr be s)) -- | Used to define one-to-many (or one-to-one) relationships with a -- nullable foreign key. Takes the table to fetch, a way to extract the -- foreign key from that table, and the table to relate to. oneToMaybe_ :: (BeamSqlBackend be, Database be db, Table tbl, Table rel, HasTableEqualityNullable be (PrimaryKey tbl)) => DatabaseEntity be db (TableEntity rel) -> (rel (QExpr be s) -> PrimaryKey tbl (Nullable (QExpr be s))) -> tbl (QExpr be s) -> Q be db s (rel (Nullable (QExpr be s))) -- | Used to define one-to-many (or one-to-one) relationships with a -- nullable foreign key. Takes the table to fetch, a way to extract the -- foreign key from that table, and the table to relate to. oneToManyOptional_ :: (BeamSqlBackend be, Database be db, Table tbl, Table rel, HasTableEqualityNullable be (PrimaryKey tbl)) => DatabaseEntity be db (TableEntity rel) -> (rel (QExpr be s) -> PrimaryKey tbl (Nullable (QExpr be s))) -> tbl (QExpr be s) -> Q be db s (rel (Nullable (QExpr be s))) -- | Used to define one-to-many (or one-to-one) relationships. Takes the -- table to fetch, a way to extract the foreign key from that table, and -- the table to relate to. oneToOne_ :: (Database be db, BeamSqlBackend be, HasTableEquality be (PrimaryKey tbl), Table tbl, Table rel) => DatabaseEntity be db (TableEntity rel) -> (rel (QExpr be s) -> PrimaryKey tbl (QExpr be s)) -> tbl (QExpr be s) -> Q be db s (rel (QExpr be s)) -- | Used to define one-to-many (or one-to-one) relationships. Takes the -- table to fetch, a way to extract the foreign key from that table, and -- the table to relate to. oneToMany_ :: (Database be db, BeamSqlBackend be, HasTableEquality be (PrimaryKey tbl), Table tbl, Table rel) => DatabaseEntity be db (TableEntity rel) -> (rel (QExpr be s) -> PrimaryKey tbl (QExpr be s)) -> tbl (QExpr be s) -> Q be db s (rel (QExpr be s)) -- | Synonym of OneToMany. Useful for giving more meaningful types, -- when the relationship is meant to be one-to-one. type OneToOne be (db :: Type -> Type -> Type) s (one :: Type -> Type -> Type) (many :: Type -> Type -> Type) = OneToMany be db s one many -- | Convenience type to declare one-to-many relationships. See the manual -- section on relationships for more information type OneToMany be (db :: Type -> Type -> Type) s (one :: Type -> Type -> Type) (many :: Type -> Type -> Type) = BeamSqlBackend be -> BeamSqlBackendCanSerialize be Bool -> one QExpr be s -> Q be db s many QExpr be s -- | Synonym of OneToManyOptional. Useful for giving more meaningful -- types, when the relationship is meant to be one-to-one. type OneToMaybe be (db :: Type -> Type -> Type) s (tbl :: Type -> Type -> Type) (rel :: Type -> Type -> Type) = OneToManyOptional be db s tbl rel -- | Convenience type to declare one-to-many relationships with a nullable -- foreign key. See the manual section on relationships for more -- information type OneToManyOptional be (db :: Type -> Type -> Type) s (tbl :: Type -> Type -> Type) (rel :: Type -> Type -> Type) = BeamSqlBackend be -> BeamSqlBackendCanSerialize be Bool -> BeamSqlBackendCanSerialize be SqlNull -> tbl QExpr be s -> Q be db s rel Nullable QExpr be s -- | Convenience type to declare many-to-many relationships. See the manual -- section on relationships for more information type ManyToMany be (db :: Type -> Type -> Type) (left :: Type -> Type -> Type) (right :: Type -> Type -> Type) = forall s. (BeamSqlBackend be, SqlEq QExpr be s PrimaryKey left QExpr be s, SqlEq QExpr be s PrimaryKey right QExpr be s) => Q be db s left QExpr be s -> Q be db s right QExpr be s -> Q be db s (left QExpr be s, right QExpr be s) -- | Convenience type to declare many-to-many relationships with additional -- data. See the manual section on relationships for more -- information type ManyToManyThrough be (db :: Type -> Type -> Type) (through :: Type -> Type -> Type) (left :: Type -> Type -> Type) (right :: Type -> Type -> Type) = forall s. (BeamSqlBackend be, SqlEq QExpr be s PrimaryKey left QExpr be s, SqlEq QExpr be s PrimaryKey right QExpr be s) => Q be db s left QExpr be s -> Q be db s right QExpr be s -> Q be db s (through QExpr be s, left QExpr be s, right QExpr be s) (<|>.) :: (SqlJustable a (QGenExpr ctxt syntax s y), SqlDeconstructMaybe syntax (QGenExpr ctxt syntax s y) a s) => QGenExpr ctxt syntax s y -> QGenExpr ctxt syntax s y -> QGenExpr ctxt syntax s y infixl 3 <|>. -- | Converta a Maybe value to a concrete value, by suppling a -- default fromMaybe_ :: BeamSqlBackend be => QGenExpr ctxt be s a -> QGenExpr ctxt be s (Maybe a) -> QGenExpr ctxt be s a -- | SQL COALESCE support coalesce_ :: BeamSqlBackend be => [QGenExpr ctxt be s (Maybe a)] -> QGenExpr ctxt be s a -> QGenExpr ctxt be s a if_ :: BeamSqlBackend be => [QIfCond context be s a] -> QIfElse context be s a -> QGenExpr context be s a else_ :: () => QGenExpr context be s a -> QIfElse context be s a then_' :: () => QGenExpr context be s SqlBool -> QGenExpr context be s a -> QIfCond context be s a then_ :: () => QGenExpr context be s Bool -> QGenExpr context be s a -> QIfCond context be s a -- | Produce a QOrd corresponding to a SQL DESC ordering desc_ :: BeamSqlBackend be => QExpr be s a -> QOrd be s a -- | Produce a QOrd corresponding to a SQL ASC ordering asc_ :: BeamSqlBackend be => QExpr be s a -> QOrd be s a nullsLast_ :: IsSql2003OrderingElementaryOLAPOperationsSyntax (BeamSqlBackendOrderingSyntax be) => QOrd be s a -> QOrd be s a nullsFirst_ :: IsSql2003OrderingElementaryOLAPOperationsSyntax (BeamSqlBackendOrderingSyntax be) => QOrd be s a -> QOrd be s a -- | Order by the given expressions. The return type of the ordering key -- should either be the result of asc_ or desc_ (or another -- ordering QOrd generated by a backend-specific ordering) or an -- (possibly nested) tuple of results of the former. -- -- The manual section has more information. orderBy_ :: (Projectible be a, SqlOrderable be ordering, ThreadRewritable (QNested s) a) => (a -> ordering) -> Q be db (QNested s) a -> Q be db s (WithRewrittenThread (QNested s) s a) -- | Compute a query over windows. -- -- The first function builds window frames using the frame_, -- partitionBy_, etc functions. The return type can be a single -- frame, tuples of frame, or any arbitrarily nested tuple of the above. -- Instances up to 8-tuples are provided. -- -- The second function builds the resulting projection using the result -- of the subquery as well as the window frames built in the first -- function. In this function, window expressions can be included in the -- output using the over_ function. withWindow_ :: (ProjectibleWithPredicate WindowFrameContext be (WithExprContext (BeamSqlBackendWindowFrameSyntax' be)) window, Projectible be r, Projectible be a, ContextRewritable a, ThreadRewritable (QNested s) (WithRewrittenContext a QValueContext)) => (r -> window) -> (r -> window -> a) -> Q be db (QNested s) r -> Q be db s (WithRewrittenThread (QNested s) s (WithRewrittenContext a QValueContext)) -- | Produce a window expression given an aggregate function and a window. over_ :: BeamSql2003ExpressionBackend be => QAgg be s a -> QWindow be s -> QWindowExpr be s a -- | Specify a window frame with all the options frame_ :: (BeamSql2003ExpressionBackend be, SqlOrderable be ordering, Projectible be partition) => Maybe partition -> Maybe ordering -> QFrameBounds be -> QWindow be s orderPartitionBy_ :: () => partition -> Maybe partition partitionBy_ :: () => partition -> Maybe partition noOrder_ :: () => Maybe (QOrd be s Int) noPartition_ :: () => Maybe (QExpr be s Int) nrows_ :: BeamSql2003ExpressionBackend be => Int -> QFrameBound be unbounded_ :: BeamSql2003ExpressionBackend be => QFrameBound be bounds_ :: BeamSql2003ExpressionBackend be => QFrameBound be -> Maybe (QFrameBound be) -> QFrameBounds be fromBound_ :: BeamSql2003ExpressionBackend be => QFrameBound be -> QFrameBounds be noBounds_ :: () => QFrameBounds be default_ :: BeamSqlBackend be => QGenExpr ctxt be s a -- | Convenience function that allows you to use type applications to -- specify the result of a QGenExpr. -- -- Useful to disambiguate the types of QGenExprs without having to -- provide a complete type signature. As an example, the -- countAll_ aggregate can return a result of any -- Integral type. Without further constraints, the type is -- ambiguous. You can use as_ to disambiguate the return type. -- -- For example, this is ambiguous -- --
-- aggregate_ (\_ -> countAll_) .. ---- -- But this is not -- --
-- aggregate_ (\_ -> as_ @Int countAll_) .. --as_ :: () => QGenExpr ctxt be s a -> QGenExpr ctxt be s a -- | SQL EXCEPT ALL operator exceptAll_ :: (BeamSqlBackend be, Projectible be a, ThreadRewritable (QNested s) a) => Q be db (QNested s) a -> Q be db (QNested s) a -> Q be db s (WithRewrittenThread (QNested s) s a) -- | SQL EXCEPT operator except_ :: (BeamSqlBackend be, Projectible be a, ThreadRewritable (QNested s) a) => Q be db (QNested s) a -> Q be db (QNested s) a -> Q be db s (WithRewrittenThread (QNested s) s a) -- | SQL INTERSECT ALL operator intersectAll_ :: (BeamSqlBackend be, Projectible be a, ThreadRewritable (QNested s) a) => Q be db (QNested s) a -> Q be db (QNested s) a -> Q be db s (WithRewrittenThread (QNested s) s a) -- | SQL INTERSECT operator intersect_ :: (BeamSqlBackend be, Projectible be a, ThreadRewritable (QNested s) a) => Q be db (QNested s) a -> Q be db (QNested s) a -> Q be db s (WithRewrittenThread (QNested s) s a) -- | SQL UNION ALL operator unionAll_ :: (BeamSqlBackend be, Projectible be a, ThreadRewritable (QNested s) a) => Q be db (QNested s) a -> Q be db (QNested s) a -> Q be db s (WithRewrittenThread (QNested s) s a) -- | SQL UNION operator union_ :: (BeamSqlBackend be, Projectible be a, ThreadRewritable (QNested s) a) => Q be db (QNested s) a -> Q be db (QNested s) a -> Q be db s (WithRewrittenThread (QNested s) s a) -- | Extract an expression representing the current (non-UPDATEd) value of -- a QField current_ :: BeamSqlBackend be => QField s ty -> QExpr be s ty -- | SQL TRIM function trim_ :: (BeamSqlBackendIsString be text, BeamSqlBackend be) => QGenExpr context be s text -> QGenExpr context be s text -- | SQL UPPER function upper_ :: (BeamSqlBackendIsString be text, BeamSqlBackend be) => QGenExpr context be s text -> QGenExpr context be s text -- | SQL LOWER function lower_ :: (BeamSqlBackendIsString be text, BeamSqlBackend be) => QGenExpr context be s text -> QGenExpr context be s text -- | SQL POSITION(.. IN ..) function position_ :: (BeamSqlBackendIsString be text, BeamSqlBackend be, Integral b) => QExpr be s text -> QExpr be s text -> QExpr be s b -- | SQL CURRENT_TIMESTAMP function currentTimestamp_ :: BeamSqlBackend be => QGenExpr ctxt be s LocalTime -- | SQL BIT_LENGTH function bitLength_ :: BeamSqlBackend be => QGenExpr context be s SqlBitString -> QGenExpr context be s Int -- | SQL OCTET_LENGTH function octetLength_ :: (BeamSqlBackend be, BeamSqlBackendIsString be text) => QGenExpr context be s text -> QGenExpr context be s Int -- | SQL CHAR_LENGTH function charLength_ :: (BeamSqlBackend be, BeamSqlBackendIsString be text) => QGenExpr context be s text -> QGenExpr context be s Int -- | Project the (presumably) singular result of the given query as an -- expression subquery_ :: (BeamSqlBackend be, HasQBuilder be, Projectible be (QExpr be s a)) => Q be db s (QExpr be s a) -> QGenExpr ctxt be s a -- | Use the SQL99 DISTINCT operator to determine if the given -- query produces a distinct result distinct_ :: (BeamSqlBackend be, BeamSql99ExpressionBackend be, HasQBuilder be, Projectible be a) => Q be db s a -> QExpr be s Bool -- | Use the SQL UNIQUE operator to determine if the given query -- produces a unique result unique_ :: (BeamSqlBackend be, HasQBuilder be, Projectible be a) => Q be db s a -> QExpr be s Bool -- | Use the SQL EXISTS operator to determine if the given query -- returns any results exists_ :: (BeamSqlBackend be, HasQBuilder be, Projectible be a) => Q be db s a -> QExpr be s Bool -- | Drop the first offset' results. offset_ :: (Projectible be a, ThreadRewritable (QNested s) a) => Integer -> Q be db (QNested s) a -> Q be db s (WithRewrittenThread (QNested s) s a) -- | Limit the number of results returned by a query. limit_ :: (Projectible be a, ThreadRewritable (QNested s) a) => Integer -> Q be db (QNested s) a -> Q be db s (WithRewrittenThread (QNested s) s a) -- | Only return distinct values from a query nub_ :: (BeamSqlBackend be, Projectible be r) => Q be db s r -> Q be db s r -- | Generate an appropriate boolean QGenExpr comparing the given -- foreign key to the given table. Useful for creating join conditions. references_ :: (Table t, BeamSqlBackend be, HasTableEquality be (PrimaryKey t)) => PrimaryKey t (QGenExpr ctxt be s) -> t (QGenExpr ctxt be s) -> QGenExpr ctxt be s Bool -- | Introduce all entries of the given table which for which the -- expression (which can depend on the queried table returns true) relatedBy_' :: (Database be db, Table rel, BeamSqlBackend be) => DatabaseEntity be db (TableEntity rel) -> (rel (QExpr be s) -> QExpr be s SqlBool) -> Q be db s (rel (QExpr be s)) -- | Introduce all entries of the given table which for which the -- expression (which can depend on the queried table returns true) relatedBy_ :: (Database be db, Table rel, BeamSqlBackend be) => DatabaseEntity be db (TableEntity rel) -> (rel (QExpr be s) -> QExpr be s Bool) -> Q be db s (rel (QExpr be s)) -- | Introduce all entries of the given table which are referenced by the -- given PrimaryKey related_ :: (Database be db, Table rel, BeamSqlBackend be, HasTableEquality be (PrimaryKey rel)) => DatabaseEntity be db (TableEntity rel) -> PrimaryKey rel (QExpr be s) -> Q be db s (rel (QExpr be s)) -- | Synonym for clause >>= x -> guard_' (mkExpr x)>> -- pure x. Use filter_ for comparisons with Bool filter_' :: BeamSqlBackend be => (r -> QExpr be s SqlBool) -> Q be db s r -> Q be db s r -- | Synonym for clause >>= x -> guard_ (mkExpr x)>> -- pure x. Use filter_' for comparisons with SqlBool filter_ :: BeamSqlBackend be => (r -> QExpr be s Bool) -> Q be db s r -> Q be db s r -- | Only allow results for which the QGenExpr yields TRUE. -- -- This function operates over SqlBool, which are like haskell -- Bools, except for the special UNKNOWN value that -- occurs when comparisons include NULL. For a version that -- operates over known non-NULL booleans, see guard_. guard_' :: BeamSqlBackend be => QExpr be s SqlBool -> Q be db s () -- | Only allow results for which the QGenExpr yields True. -- For a version that operates over possibly NULL -- SqlBools, see guard_'. guard_ :: BeamSqlBackend be => QExpr be s Bool -> Q be db s () subselect_ :: (ThreadRewritable (QNested s) r, Projectible be r) => Q be db (QNested s) r -> Q be db s (WithRewrittenThread (QNested s) s r) -- | Like leftJoin_, but accepts an ON clause returning -- SqlBool. leftJoin_' :: (BeamSqlBackend be, Projectible be r, ThreadRewritable (QNested s) r, Retaggable (QExpr be s) (WithRewrittenThread (QNested s) s r)) => Q be db (QNested s) r -> (WithRewrittenThread (QNested s) s r -> QExpr be s SqlBool) -> Q be db s (Retag Nullable (WithRewrittenThread (QNested s) s r)) -- | Introduce a table using a left join. The ON clause is required -- here.Because this is not an inner join, the resulting table is made -- nullable. This means that each field that would normally have type -- 'QExpr x' will now have type 'QExpr (Maybe x)'. -- -- The ON condition given must return Bool. For a version -- that accepts an ON condition returning SqlBool, see -- leftJoin_'. leftJoin_ :: (BeamSqlBackend be, Projectible be r, ThreadRewritable (QNested s) r, Retaggable (QExpr be s) (WithRewrittenThread (QNested s) s r)) => Q be db (QNested s) r -> (WithRewrittenThread (QNested s) s r -> QExpr be s Bool) -> Q be db s (Retag Nullable (WithRewrittenThread (QNested s) s r)) -- | Like outerJoin_, but accepting SqlBool. Pairs of rows -- for which the join condition is unknown are considered to be -- unrelated, by SQL compliant databases at least. outerJoin_' :: (BeamSqlBackend be, BeamSqlBackendSupportsOuterJoin be, Projectible be a, Projectible be b, ThreadRewritable (QNested s) a, ThreadRewritable (QNested s) b, Retaggable (QExpr be s) (WithRewrittenThread (QNested s) s a), Retaggable (QExpr be s) (WithRewrittenThread (QNested s) s b)) => Q be db (QNested s) a -> Q be db (QNested s) b -> ((WithRewrittenThread (QNested s) s a, WithRewrittenThread (QNested s) s b) -> QExpr be s SqlBool) -> Q be db s (Retag Nullable (WithRewrittenThread (QNested s) s a), Retag Nullable (WithRewrittenThread (QNested s) s b)) -- | Outer join. every row of each table, returning NULL for any -- row of either table for which the join condition finds no related -- rows. -- -- This expects a join expression returning Bool, for a version -- that accepts a SqlBool (a possibly UNKNOWN boolean, -- that maps more closely to the SQL standard), see outerJoin_' outerJoin_ :: (BeamSqlBackend be, BeamSqlBackendSupportsOuterJoin be, Projectible be a, Projectible be b, ThreadRewritable (QNested s) a, ThreadRewritable (QNested s) b, Retaggable (QExpr be s) (WithRewrittenThread (QNested s) s a), Retaggable (QExpr be s) (WithRewrittenThread (QNested s) s b)) => Q be db (QNested s) a -> Q be db (QNested s) b -> ((WithRewrittenThread (QNested s) s a, WithRewrittenThread (QNested s) s b) -> QExpr be s Bool) -> Q be db s (Retag Nullable (WithRewrittenThread (QNested s) s a), Retag Nullable (WithRewrittenThread (QNested s) s b)) -- | Introduce a table using a left join with no ON clause. Because this is -- not an inner join, the resulting table is made nullable. This means -- that each field that would normally have type 'QExpr x' will now have -- type 'QExpr (Maybe x)'. perhaps_ :: (Projectible be r, BeamSqlBackend be, ThreadRewritable (QNested s) r, Retaggable (QExpr be s) (WithRewrittenThread (QNested s) s r)) => Q be db (QNested s) r -> Q be db s (Retag Nullable (WithRewrittenThread (QNested s) s r)) -- | Like join_, but accepting an ON condition that returns -- SqlBool join_' :: (Database be db, Table table, BeamSqlBackend be) => DatabaseEntity be db (TableEntity table) -> (table (QExpr be s) -> QExpr be s SqlBool) -> Q be db s (table (QExpr be s)) -- | Introduce all entries of a table into the Q monad based on the -- given QExpr. The join condition is expected to return a Bool. -- For a version that takes SqlBool (a possibly UNKNOWN -- boolean, that maps more closely to the SQL standard), see -- join_'. join_ :: (Database be db, Table table, BeamSqlBackend be) => DatabaseEntity be db (TableEntity table) -> (table (QExpr be s) -> QExpr be s Bool) -> Q be db s (table (QExpr be s)) values_ :: (Projectible be a, BeamSqlBackend be) => [a] -> Q be db s a -- | Introduce all entries of a view into the Q monad allFromView_ :: (Database be db, Beamable table, BeamSqlBackend be) => DatabaseEntity be db (ViewEntity table) -> Q be db s (table (QExpr be s)) -- | Introduce all entries of a table into the Q monad all_ :: (Database be db, BeamSqlBackend be) => DatabaseEntity be db (TableEntity table) -> Q be db s (table (QExpr be s)) type family HaskellLiteralForQExpr x = (a :: Type) type SqlValableTable be (table :: Type -> Type -> Type) = (Beamable table, FieldsFulfillConstraint HasSqlValueSyntax BeamSqlBackendValueSyntax be table) class SqlValable a val_ :: SqlValable a => HaskellLiteralForQExpr a -> a class SqlOrderable be a | a -> be -- | Type class for things that can be nullable. This includes 'QExpr -- (Maybe a)', 'tbl (Nullable QExpr)', and 'PrimaryKey tbl (Nullable -- QExpr)' class SqlJustable a b | b -> a -- | Given something of type 'QExpr a', 'tbl QExpr', or 'PrimaryKey tbl -- QExpr', turn it into a 'QExpr (Maybe a)', 'tbl (Nullable QExpr)', or -- 'PrimaryKey t (Nullable QExpr)' respectively that contains the same -- values. just_ :: SqlJustable a b => a -> b -- | Return either a 'QExpr (Maybe x)' representing Nothing or a -- nullable Table or PrimaryKey filled with Nothing. nothing_ :: SqlJustable a b => b data QIfCond context be s a data QIfElse context be s a -- | Type class for anything which can be checked for null-ness. This -- includes 'QExpr (Maybe a)' as well as Tables or -- PrimaryKeys over 'Nullable QExpr'. class BeamSqlBackend be => SqlDeconstructMaybe be a nonNullA s | a s -> be, a -> nonNullA, a -> s, nonNullA -> s -- | Returns a QGenExpr that evaluates to true when the first -- argument is not null isJust_ :: SqlDeconstructMaybe be a nonNullA s => a -> QGenExpr ctxt be s Bool -- | Returns a QGenExpr that evaluates to true when the first -- argument is null isNothing_ :: SqlDeconstructMaybe be a nonNullA s => a -> QGenExpr ctxt be s Bool -- | Given an object (third argument) which may or may not be null, return -- the default value if null (first argument), or transform the value -- that could be null to yield the result of the expression (second -- argument) maybe_ :: SqlDeconstructMaybe be a nonNullA s => QGenExpr ctxt be s y -> (nonNullA -> QGenExpr ctxt be s y) -> a -> QGenExpr ctxt be s y reuse :: () => ReusableQ be db res -> Q be db s (WithRewrittenThread QAnyScope s res) selecting :: (BeamSql99CommonTableExpressionBackend be, HasQBuilder be, Projectible be res, ThreadRewritable QAnyScope res) => Q be db QAnyScope res -> With be db (ReusableQ be db res) data With be (db :: Type -> Type -> Type) a data ReusableQ be (db :: Type -> Type -> Type) res -- | Force a QGenExpr to be typed as an aggregate. Useful for -- defining custom aggregates for use in aggregate_. agg_ :: () => QAgg be s a -> QAgg be s a -- | Force a QGenExpr to be typed as a value expression (a -- QGenExpr). Useful for getting around type-inference errors with -- supplying the entire type. valueExpr_ :: () => QExpr be s a -> QExpr be s a -- | A type-class for expression syntaxes that can embed custom -- expressions. class (Monoid CustomSqlSyntax syntax, Semigroup CustomSqlSyntax syntax, IsString CustomSqlSyntax syntax) => IsCustomSqlSyntax syntax where { data family CustomSqlSyntax syntax :: Type; } -- | Given an arbitrary string-like expression, produce a syntax -- that represents the ByteString as a SQL expression. customExprSyntax :: IsCustomSqlSyntax syntax => CustomSqlSyntax syntax -> syntax -- | Given an arbitrary syntax, produce a string-like value that -- corresponds to how that syntax would look when rendered in the -- backend. renderSyntax :: IsCustomSqlSyntax syntax => syntax -> CustomSqlSyntax syntax class IsCustomExprFn fn res | res -> fn customExpr_ :: IsCustomExprFn fn res => fn -> res -- | Haskell requires DataTypes to match exactly. Use this function -- to convert a DataType that expects a concrete value to one -- expecting a Maybe maybeType :: () => DataType be a -> DataType be (Maybe a) -- | SQL99 array data types array :: (Typeable a, BeamSql99DataTypeBackend be) => DataType be a -> Int -> DataType be (Vector a) -- | SQL99 BLOB data type binaryLargeObject :: BeamSql99DataTypeBackend be => DataType be Text -- | SQL99 CLOB data type characterLargeObject :: BeamSql99DataTypeBackend be => DataType be Text -- | SQL99 BOOLEAN data type boolean :: BeamSql99DataTypeBackend be => DataType be Bool -- | SQL92 TIME data type time :: BeamSqlBackend be => Maybe Word -> DataType be TimeOfDay -- | SQL92 TIMESTAMP WITHOUT TIME ZONE data type timestamp :: BeamSqlBackend be => DataType be LocalTime -- | SQL92 TIMESTAMP WITH TIME ZONE data type timestamptz :: BeamSqlBackend be => DataType be LocalTime -- | SQL92 NUMERIC data type numeric :: BeamSqlBackend be => Maybe (Word, Maybe Word) -> DataType be Scientific -- | SQL92 DOUBLE data type double :: BeamSqlBackend be => DataType be Double -- | SQL92 NATIONAL CHARACTER data type nationalChar :: BeamSqlBackend be => Maybe Word -> DataType be Text -- | SQL92 NATIONAL CHARACTER VARYING data type nationalVarchar :: BeamSqlBackend be => Maybe Word -> DataType be Text -- | SQL92 VARCHAR data type varchar :: BeamSqlBackend be => Maybe Word -> DataType be Text -- | SQL92 CHAR data type char :: BeamSqlBackend be => Maybe Word -> DataType be Text -- | SQL92 DATE data type date :: BeamSqlBackend be => DataType be Day -- | SQL2003 Optional VARBINARY data type varbinary :: (BeamSqlBackend be, BeamSqlT021Backend be) => Maybe Word -> DataType be Integer -- | SQL2003 Optional BINARY data type binary :: (BeamSqlBackend be, BeamSqlT021Backend be) => Maybe Word -> DataType be Integer -- | SQL2008 Optional BIGINT data type bigint :: (BeamSqlBackend be, BeamSqlT071Backend be, Integral a) => DataType be a -- | SQL92 SMALLINT data type smallint :: (BeamSqlBackend be, Integral a) => DataType be a -- | SQL92 INTEGER data type int :: (BeamSqlBackend be, Integral a) => DataType be a -- | Cast a value to a specific data type, specified using DataType. -- -- Note: this may fail at run-time if the cast is invalid for a -- particular value cast_ :: BeamSqlBackend be => QGenExpr ctxt be s a -> DataType be b -> QGenExpr ctxt be s b -- | A data type in a given IsSql92DataTypeSyntax which describes a -- SQL type mapping to the Haskell type a newtype DataType be a DataType :: BeamSqlBackendCastTargetSyntax be -> DataType be a day_ :: (BeamSqlBackend be, HasSqlDate tgt) => ExtractField be tgt Double month_ :: (BeamSqlBackend be, HasSqlDate tgt) => ExtractField be tgt Double year_ :: (BeamSqlBackend be, HasSqlDate tgt) => ExtractField be tgt Double -- | Extracts the hours, minutes, or seconds from any timestamp or time -- field seconds_ :: (BeamSqlBackend be, HasSqlTime tgt) => ExtractField be tgt Double -- | Extracts the hours, minutes, or seconds from any timestamp or time -- field minutes_ :: (BeamSqlBackend be, HasSqlTime tgt) => ExtractField be tgt Double -- | Extracts the hours, minutes, or seconds from any timestamp or time -- field hour_ :: (BeamSqlBackend be, HasSqlTime tgt) => ExtractField be tgt Double -- | Extracts the given field from the target expression extract_ :: BeamSqlBackend be => ExtractField be tgt a -> QGenExpr ctxt be s tgt -> QGenExpr cxt be s a -- | A field that can be extracted from SQL expressions of type -- tgt that results in a type a, in backend -- be. newtype ExtractField be tgt a ExtractField :: Sql92ExtractFieldSyntax (BeamSqlBackendSyntax be) -> ExtractField be tgt a -- | Type-class for types that contain a time component class HasSqlTime tgt -- | Type-class for types that contain a date component class HasSqlDate tgt -- | SQL IN predicate in_ :: BeamSqlBackend be => QGenExpr context be s a -> [QGenExpr context be s a] -> QGenExpr context be s Bool infix 4 `in_` -- | SQL BETWEEN clause between_ :: BeamSqlBackend be => QGenExpr context be s a -> QGenExpr context be s a -> QGenExpr context be s a -> QGenExpr context be s Bool infix 4 `between_` -- | A QQuantified representing a SQL ANY(..) for use with -- a quantified comparison operator -- -- Accepts an explicit list of typed expressions. Use anyOf_ for a -- subquery anyIn_ :: BeamSqlBackend be => [QExpr be s a] -> QQuantified be s a -- | A QQuantified representing a SQL ANY(..) for use with -- a quantified comparison operator -- -- Accepts a subquery. Use anyIn_ for an explicit list anyOf_ :: (BeamSqlBackend be, HasQBuilder be) => Q be db (QNested s) (QExpr be (QNested s) a) -> QQuantified be s a -- | A QQuantified representing a SQL ALL(..) for use with -- a quantified comparison operator -- -- Accepts an explicit list of typed expressions. Use allOf_ for a -- subquery allIn_ :: BeamSqlBackend be => [QExpr be s a] -> QQuantified be s a -- | A QQuantified representing a SQL ALL(..) for use with -- a quantified comparison operator -- -- Accepts a subquery. Use allIn_ for an explicit list allOf_ :: (BeamSqlBackend be, HasQBuilder be) => Q be db (QNested s) (QExpr be (QNested s) a) -> QQuantified be s a -- | Convert a possibly NULL Bool to a SqlBool. fromPossiblyNullBool_ :: () => QGenExpr context be s (Maybe Bool) -> QGenExpr context be s SqlBool -- | Retrieve a SqlBool value as a potentially NULL -- Bool. This is useful if you want to get the value of a SQL -- boolean expression directly, without having to specify what to do on -- UNKNOWN. Note that both NULL and UNKNOWN -- will be returned as Nothing. possiblyNullBool_ :: () => QGenExpr context be s SqlBool -> QGenExpr context be s (Maybe Bool) -- | Return the first argument if the expression has the unknown SQL value -- See sqlBool_ for the inverse unknownAs_ :: BeamSqlBackend be => Bool -> QGenExpr context be s SqlBool -> QGenExpr context be s Bool -- | SQL IS NOT UNKNOWN operator isNotUnknown_ :: BeamSqlBackend be => QGenExpr context be s SqlBool -> QGenExpr context be s Bool -- | SQL IS UNKNOWN operator isUnknown_ :: BeamSqlBackend be => QGenExpr context be s SqlBool -> QGenExpr context be s Bool -- | SQL IS NOT FALSE operator isNotFalse_ :: BeamSqlBackend be => QGenExpr context be s SqlBool -> QGenExpr context be s Bool -- | SQL IS FALSE operator isFalse_ :: BeamSqlBackend be => QGenExpr context be s SqlBool -> QGenExpr context be s Bool -- | SQL IS NOT TRUE operator isNotTrue_ :: BeamSqlBackend be => QGenExpr context be s SqlBool -> QGenExpr context be s Bool -- | SQL IS TRUE operator isTrue_ :: BeamSqlBackend be => QGenExpr context be s SqlBool -> QGenExpr context be s Bool -- | Convert a known not null bool to a SqlBool. See -- unknownAs_ for the inverse sqlBool_ :: () => QGenExpr context syntax s Bool -> QGenExpr context syntax s SqlBool -- | A data structure representing the set to quantify a comparison -- operator over. data QQuantified be s r -- | Class for expression types or expression containers for which there is -- a notion of equality. -- -- Instances are provided to check the equality of expressions of the -- same type as well as entire Beamable types parameterized over -- QGenExpr class SqlEq (expr :: Type -> Type) a | a -> expr -- | Given two expressions, returns whether they are equal, using Haskell -- semantics (NULLs handled properly) (==.) :: SqlEq expr a => a -> a -> expr Bool -- | Given two expressions, returns whether they are not equal, using -- Haskell semantics (NULLs handled properly) (/=.) :: SqlEq expr a => a -> a -> expr Bool -- | Given two expressions, returns the SQL tri-state boolean when -- compared for equality (==?.) :: SqlEq expr a => a -> a -> expr SqlBool -- | Given two expressions, returns the SQL tri-state boolean when -- compared for inequality (/=?.) :: SqlEq expr a => a -> a -> expr SqlBool infix 4 ==. infix 4 /=. -- | Class for expression types for which there is a notion of -- quantified equality. class SqlEq expr a => SqlEqQuantified (expr :: Type -> Type) quantified a | a -> expr quantified -- | Quantified equality and inequality using SQL semantics -- (tri-state boolean) (==*.) :: SqlEqQuantified expr quantified a => a -> quantified -> expr SqlBool -- | Quantified equality and inequality using SQL semantics -- (tri-state boolean) (/=*.) :: SqlEqQuantified expr quantified a => a -> quantified -> expr SqlBool infix 4 ==*. infix 4 /=*. -- | Class for Haskell types that can be compared for equality in the given -- backend class BeamSqlBackend be => HasSqlEqualityCheck be a sqlEqE :: HasSqlEqualityCheck be a => Proxy a -> Proxy be -> BeamSqlBackendExpressionSyntax be -> BeamSqlBackendExpressionSyntax be -> BeamSqlBackendExpressionSyntax be sqlNeqE :: HasSqlEqualityCheck be a => Proxy a -> Proxy be -> BeamSqlBackendExpressionSyntax be -> BeamSqlBackendExpressionSyntax be -> BeamSqlBackendExpressionSyntax be -- | Tri-state equality sqlEqTriE :: HasSqlEqualityCheck be a => Proxy a -> Proxy be -> BeamSqlBackendExpressionSyntax be -> BeamSqlBackendExpressionSyntax be -> BeamSqlBackendExpressionSyntax be -- | Tri-state equality sqlNeqTriE :: HasSqlEqualityCheck be a => Proxy a -> Proxy be -> BeamSqlBackendExpressionSyntax be -> BeamSqlBackendExpressionSyntax be -> BeamSqlBackendExpressionSyntax be -- | Class for Haskell types that can be compared for quantified equality -- in the given backend class HasSqlEqualityCheck be a => HasSqlQuantifiedEqualityCheck be a sqlQEqE :: HasSqlQuantifiedEqualityCheck be a => Proxy a -> Proxy be -> Maybe (BeamSqlBackendExpressionQuantifierSyntax be) -> BeamSqlBackendExpressionSyntax be -> BeamSqlBackendExpressionSyntax be -> BeamSqlBackendExpressionSyntax be sqlQNeqE :: HasSqlQuantifiedEqualityCheck be a => Proxy a -> Proxy be -> Maybe (BeamSqlBackendExpressionQuantifierSyntax be) -> BeamSqlBackendExpressionSyntax be -> BeamSqlBackendExpressionSyntax be -> BeamSqlBackendExpressionSyntax be -- | Class for expression types or expression containers for which there is -- a notion of ordering. -- -- Instances are provided to check the ordering of expressions of the -- same type. Since there is no universal notion of ordering for an -- arbitrary number of expressions, no instance is provided for -- Beamable types. class SqlOrd (expr :: Type -> Type) e | e -> expr (<.) :: SqlOrd expr e => e -> e -> expr Bool (>.) :: SqlOrd expr e => e -> e -> expr Bool (<=.) :: SqlOrd expr e => e -> e -> expr Bool (>=.) :: SqlOrd expr e => e -> e -> expr Bool infix 4 <. infix 4 >. infix 4 <=. infix 4 >=. -- | Class for things which can be quantifiably compared. class SqlOrd expr e => SqlOrdQuantified (expr :: Type -> Type) quantified e | e -> expr quantified (<*.) :: SqlOrdQuantified expr quantified e => e -> quantified -> expr Bool (>*.) :: SqlOrdQuantified expr quantified e => e -> quantified -> expr Bool (<=*.) :: SqlOrdQuantified expr quantified e => e -> quantified -> expr Bool (>=*.) :: SqlOrdQuantified expr quantified e => e -> quantified -> expr Bool infix 4 <*. infix 4 >*. infix 4 <=*. infix 4 >=*. -- | SQL CONCAT function concat_ :: BeamSql99ConcatExpressionBackend be => [QGenExpr context be s Text] -> QGenExpr context be s Text -- | SQL % operator mod_ :: (Integral a, BeamSqlBackend be) => QGenExpr context be s a -> QGenExpr context be s a -> QGenExpr context be s a infixl 7 `mod_` -- | SQL / operator div_ :: (Integral a, BeamSqlBackend be) => QGenExpr context be s a -> QGenExpr context be s a -> QGenExpr context be s a infixl 7 `div_` -- | SQL NOT operator, but operating on SqlBool instead sqlNot_ :: BeamSqlBackend be => QGenExpr context be s SqlBool -> QGenExpr context be s SqlBool -- | SQL NOT operator not_ :: BeamSqlBackend be => QGenExpr context be s Bool -> QGenExpr context be s Bool -- | SQL99 SIMILAR TO operator similarTo_ :: (BeamSqlBackendIsString be text, BeamSql99ExpressionBackend be) => QGenExpr ctxt be s text -> QGenExpr ctxt be s text -> QGenExpr ctxt be s text infix 4 `similarTo_` -- | SQL LIKE operator like_ :: (BeamSqlBackendIsString be text, BeamSqlBackend be) => QGenExpr ctxt be s text -> QGenExpr ctxt be s text -> QGenExpr ctxt be s Bool infix 4 `like_` -- | SQL OR operator (||?.) :: BeamSqlBackend be => QGenExpr context be s SqlBool -> QGenExpr context be s SqlBool -> QGenExpr context be s SqlBool infixr 2 ||?. -- | SQL AND operator for SqlBool (&&?.) :: BeamSqlBackend be => QGenExpr context be s SqlBool -> QGenExpr context be s SqlBool -> QGenExpr context be s SqlBool infixr 3 &&?. -- | SQL OR operator (||.) :: BeamSqlBackend be => QGenExpr context be s Bool -> QGenExpr context be s Bool -> QGenExpr context be s Bool infixr 2 ||. -- | SQL AND operator (&&.) :: BeamSqlBackend be => QGenExpr context be s Bool -> QGenExpr context be s Bool -> QGenExpr context be s Bool infixr 3 &&. -- | Phantom type representing a SQL Tri-state boolean -- true, -- false, and unknown -- -- This type has no values because it cannot be sent to or retrieved from -- the database directly. Use isTrue_, isFalse_, -- isNotTrue_, isNotFalse_, isUnknown_, -- isNotUnknown_, and unknownAs_ to retrieve the -- corresponding Bool value. data SqlBool type family QExprToIdentity x :: Type type family QExprToField x :: Type class BeamSqlBackend be => HasQBuilder be buildSqlQuery :: (HasQBuilder be, Projectible be a) => TablePrefix -> Q be db s a -> BeamSqlBackendSelectSyntax be -- | The type of queries over the database db returning results of -- type a. The s argument is a threading argument meant -- to restrict cross-usage of QGenExprs. syntax -- represents the SQL syntax that this query is building. data Q be (db :: Type -> Type -> Type) s a data QField s ty data QAssignment be s data QFieldAssignment be (tbl :: Type -> Type -> Type) a data QAggregateContext data QGroupingContext data QValueContext data QWindowingContext data QWindowFrameContext -- | The type of lifted beam expressions that will yield the haskell type -- t. -- -- context is a type-level representation of the types of -- expressions this can contain. For example, QAggregateContext -- represents expressions that may contain aggregates, and -- QWindowingContext represents expressions that may contain -- OVER. -- -- syntax is the expression syntax being built (usually a type -- that implements IsSql92ExpressionSyntax at least, but not -- always). -- -- s is a state threading parameter that prevents -- QGenExprs from incompatible sources to be combined. For -- example, this is used to prevent monadic joins from depending on the -- result of previous joins (so-called LATERAL joins). newtype QGenExpr context be s t QExpr :: (TablePrefix -> BeamSqlBackendExpressionSyntax be) -> QGenExpr context be s t -- | QGenExprs represent expressions not containing aggregates. type QExpr = QGenExpr QValueContext data QWindow be s type Projectible be = ProjectibleWithPredicate AnyType be WithExprContext BeamSqlBackendExpressionSyntax' be -- | Like tableLenses but for types that are instances of -- Database. Instead of pattern matching on LensFor, -- pattern match on TableLens. dbLenses :: (Generic (db (TableLens f db)), Generic (db f), GDatabaseLenses (db f) (Rep (db f)) (Rep (db (TableLens f db)))) => db (TableLens f db) -- | Automatically deduce lenses for a table over any column tag. lenses at -- global level by doing a top-level pattern match on tableLenses, -- replacing every column in the pattern with `LensFor -- nameOfLensForField'. The lenses are generated per-column, not -- per field in the record. Thus if you have nested Beamable -- types, lenses are generated for each nested field. -- -- For example, -- --
-- data AuthorT f = AuthorT
-- { _authorEmail :: Columnar f Text
-- , _authorFirstName :: Columnar f Text
-- , _authorLastName :: Columnar f Text }
-- deriving Generic
--
-- data BlogPostT f = BlogPost
-- { _blogPostSlug :: Columnar f Text
-- , _blogPostBody :: Columnar f Text
-- , _blogPostDate :: Columnar f UTCTime
-- , _blogPostAuthor :: PrimaryKey AuthorT f
-- , _blogPostTagline :: Columnar f (Maybe Text) }
-- deriving Generic
-- instance Table BlogPostT where
-- data PrimaryKey BlogPostT f = BlogPostId (Columnar f Text)
-- primaryKey = BlogPostId . _blogPostSlug
-- instance Table AuthorT where
-- data PrimaryKey AuthorT f = AuthorId (Columnar f Text)
-- primaryKey = AuthorId . _authorEmail
--
--
-- -- BlogPost (LensFor blogPostSlug -- (LensFor blogPostBody) -- (LensFor blogPostDate) -- (AuthorId (LensFor blogPostAuthorEmail)) -- (LensFor blogPostTagLine) = tableLenses ---- -- Note: In order to have GHC deduce the right type, you will need to -- turn off the monomorphism restriction. This is a part of the Haskell -- standard that specifies that top-level definitions must be inferred to -- have a monomorphic type. However, lenses need a polymorphic type to -- work properly. You can turn off the monomorphism restriction by -- enabling the NoMonomorphismRestriction extension. You can do -- this per-file by using the {--} pragma at the top of the file. You can -- also pass the -XNoMonomorphismRestriction command line flag -- to GHC during compilation. tableLenses :: (lensType ~ Lenses t f, Generic (t lensType), Generic (t f), GTableLenses t f (Rep (t f)) (Rep (t lensType))) => t (Lenses t f) newtype TableLens (f :: k -> Type) (db :: k -> Type -> Type) (x :: k) :: forall k. () => k -> Type -> k -> Type -> Type -> k -> Type TableLens :: Lens' (db f) (f x) -> TableLens -- | Return a TableSettings for the appropriate table type -- where each column has been given its default name. See the -- manual for information on the default naming convention. defTblFieldSettings :: (Generic (TableSettings table), GDefaultTableFieldSettings (Rep (TableSettings table) ())) => TableSettings table -- | Synonym for primaryKey pk :: Table t => t f -> PrimaryKey t f -- | Van Laarhoven lens to retrieve or set the field name from a -- TableField. fieldName :: () => Lens' (TableField table ty) Text -- | A field modification to rename the field. Also offered under the -- IsString instance for 'FieldModification (TableField tbl) a' -- for convenience. fieldNamed :: () => Text -> FieldModification (TableField tbl) a -- | Construct an EntityModification to rename the fields of a -- TableEntity modifyTableFields :: () => tbl (FieldModification (TableField tbl)) -> EntityModification (DatabaseEntity be db) be (TableEntity tbl) -- | Change the entity name without consulting the beam-assigned one setEntityName :: IsDatabaseEntity be entity => Text -> EntityModification (DatabaseEntity be db) be entity -- | Construct an EntityModification to rename any database entity modifyEntityName :: IsDatabaseEntity be entity => (Text -> Text) -> EntityModification (DatabaseEntity be db) be entity -- | Provide an EntityModification for TableEntitys. Allows -- you to modify the name of the table and provide a modification for -- each field in the table. See the examples for -- withDbModification for more. modifyTable :: (Beamable tbl, Table tbl) => (Text -> Text) -> tbl (FieldModification (TableField tbl)) -> EntityModification (DatabaseEntity be db) be (TableEntity tbl) -- | Modify a table according to the given field modifications. Invoked by -- modifyTable to apply the modification in the database. Not used -- as often in user code, but provided for completeness. withTableModification :: Beamable tbl => tbl (FieldModification f) -> tbl f -> tbl f -- | Modify a database according to a given modification. Most useful for -- DatabaseSettings to change the name mappings of tables and -- fields. For example, you can use this to modify the default names of a -- table -- --
-- db :: DatabaseSettings MyDb
-- db = defaultDbSettings `withDbModification`
-- dbModification {
-- -- Change default name "table1" to "Table_1". Change the name of "table1Field1" to "first_name"
-- table1 = modifyTable (\_ -> "Table_1") (tableModification { table1Field1 = "first_name" }
-- }
--
withDbModification :: Database be db => db (entity be db) -> DatabaseModification (entity be db) be db -> db (entity be db)
-- | Return a table modification (for use with modifyTable) that
-- does nothing. Useful if you only want to change the table name, or if
-- you only want to modify a few fields.
--
-- For example,
--
--
-- tableModification { field1 = "Column1" }
--
--
-- is a table modification (where 'f ~ TableField tbl') that changes the
-- column name of field1 to Column1.
tableModification :: Beamable tbl => tbl (FieldModification f)
-- | Return a DatabaseModification that does nothing. This is useful
-- if you only want to rename one table. You can do
--
--
-- dbModification { tbl1 = modifyTable (\oldNm -> "NewTableName") tableModification }
--
dbModification :: Database be db => DatabaseModification f be db
-- | Automatically provide names for tables, and descriptions for tables
-- (using defTblFieldSettings). Your database must implement
-- Generic, and must be auto-derivable. For more information on
-- name generation, see the manual
defaultDbSettings :: (Generic (DatabaseSettings be db), GAutoDbSettings (Rep (DatabaseSettings be db) ())) => DatabaseSettings be db
-- | Allows introspection into database types.
--
-- All database types must be of kind '(* -> *) -> *'. If the type
-- parameter is named f, each field must be of the type of
-- f applied to some type for which an IsDatabaseEntity
-- instance exists.
--
-- The be type parameter is necessary so that the compiler can
-- ensure that backend-specific entities only work on the proper backend.
--
-- Entities are documented under the corresponding section and in
-- the manual
class Database be (db :: Type -> Type -> Type)
-- | A helper data type that lets you modify a database schema. Converts
-- all entities in the database into functions from that entity to
-- itself.
type DatabaseModification (f :: Type -> Type) be (db :: Type -> Type -> Type) = db EntityModification f be
-- | A newtype wrapper around 'f e -> f e' (i.e., an endomorphism
-- between entity types in f). You usually want to use
-- modifyTable or another function to contstruct these for you.
data EntityModification (f :: Type -> Type) be e
-- | A newtype wrapper around 'Columnar f a -> Columnar f ' (i.e., an
-- endomorphism between Columnars over f). You usually
-- want to use fieldNamed or the IsString instance to
-- rename the field, when 'f ~ TableField'
data FieldModification (f :: Type -> Type) a
-- | An entity tag for tables. See the documentation for Table or
-- consult the manual for more.
data TableEntity (tbl :: Type -> Type -> Type)
-- | Represents a meta-description of a particular entityType. Mostly, a
-- wrapper around 'DatabaseEntityDescriptor be entityType', but carries
-- around the IsDatabaseEntity dictionary.
data DatabaseEntity be (db :: Type -> Type -> Type) entityType
-- | When parameterized by this entity tag, a database type will hold
-- meta-information on the Haskell mappings of database entities. Under
-- the hood, each entity type is transformed into its
-- DatabaseEntityDescriptor type. For tables this includes the
-- table name as well as the corresponding TableSettings, which
-- provides names for each column.
type DatabaseSettings be (db :: Type -> Type -> Type) = db DatabaseEntity be db
data Lenses (t :: Type -> Type -> Type) (f :: Type -> Type) x
data LensFor t x
[LensFor] :: forall t x. Generic t => Lens' t x -> LensFor t x
-- | A type family that we use to "tag" columns in our table datatypes.
--
-- This is what allows us to use the same table type to hold table data,
-- describe table settings, derive lenses, and provide expressions.
--
-- The basic rules are
--
-- -- Columnar Identity x = x ---- -- Thus, any Beam table applied to Identity will yield a -- simplified version of the data type, that contains just what you'd -- expect. -- -- The Nullable type is used when referencing PrimaryKeys -- that we want to include optionally. For example, if we have a table -- with a PrimaryKey, like the following -- --
-- data BeamTableT f = BeamTableT
-- { _refToAnotherTable :: PrimaryKey AnotherTableT f
-- , ... }
--
--
-- we would typically be required to provide values for the
-- PrimaryKey embedded into BeamTableT. We can use
-- Nullable to lift this constraint.
--
--
-- data BeamTableT f = BeamTableT
-- { _refToAnotherTable :: PrimaryKey AnotherTableT (Nullable f)
-- , ... }
--
--
-- Now we can use justRef and nothingRef to refer to
-- this table optionally. The embedded PrimaryKey in
-- _refToAnotherTable automatically has its fields converted
-- into Maybe using Nullable.
--
-- The last Columnar rule is
--
-- -- Columnar f x = f x ---- -- Use this rule if you'd like to parameterize your table type over any -- other functor. For example, this is used in the query modules to write -- expressions such as 'TableT QExpr', which returns a table whose fields -- have been turned into query expressions. -- -- The other rules are used within Beam to provide lenses and to expose -- the inner structure of the data type. type family Columnar (f :: Type -> Type) x :: Type -- | A short type-alias for Columnar. May shorten your schema -- definitions type C (f :: Type -> Type) a = Columnar f a -- | If you declare a function 'Columnar f a -> b' and try to constrain -- your function by a type class for f, GHC will complain, -- because f is ambiguous in 'Columnar f a'. For example, -- 'Columnar Identity (Maybe a) ~ Maybe a' and 'Columnar (Nullable -- Identity) a ~ Maybe a', so given a type 'Columnar f a', we cannot know -- the type of f. -- -- Thus, if you need to know f, you can instead use -- Columnar'. Since its a newtype, it carries around the -- f paramater unambiguously. Internally, it simply wraps -- 'Columnar f a' data Columnar' (f :: Type -> Type) a -- | Metadata for a field of type ty in table. -- -- Essentially a wrapper over the field name, but with a phantom type -- parameter, so that it forms an appropriate column tag. -- -- Usually you use the defaultDbSettings function to generate an -- appropriate naming convention for you, and then modify it with -- withDbModification if necessary. Under this scheme, the field n -- be renamed using the IsString instance for TableField, -- or the fieldNamed function. data TableField (table :: Type -> Type -> Type) ty -- | Represents a table that contains metadata on its fields. In -- particular, each field of type 'Columnar f a' is transformed into -- 'TableField table a'. You can get or update the name of each field by -- using the fieldName lens. type TableSettings (table :: Type -> Type -> Type) = table TableField table -- | The regular Haskell version of the table. Equivalent to 'tbl Identity' type HaskellTable (table :: Type -> Type -> Type) = table Identity -- | The big Kahuna! All beam tables implement this class. -- -- The kind of all table types is '(* -> *) -> *'. This is because -- all table types are actually table type constructors. Every -- table type takes in another type constructor, called the column -- tag, and uses that constructor to instantiate the column types. -- See the documentation for Columnar. -- -- This class is mostly Generic-derivable. You need only specify a type -- for the table's primary key and a method to extract the primary key -- given the table. -- -- An example table: -- --
-- data BlogPostT f = BlogPost
-- { _blogPostSlug :: Columnar f Text
-- , _blogPostBody :: Columnar f Text
-- , _blogPostDate :: Columnar f UTCTime
-- , _blogPostAuthor :: PrimaryKey AuthorT f
-- , _blogPostTagline :: Columnar f (Maybe Text)
-- , _blogPostImageGallery :: PrimaryKey ImageGalleryT (Nullable f) }
-- deriving Generic
-- instance Beamable BlogPostT
-- instance Table BlogPostT where
-- data PrimaryKey BlogPostT f = BlogPostId (Columnar f Text) deriving Generic
-- primaryKey = BlogPostId . _blogPostSlug
-- instance Beamable (PrimaryKey BlogPostT)
--
--
-- We can interpret this as follows:
--
--
-- data MyTable f = MyTable
-- { nullableRef :: PrimaryKey AnotherTable (Nullable f)
-- , ... }
-- deriving (Generic, Typeable)
--
--
-- See Columnar for more information.
data Nullable (c :: Type -> Type) x
-- | Update a QField or Beamable type containing
-- QFields with the given QGenExpr or Beamable type
-- containing QGenExpr
(<-.) :: SqlUpdatable be s lhs rhs => lhs -> rhs -> QAssignment be s
infix 4 <-.
-- | newtype wrapper around Pg that only exports read-only
-- operations (currently runSelectReturningOne and
-- runSelectReturningList).
newtype RoPg a
RoPg :: Pg a -> RoPg a
[_fromRoPg] :: RoPg a -> Pg a
-- | class of read-only Beam operations - this has one obvious instance in
-- Pg itself, plus it lets us create a read-only alias in order to
-- restrict views to only reading from the database pool (where
-- appropriate).
class ReadOnlyM m
runSelectReturningOne :: (ReadOnlyM m, FromBackendRow Postgres a) => Sel a -> m (Maybe a)
runSelectReturningList :: (ReadOnlyM m, FromBackendRow Postgres a) => Sel a -> m [a]
-- | Type alias to handle the beam 0.7 - 0.8 API change that replaced
-- PgSelectSyntax with just plain Postgres.
type Sel a = SqlSelect Postgres a
instance GHC.Base.Monad TsWeb.Db.Beam.RoPg
instance GHC.Base.Applicative TsWeb.Db.Beam.RoPg
instance GHC.Base.Functor TsWeb.Db.Beam.RoPg
instance TsWeb.Db.Beam.ReadOnlyM TsWeb.Db.Beam.RoPg
instance TsWeb.Db.Beam.ReadOnlyM Database.Beam.Postgres.Connection.Pg
-- | Spock likes to store its session RAM, which is mostly great unless you
-- need persistence or multiple machines. This doesn't do anything
-- interesting with Spock's session manager, but just defines enough of a
-- table to be able to store Spock's core session information.
module TsWeb.Tables.Session
-- | A generic Beam table to store a Spock session. The _sessionData
-- should be your useful info, like a logged-in user or whatever. See
-- TsWeb.Tables.Session.Test for a type-checking but not very
-- function idea of what _sessionData could look like, or the code
-- under main for a fully-functional (but dumb) webapp using all
-- this stuff.
data SessionT d f
Session :: C f Text -> C f Text -> C f UTCTime -> d f -> SessionT d f
-- | Spock-generated session ID
[_sessionId] :: SessionT d f -> C f Text
-- | Session's CSRF token
[_sessionCsrf] :: SessionT d f -> C f Text
-- | Expiration date for this session
[_sessionExpires] :: SessionT d f -> C f UTCTime
-- | User-defined session data
[_sessionData] :: SessionT d f -> d f
-- | Concrete session
type Session d = SessionT d Identity
-- | Session primary key
type SessionId d = PrimaryKey (SessionT d) Identity
instance GHC.Generics.Generic (TsWeb.Tables.Session.SessionT d f)
instance GHC.Generics.Generic (Database.Beam.Schema.Tables.PrimaryKey (TsWeb.Tables.Session.SessionT d) f)
instance GHC.Show.Show (Database.Beam.Schema.Tables.PrimaryKey (TsWeb.Tables.Session.SessionT d) Data.Functor.Identity.Identity)
instance GHC.Show.Show (d Data.Functor.Identity.Identity) => GHC.Show.Show (TsWeb.Tables.Session.SessionT d Data.Functor.Identity.Identity)
instance GHC.Classes.Eq (Database.Beam.Schema.Tables.PrimaryKey (TsWeb.Tables.Session.SessionT d) Data.Functor.Identity.Identity)
instance GHC.Classes.Eq (d Data.Functor.Identity.Identity) => GHC.Classes.Eq (TsWeb.Tables.Session.SessionT d Data.Functor.Identity.Identity)
instance GHC.Classes.Ord (Database.Beam.Schema.Tables.PrimaryKey (TsWeb.Tables.Session.SessionT d) Data.Functor.Identity.Identity)
instance GHC.Classes.Ord (d Data.Functor.Identity.Identity) => GHC.Classes.Ord (TsWeb.Tables.Session.SessionT d Data.Functor.Identity.Identity)
instance Database.Beam.Schema.Tables.Beamable (Database.Beam.Schema.Tables.PrimaryKey (TsWeb.Tables.Session.SessionT d))
instance Database.Beam.Schema.Tables.Beamable d => Database.Beam.Schema.Tables.Beamable (TsWeb.Tables.Session.SessionT d)
instance (Database.Beam.Schema.Tables.Beamable d, Data.Typeable.Internal.Typeable d) => Database.Beam.Schema.Tables.Table (TsWeb.Tables.Session.SessionT d)
-- | These are the base wrappers around Spock's contexts and state monad.
-- The main thing that TsWeb does is force in a Context type that
-- is a wrapper around a Rec and a HVect. The Rec is used
-- to store tagged URL paths, while the HVect stores contextual data for
-- views, such as a database connection or authentication information.
module TsWeb.Types
-- | A container for a Rec of tagged Spock paths and a HVect
-- of view contextual data.
--
-- The paths are built with path and friends, and are queried
-- using getPath / showPath.
--
-- Context extras are currently populated using dbwrite and
-- auth; probably more will be added as needed.
data Context lts vec
Context :: Rec lts -> HVect vec -> Context lts vec
-- | Tagged paths for web context
[ctxPaths] :: Context lts vec -> Rec lts
-- | Free-form extras for web context
[ctxExtras] :: Context lts vec -> HVect vec
-- | Wrapper around WebStateM to suppress spock's database and
-- web_state
type TsWebStateM sessdata = WebStateM () sessdata ()
-- | Wrapper around ActionCtxT to use Context and
-- TsWebStateM
type TsActionCtxT lts xs sessdata a = ActionCtxT (Context lts xs) (TsWebStateM sessdata) a
-- | Wrapper around SpockCtxT to use Context and
-- TsWebStateM
type TsSpockCtxT lts xs sessdata = SpockCtxT (Context lts xs) (TsWebStateM sessdata)
-- | Various functions for reading data from the current Spock Action's
-- context. Currently that's just reading URL path info and auth data.
module TsWeb.Action
-- | Look up a tagged path in a view. If we have a route looking like
--
--
-- runroute ro rw $ path #user ("users" <//> var) (get user)
--
--
-- then a view could access that user path with
--
-- -- users <- getPath #user -- let txt = renderRoute users "bob" --getPath :: Has l lts v => FldProxy l -> TsActionCtxT lts xs sess v -- | Look up a path and render it. This returns a sort-of variadic function -- that can be provided with the right number of arguments in order to -- render a path. As with the above example, a route like this: -- --
-- runroute ro rw $ path #user ("users" <//> var) (get user)
--
--
-- could be rendered like this:
--
-- -- usersfn <- showPath #user -- let txt = usersfn "bob" ---- -- or, more succinctly: -- --
-- txt <- ($ "bob") <$> showPath $user --showPath :: (AllHave ToHttpApiData as, Has l lts v, v ~ Path as 'Open) => FldProxy l -> TsActionCtxT lts vec sess (HVectElim as Text) -- | Look up data that was put into the ctxExtras part of the -- action's context. This is pretty bound up with type signatures and -- other verbosity, but if we have a database-writing view like so: -- --
-- runroute ro rw $ path #root root (dbwrite $ get index) ---- -- then that index view could be written like so: -- --
-- index :: ListContains n ReadWritePool xs => TsActionCtxT lts xs sess a -- index = do -- db :: ReadWritePool <- getExtra -- ... --getExtra :: (MonadIO m, ListContains n v xs) => ActionCtxT (Context lts xs) m v -- | TsWeb has a strong notion that postgres should be configured in a -- warm-standby mode, with read-only queries being shipped to synchronous -- standbys whenever possible. This module defines types for -- descriminating between read-only and read-write connections, and also -- functions for making postgres connections, pools, etc. The -- connect function is working well enough for me, but will -- undoubtedly need to be improved to support the full depth of -- postgresql connection options. module TsWeb.Types.Db -- | Wrapper for some sort of Postgres connection; a raw `SomeConn t` -- represents either a read-only or a read-write connection, but the -- concrete ReadOnlyConn and ReadWriteConn are probably -- more useful in general. type SomeConn t = Tagged t Connection -- | Concrete read-only connection. Instantiate with connect type ReadOnlyConn = SomeConn ReadOnly -- | Concrete read-write connection. Instantiate with connect type ReadWriteConn = SomeConn ReadWrite -- | Pool of read-only connections. Instantiate with pool type ReadOnlyPool = Pool ReadOnlyConn -- | Pool of read-write connections. Instantiate with pool type ReadWritePool = Pool ReadWriteConn -- | Empty type to mark read-only db connections data ReadOnly -- | Empty type to mark read-write db connections data ReadWrite -- | String alias for the postgres host to connect to type HostName = String -- | String alias for the postgres database to connect to type DbName = String -- | Int alias for the createPool function numStripes -- argument type SubPools = Int -- | Int alias for the createPool function maxResources -- argument type KeepOpen = Int -- | An example of how Database.Beam does counts; this really -- doesn't belong here, and was just written for preliminary testing. count :: ProjectibleWithPredicate AnyType Postgres (WithExprContext (BeamSqlBackendExpressionSyntax' Postgres)) t => Q Postgres db (QNested s0) t -> Q Postgres db s0 (QGenExpr QValueContext Postgres s0 Int) -- | Create a resource pool of either read-only or read-write postgres -- connections. The docs for createPool give the best description -- for how this works. pool :: HostName -> DbName -> String -> SubPools -> NominalDiffTime -> KeepOpen -> IO (Pool (SomeConn t)) -- | Run an action in a Pool connection withConnection :: Pool (SomeConn a) -> (SomeConn a -> IO b) -> IO b -- | Create a ReadOnly or ReadWrite postgres connection. This -- doesn't actually check whether the connection is read-only or -- read-write, so it's really just to help with type juggling. connect :: HostName -> DbName -> String -> IO (SomeConn t) -- | Run an action within a postgresql savepoint withSavepoint :: SomeConn t -> IO a -> IO a -- | Run an action within a postgresql transaction withTransaction :: SomeConn t -> IO a -> IO a -- | Run a read-only query; this will actually run any query at all, so -- higher-level logic should ensure that only read-only queries hit this -- function. readOnly :: SomeConn t -> Pg a -> IO a -- | Same as readOnly, but prints any SQL that it runs. readOnlyDebug :: SomeConn t -> Pg a -> IO a -- | Run a query against a ReadWriteConn readWrite :: ReadWriteConn -> Pg a -> IO a -- | Same as readWrite, but printing all the SQL that gets executed. readWriteDebug :: ReadWriteConn -> Pg a -> IO a -- | This provides one essential function, patchConfig to replace -- Spock's default in-RAM session implementation with a Beam/postgres -- one. module TsWeb.Session -- | Update a spock configuration stanza to replace its default session -- with one backed by postgres. This will typically be used like so: -- --
-- spockCfg <- -- patchConfig (_dbSession db) ropool rwpool $ -- defaultSpockCfg sess PCNoDatabase () -- runSpock port (spock spockCfg routes) -- where -- sess = ... -- routes = ... --patchConfig :: (FromBackendRow Postgres (sessdata Identity), Beamable sessdata, Typeable sessdata, Database Postgres db, UserData (sessdata Identity), FieldsFulfillConstraint (HasSqlValueSyntax PgValueSyntax) sessdata) => DatabaseEntity Postgres db (TableEntity (SessionT sessdata)) -> Pool ReadOnlyConn -> Pool ReadWriteConn -> SpockCfg conn (sessdata Identity) st -> SpockCfg conn (sessdata Identity) st -- | Typeclass for user-supplied data. We really just need to know whether -- the user has set a remember-me indicator upon login so that the -- session's lifespan can be intelligently controlled. If your session -- never needs to be remembers, then rememberMe = const False -- should suffice. class UserData c -- | Should the associated session be stored permanently? rememberMe :: UserData c => c -> Bool instance GHC.Show.Show sessdata => GHC.Show.Show (TsWeb.Session.TxProgram (Web.Spock.Internal.Types.Session conn sessdata st) a) instance GHC.Base.Functor f => GHC.Base.Functor (TsWeb.Session.Free f) instance GHC.Base.Functor f => GHC.Base.Applicative (TsWeb.Session.Free f) instance GHC.Base.Functor f => GHC.Base.Monad (TsWeb.Session.Free f) instance GHC.Base.Functor (TsWeb.Session.TxAction s) module TsWeb.Tables.Session.Test -- | Some sample user info data UsersMixin f Address :: C f Int -> C f Int -> C f Bool -> UsersMixin f [loginid] :: UsersMixin f -> C f Int [masqid] :: UsersMixin f -> C f Int [remember] :: UsersMixin f -> C f Bool -- | Concrete type for users type Users = UsersMixin Identity -- | Spock session alias to use our User type Sess conn st = Session conn Users st -- | Beam database definition to hold our session data Db f Db :: f (TableEntity (SessionT UsersMixin)) -> Db f [session] :: Db f -> f (TableEntity (SessionT UsersMixin)) -- | Beam database instance db :: DatabaseSettings be Db -- | Sample of patch to be sure that all the types work enough to make a -- spock config wrapper patch :: Pool ReadOnlyConn -> Pool ReadWriteConn -> SpockCfg conn Users st -> SpockCfg conn Users st instance GHC.Generics.Generic (TsWeb.Tables.Session.Test.Db f) instance GHC.Generics.Generic (TsWeb.Tables.Session.Test.UsersMixin f) instance Database.Beam.Schema.Tables.Database be TsWeb.Tables.Session.Test.Db instance TsWeb.Session.UserData TsWeb.Tables.Session.Test.Users instance Database.Beam.Schema.Tables.Beamable TsWeb.Tables.Session.Test.UsersMixin -- | A generic authentication hook for TsWeb routing. The goal here is to -- be able to specify authentication requirements in a view's type, so -- that the routing statically guarantees that a view can only be entered -- when session preconditions are met. A full example of this is under -- the Example module of this source tree, but a synopsis follows. Given -- a session/user definition like so: -- --
-- data UserT f = User
-- { _userId :: C f Int
-- , _userLogin :: C f Text
-- } deriving (Generic)
-- ...
-- data SessionDataT f = SessionData
-- { _sdUser :: PrimaryKey UserT (Nullable f)
-- , _sdRemember :: C f Bool
-- } deriving (Generic)
-- ...
--
-- userP :: Proxy User
-- userP = Proxy
--
--
-- then we can define a logged-in Authorize check as
--
-- -- instance Authorize SessionData User where -- checkAuth _ = -- _sdUser <$> readSession >>= case -- UserId Nothing -> pure Nothing -- UserId (Just uid) -> -- queryMaybe (select $ q uid) >>= case -- QSimply (Just user) -> pure $ Just user -- _ -> pure Nothing -- where -- q uid = do -- u <- all_ $ _dbUser db -- guard_ $ _userId u ==. val_ uid -- pure u ---- -- A view requiring an authenticated user would have a signature like -- --
-- authd :: ListContains n User xs => TsActionCtxT lts xs SessionData a -- authd = do -- user :: User <- getExtra -- ... ---- -- Finally, the route for only allowing logged-in users would look like -- --
-- runroute ro rw $ path #authd "authd" $ get $ auth userP authd ---- -- That view is statically defined to only be accessible to logged-in -- users; any anonymous session will either go to an alternate (non-auth) -- view, or get a 404. module TsWeb.Routing.Auth -- | A class for session data that needs to be statically verified against -- routes. This could be checks for optional session info, or to validate -- the value of that session information. class Authorize sess perm -- | Load a value out of the session or return Nothing. Used in the context -- of auth, the wrapped view will only be called when this returns -- Just; a Nothing value will cause the wrapped view to be skipped. checkAuth :: (Authorize sess perm, ListContains n ReadOnlyPool xs) => Proxy perm -> TsActionCtxT lts xs sess (Maybe perm) -- | Guarantee that the Spock session hold some verified piece of data. If -- the requisite data can be loaded, then the view is called with the -- data in its ctxExtras; otherwise jumpNext is called and the -- view is skipped. auth :: (Authorize sess perm, ListContains n ReadOnlyPool xs, Authorize sess perm) => Proxy perm -> TsActionCtxT lts (perm : xs) sess () -> TsActionCtxT lts xs sess () -- | This module builds on Spock's "reroute" library by associating a -- GHC.OverloadedLabels label to each route, which views can then -- use to reverse routes in a type-safe manner. It also uses some -- ridiculous function chaining to almost create an indexed monad, but -- not quite because I can't figure out quite how to make that work. A -- fairly function example follows: -- -- First, we'll define a couple of views: -- --
-- index :: Has "users" lts (Path '[] 'Open) => TsActionCtxT lts xs sess a -- index = showPath #users >>= 'Spock.text -- -- users :: Has "root" lts (Path '[] 'Open) => TsActionCtxT lts xs sess a -- users = do -- root <- showPath #root -- text $ "GET users, root is, " <> root -- -- usersPost :: TsActionCtxT lts xs sess a -- usersPost = text "POST to users!" ---- -- Then, routing to those views looks like this: -- --
-- runroute ropool rwpool $ -- path #root root (getpost index) . -- path #users "users" (do get users -- post usersPost) ---- -- Notice the (.) after the getpost index. We're chaining -- functions together and then passing that chained function to -- runroute in order to generate an actual Spock RouteM. module TsWeb.Routing -- | Reader monad to pass one Path to potentially multiple different -- 'get'/'post'/etc calls. type RoutingM as lts xs sess = ReaderT (Path as 'Open, ReadWritePool) (TsSpockCtxT lts xs sess) -- | Convert a chain of path calls into a RouteM instance. -- This takes a ReadOnlyPool and a ReadWritePool in order -- to operate the auth and dbwrite calls. runroute :: (Applicative f, MonadIO m, RouteM t) => ReadOnlyPool -> ReadWritePool -> ((ReadWritePool, Rec '[], f ()) -> (ReadWritePool, Rec lts, t (Context lts '[ReadOnlyPool]) m ())) -> t ctx m () -- | Describe a path for routing. This both builds up the RouteM -- monad and associates the given label with the URL so that views can -- look up the URL using showPath &c. path :: (KnownNat ((RecSize (Sort ((l := Path as 'Open) : lts)) - RecTyIdxH 0 l (Sort ((l := Path as 'Open) : lts))) - 1), RecCopy lts lts (Sort ((l := Path as 'Open) : lts)), KnownNat (RecSize lts), KeyDoesNotExist l lts, KnownSymbol l) => FldProxy l -> Path as 'Open -> RoutingM as lts0 xs sess a -> (ReadWritePool, Rec lts, TsSpockCtxT lts0 xs sess a) -> (ReadWritePool, Record ((l := Path as 'Open) : lts), TsSpockCtxT lts0 xs sess a) -- | Raise up a RoutingM to have ReadWritePool in its extras -- record. dbwrite :: RoutingM as lts (ReadWritePool : xs) sess () -> RoutingM as lts xs sess () -- | Run this view whether the client did a GET or a POST request getpost :: HasRep as => HVectElim as (TsActionCtxT lts xs sess ()) -> RoutingM as lts xs sess () -- | Run this view only on GET requests get :: HasRep as => HVectElim as (TsActionCtxT lts xs sess ()) -> RoutingM as lts xs sess () -- | Run this view only on POST requests post :: HasRep as => HVectElim as (TsActionCtxT lts xs sess ()) -> RoutingM as lts xs sess () -- | This defines a helper function, clay, which will serve a -- Css instance from a labeled URL prefix. module TsWeb.Routing.Clay -- | Serve a Css instance. The rendered CSS will be served from a -- .css file whose name is derived from the rendered sheet's contents. -- This has two results: changing the stylesheet will change the sheet's -- full URL, and the stylesheet really needs to be referenced by label, -- using something like showPath. The first one of those is -- actually really nice, since browsers are so aggressive about caching -- css. The second one is more convenient anyhow, so this function is -- just pretty nice. clay :: (KeyDoesNotExist l lts, RecCopy lts lts (Sort ((l := Path '[] 'Open) : lts)), KnownNat (RecSize lts), KnownNat ((RecSize (Sort ((l := Path '[] 'Open) : lts)) - RecTyIdxH 0 l (Sort ((l := Path '[] 'Open) : lts))) - 1), KnownSymbol l) => FldProxy l -> String -> Css -> (ReadWritePool, Rec lts, TsSpockCtxT lts0 xs sess ()) -> (ReadWritePool, Record ((l := Path '[] 'Open) : lts), TsSpockCtxT lts0 xs sess ()) -- | This builds on TsWeb.Types.Db's read-only/read-write -- discrimination by providing query functions to perform read-only -- operations, and an execute function to run updates, inserts, -- and deletes (and also selects as appropriate). All of these are -- performed as TsActionCtxT actions so as to nicely integrate -- with Spock. Finally, because I'm not a fan of exceptions, all of these -- functions trap Postgres errors and convert them into sum-type results. -- -- I'm not yet providing shortcuts for the beam-postgres specific -- functions. I'm not actually sure that I need to (IIRC they all build -- Pg actions), but I will be adding them if necessary. module TsWeb.Db -- | Transaction option: provide WithTx to wrap operations in BEGIN/COMMIT, -- or NoTx to skip that. data TxOpt NoTx :: TxOpt WithTx :: TxOpt -- | Result of a select operation. This will either succeed with a QSimply, -- or fail with a QError (probably then an error in the db connection or -- table definitions). data QueryResult a QSimply :: a -> QueryResult a QError :: SqlError -> QueryResult a -- | The result of a select, insert, update, or delete operation. This adds -- a constraint error to the QueryResult, making it nicer to -- filter out conflicts when handling errors. data ExecResult a ESimply :: a -> ExecResult a EConstraint :: SqlError -> ConstraintViolation -> ExecResult a EError :: SqlError -> ExecResult a -- | Run one or many Beam runSelectReturningList or -- runSelectReturningOne operation(s) against a view's -- ReadOnlyPool. query :: ListContains n ReadOnlyPool xs => TxOpt -> RoPg a -> TsActionCtxT lts xs sessdata (QueryResult a) -- | Run a single Beam select, returning a single (Maybe) value queryMaybe :: (ListContains n ReadOnlyPool xs, FromBackendRow Postgres a) => Sel a -> TsActionCtxT lts xs sessdata (QueryResult (Maybe a)) -- | Run a single Beam select, returning a list of values queryList :: (ListContains n ReadOnlyPool xs, FromBackendRow Postgres a) => Sel a -> TsActionCtxT lts xs sessdata (QueryResult [a]) -- | Run any arbitrary Pg monad in the context of a view, returning -- an ExecResult execute :: ListContains n ReadWritePool xs => TxOpt -> Pg a -> TsActionCtxT lts xs sessdata (ExecResult a) instance GHC.Show.Show a => GHC.Show.Show (TsWeb.Db.ExecResult a) instance GHC.Classes.Eq a => GHC.Classes.Eq (TsWeb.Db.ExecResult a) instance GHC.Show.Show a => GHC.Show.Show (TsWeb.Db.QueryResult a) instance GHC.Classes.Eq a => GHC.Classes.Eq (TsWeb.Db.QueryResult a) instance GHC.Show.Show TsWeb.Db.TxOpt instance GHC.Enum.Bounded TsWeb.Db.TxOpt instance GHC.Enum.Enum TsWeb.Db.TxOpt instance GHC.Classes.Ord TsWeb.Db.TxOpt instance GHC.Classes.Eq TsWeb.Db.TxOpt