Add recursive parsing function

This commit is contained in:
XudongXie 2024-09-26 22:30:07 +08:00
parent 98a3b240a1
commit 54bef7c864
4 changed files with 189 additions and 95 deletions

View File

@ -8,32 +8,7 @@
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/main/java/generator/OpenGaussGenerator.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/java/generator/OpenGaussGenerator.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" />
<change beforePath="$PROJECT_DIR$/src/main/java/parser/ast/alterTable/AlterAddColumnNode.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/java/parser/ast/altertable/AlterAddColumnNode.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/main/java/parser/ast/alterTable/AlterAddConstraintNode.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/java/parser/ast/altertable/AlterAddConstraintNode.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/main/java/parser/ast/alterTable/AlterDropColumnNode.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/java/parser/ast/altertable/AlterDropColumnNode.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/main/java/parser/ast/alterTable/AlterDropConstraintNode.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/java/parser/ast/altertable/AlterDropConstraintNode.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/main/java/parser/ast/alterTable/AlterEndNode.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/java/parser/ast/altertable/AlterEndNode.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/main/java/parser/ast/alterTable/AlterModifyColumnNode.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/java/parser/ast/altertable/AlterModifyColumnNode.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/main/java/parser/ast/alterTable/AlterNode.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/java/parser/ast/altertable/AlterNode.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/main/java/parser/ast/alterTable/AlterObjNode.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/java/parser/ast/altertable/AlterObjNode.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/main/java/parser/ast/alterTable/AlterRenameColumnNode.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/java/parser/ast/altertable/AlterRenameColumnNode.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/main/java/parser/ast/alterTable/AlterRenameTableNode.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/java/parser/ast/altertable/AlterRenameTableNode.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/main/java/parser/ast/caseWhen/CaseConditionNode.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/java/parser/ast/casewhen/CaseConditionNode.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/main/java/parser/ast/caseWhen/CaseElseNode.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/java/parser/ast/casewhen/CaseElseNode.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/main/java/parser/ast/caseWhen/CaseEndNode.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/java/parser/ast/casewhen/CaseEndNode.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/main/java/parser/ast/caseWhen/CaseThenNode.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/java/parser/ast/casewhen/CaseThenNode.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/main/java/parser/ast/createTable/CRTEndNode.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/java/parser/ast/createtable/CRTEndNode.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/main/java/parser/ast/createTable/ColumnNode.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/java/parser/ast/createtable/ColumnNode.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/main/java/parser/ast/createTable/CreateTabNode.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/java/parser/ast/createtable/CreateTabNode.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/main/java/parser/ast/createTable/TableConstraintNode.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/java/parser/ast/createtable/TableConstraintNode.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/main/java/parser/ast/createTable/TableNode.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/java/parser/ast/createtable/TableNode.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/main/java/parser/ast/createTable/TableTypeNode.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/java/parser/ast/createtable/TableTypeNode.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/main/java/parser/ast/iFELSIF/ELSENode.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/java/parser/ast/ifelsif/ELSENode.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/main/java/parser/ast/iFELSIF/ELSIFActionNode.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/java/parser/ast/ifelsif/ELSIFActionNode.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/main/java/parser/ast/iFELSIF/ELSIFConditionNode.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/java/parser/ast/ifelsif/ELSIFConditionNode.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/main/java/parser/ast/iFELSIF/EndIFNode.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/java/parser/ast/ifelsif/EndIFNode.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/main/java/parser/ast/iFELSIF/IFActionNode.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/java/parser/ast/ifelsif/IFActionNode.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/main/java/parser/ast/iFELSIF/IFConditionNode.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/java/parser/ast/ifelsif/IFConditionNode.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/test/java/TestFunction.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/test/java/TestFunction.java" afterDir="false" />
</list>
<option name="SHOW_DIALOG" value="false" />
<option name="HIGHLIGHT_CONFLICTS" value="true" />
@ -66,58 +41,55 @@
<option name="hideEmptyMiddlePackages" value="true" />
<option name="showLibraryContents" value="true" />
</component>
<component name="PropertiesComponent">{
&quot;keyToString&quot;: {
&quot;Application.Main.executor&quot;: &quot;Run&quot;,
&quot;JUnit.testAlterTable.executor&quot;: &quot;Run&quot;,
&quot;JUnit.testAlterTable.testAlterTable.executor&quot;: &quot;Run&quot;,
&quot;JUnit.testCaseWhen.test.executor&quot;: &quot;Run&quot;,
&quot;JUnit.testCommitRollbackExec.test.executor&quot;: &quot;Run&quot;,
&quot;JUnit.testCreateTable.executor&quot;: &quot;Run&quot;,
&quot;JUnit.testCreateTable.test.executor&quot;: &quot;Run&quot;,
&quot;JUnit.testDelete.test.executor&quot;: &quot;Run&quot;,
&quot;JUnit.testDropTable.test.executor&quot;: &quot;Run&quot;,
&quot;JUnit.testException.executor&quot;: &quot;Run&quot;,
&quot;JUnit.testException.test.executor&quot;: &quot;Run&quot;,
&quot;JUnit.testFunction.test.executor&quot;: &quot;Run&quot;,
&quot;JUnit.testIfElse.test.executor&quot;: &quot;Run&quot;,
&quot;JUnit.testInsert.test.executor&quot;: &quot;Run&quot;,
&quot;JUnit.testJoin.executor&quot;: &quot;Run&quot;,
&quot;JUnit.testJoin.test.executor&quot;: &quot;Run&quot;,
&quot;JUnit.testLoop.test.executor&quot;: &quot;Run&quot;,
&quot;JUnit.testPL.executor&quot;: &quot;Run&quot;,
&quot;JUnit.testProcedure.test.executor&quot;: &quot;Run&quot;,
&quot;JUnit.testSelect.executor&quot;: &quot;Run&quot;,
&quot;JUnit.testSelect.test.executor&quot;: &quot;Run&quot;,
&quot;JUnit.testTrigger.executor&quot;: &quot;Run&quot;,
&quot;JUnit.testTrigger.test.executor&quot;: &quot;Run&quot;,
&quot;JUnit.testUpdate.executor&quot;: &quot;Run&quot;,
&quot;JUnit.testView.executor&quot;: &quot;Run&quot;,
&quot;RunOnceActivity.OpenProjectViewOnStart&quot;: &quot;true&quot;,
&quot;RunOnceActivity.ShowReadmeOnStart&quot;: &quot;true&quot;,
&quot;git-widget-placeholder&quot;: &quot;master&quot;,
&quot;kotlin-language-version-configured&quot;: &quot;true&quot;,
&quot;last_opened_file_path&quot;: &quot;F:/oracle2opengauss/examples/sqlTranslate&quot;,
&quot;project.structure.last.edited&quot;: &quot;Project&quot;,
&quot;project.structure.proportion&quot;: &quot;0.0&quot;,
&quot;project.structure.side.proportion&quot;: &quot;0.0&quot;,
&quot;settings.editor.selected.configurable&quot;: &quot;preferences.pluginManager&quot;
<component name="PropertiesComponent"><![CDATA[{
"keyToString": {
"Application.Main.executor": "Run",
"JUnit.TestFunction.executor": "Run",
"JUnit.TestFunction.test.executor": "Run",
"JUnit.TestPL.test.executor": "Run",
"JUnit.TestProcedure.test.executor": "Run",
"JUnit.TestTrigger.test.executor": "Run",
"JUnit.testAlterTable.executor": "Run",
"JUnit.testAlterTable.testAlterTable.executor": "Run",
"JUnit.testCaseWhen.test.executor": "Run",
"JUnit.testCommitRollbackExec.test.executor": "Run",
"JUnit.testCreateTable.executor": "Run",
"JUnit.testCreateTable.test.executor": "Run",
"JUnit.testDelete.test.executor": "Run",
"JUnit.testDropTable.test.executor": "Run",
"JUnit.testException.executor": "Run",
"JUnit.testException.test.executor": "Run",
"JUnit.testFunction.test.executor": "Run",
"JUnit.testIfElse.test.executor": "Run",
"JUnit.testInsert.test.executor": "Run",
"JUnit.testJoin.executor": "Run",
"JUnit.testJoin.test.executor": "Run",
"JUnit.testLoop.test.executor": "Run",
"JUnit.testPL.executor": "Run",
"JUnit.testProcedure.test.executor": "Run",
"JUnit.testSelect.executor": "Run",
"JUnit.testSelect.test.executor": "Run",
"JUnit.testTrigger.executor": "Run",
"JUnit.testTrigger.test.executor": "Run",
"JUnit.testUpdate.executor": "Run",
"JUnit.testView.executor": "Run",
"RunOnceActivity.OpenProjectViewOnStart": "true",
"RunOnceActivity.ShowReadmeOnStart": "true",
"git-widget-placeholder": "master",
"kotlin-language-version-configured": "true",
"last_opened_file_path": "F:/oracle2opengauss/examples/sqlTranslate",
"project.structure.last.edited": "Project",
"project.structure.proportion": "0.0",
"project.structure.side.proportion": "0.0",
"settings.editor.selected.configurable": "preferences.pluginManager"
}
}</component>
<component name="RunManager" selected="Application.Main">
<configuration name="Main" type="Application" factoryName="Application" temporary="true" nameIsGenerated="true">
<option name="MAIN_CLASS_NAME" value="Main" />
<module name="sqlTranslate" />
<method v="2">
<option name="Make" enabled="true" />
</method>
</configuration>
<configuration name="TestCaseWhen.test" type="JUnit" factoryName="JUnit" temporary="true" nameIsGenerated="true">
}]]></component>
<component name="RunManager" selected="JUnit.TestProcedure.test">
<configuration name="TestFunction" type="JUnit" factoryName="JUnit" temporary="true" nameIsGenerated="true">
<module name="sqlTranslate" />
<option name="PACKAGE_NAME" value="" />
<option name="MAIN_CLASS_NAME" value="TestCaseWhen" />
<option name="METHOD_NAME" value="test" />
<option name="TEST_OBJECT" value="method" />
<option name="MAIN_CLASS_NAME" value="TestFunction" />
<option name="TEST_OBJECT" value="class" />
<method v="2">
<option name="Make" enabled="true" />
</method>
@ -132,11 +104,22 @@
<option name="Make" enabled="true" />
</method>
</configuration>
<configuration name="TestTrigger" type="JUnit" factoryName="JUnit" temporary="true" nameIsGenerated="true">
<configuration name="TestPL.test" type="JUnit" factoryName="JUnit" temporary="true" nameIsGenerated="true">
<module name="sqlTranslate" />
<option name="PACKAGE_NAME" value="" />
<option name="MAIN_CLASS_NAME" value="TestTrigger" />
<option name="TEST_OBJECT" value="class" />
<option name="MAIN_CLASS_NAME" value="TestPL" />
<option name="METHOD_NAME" value="test" />
<option name="TEST_OBJECT" value="method" />
<method v="2">
<option name="Make" enabled="true" />
</method>
</configuration>
<configuration name="TestProcedure.test" type="JUnit" factoryName="JUnit" temporary="true" nameIsGenerated="true">
<module name="sqlTranslate" />
<option name="PACKAGE_NAME" value="" />
<option name="MAIN_CLASS_NAME" value="TestProcedure" />
<option name="METHOD_NAME" value="test" />
<option name="TEST_OBJECT" value="method" />
<method v="2">
<option name="Make" enabled="true" />
</method>
@ -152,19 +135,19 @@
</method>
</configuration>
<list>
<item itemvalue="Application.Main" />
<item itemvalue="JUnit.TestCaseWhen.test" />
<item itemvalue="JUnit.TestFunction" />
<item itemvalue="JUnit.TestPL.test" />
<item itemvalue="JUnit.TestProcedure.test" />
<item itemvalue="JUnit.TestFunction.test" />
<item itemvalue="JUnit.TestTrigger" />
<item itemvalue="JUnit.TestTrigger.test" />
</list>
<recent_temporary>
<list>
<item itemvalue="Application.Main" />
<item itemvalue="JUnit.TestTrigger.test" />
<item itemvalue="JUnit.TestProcedure.test" />
<item itemvalue="JUnit.TestFunction.test" />
<item itemvalue="JUnit.TestTrigger" />
<item itemvalue="JUnit.TestCaseWhen.test" />
<item itemvalue="JUnit.TestFunction" />
<item itemvalue="JUnit.TestTrigger.test" />
<item itemvalue="JUnit.TestPL.test" />
</list>
</recent_temporary>
</component>
@ -520,7 +503,7 @@
<option name="project" value="LOCAL" />
<updated>1726633703475</updated>
</task>
<option name="localTasksCounter" value="109" />
<option name="localTasksCounter" value="110" />
<servers />
</component>
<component name="Vcs.Log.Tabs.Properties">

View File

@ -463,7 +463,7 @@ public class OpenGaussGenerator {
String output = "";
List<Token> outputObj = new ArrayList<>();
for (Token token: lexer.getTokens()) {
if (token.hasType(Token.TokenType.STRING)) {
if (token.hasType(Token.TokenType.STRING) || token.hasType(Token.TokenType.NUMBER)) {
output += token.getValue().replace("'", "");
}
else if (token.hasType(Token.TokenType.IDENTIFIER) || token.hasType(Token.TokenType.KEYWORD)) {
@ -657,6 +657,9 @@ public class OpenGaussGenerator {
CommonConvert(currentNode);
break;
}
else {
CommonConvert(currentNode);
}
currentNode = currentNode.getFirstChild();
}
}

View File

@ -44,9 +44,13 @@ import java.util.List;
public class OracleParser {
private OracleLexer lexer;
public OracleParser() {}
public OracleParser(OracleLexer lexer) {
this.lexer = lexer;
}
public void setLexer(OracleLexer lexer) {
this.lexer = lexer;
}
public ASTNode parse()
{
try {
@ -113,6 +117,35 @@ public class OracleParser {
return null;
}
public ASTNode parseTokens(List<Token> parseTokens) {
try {
if ((parseTokens.get(0).getValue().equalsIgnoreCase("CREATE") && parseTokens.get(1).getValue().equalsIgnoreCase("TABLE")) ||
(parseTokens.get(0).getValue().equalsIgnoreCase("CREATE") && parseTokens.get(2).getValue().equalsIgnoreCase("TEMPORARY") && parseTokens.get(3).getValue().equalsIgnoreCase("TABLE"))) {
return parseCreateTab(parseTokens);
} else if (parseTokens.get(0).getValue().equalsIgnoreCase("INSERT")) {
return parseInsert(parseTokens);
} else if (parseTokens.get(0).getValue().equalsIgnoreCase("DROP")) {
return parseDrop(parseTokens);
} else if (parseTokens.get(0).getValue().equalsIgnoreCase("SELECT")) {
return parseSelect(parseTokens);
} else if (parseTokens.get(0).getValue().equalsIgnoreCase("UPDATE")) {
return parseUpdate(parseTokens);
} else if (parseTokens.get(0).getValue().equalsIgnoreCase("DELETE")) {
return parseDelete(parseTokens);
} else if (parseTokens.get(0).getValue().equalsIgnoreCase("ALTER")) {
return parseAlterTable(parseTokens);
} else if (
(parseTokens.get(0).getValue().equalsIgnoreCase("CREATE") && parseTokens.get(1).getValue().equalsIgnoreCase("OR") && parseTokens.get(2).getValue().equalsIgnoreCase("REPLACE") && parseTokens.get(3).getValue().equalsIgnoreCase("VIEW"))
|| (parseTokens.get(0).getValue().equalsIgnoreCase("CREATE") && parseTokens.get(1).getValue().equalsIgnoreCase("VIEW"))
) {
return parseCreateView(parseTokens);
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* CREATE TEMPORARY? TABLE _table ( (_column _type column_constraint), (_column _type column_constraint)* table_constraint?)
*/
@ -1894,8 +1927,18 @@ public class OracleParser {
break;
}
}
currentNode.addChild(childNode);
currentNode = childNode;
ASTNode bodystatementNode = parseTokens(childNode.getTokens());
if (bodystatementNode != null) {
currentNode.addChild(bodystatementNode);
currentNode = bodystatementNode.getDeepestChild();
ASTNode bodystatementEndNode = new ProcedurePLStatementNode();
currentNode.addChild(bodystatementEndNode);
currentNode = bodystatementEndNode;
}
else {
currentNode.addChild(childNode);
currentNode = childNode;
}
}
}
}
@ -2201,11 +2244,52 @@ public class OracleParser {
break;
}
}
currentNode.addChild(childNode);
currentNode = childNode;
ASTNode bodystatementNode = parseTokens(childNode.getTokens());
if (bodystatementNode != null) {
currentNode.addChild(bodystatementNode);
currentNode = bodystatementNode.getDeepestChild();
ASTNode bodystatementEndNode = new FunctionBodyNode();
currentNode.addChild(bodystatementEndNode);
currentNode = bodystatementEndNode;
}
else {
currentNode.addChild(childNode);
currentNode = childNode;
}
}
}
}
// match exception
else if (parseTokens.get(i).hasType(Token.TokenType.KEYWORD) && parseTokens.get(i).getValue().equalsIgnoreCase("EXCEPTION")) {
int index = -1;
for (int j = i; j < parseTokens.size(); j++) {
if (parseTokens.get(j).hasType(Token.TokenType.KEYWORD) && parseTokens.get(j).getValue().equalsIgnoreCase("END")) {
index = j;
break;
}
}
if (index == -1) {
try {
throw new ParseFailedException("There exists syntax error and no END block is found!");
} catch (ParseFailedException e) {
e.printStackTrace();
}
}
ASTNode childNode = parseException(parseTokens.subList(i, index + 1));
currentNode.addChild(childNode);
currentNode = childNode.getDeepestChild();
childNode = new FunctionEndNode();
for (int j = index; 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;
break;
}
// match function end
else if (parseTokens.get(i).hasType(Token.TokenType.KEYWORD) && parseTokens.get(i).getValue().equalsIgnoreCase("END")) {
ASTNode childNode = new FunctionEndNode();
@ -2427,8 +2511,18 @@ public class OracleParser {
}
childNode.addToken(parseTokens.get(j));
}
currentNode.addChild(childNode);
currentNode = childNode;
ASTNode bodystatementNode = parseTokens(childNode.getTokens());
if (bodystatementNode != null) {
currentNode.addChild(bodystatementNode);
currentNode = bodystatementNode.getDeepestChild();
ASTNode bodystatementEndNode = new TriggerBodyNode();
currentNode.addChild(bodystatementEndNode);
currentNode = bodystatementEndNode;
}
else {
currentNode.addChild(childNode);
currentNode = childNode;
}
}
else if (parseTokens.get(i).hasType(Token.TokenType.KEYWORD) && parseTokens.get(i).getValue().equalsIgnoreCase("END")) {
ASTNode childNode = new TriggerEndNode();
@ -2529,8 +2623,18 @@ public class OracleParser {
}
childNode.addToken(parseTokens.get(j));
}
currentNode.addChild(childNode);
currentNode = childNode;
ASTNode bodystatementNode = parseTokens(childNode.getTokens());
if (bodystatementNode != null) {
currentNode.addChild(bodystatementNode);
currentNode = bodystatementNode.getDeepestChild();
ASTNode bodystatementEndNode = new PLBodyNode();
currentNode.addChild(bodystatementEndNode);
currentNode = bodystatementEndNode;
}
else {
currentNode.addChild(childNode);
currentNode = childNode;
}
}
// match end
else if (parseTokens.get(i).hasType(Token.TokenType.KEYWORD) && parseTokens.get(i).getValue().equalsIgnoreCase("END")) {

View File

@ -18,7 +18,11 @@ public class TestFunction {
" input_string VARCHAR2\n" +
" ) RETURN NUMBER IS\n" +
" BEGIN\n" +
" SELECT name, salary INTO v_name, v_salary FROM employees WHERE employee_id = 100;\n" +
" RETURN LENGTH(input_string);\n" +
" EXCEPTION\n" +
" WHEN OTHERS THEN\n" +
" DBMS_OUTPUT.PUT_LINE('An error occurred: ' || SQLERRM);\n" +
" END;");
System.out.println("===== test of Function =====");
System.out.println("The source DBMS is: " + CommonConfig.getSourceDB());