From 9128c69a805060e9d19ad46c0ebf11f183a42014 Mon Sep 17 00:00:00 2001 From: rakeshkky <12475069+rakeshkky@users.noreply.github.com> Date: Tue, 10 Mar 2020 18:15:47 +0530 Subject: [PATCH 1/3] fix postgres query error when computed fields included in mutation response, fix #4035 --- .../src-lib/Hasura/GraphQL/Resolve/Insert.hs | 2 +- server/src-lib/Hasura/RQL/DML/Mutation.hs | 9 +- server/src-lib/Hasura/RQL/DML/Returning.hs | 86 +++++++++++++------ server/src-lib/Hasura/RQL/GBoolExp.hs | 2 +- server/src-lib/Hasura/RQL/Types/Table.hs | 5 ++ server/src-lib/Hasura/SQL/Types.hs | 5 -- ...r_user_role_insert_check_perm_success.yaml | 5 ++ .../insert/permissions/schema_setup.yaml | 21 ++++- .../insert/permissions/schema_teardown.yaml | 1 + .../update/permissions/schema_setup.yaml | 31 ++++++- .../update/permissions/schema_teardown.yaml | 1 + .../permissions/user_update_author.yaml | 36 ++++++++ server/tests-py/test_graphql_mutations.py | 5 +- 13 files changed, 170 insertions(+), 39 deletions(-) create mode 100644 server/tests-py/queries/graphql_mutation/update/permissions/user_update_author.yaml diff --git a/server/src-lib/Hasura/GraphQL/Resolve/Insert.hs b/server/src-lib/Hasura/GraphQL/Resolve/Insert.hs index 34ae37c38b7c3..7b0d614ff4d34 100644 --- a/server/src-lib/Hasura/GraphQL/Resolve/Insert.hs +++ b/server/src-lib/Hasura/GraphQL/Resolve/Insert.hs @@ -457,7 +457,7 @@ insertMultipleObjects strfyNum role tn multiObjIns addCols mutOutput errP = let affRows = sum $ map fst insResps columnValues = catMaybes $ map snd insResps cteExp <- mkSelCTEFromColVals tn tableColInfos columnValues - let sql = toSQL $ RR.mkMutationOutputExp tn (Just affRows) cteExp mutOutput strfyNum + let sql = toSQL $ RR.mkMutationOutputExp tn tableColInfos (Just affRows) cteExp mutOutput strfyNum runIdentity . Q.getRow <$> Q.rawQE dmlTxErrorHandler (Q.fromBuilder sql) [] False diff --git a/server/src-lib/Hasura/RQL/DML/Mutation.hs b/server/src-lib/Hasura/RQL/DML/Mutation.hs index c201f7fcebd2d..9438880a09f2b 100644 --- a/server/src-lib/Hasura/RQL/DML/Mutation.hs +++ b/server/src-lib/Hasura/RQL/DML/Mutation.hs @@ -38,19 +38,19 @@ runMutation mut = hasNestedFld $ _mOutput mut mutateAndReturn :: Mutation -> Q.TxE QErr EncJSON -mutateAndReturn (Mutation qt (cte, p) mutationOutput _ strfyNum) = +mutateAndReturn (Mutation qt (cte, p) mutationOutput allCols strfyNum) = encJFromBS . runIdentity . Q.getRow <$> Q.rawQE dmlTxErrorHandler (Q.fromBuilder $ toSQL selWith) (toList p) True where - selWith = mkMutationOutputExp qt Nothing cte mutationOutput strfyNum + selWith = mkMutationOutputExp qt allCols Nothing cte mutationOutput strfyNum mutateAndSel :: Mutation -> Q.TxE QErr EncJSON mutateAndSel (Mutation qt q mutationOutput allCols strfyNum) = do -- Perform mutation and fetch unique columns MutateResp _ columnVals <- mutateAndFetchCols qt allCols q strfyNum selCTE <- mkSelCTEFromColVals qt allCols columnVals - let selWith = mkMutationOutputExp qt Nothing selCTE mutationOutput strfyNum + let selWith = mkMutationOutputExp qt allCols Nothing selCTE mutationOutput strfyNum -- Perform select query and fetch returning fields encJFromBS . runIdentity . Q.getRow <$> Q.rawQE dmlTxErrorHandler (Q.fromBuilder $ toSQL selWith) [] True @@ -108,8 +108,7 @@ mkSelCTEFromColVals qt allCols colVals = where rowAlias = Iden "row" extractor = S.selectStar' $ S.QualIden rowAlias $ Just $ S.TypeAnn $ toSQLTxt qt - sortedCols = flip sortBy allCols $ \lCol rCol -> - compare (pgiPosition lCol) (pgiPosition rCol) + sortedCols = sortCols allCols mkTupsFromColVal colVal = fmap S.TupleExp $ forM sortedCols $ \ci -> do let pgCol = pgiColumn ci diff --git a/server/src-lib/Hasura/RQL/DML/Returning.hs b/server/src-lib/Hasura/RQL/DML/Returning.hs index a65d5e248a4ca..344fc79426a43 100644 --- a/server/src-lib/Hasura/RQL/DML/Returning.hs +++ b/server/src-lib/Hasura/RQL/DML/Returning.hs @@ -93,12 +93,8 @@ mkDefaultMutFlds = MOutMultirowFields . \case where mutFlds = [("affected_rows", MCount)] -qualTableToAliasIden :: QualifiedTable -> Iden -qualTableToAliasIden qt = - Iden $ snakeCaseTable qt <> "__mutation_result_alias" - -mkMutFldExp :: QualifiedTable -> Maybe Int -> Bool -> MutFld -> S.SQLExp -mkMutFldExp qt preCalAffRows strfyNum = \case +mkMutFldExp :: Iden -> Maybe Int -> Bool -> MutFld -> S.SQLExp +mkMutFldExp cteAlias preCalAffRows strfyNum = \case MCount -> let countExp = S.SESelect $ S.mkSelect @@ -112,28 +108,70 @@ mkMutFldExp qt preCalAffRows strfyNum = \case tabPerm = TablePerm annBoolExpTrue Nothing in S.SESelect $ mkSQLSelect JASMultipleRows $ AnnSelG selFlds tabFrom tabPerm noTableArgs strfyNum - where - cteAlias = qualTableToAliasIden qt +{- Note [Mutation output expression] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +An example output expression for INSERT mutation: + +WITH "__mutation_result_alias" AS ( + INSERT INTO ([..]) + VALUES + ([..]) + ON CONFLICT ON CONSTRAINT "" DO NOTHING RETURNING *, + -- An extra column expression which performs the 'CHECK' validation + CASE + WHEN () THEN NULL + ELSE "hdb_catalog"."check_violation"('insert check constraint failed') + END +), +"__all_columns_alias" AS ( + -- Only extract columns from mutated rows. Columns sorted by ordinal position so that + -- resulted rows can be casted to table type. + SELECT ([..]) + FROM + "__mutation_result_alias" +) +