refactor: rm schema arg from QueryBuilder funcs
* Change TableName to QualifiedIdentifier in ReadQuery and MutateQuery. * Move removeSourceCTESchema to DbRequestBuilder.
This commit is contained in:
committed by
Steve Chávez
parent
eebe319bfd
commit
50f2cc16ab
@@ -333,24 +333,23 @@ app dbStructure proc cols conf apiRequest =
|
||||
topLevelRange = iTopLevelRange apiRequest
|
||||
returnsScalar = maybe False procReturnsScalar proc
|
||||
|
||||
selectQuery = readRequestToQuery schema False
|
||||
countQuery = readRequestToCountQuery schema
|
||||
selectQuery = readRequestToQuery False
|
||||
readSqlParts tableName =
|
||||
let
|
||||
readReq = readRequest schema tableName maxRows (dbRelations dbStructure) apiRequest
|
||||
in
|
||||
(,,) <$>
|
||||
(selectQuery <$> readReq) <*>
|
||||
(countQuery <$> readReq) <*>
|
||||
(readRequestToCountQuery <$> readReq) <*>
|
||||
(binaryField contentType rawContentTypes returnsScalar =<< readReq)
|
||||
mutateSqlParts s t =
|
||||
let
|
||||
readReq = readRequest s t maxRows (dbRelations dbStructure) apiRequest
|
||||
mutReq = mutateRequest apiRequest t cols (tablePKCols dbStructure s t) =<< readReq
|
||||
mutReq = mutateRequest s t apiRequest cols (tablePKCols dbStructure s t) =<< readReq
|
||||
in
|
||||
(,) <$>
|
||||
(selectQuery <$> readReq) <*>
|
||||
(mutateRequestToQuery s <$> mutReq)
|
||||
(mutateRequestToQuery <$> mutReq)
|
||||
|
||||
responseContentTypeOrError :: [ContentType] -> [ContentType] -> Action -> Target -> Either Response ContentType
|
||||
responseContentTypeOrError accepts rawContentTypes action target = serves contentTypesForRequest accepts
|
||||
|
||||
@@ -50,15 +50,15 @@ readRequest schema rootTableName maxRows allRels apiRequest =
|
||||
(initReadRequest rootName <$> pRequestSelect sel)
|
||||
where
|
||||
sel = fromMaybe "*" $ iSelect apiRequest -- default to all columns requested (SELECT *) for a non existent ?select querystring param
|
||||
(rootName, rootRels) = rootWithRelations rootTableName allRels (iAction apiRequest)
|
||||
(rootName, rootRels) = rootWithRelations schema rootTableName allRels (iAction apiRequest)
|
||||
|
||||
-- Get the root table name with its relations according to the Action type.
|
||||
-- This is done because of the shape of the final SQL Query. The mutation cases are wrapped in a WITH {sourceCTEName}(see Statements.hs).
|
||||
-- So we need a FROM {sourceCTEName} instead of FROM {tableName}.
|
||||
rootWithRelations :: TableName -> [Relation] -> Action -> (TableName, [Relation])
|
||||
rootWithRelations rootTableName allRels action = case action of
|
||||
ActionRead _ -> (rootTableName, allRels) -- normal read case
|
||||
_ -> (sourceCTEName, mapMaybe toSourceRelation allRels ++ allRels) -- mutation cases and calling proc
|
||||
rootWithRelations :: Schema -> TableName -> [Relation] -> Action -> (QualifiedIdentifier, [Relation])
|
||||
rootWithRelations schema rootTableName allRels action = case action of
|
||||
ActionRead _ -> (QualifiedIdentifier schema rootTableName, allRels) -- normal read case
|
||||
_ -> (QualifiedIdentifier mempty sourceCTEName, mapMaybe toSourceRelation allRels ++ allRels) -- mutation cases and calling proc
|
||||
where
|
||||
-- To enable embedding in the sourceCTEName cases we need to replace the foreign key tableName in the Relation
|
||||
-- with {sourceCTEName}. This way findRelation can find Relations with sourceCTEName.
|
||||
@@ -69,19 +69,24 @@ rootWithRelations rootTableName allRels action = case action of
|
||||
|
||||
-- Build the initial tree with a Depth attribute so when a self join occurs we can differentiate the parent and child tables by having
|
||||
-- an alias like "table_depth", this is related to http://github.com/PostgREST/postgrest/issues/987.
|
||||
initReadRequest :: TableName -> [Tree SelectItem] -> ReadRequest
|
||||
initReadRequest rootTableName =
|
||||
initReadRequest :: QualifiedIdentifier -> [Tree SelectItem] -> ReadRequest
|
||||
initReadRequest rootQi =
|
||||
foldr (treeEntry rootDepth) initial
|
||||
where
|
||||
rootDepth = 0
|
||||
initial = Node (Select [] rootTableName Nothing [] [] [] [] allRange, (rootTableName, Nothing, Nothing, Nothing, rootDepth)) []
|
||||
rootSchema = qiSchema rootQi
|
||||
rootName = qiName rootQi
|
||||
initial = Node (Select [] rootQi Nothing [] [] [] [] allRange, (rootName, Nothing, Nothing, Nothing, rootDepth)) []
|
||||
treeEntry :: Depth -> Tree SelectItem -> ReadRequest -> ReadRequest
|
||||
treeEntry depth (Node fld@((fn, _),_,alias,relationDetail) fldForest) (Node (q, i) rForest) =
|
||||
let nxtDepth = succ depth in
|
||||
case fldForest of
|
||||
[] -> Node (q {select=fld:select q}, i) rForest
|
||||
_ -> Node (q, i) $
|
||||
foldr (treeEntry nxtDepth) (Node (Select [] fn Nothing [] [] [] [] allRange, (fn, Nothing, alias, relationDetail, nxtDepth)) []) fldForest:rForest
|
||||
foldr (treeEntry nxtDepth)
|
||||
(Node (Select [] (QualifiedIdentifier rootSchema fn) Nothing [] [] [] [] allRange,
|
||||
(fn, Nothing, alias, relationDetail, nxtDepth)) [])
|
||||
fldForest:rForest
|
||||
|
||||
treeRestrictRange :: Maybe Integer -> ReadRequest -> Either ApiRequestError ReadRequest
|
||||
treeRestrictRange maxRows request = pure $ nodeRestrictRange maxRows <$> request
|
||||
@@ -97,9 +102,10 @@ augumentRequestWithJoin schema allRels request =
|
||||
addRelations :: Schema -> [Relation] -> Maybe ReadRequest -> ReadRequest -> Either ApiRequestError ReadRequest
|
||||
addRelations schema allRelations parentNode (Node (query@Select{from=tbl}, (nodeName, _, alias, relationDetail, depth)) forest) =
|
||||
case parentNode of
|
||||
Just (Node (Select{from=parentNodeTable}, _) _) ->
|
||||
let newFrom r = if tbl == nodeName then tableName (relTable r) else tbl
|
||||
Just (Node (Select{from=parentNodeQi}, _) _) ->
|
||||
let newFrom r = if qiName tbl == nodeName then tableQi (relTable r) else tbl
|
||||
newReadNode = (\r -> (query{from=newFrom r}, (nodeName, Just r, alias, Nothing, depth))) <$> rel
|
||||
parentNodeTable = qiName parentNodeQi
|
||||
rel :: Either ApiRequestError Relation
|
||||
rel = note (NoRelationBetween parentNodeTable nodeName) $
|
||||
findRelation schema allRelations nodeName parentNodeTable relationDetail in
|
||||
@@ -201,12 +207,12 @@ addJoinConditions schema previousAlias (Node node@(query@Select{from=tbl}, nodeP
|
||||
Just rel@Relation{relType=Child} -> Node (augmentQuery rel, nodeProps) <$> updatedForest
|
||||
Just rel@Relation{relType=Many, relLinkTable=(Just linkTable)} ->
|
||||
let rq = augmentQuery rel in
|
||||
Node (rq{implicitJoins=tableName linkTable:implicitJoins rq}, nodeProps) <$> updatedForest
|
||||
Node (rq{implicitJoins=tableQi linkTable:implicitJoins rq}, nodeProps) <$> updatedForest
|
||||
_ -> Left UnknownRelation
|
||||
where
|
||||
newAlias = case isSelfJoin <$> relation of
|
||||
Just True
|
||||
| depth /= 0 -> Just (tbl <> "_" <> show depth) -- root node doesn't get aliased
|
||||
| depth /= 0 -> Just (qiName tbl <> "_" <> show depth) -- root node doesn't get aliased
|
||||
| otherwise -> Nothing
|
||||
_ -> Nothing
|
||||
augmentQuery rel =
|
||||
@@ -231,11 +237,17 @@ getJoinConditions previousAlias newAlias (Relation Table{tableSchema=tSchema, ta
|
||||
where
|
||||
toJoinCondition :: Text -> Text -> Column -> Column -> JoinCondition
|
||||
toJoinCondition tb ftb c fc =
|
||||
let qi1 = QualifiedIdentifier tSchema tb
|
||||
qi2 = QualifiedIdentifier tSchema ftb in
|
||||
let qi1 = removeSourceCTESchema tSchema tb
|
||||
qi2 = removeSourceCTESchema tSchema ftb in
|
||||
JoinCondition (maybe qi1 (QualifiedIdentifier mempty) newAlias, colName c)
|
||||
(maybe qi2 (QualifiedIdentifier mempty) previousAlias, colName fc)
|
||||
|
||||
-- On mutation and calling proc cases we wrap the target table in a WITH {sourceCTEName}
|
||||
-- if this happens remove the schema `FROM "schema"."{sourceCTEName}"` and use only the
|
||||
-- `FROM "{sourceCTEName}"`. If the schema remains the FROM would be invalid.
|
||||
removeSourceCTESchema :: Schema -> TableName -> QualifiedIdentifier
|
||||
removeSourceCTESchema schema tbl = QualifiedIdentifier (if tbl == sourceCTEName then mempty else schema) tbl
|
||||
|
||||
addFiltersOrdersRanges :: ApiRequest -> Either ApiRequestError (ReadRequest -> ReadRequest)
|
||||
addFiltersOrdersRanges apiRequest = foldr1 (liftA2 (.)) [
|
||||
flip (foldr addFilter) <$> filters,
|
||||
@@ -297,11 +309,11 @@ addProperty f (targetNodeName:remainingPath, a) (Node rn forest) =
|
||||
where
|
||||
pathNode = find (\(Node (_,(nodeName,_,alias,_,_)) _) -> nodeName == targetNodeName || alias == Just targetNodeName) forest
|
||||
|
||||
mutateRequest :: ApiRequest -> TableName -> S.Set FieldName -> [FieldName] -> ReadRequest -> Either Response MutateRequest
|
||||
mutateRequest apiRequest tName cols pkCols readReq = mapLeft errorResponseFor $
|
||||
mutateRequest :: Schema -> TableName -> ApiRequest -> S.Set FieldName -> [FieldName] -> ReadRequest -> Either Response MutateRequest
|
||||
mutateRequest schema tName apiRequest cols pkCols readReq = mapLeft errorResponseFor $
|
||||
case action of
|
||||
ActionCreate -> Right $ Insert tName cols ((,) <$> iPreferResolution apiRequest <*> Just pkCols) [] returnings
|
||||
ActionUpdate -> Update tName cols <$> combinedLogic <*> pure returnings
|
||||
ActionCreate -> Right $ Insert qi cols ((,) <$> iPreferResolution apiRequest <*> Just pkCols) [] returnings
|
||||
ActionUpdate -> Update qi cols <$> combinedLogic <*> pure returnings
|
||||
ActionSingleUpsert ->
|
||||
(\flts ->
|
||||
if null (iLogic apiRequest) &&
|
||||
@@ -310,12 +322,13 @@ mutateRequest apiRequest tName cols pkCols readReq = mapLeft errorResponseFor $
|
||||
all (\case
|
||||
Filter _ (OpExpr False (Op "eq" _)) -> True
|
||||
_ -> False) flts
|
||||
then Insert tName cols (Just (MergeDuplicates, pkCols)) <$> combinedLogic <*> pure returnings
|
||||
then Insert qi cols (Just (MergeDuplicates, pkCols)) <$> combinedLogic <*> pure returnings
|
||||
else
|
||||
Left InvalidFilters) =<< filters
|
||||
ActionDelete -> Delete tName <$> combinedLogic <*> pure returnings
|
||||
ActionDelete -> Delete qi <$> combinedLogic <*> pure returnings
|
||||
_ -> Left UnsupportedVerb
|
||||
where
|
||||
qi = QualifiedIdentifier schema tName
|
||||
action = iAction apiRequest
|
||||
returnings =
|
||||
if iPreferRepresentation apiRequest == None
|
||||
|
||||
@@ -7,7 +7,7 @@ Module : PostgREST.QueryBuilder
|
||||
Description : PostgREST SQL queries generating functions.
|
||||
|
||||
This module provides functions to consume data types that
|
||||
represent database objects (e.g. Relation, Schema) and SqlFragment
|
||||
represent database queries (e.g. ReadRequest, MutateRequest) and SqlFragment
|
||||
to produce SqlQuery type outputs.
|
||||
-}
|
||||
module PostgREST.QueryBuilder (
|
||||
@@ -34,8 +34,8 @@ import PostgREST.Types
|
||||
import Protolude hiding (cast, intercalate,
|
||||
replace)
|
||||
|
||||
readRequestToQuery :: Schema -> Bool -> ReadRequest -> SqlQuery
|
||||
readRequestToQuery schema isParent (Node (Select colSelects tbl tblAlias implJoins logicForest joinConditions_ ordts range, _) forest) =
|
||||
readRequestToQuery :: Bool -> ReadRequest -> SqlQuery
|
||||
readRequestToQuery isParent (Node (Select colSelects mainQi tblAlias implJoins logicForest joinConditions_ ordts range, _) forest) =
|
||||
unwords [
|
||||
"SELECT " <> intercalate ", " (map (pgFmtSelectItem qi) colSelects ++ selects),
|
||||
"FROM " <> intercalate ", " (tabl : implJs),
|
||||
@@ -46,8 +46,7 @@ readRequestToQuery schema isParent (Node (Select colSelects tbl tblAlias implJoi
|
||||
("LIMIT " <> maybe "ALL" show (rangeLimit range) <> " OFFSET " <> show (rangeOffset range)) `emptyOnFalse` (isParent || range == allRange) ]
|
||||
|
||||
where
|
||||
implJs = fromQi . QualifiedIdentifier schema <$> implJoins
|
||||
mainQi = removeSourceCTESchema schema tbl
|
||||
implJs = fromQi <$> implJoins
|
||||
tabl = fromQi mainQi <> maybe mempty (\a -> " AS " <> pgFmtIdent a) tblAlias
|
||||
qi = maybe mainQi (QualifiedIdentifier mempty) tblAlias
|
||||
|
||||
@@ -60,37 +59,37 @@ readRequestToQuery schema isParent (Node (Select colSelects tbl tblAlias implJoi
|
||||
<> "SELECT json_agg(" <> pgFmtIdent table <> ".*) "
|
||||
<> "FROM (" <> subquery <> ") " <> pgFmtIdent table
|
||||
<> "), '[]') AS " <> pgFmtIdent (fromMaybe name alias)
|
||||
where subquery = readRequestToQuery schema False (Node n forst)
|
||||
where subquery = readRequestToQuery False (Node n forst)
|
||||
getQueryParts (Node n@(_, (name, Just Relation{relType=Parent,relTable=Table{tableName=table}}, alias, _, _)) forst) (j,s) = (joi:j,sel:s)
|
||||
where
|
||||
aliasOrName = fromMaybe name alias
|
||||
localTableName = pgFmtIdent $ table <> "_" <> aliasOrName
|
||||
sel = "row_to_json(" <> localTableName <> ".*) AS " <> pgFmtIdent aliasOrName
|
||||
joi = " LEFT JOIN LATERAL( " <> subquery <> " ) AS " <> localTableName <> " ON TRUE "
|
||||
where subquery = readRequestToQuery schema True (Node n forst)
|
||||
where subquery = readRequestToQuery True (Node n forst)
|
||||
getQueryParts (Node n@(_, (name, Just Relation{relType=Many,relTable=Table{tableName=table}}, alias, _, _)) forst) (j,s) = (j,sel:s)
|
||||
where
|
||||
sel = "COALESCE (("
|
||||
<> "SELECT json_agg(" <> pgFmtIdent table <> ".*) "
|
||||
<> "FROM (" <> subquery <> ") " <> pgFmtIdent table
|
||||
<> "), '[]') AS " <> pgFmtIdent (fromMaybe name alias)
|
||||
where subquery = readRequestToQuery schema False (Node n forst)
|
||||
where subquery = readRequestToQuery False (Node n forst)
|
||||
--the following is just to remove the warning
|
||||
--getQueryParts is not total but readRequestToQuery is called only after addJoinConditions which ensures the only
|
||||
--posible relations are Child Parent Many
|
||||
getQueryParts _ _ = witness
|
||||
|
||||
|
||||
mutateRequestToQuery :: Schema -> MutateRequest -> SqlQuery
|
||||
mutateRequestToQuery schema (Insert mainTbl iCols onConflct putConditions returnings) =
|
||||
mutateRequestToQuery :: MutateRequest -> SqlQuery
|
||||
mutateRequestToQuery (Insert mainQi iCols onConflct putConditions returnings) =
|
||||
unwords [
|
||||
"WITH " <> normalizedBody,
|
||||
"INSERT INTO ", fromQi qi, if S.null iCols then " " else "(" <> cols <> ")",
|
||||
"INSERT INTO ", fromQi mainQi, if S.null iCols then " " else "(" <> cols <> ")",
|
||||
unwords [
|
||||
"SELECT " <> cols <> " FROM",
|
||||
"json_populate_recordset", "(null::", fromQi qi, ", " <> selectBody <> ") _",
|
||||
"json_populate_recordset", "(null::", fromQi mainQi, ", " <> selectBody <> ") _",
|
||||
-- Only used for PUT
|
||||
("WHERE " <> intercalate " AND " (pgFmtLogicTree (QualifiedIdentifier "" "_") <$> putConditions)) `emptyOnFalse` null putConditions],
|
||||
("WHERE " <> intercalate " AND " (pgFmtLogicTree (QualifiedIdentifier mempty "_") <$> putConditions)) `emptyOnFalse` null putConditions],
|
||||
maybe "" (\(oncDo, oncCols) -> (
|
||||
"ON CONFLICT(" <> intercalate ", " (pgFmtIdent <$> oncCols) <> ") " <> case oncDo of
|
||||
IgnoreDuplicates ->
|
||||
@@ -100,33 +99,29 @@ mutateRequestToQuery schema (Insert mainTbl iCols onConflct putConditions return
|
||||
then "DO NOTHING"
|
||||
else "DO UPDATE SET " <> intercalate ", " (pgFmtIdent <> const " = EXCLUDED." <> pgFmtIdent <$> S.toList iCols)
|
||||
) `emptyOnFalse` null oncCols) onConflct,
|
||||
("RETURNING " <> intercalate ", " (map (pgFmtColumn qi) returnings)) `emptyOnFalse` null returnings]
|
||||
("RETURNING " <> intercalate ", " (map (pgFmtColumn mainQi) returnings)) `emptyOnFalse` null returnings]
|
||||
where
|
||||
qi = QualifiedIdentifier schema mainTbl
|
||||
cols = intercalate ", " $ pgFmtIdent <$> S.toList iCols
|
||||
mutateRequestToQuery schema (Update mainTbl uCols logicForest returnings) =
|
||||
mutateRequestToQuery (Update mainQi uCols logicForest returnings) =
|
||||
if S.null uCols
|
||||
then "WITH " <> ignoredBody <> "SELECT null WHERE false" -- if there are no columns we cannot do UPDATE table SET {empty}, it'd be invalid syntax
|
||||
else
|
||||
unwords [
|
||||
"WITH " <> normalizedBody,
|
||||
"UPDATE " <> fromQi qi <> " SET " <> cols,
|
||||
"FROM (SELECT * FROM json_populate_recordset", "(null::", fromQi qi, ", " <> selectBody <> ")) _ ",
|
||||
("WHERE " <> intercalate " AND " (pgFmtLogicTree qi <$> logicForest)) `emptyOnFalse` null logicForest,
|
||||
("RETURNING " <> intercalate ", " (pgFmtColumn qi <$> returnings)) `emptyOnFalse` null returnings
|
||||
"UPDATE " <> fromQi mainQi <> " SET " <> cols,
|
||||
"FROM (SELECT * FROM json_populate_recordset", "(null::", fromQi mainQi, ", " <> selectBody <> ")) _ ",
|
||||
("WHERE " <> intercalate " AND " (pgFmtLogicTree mainQi <$> logicForest)) `emptyOnFalse` null logicForest,
|
||||
("RETURNING " <> intercalate ", " (pgFmtColumn mainQi <$> returnings)) `emptyOnFalse` null returnings
|
||||
]
|
||||
where
|
||||
qi = QualifiedIdentifier schema mainTbl
|
||||
cols = intercalate ", " (pgFmtIdent <> const " = _." <> pgFmtIdent <$> S.toList uCols)
|
||||
mutateRequestToQuery schema (Delete mainTbl logicForest returnings) =
|
||||
mutateRequestToQuery (Delete mainQi logicForest returnings) =
|
||||
unwords [
|
||||
"WITH " <> ignoredBody,
|
||||
"DELETE FROM ", fromQi qi,
|
||||
("WHERE " <> intercalate " AND " (map (pgFmtLogicTree qi) logicForest)) `emptyOnFalse` null logicForest,
|
||||
("RETURNING " <> intercalate ", " (map (pgFmtColumn qi) returnings)) `emptyOnFalse` null returnings
|
||||
"DELETE FROM ", fromQi mainQi,
|
||||
("WHERE " <> intercalate " AND " (map (pgFmtLogicTree mainQi) logicForest)) `emptyOnFalse` null logicForest,
|
||||
("RETURNING " <> intercalate ", " (map (pgFmtColumn mainQi) returnings)) `emptyOnFalse` null returnings
|
||||
]
|
||||
where
|
||||
qi = QualifiedIdentifier schema mainTbl
|
||||
|
||||
requestToCallProcQuery :: QualifiedIdentifier -> [PgArg] -> Bool -> Maybe PreferParameters -> SqlQuery
|
||||
requestToCallProcQuery qi pgArgs returnsScalar preferParams =
|
||||
@@ -176,15 +171,13 @@ requestToCallProcQuery qi pgArgs returnsScalar preferParams =
|
||||
-- It only takes WHERE into account and doesn't include LIMIT/OFFSET because it would reduce the COUNT.
|
||||
-- SELECT 1 is done instead of SELECT * to prevent doing expensive operations(like functions based on the columns)
|
||||
-- inside the FROM target.
|
||||
readRequestToCountQuery :: Schema -> ReadRequest -> SqlQuery
|
||||
readRequestToCountQuery schema (Node (Select{where_=logicForest}, (mainTbl, _, _, _, _)) _) =
|
||||
readRequestToCountQuery :: ReadRequest -> SqlQuery
|
||||
readRequestToCountQuery (Node (Select{from=qi, where_=logicForest}, _) _) =
|
||||
unwords [
|
||||
"SELECT 1",
|
||||
"FROM " <> fromQi qi,
|
||||
("WHERE " <> intercalate " AND " (map (pgFmtLogicTree qi) logicForest)) `emptyOnFalse` null logicForest
|
||||
]
|
||||
where
|
||||
qi = removeSourceCTESchema schema mainTbl
|
||||
|
||||
limitedQuery :: SqlQuery -> Maybe Integer -> SqlQuery
|
||||
limitedQuery query maxRows = query <> maybe mempty (\x -> " LIMIT " <> show x) maxRows
|
||||
|
||||
@@ -150,9 +150,8 @@ pgFmtFilter table (Filter fld (OpExpr hasNot oper)) = notOp <> " " <> case oper
|
||||
(find ((==) . toLower $ v) ["null","true","false"])
|
||||
|
||||
pgFmtJoinCondition :: JoinCondition -> SqlFragment
|
||||
pgFmtJoinCondition (JoinCondition (QualifiedIdentifier schema1 tName, col1) (QualifiedIdentifier schema2 ftName, col2)) =
|
||||
pgFmtColumn (removeSourceCTESchema schema1 tName) col1 <> " = " <>
|
||||
pgFmtColumn (removeSourceCTESchema schema2 ftName) col2
|
||||
pgFmtJoinCondition (JoinCondition (qi1, col1) (qi2, col2)) =
|
||||
pgFmtColumn qi1 col1 <> " = " <> pgFmtColumn qi2 col2
|
||||
|
||||
pgFmtLogicTree :: QualifiedIdentifier -> LogicTree -> SqlFragment
|
||||
pgFmtLogicTree qi (Expr hasNot op forest) = notOp <> " (" <> intercalate (" " <> show op <> " ") (pgFmtLogicTree qi <$> forest) <> ")"
|
||||
@@ -183,12 +182,6 @@ pgFmtAs _ _ (Just alias) = " AS " <> pgFmtIdent alias
|
||||
trimNullChars :: Text -> Text
|
||||
trimNullChars = T.takeWhile (/= '\x0')
|
||||
|
||||
-- On mutation and calling proc cases we wrap the target table in a WITH {sourceCTEName}
|
||||
-- if this happens remove the schema `FROM "schema"."{sourceCTEName}"` and use only the
|
||||
-- `FROM "{sourceCTEName}"`. If the schema remains the FROM would be invalid.
|
||||
removeSourceCTESchema :: Schema -> TableName -> QualifiedIdentifier
|
||||
removeSourceCTESchema schema tbl = QualifiedIdentifier (if tbl == sourceCTEName then mempty else schema) tbl
|
||||
|
||||
countF :: SqlQuery -> Bool -> (SqlFragment, SqlFragment)
|
||||
countF countQuery shouldCount =
|
||||
if shouldCount
|
||||
|
||||
@@ -188,6 +188,9 @@ data Table = Table {
|
||||
instance Eq Table where
|
||||
Table{tableSchema=s1,tableName=n1} == Table{tableSchema=s2,tableName=n2} = s1 == s2 && n1 == n2
|
||||
|
||||
tableQi :: Table -> QualifiedIdentifier
|
||||
tableQi Table{tableSchema=s, tableName=n} = QualifiedIdentifier s n
|
||||
|
||||
newtype ForeignKey = ForeignKey { fkCol :: Column } deriving (Show, Eq, Ord)
|
||||
|
||||
data Column =
|
||||
@@ -397,11 +400,11 @@ data JoinCondition = JoinCondition (QualifiedIdentifier, FieldName)
|
||||
|
||||
data ReadQuery = Select {
|
||||
select :: [SelectItem]
|
||||
, from :: TableName
|
||||
, from :: QualifiedIdentifier
|
||||
-- | A table alias is used in case of self joins
|
||||
, fromAlias :: Maybe Alias
|
||||
-- | Only used for Many to Many joins. Parent and Child joins use explicit joins.
|
||||
, implicitJoins :: [TableName]
|
||||
, implicitJoins :: [QualifiedIdentifier]
|
||||
, where_ :: [LogicTree]
|
||||
, joinConditions :: [JoinCondition]
|
||||
, order :: [OrderTerm]
|
||||
@@ -410,20 +413,20 @@ data ReadQuery = Select {
|
||||
|
||||
data MutateQuery =
|
||||
Insert {
|
||||
in_ :: TableName
|
||||
in_ :: QualifiedIdentifier
|
||||
, insCols :: S.Set FieldName
|
||||
, onConflict :: Maybe (PreferResolution, [FieldName])
|
||||
, where_ :: [LogicTree]
|
||||
, returning :: [FieldName]
|
||||
}|
|
||||
Update {
|
||||
in_ :: TableName
|
||||
in_ :: QualifiedIdentifier
|
||||
, updCols :: S.Set FieldName
|
||||
, where_ :: [LogicTree]
|
||||
, returning :: [FieldName]
|
||||
}|
|
||||
Delete {
|
||||
in_ :: TableName
|
||||
in_ :: QualifiedIdentifier
|
||||
, where_ :: [LogicTree]
|
||||
, returning :: [FieldName]
|
||||
} deriving (Show, Eq)
|
||||
|
||||
Reference in New Issue
Block a user