mirror of
https://github.com/hasura/graphql-engine.git
synced 2024-09-19 06:28:39 +03:00
server: drop the dropping trigger logic while creating/recreating an event trigger
PR-URL: https://github.com/hasura/graphql-engine-mono/pull/4101 GitOrigin-RevId: 12a2736e4d88dfb8379cd54f4beaedac32795d7d
This commit is contained in:
parent
4189122a3d
commit
330f9b6e26
@ -494,7 +494,7 @@ dropTriggerOp triggerName triggerOp =
|
||||
getDropFuncSql op =
|
||||
"DROP FUNCTION IF EXISTS"
|
||||
<> " hdb_catalog."
|
||||
<> pgIdenTrigger op triggerName
|
||||
<> unQualifiedTriggerName (pgIdenTrigger op triggerName)
|
||||
<> "()"
|
||||
<> " CASCADE"
|
||||
|
||||
@ -564,15 +564,26 @@ unlockEventsTx eventIds =
|
||||
|
||||
---- Postgres event trigger utility functions ---------------------
|
||||
|
||||
-- | QualifiedTriggerName is a type to store the name of the SQL trigger.
|
||||
-- An example of it is `"notify_hasura_users_all_INSERT"` where `users_all`
|
||||
-- is the name of the event trigger.
|
||||
newtype QualifiedTriggerName = QualifiedTriggerName {unQualifiedTriggerName :: Text}
|
||||
deriving (Show, Eq, Q.ToPrepArg)
|
||||
|
||||
pgTriggerName :: Ops -> TriggerName -> QualifiedTriggerName
|
||||
pgTriggerName op trn = qualifyTriggerName op $ triggerNameToTxt trn
|
||||
where
|
||||
qualifyTriggerName op' trn' =
|
||||
QualifiedTriggerName $ "notify_hasura_" <> trn' <> "_" <> tshow op'
|
||||
|
||||
pgIdenTrigger :: Ops -> TriggerName -> QualifiedTriggerName
|
||||
pgIdenTrigger op = QualifiedTriggerName . pgFmtIdentifier . unQualifiedTriggerName . pgTriggerName op
|
||||
|
||||
-- | pgIdenTrigger is a method used to construct the name of the pg function
|
||||
-- used for event triggers which are present in the hdb_catalog schema.
|
||||
pgIdenTrigger :: Ops -> TriggerName -> Text
|
||||
pgIdenTrigger op trn = pgFmtIdentifier . qualifyTriggerName op $ triggerNameToTxt trn
|
||||
where
|
||||
qualifyTriggerName op' trn' = "notify_hasura_" <> trn' <> "_" <> tshow op'
|
||||
|
||||
-- | Define the pgSQL trigger functions on database events.
|
||||
mkTriggerQ ::
|
||||
mkTriggerFunctionQ ::
|
||||
forall pgKind m.
|
||||
(Backend ('Postgres pgKind), MonadTx m, MonadReader ServerConfigCtx m) =>
|
||||
TriggerName ->
|
||||
@ -580,50 +591,51 @@ mkTriggerQ ::
|
||||
[ColumnInfo ('Postgres pgKind)] ->
|
||||
Ops ->
|
||||
SubscribeOpSpec ('Postgres pgKind) ->
|
||||
m ()
|
||||
mkTriggerQ trn qt@(QualifiedObject schema table) allCols op (SubscribeOpSpec listenColumns deliveryColumns') = do
|
||||
m QualifiedTriggerName
|
||||
mkTriggerFunctionQ triggerName (QualifiedObject schema table) allCols op (SubscribeOpSpec listenColumns deliveryColumns') = do
|
||||
strfyNum <- stringifyNum . _sccSQLGenCtx <$> ask
|
||||
liftTx $
|
||||
Q.multiQE defaultTxErrorHandler $
|
||||
Q.fromText . TL.toStrict $
|
||||
let -- If there are no specific delivery columns selected by user then all the columns will be delivered
|
||||
-- in payload hence 'SubCStar'.
|
||||
deliveryColumns = fromMaybe SubCStar deliveryColumns'
|
||||
getApplicableColumns = \case
|
||||
SubCStar -> allCols
|
||||
SubCArray cols -> getColInfos cols allCols
|
||||
let dbQualifiedTriggerName = pgIdenTrigger op triggerName
|
||||
() <-
|
||||
liftTx $
|
||||
Q.multiQE defaultTxErrorHandler $
|
||||
Q.fromText . TL.toStrict $
|
||||
let -- If there are no specific delivery columns selected by user then all the columns will be delivered
|
||||
-- in payload hence 'SubCStar'.
|
||||
deliveryColumns = fromMaybe SubCStar deliveryColumns'
|
||||
getApplicableColumns = \case
|
||||
SubCStar -> allCols
|
||||
SubCArray cols -> getColInfos cols allCols
|
||||
|
||||
-- Columns that should be present in the payload. By default, all columns are present.
|
||||
applicableDeliveryCols = getApplicableColumns deliveryColumns
|
||||
getRowExpression opVar = applyRowToJson' $ mkRowExpression opVar strfyNum applicableDeliveryCols
|
||||
-- Columns that should be present in the payload. By default, all columns are present.
|
||||
applicableDeliveryCols = getApplicableColumns deliveryColumns
|
||||
getRowExpression opVar = applyRowToJson' $ mkRowExpression opVar strfyNum applicableDeliveryCols
|
||||
|
||||
-- Columns that user subscribed to listen for changes. By default, we listen on all columns.
|
||||
applicableListenCols = getApplicableColumns listenColumns
|
||||
renderRow opVar = applyRow $ mkRowExpression opVar strfyNum applicableListenCols
|
||||
-- Columns that user subscribed to listen for changes. By default, we listen on all columns.
|
||||
applicableListenCols = getApplicableColumns listenColumns
|
||||
renderRow opVar = applyRow $ mkRowExpression opVar strfyNum applicableListenCols
|
||||
|
||||
oldDataExp = case op of
|
||||
INSERT -> SENull
|
||||
UPDATE -> getRowExpression OLD
|
||||
DELETE -> getRowExpression OLD
|
||||
MANUAL -> SENull
|
||||
newDataExp = case op of
|
||||
INSERT -> getRowExpression NEW
|
||||
UPDATE -> getRowExpression NEW
|
||||
DELETE -> SENull
|
||||
MANUAL -> SENull
|
||||
oldDataExp = case op of
|
||||
INSERT -> SENull
|
||||
UPDATE -> getRowExpression OLD
|
||||
DELETE -> getRowExpression OLD
|
||||
MANUAL -> SENull
|
||||
newDataExp = case op of
|
||||
INSERT -> getRowExpression NEW
|
||||
UPDATE -> getRowExpression NEW
|
||||
DELETE -> SENull
|
||||
MANUAL -> SENull
|
||||
|
||||
name = triggerNameToTxt trn
|
||||
qualifiedTriggerName = pgIdenTrigger op trn
|
||||
qualifiedTable = toSQLTxt qt
|
||||
schemaName = pgFmtLit $ getSchemaTxt schema
|
||||
tableName = pgFmtLit $ getTableTxt table
|
||||
name = triggerNameToTxt triggerName
|
||||
qualifiedTriggerName = unQualifiedTriggerName dbQualifiedTriggerName
|
||||
schemaName = pgFmtLit $ getSchemaTxt schema
|
||||
tableName = pgFmtLit $ getTableTxt table
|
||||
|
||||
operation = tshow op
|
||||
oldRow = toSQLTxt $ renderRow OLD
|
||||
newRow = toSQLTxt $ renderRow NEW
|
||||
oldPayloadExpression = toSQLTxt oldDataExp
|
||||
newPayloadExpression = toSQLTxt newDataExp
|
||||
in $(makeRelativeToProject "src-rsr/trigger.sql.shakespeare" >>= ST.stextFile)
|
||||
oldRow = toSQLTxt $ renderRow OLD
|
||||
newRow = toSQLTxt $ renderRow NEW
|
||||
oldPayloadExpression = toSQLTxt oldDataExp
|
||||
newPayloadExpression = toSQLTxt newDataExp
|
||||
in $(makeRelativeToProject "src-rsr/trigger.sql.shakespeare" >>= ST.stextFile)
|
||||
pure dbQualifiedTriggerName
|
||||
where
|
||||
applyRowToJson' e = SEFnApp "row_to_json" [e] Nothing
|
||||
applyRow e = SEFnApp "row" [e] Nothing
|
||||
@ -645,6 +657,50 @@ mkTriggerQ trn qt@(QualifiedObject schema table) allCols op (SubscribeOpSpec lis
|
||||
| otherwise = Extractor sqlExp Nothing
|
||||
getAlias col = toAlias $ Identifier $ getPGColTxt (ciColumn col)
|
||||
|
||||
checkIfTriggerExists ::
|
||||
QualifiedTriggerName ->
|
||||
QualifiedTable ->
|
||||
Q.TxE QErr Bool
|
||||
checkIfTriggerExists (QualifiedTriggerName triggerName) table =
|
||||
fmap (runIdentity . Q.getRow) $
|
||||
Q.withQE
|
||||
defaultTxErrorHandler
|
||||
[Q.sql|
|
||||
SELECT EXISTS (
|
||||
SELECT 1
|
||||
FROM pg_trigger
|
||||
WHERE NOT tgisinternal
|
||||
AND tgname = $1 AND tgrelid = $2::regclass
|
||||
)
|
||||
|]
|
||||
(triggerName, qualifiedObjectToText table)
|
||||
True
|
||||
|
||||
mkTrigger ::
|
||||
forall pgKind m.
|
||||
(Backend ('Postgres pgKind), MonadTx m, MonadReader ServerConfigCtx m) =>
|
||||
TriggerName ->
|
||||
QualifiedTable ->
|
||||
[ColumnInfo ('Postgres pgKind)] ->
|
||||
Ops ->
|
||||
SubscribeOpSpec ('Postgres pgKind) ->
|
||||
m ()
|
||||
mkTrigger triggerName table allCols op subOpSpec = do
|
||||
-- create/replace the trigger function
|
||||
dbTriggerName <- mkTriggerFunctionQ triggerName table allCols op subOpSpec
|
||||
-- check if the SQL trigger exists and only if the SQL trigger doesn't exist
|
||||
-- we create the SQL trigger.
|
||||
doesTriggerExist <- liftTx $ checkIfTriggerExists (pgTriggerName op triggerName) table
|
||||
unless doesTriggerExist $
|
||||
let sqlQuery =
|
||||
Q.fromText $ createTriggerSQL dbTriggerName (toSQLTxt table) (tshow op)
|
||||
in liftTx $ Q.unitQE defaultTxErrorHandler sqlQuery () False
|
||||
where
|
||||
createTriggerSQL (QualifiedTriggerName triggerNameTxt) tableName opText =
|
||||
[ST.st|
|
||||
CREATE TRIGGER #{triggerNameTxt} AFTER #{opText} ON #{tableName} FOR EACH ROW EXECUTE PROCEDURE hdb_catalog.#{triggerNameTxt}()
|
||||
|]
|
||||
|
||||
mkAllTriggersQ ::
|
||||
forall pgKind m.
|
||||
(Backend ('Postgres pgKind), MonadTx m, MonadReader ServerConfigCtx m) =>
|
||||
@ -653,7 +709,7 @@ mkAllTriggersQ ::
|
||||
[ColumnInfo ('Postgres pgKind)] ->
|
||||
TriggerOpsDef ('Postgres pgKind) ->
|
||||
m ()
|
||||
mkAllTriggersQ trn qt allCols fullspec = do
|
||||
onJust (tdInsert fullspec) (mkTriggerQ trn qt allCols INSERT)
|
||||
onJust (tdUpdate fullspec) (mkTriggerQ trn qt allCols UPDATE)
|
||||
onJust (tdDelete fullspec) (mkTriggerQ trn qt allCols DELETE)
|
||||
mkAllTriggersQ triggerName table allCols fullspec = do
|
||||
onJust (tdInsert fullspec) (mkTrigger triggerName table allCols INSERT)
|
||||
onJust (tdUpdate fullspec) (mkTrigger triggerName table allCols UPDATE)
|
||||
onJust (tdDelete fullspec) (mkTrigger triggerName table allCols DELETE)
|
||||
|
@ -35,5 +35,3 @@ CREATE OR REPLACE function hdb_catalog.#{qualifiedTriggerName}() RETURNS trigger
|
||||
RETURN NULL;
|
||||
END;
|
||||
$$;
|
||||
DROP TRIGGER IF EXISTS #{qualifiedTriggerName} ON #{qualifiedTable};
|
||||
CREATE TRIGGER #{qualifiedTriggerName} AFTER #{operation} ON #{qualifiedTable} FOR EACH ROW EXECUTE PROCEDURE hdb_catalog.#{qualifiedTriggerName}();
|
||||
|
@ -270,7 +270,7 @@ def validate_gql_ws_q(hge_ctx, conf, headers, retry=False, via_subscription=Fals
|
||||
print(ws_client.ws_url)
|
||||
if not headers or len(headers) == 0:
|
||||
ws_client.init({})
|
||||
|
||||
|
||||
if ws_client.remote_closed or ws_client.is_closing:
|
||||
ws_client.create_conn()
|
||||
if not headers or len(headers) == 0 or hge_ctx.hge_key is None:
|
||||
|
Loading…
Reference in New Issue
Block a user