diff --git a/sqlTranslate/.idea/workspace.xml b/sqlTranslate/.idea/workspace.xml
index 84610ff85..d0c566e2a 100644
--- a/sqlTranslate/.idea/workspace.xml
+++ b/sqlTranslate/.idea/workspace.xml
@@ -4,9 +4,12 @@
-
+
-
+
+
+
+
@@ -104,13 +107,6 @@
1723106789329
-
- 1725958136981
-
-
-
- 1725958136981
-
1725978582486
@@ -447,7 +443,14 @@
1726471382852
-
+
+ 1726472321577
+
+
+
+ 1726472321577
+
+
@@ -485,9 +488,9 @@
-
-
+
+
diff --git a/sqlTranslate/src/main/java/Generator/OpenGaussGenerator.java b/sqlTranslate/src/main/java/Generator/OpenGaussGenerator.java
index 548bcba6f..1014f31f1 100644
--- a/sqlTranslate/src/main/java/Generator/OpenGaussGenerator.java
+++ b/sqlTranslate/src/main/java/Generator/OpenGaussGenerator.java
@@ -13,6 +13,8 @@ import Exception.GenerateFailedException;
import Parser.AST.Delete.DeleteNode;
import Parser.AST.Drop.DropNode;
import Parser.AST.Drop.DropOptionNode;
+import Parser.AST.Exception.ExceptionActionNode;
+import Parser.AST.Exception.ExceptionNode;
import Parser.AST.Insert.InsertNode;
import Parser.AST.Join.JoinConditionNode;
import Parser.AST.Join.JoinSourceTabNode;
@@ -70,6 +72,9 @@ public class OpenGaussGenerator {
else if (node instanceof LoopNode || node instanceof WhileNode || node instanceof ForNode) {
return GenLoopSQL(node);
}
+ else if (node instanceof ExceptionNode) {
+ return GenExceptionSQL(node);
+ }
else {
try {
throw new GenerateFailedException("Root node:" + node.getClass() + "(Unsupported node type!)");
@@ -135,6 +140,11 @@ public class OpenGaussGenerator {
return node.toQueryString();
}
+ private String GenExceptionSQL(ASTNode node) {
+ visitException(node);
+ return node.toQueryString();
+ }
+
private void visitCrt(ASTNode node) {
if (node instanceof ColumnNode) {
ColumnTypeConvert((ColumnNode) node);
@@ -183,6 +193,15 @@ public class OpenGaussGenerator {
}
}
+ private void visitException(ASTNode node) {
+ if (node instanceof ExceptionActionNode) {
+ PLConvert(node);
+ }
+ for (ASTNode child : node.getChildren()) {
+ visitException(child);
+ }
+ }
+
private void visitSelect(ASTNode node) {
if (node instanceof JoinSourceTabNode) {
visitJoin(node);
@@ -252,7 +271,7 @@ public class OpenGaussGenerator {
if (token.hasType(Token.TokenType.STRING)) {
output += token.getValue().replace("'", "");
}
- else if (token.hasType(Token.TokenType.IDENTIFIER)) {
+ else if (token.hasType(Token.TokenType.IDENTIFIER) || token.hasType(Token.TokenType.KEYWORD)) {
output += "%";
outputObj.add(token);
}
@@ -260,16 +279,29 @@ public class OpenGaussGenerator {
continue;
}
}
- List tokens = new ArrayList<>();
- tokens.add(new Token(Token.TokenType.KEYWORD, "RAISE"));
- tokens.add(new Token(Token.TokenType.KEYWORD, "NOTICE"));
- tokens.add(new Token(Token.TokenType.STRING, "'" + output + "'"));
- for (Token token: outputObj) {
- tokens.add(new Token(Token.TokenType.SYMBOL, ","));
- tokens.add(token);
+ if (!outputObj.isEmpty()) {
+ List tokens = new ArrayList<>();
+ tokens.add(new Token(Token.TokenType.KEYWORD, "RAISE"));
+ tokens.add(new Token(Token.TokenType.KEYWORD, "NOTICE"));
+ tokens.add(new Token(Token.TokenType.STRING, "'" + output + "'"));
+ for (Token token: outputObj) {
+ tokens.add(new Token(Token.TokenType.SYMBOL, ","));
+ tokens.add(token);
+ }
+ tokens.add(new Token(Token.TokenType.SYMBOL, ";"));
+ node.setTokens(tokens);
}
- tokens.add(new Token(Token.TokenType.SYMBOL, ";"));
- node.setTokens(tokens);
+ else {
+ List tokens = new ArrayList<>();
+ tokens.add(new Token(Token.TokenType.KEYWORD, "RAISE"));
+ tokens.add(new Token(Token.TokenType.KEYWORD, "NOTICE"));
+ tokens.add(new Token(Token.TokenType.STRING, "'%'"));
+ tokens.add(new Token(Token.TokenType.SYMBOL, ","));
+ tokens.add(new Token(Token.TokenType.STRING, "'" + output + "'"));
+ tokens.add(new Token(Token.TokenType.SYMBOL, ";"));
+ node.setTokens(tokens);
+ }
+
}
}
}
diff --git a/sqlTranslate/src/main/java/Lexer/OracleLexer.java b/sqlTranslate/src/main/java/Lexer/OracleLexer.java
index 9fb4e8489..ac4d1a0bb 100644
--- a/sqlTranslate/src/main/java/Lexer/OracleLexer.java
+++ b/sqlTranslate/src/main/java/Lexer/OracleLexer.java
@@ -34,7 +34,7 @@ public class OracleLexer {
// Loop
, "LOOP", "EXIT", "WHILE", "FOR", "IN", "CONTINUE"
// Exception
- , "EXCEPTION", "SQLERRM", "ZERO_DIVIDE", "INVALID_NUMBER"
+ , "EXCEPTION", "SQLERRM", "ZERO_DIVIDE", "INVALID_NUMBER", "OTHERS"
};
private static final Pattern TOKEN_PATTERN = Pattern.compile(
"(NUMBER\\(.*?\\))|" + // NUMBER() function
diff --git a/sqlTranslate/src/main/java/Main.java b/sqlTranslate/src/main/java/Main.java
index 7fc0ed165..3d7016c09 100644
--- a/sqlTranslate/src/main/java/Main.java
+++ b/sqlTranslate/src/main/java/Main.java
@@ -45,17 +45,27 @@ public class Main {
// " ELSE\n" +
// " v_bonus := v_salary * 0.03;\n" +
// " END IF;";
- String sql = "LOOP\n" +
- " DBMS_OUTPUT.PUT_LINE(v_counter);\n" +
- " Continue;\n" +
- " v_counter := v_counter + 1;\n" +
- " EXIT WHEN v_counter > 10;\n" +
- " END LOOP;";
+// String sql = "LOOP\n" +
+// " DBMS_OUTPUT.PUT_LINE(v_counter);\n" +
+// " Continue;\n" +
+// " v_counter := v_counter + 1;\n" +
+// " EXIT WHEN v_counter > 10;\n" +
+// " END LOOP;";
+ String sql = "EXCEPTION\n" +
+ " WHEN e_custom_exception THEN\n" +
+ " DBMS_OUTPUT.PUT_LINE('Caught an exception: Custom exception raised');\n" +
+ " WHEN ZERO_DIVIDE THEN\n" +
+ " DBMS_OUTPUT.PUT_LINE('Caught an exception: Division by zero');\n" +
+ " WHEN INVALID_NUMBER THEN\n" +
+ " DBMS_OUTPUT.PUT_LINE('Caught an exception: Invalid number');\n" +
+ " WHEN OTHERS THEN\n" +
+ " DBMS_OUTPUT.PUT_LINE('Caught an exception: ' || SQLERRM);";
OracleLexer lexer = new OracleLexer(sql);
lexer.printTokens();
// OracleParser parser = new OracleParser(lexer);
// ASTNode root = parser.parse();
- ASTNode root = OracleParser.parseLoop(lexer.getTokens());
+ ASTNode root = OracleParser.parseException(lexer.getTokens());
+// ASTNode root = OracleParser.parseLoop(lexer.getTokens());
// ASTNode root = OracleParser.parseIFELSE(lexer.getTokens());
// ASTNode root = OracleParser.parseCaseWhen(lexer.getTokens());
// ASTNode root = OracleParser.parseJoin(lexer.getTokens());
diff --git a/sqlTranslate/src/main/java/Parser/OracleParser.java b/sqlTranslate/src/main/java/Parser/OracleParser.java
index 7844d9208..f3a310f5b 100644
--- a/sqlTranslate/src/main/java/Parser/OracleParser.java
+++ b/sqlTranslate/src/main/java/Parser/OracleParser.java
@@ -18,6 +18,7 @@ import Parser.AST.Drop.DropEndNode;
import Parser.AST.Drop.DropObjNameNode;
import Parser.AST.Drop.DropNode;
import Parser.AST.Drop.DropOptionNode;
+import Parser.AST.Exception.*;
import Parser.AST.IFELSIF.*;
import Parser.AST.Insert.InsertDataNode;
import Parser.AST.Insert.InsertEndNode;
@@ -849,6 +850,122 @@ public class OracleParser {
return root;
}
+ /**
+ * Exception
+ * For example: EXCEPTION
+ * -- custom exception
+ * WHEN e_custom_exception THEN
+ * DBMS_OUTPUT.PUT_LINE('Caught an exception: Custom exception raised');
+ * -- divide by zero
+ * WHEN ZERO_DIVIDE THEN
+ * DBMS_OUTPUT.PUT_LINE('Caught an exception: Division by zero');
+ * -- invalid number
+ * WHEN INVALID_NUMBER THEN
+ * DBMS_OUTPUT.PUT_LINE('Caught an exception: Invalid number');
+ * -- other exceptions
+ * WHEN OTHERS THEN
+ * DBMS_OUTPUT.PUT_LINE('Caught an exception: ' || SQLERRM);
+ * @param parseTokens should start with Exception keyword
+ * @return ASTNode will not contain 'END'
+ */
+ public static ASTNode parseException(List parseTokens) {
+ ASTNode root = new ExceptionNode();
+ root.addToken(parseTokens.get(0));
+ ASTNode currentNode = root;
+ for (int i = 1; i < parseTokens.size(); i++) {
+ // match exception type
+ if (parseTokens.get(i).hasType(Token.TokenType.KEYWORD) && parseTokens.get(i).getValue().equalsIgnoreCase("WHEN")) {
+ if (i + 1 < parseTokens.size() && parseTokens.get(i + 1).hasType(Token.TokenType.IDENTIFIER)) {
+ ASTNode childNode = new CustomExceptionNode();
+ for (int j = i; j < parseTokens.size(); j++) {
+ childNode.addToken(parseTokens.get(j));
+ if (parseTokens.get(j).hasType(Token.TokenType.KEYWORD) && parseTokens.get(j).getValue().equalsIgnoreCase("THEN")) {
+ i = j;
+ break;
+ }
+ }
+ currentNode.addChild(childNode);
+ currentNode = childNode;
+ }
+ else if (i + 1 < parseTokens.size() && parseTokens.get(i + 1).hasType(Token.TokenType.KEYWORD) && parseTokens.get(i + 1).getValue().equalsIgnoreCase("ZERO_DIVIDE")) {
+ ASTNode childNode = new Zero_divideNode();
+ for (int j = i; j < parseTokens.size(); j++) {
+ childNode.addToken(parseTokens.get(j));
+ if (parseTokens.get(j).hasType(Token.TokenType.KEYWORD) && parseTokens.get(j).getValue().equalsIgnoreCase("THEN")) {
+ i = j;
+ break;
+ }
+ }
+ currentNode.addChild(childNode);
+ currentNode = childNode;
+ }
+ else if (i + 1 < parseTokens.size() && parseTokens.get(i + 1).hasType(Token.TokenType.KEYWORD) && parseTokens.get(i + 1).getValue().equalsIgnoreCase("INVALID_NUMBER")) {
+ ASTNode childNode = new Invalid_numberNode();
+ for (int j = i; j < parseTokens.size(); j++) {
+ childNode.addToken(parseTokens.get(j));
+ if (parseTokens.get(j).hasType(Token.TokenType.KEYWORD) && parseTokens.get(j).getValue().equalsIgnoreCase("THEN")) {
+ i = j;
+ break;
+ }
+ }
+ currentNode.addChild(childNode);
+ currentNode = childNode;
+ }
+ else if (i + 1 < parseTokens.size() && parseTokens.get(i + 1).hasType(Token.TokenType.KEYWORD) && parseTokens.get(i + 1).getValue().equalsIgnoreCase("OTHERS")) {
+ ASTNode childNode = new OtherExceptionNode();
+ for (int j = i; j < parseTokens.size(); j++) {
+ childNode.addToken(parseTokens.get(j));
+ if (parseTokens.get(j).hasType(Token.TokenType.KEYWORD) && parseTokens.get(j).getValue().equalsIgnoreCase("THEN")) {
+ i = j;
+ break;
+ }
+ }
+ currentNode.addChild(childNode);
+ currentNode = childNode;
+ }
+ else {
+ try {
+ throw new ParseFailedException("Parse failed:There exists syntex error in the input sql!");
+ }
+ catch (ParseFailedException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ else if (parseTokens.get(i).hasType(Token.TokenType.KEYWORD) && parseTokens.get(i).getValue().equalsIgnoreCase("END")) {
+ ASTNode childNode = new ExceptionEndNode();
+ currentNode.addChild(childNode);
+ currentNode = childNode;
+ break;
+ }
+ else if (parseTokens.get(i).hasType(Token.TokenType.EOF)) {
+ if (!(currentNode instanceof ExceptionEndNode)) {
+ ASTNode childNode = new ExceptionEndNode();
+ currentNode.addChild(childNode);
+ currentNode = childNode;
+ }
+ else {
+ break;
+ }
+ }
+ // match exception action
+ else {
+ ASTNode childNode = new ExceptionActionNode();
+ for (int j = i; j < parseTokens.size(); j++) {
+ childNode.addToken(parseTokens.get(j));
+ if (parseTokens.get(j).hasType(Token.TokenType.SYMBOL) && parseTokens.get(j).getValue().equals(";")) {
+ i = j;
+ break;
+ }
+ }
+ currentNode.addChild(childNode);
+ currentNode = childNode;
+ }
+ }
+
+ return root;
+ }
+
/**
* JOIN clause
* For example: table1 t1 JOIN table2 t2 ON|USING t1.id = t2.id