From 6c418c98cfe63f8780a7abb61f5aefcef33e58a3 Mon Sep 17 00:00:00 2001 From: jkee <jkee@yandex-team.ru> Date: Mon, 16 Mar 2015 19:14:44 +0300 Subject: [PATCH] METR-15511: refactor 1 --- .../metrika/clickhouse/CHException.java | 22 +++ .../metrika/clickhouse/CHStatement.java | 21 ++- .../{HttpResult.java => CHResultSet.java} | 137 +----------------- .../copypaste/CHResultSetMetaData.java | 134 +++++++++++++++++ .../copypaste/ThrowingFunction.java | 5 + 5 files changed, 182 insertions(+), 137 deletions(-) create mode 100644 src/main/java/ru/yandex/metrika/clickhouse/CHException.java rename src/main/java/ru/yandex/metrika/clickhouse/copypaste/{HttpResult.java => CHResultSet.java} (63%) create mode 100644 src/main/java/ru/yandex/metrika/clickhouse/copypaste/CHResultSetMetaData.java create mode 100644 src/main/java/ru/yandex/metrika/clickhouse/copypaste/ThrowingFunction.java diff --git a/src/main/java/ru/yandex/metrika/clickhouse/CHException.java b/src/main/java/ru/yandex/metrika/clickhouse/CHException.java new file mode 100644 index 00000000..c5fc9730 --- /dev/null +++ b/src/main/java/ru/yandex/metrika/clickhouse/CHException.java @@ -0,0 +1,22 @@ +package ru.yandex.metrika.clickhouse; + +import java.sql.SQLException; + +/** + * Created by jkee on 16.03.15. + */ +public class CHException extends SQLException { + + + public CHException(String reason) { + super(reason); + } + + public CHException(String reason, int vendorCode) { + super(reason, null, vendorCode); + } + + public CHException(String reason, Throwable cause) { + super(reason, cause); + } +} diff --git a/src/main/java/ru/yandex/metrika/clickhouse/CHStatement.java b/src/main/java/ru/yandex/metrika/clickhouse/CHStatement.java index 2be88235..dc58be44 100644 --- a/src/main/java/ru/yandex/metrika/clickhouse/CHStatement.java +++ b/src/main/java/ru/yandex/metrika/clickhouse/CHStatement.java @@ -1,12 +1,12 @@ package ru.yandex.metrika.clickhouse; -import ru.yandex.metrika.clickhouse.copypaste.*; import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; import org.apache.http.client.methods.HttpPost; import org.apache.http.entity.StringEntity; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.util.EntityUtils; +import ru.yandex.metrika.clickhouse.copypaste.*; import java.io.IOException; import java.io.InputStream; @@ -30,6 +30,10 @@ public class CHStatement implements Statement { this.url = url; } + public static String clickhousifySql(String sql) { + return clickhousifySql(sql, "TabSeparatedWithNamesAndTypes"); + } + public static String clickhousifySql(String sql, String format) { sql = sql.trim(); if (!sql.replace(";", "").trim().endsWith(" TabSeparatedWithNamesAndTypes") @@ -43,11 +47,11 @@ public class CHStatement implements Statement { @Override public ResultSet executeQuery(String sql) throws SQLException { - String csql = clickhousifySql(sql, "TabSeparatedWithNamesAndTypes"); + String csql = clickhousifySql(sql); CountingInputStream is = getInputStream(csql); try { - return new HttpResult(properties.isCompress() - ? new ClickhouseLZ4Stream(is) : is, is, properties.getBufferSize()); + return new CHResultSet(properties.isCompress() + ? new ClickhouseLZ4Stream(is) : is, properties.getBufferSize()); } catch (Exception e) { throw new RuntimeException(e); } @@ -81,19 +85,22 @@ public class CHStatement implements Statement { return new CountingInputStream(is); } catch (IOException e) { EntityUtils.consumeQuietly(entity); - try { if (is != null) is.close(); } catch (IOException ignored) { } throw new RuntimeException(e); } } @Override public int executeUpdate(String sql) throws SQLException { - return 0; + throw new UnsupportedOperationException(); } @Override public void close() throws SQLException { - + try { + client.close(); + } catch (IOException e) { + throw new CHException("HTTP client close exception", e); + } } @Override diff --git a/src/main/java/ru/yandex/metrika/clickhouse/copypaste/HttpResult.java b/src/main/java/ru/yandex/metrika/clickhouse/copypaste/CHResultSet.java similarity index 63% rename from src/main/java/ru/yandex/metrika/clickhouse/copypaste/HttpResult.java rename to src/main/java/ru/yandex/metrika/clickhouse/copypaste/CHResultSet.java index 3f43b0d6..45366868 100644 --- a/src/main/java/ru/yandex/metrika/clickhouse/copypaste/HttpResult.java +++ b/src/main/java/ru/yandex/metrika/clickhouse/copypaste/CHResultSet.java @@ -25,7 +25,7 @@ import java.util.Map; * @version $Id$ * @since 7/12/12 */ -public class HttpResult extends AbstractResultSet { +public class CHResultSet extends AbstractResultSet { private ByteFragment nextLine; private final StreamSplitter bis; @@ -33,20 +33,16 @@ public class HttpResult extends AbstractResultSet { private final Map<String, Integer> col = new HashMap<String, Integer>(); // column name -> 1-based index private final String[] columns; private final String[] types; - // number of characters read from is stream - private long bytes = 0; - private final CountingInputStream cis; private static final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); // private ByteFragment[] values; - public HttpResult(InputStream is, CountingInputStream cis, int bufferSize) throws IOException { - this.cis = cis; + public CHResultSet(InputStream is, int bufferSize) throws IOException { bis = new StreamSplitter(is, (byte) 0x0A, bufferSize); /// \n ByteFragment headerFragment = bis.next(); if (headerFragment == null) { - throw new IllegalArgumentException("ru.yandex.metrika.clickhouse response without column names"); + throw new IllegalArgumentException("clickhouse response without column names"); } String header = headerFragment.asString(); if (header.startsWith("Code: ") && !header.contains("\t")) { @@ -56,7 +52,7 @@ public class HttpResult extends AbstractResultSet { columns = Patterns.TAB.split(header); ByteFragment typesFragment = bis.next(); if (typesFragment == null) { - throw new IllegalArgumentException("ru.yandex.metrika.clickhouse response without column types"); + throw new IllegalArgumentException("clickhouse response without column types"); } types = Patterns.TAB.split(typesFragment.asString()); @@ -72,8 +68,6 @@ public class HttpResult extends AbstractResultSet { nextLine = bis.next(); if (nextLine == null || nextLine.length() == 0) { bis.close(); - } else { - bytes += nextLine.getLen(); } } catch (IOException e) { throw new SQLException(e); @@ -115,125 +109,7 @@ public class HttpResult extends AbstractResultSet { @Override public ResultSetMetaData getMetaData() throws SQLException { - return new ResultSetMetaData() { - @Override - public int getColumnCount() throws SQLException { - return columns.length; - } - - @Override - public boolean isAutoIncrement(int column) throws SQLException { - return false; - } - - @Override - public boolean isCaseSensitive(int column) throws SQLException { - return true; - } - - @Override - public boolean isSearchable(int column) throws SQLException { - return true; - } - - @Override - public boolean isCurrency(int column) throws SQLException { - return false; - } - - @Override - public int isNullable(int column) throws SQLException { - return columnNoNulls; - } - - @Override - public boolean isSigned(int column) throws SQLException { - return !types[column - 1].startsWith("U"); - } - - @Override - public int getColumnDisplaySize(int column) throws SQLException { - return 80; - } - - @Override - public String getColumnLabel(int column) throws SQLException { - return columns[column - 1]; - } - - @Override - public String getColumnName(int column) throws SQLException { - return columns[column - 1]; - } - - @Override - public String getSchemaName(int column) throws SQLException { - return ""; - } - - @Override - public int getPrecision(int column) throws SQLException { - return 0; - } - - @Override - public int getScale(int column) throws SQLException { - return 0; - } - - @Override - public String getTableName(int column) throws SQLException { - throw new UnsupportedOperationException("table name unknown at this stage"); - } - - @Override - public String getCatalogName(int column) throws SQLException { - throw new UnsupportedOperationException("catalog name unknown at this stage"); - } - - @Override - public int getColumnType(int column) throws SQLException { - return toSqlType(getColumnTypeName(column)); - } - - @Override - public String getColumnTypeName(int column) throws SQLException { - if (types.length < column) { - throw new ArrayIndexOutOfBoundsException("Array length: " + types.length + " requested: " + (column - 1)); - } - return types[column - 1]; - } - - @Override - public boolean isReadOnly(int column) throws SQLException { - return true; - } - - @Override - public boolean isWritable(int column) throws SQLException { - return false; - } - - @Override - public boolean isDefinitelyWritable(int column) throws SQLException { - return false; - } - - @Override - public String getColumnClassName(int column) throws SQLException { - throw new UnsupportedOperationException("no classes for now"); - } - - @Override - public <T> T unwrap(Class<T> iface) throws SQLException { - return null; - } - - @Override - public boolean isWrapperFor(Class<?> iface) throws SQLException { - return false; - } - }; + return new CHResultSetMetaData(this); } @@ -398,7 +274,7 @@ public class HttpResult extends AbstractResultSet { } } - private int toSqlType(String type) { + int toSqlType(String type) { if (type.startsWith("Int") || type.startsWith("UInt")) { if (type.endsWith("64")) return Types.BIGINT; @@ -414,4 +290,5 @@ public class HttpResult extends AbstractResultSet { return Types.VARCHAR; } + } diff --git a/src/main/java/ru/yandex/metrika/clickhouse/copypaste/CHResultSetMetaData.java b/src/main/java/ru/yandex/metrika/clickhouse/copypaste/CHResultSetMetaData.java new file mode 100644 index 00000000..8c827b5e --- /dev/null +++ b/src/main/java/ru/yandex/metrika/clickhouse/copypaste/CHResultSetMetaData.java @@ -0,0 +1,134 @@ +package ru.yandex.metrika.clickhouse.copypaste; + +import java.sql.ResultSetMetaData; +import java.sql.SQLException; + +/** +* Created by jkee on 16.03.15. +*/ +public class CHResultSetMetaData implements ResultSetMetaData { + + private final CHResultSet CHResultSet; + + public CHResultSetMetaData(CHResultSet CHResultSet) { + this.CHResultSet = CHResultSet; + } + + @Override + public int getColumnCount() throws SQLException { + return CHResultSet.getColumnNames().length; + } + + @Override + public boolean isAutoIncrement(int column) throws SQLException { + return false; + } + + @Override + public boolean isCaseSensitive(int column) throws SQLException { + return true; + } + + @Override + public boolean isSearchable(int column) throws SQLException { + return true; + } + + @Override + public boolean isCurrency(int column) throws SQLException { + return false; + } + + @Override + public int isNullable(int column) throws SQLException { + return columnNoNulls; + } + + @Override + public boolean isSigned(int column) throws SQLException { + return !CHResultSet.getTypes()[column - 1].startsWith("U"); + } + + @Override + public int getColumnDisplaySize(int column) throws SQLException { + return 80; + } + + @Override + public String getColumnLabel(int column) throws SQLException { + return CHResultSet.getColumnNames()[column - 1]; + } + + @Override + public String getColumnName(int column) throws SQLException { + return CHResultSet.getColumnNames()[column - 1]; + } + + @Override + public String getSchemaName(int column) throws SQLException { + return ""; + } + + @Override + public int getPrecision(int column) throws SQLException { + return 0; + } + + @Override + public int getScale(int column) throws SQLException { + return 0; + } + + @Override + public String getTableName(int column) throws SQLException { + throw new UnsupportedOperationException("table name unknown at this stage"); + } + + @Override + public String getCatalogName(int column) throws SQLException { + throw new UnsupportedOperationException("catalog name unknown at this stage"); + } + + @Override + public int getColumnType(int column) throws SQLException { + return CHResultSet.toSqlType(getColumnTypeName(column)); + } + + @Override + public String getColumnTypeName(int column) throws SQLException { + if (CHResultSet.getTypes().length < column) { + throw new ArrayIndexOutOfBoundsException("Array length: " + CHResultSet.getTypes().length + " requested: " + (column - 1)); + } + return CHResultSet.getTypes()[column - 1]; + } + + @Override + public boolean isReadOnly(int column) throws SQLException { + return true; + } + + @Override + public boolean isWritable(int column) throws SQLException { + return false; + } + + @Override + public boolean isDefinitelyWritable(int column) throws SQLException { + return false; + } + + @Override + public String getColumnClassName(int column) throws SQLException { + throw new UnsupportedOperationException("no classes for now"); + } + + @Override + public <T> T unwrap(Class<T> iface) throws SQLException { + return null; + } + + @Override + public boolean isWrapperFor(Class<?> iface) throws SQLException { + return false; + } +} diff --git a/src/main/java/ru/yandex/metrika/clickhouse/copypaste/ThrowingFunction.java b/src/main/java/ru/yandex/metrika/clickhouse/copypaste/ThrowingFunction.java new file mode 100644 index 00000000..7c4dd4a8 --- /dev/null +++ b/src/main/java/ru/yandex/metrika/clickhouse/copypaste/ThrowingFunction.java @@ -0,0 +1,5 @@ +package ru.yandex.metrika.clickhouse.copypaste; + +public interface ThrowingFunction<F,R> { + R apply(F f) throws Exception; +} \ No newline at end of file -- GitLab