mirror of
https://github.com/hasura/graphql-engine.git
synced 2024-12-18 13:02:11 +03:00
8f6b19d6f1
### Description What component does this PR affect? - [x] Server ### Related Issue #494 ### Solution and Design Use `quote_ident()` SQL function over `constraint_name` in insert trigger function definition. ### Type - [x] Bug fix (non-breaking change which fixes an issue)
65 lines
2.8 KiB
Haskell
65 lines
2.8 KiB
Haskell
{-# LANGUAGE OverloadedStrings #-}
|
|
|
|
module Hasura.RQL.DDL.Permission.Triggers where
|
|
|
|
import Hasura.Prelude
|
|
import Hasura.SQL.Types
|
|
|
|
import qualified Database.PG.Query as Q
|
|
import qualified Hasura.SQL.DML as S
|
|
|
|
import qualified Data.ByteString.Builder as BB
|
|
|
|
buildInsTrig :: QualifiedTable -> Q.Query
|
|
buildInsTrig qt@(QualifiedTable _ tn) =
|
|
Q.fromBuilder $ mconcat
|
|
[ BB.string7 "CREATE TRIGGER " <> toSQL tn
|
|
, BB.string7 " INSTEAD OF INSERT ON " <> toSQL qt
|
|
, BB.string7 " FOR EACH ROW EXECUTE PROCEDURE "
|
|
, toSQL qt <> BB.string7 "();"
|
|
]
|
|
|
|
dropInsTrigFn :: QualifiedTable -> Q.Query
|
|
dropInsTrigFn fn =
|
|
Q.fromBuilder $ BB.string7 "DROP FUNCTION " <> toSQL fn <> "()"
|
|
|
|
buildInsTrigFn :: QualifiedTable -> QualifiedTable -> S.BoolExp -> Q.Query
|
|
buildInsTrigFn fn tn be =
|
|
Q.fromBuilder $ mconcat
|
|
[ BB.string7 "CREATE OR REPLACE FUNCTION " <> toSQL fn
|
|
, BB.string7 "() RETURNS trigger LANGUAGE plpgsql AS $$ "
|
|
, BB.string7 "DECLARE r " <> toSQL tn <> "%ROWTYPE; "
|
|
, BB.string7 "DECLARE conflict_clause jsonb; DECLARE action text; "
|
|
, BB.string7 "DECLARE constraint_name text; "
|
|
, BB.string7 "DECLARE set_expression text; "
|
|
, BB.string7 "BEGIN "
|
|
, BB.string7 "conflict_clause = current_setting('hasura.conflict_clause')::jsonb; "
|
|
, BB.string7 "IF (" <> toSQL be <> BB.string7 ") THEN "
|
|
, BB.string7 "CASE "
|
|
, BB.string7 "WHEN conflict_clause = 'null'::jsonb THEN INSERT INTO " <> toSQL tn
|
|
, BB.string7 " VALUES (NEW.*) RETURNING * INTO r; RETURN r; "
|
|
, BB.string7 "ELSE "
|
|
, BB.string7 "action = conflict_clause ->> 'action'; "
|
|
, BB.string7 "constraint_name = conflict_clause ->> 'constraint'; "
|
|
, BB.string7 "set_expression = conflict_clause ->> 'set_expression'; "
|
|
, BB.string7 "IF action is NOT NULL THEN "
|
|
, BB.string7 "CASE "
|
|
, BB.string7 "WHEN action = 'ignore'::text AND constraint_name IS NULL THEN "
|
|
, BB.string7 "INSERT INTO " <> toSQL tn
|
|
, BB.string7 " VALUES (NEW.*) ON CONFLICT DO NOTHING RETURNING * INTO r; RETURN r; "
|
|
, BB.string7 "WHEN action = 'ignore'::text AND constraint_name is NOT NULL THEN "
|
|
, BB.string7 "EXECUTE 'INSERT INTO " <> toSQL tn
|
|
, BB.string7 " VALUES ($1.*) ON CONFLICT ON CONSTRAINT ' || quote_ident(constraint_name) || ' DO NOTHING RETURNING *'"
|
|
, BB.string7 " INTO r USING NEW; RETURN r; "
|
|
, BB.string7 "ELSE EXECUTE 'INSERT INTO " <> toSQL tn
|
|
, BB.string7 " VALUES ($1.*) ON CONFLICT ON CONSTRAINT ' || quote_ident(constraint_name) || ' DO UPDATE ' || set_expression || "
|
|
, BB.string7 "' RETURNING *' INTO r USING NEW; RETURN r; "
|
|
, BB.string7 "END CASE; "
|
|
, BB.string7 "ELSE RAISE internal_error using message = 'action is not found'; RETURN NULL; "
|
|
, BB.string7 "END IF; "
|
|
, BB.string7 "END CASE; "
|
|
, BB.string7 "ELSE RAISE check_violation using message = 'insert check constraint failed'; RETURN NULL; "
|
|
, BB.string7 "END IF; "
|
|
, BB.string7 "END $$;"
|
|
]
|