From 455d5e2fbcdc99e2c8f1f4cebde814da223a7bf6 Mon Sep 17 00:00:00 2001
From: serebrserg <serebrserg@yandex-team.ru>
Date: Mon, 28 Mar 2016 15:36:07 +0300
Subject: [PATCH] METR-20494: add CHQueryParam enum

---
 .../metrika/clickhouse/CHStatement.java       |  7 +-
 .../metrika/clickhouse/CHStatementImpl.java   | 35 +++++-----
 .../clickhouse/copypaste/CHQueryParam.java    | 70 +++++++++++++++++++
 3 files changed, 92 insertions(+), 20 deletions(-)
 create mode 100644 src/main/java/ru/yandex/metrika/clickhouse/copypaste/CHQueryParam.java

diff --git a/src/main/java/ru/yandex/metrika/clickhouse/CHStatement.java b/src/main/java/ru/yandex/metrika/clickhouse/CHStatement.java
index d14364c7..54892ec0 100644
--- a/src/main/java/ru/yandex/metrika/clickhouse/CHStatement.java
+++ b/src/main/java/ru/yandex/metrika/clickhouse/CHStatement.java
@@ -1,5 +1,6 @@
 package ru.yandex.metrika.clickhouse;
 
+import ru.yandex.metrika.clickhouse.copypaste.CHQueryParam;
 import ru.yandex.metrika.clickhouse.copypaste.ClickhouseResponse;
 
 import java.io.InputStream;
@@ -14,8 +15,8 @@ import java.util.Map;
  */
 public interface CHStatement extends Statement {
     ClickhouseResponse executeQueryClickhouseResponse(String sql) throws SQLException;
-    ClickhouseResponse executeQueryClickhouseResponse(String sql, Map<String, String> additionalDBParams) throws SQLException;
-    ClickhouseResponse executeQueryClickhouseResponse(String sql, Map<String, String> additionalDBParams, boolean ignoreDatabase) throws SQLException;
-    ResultSet executeQuery(String sql, Map<String, String> additionalDBParams) throws SQLException;
+    ClickhouseResponse executeQueryClickhouseResponse(String sql, Map<CHQueryParam, String> additionalDBParams) throws SQLException;
+    ClickhouseResponse executeQueryClickhouseResponse(String sql, Map<CHQueryParam, String> additionalDBParams, boolean ignoreDatabase) throws SQLException;
+    ResultSet executeQuery(String sql, Map<CHQueryParam, String> additionalDBParams) throws SQLException;
     void sendStream(InputStream content, String table) throws SQLException;
 }
diff --git a/src/main/java/ru/yandex/metrika/clickhouse/CHStatementImpl.java b/src/main/java/ru/yandex/metrika/clickhouse/CHStatementImpl.java
index 0a98e0ff..6f366984 100644
--- a/src/main/java/ru/yandex/metrika/clickhouse/CHStatementImpl.java
+++ b/src/main/java/ru/yandex/metrika/clickhouse/CHStatementImpl.java
@@ -27,6 +27,7 @@ import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
+import static ru.yandex.metrika.clickhouse.copypaste.CHQueryParam.*;
 /**
  * Created by jkee on 14.03.15.
  */
@@ -65,7 +66,7 @@ public class CHStatementImpl implements CHStatement {
         return executeQuery(sql, null);
     }
 
-    public ResultSet executeQuery(String sql, Map<String, String> additionalDBParams) throws SQLException {
+    public ResultSet executeQuery(String sql, Map<CHQueryParam, String> additionalDBParams) throws SQLException {
         InputStream is = getInputStream(sql, additionalDBParams, false);
         try {
             currentResult = new CHResultSet(properties.isCompress()
@@ -84,11 +85,11 @@ public class CHStatementImpl implements CHStatement {
         return executeQueryClickhouseResponse(sql, null);
     }
 
-    public ClickhouseResponse executeQueryClickhouseResponse(String sql, Map<String, String> additionalDBParams) throws SQLException {
+    public ClickhouseResponse executeQueryClickhouseResponse(String sql, Map<CHQueryParam, String> additionalDBParams) throws SQLException {
         return executeQueryClickhouseResponse(sql, additionalDBParams, false);
     }
 
-    public ClickhouseResponse executeQueryClickhouseResponse(String sql, Map<String, String> additionalDBParams, boolean ignoreDatabase) throws SQLException {
+    public ClickhouseResponse executeQueryClickhouseResponse(String sql, Map<CHQueryParam, String> additionalDBParams, boolean ignoreDatabase) throws SQLException {
         InputStream is = getInputStream(clickhousifySql(sql, "JSONCompact"), additionalDBParams, ignoreDatabase);
         try {
             byte[] bytes = null;
@@ -381,20 +382,20 @@ public class CHStatementImpl implements CHStatement {
     }
 
     private InputStream getInputStream(String sql,
-                                       Map<String, String> additionalClickHouseDBParams,
+                                       Map<CHQueryParam, String> additionalClickHouseDBParams,
                                        boolean ignoreDatabase
     ) throws CHException {
         sql = clickhousifySql(sql);
         log.debug("Executing SQL: " + sql);
         URI uri = null;
         try {
-            Map<String, String> params = getParams(ignoreDatabase);
+            Map<CHQueryParam, String> params = getParams(ignoreDatabase);
             if (additionalClickHouseDBParams != null && !additionalClickHouseDBParams.isEmpty()) {
                 params.putAll(additionalClickHouseDBParams);
             }
             List<String> paramPairs = new ArrayList<String>();
-            for (Map.Entry<String, String> entry : params.entrySet()) {
-                paramPairs.add(entry.getKey() + '=' + entry.getValue());
+            for (Map.Entry<CHQueryParam, String> entry : params.entrySet()) {
+                paramPairs.add(entry.getKey().toString() + '=' + entry.getValue());
             }
             String query = CopypasteUtils.join(paramPairs, '&');
             uri = new URI("http", null, source.getHost(), source.getPort(),
@@ -471,31 +472,31 @@ public class CHStatementImpl implements CHStatement {
         }
     }
 
-    public Map<String, String> getParams(boolean ignoreDatabase) {
-        Map<String, String> params = new HashMap<String, String>();
+    public Map<CHQueryParam, String> getParams(boolean ignoreDatabase) {
+        Map<CHQueryParam, String> params = new HashMap<CHQueryParam, String>();
         //в clickhouse бывают таблички без базы (т.е. в базе default)
         if (!CopypasteUtils.isBlank(source.getDatabase()) && !ignoreDatabase) {
-            params.put("database", source.getDatabase());
+            params.put(DATABASE, source.getDatabase());
         }
         if (properties.isCompress()) {
-            params.put("compress", "1");
+            params.put(COMPRESS, "1");
         }
         // нам всегда нужны min и max в ответе
-        params.put("extremes", "1");
+        params.put(EXTREMES, "1");
         if (CopypasteUtils.isBlank(properties.getProfile())) {
             if (properties.getMaxThreads() != null)
-                params.put("max_threads", String.valueOf(properties.getMaxThreads()));
+                params.put(MAX_THREADS, String.valueOf(properties.getMaxThreads()));
             // да, там в секундах
-            params.put("max_execution_time", String.valueOf((properties.getSocketTimeout() + properties.getDataTransferTimeout()) / 1000));
+            params.put(MAX_EXECUTION_TIME, String.valueOf((properties.getSocketTimeout() + properties.getDataTransferTimeout()) / 1000));
             if (properties.getMaxBlockSize() != null) {
-                params.put("max_block_size", String.valueOf(properties.getMaxBlockSize()));
+                params.put(MAX_BLOCK_SIZE, String.valueOf(properties.getMaxBlockSize()));
             }
         } else {
-            params.put("profile", properties.getProfile());
+            params.put(PROFILE, properties.getProfile());
         }
         //в кликхаус иногда бывает user
         if (properties.getUser() != null) {
-            params.put("user", properties.getUser());
+            params.put(USER, properties.getUser());
         }
         return params;
     }
diff --git a/src/main/java/ru/yandex/metrika/clickhouse/copypaste/CHQueryParam.java b/src/main/java/ru/yandex/metrika/clickhouse/copypaste/CHQueryParam.java
new file mode 100644
index 00000000..02482b58
--- /dev/null
+++ b/src/main/java/ru/yandex/metrika/clickhouse/copypaste/CHQueryParam.java
@@ -0,0 +1,70 @@
+package ru.yandex.metrika.clickhouse.copypaste;
+
+/**
+ * @author serebrserg
+ * @since 25.03.16
+ */
+public enum CHQueryParam {
+    MAX_PARALLEL_REPLICAS,
+    /**
+     * Каким образом вычислять TOTALS при наличии HAVING, а также при наличии max_rows_to_group_by и group_by_overflow_mode = 'any'
+     * https://clickhouse.yandex-team.ru/#%D0%9C%D0%BE%D0%B4%D0%B8%D1%84%D0%B8%D0%BA%D0%B0%D1%82%D0%BE%D1%80%20WITH%20TOTALS
+     */
+    TOTALS_MODE,
+    /**
+     * keyed - значит в параметре запроса передаётся "ключ" quota_key,
+     и квота считается по отдельности для каждого значения ключа.
+     Например, в качестве ключа может передаваться логин пользователя в Метрике,
+     и тогда квота будет считаться для каждого логина по отдельности.
+     Имеет смысл использовать только если quota_key передаётся не пользователем, а программой.
+     */
+    QUOTA_KEY,
+    /**
+     * Меньше значение - больше приоритет
+     */
+    PRIORITY,
+    /**
+     * БД по умолчанию.
+     */
+    DATABASE,
+    /**
+     *  сервер будет сжимать отправляемые вам данные
+     */
+    COMPRESS,
+    /**
+     * Вы можете получить в дополнение к результату также минимальные и максимальные значения по столбцам результата.
+     * Для этого, выставите настройку extremes в 1. Минимумы и максимумы считаются для числовых типов, дат, дат-с-временем.
+     * Для остальных столбцов, будут выведены значения по умолчанию.
+     */
+    EXTREMES,
+    /**
+     * Максимальное количество потоков обработки запроса
+     * https://clickhouse.yandex-team.ru/#max_threads
+     */
+    MAX_THREADS,
+    /**
+     * Максимальное время выполнения запроса в секундах.
+     * https://clickhouse.yandex-team.ru/#max_execution_time
+     */
+    MAX_EXECUTION_TIME,
+    /**
+     *  это рекомендация, какого размера блоки (в количестве строк) загружать из таблицы.
+     * https://clickhouse.yandex-team.ru/#max_block_size
+     */
+    MAX_BLOCK_SIZE,
+    /**
+     * Профили настроек - это множество настроек, сгруппированных под одним именем.
+     * Для каждого пользователя ClickHouse указывается некоторый профиль.
+     */
+    PROFILE,
+    /**
+     *  имя пользователя, по умолчанию - default.
+     */
+    USER;
+
+
+    @Override
+    public String toString() {
+        return name().toLowerCase();
+    }
+}
-- 
GitLab