From f7560a6ce723e36a1fd5c6528d0f33289f37a4d0 Mon Sep 17 00:00:00 2001 From: walter Date: Wed, 8 Jan 2025 22:34:02 +0800 Subject: [PATCH] [fix](suites) Fix atomic restore alter suite with master_sql (#46550) Add a helper `master_sql`, to connect to FE master and execute sql. --- .../doris/regression/suite/Suite.groovy | 12 +++++ .../regression/suite/SuiteContext.groovy | 47 ++++++++++++++++++- ...st_backup_restore_atomic_with_alter.groovy | 4 +- 3 files changed, 60 insertions(+), 3 deletions(-) diff --git a/regression-test/framework/src/main/groovy/org/apache/doris/regression/suite/Suite.groovy b/regression-test/framework/src/main/groovy/org/apache/doris/regression/suite/Suite.groovy index 7f21f45774bd6e..3995371db952da 100644 --- a/regression-test/framework/src/main/groovy/org/apache/doris/regression/suite/Suite.groovy +++ b/regression-test/framework/src/main/groovy/org/apache/doris/regression/suite/Suite.groovy @@ -403,6 +403,10 @@ class Suite implements GroovyInterceptable { } } + List> master_sql(String sqlStr, boolean isOrder = false) { + return sql_impl(context.getMasterConnection(), sqlStr, isOrder) + } + List> multi_sql(String sqlStr, boolean isOrder = false) { String[] sqls = sqlStr.split(";") def result = new ArrayList(); @@ -514,6 +518,10 @@ class Suite implements GroovyInterceptable { return sql_return_maparray_impl(sqlStr, context.getConnection()) } + def master_sql_return_maparray(String sqlStr) { + return sql_return_maparray_impl(sqlStr, context.getMasterConnection()) + } + def arrow_flight_sql_return_maparray(String sqlStr) { return sql_return_maparray_impl((String) ("USE ${context.dbName};" + sqlStr), context.getArrowFlightSqlConnection()) } @@ -1268,6 +1276,8 @@ class Suite implements GroovyInterceptable { tupleResult = JdbcUtils.executeToStringList(context.getArrowFlightSqlConnection(), (PreparedStatement) arg) } else if (tag.contains("target_sql")) { tupleResult = JdbcUtils.executeToStringList(context.getTargetConnection(this), (PreparedStatement) arg) + } else if (tag.contains("master_sql")) { + tupleResult = JdbcUtils.executeToStringList(context.getMasterConnection(), (PreparedStatement) arg) } else { tupleResult = JdbcUtils.executeToStringList(context.getConnection(), (PreparedStatement) arg) } @@ -1281,6 +1291,8 @@ class Suite implements GroovyInterceptable { (String) ("USE ${context.dbName};" + (String) arg)) } else if (tag.contains("target_sql")) { tupleResult = JdbcUtils.executeToStringList(context.getTargetConnection(this), (String) arg) + } else if (tag.contains("master_sql")) { + tupleResult = JdbcUtils.executeToStringList(context.getMasterConnection(), (PreparedStatement) arg) } else { tupleResult = JdbcUtils.executeToStringList(context.getConnection(), (String) arg) } diff --git a/regression-test/framework/src/main/groovy/org/apache/doris/regression/suite/SuiteContext.groovy b/regression-test/framework/src/main/groovy/org/apache/doris/regression/suite/SuiteContext.groovy index 88ad1fac355d17..076566651e5429 100644 --- a/regression-test/framework/src/main/groovy/org/apache/doris/regression/suite/SuiteContext.groovy +++ b/regression-test/framework/src/main/groovy/org/apache/doris/regression/suite/SuiteContext.groovy @@ -44,6 +44,7 @@ class SuiteContext implements Closeable { public final String group public final String dbName public final ThreadLocal threadLocalConn = new ThreadLocal<>() + public final ThreadLocal threadLocalMasterConn = new ThreadLocal<>() public final ThreadLocal threadArrowFlightSqlConn = new ThreadLocal<>() public final ThreadLocal threadHive2DockerConn = new ThreadLocal<>() public final ThreadLocal threadHive3DockerConn = new ThreadLocal<>() @@ -145,13 +146,26 @@ class SuiteContext implements Closeable { if (threadConnInfo == null) { threadConnInfo = new ConnectionInfo() threadConnInfo.conn = config.getConnectionByDbName(dbName) - threadConnInfo.username = config.jdbcUser + threadConnInfo.username = config.jdbcUser threadConnInfo.password = config.jdbcPassword threadLocalConn.set(threadConnInfo) } return threadConnInfo.conn } + // like getConnection, but connect to FE master + Connection getMasterConnection() { + def threadConnInfo = threadLocalMasterConn.get() + if (threadConnInfo == null) { + threadConnInfo = new ConnectionInfo() + threadConnInfo.conn = getMasterConnectionByDbName(dbName) + threadConnInfo.username = config.jdbcUser + threadConnInfo.password = config.jdbcPassword + threadLocalMasterConn.set(threadConnInfo) + } + return threadConnInfo.conn + } + Connection getArrowFlightSqlConnection() { def threadConnInfo = threadArrowFlightSqlConn.get() if (threadConnInfo == null) { @@ -316,6 +330,27 @@ class SuiteContext implements Closeable { } } + Connection getMasterConnectionByDbName(String dbName) { + def result = JdbcUtils.executeToMapArray(getConnection(), "SHOW FRONTENDS") + def master = null + for (def row : result) { + if (row.IsMaster == "true") { + master = row + break + } + } + if (master) { + log.info("master found: ${master.Host}:${master.HttpPort}") + def url = Config.buildUrlWithDb(master.Host as String, master.QueryPort as Integer, dbName) + def username = config.jdbcUser + def password = config.jdbcPassword + + return DriverManager.getConnection(url, username, password) + } else { + throw new Exception("No master found to reconnect") + } + } + def reconnectToMasterFe = { -> log.info("Reconnecting to a new master frontend...") def result = JdbcUtils.executeToMapArray(getConnection(), "SHOW FRONTENDS") @@ -468,6 +503,16 @@ class SuiteContext implements Closeable { } } + ConnectionInfo master_conn = threadLocalMasterConn.get() + if (master_conn != null) { + threadLocalMasterConn.remove() + try { + master_conn.conn.close() + } catch (Throwable t) { + log.warn("Close master connection failed", t) + } + } + ConnectionInfo arrow_flight_sql_conn = threadArrowFlightSqlConn.get() if (arrow_flight_sql_conn != null) { threadArrowFlightSqlConn.remove() diff --git a/regression-test/suites/backup_restore/test_backup_restore_atomic_with_alter.groovy b/regression-test/suites/backup_restore/test_backup_restore_atomic_with_alter.groovy index ea8ddd4d11c1d9..6de54eafca5db7 100644 --- a/regression-test/suites/backup_restore/test_backup_restore_atomic_with_alter.groovy +++ b/regression-test/suites/backup_restore/test_backup_restore_atomic_with_alter.groovy @@ -125,7 +125,7 @@ suite("test_backup_restore_atomic_with_alter", "backup_restore") { sql "SYNC" // 0. table_1 has in_atomic_restore property - def show_result = sql """ SHOW CREATE TABLE ${dbName}.${tableNamePrefix}_1 """ + def show_result = master_sql """ SHOW CREATE TABLE ${dbName}.${tableNamePrefix}_1 """ logger.info("SHOW CREATE TABLE ${tableNamePrefix}_1: ${show_result}") assertTrue(show_result[0][1].contains("in_atomic_restore")) @@ -230,7 +230,7 @@ suite("test_backup_restore_atomic_with_alter", "backup_restore") { sql "SYNC" // 5. The restore job is cancelled, the in_atomic_restore property has been removed. - show_result = sql """ SHOW CREATE TABLE ${dbName}.${tableNamePrefix}_1 """ + show_result = master_sql """ SHOW CREATE TABLE ${dbName}.${tableNamePrefix}_1 """ logger.info("SHOW CREATE TABLE ${tableNamePrefix}_1: ${show_result}") assertFalse(show_result[0][1].contains("in_atomic_restore"))