refactor: put callProc core query to QueryBuilder
* Move set local queries to QueryBuilder * Move unquoted to Middleware
This commit is contained in:
committed by
Steve Chávez
parent
3c00f46e36
commit
200540dfc3
@@ -7,7 +7,7 @@ This module constructs single SQL statements that can be parametrized and prepar
|
||||
- It consumes the SqlQuery types generated by the QueryBuilder module.
|
||||
- It generates the body format and some headers of the final HTTP response.
|
||||
|
||||
TODO: Currently, createReadStatement is not using prepared statements, see https://github.com/PostgREST/postgrest/issues/718.
|
||||
TODO: Currently, createReadStatement is not using prepared statements. See https://github.com/PostgREST/postgrest/issues/718.
|
||||
-}
|
||||
module PostgREST.Statements (
|
||||
createWriteStatement
|
||||
@@ -117,18 +117,14 @@ standardRow = (,,,) <$> nullableColumn HD.int8 <*> column HD.int8
|
||||
|
||||
type ProcResults = (Maybe Int64, Int64, ByteString, Either Text [GucHeader])
|
||||
|
||||
callProcStatement :: QualifiedIdentifier -> [PgArg] -> Bool -> SqlQuery -> SqlQuery -> Bool ->
|
||||
Bool -> Bool -> Bool -> Bool -> Maybe FieldName -> PgVersion ->
|
||||
callProcStatement :: Bool -> SqlQuery -> SqlQuery -> SqlQuery -> Bool ->
|
||||
Bool -> Bool -> Bool -> Maybe FieldName -> PgVersion ->
|
||||
H.Statement ByteString ProcResults
|
||||
callProcStatement qi pgArgs returnsScalar selectQuery countQuery countTotal isSingle paramsAsSingleObject asCsv asBinary binaryField pgVer =
|
||||
callProcStatement returnsScalar callProcQuery selectQuery countQuery countTotal isSingle asCsv asBinary binaryField pgVer =
|
||||
unicodeStatement sql (param HE.unknown) decodeProc True
|
||||
where
|
||||
sql =[qc|
|
||||
WITH
|
||||
{argsRecord},
|
||||
{sourceCTEName} AS (
|
||||
{sourceBody}
|
||||
)
|
||||
sql = [qc|
|
||||
WITH {sourceCTEName} AS ({callProcQuery})
|
||||
SELECT
|
||||
{countResultF} AS total_result_set,
|
||||
pg_catalog.count(_postgrest_t) AS page_total,
|
||||
@@ -136,31 +132,6 @@ callProcStatement qi pgArgs returnsScalar selectQuery countQuery countTotal isSi
|
||||
{responseHeaders} AS response_headers
|
||||
FROM ({selectQuery}) _postgrest_t;|]
|
||||
|
||||
(argsRecord, args)
|
||||
| paramsAsSingleObject = ("_args_record AS (SELECT NULL)", "$1::json")
|
||||
| null pgArgs = (ignoredBody, "")
|
||||
| otherwise = (
|
||||
unwords [
|
||||
normalizedBody <> ",",
|
||||
"_args_record AS (",
|
||||
"SELECT * FROM json_to_recordset(" <> selectBody <> ") AS _(" <>
|
||||
intercalate ", " ((\a -> pgFmtIdent (pgaName a) <> " " <> pgaType a) <$> pgArgs) <> ")",
|
||||
")"]
|
||||
, intercalate ", " ((\a -> pgFmtIdent (pgaName a) <> " := _args_record." <> pgFmtIdent (pgaName a)) <$> pgArgs))
|
||||
|
||||
sourceBody :: SqlFragment
|
||||
sourceBody
|
||||
| paramsAsSingleObject || null pgArgs =
|
||||
if returnsScalar
|
||||
then [qc| SELECT {fromQi qi}({args}) |]
|
||||
else [qc| SELECT * FROM {fromQi qi}({args}) |]
|
||||
| otherwise =
|
||||
if returnsScalar
|
||||
then [qc| SELECT {fromQi qi}({args}) FROM _args_record |]
|
||||
else [qc| SELECT _.*
|
||||
FROM _args_record,
|
||||
LATERAL ( SELECT * FROM {fromQi qi}({args}) ) _ |]
|
||||
|
||||
bodyF
|
||||
| returnsScalar = scalarBodyF
|
||||
| isSingle = asJsonSingleF
|
||||
@@ -169,16 +140,15 @@ callProcStatement qi pgArgs returnsScalar selectQuery countQuery countTotal isSi
|
||||
| otherwise = asJsonF
|
||||
|
||||
scalarBodyF
|
||||
| asBinary = asBinaryF _procName
|
||||
| asBinary = asBinaryF "_scalar_res"
|
||||
| otherwise = unwords [
|
||||
"CASE",
|
||||
"WHEN pg_catalog.count(_postgrest_t) = 1",
|
||||
"THEN (json_agg(_postgrest_t." <> pgFmtIdent _procName <> ")->0)::character varying",
|
||||
"ELSE (json_agg(_postgrest_t." <> pgFmtIdent _procName <> "))::character varying",
|
||||
"THEN (json_agg(_postgrest_t._scalar_res)->0)::character varying",
|
||||
"ELSE (json_agg(_postgrest_t._scalar_res))::character varying",
|
||||
"END"]
|
||||
|
||||
countResultF = if countTotal then "( "<> countQuery <> ")" else "null::bigint" :: Text
|
||||
_procName = qiName qi
|
||||
responseHeaders =
|
||||
if pgVer >= pgVersion96
|
||||
then "coalesce(nullif(current_setting('response.headers', true), ''), '[]')" :: Text -- nullif is used because of https://gist.github.com/steve-chavez/8d7033ea5655096903f3b52f8ed09a15
|
||||
|
||||
Reference in New Issue
Block a user