From ffd026f69027ace2e3bea83b86a80d93357dac11 Mon Sep 17 00:00:00 2001 From: pynzzZ <39962741+MarkPotato777@users.noreply.github.com> Date: Tue, 5 Sep 2023 12:46:24 +0800 Subject: [PATCH 1/7] fix security (#146) --- .secignore | 16 ++++++++++++++++ ...-splitter-10-string-with-backslash-inside.yml | 1 - 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/.secignore b/.secignore index 946958eb65..0128e11c3f 100644 --- a/.secignore +++ b/.secignore @@ -84,6 +84,22 @@ http://xxx.xxx.xxx.xxx:xxxx* test@email.com https://tools.ietf.org* + https://obodc-front.oss-cn-beijing.aliyuncs.com/ODC* + https://discord.gg/drPUb2kq + https://qr.dingtalk.com/action/joingroup* + https://help.github.com* + https://npmmirror.com* + https://www.contributor-covenant.org* + https://www.conventionalcommits* + https://plugins.jetbrains.com + yizhou.xw@oceanbase.com + https://www.jetbrains.com* + https://plugins.jetbrains.com* + http://alipay-rmsdeploy-image.cn-hangzhou.alipay.aliyun-inc.com/oceanbase/odc* + http://pmd.sourceforge.net* + https://pmd.github.io* + http://ns.adobe.com* + -------------------------------------------------------- # Should use GLOB wildcard to configure and analysis the ignored folder diff --git a/server/odc-core/src/test/resources/sql/split/sql-splitter-10-string-with-backslash-inside.yml b/server/odc-core/src/test/resources/sql/split/sql-splitter-10-string-with-backslash-inside.yml index b1b7c309d7..151afa8878 100644 --- a/server/odc-core/src/test/resources/sql/split/sql-splitter-10-string-with-backslash-inside.yml +++ b/server/odc-core/src/test/resources/sql/split/sql-splitter-10-string-with-backslash-inside.yml @@ -1,4 +1,3 @@ -#scenario of https://aone.alipay.com/v2/project/874455/bug/39224304 origin: |- select 'hello \\world' as col1 from dual; insert into table_1 values ('sadasd'); From fba0c44b9871c48b4207cb8b1b26444287fbc132 Mon Sep 17 00:00:00 2001 From: zhangxiao <140503120+PeachThinking@users.noreply.github.com> Date: Tue, 5 Sep 2023 14:08:27 +0800 Subject: [PATCH 2/7] fix filter out the internal schema when synchronizing the database (#126) --- .../tools/dbbrowser/schema/oracle/OBOracleSchemaAccessor.java | 4 +++- .../tools/dbbrowser/schema/oracle/OracleSchemaAccessor.java | 3 ++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/libs/db-browser/src/main/java/com/oceanbase/tools/dbbrowser/schema/oracle/OBOracleSchemaAccessor.java b/libs/db-browser/src/main/java/com/oceanbase/tools/dbbrowser/schema/oracle/OBOracleSchemaAccessor.java index 50fbbadeb4..0380340be8 100644 --- a/libs/db-browser/src/main/java/com/oceanbase/tools/dbbrowser/schema/oracle/OBOracleSchemaAccessor.java +++ b/libs/db-browser/src/main/java/com/oceanbase/tools/dbbrowser/schema/oracle/OBOracleSchemaAccessor.java @@ -24,6 +24,7 @@ import java.util.Map; import java.util.Objects; import java.util.concurrent.atomic.AtomicReference; +import java.util.stream.Collectors; import javax.validation.constraints.NotEmpty; @@ -131,7 +132,8 @@ public List listDatabases() { item.setCharset(charset.get()); item.setCollation(collation.get()); }); - return databases; + return databases.stream().filter(database -> !ESCAPE_USER_SET.contains(database.getName())) + .collect(Collectors.toList()); } @Override diff --git a/libs/db-browser/src/main/java/com/oceanbase/tools/dbbrowser/schema/oracle/OracleSchemaAccessor.java b/libs/db-browser/src/main/java/com/oceanbase/tools/dbbrowser/schema/oracle/OracleSchemaAccessor.java index 76d742bab4..29ce81f85c 100644 --- a/libs/db-browser/src/main/java/com/oceanbase/tools/dbbrowser/schema/oracle/OracleSchemaAccessor.java +++ b/libs/db-browser/src/main/java/com/oceanbase/tools/dbbrowser/schema/oracle/OracleSchemaAccessor.java @@ -86,12 +86,13 @@ public class OracleSchemaAccessor implements DBSchemaAccessor { "COMMENT ON TABLE ${schemaName}.${tableName} IS ${comment}"; private static final String ORACLE_COLUMN_COMMENT_DDL_TEMPLATE = "COMMENT ON COLUMN ${schemaName}.${tableName}.${columnName} IS ${comment}"; - private static final Set ESCAPE_USER_SET = new HashSet<>(3); + protected static final Set ESCAPE_USER_SET = new HashSet<>(3); static { ESCAPE_USER_SET.add("PUBLIC"); ESCAPE_USER_SET.add("LBACSYS"); ESCAPE_USER_SET.add("ORAAUDITOR"); + ESCAPE_USER_SET.add("__public"); } protected OracleDataDictTableNames dataDictTableNames; protected JdbcOperations jdbcOperations; From d49e5665a9a7bf74317f893a5f7e14830ed19ce3 Mon Sep 17 00:00:00 2001 From: pynzzZ <39962741+MarkPotato777@users.noreply.github.com> Date: Tue, 5 Sep 2023 14:09:34 +0800 Subject: [PATCH 3/7] fix (#148) --- .secignore | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.secignore b/.secignore index 0128e11c3f..641b111ca0 100644 --- a/.secignore +++ b/.secignore @@ -85,14 +85,14 @@ test@email.com https://tools.ietf.org* https://obodc-front.oss-cn-beijing.aliyuncs.com/ODC* - https://discord.gg/drPUb2kq + https://discord.gg* https://qr.dingtalk.com/action/joingroup* https://help.github.com* https://npmmirror.com* https://www.contributor-covenant.org* https://www.conventionalcommits* https://plugins.jetbrains.com - yizhou.xw@oceanbase.com + *@oceanbase.com https://www.jetbrains.com* https://plugins.jetbrains.com* http://alipay-rmsdeploy-image.cn-hangzhou.alipay.aliyun-inc.com/oceanbase/odc* From 549dabe230d2b00b84bad3066d1c3048aa3f01ee Mon Sep 17 00:00:00 2001 From: IL MARE Date: Tue, 5 Sep 2023 14:39:26 +0800 Subject: [PATCH 4/7] fix(db-session): fix can not get latest query sql when list all sessions (#133) * fix(db-session): fix can not get latest query sql when list all sessions * refactor(OdcDBSession): rename variable * Revert "refactor(OdcDBSession): rename variable" This reverts commit 05bfecb1 * refactor(OdcDBSession): rename variable --- .../odc/core/shared/model/OdcDBSession.java | 21 ++++++++++--------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/server/odc-core/src/main/java/com/oceanbase/odc/core/shared/model/OdcDBSession.java b/server/odc-core/src/main/java/com/oceanbase/odc/core/shared/model/OdcDBSession.java index 2ae8acd551..a92c201bb6 100644 --- a/server/odc-core/src/main/java/com/oceanbase/odc/core/shared/model/OdcDBSession.java +++ b/server/odc-core/src/main/java/com/oceanbase/odc/core/shared/model/OdcDBSession.java @@ -33,15 +33,16 @@ public class OdcDBSession { private String svrIp; public static OdcDBSession from(DBSession dbSession) { - OdcDBSession odcDBSession = new OdcDBSession(); - odcDBSession.setSessionId(Long.parseLong(dbSession.getId())); - odcDBSession.setDbUser(dbSession.getUsername()); - odcDBSession.setSrcIp(dbSession.getHost()); - odcDBSession.setDatabase(dbSession.getDatabaseName()); - odcDBSession.setCommand(dbSession.getCommand()); - odcDBSession.setExecuteTime(dbSession.getExecuteTime()); - odcDBSession.setStatus(dbSession.getState()); - odcDBSession.setObproxyIp(dbSession.getProxyHost()); - return odcDBSession; + OdcDBSession session = new OdcDBSession(); + session.setSessionId(Long.parseLong(dbSession.getId())); + session.setDbUser(dbSession.getUsername()); + session.setSrcIp(dbSession.getHost()); + session.setDatabase(dbSession.getDatabaseName()); + session.setCommand(dbSession.getCommand()); + session.setExecuteTime(dbSession.getExecuteTime()); + session.setStatus(dbSession.getState()); + session.setObproxyIp(dbSession.getProxyHost()); + session.setSql(dbSession.getLatestQueries()); + return session; } } From db9672fba9d97d646dda2f3ebc14faab5c1c8ce5 Mon Sep 17 00:00:00 2001 From: zhangxiao <140503120+PeachThinking@users.noreply.github.com> Date: Tue, 5 Sep 2023 15:16:51 +0800 Subject: [PATCH 5/7] fix desktop odc cannot generate rollback plan (#145) --- .../odc/service/flow/FlowInstanceService.java | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/server/odc-service/src/main/java/com/oceanbase/odc/service/flow/FlowInstanceService.java b/server/odc-service/src/main/java/com/oceanbase/odc/service/flow/FlowInstanceService.java index b80ebba52b..79544cceaf 100644 --- a/server/odc-service/src/main/java/com/oceanbase/odc/service/flow/FlowInstanceService.java +++ b/server/odc-service/src/main/java/com/oceanbase/odc/service/flow/FlowInstanceService.java @@ -629,7 +629,17 @@ private FlowInstanceDetailResp buildWithoutApprovalNode(CreateFlowInstanceReq fl strategyConfig); taskInstance.setTargetTaskId(taskEntity.getId()); taskInstance.update(); - FlowInstanceConfigurer taskConfigurer = flowInstance.newFlowInstance().next(taskInstance); + TaskParameters parameters = flowInstanceReq.getParameters(); + FlowInstanceConfigurer taskConfigurer; + if (taskType == TaskType.ASYNC + && Boolean.TRUE.equals(((DatabaseChangeParameters) parameters).getGenerateRollbackPlan())) { + FlowTaskInstance rollbackPlanInstance = + flowFactory.generateFlowTaskInstance(flowInstance.getId(), false, false, + TaskType.GENERATE_ROLLBACK, ExecutionStrategyConfig.autoStrategy()); + taskConfigurer = flowInstance.newFlowInstance().next(rollbackPlanInstance).next(taskInstance); + } else { + taskConfigurer = flowInstance.newFlowInstance().next(taskInstance); + } taskConfigurer.endFlowInstance(); flowInstance.buildTopology(); From 6d44d4914243dc608c7cd74fa09f551cbcb1a1c0 Mon Sep 17 00:00:00 2001 From: yaobin <51393259+krihy@users.noreply.github.com> Date: Tue, 5 Sep 2023 15:39:35 +0800 Subject: [PATCH 6/7] fix(osc): fix duplicate foreign key constraint name when execute new table create ddl (#135) * create CreateWalkerOBParserReplaceStatementListener extends alter ddl * 1.add test case * 1.format code --- .../OnlineSchemaChangeValidatorTest.java | 19 +++- .../ddl/TableNameReplacerTest.java | 73 ++++++++++++++ .../ddl/OBMysqlTableNameReplacer.java | 96 +++++++++++++++---- 3 files changed, 170 insertions(+), 18 deletions(-) diff --git a/server/integration-test/src/test/java/com/oceanbase/odc/service/onlineschemachange/OnlineSchemaChangeValidatorTest.java b/server/integration-test/src/test/java/com/oceanbase/odc/service/onlineschemachange/OnlineSchemaChangeValidatorTest.java index c4fd40eba8..8dd9d0f181 100644 --- a/server/integration-test/src/test/java/com/oceanbase/odc/service/onlineschemachange/OnlineSchemaChangeValidatorTest.java +++ b/server/integration-test/src/test/java/com/oceanbase/odc/service/onlineschemachange/OnlineSchemaChangeValidatorTest.java @@ -16,6 +16,7 @@ package com.oceanbase.odc.service.onlineschemachange; import org.junit.After; +import org.junit.Assert; import org.junit.Before; import org.junit.Test; import org.mockito.Mockito; @@ -28,6 +29,7 @@ import com.oceanbase.odc.core.session.ConnectionSession; import com.oceanbase.odc.core.session.ConnectionSessionConstants; import com.oceanbase.odc.core.shared.constant.ConnectType; +import com.oceanbase.odc.core.shared.constant.ErrorCodes; import com.oceanbase.odc.core.shared.exception.BadArgumentException; import com.oceanbase.odc.service.connection.ConnectionService; import com.oceanbase.odc.service.connection.model.ConnectionConfig; @@ -67,7 +69,9 @@ public void setUp() { @After public void tearDown() { - session.getSyncJdbcExecutor(ConnectionSessionConstants.CONSOLE_DS_KEY).execute(DROP_STMT); + if (session != null) { + session.getSyncJdbcExecutor(ConnectionSessionConstants.CONSOLE_DS_KEY).execute(DROP_STMT); + } } @Test @@ -98,6 +102,19 @@ public void test_Validate_Alter_Failed() { OnlineSchemaChangeSqlType.CREATE)); } + @Test(expected = BadArgumentException.class) + public void test_Validate_Invalid_Sql() { + String sql = " CREATE TABLE \"ABC10_OSC_NEW_111\" (\n \"COL\" NUMBER(38) DEFAULT NULL"; + try { + validService.validate(getCreateRequest( + sql, + OnlineSchemaChangeSqlType.CREATE)); + } catch (BadArgumentException ex) { + Assert.assertSame(ex.getErrorCode(), ErrorCodes.ObPreCheckDdlFailed); + throw ex; + } + } + private CreateFlowInstanceReq getCreateRequest(String sql, OnlineSchemaChangeSqlType sqlType) { OnlineSchemaChangeParameters parameter = new OnlineSchemaChangeParameters(); parameter.setSqlType(sqlType); diff --git a/server/integration-test/src/test/java/com/oceanbase/odc/service/onlineschemachange/ddl/TableNameReplacerTest.java b/server/integration-test/src/test/java/com/oceanbase/odc/service/onlineschemachange/ddl/TableNameReplacerTest.java index 293394fed8..51ab35d4a2 100644 --- a/server/integration-test/src/test/java/com/oceanbase/odc/service/onlineschemachange/ddl/TableNameReplacerTest.java +++ b/server/integration-test/src/test/java/com/oceanbase/odc/service/onlineschemachange/ddl/TableNameReplacerTest.java @@ -15,9 +15,20 @@ */ package com.oceanbase.odc.service.onlineschemachange.ddl; +import java.io.StringReader; +import java.util.List; +import java.util.Optional; + import org.junit.Assert; import org.junit.Test; +import com.oceanbase.tools.sqlparser.OBMySQLParser; +import com.oceanbase.tools.sqlparser.OBOracleSQLParser; +import com.oceanbase.tools.sqlparser.statement.Statement; +import com.oceanbase.tools.sqlparser.statement.createtable.CreateTable; +import com.oceanbase.tools.sqlparser.statement.createtable.OutOfLineConstraint; +import com.oceanbase.tools.sqlparser.statement.createtable.OutOfLineForeignConstraint; + public class TableNameReplacerTest { private static final String CREATE_STMT = "create table t1 (id int);"; private static final String CREATE_QUOTE_STMT = "create table \"t1\" (id int);"; @@ -44,6 +55,68 @@ public void test_RewriteCreateStmt_Oracle() { Assert.assertEquals("create table t1_osc_new_ (id int);", newSql); } + @Test + public void test_RewriteCreateStmtWittConstraint_Oracle() { + String createSql = "CREATE TABLE CHILD_TABLE1 (\n" + + "COL NUMBER NOT NULL,\n" + + "COL1 NUMBER NOT NULL,\n" + + "CONSTRAINT P1 PRIMARY KEY (COL),\n" + + "CONSTRAINT U1 UNIQUE (COL1),\n" + + "CONSTRAINT F1 FOREIGN KEY (COL) REFERENCES PARENT_TABLE1 (COL) ON DELETE CASCADE \n" + + ")"; + String newSql = new OBOracleTableNameReplacer().replaceCreateStmt(createSql, "CHILD_TABLE_NEW"); + Statement statement = new OBOracleSQLParser().parse(new StringReader(newSql)); + Assert.assertTrue(statement instanceof CreateTable); + CreateTable createTable = (CreateTable) statement; + List constraints = createTable.getConstraints(); + Optional pk = constraints.stream().filter(OutOfLineConstraint::isPrimaryKey).findFirst(); + Assert.assertTrue(pk.isPresent()); + Assert.assertNotEquals("P1", pk.get().getConstraintName()); + + Optional uk = constraints.stream().filter(OutOfLineConstraint::isUniqueKey).findFirst(); + Assert.assertTrue(uk.isPresent()); + Assert.assertNotEquals("U1", uk.get().getConstraintName()); + + Optional fk = + constraints.stream().filter(c -> (c instanceof OutOfLineForeignConstraint)) + .map(c -> (OutOfLineForeignConstraint) c).findFirst(); + Assert.assertTrue(fk.isPresent()); + Assert.assertNotEquals("F1", pk.get().getConstraintName()); + } + + + + @Test + public void test_RewriteCreateStmtWittConstraint_MySql() { + String createSql = "CREATE TABLE `child_table1` (\n" + + "`col` int NOT NULL,\n" + + "`col1` int NOT NULL,\n" + + "CONSTRAINT `p1` PRIMARY KEY (`col`),\n" + + "CONSTRAINT `u1` UNIQUE (`col`),\n" + + "UNIQUE (`col`),\n" + + "CONSTRAINT `f1` FOREIGN KEY (`col`) REFERENCES `parent_table1` (`col`) ON DELETE CASCADE ON " + + "UPDATE NO ACTION\n" + + ")\n"; + String newSql = new OBMysqlTableNameReplacer().replaceCreateStmt(createSql, "`child_table1_new`"); + Statement statement = new OBMySQLParser().parse(new StringReader(newSql)); + Assert.assertTrue(statement instanceof CreateTable); + CreateTable createTable = (CreateTable) statement; + List constraints = createTable.getConstraints(); + Optional pk = constraints.stream().filter(OutOfLineConstraint::isPrimaryKey).findFirst(); + Assert.assertTrue(pk.isPresent()); + Assert.assertEquals("`p1`", pk.get().getConstraintName()); + + Optional uk = constraints.stream().filter(OutOfLineConstraint::isUniqueKey).findFirst(); + Assert.assertTrue(uk.isPresent()); + Assert.assertEquals("`u1`", uk.get().getConstraintName()); + + Optional fk = + constraints.stream().filter(c -> (c instanceof OutOfLineForeignConstraint)) + .map(c -> (OutOfLineForeignConstraint) c).findFirst(); + Assert.assertTrue(fk.isPresent()); + Assert.assertNotEquals("`f1`", pk.get().getConstraintName()); + } + @Test public void test_RewriteCreateStmtWithQuote_Oracle() { String newSql = new OBOracleTableNameReplacer().replaceCreateStmt(CREATE_QUOTE_STMT, diff --git a/server/odc-service/src/main/java/com/oceanbase/odc/service/onlineschemachange/ddl/OBMysqlTableNameReplacer.java b/server/odc-service/src/main/java/com/oceanbase/odc/service/onlineschemachange/ddl/OBMysqlTableNameReplacer.java index c6fd60d9d0..237d4c0693 100644 --- a/server/odc-service/src/main/java/com/oceanbase/odc/service/onlineschemachange/ddl/OBMysqlTableNameReplacer.java +++ b/server/odc-service/src/main/java/com/oceanbase/odc/service/onlineschemachange/ddl/OBMysqlTableNameReplacer.java @@ -16,6 +16,8 @@ package com.oceanbase.odc.service.onlineschemachange.ddl; import java.util.List; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.function.Function; import org.antlr.v4.runtime.CharStream; import org.antlr.v4.runtime.CharStreams; @@ -24,20 +26,39 @@ import org.antlr.v4.runtime.tree.ParseTree; import org.antlr.v4.runtime.tree.ParseTreeWalker; import org.antlr.v4.runtime.tree.TerminalNode; +import org.antlr.v4.runtime.tree.TerminalNodeImpl; +import com.oceanbase.odc.common.util.StringUtils; import com.oceanbase.odc.core.shared.PreConditions; import com.oceanbase.tools.sqlparser.FastFailErrorListener; import com.oceanbase.tools.sqlparser.obmysql.OBLexer; import com.oceanbase.tools.sqlparser.obmysql.OBParser; import com.oceanbase.tools.sqlparser.obmysql.OBParser.Alter_table_stmtContext; +import com.oceanbase.tools.sqlparser.obmysql.OBParser.Constraint_nameContext; import com.oceanbase.tools.sqlparser.obmysql.OBParser.Create_table_stmtContext; +import com.oceanbase.tools.sqlparser.obmysql.OBParser.Out_of_line_constraintContext; import com.oceanbase.tools.sqlparser.obmysql.OBParser.Relation_factorContext; import com.oceanbase.tools.sqlparser.obmysql.OBParser.Relation_nameContext; import com.oceanbase.tools.sqlparser.obmysql.OBParserBaseListener; public class OBMysqlTableNameReplacer implements TableNameReplacer { + private static final String CONSTRAINT_KEYWORD = "CONSTRAINT"; + private static final String FOREIGN_KEYWORD = "FOREIGN"; + public String replaceCreateStmt(String originCreateStmt, String newTableName) { + return getRewriteSql(originCreateStmt, + rewriter -> new CreateWalkerOBParserReplaceStatementListener(rewriter, newTableName)); + } + + @Override + public String replaceAlterStmt(String originAlterStmt, String newTableName) { + return getRewriteSql(originAlterStmt, + rewriter -> new WalkerOBParserReplaceStatementListener(rewriter, newTableName)); + } + + private static String getRewriteSql(String originCreateStmt, + Function obParserBaseListenerFunc) { CharStream charStream = CharStreams.fromString(originCreateStmt); OBLexer lexer = new OBLexer(charStream); @@ -49,21 +70,13 @@ public String replaceCreateStmt(String originCreateStmt, String newTableName) { parser.setTrace(false); TokenStreamRewriter tokenStreamRewriter = new TokenStreamRewriter(tokens); - WalkerOBParserReplaceStatementListener eventParser = new WalkerOBParserReplaceStatementListener( - tokenStreamRewriter, newTableName); - - new ParseTreeWalker().walk(eventParser, parser.sql_stmt()); + new ParseTreeWalker().walk(obParserBaseListenerFunc.apply(tokenStreamRewriter), parser.sql_stmt()); return tokenStreamRewriter.getText(); } - @Override - public String replaceAlterStmt(String originAlterStmt, String newTableName) { - return replaceCreateStmt(originAlterStmt, newTableName); - } - static class WalkerOBParserReplaceStatementListener extends OBParserBaseListener { - private final TokenStreamRewriter tokenStreamRewriter; - private final String newTableName; + protected final TokenStreamRewriter tokenStreamRewriter; + protected final String newTableName; public WalkerOBParserReplaceStatementListener(TokenStreamRewriter tokenStreamRewriter, String newTableName) { this.tokenStreamRewriter = tokenStreamRewriter; @@ -75,12 +88,7 @@ public void enterAlter_table_stmt(Alter_table_stmtContext ctx) { relationFactorReplace(ctx.relation_factor()); } - @Override - public void enterCreate_table_stmt(Create_table_stmtContext ctx) { - relationFactorReplace(ctx.relation_factor()); - } - - private void relationFactorReplace(Relation_factorContext relation_factorContext) { + protected void relationFactorReplace(Relation_factorContext relation_factorContext) { List relation_nameContexts = relation_factorContext.normal_relation_factor() .relation_name(); @@ -93,6 +101,60 @@ private void relationFactorReplace(Relation_factorContext relation_factorContext tokenStreamRewriter.replace(terminalNode.getSymbol(), newTableName); } } + } + + static class CreateWalkerOBParserReplaceStatementListener extends WalkerOBParserReplaceStatementListener { + private final AtomicBoolean IS_CONSTRAINT_FOREIGN_KEY = new AtomicBoolean(false); + + public CreateWalkerOBParserReplaceStatementListener(TokenStreamRewriter tokenStreamRewriter, + String newTableName) { + super(tokenStreamRewriter, newTableName); + } + + @Override + public void enterCreate_table_stmt(Create_table_stmtContext ctx) { + relationFactorReplace(ctx.relation_factor()); + } + + @Override + public void enterOut_of_line_constraint(Out_of_line_constraintContext ctx) { + if (ctx.getChildCount() == 0) { + return; + } + ParseTree firstChild = ctx.getChild(0); + if (firstChild instanceof TerminalNodeImpl) { + String keyword = ((TerminalNodeImpl) firstChild).getSymbol().getText(); + if (CONSTRAINT_KEYWORD.equalsIgnoreCase(keyword) && ctx.getChildCount() >= 3) { + if (ctx.getChild(2) instanceof TerminalNodeImpl) { + if (FOREIGN_KEYWORD.equalsIgnoreCase( + ((TerminalNodeImpl) ctx.getChild(2)).getSymbol().getText())) { + IS_CONSTRAINT_FOREIGN_KEY.getAndSet(true); + } + } + } + } + } + + @Override + public void exitOut_of_line_constraint(Out_of_line_constraintContext ctx) { + IS_CONSTRAINT_FOREIGN_KEY.getAndSet(false); + } + @Override + public void enterConstraint_name(Constraint_nameContext ctx) { + if (ctx.getChildCount() == 0 || !IS_CONSTRAINT_FOREIGN_KEY.get()) { + return; + } + ParseTree parseTree = ctx.getChild(0); + if (parseTree instanceof Relation_nameContext) { + + Relation_nameContext relation_nameContext = (Relation_nameContext) parseTree; + ParseTree childNode = relation_nameContext.getChild(0); + if (childNode instanceof TerminalNode) { + TerminalNode terminalNode = (TerminalNode) childNode; + tokenStreamRewriter.replace(terminalNode.getSymbol(), "A" + StringUtils.uuidNoHyphen()); + } + } + } } } From aff12d96acda2ef874af77868022ba52b6f5b39c Mon Sep 17 00:00:00 2001 From: XiaoYang Date: Tue, 5 Sep 2023 16:57:24 +0800 Subject: [PATCH 7/7] fix(integration): uncatched exception when failed to get flow instance (#156) --- .../odc/service/flow/FlowInstanceService.java | 1 + .../flow/instance/FlowInstanceConfigurer.java | 6 +-- .../flow/task/CreateExternalApprovalTask.java | 45 +++++++++++-------- .../flow/task/model/RuntimeTaskConstants.java | 1 + .../odc/service/flow/util/FlowTaskUtil.java | 9 ++++ 5 files changed, 40 insertions(+), 22 deletions(-) diff --git a/server/odc-service/src/main/java/com/oceanbase/odc/service/flow/FlowInstanceService.java b/server/odc-service/src/main/java/com/oceanbase/odc/service/flow/FlowInstanceService.java index 79544cceaf..ab2a96df59 100644 --- a/server/odc-service/src/main/java/com/oceanbase/odc/service/flow/FlowInstanceService.java +++ b/server/odc-service/src/main/java/com/oceanbase/odc/service/flow/FlowInstanceService.java @@ -710,6 +710,7 @@ private FlowInstanceDetailResp buildFlowInstance(List riskLevels, flowInstance.dealloc(); } Map variables = new HashMap<>(); + FlowTaskUtil.setFlowInstanceId(variables, flowInstance.getId()); FlowTaskUtil.setTemplateVariables(variables, buildTemplateVariables(flowInstanceReq, connectionConfig)); initVariables(variables, taskEntity, preCheckTaskEntity, connectionConfig, buildRiskLevelDescriber(flowInstanceReq)); diff --git a/server/odc-service/src/main/java/com/oceanbase/odc/service/flow/instance/FlowInstanceConfigurer.java b/server/odc-service/src/main/java/com/oceanbase/odc/service/flow/instance/FlowInstanceConfigurer.java index 0e721a356b..10c14985ef 100644 --- a/server/odc-service/src/main/java/com/oceanbase/odc/service/flow/instance/FlowInstanceConfigurer.java +++ b/server/odc-service/src/main/java/com/oceanbase/odc/service/flow/instance/FlowInstanceConfigurer.java @@ -222,11 +222,11 @@ protected FlowInstanceConfigurer next(@NonNull FlowApprovalInstance nextNode, ExclusiveGatewayBuilder gatewayBuilder = nullSafeGetNodeBuilder(gatewayName, nextNode, () -> new ExclusiveGatewayBuilder(gatewayName)); targetExecution.next(serviceTaskBuilder).next(gatewayBuilder); - String expr = RuntimeTaskConstants.SUCCESS_CREATE_EXT_INS + "_" + nextNode.getId(); - targetExecution.route(String.format("${!%s}", expr), this.targetProcessBuilder.endProcess()); + targetExecution.route(String.format("${!%s}", RuntimeTaskConstants.SUCCESS_CREATE_EXT_INS), + this.targetProcessBuilder.endProcess()); targetExecution.next(userTaskBuilder, new ConditionSequenceFlowBuilder( gatewayBuilder.getGraphId() + " -> " + serviceTaskBuilder.getGraphId(), - String.format("${%s}", expr))); + String.format("${%s}", RuntimeTaskConstants.SUCCESS_CREATE_EXT_INS))); } else { targetExecution.next(userTaskBuilder); } diff --git a/server/odc-service/src/main/java/com/oceanbase/odc/service/flow/task/CreateExternalApprovalTask.java b/server/odc-service/src/main/java/com/oceanbase/odc/service/flow/task/CreateExternalApprovalTask.java index d5715b44a6..ea833075e0 100644 --- a/server/odc-service/src/main/java/com/oceanbase/odc/service/flow/task/CreateExternalApprovalTask.java +++ b/server/odc-service/src/main/java/com/oceanbase/odc/service/flow/task/CreateExternalApprovalTask.java @@ -16,7 +16,6 @@ package com.oceanbase.odc.service.flow.task; -import java.util.Objects; import java.util.Optional; import org.flowable.engine.delegate.DelegateExecution; @@ -24,6 +23,7 @@ import com.oceanbase.odc.common.util.RetryExecutor; import com.oceanbase.odc.core.flow.BaseFlowableDelegate; +import com.oceanbase.odc.core.shared.Verify; import com.oceanbase.odc.core.shared.constant.FlowStatus; import com.oceanbase.odc.metadb.flow.FlowInstanceRepository; import com.oceanbase.odc.service.flow.FlowableAdaptor; @@ -62,31 +62,39 @@ protected void run(DelegateExecution execution) throws Exception { try { flowApprovalInstance = getFlowApprovalInstance(execution); } catch (Exception e) { - log.warn("Get flow approval instance failed, activityId={}, processDefinitionId={}", + log.warn( + "Get flow approval instance failed, the flow instance is coming to an end, activityId={}, processDefinitionId={}", execution.getCurrentActivityId(), execution.getProcessDefinitionId(), e); + try { + flowInstanceRepository.updateStatusById(FlowTaskUtil.getFlowInstanceId(execution), + FlowStatus.EXECUTION_FAILED); + } finally { + execution.setVariable(RuntimeTaskConstants.SUCCESS_CREATE_EXT_INS, false); + } return; } Long externalApprovalId = flowApprovalInstance.getExternalApprovalId(); - String expr = RuntimeTaskConstants.SUCCESS_CREATE_EXT_INS + "_" + flowApprovalInstance.getId(); - if (Objects.nonNull(externalApprovalId)) { + try { + Verify.notNull(externalApprovalId, "externalApprovalId"); + IntegrationConfig config = integrationService.detailWithoutPermissionCheck(externalApprovalId); + ApprovalProperties properties = ApprovalProperties.from(config); + TemplateVariables variables = FlowTaskUtil.getTemplateVariables(execution.getVariables()); + String externalFlowInstanceId = approvalClient.start(properties, variables); + flowApprovalInstance.setExternalFlowInstanceId(externalFlowInstanceId); + flowApprovalInstance.update(); + execution.setVariable(RuntimeTaskConstants.SUCCESS_CREATE_EXT_INS, true); + } catch (Exception e) { + log.warn("Create external approval instance failed, the flow instance is coming to an end, " + + "flowApprovalInstanceId={}, externalApprovalId={}", + flowApprovalInstance.getId(), externalApprovalId, e); try { - IntegrationConfig config = integrationService.detailWithoutPermissionCheck(externalApprovalId); - ApprovalProperties properties = ApprovalProperties.from(config); - TemplateVariables variables = FlowTaskUtil.getTemplateVariables(execution.getVariables()); - String externalFlowInstanceId = approvalClient.start(properties, variables); - flowApprovalInstance.setExternalFlowInstanceId(externalFlowInstanceId); - flowApprovalInstance.update(); - execution.setVariable(expr, true); - } catch (Exception e) { - log.warn("Create external approval instance failed, the flow instance is coming to an end, " - + "flowApprovalInstanceId={}, externalApprovalId={}", - flowApprovalInstance.getId(), externalApprovalId, e); flowApprovalInstance.setStatus(FlowNodeStatus.FAILED); flowApprovalInstance.setComment(e.getLocalizedMessage()); flowApprovalInstance.update(); flowInstanceRepository.updateStatusById(flowApprovalInstance.getFlowInstanceId(), FlowStatus.EXECUTION_FAILED); - execution.setVariable(expr, false); + } finally { + execution.setVariable(RuntimeTaskConstants.SUCCESS_CREATE_EXT_INS, false); } } } @@ -97,8 +105,7 @@ private FlowApprovalInstance getFlowApprovalInstance(DelegateExecution execution Optional> flowInstanceIdOpt = retryExecutor.run( () -> flowableAdaptor.getFlowInstanceIdByProcessDefinitionId(processDefinitionId), Optional::isPresent); if (!flowInstanceIdOpt.isPresent() || !flowInstanceIdOpt.get().isPresent()) { - log.warn("Flow instance id does not exist, activityId={}, processDefinitionId={}", activityId, - processDefinitionId); + log.warn("Flow instance id does not exist, processDefinitionId={}", processDefinitionId); throw new IllegalStateException( "Can not find flow instance id by process definition id " + processDefinitionId); } @@ -108,7 +115,7 @@ private FlowApprovalInstance getFlowApprovalInstance(DelegateExecution execution if (!instanceOpt.isPresent()) { log.warn("Flow approval instance does not exist, activityId={}, flowInstanceId={}", activityId, flowInstanceId); - throw new IllegalStateException("Can not find instance by activityId " + activityId); + throw new IllegalStateException("Can not find flow approval instance by activityId " + activityId); } return instanceOpt.get(); } diff --git a/server/odc-service/src/main/java/com/oceanbase/odc/service/flow/task/model/RuntimeTaskConstants.java b/server/odc-service/src/main/java/com/oceanbase/odc/service/flow/task/model/RuntimeTaskConstants.java index 84d184f4bd..6500891cf1 100644 --- a/server/odc-service/src/main/java/com/oceanbase/odc/service/flow/task/model/RuntimeTaskConstants.java +++ b/server/odc-service/src/main/java/com/oceanbase/odc/service/flow/task/model/RuntimeTaskConstants.java @@ -22,6 +22,7 @@ public class RuntimeTaskConstants { public static final String PRE_CHECK_TASK_ID = "preCheckTaskId"; public static final String TASK_ID = "taskId"; + public static final String FLOW_INSTANCE_ID = "flowInstanceId"; public static final String TIMEOUT_MILLI_SECONDS = "timeOutMilliSeconds"; public static final String CONNECTION_CONFIG = "connectionConfig"; public static final String SCHEMA_NAME = "schemaName"; diff --git a/server/odc-service/src/main/java/com/oceanbase/odc/service/flow/util/FlowTaskUtil.java b/server/odc-service/src/main/java/com/oceanbase/odc/service/flow/util/FlowTaskUtil.java index df1a3e3bc6..9ed799d0c1 100644 --- a/server/odc-service/src/main/java/com/oceanbase/odc/service/flow/util/FlowTaskUtil.java +++ b/server/odc-service/src/main/java/com/oceanbase/odc/service/flow/util/FlowTaskUtil.java @@ -224,6 +224,15 @@ public static ConnectionConfig getConnectionConfig(@NonNull DelegateExecution ex () -> new VerifyException("ConnectionConfig is absent")); } + public static void setFlowInstanceId(@NonNull Map variables, @NonNull Long flowInstanceId) { + variables.put(RuntimeTaskConstants.FLOW_INSTANCE_ID, flowInstanceId); + } + + public static Long getFlowInstanceId(@NonNull DelegateExecution execution) { + Object value = execution.getVariables().get(RuntimeTaskConstants.FLOW_INSTANCE_ID); + return internalGet(value, Long.class).orElseThrow(() -> new VerifyException("FlowInstanceId is absent")); + } + public static void setTemplateVariables(@NonNull Map variables, @NonNull TemplateVariables templateVariables) { variables.put(RuntimeTaskConstants.INTEGRATION_TEMPLATE_VARIABLES, templateVariables);