Skip to content

Commit

Permalink
support postgres event trigger in schema.sql
Browse files Browse the repository at this point in the history
  • Loading branch information
mpscholten committed Nov 12, 2024
1 parent 51d17d2 commit e2360aa
Show file tree
Hide file tree
Showing 6 changed files with 91 additions and 2 deletions.
11 changes: 11 additions & 0 deletions Test/IDE/SchemaDesigner/CompilerSpec.hs
Original file line number Diff line number Diff line change
Expand Up @@ -998,6 +998,17 @@ tests = do
} ]
compileSql statements `shouldBe` sql

it "should compile 'CREATE EVENT TRIGGER ..' statements" do
let sql = "CREATE EVENT TRIGGER trigger_update_schema ON ddl_command_end WHEN TAG IN ('CREATE TABLE', 'ALTER TABLE', 'DROP TABLE') EXECUTE FUNCTION update_tables_and_columns();\n"
let statements = [ CreateEventTrigger
{ name = "trigger_update_schema"
, eventOn = "ddl_command_end"
, whenCondition = Just (InExpression (VarExpression "TAG") (InArrayExpression [TextExpression "CREATE TABLE", TextExpression "ALTER TABLE", TextExpression "DROP TABLE"]))
, functionName = "update_tables_and_columns"
, arguments = []
} ]
compileSql statements `shouldBe` sql

it "should compile 'BEGIN;' statements" do
let sql = "BEGIN;\n"
let statements = [ Begin ]
Expand Down
15 changes: 15 additions & 0 deletions Test/IDE/SchemaDesigner/ParserSpec.hs
Original file line number Diff line number Diff line change
Expand Up @@ -1102,6 +1102,21 @@ COMMENT ON EXTENSION "uuid-ossp" IS 'generate universally unique identifiers (UU
, arguments = [TextExpression "hello"]
}

it "should parse 'CREATE EVENT TRIGGER ..' statements" do
let sql = cs [plain|
CREATE EVENT TRIGGER trigger_update_schema
ON ddl_command_end
WHEN TAG IN ('CREATE TABLE', 'ALTER TABLE', 'DROP TABLE')
EXECUTE FUNCTION update_tables_and_columns();
|]
parseSql sql `shouldBe` CreateEventTrigger
{ name = "trigger_update_schema"
, eventOn = "ddl_command_end"
, whenCondition = Just (InExpression (VarExpression "TAG") (InArrayExpression [TextExpression "CREATE TABLE", TextExpression "ALTER TABLE", TextExpression "DROP TABLE"]))
, functionName = "update_tables_and_columns"
, arguments = []
}

it "should parse 'ALTER SEQUENCE ..' statements" do
let sql = cs [plain|ALTER SEQUENCE public.a OWNED BY public.b.serial_number;|]
parseSql sql `shouldBe` UnknownStatement { raw = "ALTER SEQUENCE public.a OWNED BY public.b.serial_number" }
Expand Down
1 change: 1 addition & 0 deletions ihp-ide/IHP/IDE/CodeGen/MigrationGenerator.hs
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,7 @@ diffSchemas targetSchema' actualSchema' = (drop <> create)
toDropStatement CreatePolicy { tableName, name } = Just DropPolicy { tableName, policyName = name }
toDropStatement CreateFunction { functionName } = Just DropFunction { functionName }
toDropStatement CreateTrigger { name, tableName } = Just DropTrigger { name, tableName }
toDropStatement CreateEventTrigger { name } = Just DropEventTrigger { name }
toDropStatement otherwise = Nothing


Expand Down
4 changes: 4 additions & 0 deletions ihp-ide/IHP/IDE/SchemaDesigner/Compiler.hs
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@ compileStatement UnknownStatement { raw } = raw <> ";"
compileStatement Set { name, value } = "SET " <> compileIdentifier name <> " = " <> compileExpression value <> ";"
compileStatement SelectStatement { query } = "SELECT " <> query <> ";"
compileStatement DropTrigger { name, tableName } = "DROP TRIGGER " <> compileIdentifier name <> " ON " <> compileIdentifier tableName <> ";"
compileStatement CreateEventTrigger { name, eventOn, whenCondition, functionName, arguments } = "CREATE EVENT TRIGGER " <> compileIdentifier name <> " ON " <> compileIdentifier eventOn <> " " <> (maybe "" (\expression -> "WHEN " <> compileExpression expression) whenCondition) <> " EXECUTE FUNCTION " <> compileExpression (CallExpression functionName arguments) <> ";"
compileStatement DropEventTrigger { name } = "DROP EVENT TRIGGER " <> compileIdentifier name <> ";"

-- | Emit a PRIMARY KEY constraint when there are multiple primary key columns
compilePrimaryKeyConstraint :: PrimaryKeyConstraint -> Maybe Text
Expand Down Expand Up @@ -132,6 +134,7 @@ compileExpression (EqExpression a b) = compileExpressionWithOptionalParenthese a
compileExpression (IsExpression a (NotExpression b)) = compileExpressionWithOptionalParenthese a <> " IS NOT " <> compileExpressionWithOptionalParenthese b -- 'IS (NOT NULL)' => 'IS NOT NULL'
compileExpression (IsExpression a b) = compileExpressionWithOptionalParenthese a <> " IS " <> compileExpressionWithOptionalParenthese b
compileExpression (InExpression a b) = compileExpressionWithOptionalParenthese a <> " IN " <> compileExpressionWithOptionalParenthese b
compileExpression (InArrayExpression values) = "(" <> intercalate ", " (map compileExpression values) <> ")"
compileExpression (NotExpression a) = "NOT " <> compileExpressionWithOptionalParenthese a
compileExpression (AndExpression a b) = compileExpressionWithOptionalParenthese a <> " AND " <> compileExpressionWithOptionalParenthese b
compileExpression (OrExpression a b) = compileExpressionWithOptionalParenthese a <> " OR " <> compileExpressionWithOptionalParenthese b
Expand Down Expand Up @@ -161,6 +164,7 @@ compileExpressionWithOptionalParenthese expr@(IntExpression {}) = compileExpress
compileExpressionWithOptionalParenthese expr@(DoubleExpression {}) = compileExpression expr
compileExpressionWithOptionalParenthese expr@(DotExpression (VarExpression {}) b) = compileExpression expr
compileExpressionWithOptionalParenthese expr@(ConcatenationExpression a b ) = compileExpression expr
compileExpressionWithOptionalParenthese expr@(InArrayExpression values) = compileExpression expr
compileExpressionWithOptionalParenthese expression = "(" <> compileExpression expression <> ")"

compareStatement (CreateEnumType {}) _ = LT
Expand Down
56 changes: 54 additions & 2 deletions ihp-ide/IHP/IDE/SchemaDesigner/Parser.hs
Original file line number Diff line number Diff line change
Expand Up @@ -464,7 +464,7 @@ table = [
, binary "||" ConcatenationExpression

, binary "IS" IsExpression
, binary "IN" InExpression
, inExpr
, prefix "NOT" NotExpression
, prefix "EXISTS" ExistsExpression
, typeCast
Expand All @@ -488,6 +488,11 @@ table = [
char '.'
name <- identifier
pure $ \expr -> DotExpression expr name

inExpr = Postfix do
lexeme "IN"
right <- try inArrayExpression <|> expression
pure $ \expr -> InExpression expr right

-- | Parses a SQL expression
--
Expand Down Expand Up @@ -548,7 +553,10 @@ selectExpr = do

whereClause Nothing <|> explicitAs <|> implicitAs


inArrayExpression :: Parser Expression
inArrayExpression = do
values <- between (char '(') (char ')') (expression `sepBy` (char ',' >> space))
pure (InArrayExpression values)



Expand Down Expand Up @@ -630,6 +638,38 @@ createFunction = do

createTrigger = do
lexeme "CREATE"
createEventTrigger <|> createTrigger'

createEventTrigger = do
lexeme "EVENT"
lexeme "TRIGGER"

name <- qualifiedIdentifier
lexeme "ON"
eventOn <- identifier

whenCondition <- optional do
lexeme "WHEN"
expression

lexeme "EXECUTE"
(lexeme "FUNCTION") <|> (lexeme "PROCEDURE")

(CallExpression functionName arguments) <- callExpr

char ';'

pure CreateEventTrigger
{ name
, eventOn
, whenCondition
, functionName
, arguments
}



createTrigger' = do
lexeme "TRIGGER"

name <- qualifiedIdentifier
Expand Down Expand Up @@ -875,13 +915,25 @@ dropPolicy = do

dropTrigger = do
lexeme "DROP"

dropEventTrigger <|> dropTrigger'

dropTrigger' = do
lexeme "TRIGGER"
name <- qualifiedIdentifier
lexeme "ON"
tableName <- qualifiedIdentifier
char ';'
pure DropTrigger { name, tableName }


dropEventTrigger = do
lexeme "EVENT"
lexeme "TRIGGER"
name <- qualifiedIdentifier
char ';'
pure DropEventTrigger { name }

createSequence = do
lexeme "CREATE"
lexeme "SEQUENCE"
Expand Down
6 changes: 6 additions & 0 deletions ihp-ide/IHP/IDE/SchemaDesigner/Types.hs
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,12 @@ data Statement
| DropDefaultValue { tableName :: Text, columnName :: Text }
-- | CREATE TRIGGER ..;
| CreateTrigger { name :: !Text, eventWhen :: !TriggerEventWhen, event :: !TriggerEvent, tableName :: !Text, for :: !TriggerFor, whenCondition :: Maybe Expression, functionName :: !Text, arguments :: ![Expression] }
-- | CREATE EVENT TRIGGER ..;
| CreateEventTrigger { name :: !Text, eventOn :: !Text, whenCondition :: Maybe Expression, functionName :: !Text, arguments :: ![Expression] }
-- | DROP TRIGGER .. ON ..;
| DropTrigger { name :: !Text, tableName :: !Text }
-- | DROP EVENT TRIGGER ..;
| DropEventTrigger { name :: !Text }
-- | BEGIN;
| Begin
-- | COMMIT;
Expand Down Expand Up @@ -165,6 +169,8 @@ data Expression =
| IsExpression Expression Expression
-- | a IN b
| InExpression Expression Expression
-- | ('a', 'b')
| InArrayExpression [Expression]
-- | NOT a
| NotExpression Expression
-- | EXISTS a
Expand Down

0 comments on commit e2360aa

Please sign in to comment.