From 246484ec011a8dc607fdc8c151b7b117589830fb Mon Sep 17 00:00:00 2001 From: yangwucheng Date: Fri, 22 Mar 2024 17:45:17 +0800 Subject: [PATCH 1/3] feat(open-mysql-db): refactor 1. remove unnecessary instance var port 2. fix cause null bug 3. remove unnecessary throws 4. fix ctx.close() sequence bug 5. config sessionTimeout and requestTimeout 6. add docs of SqlEngine --- .../java/cn/paxos/mysql/MySqlListener.java | 35 +++++++++++-------- .../java/cn/paxos/mysql/engine/SqlEngine.java | 19 +++++++++- .../mysql/server/OpenmldbMysqlServer.java | 15 ++++---- .../openmldb/mysql/server/ServerConfig.java | 14 ++++---- .../src/main/resources/server.properties | 4 ++- 5 files changed, 59 insertions(+), 28 deletions(-) diff --git a/extensions/open-mysql-db/src/main/java/cn/paxos/mysql/MySqlListener.java b/extensions/open-mysql-db/src/main/java/cn/paxos/mysql/MySqlListener.java index 700c1c38abd..24198033253 100644 --- a/extensions/open-mysql-db/src/main/java/cn/paxos/mysql/MySqlListener.java +++ b/extensions/open-mysql-db/src/main/java/cn/paxos/mysql/MySqlListener.java @@ -45,14 +45,12 @@ public class MySqlListener implements AutoCloseable { Pattern.compile("@@([\\w.]+)(?:\\sAS\\s)?(\\w+)?"); private static final Pattern USE_DB_PATTERN = Pattern.compile("(?i)use (.+)"); private final SqlEngine sqlEngine; - private final int port; private final Channel channel; private final io.netty.channel.EventLoopGroup parentGroup; private final EventLoopGroup childGroup; private final EventExecutorGroup eventExecutorGroup; public MySqlListener(int port, int executorGroupSize, SqlEngine sqlEngine) { - this.port = port; this.sqlEngine = sqlEngine; parentGroup = new NioEventLoopGroup(); @@ -87,7 +85,7 @@ public MySqlListener(int port, int executorGroupSize, SqlEngine sqlEngine) { .childHandler( new ChannelInitializer() { @Override - protected void initChannel(NioSocketChannel ch) throws Exception { + protected void initChannel(NioSocketChannel ch) { System.out.println("[mysql-protocol] Initializing child channel"); final ChannelPipeline pipeline = ch.pipeline(); pipeline.addLast(new MysqlServerPacketEncoder()); @@ -160,14 +158,21 @@ private void handleHandshakeResponse( Throwable cause = e.getCause(); int errorCode; byte[] sqlState; - String errMsg = - Utils.getLocalDateTimeNow() - + " " - + Objects.requireNonNullElse(cause.getMessage(), e.getMessage()); - if (cause instanceof IllegalAccessException) { - errorCode = 1045; - sqlState = "#28000".getBytes(StandardCharsets.US_ASCII); + String errMsg; + if (cause != null) { + errMsg = + Utils.getLocalDateTimeNow() + + " " + + Objects.requireNonNullElse(cause.getMessage(), e.getMessage()); + if (cause instanceof IllegalAccessException) { + errorCode = 1045; + sqlState = "#28000".getBytes(StandardCharsets.US_ASCII); + } else { + errorCode = 1105; + sqlState = "#HY000".getBytes(StandardCharsets.US_ASCII); + } } else { + errMsg = Utils.getLocalDateTimeNow() + " " + Objects.requireNonNullElse(e.getMessage(), ""); errorCode = 1105; sqlState = "#HY000".getBytes(StandardCharsets.US_ASCII); } @@ -632,7 +637,7 @@ public ServerHandler() { } @Override - public void channelActive(ChannelHandlerContext ctx) throws Exception { + public void channelActive(ChannelHandlerContext ctx) { // todo may java.lang.NullPointerException this.remoteAddr = ((InetSocketAddress) ctx.channel().remoteAddress()).getAddress().getHostAddress(); @@ -650,7 +655,7 @@ public void channelActive(ChannelHandlerContext ctx) throws Exception { } @Override - public void channelInactive(ChannelHandlerContext ctx) throws Exception { + public void channelInactive(ChannelHandlerContext ctx) { System.out.println("[mysql-protocol] Server channel inactive: " + new Date()); sqlEngine.close(getConnectionId(ctx)); } @@ -682,6 +687,8 @@ public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception } else if (command.equals(Command.COM_PING)) { ctx.writeAndFlush(OkResponse.builder().sequenceId(sequenceId + 1).build()); } else if (command.equals(Command.COM_FIELD_LIST)) { + // ToDo: + // https://dev.mysql.com/doc/dev/mysql-server/8.0.34/page_protocol_com_field_list.html ctx.writeAndFlush(new EofResponse(sequenceId + 1, 0)); } else if (command.equals(Command.COM_STATISTICS)) { String statString = @@ -696,10 +703,10 @@ public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception } @Override - public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { + public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { cause.printStackTrace(); - ctx.close(); sqlEngine.close(getConnectionId(ctx)); + ctx.close(); } } } diff --git a/extensions/open-mysql-db/src/main/java/cn/paxos/mysql/engine/SqlEngine.java b/extensions/open-mysql-db/src/main/java/cn/paxos/mysql/engine/SqlEngine.java index e1c48f6b8c6..a971c4add4a 100644 --- a/extensions/open-mysql-db/src/main/java/cn/paxos/mysql/engine/SqlEngine.java +++ b/extensions/open-mysql-db/src/main/java/cn/paxos/mysql/engine/SqlEngine.java @@ -21,11 +21,22 @@ /** An interface to callback events received from the MySQL server. */ public interface SqlEngine { + /** + * Execute query use database + * + * @param connectionId Connection id + * @param database Database name + * @throws IOException Thrown with SQLTimeoutException as the inner cause if when the driver has + * determined that the timeout value that was specified by the setQueryTimeout method has been + * exceeded and has at least attempted to cancel the currently running Statement, or + * SQLException as the inner cause if a database access error occurs. + */ void useDatabase(int connectionId, String database) throws IOException; /** * Authenticating the user and password. * + * @param connectionId Connection id * @param database Database name * @param userName User name * @param scramble411 Encoded password @@ -40,6 +51,7 @@ void authenticate( /** * Querying the SQL. * + * @param connectionId Connection id * @param resultSetWriter Response writer * @param database Database name * @param userName User name @@ -59,5 +71,10 @@ void query( String sql) throws IOException; - void close(int connectionId) throws IOException; + /** + * Close resources of connection + * + * @param connectionId Connection id + */ + void close(int connectionId); } diff --git a/extensions/open-mysql-db/src/main/java/com/_4paradigm/openmldb/mysql/server/OpenmldbMysqlServer.java b/extensions/open-mysql-db/src/main/java/com/_4paradigm/openmldb/mysql/server/OpenmldbMysqlServer.java index 9128cfb7486..555b1006665 100644 --- a/extensions/open-mysql-db/src/main/java/com/_4paradigm/openmldb/mysql/server/OpenmldbMysqlServer.java +++ b/extensions/open-mysql-db/src/main/java/com/_4paradigm/openmldb/mysql/server/OpenmldbMysqlServer.java @@ -82,7 +82,8 @@ public class OpenmldbMysqlServer { // "(?i)(?s)(?m)CREATE TABLE `(.+)` \\([\\s\\r\\n]+(?:`(.+)` (.+),[\\s\\r\\n]+)+.*\\) // OPTIONS .*"); - public OpenmldbMysqlServer(int port, String zkCluster, String zkRootPath) { + public OpenmldbMysqlServer( + int port, String zkCluster, String zkRootPath, long sessionTimeout, long requestTimeout) { new MySqlListener( port, 100, @@ -108,7 +109,6 @@ public void authenticate( byte[] scramble411, byte[] authSeed) throws IOException { - // mocked username String validUser = ServerConfig.getOpenmldbUser(); if (!userName.equals(validUser)) { @@ -135,9 +135,8 @@ public void authenticate( SdkOption option = new SdkOption(); option.setZkCluster(zkCluster); option.setZkPath(zkRootPath); - // TODO: Make these configurable - option.setSessionTimeout(10000); - option.setRequestTimeout(60000); + option.setSessionTimeout(sessionTimeout); + option.setRequestTimeout(requestTimeout); option.setUser(userName); option.setPassword(validPassword); SqlClusterExecutor sqlExecutor = new SqlClusterExecutor(option); @@ -602,9 +601,13 @@ public static void main(String[] args) { int serverPort = ServerConfig.getPort(); String zkCluster = ServerConfig.getZkCluster(); String zkRootPath = ServerConfig.getZkRootPath(); + long sessionTimeout = ServerConfig.getSessionTimeout(); + long requestTimeout = ServerConfig.getRequestTimeout(); try { - OpenmldbMysqlServer server = new OpenmldbMysqlServer(serverPort, zkCluster, zkRootPath); + OpenmldbMysqlServer server = + new OpenmldbMysqlServer( + serverPort, zkCluster, zkRootPath, sessionTimeout, requestTimeout); server.start(); // Conenct with mysql client, mysql -h127.0.0.1 -P3307 } catch (Exception e) { diff --git a/extensions/open-mysql-db/src/main/java/com/_4paradigm/openmldb/mysql/server/ServerConfig.java b/extensions/open-mysql-db/src/main/java/com/_4paradigm/openmldb/mysql/server/ServerConfig.java index 9127e963ad3..d343bf996d4 100644 --- a/extensions/open-mysql-db/src/main/java/com/_4paradigm/openmldb/mysql/server/ServerConfig.java +++ b/extensions/open-mysql-db/src/main/java/com/_4paradigm/openmldb/mysql/server/ServerConfig.java @@ -25,12 +25,6 @@ public class ServerConfig { e1.printStackTrace(); } } - - // try (FileInputStream input = new FileInputStream(CONFIG_FILE_PATH)) { - // properties.load(input); - // } catch (IOException e) { - // e.printStackTrace(); - // } } public static int getPort() { @@ -52,4 +46,12 @@ public static String getOpenmldbUser() { public static String getOpenmldbPassword() { return properties.getProperty("openmldb.password", "root"); } + + public static long getSessionTimeout() { + return Long.parseLong(properties.getProperty("openmldb.sessionTimeout", "10000")); + } + + public static long getRequestTimeout() { + return Long.parseLong(properties.getProperty("openmldb.requestTimeout", "60000")); + } } diff --git a/extensions/open-mysql-db/src/main/resources/server.properties b/extensions/open-mysql-db/src/main/resources/server.properties index 0c7b271bd12..c551649022c 100644 --- a/extensions/open-mysql-db/src/main/resources/server.properties +++ b/extensions/open-mysql-db/src/main/resources/server.properties @@ -6,4 +6,6 @@ server.port=3307 zookeeper.cluster=0.0.0.0:2181 zookeeper.root_path=/openmldb openmldb.user=root -openmldb.password=root +openmldb.password=4pdadmin +openmldb.sessionTimeout=10000 +openmldb.requestTimeout=60000 From 6f19a44c02f05fbf6e994c93ba3c185173929256 Mon Sep 17 00:00:00 2001 From: yangwucheng Date: Mon, 25 Mar 2024 14:55:27 +0800 Subject: [PATCH 2/3] feat(open-mysql-db): refactor --- .../java/cn/paxos/mysql/MySqlListener.java | 87 +- .../openmldb/mysql/mock/MockResult.java | 256 +++--- .../mysql/server/OpenmldbMysqlServer.java | 849 ++++++++++-------- 3 files changed, 611 insertions(+), 581 deletions(-) diff --git a/extensions/open-mysql-db/src/main/java/cn/paxos/mysql/MySqlListener.java b/extensions/open-mysql-db/src/main/java/cn/paxos/mysql/MySqlListener.java index 24198033253..a775a3ac78f 100644 --- a/extensions/open-mysql-db/src/main/java/cn/paxos/mysql/MySqlListener.java +++ b/extensions/open-mysql-db/src/main/java/cn/paxos/mysql/MySqlListener.java @@ -41,6 +41,11 @@ public class MySqlListener implements AutoCloseable { public static final String VERSION = "8.0.29"; public static final String VERSION_COMMENT = ""; + public static final String CHARACTER_SET_UTF8MB4 = "utf8mb4"; + public static final String COLLATION_UTF8MB4_0900_AI_CI = "utf8mb4_0900_ai_ci"; + public static final String SETTINGS_LOWER_CASE_TABLE_NAMES = "2"; + public static final String SETTINGS_INTERACTIVE_TIMEOUT = "28800"; + public static final String SETTINGS_WAIT_TIMEOUT = "28800"; private static final Pattern SETTINGS_PATTERN = Pattern.compile("@@([\\w.]+)(?:\\sAS\\s)?(\\w+)?"); private static final Pattern USE_DB_PATTERN = Pattern.compile("(?i)use (.+)"); @@ -202,17 +207,14 @@ private void handleQuery( + userName + ", scramble411: " + scramble411.length); - Matcher useDbMatcher = - USE_DB_PATTERN.matcher(queryString.replaceAll("/\\*.*\\*/", "").toLowerCase().trim()); + String queryStringWithoutComment = + queryString.replaceAll("/\\*.*\\*/", "").toLowerCase().trim(); + Matcher useDbMatcher = USE_DB_PATTERN.matcher(queryStringWithoutComment); if (isServerSettingsQuery(queryString)) { sendSettingsResponse(ctx, query, remoteAddr); - } else if (queryString.replaceAll("/\\*.*\\*/", "").toLowerCase().trim().startsWith("set ") - && !queryString - .replaceAll("/\\*.*\\*/", "") - .toLowerCase() - .trim() - .startsWith("set @@execute_mode=")) { + } else if (queryStringWithoutComment.startsWith("set ") + && !queryStringWithoutComment.startsWith("set @@execute_mode=")) { // ignore SET command ctx.writeAndFlush(OkResponse.builder().sequenceId(query.getSequenceId() + 1).build()); } else if (useDbMatcher.matches()) { @@ -223,12 +225,9 @@ private void handleQuery( } else { // Generic response int[] sequenceId = new int[] {query.getSequenceId()}; - boolean[] columnsWritten = new boolean[1]; - ResultSetWriter resultSetWriter = new ResultSetWriter() { - @Override public void writeColumns(List columns) { ctx.write(new ColumnCount(++sequenceId[0], columns.size())); @@ -277,9 +276,7 @@ public void writeColumns(List columns) { .build()); } ctx.write(new EofResponse(++sequenceId[0], 0)); - System.out.println("[mysql-protocol] Columns done"); - columnsWritten[0] = !columns.isEmpty(); } @@ -295,7 +292,6 @@ public void writeRow(List row) { @Override public void finish() { ctx.writeAndFlush(new EofResponse(++sequenceId[0], 0)); - System.out.println("[mysql-protocol] All done"); } }; @@ -316,22 +312,29 @@ public void finish() { Throwable cause = e.getCause(); int errorCode; byte[] sqlState; - String errMsg = - Utils.getLocalDateTimeNow() - + " " - + Objects.requireNonNullElse(cause.getMessage(), e.getMessage()); - if (cause instanceof IllegalAccessException) { - errorCode = 1045; - sqlState = "#28000".getBytes(StandardCharsets.US_ASCII); - } else if (cause instanceof IllegalArgumentException) { - errorCode = 1064; - sqlState = "#42000".getBytes(StandardCharsets.US_ASCII); - } else if (e.getMessage() - .equalsIgnoreCase( - "java.sql.SQLException: executeSQL fail: [2000] please enter database first")) { - errorCode = 1046; - sqlState = "#3D000".getBytes(StandardCharsets.US_ASCII); + String errMsg; + if (cause != null) { + errMsg = + Utils.getLocalDateTimeNow() + + " " + + Objects.requireNonNullElse(cause.getMessage(), e.getMessage()); + if (cause instanceof IllegalAccessException) { + errorCode = 1045; + sqlState = "#28000".getBytes(StandardCharsets.US_ASCII); + } else if (cause instanceof IllegalArgumentException) { + errorCode = 1064; + sqlState = "#42000".getBytes(StandardCharsets.US_ASCII); + } else if (e.getMessage() + .equalsIgnoreCase( + "java.sql.SQLException: executeSQL fail: [2000] please enter database first")) { + errorCode = 1046; + sqlState = "#3D000".getBytes(StandardCharsets.US_ASCII); + } else { + errorCode = 1105; + sqlState = "#HY000".getBytes(StandardCharsets.US_ASCII); + } } else { + errMsg = Utils.getLocalDateTimeNow() + " " + e.getMessage(); errorCode = 1105; sqlState = "#HY000".getBytes(StandardCharsets.US_ASCII); } @@ -440,16 +443,18 @@ private void sendSettingsResponse( columnDefinitions.add( newColumnDefinition( ++sequenceId, fieldName, systemVariable, ColumnType.MYSQL_TYPE_VAR_STRING, 12)); - values.add("utf8mb4"); + values.add(CHARACTER_SET_UTF8MB4); break; case "collation_server": case "GLOBAL.collation_server": + case "collation_connection": columnDefinitions.add( newColumnDefinition( ++sequenceId, fieldName, systemVariable, ColumnType.MYSQL_TYPE_VAR_STRING, 63)); - values.add("utf8mb4_0900_ai_ci"); + values.add(COLLATION_UTF8MB4_0900_AI_CI); break; case "init_connect": + case "language": columnDefinitions.add( newColumnDefinition( ++sequenceId, fieldName, systemVariable, ColumnType.MYSQL_TYPE_VAR_STRING, 0)); @@ -459,13 +464,7 @@ private void sendSettingsResponse( columnDefinitions.add( newColumnDefinition( ++sequenceId, fieldName, systemVariable, ColumnType.MYSQL_TYPE_VAR_STRING, 21)); - values.add("28800"); - break; - case "language": - columnDefinitions.add( - newColumnDefinition( - ++sequenceId, fieldName, systemVariable, ColumnType.MYSQL_TYPE_VAR_STRING, 0)); - values.add(""); + values.add(SETTINGS_INTERACTIVE_TIMEOUT); break; case "license": columnDefinitions.add( @@ -477,7 +476,7 @@ private void sendSettingsResponse( columnDefinitions.add( newColumnDefinition( ++sequenceId, fieldName, systemVariable, ColumnType.MYSQL_TYPE_LONGLONG, 63)); - values.add("2"); + values.add(SETTINGS_LOWER_CASE_TABLE_NAMES); break; case "max_allowed_packet": case "global.max_allowed_packet": @@ -533,7 +532,7 @@ private void sendSettingsResponse( columnDefinitions.add( newColumnDefinition( ++sequenceId, fieldName, systemVariable, ColumnType.MYSQL_TYPE_LONGLONG, 12)); - values.add("28800"); + values.add(SETTINGS_WAIT_TIMEOUT); break; case "query_cache_type": columnDefinitions.add( @@ -547,12 +546,6 @@ private void sendSettingsResponse( ++sequenceId, fieldName, systemVariable, ColumnType.MYSQL_TYPE_VAR_STRING, 0)); values.add(VERSION_COMMENT); break; - case "collation_connection": - columnDefinitions.add( - newColumnDefinition( - ++sequenceId, fieldName, systemVariable, ColumnType.MYSQL_TYPE_VAR_STRING, 63)); - values.add("utf8mb4_0900_ai_ci"); - break; case "query_cache_size": columnDefinitions.add( newColumnDefinition( @@ -583,14 +576,12 @@ private void sendSettingsResponse( newColumnDefinition( ++sequenceId, fieldName, systemVariable, ColumnType.MYSQL_TYPE_VAR_STRING, 63)); values.add("REPEATABLE-READ"); - // values.add("READ-UNCOMMITTED"); break; case "session.transaction_read_only": columnDefinitions.add( newColumnDefinition( ++sequenceId, fieldName, systemVariable, ColumnType.MYSQL_TYPE_TINY, 1)); values.add("0"); - // values.add("READ-UNCOMMITTED"); break; default: System.err.println("[mysql-protocol] Unknown system variable: " + systemVariable); diff --git a/extensions/open-mysql-db/src/main/java/com/_4paradigm/openmldb/mysql/mock/MockResult.java b/extensions/open-mysql-db/src/main/java/com/_4paradigm/openmldb/mysql/mock/MockResult.java index f62b4f62d89..ab51b6694e6 100644 --- a/extensions/open-mysql-db/src/main/java/com/_4paradigm/openmldb/mysql/mock/MockResult.java +++ b/extensions/open-mysql-db/src/main/java/com/_4paradigm/openmldb/mysql/mock/MockResult.java @@ -9,13 +9,15 @@ import java.util.Map; public class MockResult { + public static final String DEFAULT_STORAGE_ENGINE = "InnoDB"; + public static final String VARIABLE_VALUE_SQL_MODE = + "ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION"; + public static final String VARIABLE_VALUE_SSL_CIPHER = "TLS_AES_256_GCM_SHA384"; public static Map, List>>> mockResults = new HashMap<>(); public static Map, List>>> mockPatternResults = new HashMap<>(); - public static Map mockVariables = new HashMap<>(); - public static Map mockSessionStatusVariables = new HashMap<>(); public static Map mockSessionVariablesVariables = new HashMap<>(); @@ -25,12 +27,13 @@ public class MockResult { List> rows; List row; - mockVariables.put("character_set_database", "utf8mb4"); - mockVariables.put("collation_database", "utf8mb4_0900_ai_ci"); - mockVariables.put("default_storage_engine", "InnoDB"); + mockVariables.put("character_set_database", MySqlListener.CHARACTER_SET_UTF8MB4); + mockVariables.put("collation_database", MySqlListener.COLLATION_UTF8MB4_0900_AI_CI); + mockVariables.put("default_storage_engine", DEFAULT_STORAGE_ENGINE); mockVariables.put("skip_show_database", "OFF"); mockVariables.put("version", MySqlListener.VERSION); mockVariables.put("version_comment", MySqlListener.VERSION_COMMENT); + mockVariables.put("lower_case_table_names", MySqlListener.SETTINGS_LOWER_CASE_TABLE_NAMES); for (String variable : MockResult.mockVariables.keySet()) { query = "show variables like '" + variable.toLowerCase() + "'"; columns = new ArrayList<>(); @@ -44,64 +47,58 @@ public class MockResult { mockResults.put(query, new Pair<>(columns, rows)); } + List characterSetUtf8mb4Columns = new ArrayList<>(); + characterSetUtf8mb4Columns.add(new QueryResultColumn("Charset", "VARCHAR(255)")); + characterSetUtf8mb4Columns.add(new QueryResultColumn("Description", "VARCHAR(255)")); + characterSetUtf8mb4Columns.add(new QueryResultColumn("Default collation", "VARCHAR(255)")); + characterSetUtf8mb4Columns.add(new QueryResultColumn("Maxlen", "VARCHAR(255)")); + + List> characterSetUtf8mb4Rows = new ArrayList<>(); + List characterSetUtf8mb4Row = new ArrayList<>(); + characterSetUtf8mb4Row.add(MySqlListener.CHARACTER_SET_UTF8MB4); + characterSetUtf8mb4Row.add("UTF-8 Unicode"); + characterSetUtf8mb4Row.add(MySqlListener.COLLATION_UTF8MB4_0900_AI_CI); + characterSetUtf8mb4Row.add("4"); + characterSetUtf8mb4Rows.add(characterSetUtf8mb4Row); + query = "show character set"; - columns = new ArrayList<>(); - columns.add(new QueryResultColumn("Charset", "VARCHAR(255)")); - columns.add(new QueryResultColumn("Description", "VARCHAR(255)")); - columns.add(new QueryResultColumn("Default collation", "VARCHAR(255)")); - columns.add(new QueryResultColumn("Maxlen", "VARCHAR(255)")); - rows = new ArrayList<>(); - row = new ArrayList<>(); - row.add("utf8mb4"); - row.add("UTF-8 Unicode"); - row.add("utf8mb4_0900_ai_ci"); - row.add("4"); - rows.add(row); - mockResults.put(query, new Pair<>(columns, rows)); + mockResults.put(query, new Pair<>(characterSetUtf8mb4Columns, characterSetUtf8mb4Rows)); query = "show charset"; - columns = new ArrayList<>(); - columns.add(new QueryResultColumn("Charset", "VARCHAR(255)")); - columns.add(new QueryResultColumn("Description", "VARCHAR(255)")); - columns.add(new QueryResultColumn("Default collation", "VARCHAR(255)")); - columns.add(new QueryResultColumn("Maxlen", "VARCHAR(255)")); - rows = new ArrayList<>(); - row = new ArrayList<>(); - row.add("utf8mb4"); - row.add("UTF-8 Unicode"); - row.add("utf8mb4_0900_ai_ci"); - row.add("4"); - rows.add(row); - mockResults.put(query, new Pair<>(columns, rows)); - - query = "show variables like 'lower_case_table_names'"; - // Variable_name Value - // lower_case_table_names 2 - columns = new ArrayList<>(); - columns.add(new QueryResultColumn("Variable_name", "VARCHAR(255)")); - columns.add(new QueryResultColumn("Value", "VARCHAR(255)")); - rows = new ArrayList<>(); - row = new ArrayList<>(); - row.add("lower_case_table_names"); - row.add("2"); - rows.add(row); - mockResults.put(query, new Pair<>(columns, rows)); + mockResults.put(query, new Pair<>(characterSetUtf8mb4Columns, characterSetUtf8mb4Rows)); query = "show character set where charset = 'utf8mb4'"; + mockResults.put(query, new Pair<>(characterSetUtf8mb4Columns, characterSetUtf8mb4Rows)); + + query = "select * from `information_schema`.`character_sets` order by `character_set_name` asc"; columns = new ArrayList<>(); - columns.add(new QueryResultColumn("Charset", "VARCHAR(255)")); - columns.add(new QueryResultColumn("Description", "VARCHAR(255)")); - columns.add(new QueryResultColumn("Default collation", "VARCHAR(255)")); - columns.add(new QueryResultColumn("Maxlen", "VARCHAR(255)")); + columns.add(new QueryResultColumn("CHARACTER_SET_NAME", "VARCHAR(255)")); + columns.add(new QueryResultColumn("DEFAULT_COLLATE_NAME", "VARCHAR(255)")); + columns.add(new QueryResultColumn("DESCRIPTION", "VARCHAR(255)")); + columns.add(new QueryResultColumn("MAXLEN", "VARCHAR(255)")); rows = new ArrayList<>(); + // # CHARACTER_SET_NAME, DEFAULT_COLLATE_NAME, DESCRIPTION, MAXLEN + // latin1, latin1_swedish_ci, cp1252 West European, 1 row = new ArrayList<>(); - row.add("utf8mb4"); - row.add("UTF-8 Unicode"); - row.add("utf8mb4_0900_ai_ci"); - row.add("4"); + row.add("latin1"); + row.add("latin1_swedish_ci"); + row.add("cp1252 West European"); + row.add("1"); rows.add(row); + // # CHARACTER_SET_NAME, DEFAULT_COLLATE_NAME, DESCRIPTION, MAXLEN + // utf8mb4, utf8mb4_0900_ai_ci, UTF-8 Unicode, 4 + rows.add(characterSetUtf8mb4Row); mockResults.put(query, new Pair<>(columns, rows)); + List collationUtf8mb4Row = new ArrayList<>(); + row.add(MySqlListener.COLLATION_UTF8MB4_0900_AI_CI); + row.add(MySqlListener.CHARACTER_SET_UTF8MB4); + row.add("255"); + row.add("Yes"); + row.add("Yes"); + row.add("0"); + row.add("NO PAD"); + query = "show collation"; // Collation Charset Id Default Compiled Sortlen Pad_attribute // utf8mb4_0900_ai_ci utf8mb4 255 Yes Yes 0 NO PAD @@ -114,17 +111,50 @@ public class MockResult { columns.add(new QueryResultColumn("Sortlen", "VARCHAR(255)")); columns.add(new QueryResultColumn("Pad_attribute", "VARCHAR(255)")); rows = new ArrayList<>(); + rows.add(collationUtf8mb4Row); + mockResults.put(query, new Pair<>(columns, rows)); + + query = + "select * from `information_schema`.`collations` where character_set_name = 'latin1' order by `collation_name` asc"; + columns = new ArrayList<>(); + columns.add(new QueryResultColumn("COLLATION_NAME", "VARCHAR(255)")); + columns.add(new QueryResultColumn("CHARACTER_SET_NAME", "VARCHAR(255)")); + columns.add(new QueryResultColumn("ID", "VARCHAR(255)")); + columns.add(new QueryResultColumn("IS_DEFAULT", "VARCHAR(255)")); + columns.add(new QueryResultColumn("IS_COMPILED", "VARCHAR(255)")); + columns.add(new QueryResultColumn("SORTLEN", "VARCHAR(255)")); + columns.add(new QueryResultColumn("PAD_ATTRIBUTE", "VARCHAR(255)")); + rows = new ArrayList<>(); + // # COLLATION_NAME, CHARACTER_SET_NAME, ID, IS_DEFAULT, IS_COMPILED, SORTLEN, PAD_ATTRIBUTE + // latin1_swedish_ci, latin1, 8, Yes, Yes, 1, PAD SPACE row = new ArrayList<>(); - row.add("utf8mb4_0900_ai_ci"); - row.add("utf8mb4"); - row.add("255"); + row.add("latin1_swedish_ci"); + row.add("latin1"); + row.add("8"); row.add("Yes"); row.add("Yes"); - row.add("0"); - row.add("NO PAD"); + row.add("1"); + row.add("PAD SPACE"); rows.add(row); mockResults.put(query, new Pair<>(columns, rows)); + // COLLATION_NAME, CHARACTER_SET_NAME, ID, IS_DEFAULT, IS_COMPILED, SORTLEN, PAD_ATTRIBUTE + query = + "select * from `information_schema`.`collations` where character_set_name = 'utf8mb4' order by `collation_name` asc"; + // # COLLATION_NAME, CHARACTER_SET_NAME, ID, IS_DEFAULT, IS_COMPILED, SORTLEN, PAD_ATTRIBUTE + // utf8mb4_0900_ai_ci, utf8mb4, 255, Yes, Yes, 0, NO PAD + columns = new ArrayList<>(); + columns.add(new QueryResultColumn("COLLATION_NAME", "VARCHAR(255)")); + columns.add(new QueryResultColumn("CHARACTER_SET_NAME", "VARCHAR(255)")); + columns.add(new QueryResultColumn("ID", "VARCHAR(255)")); + columns.add(new QueryResultColumn("IS_DEFAULT", "VARCHAR(255)")); + columns.add(new QueryResultColumn("IS_COMPILED", "VARCHAR(255)")); + columns.add(new QueryResultColumn("SORTLEN", "VARCHAR(255)")); + columns.add(new QueryResultColumn("PAD_ATTRIBUTE", "VARCHAR(255)")); + rows = new ArrayList<>(); + rows.add(collationUtf8mb4Row); + mockResults.put(query, new Pair<>(columns, rows)); + query = "show engines"; // Engine Support Comment Transactions XA Savepoints // InnoDB DEFAULT Supports transactions, row-level locking, and foreign keys YES YES YES @@ -137,7 +167,7 @@ public class MockResult { columns.add(new QueryResultColumn("Savepoints", "VARCHAR(255)")); rows = new ArrayList<>(); row = new ArrayList<>(); - row.add("InnoDB"); + row.add(DEFAULT_STORAGE_ENGINE); row.add("DEFAULT"); row.add("Supports transactions, row-level locking, and foreign keys"); row.add("YES"); @@ -153,6 +183,14 @@ public class MockResult { rows = new ArrayList<>(); mockResults.put(query, new Pair<>(columns, rows)); + query = "show status"; + // Variable_name Value + columns = new ArrayList<>(); + columns.add(new QueryResultColumn("Variable_name", "VARCHAR(255)")); + columns.add(new QueryResultColumn("Value", "VARCHAR(255)")); + rows = new ArrayList<>(); + mockResults.put(query, new Pair<>(columns, rows)); + query = "show variables like 'lower_case_%'; show variables like 'sql_mode'; select count(*) as support_ndb from information_schema.engines where engine = 'ndbcluster'"; columns = new ArrayList<>(); @@ -165,10 +203,8 @@ public class MockResult { rows.add(row); mockResults.put(query, new Pair<>(columns, rows)); - mockSessionStatusVariables.put( - "sql_mode", - "ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION"); - mockSessionStatusVariables.put("Ssl_cipher", "TLS_AES_256_GCM_SHA384"); + mockSessionStatusVariables.put("sql_mode", VARIABLE_VALUE_SQL_MODE); + mockSessionStatusVariables.put("Ssl_cipher", VARIABLE_VALUE_SSL_CIPHER); mockSessionStatusVariables.put("version_comment", MySqlListener.VERSION_COMMENT); mockSessionStatusVariables.put("version", MySqlListener.VERSION); for (String sessionVariable : MockResult.mockSessionStatusVariables.keySet()) { @@ -184,18 +220,18 @@ public class MockResult { mockResults.put(query, new Pair<>(columns, rows)); } - mockSessionVariablesVariables.put( - "sql_mode", - "ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION"); + mockSessionVariablesVariables.put("sql_mode", VARIABLE_VALUE_SQL_MODE); mockSessionVariablesVariables.put("version_comment", MySqlListener.VERSION_COMMENT); mockSessionVariablesVariables.put("version", MySqlListener.VERSION); // Variable_name Value // version_compile_os macos12 mockSessionVariablesVariables.put("version_compile_os", ""); mockSessionVariablesVariables.put("offline_mode", "OFF"); - mockSessionVariablesVariables.put("wait_timeout", "28800"); - mockSessionVariablesVariables.put("interactive_timeout", "28800"); - mockSessionVariablesVariables.put("lower_case_table_names", "2"); + mockSessionVariablesVariables.put("wait_timeout", MySqlListener.SETTINGS_WAIT_TIMEOUT); + mockSessionVariablesVariables.put( + "interactive_timeout", MySqlListener.SETTINGS_INTERACTIVE_TIMEOUT); + mockSessionVariablesVariables.put( + "lower_case_table_names", MySqlListener.SETTINGS_LOWER_CASE_TABLE_NAMES); for (String sessionVariable : MockResult.mockSessionVariablesVariables.keySet()) { query = "show session variables like '" + sessionVariable.toLowerCase() + "'"; columns = new ArrayList<>(); @@ -230,14 +266,6 @@ public class MockResult { rows.add(row); mockResults.put(query, new Pair<>(columns, rows)); - query = "show status"; - // Variable_name Value - columns = new ArrayList<>(); - columns.add(new QueryResultColumn("Variable_name", "VARCHAR(255)")); - columns.add(new QueryResultColumn("Value", "VARCHAR(255)")); - rows = new ArrayList<>(); - mockResults.put(query, new Pair<>(columns, rows)); - query = "select query_id, sum(duration) as sum_duration from information_schema.profiling group by query_id"; // QUERY_ID SUM_DURATION @@ -312,7 +340,7 @@ public class MockResult { // row.add("YES"); // rows.add(row); row = new ArrayList<>(); - row.add("InnoDB"); + row.add(DEFAULT_STORAGE_ENGINE); row.add("DEFAULT"); rows.add(row); // row = new ArrayList<>(); @@ -325,80 +353,6 @@ public class MockResult { // rows.add(row); mockResults.put(query, new Pair<>(columns, rows)); - query = "select * from `information_schema`.`character_sets` order by `character_set_name` asc"; - columns = new ArrayList<>(); - columns.add(new QueryResultColumn("CHARACTER_SET_NAME", "VARCHAR(255)")); - columns.add(new QueryResultColumn("DEFAULT_COLLATE_NAME", "VARCHAR(255)")); - columns.add(new QueryResultColumn("DESCRIPTION", "VARCHAR(255)")); - columns.add(new QueryResultColumn("MAXLEN", "VARCHAR(255)")); - rows = new ArrayList<>(); - // # CHARACTER_SET_NAME, DEFAULT_COLLATE_NAME, DESCRIPTION, MAXLEN - // latin1, latin1_swedish_ci, cp1252 West European, 1 - row = new ArrayList<>(); - row.add("latin1"); - row.add("latin1_swedish_ci"); - row.add("cp1252 West European"); - row.add("1"); - rows.add(row); - // # CHARACTER_SET_NAME, DEFAULT_COLLATE_NAME, DESCRIPTION, MAXLEN - // utf8mb4, utf8mb4_0900_ai_ci, UTF-8 Unicode, 4 - row = new ArrayList<>(); - row.add("utf8mb4"); - row.add("utf8mb4_0900_ai_ci"); - row.add("UTF-8 Unicode"); - row.add("4"); - rows.add(row); - mockResults.put(query, new Pair<>(columns, rows)); - - query = - "select * from `information_schema`.`collations` where character_set_name = 'latin1' order by `collation_name` asc"; - columns = new ArrayList<>(); - columns.add(new QueryResultColumn("COLLATION_NAME", "VARCHAR(255)")); - columns.add(new QueryResultColumn("CHARACTER_SET_NAME", "VARCHAR(255)")); - columns.add(new QueryResultColumn("ID", "VARCHAR(255)")); - columns.add(new QueryResultColumn("IS_DEFAULT", "VARCHAR(255)")); - columns.add(new QueryResultColumn("IS_COMPILED", "VARCHAR(255)")); - columns.add(new QueryResultColumn("SORTLEN", "VARCHAR(255)")); - columns.add(new QueryResultColumn("PAD_ATTRIBUTE", "VARCHAR(255)")); - rows = new ArrayList<>(); - // # COLLATION_NAME, CHARACTER_SET_NAME, ID, IS_DEFAULT, IS_COMPILED, SORTLEN, PAD_ATTRIBUTE - // latin1_swedish_ci, latin1, 8, Yes, Yes, 1, PAD SPACE - row = new ArrayList<>(); - row.add("latin1_swedish_ci"); - row.add("latin1"); - row.add("8"); - row.add("Yes"); - row.add("Yes"); - row.add("1"); - row.add("PAD SPACE"); - rows.add(row); - mockResults.put(query, new Pair<>(columns, rows)); - - // COLLATION_NAME, CHARACTER_SET_NAME, ID, IS_DEFAULT, IS_COMPILED, SORTLEN, PAD_ATTRIBUTE - query = - "select * from `information_schema`.`collations` where character_set_name = 'utf8mb4' order by `collation_name` asc"; - // # COLLATION_NAME, CHARACTER_SET_NAME, ID, IS_DEFAULT, IS_COMPILED, SORTLEN, PAD_ATTRIBUTE - // utf8mb4_0900_ai_ci, utf8mb4, 255, Yes, Yes, 0, NO PAD - columns = new ArrayList<>(); - columns.add(new QueryResultColumn("COLLATION_NAME", "VARCHAR(255)")); - columns.add(new QueryResultColumn("CHARACTER_SET_NAME", "VARCHAR(255)")); - columns.add(new QueryResultColumn("ID", "VARCHAR(255)")); - columns.add(new QueryResultColumn("IS_DEFAULT", "VARCHAR(255)")); - columns.add(new QueryResultColumn("IS_COMPILED", "VARCHAR(255)")); - columns.add(new QueryResultColumn("SORTLEN", "VARCHAR(255)")); - columns.add(new QueryResultColumn("PAD_ATTRIBUTE", "VARCHAR(255)")); - rows = new ArrayList<>(); - row = new ArrayList<>(); - row.add("utf8mb4_0900_ai_ci"); - row.add("utf8mb4"); - row.add("255"); - row.add("Yes"); - row.add("Yes"); - row.add("0"); - row.add("NO PAD"); - rows.add(row); - mockResults.put(query, new Pair<>(columns, rows)); - query = "select word from information_schema.keywords where reserved=1 order by word"; columns = new ArrayList<>(); columns.add(new QueryResultColumn("WORD", "VARCHAR(255)")); diff --git a/extensions/open-mysql-db/src/main/java/com/_4paradigm/openmldb/mysql/server/OpenmldbMysqlServer.java b/extensions/open-mysql-db/src/main/java/com/_4paradigm/openmldb/mysql/server/OpenmldbMysqlServer.java index 555b1006665..0e9a0ce8ec3 100644 --- a/extensions/open-mysql-db/src/main/java/com/_4paradigm/openmldb/mysql/server/OpenmldbMysqlServer.java +++ b/extensions/open-mysql-db/src/main/java/com/_4paradigm/openmldb/mysql/server/OpenmldbMysqlServer.java @@ -18,6 +18,7 @@ import com.google.common.base.Strings; import java.io.IOException; import java.sql.SQLException; +import java.sql.Statement; import java.util.*; import java.util.concurrent.ConcurrentHashMap; import java.util.regex.Matcher; @@ -67,8 +68,7 @@ public class OpenmldbMysqlServer { private final Pattern createDatabasePattern = Pattern.compile("(?i)(CREATE DATABASE `.+`).*"); - private final Pattern selectLimitPattern = - Pattern.compile("(?i)(SELECT .+) limit (?:\\d)+,(?:\\d)+"); + private final Pattern selectLimitPattern = Pattern.compile("(?i)(SELECT .+) limit \\d+,\\s*\\d+"); // SELECT * FROM information_schema.SCHEMATA WHERE SCHEMA_NAME='demo_db' private final Pattern selectSchemaTaPattern = @@ -77,11 +77,6 @@ public class OpenmldbMysqlServer { // SHOW FULL TABLES FROM demo_db private final Pattern showTablesFromDbPattern = Pattern.compile("(?i)SHOW FULL TABLES FROM (.+)"); - // private final Pattern crateTableResultPattern = - // Pattern.compile( - // "(?i)(?s)(?m)CREATE TABLE `(.+)` \\([\\s\\r\\n]+(?:`(.+)` (.+),[\\s\\r\\n]+)+.*\\) - // OPTIONS .*"); - public OpenmldbMysqlServer( int port, String zkCluster, String zkRootPath, long sessionTimeout, long requestTimeout) { new MySqlListener( @@ -183,411 +178,501 @@ public void query( this.authenticate(connectionId, database, userName, scramble411, authSeed); try { - if (MockResult.mockResults.containsKey(sql.toLowerCase())) { - Pair, List>> pair = - MockResult.mockResults.get(sql.toLowerCase()); - resultSetWriter.writeColumns(pair.getKey()); - for (List row : pair.getValue()) { - resultSetWriter.writeRow(row); + if (mockPlainQuery(resultSetWriter, sql)) { + return; + } + + // This mock must execute before mockPatternQuery + // SELECT COUNT(*) FROM information_schema.TABLES WHERE TABLE_SCHEMA = 'demo_db' + // UNION SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = + // 'demo_db' UNION SELECT COUNT(*) FROM information_schema.ROUTINES WHERE + // ROUTINE_SCHEMA = 'demo_db' + if (mockSelectCountUnion(connectionId, resultSetWriter, sql)) { + return; + } + + if (mockPatternQuery(resultSetWriter, sql)) { + return; + } + + // mock SELECT SCHEMA_NAME, DEFAULT_CHARACTER_SET_NAME, DEFAULT_COLLATION_NAME FROM + // information_schema.SCHEMATA + if (mockInformationSchemaSchemaTa(connectionId, resultSetWriter, sql)) { + return; + } + + // mock SELECT DATABASE() + if (mockSelectDatabase(connectionId, resultSetWriter, sql)) { + return; + } + + // mock SELECT TABLE_SCHEMA, TABLE_NAME, TABLE_TYPE FROM information_schema.TABLES + // WHERE TABLE_SCHEMA = 'demo_db' ORDER BY TABLE_SCHEMA, TABLE_TYPE + if (mockSelectTables(connectionId, resultSetWriter, sql)) { + return; + } + + // mock SELECT TABLE_SCHEMA, TABLE_NAME, COLUMN_NAME, COLUMN_TYPE FROM + // information_schema.COLUMNS WHERE TABLE_SCHEMA = 'demo_db' ORDER BY TABLE_SCHEMA, + // TABLE_NAME + if (mockSelectColumns(connectionId, resultSetWriter, sql)) { + return; + } + + // mock SELECT * FROM information_schema.COLUMNS WHERE TABLE_SCHEMA='xzs' AND + // TABLE_NAME='t_exam_paper' ORDER BY ORDINAL_POSITION + if (mockSelectColumns4Dbeaver(connectionId, resultSetWriter, sql)) { + return; + } + + // mock SELECT * FROM information_schema.SCHEMATA WHERE SCHEMA_NAME='demo_db' + if (mockSchemaTa(resultSetWriter, sql)) { + return; + } + + java.sql.Statement stmt = sqlClusterExecutorMap.get(connectionId).getStatement(); + + if (!Strings.isNullOrEmpty(database)) { + stmt.execute("use " + database); + } + + if (mockShowColumns(resultSetWriter, sql, stmt)) { + return; + } + + if (sql.startsWith("SHOW FULL TABLES")) { + // SHOW FULL TABLES WHERE Table_type != 'VIEW' + Matcher showTablesFromDbMatcher = showTablesFromDbPattern.matcher(sql); + if (showTablesFromDbMatcher.matches()) { + String dbName = showTablesFromDbMatcher.group(1); + stmt.execute("use " + dbName); + sql = "SHOW TABLES FROM " + dbName; + } else { + sql = "SHOW TABLES"; } - resultSetWriter.finish(); } else { - // SELECT COUNT(*) FROM information_schema.TABLES WHERE TABLE_SCHEMA = 'demo_db' - // UNION SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = - // 'demo_db' UNION SELECT COUNT(*) FROM information_schema.ROUTINES WHERE - // ROUTINE_SCHEMA = 'demo_db' - Matcher selectCountUnionMatcher = selectCountUnionPattern.matcher(sql); - if (selectCountUnionMatcher.matches()) { - // COUNT(*) - List columns = new ArrayList<>(); - columns.add(new QueryResultColumn("COUNT(*)", "VARCHAR(255)")); - resultSetWriter.writeColumns(columns); - List row; - for (int i = 1; i <= selectCountUnionMatcher.groupCount(); ++i) { - String unionSql = selectCountUnionMatcher.group(i); - - Matcher selectCountTablesMatcher = selectCountTablesPattern.matcher(unionSql); - Matcher selectCountColumnsMatcher = selectCountColumnsPattern.matcher(unionSql); - Matcher selectCountRoutinesMatcher = - selectCountRoutinesPattern.matcher(unionSql); - if (selectCountTablesMatcher.matches()) { - String dbName = selectCountTablesMatcher.group(1); - row = new ArrayList<>(); - row.add( - Integer.toString( - sqlClusterExecutorMap - .get(connectionId) - .getTableNames(dbName) - .size())); - resultSetWriter.writeRow(row); - } else if (selectCountColumnsMatcher.matches()) { - String dbName = selectCountTablesMatcher.group(1); - int columnCount = 0; - for (String tableName : - sqlClusterExecutorMap.get(connectionId).getTableNames(dbName)) { - columnCount += - sqlClusterExecutorMap - .get(connectionId) - .getTableSchema(dbName, tableName) - .getColumnList() - .size(); - } - row = new ArrayList<>(); - row.add(Integer.toString(columnCount)); - resultSetWriter.writeRow(row); - } else if (selectCountRoutinesMatcher.matches()) { - row = new ArrayList<>(); - row.add(Integer.toString(0)); - resultSetWriter.writeRow(row); - } - } - resultSetWriter.finish(); - return; + Matcher crateDatabaseMatcher = createDatabasePattern.matcher(sql); + Matcher selectLimitMatcher = selectLimitPattern.matcher(sql); + if (crateDatabaseMatcher.matches()) { + sql = crateDatabaseMatcher.group(1); + } else if (selectLimitMatcher.matches()) { + sql = selectLimitMatcher.group(1); } + } + sql = sql.replaceAll("(?i)\\s*limit\\s*\\d+\\s*,\\s*\\d+", ""); + stmt.execute(sql); - for (String patternStr : MockResult.mockPatternResults.keySet()) { - Pattern pattern = Pattern.compile(patternStr); - if (pattern.matcher(sql).matches()) { - Pair, List>> pair = - MockResult.mockPatternResults.get(patternStr); - resultSetWriter.writeColumns(pair.getKey()); - for (List row : pair.getValue()) { - resultSetWriter.writeRow(row); - } - resultSetWriter.finish(); - return; - } - } + if (sql.toLowerCase().startsWith("select") || sql.toLowerCase().startsWith("show")) { + SQLResultSet resultSet = (SQLResultSet) stmt.getResultSet(); + outputResultSet(resultSetWriter, resultSet, sql); + } - // mock SELECT SCHEMA_NAME, DEFAULT_CHARACTER_SET_NAME, DEFAULT_COLLATION_NAME FROM - // information_schema.SCHEMATA - if (sql.equalsIgnoreCase( - "SELECT SCHEMA_NAME, DEFAULT_CHARACTER_SET_NAME, DEFAULT_COLLATION_NAME FROM information_schema.SCHEMATA")) { - List dbs = sqlClusterExecutorMap.get(connectionId).showDatabases(); - // SCHEMA_NAME DEFAULT_CHARACTER_SET_NAME DEFAULT_COLLATION_NAME - // mysql utf8mb4 utf8mb4_0900_ai_ci - List columns = new ArrayList<>(); - columns.add(new QueryResultColumn("SCHEMA_NAME", "VARCHAR(255)")); - columns.add(new QueryResultColumn("DEFAULT_CHARACTER_SET_NAME", "VARCHAR(255)")); - columns.add(new QueryResultColumn("DEFAULT_COLLATION_NAME", "VARCHAR(255)")); - resultSetWriter.writeColumns(columns); - List row; - for (String db : dbs) { - row = new ArrayList<>(); - row.add(db); - row.add("utf8mb4"); - row.add("utf8mb4_0900_ai_ci"); - resultSetWriter.writeRow(row); - } - resultSetWriter.finish(); - return; - } + System.out.println("Success to execute OpenMLDB SQL: " + sql); - // mock SELECT DATABASE() - if (sql.equalsIgnoreCase("SELECT DATABASE()")) { - java.sql.Statement stmt = sqlClusterExecutorMap.get(connectionId).getStatement(); - stmt.execute("show table status"); - - // DATABASE() - // demo_db - List columns = new ArrayList<>(); - columns.add(new QueryResultColumn("DATABASE()", "VARCHAR(255)")); - resultSetWriter.writeColumns(columns); - SQLResultSet resultSet = (SQLResultSet) stmt.getResultSet(); - Schema schema = resultSet.GetInternalSchema(); - int columnCount = schema.getColumnList().size(); - int dbNameIndex = -1; - for (int i = 0; i < columnCount; i++) { - if (schema.getColumnName(i).equalsIgnoreCase("Database_name")) { - dbNameIndex = i; - break; - } - } + // Close resources + stmt.close(); + } catch (Exception e) { + e.printStackTrace(); + throw new IOException(e); + } + } - if (dbNameIndex != -1) { - while (resultSet.next()) { - // Build and respond rows - List row = new ArrayList<>(); - for (int i = 0; i < columnCount; i++) { - if (i == dbNameIndex) { - int type = schema.getColumnType(i); - String columnValue = - TypeUtil.getResultSetStringColumn(resultSet, i + 1, type); - row.add(columnValue); - break; - } - } - resultSetWriter.writeRow(row); - } - } + private boolean mockPlainQuery(ResultSetWriter resultSetWriter, String sql) { + if (MockResult.mockResults.containsKey(sql.toLowerCase())) { + Pair, List>> pair = + MockResult.mockResults.get(sql.toLowerCase()); + resultSetWriter.writeColumns(pair.getKey()); + for (List row : pair.getValue()) { + resultSetWriter.writeRow(row); + } + resultSetWriter.finish(); + return true; + } + return false; + } - resultSetWriter.finish(); - stmt.close(); - return; + private boolean mockShowColumns( + ResultSetWriter resultSetWriter, String sql, Statement stmt) throws SQLException { + Matcher showFullColumnsMatcher = showFullColumnsPattern.matcher(sql); + Matcher showColumnsMatcher = showColumnsPattern.matcher(sql); + boolean showFullColumnsMatch = showFullColumnsMatcher.matches(); + boolean showColumnsMatch = showColumnsMatcher.matches(); + if (showFullColumnsMatch || showColumnsMatch) { + String tableName; + String databaseName; + if (showFullColumnsMatch) { + tableName = showFullColumnsMatcher.group(1); + databaseName = showFullColumnsMatcher.group(2); + } else { + tableName = showColumnsMatcher.group(1); + databaseName = showColumnsMatcher.group(2); + } + String selectStarSql = "select * from `" + databaseName + "`.`" + tableName + "`"; + stmt.execute(selectStarSql); + + List columns = new ArrayList<>(); + // # Field, Type, Collation, Null, Key, Default, Extra, Privileges, Comment + // id, int, , NO, PRI, , auto_increment, select,insert,update,references, + columns.add(new QueryResultColumn("Field", "VARCHAR(255)")); + columns.add(new QueryResultColumn("Type", "VARCHAR(255)")); + if (showFullColumnsMatch) { + columns.add(new QueryResultColumn("Collation", "VARCHAR(255)")); + } + columns.add(new QueryResultColumn("Null", "VARCHAR(255)")); + columns.add(new QueryResultColumn("Key", "VARCHAR(255)")); + columns.add(new QueryResultColumn("Default", "VARCHAR(255)")); + columns.add(new QueryResultColumn("Extra", "VARCHAR(255)")); + if (showFullColumnsMatch) { + columns.add(new QueryResultColumn("Privileges", "VARCHAR(255)")); + columns.add(new QueryResultColumn("Comment", "VARCHAR(255)")); + } + resultSetWriter.writeColumns(columns); + + SQLResultSet resultSet = (SQLResultSet) stmt.getResultSet(); + Schema schema = resultSet.GetInternalSchema(); + // int columnCount = schema.GetColumnCnt(); + int columnCount = schema.getColumnList().size(); + // Add schema + for (int i = 0; i < columnCount; i++) { + List row = new ArrayList<>(); + row.add(schema.getColumnName(i)); + row.add(TypeUtil.openmldbTypeToMysqlTypeString(schema.getColumnType(i))); + if (showFullColumnsMatch) { + row.add(""); } - - // mock SELECT TABLE_SCHEMA, TABLE_NAME, TABLE_TYPE FROM information_schema.TABLES - // WHERE TABLE_SCHEMA = 'demo_db' ORDER BY TABLE_SCHEMA, TABLE_TYPE - Matcher selectTablesMatcher = selectTablesPattern.matcher(sql); - if (selectTablesMatcher.matches()) { - String dbName = selectTablesMatcher.group(1); - List tableNames = - sqlClusterExecutorMap.get(connectionId).getTableNames(dbName); - // TABLE_SCHEMA TABLE_NAME TABLE_TYPE - List columns = new ArrayList<>(); - columns.add(new QueryResultColumn("TABLE_SCHEMA", "VARCHAR(255)")); - columns.add(new QueryResultColumn("TABLE_NAME", "VARCHAR(255)")); - columns.add(new QueryResultColumn("TABLE_TYPE", "VARCHAR(255)")); - resultSetWriter.writeColumns(columns); - List row; - for (String tableName : tableNames) { - row = new ArrayList<>(); - row.add(dbName); - row.add(tableName); - row.add("BASE TABLE"); - resultSetWriter.writeRow(row); - } - resultSetWriter.finish(); - return; + row.add(""); + row.add(""); + row.add(""); + row.add(""); + if (showFullColumnsMatch) { + row.add(""); + row.add(""); } + resultSetWriter.writeRow(row); + } + resultSetWriter.finish(); + stmt.close(); + return true; + } + return false; + } - // mock SELECT TABLE_SCHEMA, TABLE_NAME, COLUMN_NAME, COLUMN_TYPE FROM - // information_schema.COLUMNS WHERE TABLE_SCHEMA = 'demo_db' ORDER BY TABLE_SCHEMA, - // TABLE_NAME - Matcher selectColumnsMatcher = selectColumnsPattern.matcher(sql); - if (selectColumnsMatcher.matches()) { - String dbName = selectColumnsMatcher.group(1); - List tableNames = - sqlClusterExecutorMap.get(connectionId).getTableNames(dbName); - // TABLE_SCHEMA TABLE_NAME COLUMN_NAME COLUMN_TYPE - List columns = new ArrayList<>(); - columns.add(new QueryResultColumn("TABLE_SCHEMA", "VARCHAR(255)")); - columns.add(new QueryResultColumn("TABLE_NAME", "VARCHAR(255)")); - columns.add(new QueryResultColumn("COLUMN_NAME", "VARCHAR(255)")); - columns.add(new QueryResultColumn("COLUMN_TYPE", "VARCHAR(255)")); - resultSetWriter.writeColumns(columns); - List row; - Collections.sort(tableNames); - for (String tableName : tableNames) { - Schema tableSchema = - sqlClusterExecutorMap.get(connectionId).getTableSchema(dbName, tableName); - for (Column column : tableSchema.getColumnList()) { - row = new ArrayList<>(); - row.add(dbName); - row.add(tableName); - row.add(column.getColumnName()); - row.add(TypeUtil.openmldbTypeToMysqlTypeString(column.getSqlType())); - resultSetWriter.writeRow(row); - } - } - resultSetWriter.finish(); - return; - } + private boolean mockSchemaTa(ResultSetWriter resultSetWriter, String sql) { + // mock SELECT * FROM information_schema.SCHEMATA WHERE SCHEMA_NAME='demo_db' + Matcher selectSchemaTaMatcher = selectSchemaTaPattern.matcher(sql); + if (selectSchemaTaMatcher.matches()) { + String dbName = selectSchemaTaMatcher.group(1); + // CATALOG_NAME SCHEMA_NAME DEFAULT_CHARACTER_SET_NAME DEFAULT_COLLATION_NAME + // SQL_PATH DEFAULT_ENCRYPTION + List columns = new ArrayList<>(); + columns.add(new QueryResultColumn("CATALOG_NAME", "VARCHAR(255)")); + columns.add(new QueryResultColumn("SCHEMA_NAME", "VARCHAR(255)")); + columns.add(new QueryResultColumn("DEFAULT_CHARACTER_SET_NAME", "VARCHAR(255)")); + columns.add(new QueryResultColumn("DEFAULT_COLLATION_NAME", "VARCHAR(255)")); + columns.add(new QueryResultColumn("SQL_PATH", "VARCHAR(255)")); + columns.add(new QueryResultColumn("DEFAULT_ENCRYPTION", "VARCHAR(255)")); + resultSetWriter.writeColumns(columns); + List row; + // def xzs utf8mb4 utf8mb4_0900_ai_ci NO + row = new ArrayList<>(); + row.add("def"); + row.add(dbName); + row.add("utf8mb4"); + row.add("utf8mb4_0900_ai_ci"); + row.add(null); + row.add("NO"); + resultSetWriter.writeRow(row); + resultSetWriter.finish(); + return true; + } + return false; + } - // mock SELECT * FROM information_schema.COLUMNS WHERE TABLE_SCHEMA='xzs' AND - // TABLE_NAME='t_exam_paper' ORDER BY ORDINAL_POSITION - Matcher selectColumns4DbeaverMatcher = selectColumns4DbeaverPattern.matcher(sql); - if (selectColumns4DbeaverMatcher.matches()) { - String dbName = selectColumns4DbeaverMatcher.group(1); - String tableName = selectColumns4DbeaverMatcher.group(2); - // TABLE_CATALOG TABLE_SCHEMA TABLE_NAME COLUMN_NAME ORDINAL_POSITION - // COLUMN_DEFAULT IS_NULLABLE DATA_TYPE CHARACTER_MAXIMUM_LENGTH - // CHARACTER_OCTET_LENGTH NUMERIC_PRECISION NUMERIC_SCALE DATETIME_PRECISION - // CHARACTER_SET_NAME COLLATION_NAME COLUMN_TYPE COLUMN_KEY EXTRA PRIVILEGES - // COLUMN_COMMENT GENERATION_EXPRESSION SRS_ID - // def xzs t_exam_paper id 1 NO int 10 0 int PRI auto_increment - // select,insert,update,references - List columns = new ArrayList<>(); - columns.add(new QueryResultColumn("TABLE_CATALOG", "VARCHAR(255)")); - columns.add(new QueryResultColumn("TABLE_SCHEMA", "VARCHAR(255)")); - columns.add(new QueryResultColumn("TABLE_NAME", "VARCHAR(255)")); - columns.add(new QueryResultColumn("COLUMN_NAME", "VARCHAR(255)")); - columns.add(new QueryResultColumn("ORDINAL_POSITION", "VARCHAR(255)")); - columns.add(new QueryResultColumn("COLUMN_DEFAULT", "VARCHAR(255)")); - columns.add(new QueryResultColumn("IS_NULLABLE", "VARCHAR(255)")); - columns.add(new QueryResultColumn("DATA_TYPE", "VARCHAR(255)")); - columns.add(new QueryResultColumn("CHARACTER_MAXIMUM_LENGTH", "VARCHAR(255)")); - columns.add(new QueryResultColumn("CHARACTER_OCTET_LENGTH", "VARCHAR(255)")); - columns.add(new QueryResultColumn("NUMERIC_PRECISION", "VARCHAR(255)")); - columns.add(new QueryResultColumn("NUMERIC_SCALE", "VARCHAR(255)")); - columns.add(new QueryResultColumn("DATETIME_PRECISION", "VARCHAR(255)")); - columns.add(new QueryResultColumn("CHARACTER_SET_NAME", "VARCHAR(255)")); - columns.add(new QueryResultColumn("COLLATION_NAME", "VARCHAR(255)")); - columns.add(new QueryResultColumn("COLUMN_TYPE", "VARCHAR(255)")); - columns.add(new QueryResultColumn("COLUMN_KEY", "VARCHAR(255)")); - columns.add(new QueryResultColumn("EXTRA", "VARCHAR(255)")); - columns.add(new QueryResultColumn("PRIVILEGES", "VARCHAR(255)")); - columns.add(new QueryResultColumn("COLUMN_COMMENT", "VARCHAR(255)")); - columns.add(new QueryResultColumn("GENERATION_EXPRESSION", "VARCHAR(255)")); - columns.add(new QueryResultColumn("SRS_ID", "VARCHAR(255)")); - resultSetWriter.writeColumns(columns); - List row; - Schema tableSchema = - sqlClusterExecutorMap.get(connectionId).getTableSchema(dbName, tableName); - int ordinalPosition = 1; - for (Column column : tableSchema.getColumnList()) { - row = new ArrayList<>(); - row.add("def"); - row.add(dbName); - row.add(tableName); - row.add(column.getColumnName()); - row.add(Integer.toString(ordinalPosition++)); - row.add(null); - row.add("NO"); - row.add(TypeUtil.openmldbTypeToMysqlTypeString(column.getSqlType())); - row.add(null); - row.add(null); - row.add(null); - row.add(null); - row.add(null); - row.add(null); - row.add(null); - row.add(TypeUtil.openmldbTypeToMysqlTypeString(column.getSqlType())); - row.add(null); - row.add(null); - row.add("select,insert,update,references"); - row.add(null); - row.add(null); - row.add(null); - resultSetWriter.writeRow(row); - } + private boolean mockSelectColumns4Dbeaver( + int connectionId, ResultSetWriter resultSetWriter, String sql) throws SQLException { + // mock SELECT * FROM information_schema.COLUMNS WHERE TABLE_SCHEMA='xzs' AND + // TABLE_NAME='t_exam_paper' ORDER BY ORDINAL_POSITION + Matcher selectColumns4DbeaverMatcher = selectColumns4DbeaverPattern.matcher(sql); + if (selectColumns4DbeaverMatcher.matches()) { + String dbName = selectColumns4DbeaverMatcher.group(1); + String tableName = selectColumns4DbeaverMatcher.group(2); + // TABLE_CATALOG TABLE_SCHEMA TABLE_NAME COLUMN_NAME ORDINAL_POSITION + // COLUMN_DEFAULT IS_NULLABLE DATA_TYPE CHARACTER_MAXIMUM_LENGTH + // CHARACTER_OCTET_LENGTH NUMERIC_PRECISION NUMERIC_SCALE DATETIME_PRECISION + // CHARACTER_SET_NAME COLLATION_NAME COLUMN_TYPE COLUMN_KEY EXTRA PRIVILEGES + // COLUMN_COMMENT GENERATION_EXPRESSION SRS_ID + // def xzs t_exam_paper id 1 NO int 10 0 int PRI auto_increment + // select,insert,update,references + List columns = new ArrayList<>(); + columns.add(new QueryResultColumn("TABLE_CATALOG", "VARCHAR(255)")); + columns.add(new QueryResultColumn("TABLE_SCHEMA", "VARCHAR(255)")); + columns.add(new QueryResultColumn("TABLE_NAME", "VARCHAR(255)")); + columns.add(new QueryResultColumn("COLUMN_NAME", "VARCHAR(255)")); + columns.add(new QueryResultColumn("ORDINAL_POSITION", "VARCHAR(255)")); + columns.add(new QueryResultColumn("COLUMN_DEFAULT", "VARCHAR(255)")); + columns.add(new QueryResultColumn("IS_NULLABLE", "VARCHAR(255)")); + columns.add(new QueryResultColumn("DATA_TYPE", "VARCHAR(255)")); + columns.add(new QueryResultColumn("CHARACTER_MAXIMUM_LENGTH", "VARCHAR(255)")); + columns.add(new QueryResultColumn("CHARACTER_OCTET_LENGTH", "VARCHAR(255)")); + columns.add(new QueryResultColumn("NUMERIC_PRECISION", "VARCHAR(255)")); + columns.add(new QueryResultColumn("NUMERIC_SCALE", "VARCHAR(255)")); + columns.add(new QueryResultColumn("DATETIME_PRECISION", "VARCHAR(255)")); + columns.add(new QueryResultColumn("CHARACTER_SET_NAME", "VARCHAR(255)")); + columns.add(new QueryResultColumn("COLLATION_NAME", "VARCHAR(255)")); + columns.add(new QueryResultColumn("COLUMN_TYPE", "VARCHAR(255)")); + columns.add(new QueryResultColumn("COLUMN_KEY", "VARCHAR(255)")); + columns.add(new QueryResultColumn("EXTRA", "VARCHAR(255)")); + columns.add(new QueryResultColumn("PRIVILEGES", "VARCHAR(255)")); + columns.add(new QueryResultColumn("COLUMN_COMMENT", "VARCHAR(255)")); + columns.add(new QueryResultColumn("GENERATION_EXPRESSION", "VARCHAR(255)")); + columns.add(new QueryResultColumn("SRS_ID", "VARCHAR(255)")); + resultSetWriter.writeColumns(columns); + List row; + Schema tableSchema = + sqlClusterExecutorMap.get(connectionId).getTableSchema(dbName, tableName); + int ordinalPosition = 1; + for (Column column : tableSchema.getColumnList()) { + row = new ArrayList<>(); + row.add("def"); + row.add(dbName); + row.add(tableName); + row.add(column.getColumnName()); + row.add(Integer.toString(ordinalPosition++)); + row.add(null); + row.add("NO"); + row.add(TypeUtil.openmldbTypeToMysqlTypeString(column.getSqlType())); + row.add(null); + row.add(null); + row.add(null); + row.add(null); + row.add(null); + row.add(null); + row.add(null); + row.add(TypeUtil.openmldbTypeToMysqlTypeString(column.getSqlType())); + row.add(null); + row.add(null); + row.add("select,insert,update,references"); + row.add(null); + row.add(null); + row.add(null); + resultSetWriter.writeRow(row); + } - resultSetWriter.finish(); - return; - } + resultSetWriter.finish(); + return true; + } + return false; + } - // mock SELECT * FROM information_schema.SCHEMATA WHERE SCHEMA_NAME='demo_db' - Matcher selectSchemaTaMatcher = selectSchemaTaPattern.matcher(sql); - if (selectSchemaTaMatcher.matches()) { - String dbName = selectSchemaTaMatcher.group(1); - // CATALOG_NAME SCHEMA_NAME DEFAULT_CHARACTER_SET_NAME DEFAULT_COLLATION_NAME - // SQL_PATH DEFAULT_ENCRYPTION - List columns = new ArrayList<>(); - columns.add(new QueryResultColumn("CATALOG_NAME", "VARCHAR(255)")); - columns.add(new QueryResultColumn("SCHEMA_NAME", "VARCHAR(255)")); - columns.add(new QueryResultColumn("DEFAULT_CHARACTER_SET_NAME", "VARCHAR(255)")); - columns.add(new QueryResultColumn("DEFAULT_COLLATION_NAME", "VARCHAR(255)")); - columns.add(new QueryResultColumn("SQL_PATH", "VARCHAR(255)")); - columns.add(new QueryResultColumn("DEFAULT_ENCRYPTION", "VARCHAR(255)")); - resultSetWriter.writeColumns(columns); - List row; - // def xzs utf8mb4 utf8mb4_0900_ai_ci NO + private boolean mockSelectColumns( + int connectionId, ResultSetWriter resultSetWriter, String sql) throws SQLException { + // mock SELECT TABLE_SCHEMA, TABLE_NAME, COLUMN_NAME, COLUMN_TYPE FROM + // information_schema.COLUMNS WHERE TABLE_SCHEMA = 'demo_db' ORDER BY TABLE_SCHEMA, + // TABLE_NAME + Matcher selectColumnsMatcher = selectColumnsPattern.matcher(sql); + if (selectColumnsMatcher.matches()) { + String dbName = selectColumnsMatcher.group(1); + List tableNames = + sqlClusterExecutorMap.get(connectionId).getTableNames(dbName); + // TABLE_SCHEMA TABLE_NAME COLUMN_NAME COLUMN_TYPE + List columns = new ArrayList<>(); + columns.add(new QueryResultColumn("TABLE_SCHEMA", "VARCHAR(255)")); + columns.add(new QueryResultColumn("TABLE_NAME", "VARCHAR(255)")); + columns.add(new QueryResultColumn("COLUMN_NAME", "VARCHAR(255)")); + columns.add(new QueryResultColumn("COLUMN_TYPE", "VARCHAR(255)")); + resultSetWriter.writeColumns(columns); + List row; + Collections.sort(tableNames); + for (String tableName : tableNames) { + Schema tableSchema = + sqlClusterExecutorMap.get(connectionId).getTableSchema(dbName, tableName); + for (Column column : tableSchema.getColumnList()) { row = new ArrayList<>(); - row.add("def"); row.add(dbName); - row.add("utf8mb4"); - row.add("utf8mb4_0900_ai_ci"); - row.add(null); - row.add("NO"); + row.add(tableName); + row.add(column.getColumnName()); + row.add(TypeUtil.openmldbTypeToMysqlTypeString(column.getSqlType())); resultSetWriter.writeRow(row); - resultSetWriter.finish(); - return; } + } + resultSetWriter.finish(); + return true; + } + return false; + } - java.sql.Statement stmt = sqlClusterExecutorMap.get(connectionId).getStatement(); - - Matcher showFullColumnsMatcher = showFullColumnsPattern.matcher(sql); - Matcher showColumnsMatcher = showColumnsPattern.matcher(sql); - boolean showFullColumnsMatch = showFullColumnsMatcher.matches(); - boolean showColumnsMatch = showColumnsMatcher.matches(); - if (showFullColumnsMatch || showColumnsMatch) { - String tableName; - String databaseName; - if (showFullColumnsMatch) { - tableName = showFullColumnsMatcher.group(1); - databaseName = showFullColumnsMatcher.group(2); - } else { - tableName = showColumnsMatcher.group(1); - databaseName = showColumnsMatcher.group(2); - } - String selectStarSql = "select * from `" + databaseName + "`.`" + tableName + "`"; - stmt.execute(selectStarSql); - - List columns = new ArrayList<>(); - // # Field, Type, Collation, Null, Key, Default, Extra, Privileges, Comment - // id, int, , NO, PRI, , auto_increment, select,insert,update,references, - columns.add(new QueryResultColumn("Field", "VARCHAR(255)")); - columns.add(new QueryResultColumn("Type", "VARCHAR(255)")); - if (showFullColumnsMatch) { - columns.add(new QueryResultColumn("Collation", "VARCHAR(255)")); - } - columns.add(new QueryResultColumn("Null", "VARCHAR(255)")); - columns.add(new QueryResultColumn("Key", "VARCHAR(255)")); - columns.add(new QueryResultColumn("Default", "VARCHAR(255)")); - columns.add(new QueryResultColumn("Extra", "VARCHAR(255)")); - if (showFullColumnsMatch) { - columns.add(new QueryResultColumn("Privileges", "VARCHAR(255)")); - columns.add(new QueryResultColumn("Comment", "VARCHAR(255)")); - } - resultSetWriter.writeColumns(columns); + private boolean mockSelectTables( + int connectionId, ResultSetWriter resultSetWriter, String sql) { + // mock SELECT TABLE_SCHEMA, TABLE_NAME, TABLE_TYPE FROM information_schema.TABLES + // WHERE TABLE_SCHEMA = 'demo_db' ORDER BY TABLE_SCHEMA, TABLE_TYPE + Matcher selectTablesMatcher = selectTablesPattern.matcher(sql); + if (selectTablesMatcher.matches()) { + String dbName = selectTablesMatcher.group(1); + List tableNames = + sqlClusterExecutorMap.get(connectionId).getTableNames(dbName); + // TABLE_SCHEMA TABLE_NAME TABLE_TYPE + List columns = new ArrayList<>(); + columns.add(new QueryResultColumn("TABLE_SCHEMA", "VARCHAR(255)")); + columns.add(new QueryResultColumn("TABLE_NAME", "VARCHAR(255)")); + columns.add(new QueryResultColumn("TABLE_TYPE", "VARCHAR(255)")); + resultSetWriter.writeColumns(columns); + List row; + for (String tableName : tableNames) { + row = new ArrayList<>(); + row.add(dbName); + row.add(tableName); + row.add("BASE TABLE"); + resultSetWriter.writeRow(row); + } + resultSetWriter.finish(); + return true; + } + return false; + } - SQLResultSet resultSet = (SQLResultSet) stmt.getResultSet(); - Schema schema = resultSet.GetInternalSchema(); - // int columnCount = schema.GetColumnCnt(); - int columnCount = schema.getColumnList().size(); - // Add schema + private boolean mockSelectDatabase( + int connectionId, ResultSetWriter resultSetWriter, String sql) throws SQLException { + // mock SELECT DATABASE() + if (sql.equalsIgnoreCase("SELECT DATABASE()")) { + java.sql.Statement stmt = sqlClusterExecutorMap.get(connectionId).getStatement(); + stmt.execute("show table status"); + + // DATABASE() + // demo_db + List columns = new ArrayList<>(); + columns.add(new QueryResultColumn("DATABASE()", "VARCHAR(255)")); + resultSetWriter.writeColumns(columns); + SQLResultSet resultSet = (SQLResultSet) stmt.getResultSet(); + Schema schema = resultSet.GetInternalSchema(); + int columnCount = schema.getColumnList().size(); + int dbNameIndex = -1; + for (int i = 0; i < columnCount; i++) { + if (schema.getColumnName(i).equalsIgnoreCase("Database_name")) { + dbNameIndex = i; + break; + } + } + + if (dbNameIndex != -1) { + while (resultSet.next()) { + // Build and respond rows + List row = new ArrayList<>(); for (int i = 0; i < columnCount; i++) { - List row = new ArrayList<>(); - row.add(schema.getColumnName(i)); - row.add(TypeUtil.openmldbTypeToMysqlTypeString(schema.getColumnType(i))); - if (showFullColumnsMatch) { - row.add(""); - } - row.add(""); - row.add(""); - row.add(""); - row.add(""); - if (showFullColumnsMatch) { - row.add(""); - row.add(""); + if (i == dbNameIndex) { + int type = schema.getColumnType(i); + String columnValue = + TypeUtil.getResultSetStringColumn(resultSet, i + 1, type); + row.add(columnValue); + break; } - resultSetWriter.writeRow(row); } - resultSetWriter.finish(); - stmt.close(); - return; + resultSetWriter.writeRow(row); } + } - if (!Strings.isNullOrEmpty(database)) { - stmt.execute("use " + database); - } - if (sql.startsWith("SHOW FULL TABLES")) { - // SHOW FULL TABLES WHERE Table_type != 'VIEW' - Matcher showTablesFromDbMatcher = showTablesFromDbPattern.matcher(sql); - if (showTablesFromDbMatcher.matches()) { - String dbName = showTablesFromDbMatcher.group(1); - stmt.execute("use " + dbName); - sql = "SHOW TABLES FROM " + dbName; - } else { - sql = "SHOW TABLES"; - } - } else { - Matcher crateDatabaseMatcher = createDatabasePattern.matcher(sql); - Matcher selectLimitMatcher = selectLimitPattern.matcher(sql); - if (crateDatabaseMatcher.matches()) { - sql = crateDatabaseMatcher.group(1); - } else if (selectLimitMatcher.matches()) { - sql = selectLimitMatcher.group(1); - } - } - sql = sql.replaceAll("(?i)\\s*limit\\s*\\d+\\s*,\\s*\\d+", ""); - stmt.execute(sql); + resultSetWriter.finish(); + stmt.close(); + return true; + } + return false; + } - if (sql.toLowerCase().startsWith("select") - || sql.toLowerCase().startsWith("show")) { - SQLResultSet resultSet = (SQLResultSet) stmt.getResultSet(); - outputResultSet(resultSetWriter, resultSet, sql); - } + private boolean mockInformationSchemaSchemaTa( + int connectionId, ResultSetWriter resultSetWriter, String sql) { + // mock SELECT SCHEMA_NAME, DEFAULT_CHARACTER_SET_NAME, DEFAULT_COLLATION_NAME FROM + // information_schema.SCHEMATA + if (sql.equalsIgnoreCase( + "SELECT SCHEMA_NAME, DEFAULT_CHARACTER_SET_NAME, DEFAULT_COLLATION_NAME FROM information_schema.SCHEMATA")) { + List dbs = sqlClusterExecutorMap.get(connectionId).showDatabases(); + // SCHEMA_NAME DEFAULT_CHARACTER_SET_NAME DEFAULT_COLLATION_NAME + // mysql utf8mb4 utf8mb4_0900_ai_ci + List columns = new ArrayList<>(); + columns.add(new QueryResultColumn("SCHEMA_NAME", "VARCHAR(255)")); + columns.add(new QueryResultColumn("DEFAULT_CHARACTER_SET_NAME", "VARCHAR(255)")); + columns.add(new QueryResultColumn("DEFAULT_COLLATION_NAME", "VARCHAR(255)")); + resultSetWriter.writeColumns(columns); + List row; + for (String db : dbs) { + row = new ArrayList<>(); + row.add(db); + row.add("utf8mb4"); + row.add("utf8mb4_0900_ai_ci"); + resultSetWriter.writeRow(row); + } + resultSetWriter.finish(); + return true; + } + return false; + } - System.out.println("Success to execute OpenMLDB SQL: " + sql); + private boolean mockPatternQuery(ResultSetWriter resultSetWriter, String sql) { + for (String patternStr : MockResult.mockPatternResults.keySet()) { + Pattern pattern = Pattern.compile(patternStr); + if (pattern.matcher(sql).matches()) { + Pair, List>> pair = + MockResult.mockPatternResults.get(patternStr); + resultSetWriter.writeColumns(pair.getKey()); + for (List row : pair.getValue()) { + resultSetWriter.writeRow(row); + } + resultSetWriter.finish(); + return true; + } + } + return false; + } - // Close resources - stmt.close(); + private boolean mockSelectCountUnion( + int connectionId, ResultSetWriter resultSetWriter, String sql) throws SQLException { + // SELECT COUNT(*) FROM information_schema.TABLES WHERE TABLE_SCHEMA = 'demo_db' + // UNION SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = + // 'demo_db' UNION SELECT COUNT(*) FROM information_schema.ROUTINES WHERE + // ROUTINE_SCHEMA = 'demo_db' + Matcher selectCountUnionMatcher = selectCountUnionPattern.matcher(sql); + if (selectCountUnionMatcher.matches()) { + // COUNT(*) + List columns = new ArrayList<>(); + columns.add(new QueryResultColumn("COUNT(*)", "VARCHAR(255)")); + resultSetWriter.writeColumns(columns); + List row; + for (int i = 1; i <= selectCountUnionMatcher.groupCount(); ++i) { + String unionSql = selectCountUnionMatcher.group(i); + + Matcher selectCountTablesMatcher = selectCountTablesPattern.matcher(unionSql); + Matcher selectCountColumnsMatcher = selectCountColumnsPattern.matcher(unionSql); + Matcher selectCountRoutinesMatcher = selectCountRoutinesPattern.matcher(unionSql); + if (selectCountTablesMatcher.matches()) { + String dbName = selectCountTablesMatcher.group(1); + row = new ArrayList<>(); + row.add( + Integer.toString( + sqlClusterExecutorMap.get(connectionId).getTableNames(dbName).size())); + resultSetWriter.writeRow(row); + } else if (selectCountColumnsMatcher.matches()) { + String dbName = selectCountTablesMatcher.group(1); + int columnCount = 0; + for (String tableName : + sqlClusterExecutorMap.get(connectionId).getTableNames(dbName)) { + columnCount += + sqlClusterExecutorMap + .get(connectionId) + .getTableSchema(dbName, tableName) + .getColumnList() + .size(); + } + row = new ArrayList<>(); + row.add(Integer.toString(columnCount)); + resultSetWriter.writeRow(row); + } else if (selectCountRoutinesMatcher.matches()) { + row = new ArrayList<>(); + row.add(Integer.toString(0)); + resultSetWriter.writeRow(row); + } } - } catch (Exception e) { - e.printStackTrace(); - throw new IOException(e); + resultSetWriter.finish(); + return true; } + return false; } @Override From 17b691f4baa877f770419b9fd023380aed5643f2 Mon Sep 17 00:00:00 2001 From: yangwucheng Date: Thu, 11 Apr 2024 17:43:50 +0800 Subject: [PATCH 3/3] feat(open-mysql-db): revert passsword --- extensions/open-mysql-db/src/main/resources/server.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extensions/open-mysql-db/src/main/resources/server.properties b/extensions/open-mysql-db/src/main/resources/server.properties index c551649022c..2e0699d5c7e 100644 --- a/extensions/open-mysql-db/src/main/resources/server.properties +++ b/extensions/open-mysql-db/src/main/resources/server.properties @@ -6,6 +6,6 @@ server.port=3307 zookeeper.cluster=0.0.0.0:2181 zookeeper.root_path=/openmldb openmldb.user=root -openmldb.password=4pdadmin +openmldb.password=root openmldb.sessionTimeout=10000 openmldb.requestTimeout=60000