avoid CTE expressions in sql function queries, close #3349 (#3504)

Instead of
'WITH some_alias (SELECT * from some_func()) SELECT <rows> FROM some_alias'
for SQL function queries, Use
'SELECT <rows> FROM some_func() AS some_alias'
This commit is contained in:
Rakesh Emmadi
2019-12-10 07:57:44 +05:30
committed by Alexis King
parent 3f8a1d9ebf
commit 9fe6070663
6 changed files with 23 additions and 109 deletions

View File

@@ -108,7 +108,7 @@ fromSelSet fldTy flds =
colMapping = riMapping relInfo
rn = riName relInfo
if isAgg then do
aggSel <- fromAggField relTN colGNameMap tableFilter tableLimit fld
aggSel <- fromAggField (RS.FromTable relTN) colGNameMap tableFilter tableLimit fld
return $ RS.FArr $ RS.ASAgg $ RS.AnnRelG rn colMapping aggSel
else do
annSel <- fromField (RS.FromTable relTN) colGNameMap tableFilter tableLimit fld
@@ -423,20 +423,19 @@ fromAggField
:: ( MonadReusability m, MonadError QErr m, MonadReader r m, Has FieldMap r
, Has OrdByCtx r, Has SQLGenCtx r
)
=> QualifiedTable
=> RS.SelectFromG UnresolvedVal
-> PGColGNameMap
-> AnnBoolExpPartialSQL
-> Maybe Int
-> Field -> m AnnAggSel
fromAggField tn colGNameMap permFilter permLimit fld = fieldAsPath fld $ do
fromAggField selectFrom colGNameMap permFilter permLimit fld = fieldAsPath fld $ do
tableArgs <- parseTableArgs colGNameMap args
aggSelFlds <- fromAggSelSet colGNameMap (_fType fld) (_fSelSet fld)
let unresolvedPermFltr =
fmapAnnBoolExp partialSQLExpToUnresolvedVal permFilter
let tabFrom = RS.FromTable tn
tabPerm = RS.TablePerm unresolvedPermFltr permLimit
let tabPerm = RS.TablePerm unresolvedPermFltr permLimit
strfyNum <- stringifyNum <$> asks getter
return $ RS.AnnSelG aggSelFlds tabFrom tabPerm tableArgs strfyNum
return $ RS.AnnSelG aggSelFlds selectFrom tabPerm tableArgs strfyNum
where
args = _fArguments fld
@@ -447,7 +446,7 @@ convertAggSelect
=> SelOpCtx -> Field -> m QueryRootFldUnresolved
convertAggSelect opCtx fld =
withPathK "selectionSet" $ QRFAgg <$>
fromAggField qt colGNameMap permFilter permLimit fld
fromAggField (RS.FromTable qt) colGNameMap permFilter permLimit fld
-- return $ RS.selectAggQuerySQL selData
where
SelOpCtx qt _ colGNameMap permFilter permLimit = opCtx
@@ -483,17 +482,16 @@ parseFunctionArgs argSeq argFn val = flip withObject val $ \_ obj -> do
throw400 NotSupported "Non default arguments cannot be omitted"
else pure Nothing
fromFuncQueryField
makeFunctionSelectFrom
:: (MonadReusability m, MonadError QErr m)
=> (Field -> m s)
-> QualifiedFunction
=> QualifiedFunction
-> FunctionArgSeq
-> Field
-> m (RS.AnnFnSelG s UnresolvedVal)
fromFuncQueryField fn qf argSeq fld = fieldAsPath fld $ do
-> m (RS.SelectFromG UnresolvedVal)
makeFunctionSelectFrom qf argSeq fld = do
funcArgsM <- withArgM (_fArguments fld) "args" $ parseFunctionArgs argSeq argFn
let funcArgs = fromMaybe RS.emptyFunctionArgsExp funcArgsM
RS.AnnFnSel qf funcArgs <$> fn fld
let funcArgs = RS.AEInput <$> fromMaybe RS.emptyFunctionArgsExp funcArgsM
pure $ RS.FromFunction qf funcArgs
where
argFn (IAUserProvided val) = IFAUnknown val
argFn (IASessionVariables argName) = IFAKnown argName UVSession
@@ -508,10 +506,11 @@ convertFuncQuerySimple
)
=> FuncQOpCtx -> Field -> m QueryRootFldUnresolved
convertFuncQuerySimple funcOpCtx fld =
withPathK "selectionSet" $ QRFFnSimple <$> fromFuncQueryField
(fromField (RS.FromTable qt) colGNameMap permFilter permLimit) qf argSeq fld
withPathK "selectionSet" $ fieldAsPath fld $ do
selectFrom <- makeFunctionSelectFrom qf argSeq fld
QRFSimple <$> fromField selectFrom colGNameMap permFilter permLimit fld
where
FuncQOpCtx qt _ colGNameMap permFilter permLimit qf argSeq = funcOpCtx
FuncQOpCtx qf argSeq _ colGNameMap permFilter permLimit = funcOpCtx
convertFuncQueryAgg
:: ( MonadReusability m
@@ -523,17 +522,16 @@ convertFuncQueryAgg
)
=> FuncQOpCtx -> Field -> m QueryRootFldUnresolved
convertFuncQueryAgg funcOpCtx fld =
withPathK "selectionSet" $ QRFFnAgg <$> fromFuncQueryField
(fromAggField qt colGNameMap permFilter permLimit) qf argSeq fld
withPathK "selectionSet" $ fieldAsPath fld $ do
selectFrom <- makeFunctionSelectFrom qf argSeq fld
QRFAgg <$> fromAggField selectFrom colGNameMap permFilter permLimit fld
where
FuncQOpCtx qt _ colGNameMap permFilter permLimit qf argSeq = funcOpCtx
FuncQOpCtx qf argSeq _ colGNameMap permFilter permLimit = funcOpCtx
data QueryRootFldAST v
= QRFPk !(RS.AnnSimpleSelG v)
| QRFSimple !(RS.AnnSimpleSelG v)
| QRFAgg !(RS.AnnAggSelG v)
| QRFFnSimple !(RS.AnnFnSelSimpleG v)
| QRFFnAgg !(RS.AnnFnSelAggG v)
deriving (Show, Eq)
type QueryRootFldUnresolved = QueryRootFldAST UnresolvedVal
@@ -548,13 +546,9 @@ traverseQueryRootFldAST f = \case
QRFPk s -> QRFPk <$> RS.traverseAnnSimpleSel f s
QRFSimple s -> QRFSimple <$> RS.traverseAnnSimpleSel f s
QRFAgg s -> QRFAgg <$> RS.traverseAnnAggSel f s
QRFFnSimple s -> QRFFnSimple <$> RS.traverseAnnFnSimple f s
QRFFnAgg s -> QRFFnAgg <$> RS.traverseAnnFnAgg f s
toPGQuery :: QueryRootFldResolved -> Q.Query
toPGQuery = \case
QRFPk s -> RS.selectQuerySQL True s
QRFSimple s -> RS.selectQuerySQL False s
QRFAgg s -> RS.selectAggQuerySQL s
QRFFnSimple s -> RS.mkFuncSelectSimple s
QRFFnAgg s -> RS.mkFuncSelectAgg s

View File

@@ -69,13 +69,12 @@ type FunctionArgSeq = Seq.Seq (InputArgument FunctionArgItem)
data FuncQOpCtx
= FuncQOpCtx
{ _fqocTable :: !QualifiedTable
{ _fqocFunction :: !QualifiedFunction
, _fqocArgs :: !FunctionArgSeq
, _fqocHeaders :: ![T.Text]
, _fqocAllCols :: !PGColGNameMap
, _fqocFilter :: !AnnBoolExpPartialSQL
, _fqocLimit :: !(Maybe Int)
, _fqocFunction :: !QualifiedFunction
, _fqocArgs :: !FunctionArgSeq
} deriving (Show, Eq)
data UpdOpCtx

View File

@@ -414,8 +414,7 @@ getRootFldsRole' tn primCols constraints fields funcs insM
funcFldHelper f g pFltr pLimit hdrs =
flip map funcs $ \fi ->
( f $ FuncQOpCtx tn hdrs colGNameMap pFltr pLimit
(fiName fi) (mkFuncArgItemSeq fi)
( f $ FuncQOpCtx (fiName fi) (mkFuncArgItemSeq fi) hdrs colGNameMap pFltr pLimit
, g fi $ fiDescription fi
)

View File

@@ -2,8 +2,6 @@ module Hasura.RQL.DML.Select
( selectP2
, selectQuerySQL
, selectAggQuerySQL
, mkFuncSelectSimple
, mkFuncSelectAgg
, convSelectQuery
, asSingleRowJsonResp
, module Hasura.RQL.DML.Select.Internal
@@ -269,20 +267,6 @@ convSelectQuery sessVarBldr prepArgBuilder (DMLQuery qt selQ) = do
convSelectQ (_tiFieldInfoMap tabInfo) selPermInfo
extSelQ sessVarBldr prepArgBuilder
mkFuncSelectSimple
:: AnnFnSelSimple
-> Q.Query
mkFuncSelectSimple annFnSel =
Q.fromBuilder $ toSQL $
mkFuncSelectWith (mkSQLSelect False) annFnSel
mkFuncSelectAgg
:: AnnFnSelAgg
-> Q.Query
mkFuncSelectAgg annFnSel =
Q.fromBuilder $ toSQL $
mkFuncSelectWith mkAggSelect annFnSel
selectP2 :: Bool -> (AnnSimpleSel, DS.Seq Q.PrepArg) -> Q.TxE QErr EncJSON
selectP2 asSingleObject (sel, p) =
encJFromBS . runIdentity . Q.getRow

View File

@@ -1,7 +1,6 @@
module Hasura.RQL.DML.Select.Internal
( mkSQLSelect
, mkAggSelect
, mkFuncSelectWith
, module Hasura.RQL.DML.Select.Types
)
where
@@ -773,30 +772,3 @@ mkSQLSelect isSingleObject annSel =
baseNode = annSelToBaseNode False rootPrefix rootFldName annSel
rootFldName = FieldName "root"
rootFldAls = S.Alias $ toIden rootFldName
mkFuncSelectWith
:: (AnnSelG a S.SQLExp -> S.Select)
-> AnnFnSelG (AnnSelG a S.SQLExp) S.SQLExp
-> S.SelectWith
mkFuncSelectWith f annFn =
S.SelectWith [(funcAls, S.CTESelect funcSel)] $
-- we'll need to modify the table from of the underlying
-- select to the alias of the select from function
f annSel { _asnFrom = newSelFrom }
where
AnnFnSel qf fnArgs annSel = annFn
-- SELECT * FROM function_name(args)
funcSel = S.mkSelect { S.selFrom = Just $ S.FromExp [frmItem]
, S.selExtr = [S.Extractor S.SEStar Nothing]
}
frmItem = S.mkFuncFromItem qf $ mkSQLFunctionArgs fnArgs
mkSQLFunctionArgs (FunctionArgsExp positional named) =
S.FunctionArgs positional named
newSelFrom = FromIden $ toIden funcAls
QualifiedObject sn fn = qf
funcAls = S.Alias $ Iden $
getSchemaTxt sn <> "_" <> getFunctionTxt fn <> "__result"

View File

@@ -353,40 +353,6 @@ insertFunctionArg argName index value (FunctionArgsExp positional named) =
where
insertAt i a = toList . Seq.insertAt i a . Seq.fromList
data AnnFnSelG s v
= AnnFnSel
{ _afFn :: !QualifiedFunction
, _afFnArgs :: !(FunctionArgsExpG v)
, _afSelect :: !s
} deriving (Show, Eq)
traverseAnnFnSel
:: (Applicative f)
=> (a -> f b) -> (v -> f w)
-> AnnFnSelG a v -> f (AnnFnSelG b w)
traverseAnnFnSel fs fv (AnnFnSel fn fnArgs s) =
AnnFnSel fn <$> traverse fv fnArgs <*> fs s
type AnnFnSelSimpleG v = AnnFnSelG (AnnSimpleSelG v) v
type AnnFnSelSimple = AnnFnSelSimpleG S.SQLExp
traverseAnnFnSimple
:: (Applicative f)
=> (a -> f b)
-> AnnFnSelSimpleG a -> f (AnnFnSelSimpleG b)
traverseAnnFnSimple f =
traverseAnnFnSel (traverseAnnSimpleSel f) f
type AnnFnSelAggG v = AnnFnSelG (AnnAggSelG v) v
type AnnFnSelAgg = AnnFnSelAggG S.SQLExp
traverseAnnFnAgg
:: (Applicative f)
=> (a -> f b)
-> AnnFnSelAggG a -> f (AnnFnSelAggG b)
traverseAnnFnAgg f =
traverseAnnFnSel (traverseAnnAggSel f) f
data BaseNode
= BaseNode
{ _bnPrefix :: !Iden