liyang-gmt8 closed pull request #118: Batch up
URL: https://github.com/apache/kylin/pull/118
 
 
   

This is a PR merged from a forked repository.
As GitHub hides the original diff on merge, it is displayed below for
the sake of provenance:

As this is a foreign pull request (from a fork), the diff is supplied
below (as it won't show otherwise due to GitHub magic):

diff --git 
a/atopcalcite/src/main/java/org/apache/calcite/prepare/CalcitePrepareImpl.java 
b/atopcalcite/src/main/java/org/apache/calcite/prepare/CalcitePrepareImpl.java
index 7b4c549fe6..b63beeeb49 100644
--- 
a/atopcalcite/src/main/java/org/apache/calcite/prepare/CalcitePrepareImpl.java
+++ 
b/atopcalcite/src/main/java/org/apache/calcite/prepare/CalcitePrepareImpl.java
@@ -146,6 +146,7 @@
 import org.apache.calcite.sql2rel.SqlToRelConverter;
 import org.apache.calcite.sql2rel.StandardConvertletTable;
 import org.apache.calcite.tools.Frameworks;
+import org.apache.calcite.tools.RelUtils;
 import org.apache.calcite.util.ImmutableIntList;
 import org.apache.calcite.util.Pair;
 import org.apache.calcite.util.Util;
@@ -1165,10 +1166,13 @@ private PreparedResult prepare_(Supplier<RelNode> fn,
 
       final List<Materialization> materializations = ImmutableList.of();
       final List<LatticeEntry> lattices = ImmutableList.of();
+      long start = System.currentTimeMillis();
+      LOGGER.info("Begin optimize");
       root = optimize(root, materializations, lattices);
+      LOGGER.info("End optimize, take : " + (System.currentTimeMillis() - 
start));
 
       if (timingTracer != null) {
-        timingTracer.traceTime("end optimization");
+          timingTracer.traceTime("end optimization");
       }
 
       return implement(root);
@@ -1250,6 +1254,10 @@ protected SqlValidator createSqlValidator(CatalogReader 
catalogReader) {
     }
 
     @Override protected PreparedResult implement(RelRoot root) {
+      if(RelUtils.findOLAPRel(root.rel) && 
!root.rel.getClass().getName().contains("OLAPToEnumerableConverter")){
+        String dumpPlan = RelOptUtil.dumpPlan("", root.rel, false, 
SqlExplainLevel.DIGEST_ATTRIBUTES);
+        throw new IllegalArgumentException("Error planer:" + dumpPlan);
+      }
       RelDataType resultType = root.rel.getRowType();
       boolean isDml = root.kind.belongsTo(SqlKind.DML);
       final Bindable bindable;
diff --git a/atopcalcite/src/main/java/org/apache/calcite/tools/RelUtils.java 
b/atopcalcite/src/main/java/org/apache/calcite/tools/RelUtils.java
new file mode 100644
index 0000000000..68ad5cd1a4
--- /dev/null
+++ b/atopcalcite/src/main/java/org/apache/calcite/tools/RelUtils.java
@@ -0,0 +1,71 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.calcite.tools;
+
+import java.util.List;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import org.apache.calcite.rel.RelNode;
+import org.apache.calcite.rex.RexCall;
+import org.apache.calcite.rex.RexNode;
+import org.apache.calcite.rex.RexVisitor;
+import org.apache.calcite.rex.RexVisitorImpl;
+import org.apache.calcite.sql.SqlOperator;
+
+import com.google.common.collect.Lists;
+
+public class RelUtils {
+    public static boolean findOLAPRel(RelNode rel) {
+        Class aClass;
+        try {
+            aClass = 
Thread.currentThread().getContextClassLoader().loadClass("org.apache.kylin.query.relnode.OLAPRel");
+        } catch (ClassNotFoundException e) {
+            return false;
+        }
+        return findRel(rel, Lists.newArrayList(aClass)) != null;
+    }
+
+    private static RelNode findRel(RelNode rel, List<Class> candidate) {
+        for (Class clazz : candidate) {
+            if (clazz.isInstance(rel)) {
+                return rel;
+            }
+        }
+
+        if (rel.getInputs().size() < 1) {
+            return null;
+        }
+
+        return findRel(rel.getInput(0), candidate);
+    }
+
+    public static int countOperatorCall(final SqlOperator operator, RexNode 
node) {
+        final AtomicInteger atomicInteger = new AtomicInteger(0);
+        RexVisitor<Void> visitor = new RexVisitorImpl<Void>(true) {
+            public Void visitCall(RexCall call) {
+                if (call.getOperator().equals(operator)) {
+                    atomicInteger.incrementAndGet();
+                }
+                return super.visitCall(call);
+            }
+        };
+        node.accept(visitor);
+        return atomicInteger.get();
+    }
+}
diff --git 
a/core-common/src/main/java/org/apache/kylin/common/KylinConfigBase.java 
b/core-common/src/main/java/org/apache/kylin/common/KylinConfigBase.java
index 7596d2c211..0726897e9c 100644
--- a/core-common/src/main/java/org/apache/kylin/common/KylinConfigBase.java
+++ b/core-common/src/main/java/org/apache/kylin/common/KylinConfigBase.java
@@ -1187,6 +1187,14 @@ public boolean isSparkSanityCheckEnabled() {
     // QUERY
     // 
============================================================================
 
+    public Boolean isEnumerableRulesEnabled() {
+        return 
Boolean.parseBoolean(getOptional("kylin.query.calcite.enumerable-rules-enabled",
 "false"));
+    }
+    
+    public boolean isReduceExpressionsRulesEnabled() {
+        return 
Boolean.parseBoolean(getOptional("kylin.query.calcite.reduce-rules-enabled", 
"true"));
+    }
+    
     public boolean isConvertCreateTableToWith() {
         return 
Boolean.valueOf(getOptional("kylin.query.convert-create-table-to-with", 
"false"));
     }
@@ -1636,5 +1644,4 @@ public String getAutoMigrateCubeSrcConfig() {
     public String getAutoMigrateCubeDestConfig() {
         return getOptional("kylin.tool.auto-migrate-cube.dest-config", "");
     }
-
 }
diff --git 
a/core-common/src/main/java/org/apache/kylin/common/QueryContext.java 
b/core-common/src/main/java/org/apache/kylin/common/QueryContext.java
index 1aa94d3e8d..66b9871344 100644
--- a/core-common/src/main/java/org/apache/kylin/common/QueryContext.java
+++ b/core-common/src/main/java/org/apache/kylin/common/QueryContext.java
@@ -52,6 +52,7 @@
     private AtomicLong scannedRows = new AtomicLong();
     private AtomicLong returnedRows = new AtomicLong();
     private AtomicLong scannedBytes = new AtomicLong();
+    private Object calcitePlan;
 
     private AtomicBoolean isRunning = new AtomicBoolean(true);
     private volatile Throwable throwable;
@@ -104,6 +105,14 @@ public void setGroups(Set<String> groups) {
         this.groups = groups;
     }
 
+    public Object getCalcitePlan() {
+        return calcitePlan;
+    }
+
+    public void setCalcitePlan(Object calcitePlan) {
+        this.calcitePlan = calcitePlan;
+    }
+
     public long getScannedRows() {
         return scannedRows.get();
     }
diff --git 
a/core-common/src/main/java/org/apache/kylin/common/util/EncryptUtil.java 
b/core-common/src/main/java/org/apache/kylin/common/util/EncryptUtil.java
new file mode 100644
index 0000000000..309fb3dd1d
--- /dev/null
+++ b/core-common/src/main/java/org/apache/kylin/common/util/EncryptUtil.java
@@ -0,0 +1,55 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.kylin.common.util;
+
+import org.apache.commons.codec.binary.Base64;
+
+import javax.crypto.Cipher;
+import javax.crypto.spec.SecretKeySpec;
+
+public class EncryptUtil {
+    /**
+     * thisIsAsecretKey
+     */
+    private static byte[] key = { 0x74, 0x68, 0x69, 0x73, 0x49, 0x73, 0x41, 
0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x4b, 0x65, 0x79 };
+
+    public static String encrypt(String strToEncrypt) {
+        try {
+            Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
+            final SecretKeySpec secretKey = new SecretKeySpec(key, "AES");
+            cipher.init(Cipher.ENCRYPT_MODE, secretKey);
+            final String encryptedString = 
Base64.encodeBase64String(cipher.doFinal(strToEncrypt.getBytes()));
+            return encryptedString;
+        } catch (Exception e) {
+            throw new RuntimeException(e.getMessage(), e);
+        }
+    }
+
+    public static String decrypt(String strToDecrypt) {
+        try {
+            Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5PADDING");
+            final SecretKeySpec secretKey = new SecretKeySpec(key, "AES");
+            cipher.init(Cipher.DECRYPT_MODE, secretKey);
+            final String decryptedString = new 
String(cipher.doFinal(Base64.decodeBase64(strToDecrypt)));
+            return decryptedString;
+        } catch (Exception e) {
+            throw new RuntimeException(e.getMessage(), e);
+        }
+    }
+}
diff --git 
a/server-base/src/test/java/org/apache/kylin/rest/security/PasswordPlaceHolderConfigurerTest.java
 b/core-common/src/test/java/org/apache/kylin/common/util/EncryptUtilTest.java
similarity index 86%
rename from 
server-base/src/test/java/org/apache/kylin/rest/security/PasswordPlaceHolderConfigurerTest.java
rename to 
core-common/src/test/java/org/apache/kylin/common/util/EncryptUtilTest.java
index ac42ad7d0c..bc1c3e7ae4 100644
--- 
a/server-base/src/test/java/org/apache/kylin/rest/security/PasswordPlaceHolderConfigurerTest.java
+++ 
b/core-common/src/test/java/org/apache/kylin/common/util/EncryptUtilTest.java
@@ -16,18 +16,19 @@
  * limitations under the License.
 */
 
-package org.apache.kylin.rest.security;
+package org.apache.kylin.common.util;
 
 import org.junit.Assert;
 import org.junit.Test;
 
-public class PasswordPlaceHolderConfigurerTest {
+public class EncryptUtilTest {
 
     @Test
     public void testAESEncrypt(){
         String input = "hello world";
-        String result = PasswordPlaceholderConfigurer.encrypt(input);
+        String result = EncryptUtil.encrypt(input);
         Assert.assertEquals("4stv/RRleOtvie/8SLHmXA==", result);
     }
 
 }
+
diff --git a/dev-support/jacocoagent.jar b/dev-support/jacocoagent.jar
new file mode 100644
index 0000000000..6e70590cc2
Binary files /dev/null and b/dev-support/jacocoagent.jar differ
diff --git 
a/engine-mr/src/main/java/org/apache/kylin/engine/mr/steps/CreateDictionaryJob.java
 
b/engine-mr/src/main/java/org/apache/kylin/engine/mr/steps/CreateDictionaryJob.java
index a4576774aa..dab4880390 100644
--- 
a/engine-mr/src/main/java/org/apache/kylin/engine/mr/steps/CreateDictionaryJob.java
+++ 
b/engine-mr/src/main/java/org/apache/kylin/engine/mr/steps/CreateDictionaryJob.java
@@ -82,7 +82,7 @@ public IReadableTable getDistinctValuesFor(TblColRef col) {
                 List<TblColRef> uhcColumns = 
cube.getDescriptor().getAllUHCColumns();
 
                 Path colDir;
-                if (uhcColumns.contains(col)) {
+                if (config.isBuildUHCDictWithMREnabled() && 
uhcColumns.contains(col)) {
                     colDir = new Path(dictPath, col.getIdentity());
                 } else {
                     colDir = new Path(factColumnsInputPath, col.getIdentity());
diff --git 
a/examples/test_case_data/localmeta/cube_desc/ci_inner_join_cube.json 
b/examples/test_case_data/localmeta/cube_desc/ci_inner_join_cube.json
index 809e188ee3..ec1100a1da 100644
--- a/examples/test_case_data/localmeta/cube_desc/ci_inner_join_cube.json
+++ b/examples/test_case_data/localmeta/cube_desc/ci_inner_join_cube.json
@@ -342,7 +342,8 @@
       },
       {
         "column": "TEST_KYLIN_FACT.LEAF_CATEG_ID",
-        "encoding": "dict"
+        "encoding": "dict",
+        "isShardBy" : true
       },
       {
         "column": "TEST_CATEGORY_GROUPINGS.META_CATEG_NAME",
diff --git a/kylin-it/pom.xml b/kylin-it/pom.xml
index fd4fa8bb62..101f63021f 100644
--- a/kylin-it/pom.xml
+++ b/kylin-it/pom.xml
@@ -345,6 +345,7 @@
                             </systemProperties>
                             <argLine>-Xms1G -Xmx2G -XX:PermSize=128M 
-XX:MaxPermSize=512M
                                 -Dkylin.server.cluster-servers=localhost:7070
+                                
-javaagent:${project.basedir}/..//dev-support/jacocoagent.jar=includes=org.apache.kylin.*,output=file,destfile=jacoco-it.exec
                             </argLine>
                         </configuration>
                     </plugin>
@@ -372,6 +373,9 @@
                                         <argument>
                                             
-Dlog4j.configuration=file:${project.basedir}/..//build/conf/kylin-tools-log4j.properties
                                         </argument>
+                                        <argument>
+                                            
-javaagent:${project.basedir}/..//dev-support/jacocoagent.jar=includes=org.apache.kylin.*,output=file,destfile=jacoco-it-engine.exec
+                                        </argument>
                                         <argument>-classpath</argument>
                                         <classpath />
                                         
<argument>org.apache.kylin.provision.BuildCubeWithEngine
@@ -399,6 +403,9 @@
                                         <argument>
                                             
-Dlog4j.configuration=file:${project.basedir}/..//build/conf/kylin-tools-log4j.properties
                                         </argument>
+                                        <argument>
+                                            
-javaagent:${project.basedir}/..//dev-support/jacocoagent.jar=includes=org.apache.kylin.*,output=file,destfile=jacoco-it-stream.exec
+                                        </argument>
                                         <argument>-classpath</argument>
                                         <classpath />
                                         
<argument>org.apache.kylin.provision.BuildCubeWithStream
diff --git a/kylin-it/src/test/java/org/apache/kylin/jdbc/ITJDBCDriverTest.java 
b/kylin-it/src/test/java/org/apache/kylin/jdbc/ITJDBCDriverTest.java
index 765b12c482..eb3c773c2a 100644
--- a/kylin-it/src/test/java/org/apache/kylin/jdbc/ITJDBCDriverTest.java
+++ b/kylin-it/src/test/java/org/apache/kylin/jdbc/ITJDBCDriverTest.java
@@ -301,6 +301,33 @@ public void testResultSetWithMaxRows() throws Exception {
 
     }
 
+    @Test
+    public void testPreparedStatementWithCache() throws Exception {
+        Connection conn = getConnection();
+
+        PreparedStatement statement = conn
+                .prepareStatement("select count(1) as TRANS_CNT from 
test_kylin_fact where LSTG_FORMAT_NAME like ?");
+
+        statement.setString(1, "%");
+        ResultSet rs = statement.executeQuery();
+        Assert.assertTrue(rs.next());
+        Object object = rs.getObject(1);
+        long countFirst = (long) object;
+
+        statement.setString(1, "O%");
+        rs = statement.executeQuery();
+        Assert.assertTrue(rs.next());
+        object = rs.getObject(1);
+        long countSecond = (long) object;
+
+        Assert.assertTrue(countFirst > countSecond);
+
+        rs.close();
+        statement.close();
+        conn.close();
+
+    }
+
     private static class SystemPropertiesOverride {
         HashMap<String, String> backup = new HashMap<String, String>();
 
diff --git 
a/kylin-it/src/test/java/org/apache/kylin/query/ITKylinQueryTest.java 
b/kylin-it/src/test/java/org/apache/kylin/query/ITKylinQueryTest.java
index 4edfb3d279..e5d3c6bb2d 100644
--- a/kylin-it/src/test/java/org/apache/kylin/query/ITKylinQueryTest.java
+++ b/kylin-it/src/test/java/org/apache/kylin/query/ITKylinQueryTest.java
@@ -415,4 +415,21 @@ public void testPercentileQuery() throws Exception {
         batchExecuteQuery(getQueryFolderPrefix() + 
"src/test/resources/query/sql_percentile");
     }
 
+
+    @Test
+    public void testValues() throws Exception {
+        execAndCompQuery(getQueryFolderPrefix() + 
"src/test/resources/query/sql_values", null, true);
+    }
+
+
+
+    @Test
+    public void testPlan() throws Exception {
+        String originProp = System.getProperty("calcite.debug");
+        System.setProperty("calcite.debug", "true");
+        execAndCompPlan(getQueryFolderPrefix() + 
"src/test/resources/query/sql_plan", null, true);
+        if (originProp == null || "false".equals(originProp))
+            System.setProperty("calcite.debug", "false");
+    }
 }
+                                                  
\ No newline at end of file
diff --git a/kylin-it/src/test/java/org/apache/kylin/query/KylinTestBase.java 
b/kylin-it/src/test/java/org/apache/kylin/query/KylinTestBase.java
index 42ec917c10..fa49afb49c 100644
--- a/kylin-it/src/test/java/org/apache/kylin/query/KylinTestBase.java
+++ b/kylin-it/src/test/java/org/apache/kylin/query/KylinTestBase.java
@@ -18,6 +18,8 @@
 
 package org.apache.kylin.query;
 
+import static org.apache.calcite.sql.SqlDialect.CALCITE;
+
 import java.io.BufferedReader;
 import java.io.File;
 import java.io.FileInputStream;
@@ -42,6 +44,9 @@
 import java.util.TreeSet;
 import java.util.logging.LogManager;
 
+import org.apache.calcite.rel.RelNode;
+import org.apache.calcite.rel.rel2sql.RelToSqlConverter;
+import org.apache.calcite.sql.SqlNode;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.kylin.common.KylinConfig;
 import org.apache.kylin.common.QueryContextFacade;
@@ -54,6 +59,7 @@
 import org.apache.kylin.query.relnode.OLAPContext;
 import org.apache.kylin.query.routing.rules.RemoveBlackoutRealizationsRule;
 import org.apache.kylin.query.util.PushDownUtil;
+import org.apache.parquet.Strings;
 import org.dbunit.DatabaseUnitException;
 import org.dbunit.database.DatabaseConfig;
 import org.dbunit.database.DatabaseConnection;
@@ -546,6 +552,70 @@ public String transform(File f) {
         });
     }
 
+
+    protected void execAndCompPlan(String queryFolder, String[] 
exclusiveQuerys, boolean needSort) throws Exception {
+        execAndCompPlan(queryFolder, exclusiveQuerys, needSort, new 
ICompareQueryTranslator() {
+            @Override
+            public String transform(File f) {
+                try {
+                    return KylinTestBase.getTextFromFile(f);
+                } catch (IOException e) {
+                    throw new RuntimeException(e);
+                }
+            }
+        });
+
+    }
+
+    protected void execAndCompPlan(String queryFolder, String[] 
exclusiveQuerys, boolean needSort,
+            ICompareQueryTranslator translator) throws Exception {
+        logger.info("---------- test folder: " + new 
File(queryFolder).getAbsolutePath());
+        Set<String> exclusiveSet = buildExclusiveSet(exclusiveQuerys);
+
+        List<File> sqlFiles = getFilesFromFolder(new File(queryFolder), 
".sql");
+        for (File sqlFile : sqlFiles) {
+            String queryName = StringUtils.split(sqlFile.getName(), '.')[0];
+            if (exclusiveSet.contains(queryName)) {
+                continue;
+            }
+            String sql1 = getTextFromFile(sqlFile);
+            String sql2 = translator.transform(sqlFile);
+
+            // execute Kylin
+            logger.info("Query Result from Kylin - " + queryName + "  (" + 
queryFolder + ")");
+            IDatabaseConnection kylinConn = new 
DatabaseConnection(cubeConnection);
+            ITable kylinTable = executeQuery(kylinConn, queryName, sql1, 
needSort);
+            RelNode calcitePlan = (RelNode) 
QueryContextFacade.current().getCalcitePlan();
+            if (calcitePlan == null)
+                throw new NullPointerException();
+
+            // execute H2
+            logger.info("Query Result from H2 - " + queryName);
+            long currentTime = System.currentTimeMillis();
+            ITable h2Table = executeQuery(newH2Connection(), queryName, sql2, 
needSort);
+            logger.info("H2 spent " + (System.currentTimeMillis() - 
currentTime) + " mili-seconds.");
+
+            try {
+                // compare the result
+                assertTableEquals(h2Table, kylinTable);
+            } catch (Throwable t) {
+                logger.info("execAndCompQuery failed on: " + 
sqlFile.getAbsolutePath());
+                throw t;
+            }
+
+            RelToSqlConverter converter = new RelToSqlConverter(CALCITE);
+            SqlNode sqlNode = converter.visitChild(0, 
calcitePlan.getInput(0)).asStatement();
+            String optimizedSQL = sqlNode.toSqlString(CALCITE).getSql();
+            String expectedSQL = Strings.join(Files.readLines(
+                    new File(sqlFile.getParent(), sqlFile.getName() + 
".expected"), Charset.forName("utf-8")), "\n");
+            Assert.assertEquals(expectedSQL, optimizedSQL);
+            compQueryCount++;
+            if (kylinTable.getRowCount() == 0) {
+                zeroResultQueries.add(sql1);
+            }
+        }
+    }
+
     protected void execAndCompQuery(String queryFolder, String[] 
exclusiveQuerys, boolean needSort,
             ICompareQueryTranslator translator) throws Exception {
         logger.info("---------- test folder: " + new 
File(queryFolder).getAbsolutePath());
diff --git a/kylin-it/src/test/resources/query/sql_plan/query01.sql 
b/kylin-it/src/test/resources/query/sql_plan/query01.sql
new file mode 100644
index 0000000000..cc582b0573
--- /dev/null
+++ b/kylin-it/src/test/resources/query/sql_plan/query01.sql
@@ -0,0 +1,8 @@
+SELECT ORDER_ID
+FROM test_kylin_fact
+GROUP BY CAST(CASE
+               WHEN '1030101' = '1030101' THEN 
substring(COALESCE(LSTG_FORMAT_NAME, '888888888888'), 1, 1)
+               WHEN '1030101' = '1030102' THEN 
substring(COALESCE(LSTG_FORMAT_NAME, '999999999999'), 1, 1)
+               WHEN '1030101' = '1030103' THEN 
substring(COALESCE(LSTG_FORMAT_NAME, '777777777777'), 1, 1)
+               WHEN '1030101' = '1030104' THEN 
substring(COALESCE(LSTG_FORMAT_NAME, '666666666666'), 1, 1)
+       END AS varchar(256)), ORDER_ID
\ No newline at end of file
diff --git a/kylin-it/src/test/resources/query/sql_plan/query01.sql.expected 
b/kylin-it/src/test/resources/query/sql_plan/query01.sql.expected
new file mode 100644
index 0000000000..d233a920b6
--- /dev/null
+++ b/kylin-it/src/test/resources/query/sql_plan/query01.sql.expected
@@ -0,0 +1,3 @@
+SELECT "ORDER_ID"
+FROM "DEFAULT"."TEST_KYLIN_FACT"
+GROUP BY SUBSTRING(CASE WHEN "LSTG_FORMAT_NAME" IS NOT NULL THEN 
"LSTG_FORMAT_NAME" ELSE '888888888888' END FROM 1 FOR 1), "ORDER_ID"
\ No newline at end of file
diff --git a/kylin-it/src/test/resources/query/sql_subquery/query36.sql 
b/kylin-it/src/test/resources/query/sql_subquery/query36.sql
new file mode 100644
index 0000000000..d4d94bf846
--- /dev/null
+++ b/kylin-it/src/test/resources/query/sql_subquery/query36.sql
@@ -0,0 +1,24 @@
+--
+-- Licensed to the Apache Software Foundation (ASF) under one
+-- or more contributor license agreements.  See the NOTICE file
+-- distributed with this work for additional information
+-- regarding copyright ownership.  The ASF licenses this file
+-- to you under the Apache License, Version 2.0 (the
+-- "License"); you may not use this file except in compliance
+-- with the License.  You may obtain a copy of the License at
+--
+--     http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+--
+SELECT CAST(SUM("COUNT") as BIGINT) as TOTAL_COUNT
+FROM (
+       SELECT LSTG_FORMAT_NAME, COUNT(*) AS "COUNT"
+       FROM TEST_KYLIN_FACT
+       GROUP BY LSTG_FORMAT_NAME
+       ORDER BY "COUNT" DESC
+) A
diff --git a/kylin-it/src/test/resources/query/sql_values/query01.sql 
b/kylin-it/src/test/resources/query/sql_values/query01.sql
new file mode 100644
index 0000000000..055464e022
--- /dev/null
+++ b/kylin-it/src/test/resources/query/sql_values/query01.sql
@@ -0,0 +1,51 @@
+--
+-- Licensed to the Apache Software Foundation (ASF) under one
+-- or more contributor license agreements.  See the NOTICE file
+-- distributed with this work for additional information
+-- regarding copyright ownership.  The ASF licenses this file
+-- to you under the Apache License, Version 2.0 (the
+-- "License"); you may not use this file except in compliance
+-- with the License.  You may obtain a copy of the License at
+--
+--     http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+--
+SELECT *
+FROM (
+       SELECT leaf_categ_id, SUM(price) AS sum_price
+       FROM test_kylin_fact
+       GROUP BY leaf_categ_id
+       UNION ALL
+       SELECT leaf_categ_id, SUM(price) AS sum_price
+       FROM test_kylin_fact
+       GROUP BY leaf_categ_id
+)
+       CROSS JOIN (
+               SELECT SUM(price) AS sum_price_2
+               FROM test_kylin_fact
+               GROUP BY leaf_categ_id
+       )
+UNION ALL
+SELECT cast(1999 as bigint) AS leaf_categ_id, 11.2 AS sum_price, 21.2 AS 
sum_price2
+UNION ALL
+SELECT *
+FROM (
+       SELECT leaf_categ_id, SUM(price) AS sum_price
+       FROM test_kylin_fact
+       GROUP BY leaf_categ_id
+       UNION ALL
+       SELECT leaf_categ_id, SUM(price) AS sum_price
+       FROM test_kylin_fact
+       GROUP BY leaf_categ_id
+)
+       CROSS JOIN (
+               SELECT SUM(price) AS sum_price_2
+               FROM test_kylin_fact
+               GROUP BY leaf_categ_id
+       )
+ORDER BY 1
\ No newline at end of file
diff --git a/kylin-it/src/test/resources/query/sql_values/query02.sql 
b/kylin-it/src/test/resources/query/sql_values/query02.sql
new file mode 100644
index 0000000000..0c9b5603d2
--- /dev/null
+++ b/kylin-it/src/test/resources/query/sql_values/query02.sql
@@ -0,0 +1,27 @@
+--
+-- Licensed to the Apache Software Foundation (ASF) under one
+-- or more contributor license agreements.  See the NOTICE file
+-- distributed with this work for additional information
+-- regarding copyright ownership.  The ASF licenses this file
+-- to you under the Apache License, Version 2.0 (the
+-- "License"); you may not use this file except in compliance
+-- with the License.  You may obtain a copy of the License at
+--
+--     http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+--
+SELECT test_kylin_fact.lstg_format_name, test_cal_dt.week_beg_dt, 
SUM(test_kylin_fact.price) AS GMV
+       , COUNT(*) AS TRANS_CNT
+FROM test_kylin_fact
+       INNER JOIN edw.test_cal_dt test_cal_dt ON test_kylin_fact.cal_dt = 
test_cal_dt.cal_dt
+       INNER JOIN test_category_groupings
+       ON test_kylin_fact.leaf_categ_id = test_category_groupings.leaf_categ_id
+               AND test_kylin_fact.lstg_site_id = 
test_category_groupings.site_id
+       INNER JOIN edw.test_sites test_sites ON test_kylin_fact.lstg_site_id = 
test_sites.site_id
+WHERE 1 <> 1
+GROUP BY test_kylin_fact.lstg_format_name, test_cal_dt.week_beg_dt
\ No newline at end of file
diff --git a/kylin-it/src/test/resources/query/sql_values/query03.sql 
b/kylin-it/src/test/resources/query/sql_values/query03.sql
new file mode 100644
index 0000000000..6fac7b6fd6
--- /dev/null
+++ b/kylin-it/src/test/resources/query/sql_values/query03.sql
@@ -0,0 +1,17 @@
+SELECT LSTG_FORMAT_NAME, sum_price, sum_price2
+FROM (
+       SELECT LSTG_FORMAT_NAME, SUM(price) AS sum_price
+       FROM test_kylin_fact
+       GROUP BY LSTG_FORMAT_NAME
+       UNION ALL
+       SELECT LSTG_FORMAT_NAME, SUM(price) AS sum_price
+       FROM test_kylin_fact
+       GROUP BY LSTG_FORMAT_NAME
+)
+       CROSS JOIN (
+               SELECT SUM(price) AS sum_price2
+               FROM test_kylin_fact
+               GROUP BY LSTG_FORMAT_NAME
+       )
+UNION ALL
+SELECT 'name' AS LSTG_FORMAT_NAME, 11.2 AS sum_price, 22.1 AS sum_price2
\ No newline at end of file
diff --git a/kylin-it/src/test/resources/query/sql_values/query04.sql 
b/kylin-it/src/test/resources/query/sql_values/query04.sql
new file mode 100644
index 0000000000..24dfec88cc
--- /dev/null
+++ b/kylin-it/src/test/resources/query/sql_values/query04.sql
@@ -0,0 +1,50 @@
+SELECT *
+FROM (
+       SELECT leaf_categ_id, SUM(price) AS sum_price
+       FROM test_kylin_fact
+       GROUP BY leaf_categ_id
+       UNION ALL
+       SELECT leaf_categ_id, SUM(price) AS sum_price
+       FROM test_kylin_fact
+       GROUP BY leaf_categ_id
+)
+       CROSS JOIN (
+               SELECT MAX(price) AS sum_price_2
+               FROM test_kylin_fact
+               GROUP BY leaf_categ_id
+       )
+UNION ALL
+SELECT *
+FROM (
+       SELECT cast(1  as bigint) AS leaf_categ_id, SUM(price) AS sum_price
+       FROM test_kylin_fact
+       WHERE 1 <> 1
+       GROUP BY leaf_categ_id
+       UNION ALL
+       SELECT cast(2  as bigint) AS leaf_categ_id, SUM(price) AS sum_price
+       FROM test_kylin_fact
+       WHERE 1 <> 1
+       GROUP BY leaf_categ_id
+)
+       CROSS JOIN (
+               SELECT MAX(price) AS sum_price_2
+               FROM test_kylin_fact
+               GROUP BY leaf_categ_id
+       )
+UNION ALL
+SELECT *
+FROM (
+       SELECT leaf_categ_id, SUM(price) AS sum_price
+       FROM test_kylin_fact
+       GROUP BY leaf_categ_id
+       UNION ALL
+       SELECT leaf_categ_id, SUM(price) AS sum_price
+       FROM test_kylin_fact
+       GROUP BY leaf_categ_id
+)
+       CROSS JOIN (
+               SELECT MAX(price) AS sum_price_2
+               FROM test_kylin_fact
+               GROUP BY leaf_categ_id
+       )
+ORDER BY 1
\ No newline at end of file
diff --git a/kylin-it/src/test/resources/query/sql_values/query05.sql 
b/kylin-it/src/test/resources/query/sql_values/query05.sql
new file mode 100644
index 0000000000..cdfd622cc8
--- /dev/null
+++ b/kylin-it/src/test/resources/query/sql_values/query05.sql
@@ -0,0 +1,3 @@
+select leaf_categ_id, sum(price) as sum_price from test_kylin_fact  group by 
leaf_categ_id
+union all
+select cast(1  as bigint) as leaf_categ_id, 22.5 as sum_price
\ No newline at end of file
diff --git 
a/query/src/main/java/org/apache/kylin/query/optrule/OLAPAggregateRule.java 
b/query/src/main/java/org/apache/kylin/query/optrule/OLAPAggregateRule.java
index da53152ab4..14c4bc3053 100644
--- a/query/src/main/java/org/apache/kylin/query/optrule/OLAPAggregateRule.java
+++ b/query/src/main/java/org/apache/kylin/query/optrule/OLAPAggregateRule.java
@@ -52,7 +52,7 @@ public RelNode convert(RelNode rel) {
 
         RelTraitSet traitSet = agg.getTraitSet().replace(OLAPRel.CONVENTION);
         try {
-            return new OLAPAggregateRel(agg.getCluster(), traitSet, 
convert(agg.getInput(), traitSet), agg.indicator, agg.getGroupSet(), 
agg.getGroupSets(), agg.getAggCallList());
+            return new OLAPAggregateRel(agg.getCluster(), traitSet, 
convert(agg.getInput(), OLAPRel.CONVENTION), agg.indicator, agg.getGroupSet(), 
agg.getGroupSets(), agg.getAggCallList());
         } catch (InvalidRelException e) {
             throw new IllegalStateException("Can't create OLAPAggregateRel!", 
e);
         }
diff --git 
a/query/src/main/java/org/apache/kylin/query/optrule/OLAPFilterRule.java 
b/query/src/main/java/org/apache/kylin/query/optrule/OLAPFilterRule.java
index 33f3ea82e6..af47e242b3 100644
--- a/query/src/main/java/org/apache/kylin/query/optrule/OLAPFilterRule.java
+++ b/query/src/main/java/org/apache/kylin/query/optrule/OLAPFilterRule.java
@@ -18,32 +18,35 @@
 
 package org.apache.kylin.query.optrule;
 
+import org.apache.calcite.plan.Convention;
 import org.apache.calcite.plan.RelOptRule;
-import org.apache.calcite.plan.RelOptRuleCall;
+import org.apache.calcite.plan.RelOptUtil;
 import org.apache.calcite.plan.RelTraitSet;
+import org.apache.calcite.rel.RelNode;
+import org.apache.calcite.rel.convert.ConverterRule;
 import org.apache.calcite.rel.logical.LogicalFilter;
 import org.apache.kylin.query.relnode.OLAPFilterRel;
 import org.apache.kylin.query.relnode.OLAPRel;
 
 /**
  */
-public class OLAPFilterRule extends RelOptRule {
+public class OLAPFilterRule extends ConverterRule {
 
     public static final RelOptRule INSTANCE = new OLAPFilterRule();
 
     public OLAPFilterRule() {
-        super(operand(LogicalFilter.class, any()));
+        super(LogicalFilter.class, RelOptUtil.FILTER_PREDICATE, 
Convention.NONE, OLAPRel.CONVENTION, "OLAPFilterRule");
     }
 
     @Override
-    public void onMatch(RelOptRuleCall call) {
-        LogicalFilter filter = call.rel(0);
+    public RelNode convert(RelNode rel) {
+        LogicalFilter filter = (LogicalFilter) rel;
 
         RelTraitSet origTraitSet = filter.getTraitSet();
         RelTraitSet traitSet = 
origTraitSet.replace(OLAPRel.CONVENTION).simplify();
 
-        OLAPFilterRel olapFilter = new OLAPFilterRel(filter.getCluster(), 
traitSet, convert(filter.getInput(), traitSet), filter.getCondition());
-        call.transformTo(olapFilter);
+        return new OLAPFilterRel(filter.getCluster(), traitSet,
+                convert(filter.getInput(), 
filter.getInput().getTraitSet().replace(OLAPRel.CONVENTION)),
+                filter.getCondition());
     }
-
 }
diff --git 
a/query/src/main/java/org/apache/kylin/query/optrule/OLAPJoinRule.java 
b/query/src/main/java/org/apache/kylin/query/optrule/OLAPJoinRule.java
index c31d1d0533..d87a0c4e99 100644
--- a/query/src/main/java/org/apache/kylin/query/optrule/OLAPJoinRule.java
+++ b/query/src/main/java/org/apache/kylin/query/optrule/OLAPJoinRule.java
@@ -48,8 +48,8 @@ public RelNode convert(RelNode rel) {
         RelNode right = join.getInput(1);
 
         RelTraitSet traitSet = join.getTraitSet().replace(OLAPRel.CONVENTION);
-        left = convert(left, traitSet);
-        right = convert(right, traitSet);
+        left = convert(left, left.getTraitSet().replace(OLAPRel.CONVENTION));
+        right = convert(right, 
right.getTraitSet().replace(OLAPRel.CONVENTION));
 
         final JoinInfo info = JoinInfo.of(left, right, join.getCondition());
         if (!info.isEqui() && join.getJoinType() != JoinRelType.INNER) {
diff --git 
a/query/src/main/java/org/apache/kylin/query/optrule/OLAPProjectRule.java 
b/query/src/main/java/org/apache/kylin/query/optrule/OLAPProjectRule.java
index bee992b499..285c498a16 100644
--- a/query/src/main/java/org/apache/kylin/query/optrule/OLAPProjectRule.java
+++ b/query/src/main/java/org/apache/kylin/query/optrule/OLAPProjectRule.java
@@ -18,33 +18,52 @@
 
 package org.apache.kylin.query.optrule;
 
+import java.util.List;
+
+import org.apache.calcite.plan.Convention;
+import org.apache.calcite.plan.RelOptCluster;
 import org.apache.calcite.plan.RelOptRule;
-import org.apache.calcite.plan.RelOptRuleCall;
+import org.apache.calcite.plan.RelOptUtil;
 import org.apache.calcite.plan.RelTraitSet;
+import org.apache.calcite.rel.RelCollation;
+import org.apache.calcite.rel.RelCollationTraitDef;
+import org.apache.calcite.rel.RelNode;
+import org.apache.calcite.rel.convert.ConverterRule;
 import org.apache.calcite.rel.logical.LogicalProject;
+import org.apache.calcite.rel.metadata.RelMdCollation;
 import org.apache.kylin.query.relnode.OLAPProjectRel;
 import org.apache.kylin.query.relnode.OLAPRel;
 
+import com.google.common.base.Supplier;
+
 /**
  */
-public class OLAPProjectRule extends RelOptRule {
+public class OLAPProjectRule extends ConverterRule {
 
     public static final RelOptRule INSTANCE = new OLAPProjectRule();
 
     public OLAPProjectRule() {
-        super(operand(LogicalProject.class, any()));
+        super(LogicalProject.class, RelOptUtil.PROJECT_PREDICATE, 
Convention.NONE, OLAPRel.CONVENTION,
+                "OLAPProjectRule");
     }
 
     @Override
-    public void onMatch(RelOptRuleCall call) {
-        LogicalProject project = call.rel(0);
+    public RelNode convert(final RelNode rel) {
 
-        RelTraitSet origTraitSet = project.getTraitSet();
-        RelTraitSet traitSet = 
origTraitSet.replace(OLAPRel.CONVENTION).simplify();
-
-        OLAPProjectRel olapProj = new OLAPProjectRel(project.getCluster(), 
traitSet, //
-                convert(project.getInput(), traitSet), project.getProjects(), 
project.getRowType());
-        call.transformTo(olapProj);
+        //  KYLIN-3281
+        //  OLAPProjectRule can't normal working with projectRel[input=sortRel]
+        final LogicalProject project = (LogicalProject) rel;
+        final RelNode convertChild = convert(project.getInput(),
+                project.getInput().getTraitSet().replace(OLAPRel.CONVENTION));
+        final RelOptCluster cluster = convertChild.getCluster();
+        final RelTraitSet traitSet = 
cluster.traitSet().replace(OLAPRel.CONVENTION)
+                .replaceIfs(RelCollationTraitDef.INSTANCE, new 
Supplier<List<RelCollation>>() {
+                    public List<RelCollation> get() {
+                        //  CALCITE-88
+                        return 
RelMdCollation.project(cluster.getMetadataQuery(), convertChild, 
project.getProjects());
+                    }
+                });
+        return new OLAPProjectRel(convertChild.getCluster(), traitSet, 
convertChild, project.getProjects(),
+                project.getRowType());
     }
-
 }
diff --git 
a/query/src/main/java/org/apache/kylin/query/optrule/OLAPValuesRule.java 
b/query/src/main/java/org/apache/kylin/query/optrule/OLAPValuesRule.java
new file mode 100644
index 0000000000..4b06d4d863
--- /dev/null
+++ b/query/src/main/java/org/apache/kylin/query/optrule/OLAPValuesRule.java
@@ -0,0 +1,40 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.kylin.query.optrule;
+
+import org.apache.calcite.plan.Convention;
+import org.apache.calcite.rel.RelNode;
+import org.apache.calcite.rel.convert.ConverterRule;
+import org.apache.calcite.rel.logical.LogicalValues;
+import org.apache.kylin.query.relnode.OLAPRel;
+import org.apache.kylin.query.relnode.OLAPValuesRel;
+
+public class OLAPValuesRule extends ConverterRule {
+    public static final OLAPValuesRule INSTANCE = new OLAPValuesRule();
+
+    OLAPValuesRule() {
+        super(LogicalValues.class, Convention.NONE, OLAPRel.CONVENTION, 
"OLAPValuesRule");
+    }
+
+    @Override
+    public RelNode convert(RelNode rel) {
+        LogicalValues values = (LogicalValues) rel;
+        return OLAPValuesRel.create(values.getCluster(), values.getRowType(), 
values.getTuples());
+    }
+}
\ No newline at end of file
diff --git 
a/query/src/main/java/org/apache/kylin/query/optrule/OLAPWindowRule.java 
b/query/src/main/java/org/apache/kylin/query/optrule/OLAPWindowRule.java
index 74d1b106ba..4dc59c83dc 100644
--- a/query/src/main/java/org/apache/kylin/query/optrule/OLAPWindowRule.java
+++ b/query/src/main/java/org/apache/kylin/query/optrule/OLAPWindowRule.java
@@ -41,6 +41,8 @@ public RelNode convert(RelNode rel) {
         final Window window = (Window) rel;
         final RelTraitSet traitSet = 
window.getTraitSet().replace(OLAPRel.CONVENTION);
         final RelNode input = window.getInput();
-        return new OLAPWindowRel(rel.getCluster(), traitSet, convert(input, 
OLAPRel.CONVENTION), window.constants, window.getRowType(), window.groups);
+        return new OLAPWindowRel(rel.getCluster(), traitSet,
+                convert(input, 
input.getTraitSet().replace(OLAPRel.CONVENTION)), window.constants, 
window.getRowType(),
+                window.groups);
     }
 }
diff --git 
a/query/src/main/java/org/apache/kylin/query/relnode/OLAPProjectRel.java 
b/query/src/main/java/org/apache/kylin/query/relnode/OLAPProjectRel.java
index 78b0248c02..b0938bd66f 100644
--- a/query/src/main/java/org/apache/kylin/query/relnode/OLAPProjectRel.java
+++ b/query/src/main/java/org/apache/kylin/query/relnode/OLAPProjectRel.java
@@ -54,6 +54,7 @@
 import org.apache.calcite.sql.fun.SqlCaseOperator;
 import org.apache.calcite.sql.fun.SqlStdOperatorTable;
 import org.apache.calcite.sql.validate.SqlUserDefinedFunction;
+import org.apache.calcite.tools.RelUtils;
 import org.apache.kylin.metadata.model.TblColRef;
 import org.apache.kylin.metadata.model.TblColRef.InnerDataTypeEnum;
 
@@ -72,6 +73,7 @@
     boolean afterJoin;
     boolean afterAggregate;
     boolean isMerelyPermutation = false;//project additionally added by 
OLAPJoinPushThroughJoinRule
+    private int caseCount = 0;
 
     public OLAPProjectRel(RelOptCluster cluster, RelTraitSet traitSet, RelNode 
child, List<RexNode> exps,
             RelDataType rowType) {
@@ -82,6 +84,9 @@ public OLAPProjectRel(RelOptCluster cluster, RelTraitSet 
traitSet, RelNode child
         this.hasJoin = false;
         this.afterJoin = false;
         this.rowType = getRowType();
+        for (RexNode exp : exps) {
+                caseCount += 
RelUtils.countOperatorCall(SqlCaseOperator.INSTANCE, exp);
+        }
     }
 
     @Override
@@ -104,8 +109,10 @@ public OLAPProjectRel(RelOptCluster cluster, RelTraitSet 
traitSet, RelNode child
     @Override
     public RelOptCost computeSelfCost(RelOptPlanner planner, RelMetadataQuery 
mq) {
         boolean hasRexOver = RexOver.containsOver(getProjects(), null);
-        return super.computeSelfCost(planner, mq).multiplyBy(.05)
-                .multiplyBy(getProjects().size() * (hasRexOver ? 50 : 1));
+        RelOptCost relOptCost = super.computeSelfCost(planner, 
mq).multiplyBy(.05)
+                .multiplyBy(getProjects().size() * (hasRexOver ? 50 : 1))
+                .plus(planner.getCostFactory().makeCost(0.1 * caseCount, 0, 
0));
+        return planner.getCostFactory().makeCost(relOptCost.getRows(), 0, 0);
     }
 
     @Override
diff --git 
a/query/src/main/java/org/apache/kylin/query/relnode/OLAPTableScan.java 
b/query/src/main/java/org/apache/kylin/query/relnode/OLAPTableScan.java
index c557a9a977..67d3851fca 100644
--- a/query/src/main/java/org/apache/kylin/query/relnode/OLAPTableScan.java
+++ b/query/src/main/java/org/apache/kylin/query/relnode/OLAPTableScan.java
@@ -42,6 +42,7 @@
 import org.apache.calcite.plan.RelTrait;
 import org.apache.calcite.plan.RelTraitSet;
 import org.apache.calcite.plan.volcano.AbstractConverter.ExpandConversionRule;
+import org.apache.calcite.prepare.CalcitePrepareImpl;
 import org.apache.calcite.rel.RelNode;
 import org.apache.calcite.rel.RelWriter;
 import org.apache.calcite.rel.core.TableScan;
@@ -80,6 +81,7 @@
 import org.apache.kylin.query.optrule.OLAPSortRule;
 import org.apache.kylin.query.optrule.OLAPToEnumerableConverterRule;
 import org.apache.kylin.query.optrule.OLAPUnionRule;
+import org.apache.kylin.query.optrule.OLAPValuesRule;
 import org.apache.kylin.query.optrule.OLAPWindowRule;
 import org.apache.kylin.query.schema.OLAPSchema;
 import org.apache.kylin.query.schema.OLAPTable;
@@ -98,7 +100,7 @@
     private String backupAlias;
     protected ColumnRowType columnRowType;
     protected OLAPContext context;
-    private KylinConfig kylinConfig;
+    protected KylinConfig kylinConfig;
 
     public OLAPTableScan(RelOptCluster cluster, RelOptTable table, OLAPTable 
olapTable, int[] fields) {
         super(cluster, cluster.traitSetOf(OLAPRel.CONVENTION), table);
@@ -157,23 +159,30 @@ public void register(RelOptPlanner planner) {
         planner.addRule(OLAPSortRule.INSTANCE);
         planner.addRule(OLAPUnionRule.INSTANCE);
         planner.addRule(OLAPWindowRule.INSTANCE);
-
+        planner.addRule(OLAPValuesRule.INSTANCE);
+        
         // Support translate the grouping aggregate into union of simple 
aggregates
         planner.addRule(AggregateMultipleExpandRule.INSTANCE);
         planner.addRule(AggregateProjectReduceRule.INSTANCE);
 
         // CalcitePrepareImpl.CONSTANT_REDUCTION_RULES
-        planner.addRule(ReduceExpressionsRule.PROJECT_INSTANCE);
-        planner.addRule(ReduceExpressionsRule.FILTER_INSTANCE);
-        planner.addRule(ReduceExpressionsRule.CALC_INSTANCE);
-        planner.addRule(ReduceExpressionsRule.JOIN_INSTANCE);
+        if(kylinConfig.isReduceExpressionsRulesEnabled()) {
+            planner.addRule(ReduceExpressionsRule.PROJECT_INSTANCE);
+            planner.addRule(ReduceExpressionsRule.FILTER_INSTANCE);
+            planner.addRule(ReduceExpressionsRule.CALC_INSTANCE);
+            planner.addRule(ReduceExpressionsRule.JOIN_INSTANCE);
+        }
         // the ValuesReduceRule breaks query test somehow...
         //        planner.addRule(ValuesReduceRule.FILTER_INSTANCE);
         //        planner.addRule(ValuesReduceRule.PROJECT_FILTER_INSTANCE);
         //        planner.addRule(ValuesReduceRule.PROJECT_INSTANCE);
 
         removeRules(planner, kylinConfig.getCalciteRemoveRule());
-
+        if(!kylinConfig.isEnumerableRulesEnabled()) {
+            for (RelOptRule rule : CalcitePrepareImpl.ENUMERABLE_RULES) {
+                planner.removeRule(rule);
+            }
+        }
         // since join is the entry point, we can't push filter past join
         planner.removeRule(FilterJoinRule.FILTER_ON_JOIN);
         planner.removeRule(FilterJoinRule.JOIN);
@@ -203,7 +212,7 @@ public void register(RelOptPlanner planner) {
         planner.removeRule(ExpandConversionRule.INSTANCE);
     }
 
-    private void addRules(final RelOptPlanner planner, List<String> rules) {
+    protected void addRules(final RelOptPlanner planner, List<String> rules) {
         modifyRules(rules, new Function<RelOptRule, Void>() {
             @Nullable
             @Override
@@ -214,7 +223,7 @@ public Void apply(@Nullable RelOptRule input) {
         });
     }
 
-    private void removeRules(final RelOptPlanner planner, List<String> rules) {
+    protected void removeRules(final RelOptPlanner planner, List<String> 
rules) {
         modifyRules(rules, new Function<RelOptRule, Void>() {
             @Nullable
             @Override
diff --git 
a/query/src/main/java/org/apache/kylin/query/relnode/OLAPToEnumerableConverter.java
 
b/query/src/main/java/org/apache/kylin/query/relnode/OLAPToEnumerableConverter.java
index 89c9041812..ebfb6f446a 100644
--- 
a/query/src/main/java/org/apache/kylin/query/relnode/OLAPToEnumerableConverter.java
+++ 
b/query/src/main/java/org/apache/kylin/query/relnode/OLAPToEnumerableConverter.java
@@ -33,6 +33,7 @@
 import org.apache.calcite.rel.metadata.RelMetadataQuery;
 import org.apache.calcite.sql.SqlExplainLevel;
 import org.apache.kylin.common.KylinConfig;
+import org.apache.kylin.common.QueryContextFacade;
 import org.apache.kylin.common.util.ClassUtil;
 import org.apache.kylin.query.routing.RealizationChooser;
 import org.apache.kylin.query.security.QueryInterceptor;
@@ -58,7 +59,7 @@ public RelNode copy(RelTraitSet traitSet, List<RelNode> 
inputs) {
     @Override
     public RelOptCost computeSelfCost(RelOptPlanner planner, RelMetadataQuery 
mq) {
         // huge cost to ensure OLAPToEnumerableConverter only appears once in 
rel tree
-        return planner.getCostFactory().makeCost(1E100, 0, 0);
+        return super.computeSelfCost(planner, mq).multiplyBy(0.05);
     }
 
     @Override
@@ -77,9 +78,11 @@ public Result implement(EnumerableRelImplementor 
enumImplementor, Prefer pref) {
         List<OLAPContext> contexts = listContextsHavingScan();
 
         // intercept query
-        List<QueryInterceptor> intercepts = 
QueryInterceptorUtil.getQueryInterceptors();
-        for (QueryInterceptor intercept : intercepts) {
-            intercept.intercept(contexts);
+        if (contexts.size() > 0) {
+            List<QueryInterceptor> intercepts = 
QueryInterceptorUtil.getQueryInterceptors();
+            for (QueryInterceptor intercept : intercepts) {
+                intercept.intercept(contexts);
+            }
         }
 
         if (System.getProperty("calcite.debug") != null) {
@@ -105,6 +108,7 @@ public Result implement(EnumerableRelImplementor 
enumImplementor, Prefer pref) {
             String dumpPlan = RelOptUtil.dumpPlan("", this, false, 
SqlExplainLevel.DIGEST_ATTRIBUTES);
             System.out.println("EXECUTION PLAN AFTER REWRITE");
             System.out.println(dumpPlan);
+            
QueryContextFacade.current().setCalcitePlan(this.copy(getTraitSet(), 
getInputs()));
         }
 
         return impl.visitChild(this, 0, inputAsEnum, pref);
diff --git 
a/query/src/main/java/org/apache/kylin/query/relnode/OLAPUnionRel.java 
b/query/src/main/java/org/apache/kylin/query/relnode/OLAPUnionRel.java
index 5641d43462..4276449164 100644
--- a/query/src/main/java/org/apache/kylin/query/relnode/OLAPUnionRel.java
+++ b/query/src/main/java/org/apache/kylin/query/relnode/OLAPUnionRel.java
@@ -131,7 +131,7 @@ public EnumerableRel 
implementEnumerable(List<EnumerableRel> inputs) {
             }
             relInputs.add(input);
         }
-        return new EnumerableUnion(getCluster(), traitSet, relInputs, 
localAll);
+        return new EnumerableUnion(getCluster(), 
traitSet.replace(EnumerableConvention.INSTANCE), relInputs, localAll);
     }
 
     @Override
diff --git 
a/query/src/main/java/org/apache/kylin/query/relnode/OLAPValuesRel.java 
b/query/src/main/java/org/apache/kylin/query/relnode/OLAPValuesRel.java
new file mode 100644
index 0000000000..9bb05188de
--- /dev/null
+++ b/query/src/main/java/org/apache/kylin/query/relnode/OLAPValuesRel.java
@@ -0,0 +1,131 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.kylin.query.relnode;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import com.google.common.collect.Lists;
+import org.apache.calcite.adapter.enumerable.EnumerableRel;
+import org.apache.calcite.adapter.enumerable.EnumerableValues;
+import org.apache.calcite.plan.RelOptCluster;
+import org.apache.calcite.plan.RelOptCost;
+import org.apache.calcite.plan.RelOptPlanner;
+import org.apache.calcite.plan.RelTrait;
+import org.apache.calcite.plan.RelTraitSet;
+import org.apache.calcite.rel.RelCollation;
+import org.apache.calcite.rel.RelCollationTraitDef;
+import org.apache.calcite.rel.RelDistribution;
+import org.apache.calcite.rel.RelDistributionTraitDef;
+import org.apache.calcite.rel.RelNode;
+import org.apache.calcite.rel.core.Values;
+import org.apache.calcite.rel.metadata.RelMdCollation;
+import org.apache.calcite.rel.metadata.RelMdDistribution;
+import org.apache.calcite.rel.metadata.RelMetadataQuery;
+import org.apache.calcite.rel.type.RelDataType;
+import org.apache.calcite.rel.type.RelDataTypeField;
+import org.apache.calcite.rex.RexLiteral;
+
+import com.google.common.base.Supplier;
+import com.google.common.collect.ImmutableList;
+import org.apache.kylin.metadata.model.TblColRef;
+
+public class OLAPValuesRel extends Values implements OLAPRel {
+    OLAPContext context;
+    public OLAPValuesRel(RelOptCluster cluster, RelDataType rowType, 
ImmutableList<ImmutableList<RexLiteral>> tuples,
+            RelTraitSet traitSet) {
+        super(cluster, rowType, tuples, traitSet);
+    }
+
+    /** Creates an OLAPValuesRel. */
+    public static OLAPValuesRel create(RelOptCluster cluster, final 
RelDataType rowType,
+            final ImmutableList<ImmutableList<RexLiteral>> tuples) {
+        final RelMetadataQuery mq = cluster.getMetadataQuery();
+        final RelTraitSet traitSet = cluster.traitSetOf(OLAPRel.CONVENTION)
+                .replaceIfs(RelCollationTraitDef.INSTANCE, new 
Supplier<List<RelCollation>>() {
+                    public List<RelCollation> get() {
+                        return RelMdCollation.values(mq, rowType, tuples);
+                    }
+                }).replaceIf(RelDistributionTraitDef.INSTANCE, new 
Supplier<RelDistribution>() {
+                    public RelDistribution get() {
+                        return RelMdDistribution.values(rowType, tuples);
+                    }
+                });
+        return new OLAPValuesRel(cluster, rowType, tuples, traitSet);
+    }
+
+    @Override
+    public RelOptCost computeSelfCost(RelOptPlanner planner, RelMetadataQuery 
mq) {
+        RelOptCost relOptCost = super.computeSelfCost(planner, 
mq).multiplyBy(0.05);
+        return planner.getCostFactory().makeCost(relOptCost.getRows(), 0, 0);
+    }
+
+    @Override
+    public RelNode copy(RelTraitSet traitSet, List<RelNode> inputs) {
+        assert inputs.isEmpty();
+        return create(getCluster(), rowType, tuples);
+    }
+
+    @Override
+    public OLAPContext getContext() {
+        return context;
+    }
+
+    @Override
+    public ColumnRowType getColumnRowType() {
+        return buildColumnRowType();
+    }
+
+    ColumnRowType buildColumnRowType() {
+        ArrayList<TblColRef> colRefs = 
Lists.newArrayListWithCapacity(rowType.getFieldCount());
+        for(RelDataTypeField r:rowType.getFieldList()){
+            colRefs.add(TblColRef.newInnerColumn(r.getName(), 
TblColRef.InnerDataTypeEnum.LITERAL));
+        }
+        return new ColumnRowType(colRefs);
+    }
+
+    @Override
+    public boolean hasSubQuery() {
+        return false;
+    }
+
+    @Override
+    public RelTraitSet replaceTraitSet(RelTrait trait) {
+        RelTraitSet oldTraitSet = this.traitSet;
+        this.traitSet = this.traitSet.replace(trait);
+        return oldTraitSet;
+    }
+
+    @Override
+    public void implementOLAP(OLAPImplementor implementor) {
+        implementor.allocateContext();
+        this.context = implementor.getContext();
+
+    }
+
+    @Override
+    public void implementRewrite(RewriteImplementor rewriter) {
+
+    }
+
+    @Override
+    public EnumerableRel implementEnumerable(List<EnumerableRel> inputs) {
+        return EnumerableValues.create(getCluster(), getRowType(), 
getTuples());
+    }
+}
diff --git a/query/src/main/java/org/apache/kylin/query/util/QueryUtil.java 
b/query/src/main/java/org/apache/kylin/query/util/QueryUtil.java
index 4de6a2c337..055289578a 100644
--- a/query/src/main/java/org/apache/kylin/query/util/QueryUtil.java
+++ b/query/src/main/java/org/apache/kylin/query/util/QueryUtil.java
@@ -50,22 +50,29 @@ public static String massageSql(String sql, String project, 
int limit, int offse
         ProjectManager projectManager = 
ProjectManager.getInstance(KylinConfig.getInstanceFromEnv());
         ProjectInstance projectInstance = projectManager.getProject(project);
         KylinConfig kylinConfig = projectInstance.getConfig();
-
+        sql = removeCommentInSql(sql);
         while (sql.endsWith(";"))
             sql = sql.substring(0, sql.length() - 1);
 
-        if (limit > 0 && !sql.toLowerCase().contains("limit")) {
-            sql += ("\nLIMIT " + limit);
-        }
+        String sql1=sql;
+        final String suffixPattern = 
"^.+?\\s(limit\\s\\d+)?\\s(offset\\s\\d+)?\\s*$";
+        sql = sql.replaceAll("\\s+", " ");
+        Pattern pattern = Pattern.compile(suffixPattern);
+        Matcher matcher = pattern.matcher(sql.toLowerCase() + "  ");
 
-        if (offset > 0 && !sql.toLowerCase().contains("offset")) {
-            sql += ("\nOFFSET " + offset);
+        if (matcher.find()) {
+            if (limit > 0 && matcher.group(1) == null) {
+                sql1 += ("\nLIMIT " + limit);
+            }
+            if (offset > 0 && matcher.group(2) == null) {
+                sql1 += ("\nOFFSET " + offset);
+            }
         }
 
         // https://issues.apache.org/jira/browse/KYLIN-2649
-        if (kylinConfig.getForceLimit() > 0 && 
!sql.toLowerCase().contains("limit")
-                && sql.toLowerCase().matches("^select\\s+\\*\\p{all}*")) {
-            sql += ("\nLIMIT " + kylinConfig.getForceLimit());
+        if (kylinConfig.getForceLimit() > 0 && limit <= 0 && matcher.group(1) 
== null
+                && sql1.toLowerCase().matches("^select\\s+\\*\\p{all}*")) {
+            sql1 += ("\nLIMIT " + kylinConfig.getForceLimit());
         }
 
         // customizable SQL transformation
@@ -73,9 +80,9 @@ public static String massageSql(String sql, String project, 
int limit, int offse
             initQueryTransformers();
         }
         for (IQueryTransformer t : queryTransformers) {
-            sql = t.transform(sql, project, defaultSchema);
+            sql1 = t.transform(sql1, project, defaultSchema);
         }
-        return sql;
+        return sql1;
     }
 
     private static void initQueryTransformers() {
diff --git a/query/src/test/java/org/apache/kylin/query/util/QueryUtilTest.java 
b/query/src/test/java/org/apache/kylin/query/util/QueryUtilTest.java
index 01c2f7f113..4d766b9e33 100644
--- a/query/src/test/java/org/apache/kylin/query/util/QueryUtilTest.java
+++ b/query/src/test/java/org/apache/kylin/query/util/QueryUtilTest.java
@@ -51,6 +51,58 @@ public void testMassageSql() {
                     "select ( date '2001-09-28' + interval '2' month) from 
test_kylin_fact group by ( date '2001-09-28' + interval '2' month)",
                     s);
         }
+        {
+            String sql = "select count(*) test_limit from test_kylin_fact 
where price > 10.0";
+            String s = QueryUtil.massageSql(sql, "default", 50000, 0, 
"DEFAULT");
+            Assert.assertEquals(
+                    "select count(*) test_limit from test_kylin_fact where 
price > 10.0\n" +
+                            "LIMIT 50000",
+                    s);
+        }
+        {
+            String sql = "select count(*) test_offset from test_kylin_fact 
where price > 10.0";
+            String s = QueryUtil.massageSql(sql, "default", 0, 50, "DEFAULT");
+            Assert.assertEquals(
+                    "select count(*) test_offset from test_kylin_fact where 
price > 10.0\n" +
+                            "OFFSET 50",
+                    s);
+        }
+        {
+            String sql = "select count(*) test_limit_and_offset from 
test_kylin_fact where price > 10.0";
+            String s = QueryUtil.massageSql(sql, "default", 50000, 50, 
"DEFAULT");
+            Assert.assertEquals(
+                    "select count(*) test_limit_and_offset from 
test_kylin_fact where price > 10.0\n" +
+                            "LIMIT 50000\nOFFSET 50",
+                    s);
+        }
+
+        {
+            String newLine = System.getProperty("line.separator");
+            String sql = "select count(*)     test_limit from " + newLine + 
"test_kylin_fact where price > 10.0";
+            newLine = newLine.replace("\r", " ").replace("\n", newLine);
+            String s = QueryUtil.massageSql(sql, "default", 50000, 0, 
"DEFAULT");
+            Assert.assertEquals(
+                    "select count(*)     test_limit from " + newLine + 
"test_kylin_fact where price > 10.0\nLIMIT 50000",
+                    s);
+        }
+        {
+            String newLine = System.getProperty("line.separator");
+            String sql = "select count(*)     test_offset from " + newLine + 
"test_kylin_fact where price > 10.0";
+            newLine = newLine.replace("\r", " ").replace("\n", newLine);
+            String s = QueryUtil.massageSql(sql, "default", 50000, 0, 
"DEFAULT");
+            Assert.assertEquals(
+                    "select count(*)     test_offset from " + newLine + 
"test_kylin_fact where price > 10.0\nLIMIT 50000",
+                    s);
+        }
+        {
+            String newLine = System.getProperty("line.separator");
+            String sql = "select count(*)     test_limit_and_offset from " + 
newLine + "test_kylin_fact where price > 10.0";
+            newLine = newLine.replace("\r", " ").replace("\n", newLine);
+            String s = QueryUtil.massageSql(sql, "default", 50000, 0, 
"DEFAULT");
+            Assert.assertEquals(
+                    "select count(*)     test_limit_and_offset from " + 
newLine + "test_kylin_fact where price > 10.0\nLIMIT 50000",
+                    s);
+        }
     }
 
     @Test
diff --git 
a/server-base/src/main/java/org/apache/kylin/rest/request/PrepareSqlRequest.java
 
b/server-base/src/main/java/org/apache/kylin/rest/request/PrepareSqlRequest.java
index e2962483a2..97a486326a 100644
--- 
a/server-base/src/main/java/org/apache/kylin/rest/request/PrepareSqlRequest.java
+++ 
b/server-base/src/main/java/org/apache/kylin/rest/request/PrepareSqlRequest.java
@@ -19,7 +19,9 @@
 package org.apache.kylin.rest.request;
 
 import java.io.Serializable;
+import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Collections;
 
 /**
  * @author xduo
@@ -41,7 +43,7 @@ public void setParams(StateParam[] params) {
         this.params = params;
     }
 
-    public static class StateParam implements Serializable{
+    public static class StateParam implements Serializable {
         private String className;
         private String value;
 
@@ -96,6 +98,20 @@ public boolean equals(Object obj) {
         }
     }
 
+    @Override
+    public Object getCacheKey() {
+        if (cacheKey != null)
+            return cacheKey;
+
+        cacheKey = super.getCacheKey();
+
+        if (params != null) {
+            ArrayList keyList = (ArrayList) (cacheKey);
+            Collections.addAll(keyList, params);
+        }
+        return cacheKey;
+    }
+
     @Override
     public int hashCode() {
         final int prime = 31;
diff --git 
a/server-base/src/main/java/org/apache/kylin/rest/request/SQLRequest.java 
b/server-base/src/main/java/org/apache/kylin/rest/request/SQLRequest.java
index 92533b8e77..56db74551c 100644
--- a/server-base/src/main/java/org/apache/kylin/rest/request/SQLRequest.java
+++ b/server-base/src/main/java/org/apache/kylin/rest/request/SQLRequest.java
@@ -39,7 +39,7 @@
 
     private Map<String, String> backdoorToggles;
 
-    private volatile Object cacheKey = null;
+    protected volatile Object cacheKey = null;
 
     public SQLRequest() {
     }
diff --git 
a/server-base/src/main/java/org/apache/kylin/rest/security/PasswordPlaceholderConfigurer.java
 
b/server-base/src/main/java/org/apache/kylin/rest/security/PasswordPlaceholderConfigurer.java
index 095b74a37a..0a8e84745a 100644
--- 
a/server-base/src/main/java/org/apache/kylin/rest/security/PasswordPlaceholderConfigurer.java
+++ 
b/server-base/src/main/java/org/apache/kylin/rest/security/PasswordPlaceholderConfigurer.java
@@ -26,13 +26,10 @@
 import java.nio.charset.Charset;
 import java.util.Properties;
 
-import javax.crypto.Cipher;
-import javax.crypto.spec.SecretKeySpec;
-
-import org.apache.commons.codec.binary.Base64;
 import org.apache.commons.io.IOUtils;
 import org.apache.kylin.common.KylinConfig;
 import org.apache.kylin.common.KylinConfigBase;
+import org.apache.kylin.common.util.EncryptUtil;
 import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer;
 import org.springframework.core.io.InputStreamResource;
 import org.springframework.core.io.Resource;
@@ -44,11 +41,6 @@
  */
 public class PasswordPlaceholderConfigurer extends 
PropertyPlaceholderConfigurer {
 
-    /**
-     * thisIsAsecretKey
-     */
-    private static byte[] key = { 0x74, 0x68, 0x69, 0x73, 0x49, 0x73, 0x41, 
0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x4b, 0x65, 0x79 };
-
     /**
      * The PasswordPlaceholderConfigurer will read Kylin properties as the 
Spring resource
      */
@@ -79,40 +71,17 @@ public Properties getAllKylinProperties() {
         return allProps;
     }
 
-    public static String encrypt(String strToEncrypt) {
-        try {
-            Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
-            final SecretKeySpec secretKey = new SecretKeySpec(key, "AES");
-            cipher.init(Cipher.ENCRYPT_MODE, secretKey);
-            final String encryptedString = 
Base64.encodeBase64String(cipher.doFinal(strToEncrypt.getBytes()));
-            return encryptedString;
-        } catch (Exception e) {
-            throw new RuntimeException(e.getMessage(), e);
-        }
-    }
-
-    public static String decrypt(String strToDecrypt) {
-        try {
-            Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5PADDING");
-            final SecretKeySpec secretKey = new SecretKeySpec(key, "AES");
-            cipher.init(Cipher.DECRYPT_MODE, secretKey);
-            final String decryptedString = new 
String(cipher.doFinal(Base64.decodeBase64(strToDecrypt)));
-            return decryptedString;
-        } catch (Exception e) {
-            throw new RuntimeException(e.getMessage(), e);
-        }
-    }
-
     protected String resolvePlaceholder(String placeholder, Properties props) {
         if (placeholder.toLowerCase().contains("password")) {
-            return decrypt(props.getProperty(placeholder));
+            return EncryptUtil.decrypt(props.getProperty(placeholder));
         } else {
             return props.getProperty(placeholder);
         }
     }
 
     private static void printUsage() {
-        System.out.println("Usage: java 
org.apache.kylin.rest.security.PasswordPlaceholderConfigurer <EncryptMethod> 
<your_password>");
+        System.out.println(
+                "Usage: java 
org.apache.kylin.rest.security.PasswordPlaceholderConfigurer <EncryptMethod> 
<your_password>");
         System.out.println("EncryptMethod: AES or BCrypt");
     }
 
@@ -127,7 +96,7 @@ public static void main(String[] args) {
         if ("AES".equalsIgnoreCase(encryptMethod)) {
             // for encrypt password like LDAP password
             System.out.println(encryptMethod + " encrypted password is: ");
-            System.out.println(encrypt(passwordTxt));
+            System.out.println(EncryptUtil.encrypt(passwordTxt));
         } else if ("BCrypt".equalsIgnoreCase(encryptMethod)) {
             // for encrypt the predefined user password, like ADMIN, MODELER.
             BCryptPasswordEncoder bCryptPasswordEncoder = new 
BCryptPasswordEncoder();
diff --git 
a/server-base/src/main/java/org/apache/kylin/rest/service/AdminService.java 
b/server-base/src/main/java/org/apache/kylin/rest/service/AdminService.java
index 70afefdce7..f7881f141c 100644
--- a/server-base/src/main/java/org/apache/kylin/rest/service/AdminService.java
+++ b/server-base/src/main/java/org/apache/kylin/rest/service/AdminService.java
@@ -93,7 +93,7 @@ public void cleanupStorage() {
         try {
             job = new StorageCleanupJob();
         } catch (IOException e) {
-            logger.error("can not init StorageCleanupJob", e);
+            throw new RuntimeException("Can not init StorageCleanupJob", e);
         }
         String[] args = new String[] { "-delete", "true" };
         job.execute(args);
diff --git a/webapp/app/partials/cubes/cube_delete_segment.html 
b/webapp/app/partials/cubes/cube_delete_segment.html
index 8500f3f7a9..93356eeeae 100644
--- a/webapp/app/partials/cubes/cube_delete_segment.html
+++ b/webapp/app/partials/cubes/cube_delete_segment.html
@@ -83,7 +83,7 @@ <h4 tooltip="refresh">CUBE SEGMENT DELETE CONFIRM</h4>
 
     <div class="modal-footer">
         <button class="btn btn-primary" ng-click="cancel()">Close</button>
-        <button class="btn btn-success" ng-click="deleteSegment()">Delete
+        <button class="btn btn-success" ng-click="deleteSegment()" 
ng-disabled="!(cube.segments && cube.segments.length > 0)">Delete
         </button>
     </div>
 </script>
\ No newline at end of file


 

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
[email protected]


With regards,
Apache Git Services

Reply via email to