forked from opengaussexamples/examples
add trigger
This commit is contained in:
parent
fe805b9721
commit
8a8b13c793
|
|
@ -4,12 +4,10 @@
|
|||
<option name="autoReloadType" value="SELECTIVE" />
|
||||
</component>
|
||||
<component name="ChangeListManager">
|
||||
<list default="true" id="d8d12963-4777-48e3-9669-309cf5e41d60" name="更改" comment="add trigger document">
|
||||
<change afterPath="$PROJECT_DIR$/src/main/java/Parser/AST/Trigger/TriggerConditionNode.java" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/src/main/java/Parser/AST/Trigger/TriggerNameNode.java" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/src/main/java/Parser/AST/Trigger/TriggerNode.java" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/src/main/java/Parser/AST/Trigger/TriggerObjNode.java" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/src/main/java/Parser/AST/Trigger/TriggerOptionNode.java" afterDir="false" />
|
||||
<list default="true" id="d8d12963-4777-48e3-9669-309cf5e41d60" name="更改" comment="add trigger ast classes">
|
||||
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/main/java/Lexer/OracleLexer.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/java/Lexer/OracleLexer.java" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/main/java/Parser/OracleParser.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/java/Parser/OracleParser.java" afterDir="false" />
|
||||
</list>
|
||||
<option name="SHOW_DIALOG" value="false" />
|
||||
<option name="HIGHLIGHT_CONFLICTS" value="true" />
|
||||
|
|
@ -107,13 +105,6 @@
|
|||
<option name="presentableId" value="Default" />
|
||||
<updated>1723106789329</updated>
|
||||
</task>
|
||||
<task id="LOCAL-00038" summary="add join class">
|
||||
<created>1726112198383</created>
|
||||
<option name="number" value="00038" />
|
||||
<option name="presentableId" value="LOCAL-00038" />
|
||||
<option name="project" value="LOCAL" />
|
||||
<updated>1726112198384</updated>
|
||||
</task>
|
||||
<task id="LOCAL-00039" summary="add join">
|
||||
<created>1726127728384</created>
|
||||
<option name="number" value="00039" />
|
||||
|
|
@ -450,7 +441,14 @@
|
|||
<option name="project" value="LOCAL" />
|
||||
<updated>1726588739459</updated>
|
||||
</task>
|
||||
<option name="localTasksCounter" value="87" />
|
||||
<task id="LOCAL-00087" summary="add trigger ast classes">
|
||||
<created>1726590115566</created>
|
||||
<option name="number" value="00087" />
|
||||
<option name="presentableId" value="LOCAL-00087" />
|
||||
<option name="project" value="LOCAL" />
|
||||
<updated>1726590115566</updated>
|
||||
</task>
|
||||
<option name="localTasksCounter" value="88" />
|
||||
<servers />
|
||||
</component>
|
||||
<component name="Vcs.Log.Tabs.Properties">
|
||||
|
|
@ -465,7 +463,6 @@
|
|||
</option>
|
||||
</component>
|
||||
<component name="VcsManagerConfiguration">
|
||||
<MESSAGE value="fix some bugs" />
|
||||
<MESSAGE value="add view document" />
|
||||
<MESSAGE value="add keywords of view" />
|
||||
<MESSAGE value="add ast class of view" />
|
||||
|
|
@ -490,7 +487,8 @@
|
|||
<MESSAGE value="add ast classes of function" />
|
||||
<MESSAGE value="add function" />
|
||||
<MESSAGE value="add trigger document" />
|
||||
<option name="LAST_COMMIT_MESSAGE" value="add trigger document" />
|
||||
<MESSAGE value="add trigger ast classes" />
|
||||
<option name="LAST_COMMIT_MESSAGE" value="add trigger ast classes" />
|
||||
</component>
|
||||
<component name="XDebuggerManager">
|
||||
<watches-manager>
|
||||
|
|
|
|||
|
|
@ -39,6 +39,8 @@ public class OracleLexer {
|
|||
, "PROCEDURE", "IS", "IN", "OUT", "$$", "COMMIT", "ROLLBACK", "EXEC", "EXECUTE"
|
||||
// function
|
||||
, "FUNCTION", "RETURN"
|
||||
// trigger
|
||||
, "TRIGGER", "BEFORE", "AFTER", "INSTEAD OF", "REFERENCING", "NEW", "OLD", "EACH", "ROW"
|
||||
};
|
||||
private static final Pattern TOKEN_PATTERN = Pattern.compile(
|
||||
"(NUMBER\\(.*?\\))|" + // NUMBER() function
|
||||
|
|
@ -79,6 +81,7 @@ public class OracleLexer {
|
|||
"(FULL JOIN)|" +
|
||||
"(FULL OUTER JOIN)|" +
|
||||
"(CROSS JOIN)|" +
|
||||
"(INSTEAD OF)|" +
|
||||
"(\\|\\|)|" +
|
||||
"(:=)|" +
|
||||
"(\\.\\.)|" +
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ import Parser.AST.Join.*;
|
|||
import Parser.AST.Loop.*;
|
||||
import Parser.AST.Procedure.*;
|
||||
import Parser.AST.Select.*;
|
||||
import Parser.AST.Trigger.*;
|
||||
import Parser.AST.Update.*;
|
||||
import Parser.AST.View.ViewCreateNode;
|
||||
import Parser.AST.View.ViewEndNode;
|
||||
|
|
@ -87,6 +88,12 @@ public class OracleParser {
|
|||
)
|
||||
{
|
||||
return parseFunction(lexer.getTokens());
|
||||
} else if (
|
||||
(lexer.getTokens().get(0).getValue().equalsIgnoreCase("CREATE") && lexer.getTokens().get(1).getValue().equalsIgnoreCase("TRIGGER"))
|
||||
|| (lexer.getTokens().get(0).getValue().equalsIgnoreCase("CREATE") && lexer.getTokens().get(1).getValue().equalsIgnoreCase("OR") && lexer.getTokens().get(2).getValue().equalsIgnoreCase("REPLACE") && lexer.getTokens().get(3).getValue().equalsIgnoreCase("TRIGGER"))
|
||||
)
|
||||
{
|
||||
return parseTrigger(lexer.getTokens());
|
||||
}
|
||||
else {
|
||||
try {
|
||||
|
|
@ -2141,5 +2148,157 @@ public class OracleParser {
|
|||
return root;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create TRIGGER
|
||||
* Grammar: CREATE OR REPLACE TRIGGER trigger_name
|
||||
* BEFORE | AFTER | INSTEAD OF -- OpenGauss does not support INSTEAD OF
|
||||
* { INSERT | UPDATE | DELETE }
|
||||
* ON table_name
|
||||
* [REFERENCING NEW AS new OLD AS old] -- OpenGauss does not support this
|
||||
* FOR EACH ROW
|
||||
* [WHEN (condition)]
|
||||
* BEGIN
|
||||
* -- trigger body
|
||||
* END;
|
||||
* Example: CREATE OR REPLACE TRIGGER log_insert
|
||||
* BEFORE INSERT ON employees
|
||||
* FOR EACH ROW
|
||||
* BEGIN
|
||||
* INSERT INTO audit_log (action, employee_id) VALUES ('INSERT', :NEW.id);
|
||||
* END;
|
||||
*/
|
||||
private ASTNode parseTrigger(List<Token> parseTokens) {
|
||||
ASTNode root = new TriggerNode();
|
||||
ASTNode currentNode = root;
|
||||
for (int i = 0; i < parseTokens.size(); i++) {
|
||||
// match create trigger
|
||||
if (root.getTokens().isEmpty()) {
|
||||
for (int j = i; j < parseTokens.size(); j++) {
|
||||
root.addToken(parseTokens.get(j));
|
||||
if (parseTokens.get(j).hasType(Token.TokenType.KEYWORD) && parseTokens.get(j).getValue().equalsIgnoreCase("TRIGGER")) {
|
||||
i = j;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
// match trigger name
|
||||
else if (currentNode == root && parseTokens.get(i).hasType(Token.TokenType.IDENTIFIER)) {
|
||||
ASTNode childNode = new TriggerNameNode();
|
||||
childNode.addToken(parseTokens.get(i));
|
||||
currentNode.addChild(childNode);
|
||||
currentNode = childNode;
|
||||
}
|
||||
// match trigger condition
|
||||
else if (currentNode instanceof TriggerNameNode && (
|
||||
parseTokens.get(i).hasType(Token.TokenType.KEYWORD) && parseTokens.get(i).getValue().equalsIgnoreCase("BEFORE") ||
|
||||
parseTokens.get(i).hasType(Token.TokenType.KEYWORD) && parseTokens.get(i).getValue().equalsIgnoreCase("AFTER") ||
|
||||
parseTokens.get(i).hasType(Token.TokenType.KEYWORD) && parseTokens.get(i).getValue().equalsIgnoreCase("INSTEAD OF")
|
||||
)) {
|
||||
if (i + 1 < parseTokens.size() && (
|
||||
parseTokens.get(i + 1).hasType(Token.TokenType.KEYWORD) && parseTokens.get(i + 1).getValue().equalsIgnoreCase("INSERT") ||
|
||||
parseTokens.get(i + 1).hasType(Token.TokenType.KEYWORD) && parseTokens.get(i + 1).getValue().equalsIgnoreCase("UPDATE") ||
|
||||
parseTokens.get(i + 1).hasType(Token.TokenType.KEYWORD) && parseTokens.get(i + 1).getValue().equalsIgnoreCase("DELETE")
|
||||
)) {
|
||||
TriggerConditionNode childNode = new TriggerConditionNode();
|
||||
childNode.setCondition(parseTokens.get(i));
|
||||
childNode.setAction(parseTokens.get(i + 1));
|
||||
}
|
||||
else {
|
||||
try {
|
||||
throw new ParseFailedException("There exists syntax error!");
|
||||
} catch (ParseFailedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
// match trigger on table
|
||||
else if (currentNode instanceof TriggerConditionNode && parseTokens.get(i).hasType(Token.TokenType.KEYWORD) && parseTokens.get(i).getValue().equalsIgnoreCase("ON")) {
|
||||
if (i + 1 < parseTokens.size() && parseTokens.get(i + 1).hasType(Token.TokenType.IDENTIFIER)) {
|
||||
ASTNode childNode = new TriggerObjNode();
|
||||
childNode.addToken(parseTokens.get(i));
|
||||
childNode.addToken(parseTokens.get(i + 1));
|
||||
currentNode.addChild(childNode);
|
||||
currentNode = childNode;
|
||||
i++;
|
||||
}
|
||||
else {
|
||||
try {
|
||||
throw new ParseFailedException("There exists syntax error!");
|
||||
} catch (ParseFailedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
// match [REFERENCING NEW AS new OLD AS old]
|
||||
else if (currentNode instanceof TriggerObjNode && parseTokens.get(i).hasType(Token.TokenType.KEYWORD) && parseTokens.get(i).getValue().equalsIgnoreCase("REFERENCING")) {
|
||||
ASTNode childNode = new TriggerOptionNode();
|
||||
for (int j = i; j < parseTokens.size(); j++) {
|
||||
if (parseTokens.get(j).hasType(Token.TokenType.KEYWORD) && parseTokens.get(j).getValue().equalsIgnoreCase("FOR")) {
|
||||
i = j - 1;
|
||||
break;
|
||||
}
|
||||
childNode.addToken(parseTokens.get(j));
|
||||
}
|
||||
currentNode.addChild(childNode);
|
||||
currentNode = childNode;
|
||||
}
|
||||
// match FOR EACH ROW
|
||||
else if (parseTokens.get(i).hasType(Token.TokenType.KEYWORD) && parseTokens.get(i).getValue().equalsIgnoreCase("FOR")) {
|
||||
if ((i + 1 < parseTokens.size() && parseTokens.get(i + 1).hasType(Token.TokenType.KEYWORD) && parseTokens.get(i + 1).getValue().equalsIgnoreCase("EACH"))
|
||||
&& (i + 2 < parseTokens.size() && parseTokens.get(i + 2).hasType(Token.TokenType.KEYWORD) && parseTokens.get(i + 2).getValue().equalsIgnoreCase("ROW"))) {
|
||||
ASTNode childNode = new TriggerForEachRowNode();
|
||||
childNode.addToken(parseTokens.get(i));
|
||||
childNode.addToken(parseTokens.get(i + 1));
|
||||
childNode.addToken(parseTokens.get(i + 2));
|
||||
currentNode.addChild(childNode);
|
||||
currentNode = childNode;
|
||||
}
|
||||
else {
|
||||
try {
|
||||
throw new ParseFailedException("There exists syntax error!");
|
||||
} catch (ParseFailedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
// match when
|
||||
else if (currentNode instanceof TriggerForEachRowNode && parseTokens.get(i).hasType(Token.TokenType.KEYWORD) && parseTokens.get(i).getValue().equalsIgnoreCase("WHEN")) {
|
||||
ASTNode childNode = new TriggerWhenNode();
|
||||
for(int j = i; j < parseTokens.size(); j++) {
|
||||
if (parseTokens.get(j).hasType(Token.TokenType.KEYWORD) && parseTokens.get(j).getValue().equalsIgnoreCase("BEGIN")) {
|
||||
i = j - 1;
|
||||
break;
|
||||
}
|
||||
childNode.addToken(parseTokens.get(j));
|
||||
}
|
||||
currentNode.addChild(childNode);
|
||||
currentNode = childNode;
|
||||
}
|
||||
// match begin
|
||||
else if (parseTokens.get(i).hasType(Token.TokenType.KEYWORD) && parseTokens.get(i).getValue().equalsIgnoreCase("BEGIN")) {
|
||||
ASTNode childNode = new TriggerBeginNode();
|
||||
childNode.addToken(parseTokens.get(i));
|
||||
currentNode.addChild(childNode);
|
||||
currentNode = childNode;
|
||||
}
|
||||
// match trigger body
|
||||
else if (currentNode instanceof TriggerBeginNode) {
|
||||
//TODO: parse trigger body
|
||||
}
|
||||
else if (parseTokens.get(i).hasType(Token.TokenType.EOF)) {
|
||||
break;
|
||||
}
|
||||
else {
|
||||
try {
|
||||
throw new ParseFailedException("Failed to parse:" + parseTokens.get(i));
|
||||
}
|
||||
catch (ParseFailedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return root;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue