diff --git a/src/main/java/ru/yandex/clickhouse/ClickHouseStatementImpl.java b/src/main/java/ru/yandex/clickhouse/ClickHouseStatementImpl.java index 3df0ea2cb..a728e7106 100644 --- a/src/main/java/ru/yandex/clickhouse/ClickHouseStatementImpl.java +++ b/src/main/java/ru/yandex/clickhouse/ClickHouseStatementImpl.java @@ -36,6 +36,8 @@ import java.sql.SQLException; import java.sql.SQLWarning; import java.util.*; +import java.util.regex.Matcher; +import java.util.regex.Pattern; public class ClickHouseStatementImpl implements ClickHouseStatement { @@ -491,7 +493,7 @@ static boolean isSelect(String sql) { return false; } - private String extractTableName(String sql) { + static String extractTableName(String sql) { String s = extractDBAndTableName(sql); if (s.contains(".")) { return s.substring(s.indexOf(".") + 1); @@ -500,34 +502,37 @@ private String extractTableName(String sql) { } } - private String extractDBName(String sql) { + static String extractDBNameInt(String sql) { String s = extractDBAndTableName(sql); if (s.contains(".")) { return s.substring(0, s.indexOf(".")); - } else { - return properties.getDatabase(); } + return ""; } - private String extractDBAndTableName(String sql) { - if (Utils.startsWithIgnoreCase(sql, "select")) { - String withoutStrings = Utils.retainUnquoted(sql, '\''); - int fromIndex = withoutStrings.indexOf("from"); - if (fromIndex == -1) { - fromIndex = withoutStrings.indexOf("FROM"); - } - if (fromIndex != -1) { - String fromFrom = withoutStrings.substring(fromIndex); - String fromTable = fromFrom.substring("from".length()).trim(); - return fromTable.split(" ")[0]; - } - } - if (Utils.startsWithIgnoreCase(sql, "desc")) { + private String extractDBName(String sql) { + String dbName = extractDBNameInt(sql); + return dbName.equals("") ? properties.getDatabase() : dbName; + } + + static String extractDBAndTableName(String sql) { + String withoutStrings = Utils.retainUnquoted(sql, '\''); + + if (withoutStrings.matches("^.*[dD][eE][sS][cC].+")) { return "system.columns"; } - if (Utils.startsWithIgnoreCase(sql, "show")) { + + if (withoutStrings.matches("^.*[sS][hH][oO][wW].+")) { return "system.tables"; } + + String pattern = "[sS][eE][lL][eE][cC][tT]\\s+.*[fF][rR][oO][Mm]\\s+([\\w.\"`]+)\\s*"; + Pattern r = Pattern.compile(pattern); + Matcher m = r.matcher(withoutStrings); + if (m.find()) { + return m.group(1).replace("\"","").replace("`",""); + } + return "system.unknown"; } diff --git a/src/test/java/ru/yandex/clickhouse/ClickHouseStatementTest.java b/src/test/java/ru/yandex/clickhouse/ClickHouseStatementTest.java index 36762fa19..4e7cd5ef0 100644 --- a/src/test/java/ru/yandex/clickhouse/ClickHouseStatementTest.java +++ b/src/test/java/ru/yandex/clickhouse/ClickHouseStatementTest.java @@ -158,4 +158,51 @@ public void testIsSelect() { assertTrue(ClickHouseStatementImpl.isSelect("/*test*/ EXPLAIN select 42")); } + @Test + public void testExtractDBAndTableName() { + assertEquals(ClickHouseStatementImpl.extractDBAndTableName("SELECT from table"), "table"); + assertEquals(ClickHouseStatementImpl.extractDBAndTableName("SELECT from table a"), "table"); + assertEquals(ClickHouseStatementImpl.extractDBAndTableName("SELECT from\ntable a"), "table"); + assertEquals(ClickHouseStatementImpl.extractDBAndTableName("SELECT\nfrom\ntable a"), "table"); + assertEquals(ClickHouseStatementImpl.extractDBAndTableName("SELECT\nFrom\ntable a"), "table"); + assertEquals(ClickHouseStatementImpl.extractDBAndTableName("SELECT from db.table a"), "db.table"); + assertEquals(ClickHouseStatementImpl.extractDBAndTableName(" SELECT from \"db.table\" a"), "db.table"); + assertEquals(ClickHouseStatementImpl.extractDBAndTableName("SELECT from `db.table` a"), "db.table"); + assertEquals(ClickHouseStatementImpl.extractDBAndTableName("from `db.table` a"), "system.unknown"); + assertEquals(ClickHouseStatementImpl.extractDBAndTableName(" from `db.table` a"), "system.unknown"); + assertEquals(ClickHouseStatementImpl.extractDBAndTableName("ELECT from `db.table` a"), "system.unknown"); + assertEquals(ClickHouseStatementImpl.extractDBAndTableName("SHOW create"), "system.tables"); + assertEquals(ClickHouseStatementImpl.extractDBAndTableName("desc table"), "system.columns"); + assertEquals(ClickHouseStatementImpl.extractDBAndTableName("DESC table"), "system.columns"); + assertEquals(ClickHouseStatementImpl.extractDBAndTableName("SELECT 'from db.table a' from tab"), "tab"); + assertEquals(ClickHouseStatementImpl.extractDBAndTableName("SELECT"), "system.unknown"); + assertEquals(ClickHouseStatementImpl.extractDBAndTableName("S"), "system.unknown"); + assertEquals(ClickHouseStatementImpl.extractDBAndTableName(""), "system.unknown"); + assertEquals(ClickHouseStatementImpl.extractDBAndTableName(" SELECT from table from"), "table"); + assertEquals(ClickHouseStatementImpl.extractDBAndTableName(" SELECT from table from"), "table"); + assertEquals(ClickHouseStatementImpl.extractDBAndTableName("SELECT fromUnixTimestamp64Milli(time) as x from table"), "table"); + assertEquals(ClickHouseStatementImpl.extractDBAndTableName(" SELECT fromUnixTimestamp64Milli(time)from table"), "table"); + assertEquals(ClickHouseStatementImpl.extractDBAndTableName("/*qq*/ SELECT fromUnixTimestamp64Milli(time)from table"), "table"); + assertEquals(ClickHouseStatementImpl.extractDBAndTableName(" SELECTfromUnixTimestamp64Milli(time)from table"), "system.unknown"); + assertEquals(ClickHouseStatementImpl.extractDBAndTableName(" SELECT fromUnixTimestamp64Milli(time)from .inner.a"), ".inner.a"); + assertEquals(ClickHouseStatementImpl.extractDBAndTableName(" SELECT fromUnixTimestamp64Milli(time)from db.`.inner.a`"), "db..inner.a"); + } + + @Test + public void testExtractTableName() { + assertEquals(ClickHouseStatementImpl.extractTableName("SELECT from table"), "table"); + assertEquals(ClickHouseStatementImpl.extractTableName("SELECT from table a"), "table"); + assertEquals(ClickHouseStatementImpl.extractTableName("SELECT from db.table a"), "table"); + assertEquals(ClickHouseStatementImpl.extractTableName("SELECT from `db.table` a"), "table"); + assertEquals(ClickHouseStatementImpl.extractTableName(" SELECT fromUnixTimestamp64Milli(time)from db.`.inner.a`"), ".inner.a"); + } + + @Test + public void testExtractDBNameInt() { + assertEquals(ClickHouseStatementImpl.extractDBNameInt("SELECT from table"), ""); + assertEquals(ClickHouseStatementImpl.extractDBNameInt("SELECT from table a"), ""); + assertEquals(ClickHouseStatementImpl.extractDBNameInt("SELECT from db.table a"), "db"); + assertEquals(ClickHouseStatementImpl.extractDBNameInt("SELECT from `db.table` a"), "db"); + assertEquals(ClickHouseStatementImpl.extractDBNameInt(" SELECT fromUnixTimestamp64Milli(time)from db.`.inner.a`"), "db"); + } }