drill-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From j..@apache.org
Subject [15/27] drill git commit: DRILL-5301: Server metadata API
Date Thu, 02 Mar 2017 20:59:42 GMT
DRILL-5301: Server metadata API

Add a Server metadata API to the User protocol, to query server support
of various SQL features.

Add support to the client (DrillClient) to query this information.

Add support to the JDBC driver to query this information, if the server supports
the new API, or fallback to the previous behaviour (rely on Avatica defaults) otherwise.

close #764


Project: http://git-wip-us.apache.org/repos/asf/drill/repo
Commit: http://git-wip-us.apache.org/repos/asf/drill/commit/d2e0f415
Tree: http://git-wip-us.apache.org/repos/asf/drill/tree/d2e0f415
Diff: http://git-wip-us.apache.org/repos/asf/drill/diff/d2e0f415

Branch: refs/heads/master
Commit: d2e0f415c9cbaf609805708586832b6771883f53
Parents: 17f888d
Author: Laurent Goujon <laurent@dremio.com>
Authored: Fri Feb 24 15:41:07 2017 -0800
Committer: Jinfeng Ni <jni@apache.org>
Committed: Wed Mar 1 23:15:32 2017 -0800

----------------------------------------------------------------------
 .../apache/drill/exec/client/DrillClient.java   |    15 +
 .../apache/drill/exec/client/ServerMethod.java  |     9 +-
 .../exec/planner/sql/DrillParserConfig.java     |    65 +
 .../drill/exec/planner/sql/SqlConverter.java    |    53 +-
 .../drill/exec/resolver/TypeCastRules.java      |    67 +-
 .../apache/drill/exec/rpc/user/UserClient.java  |     3 +
 .../drill/exec/rpc/user/UserRpcConfig.java      |     5 +-
 .../drill/exec/rpc/user/UserRpcUtils.java       |    28 +-
 .../apache/drill/exec/rpc/user/UserServer.java  |    16 +-
 .../exec/rpc/user/UserServerRequestHandler.java |    20 +-
 .../exec/work/metadata/MetadataProvider.java    |     2 +-
 .../exec/work/metadata/ServerMetaProvider.java  |   168 +
 .../apache/drill/exec/work/user/UserWorker.java |     7 +
 .../work/metadata/TestServerMetaProvider.java   |    48 +
 .../drill/jdbc/DrillConnectionConfig.java       |     5 +-
 .../jdbc/impl/DrillDatabaseMetaDataImpl.java    |   456 +-
 .../drill/jdbc/impl/DrillJdbc41Factory.java     |     4 +-
 .../apache/drill/jdbc/impl/DrillMetaImpl.java   |     8 +-
 .../common/expression/fn/CastFunctions.java     |     3 +-
 .../drill/exec/proto/SchemaUserProtos.java      |   800 +
 .../org/apache/drill/exec/proto/UserProtos.java | 47067 ++++++++++-------
 .../drill/exec/proto/beans/CollateSupport.java  |    49 +
 .../drill/exec/proto/beans/ConvertSupport.java  |   199 +
 .../proto/beans/CorrelationNamesSupport.java    |    51 +
 .../proto/beans/DateTimeLiteralsSupport.java    |    79 +
 .../exec/proto/beans/GetServerMetaResp.java     |   211 +
 .../drill/exec/proto/beans/GroupBySupport.java  |    53 +
 .../exec/proto/beans/IdentifierCasing.java      |    55 +
 .../drill/exec/proto/beans/NullCollation.java   |    55 +
 .../drill/exec/proto/beans/OrderBySupport.java  |    51 +
 .../exec/proto/beans/OuterJoinSupport.java      |    61 +
 .../apache/drill/exec/proto/beans/RpcType.java  |     8 +-
 .../drill/exec/proto/beans/ServerMeta.java      |  1319 +
 .../drill/exec/proto/beans/SubQuerySupport.java |    57 +
 .../drill/exec/proto/beans/UnionSupport.java    |    51 +
 protocol/src/main/protobuf/User.proto           |   219 +-
 36 files changed, 33484 insertions(+), 17883 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/drill/blob/d2e0f415/exec/java-exec/src/main/java/org/apache/drill/exec/client/DrillClient.java
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/client/DrillClient.java b/exec/java-exec/src/main/java/org/apache/drill/exec/client/DrillClient.java
index 0b5bf30..0ff6a5b 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/client/DrillClient.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/client/DrillClient.java
@@ -64,6 +64,8 @@ import org.apache.drill.exec.proto.UserProtos.GetColumnsResp;
 import org.apache.drill.exec.proto.UserProtos.GetQueryPlanFragments;
 import org.apache.drill.exec.proto.UserProtos.GetSchemasReq;
 import org.apache.drill.exec.proto.UserProtos.GetSchemasResp;
+import org.apache.drill.exec.proto.UserProtos.GetServerMetaReq;
+import org.apache.drill.exec.proto.UserProtos.GetServerMetaResp;
 import org.apache.drill.exec.proto.UserProtos.GetTablesReq;
 import org.apache.drill.exec.proto.UserProtos.GetTablesResp;
 import org.apache.drill.exec.proto.UserProtos.LikeFilter;
@@ -509,6 +511,19 @@ public class DrillClient implements Closeable, ConnectionThrottle {
   public Version getServerVersion() {
     return (client != null && client.getServerInfos() != null) ? UserRpcUtils.getVersion(client.getServerInfos()) : null;
   }
+
+  /**
+   * Get server meta information
+   *
+   * Get meta information about the server like the the available functions
+   * or the identifier quoting string used by the current session
+   *
+   * @return a future to the server meta response
+   */
+  public DrillRpcFuture<GetServerMetaResp> getServerMeta() {
+    return client.send(RpcType.GET_SERVER_META, GetServerMetaReq.getDefaultInstance(), GetServerMetaResp.class);
+  }
+
   /**
    * Returns the list of methods supported by the server based on its advertised information.
    *

http://git-wip-us.apache.org/repos/asf/drill/blob/d2e0f415/exec/java-exec/src/main/java/org/apache/drill/exec/client/ServerMethod.java
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/client/ServerMethod.java b/exec/java-exec/src/main/java/org/apache/drill/exec/client/ServerMethod.java
index 5c6640d..5896df2 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/client/ServerMethod.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/client/ServerMethod.java
@@ -80,12 +80,17 @@ public enum ServerMethod {
   /**
    * Get columns metadata
    */
-  GET_COLUMNS(RpcType.GET_COLUMNS, Constants.DRILL_1_8_0);
+  GET_COLUMNS(RpcType.GET_COLUMNS, Constants.DRILL_1_8_0),
+
+  /**
+   * Get server metadata
+   */
+  SERVER_META(RpcType.SERVER_META, Constants.DRILL_1_10_0);
 
   private static class Constants {
     private static final Version DRILL_0_0_0 = new Version("0.0.0", 0, 0, 0, 0, "");
-
     private static final Version DRILL_1_8_0 = new Version("1.8.0", 1, 8, 0, 0, "");
+    private static final Version DRILL_1_10_0 = new Version("1.10.0", 1, 10, 0, 0, "");
   }
 
   private static final Map<RpcType, ServerMethod> REVERSE_MAPPING;

http://git-wip-us.apache.org/repos/asf/drill/blob/d2e0f415/exec/java-exec/src/main/java/org/apache/drill/exec/planner/sql/DrillParserConfig.java
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/planner/sql/DrillParserConfig.java b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/sql/DrillParserConfig.java
new file mode 100644
index 0000000..7e7b140
--- /dev/null
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/sql/DrillParserConfig.java
@@ -0,0 +1,65 @@
+/*
+ * 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.drill.exec.planner.sql;
+
+import org.apache.calcite.avatica.util.Casing;
+import org.apache.calcite.avatica.util.Quoting;
+import org.apache.calcite.sql.parser.SqlParser;
+import org.apache.calcite.sql.parser.SqlParserImplFactory;
+import org.apache.drill.exec.planner.physical.PlannerSettings;
+import org.apache.drill.exec.planner.sql.parser.impl.DrillParserWithCompoundIdConverter;
+
+public class DrillParserConfig implements SqlParser.Config {
+
+  private final long identifierMaxLength;
+
+  public DrillParserConfig(PlannerSettings settings) {
+    identifierMaxLength = settings.getIdentifierMaxLength();
+  }
+
+  @Override
+  public int identifierMaxLength() {
+    return (int) identifierMaxLength;
+  }
+
+  @Override
+  public Casing quotedCasing() {
+    return Casing.UNCHANGED;
+  }
+
+  @Override
+  public Casing unquotedCasing() {
+    return Casing.UNCHANGED;
+  }
+
+  @Override
+  public Quoting quoting() {
+    return Quoting.BACK_TICK;
+  }
+
+  @Override
+  public boolean caseSensitive() {
+    return false;
+  }
+
+  @Override
+  public SqlParserImplFactory parserFactory() {
+    return DrillParserWithCompoundIdConverter.FACTORY;
+  }
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/drill/blob/d2e0f415/exec/java-exec/src/main/java/org/apache/drill/exec/planner/sql/SqlConverter.java
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/planner/sql/SqlConverter.java b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/sql/SqlConverter.java
index 3e3226d..e9085f7 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/planner/sql/SqlConverter.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/sql/SqlConverter.java
@@ -21,11 +21,7 @@ import java.util.Arrays;
 import java.util.List;
 import java.util.Set;
 
-import com.google.common.collect.Lists;
-import com.google.common.collect.Sets;
 import org.apache.calcite.adapter.java.JavaTypeFactory;
-import org.apache.calcite.avatica.util.Casing;
-import org.apache.calcite.avatica.util.Quoting;
 import org.apache.calcite.jdbc.CalciteSchema;
 import org.apache.calcite.jdbc.CalciteSchemaImpl;
 import org.apache.calcite.jdbc.JavaTypeFactoryImpl;
@@ -48,7 +44,6 @@ import org.apache.calcite.sql.SqlNode;
 import org.apache.calcite.sql.SqlOperatorTable;
 import org.apache.calcite.sql.parser.SqlParseException;
 import org.apache.calcite.sql.parser.SqlParser;
-import org.apache.calcite.sql.parser.SqlParserImplFactory;
 import org.apache.calcite.sql.parser.SqlParserPos;
 import org.apache.calcite.sql.type.SqlTypeName;
 import org.apache.calcite.sql.util.ChainedSqlOperatorTable;
@@ -63,8 +58,8 @@ import org.apache.commons.lang3.StringUtils;
 import org.apache.commons.lang3.exception.ExceptionUtils;
 import org.apache.drill.common.config.DrillConfig;
 import org.apache.drill.common.exceptions.UserException;
-import org.apache.drill.exec.exception.FunctionNotFoundException;
 import org.apache.drill.exec.ExecConstants;
+import org.apache.drill.exec.exception.FunctionNotFoundException;
 import org.apache.drill.exec.expr.fn.FunctionImplementationRegistry;
 import org.apache.drill.exec.ops.QueryContext;
 import org.apache.drill.exec.ops.UdfUtilities;
@@ -72,10 +67,11 @@ import org.apache.drill.exec.planner.cost.DrillCostBase;
 import org.apache.drill.exec.planner.logical.DrillConstExecutor;
 import org.apache.drill.exec.planner.physical.DrillDistributionTraitDef;
 import org.apache.drill.exec.planner.physical.PlannerSettings;
-import org.apache.drill.exec.planner.sql.parser.impl.DrillParserWithCompoundIdConverter;
+import org.apache.drill.exec.rpc.user.UserSession;
 
 import com.google.common.base.Joiner;
-import org.apache.drill.exec.rpc.user.UserSession;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Sets;
 
 /**
  * Class responsible for managing parsing, validation and toRel conversion for sql statements.
@@ -109,9 +105,9 @@ public class SqlConverter {
 
   public SqlConverter(QueryContext context) {
     this.settings = context.getPlannerSettings();
-    this.util = (UdfUtilities) context;
+    this.util = context;
     this.functions = context.getFunctionRegistry();
-    this.parserConfig = new ParserConfig();
+    this.parserConfig = new DrillParserConfig(settings);
     this.sqlToRelConverterConfig = new SqlToRelConverterConfig();
     this.isInnerQuery = false;
     this.typeFactory = new JavaTypeFactoryImpl(DRILL_TYPE_SYSTEM);
@@ -290,6 +286,7 @@ public class SqlConverter {
     public Expander() {
     }
 
+    @Override
     public RelNode expandView(RelDataType rowType, String queryString, List<String> schemaPath) {
       final DrillCalciteCatalogReader catalogReader = new DrillCalciteCatalogReader(
           CalciteSchemaImpl.from(rootSchema),
@@ -341,42 +338,6 @@ public class SqlConverter {
 
   }
 
-  private class ParserConfig implements SqlParser.Config {
-
-    final long identifierMaxLength = settings.getIdentifierMaxLength();
-
-    @Override
-    public int identifierMaxLength() {
-      return (int) identifierMaxLength;
-    }
-
-    @Override
-    public Casing quotedCasing() {
-      return Casing.UNCHANGED;
-    }
-
-    @Override
-    public Casing unquotedCasing() {
-      return Casing.UNCHANGED;
-    }
-
-    @Override
-    public Quoting quoting() {
-      return Quoting.BACK_TICK;
-    }
-
-    @Override
-    public boolean caseSensitive() {
-      return false;
-    }
-
-    @Override
-    public SqlParserImplFactory parserFactory() {
-      return DrillParserWithCompoundIdConverter.FACTORY;
-    }
-
-  }
-
   private class SqlToRelConverterConfig implements SqlToRelConverter.Config {
 
     final int inSubqueryThreshold = (int)settings.getInSubqueryThreshold();

http://git-wip-us.apache.org/repos/asf/drill/blob/d2e0f415/exec/java-exec/src/main/java/org/apache/drill/exec/resolver/TypeCastRules.java
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/resolver/TypeCastRules.java b/exec/java-exec/src/main/java/org/apache/drill/exec/resolver/TypeCastRules.java
index 8bb6c2a..78a4509 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/resolver/TypeCastRules.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/resolver/TypeCastRules.java
@@ -24,10 +24,8 @@ import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
-import com.google.common.collect.Lists;
-import com.google.common.collect.Sets;
-import org.apache.drill.common.expression.MajorTypeInLogicalExpression;
 import org.apache.drill.common.expression.LogicalExpression;
+import org.apache.drill.common.expression.MajorTypeInLogicalExpression;
 import org.apache.drill.common.types.TypeProtos.DataMode;
 import org.apache.drill.common.types.TypeProtos.MajorType;
 import org.apache.drill.common.types.TypeProtos.MinorType;
@@ -35,6 +33,9 @@ import org.apache.drill.exec.expr.annotations.FunctionTemplate.NullHandling;
 import org.apache.drill.exec.expr.fn.DrillFuncHolder;
 import org.apache.drill.exec.util.DecimalUtility;
 
+import com.google.common.collect.Lists;
+import com.google.common.collect.Sets;
+
 public class TypeCastRules {
 
   private static Map<MinorType, Set<MinorType>> rules;
@@ -47,12 +48,12 @@ public class TypeCastRules {
   }
 
   private static void initTypeRules() {
-    rules = new HashMap<MinorType, Set<MinorType>>();
+    rules = new HashMap<>();
 
     Set<MinorType> rule;
 
     /** TINYINT cast able from **/
-    rule = new HashSet<MinorType>();
+    rule = new HashSet<>();
     rule.add(MinorType.TINYINT);
     rule.add(MinorType.SMALLINT);
     rule.add(MinorType.INT);
@@ -80,7 +81,7 @@ public class TypeCastRules {
     rules.put(MinorType.TINYINT, rule);
 
     /** SMALLINT cast able from **/
-    rule = new HashSet<MinorType>();
+    rule = new HashSet<>();
     rule.add(MinorType.TINYINT);
     rule.add(MinorType.SMALLINT);
     rule.add(MinorType.INT);
@@ -108,7 +109,7 @@ public class TypeCastRules {
     rules.put(MinorType.SMALLINT, rule);
 
     /** INT cast able from **/
-    rule = new HashSet<MinorType>();
+    rule = new HashSet<>();
     rule.add(MinorType.TINYINT);
     rule.add(MinorType.SMALLINT);
     rule.add(MinorType.INT);
@@ -136,7 +137,7 @@ public class TypeCastRules {
     rules.put(MinorType.INT, rule);
 
     /** BIGINT cast able from **/
-    rule = new HashSet<MinorType>();
+    rule = new HashSet<>();
     rule.add(MinorType.TINYINT);
     rule.add(MinorType.SMALLINT);
     rule.add(MinorType.INT);
@@ -164,7 +165,7 @@ public class TypeCastRules {
     rules.put(MinorType.BIGINT, rule);
 
     /** UINT8 cast able from **/
-    rule = new HashSet<MinorType>();
+    rule = new HashSet<>();
     rule.add(MinorType.TINYINT);
     rule.add(MinorType.SMALLINT);
     rule.add(MinorType.INT);
@@ -192,7 +193,7 @@ public class TypeCastRules {
     rules.put(MinorType.UINT8, rule);
 
     /** DECIMAL9 cast able from **/
-    rule = new HashSet<MinorType>();
+    rule = new HashSet<>();
     rule.add(MinorType.TINYINT);
     rule.add(MinorType.SMALLINT);
     rule.add(MinorType.INT);
@@ -220,7 +221,7 @@ public class TypeCastRules {
     rules.put(MinorType.DECIMAL9, rule);
 
     /** DECIMAL18 cast able from **/
-    rule = new HashSet<MinorType>();
+    rule = new HashSet<>();
     rule.add(MinorType.TINYINT);
     rule.add(MinorType.SMALLINT);
     rule.add(MinorType.INT);
@@ -248,7 +249,7 @@ public class TypeCastRules {
     rules.put(MinorType.DECIMAL18, rule);
 
     /** DECIMAL28Dense cast able from **/
-    rule = new HashSet<MinorType>();
+    rule = new HashSet<>();
     rule.add(MinorType.TINYINT);
     rule.add(MinorType.SMALLINT);
     rule.add(MinorType.INT);
@@ -276,7 +277,7 @@ public class TypeCastRules {
     rules.put(MinorType.DECIMAL28DENSE, rule);
 
     /** DECIMAL28Sparse cast able from **/
-    rule = new HashSet<MinorType>();
+    rule = new HashSet<>();
     rule.add(MinorType.TINYINT);
     rule.add(MinorType.SMALLINT);
     rule.add(MinorType.INT);
@@ -304,7 +305,7 @@ public class TypeCastRules {
     rules.put(MinorType.DECIMAL28SPARSE, rule);
 
     /** DECIMAL38Dense cast able from **/
-    rule = new HashSet<MinorType>();
+    rule = new HashSet<>();
     rule.add(MinorType.TINYINT);
     rule.add(MinorType.SMALLINT);
     rule.add(MinorType.INT);
@@ -333,7 +334,7 @@ public class TypeCastRules {
 
 
     /** DECIMAL38Sparse cast able from **/
-    rule = new HashSet<MinorType>();
+    rule = new HashSet<>();
     rule.add(MinorType.TINYINT);
     rule.add(MinorType.SMALLINT);
     rule.add(MinorType.INT);
@@ -361,7 +362,7 @@ public class TypeCastRules {
     rules.put(MinorType.DECIMAL38SPARSE, rule);
 
     /** MONEY cast able from **/
-    rule = new HashSet<MinorType>();
+    rule = new HashSet<>();
     rule.add(MinorType.TINYINT);
     rule.add(MinorType.SMALLINT);
     rule.add(MinorType.INT);
@@ -389,7 +390,7 @@ public class TypeCastRules {
     rules.put(MinorType.MONEY, rule);
 
     /** DATE cast able from **/
-    rule = new HashSet<MinorType>();
+    rule = new HashSet<>();
     rule.add(MinorType.DATE);
     rule.add(MinorType.TIMESTAMP);
     rule.add(MinorType.TIMESTAMPTZ);
@@ -402,7 +403,7 @@ public class TypeCastRules {
     rules.put(MinorType.DATE, rule);
 
     /** TIME cast able from **/
-    rule = new HashSet<MinorType>();
+    rule = new HashSet<>();
     rule.add(MinorType.TIME);
     rule.add(MinorType.TIMESTAMP);
     rule.add(MinorType.TIMESTAMPTZ);
@@ -415,7 +416,7 @@ public class TypeCastRules {
     rules.put(MinorType.TIME, rule);
 
     /** TIMESTAMP cast able from **/
-    rule = new HashSet<MinorType>();
+    rule = new HashSet<>();
     rule.add(MinorType.VAR16CHAR);
     rule.add(MinorType.VARCHAR);
     rule.add(MinorType.VARBINARY);
@@ -433,7 +434,7 @@ public class TypeCastRules {
     rules.put(MinorType.TIMESTAMP, rule);
 
     /** TIMESTAMPTZ cast able from **/
-    rule = new HashSet<MinorType>();
+    rule = new HashSet<>();
     rule.add(MinorType.TIMESTAMPTZ);
     rule.add(MinorType.DATE);
     rule.add(MinorType.TIMESTAMP);
@@ -447,7 +448,7 @@ public class TypeCastRules {
     rules.put(MinorType.TIMESTAMPTZ, rule);
 
     /** Interval cast able from **/
-    rule = new HashSet<MinorType>();
+    rule = new HashSet<>();
     rule.add(MinorType.INTERVAL);
     rule.add(MinorType.INTERVALDAY);
     rule.add(MinorType.INTERVALYEAR);
@@ -463,7 +464,7 @@ public class TypeCastRules {
     rules.put(MinorType.INTERVAL, rule);
 
     /** INTERVAL YEAR cast able from **/
-    rule = new HashSet<MinorType>();
+    rule = new HashSet<>();
     rule.add(MinorType.INTERVALYEAR);
     rule.add(MinorType.INTERVAL);
     rule.add(MinorType.INTERVALDAY);
@@ -479,7 +480,7 @@ public class TypeCastRules {
     rules.put(MinorType.INTERVALYEAR, rule);
 
     /** INTERVAL DAY cast able from **/
-    rule = new HashSet<MinorType>();
+    rule = new HashSet<>();
     rule.add(MinorType.INTERVALDAY);
     rule.add(MinorType.INTERVALYEAR);
     rule.add(MinorType.INTERVAL);
@@ -495,7 +496,7 @@ public class TypeCastRules {
     rules.put(MinorType.INTERVALDAY, rule);
 
     /** FLOAT4 cast able from **/
-    rule = new HashSet<MinorType>();
+    rule = new HashSet<>();
     rule.add(MinorType.TINYINT);
     rule.add(MinorType.SMALLINT);
     rule.add(MinorType.INT);
@@ -520,7 +521,7 @@ public class TypeCastRules {
     rules.put(MinorType.FLOAT4, rule);
 
     /** FLOAT8 cast able from **/
-    rule = new HashSet<MinorType>();
+    rule = new HashSet<>();
     rule.add(MinorType.TINYINT);
     rule.add(MinorType.SMALLINT);
     rule.add(MinorType.INT);
@@ -546,7 +547,7 @@ public class TypeCastRules {
     rules.put(MinorType.FLOAT8, rule);
 
     /** BIT cast able from **/
-    rule = new HashSet<MinorType>();
+    rule = new HashSet<>();
     rule.add(MinorType.TINYINT);
     rule.add(MinorType.BIT);
     rule.add(MinorType.FIXEDCHAR);
@@ -557,7 +558,7 @@ public class TypeCastRules {
     rules.put(MinorType.BIT, rule);
 
     /** FIXEDCHAR cast able from **/
-    rule = new HashSet<MinorType>();
+    rule = new HashSet<>();
     rule.add(MinorType.TINYINT);
     rule.add(MinorType.SMALLINT);
     rule.add(MinorType.INT);
@@ -594,7 +595,7 @@ public class TypeCastRules {
     rules.put(MinorType.FIXEDCHAR, rule);
 
     /** FIXED16CHAR cast able from **/
-    rule = new HashSet<MinorType>();
+    rule = new HashSet<>();
     rule.add(MinorType.TINYINT);
     rule.add(MinorType.SMALLINT);
     rule.add(MinorType.INT);
@@ -630,7 +631,7 @@ public class TypeCastRules {
     rules.put(MinorType.FIXED16CHAR, rule);
 
     /** FIXEDBINARY cast able from **/
-    rule = new HashSet<MinorType>();
+    rule = new HashSet<>();
     rule.add(MinorType.TINYINT);
     rule.add(MinorType.SMALLINT);
     rule.add(MinorType.INT);
@@ -657,7 +658,7 @@ public class TypeCastRules {
     rules.put(MinorType.FIXEDBINARY, rule);
 
     /** VARCHAR cast able from **/
-    rule = new HashSet<MinorType>();
+    rule = new HashSet<>();
     rule.add(MinorType.TINYINT);
     rule.add(MinorType.SMALLINT);
     rule.add(MinorType.INT);
@@ -693,7 +694,7 @@ public class TypeCastRules {
     rules.put(MinorType.VARCHAR, rule);
 
     /** VAR16CHAR cast able from **/
-    rule = new HashSet<MinorType>();
+    rule = new HashSet<>();
     rule.add(MinorType.TINYINT);
     rule.add(MinorType.SMALLINT);
     rule.add(MinorType.INT);
@@ -728,7 +729,7 @@ public class TypeCastRules {
     rules.put(MinorType.VAR16CHAR, rule);
 
     /** VARBINARY cast able from **/
-    rule = new HashSet<MinorType>();
+    rule = new HashSet<>();
     rule.add(MinorType.TINYINT);
     rule.add(MinorType.SMALLINT);
     rule.add(MinorType.INT);
@@ -769,7 +770,7 @@ public class TypeCastRules {
     return isCastable(from.getMinorType(), to.getMinorType());
   }
 
-  private static boolean isCastable(MinorType from, MinorType to) {
+  public static boolean isCastable(MinorType from, MinorType to) {
     return from.equals(MinorType.NULL) ||      //null could be casted to any other type.
         (rules.get(to) == null ? false : rules.get(to).contains(from));
   }

http://git-wip-us.apache.org/repos/asf/drill/blob/d2e0f415/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/user/UserClient.java
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/user/UserClient.java b/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/user/UserClient.java
index 847b726..a7ea7b7 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/user/UserClient.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/user/UserClient.java
@@ -44,6 +44,7 @@ import org.apache.drill.exec.proto.UserProtos.GetCatalogsResp;
 import org.apache.drill.exec.proto.UserProtos.GetColumnsResp;
 import org.apache.drill.exec.proto.UserProtos.GetQueryPlanFragments;
 import org.apache.drill.exec.proto.UserProtos.GetSchemasResp;
+import org.apache.drill.exec.proto.UserProtos.GetServerMetaResp;
 import org.apache.drill.exec.proto.UserProtos.GetTablesResp;
 import org.apache.drill.exec.proto.UserProtos.QueryPlanFragments;
 import org.apache.drill.exec.proto.UserProtos.RpcEndpointInfos;
@@ -318,6 +319,8 @@ public class UserClient extends BasicClient<RpcType, UserClient.UserToBitConnect
       return CreatePreparedStatementResp.getDefaultInstance();
     case RpcType.SASL_MESSAGE_VALUE:
       return SaslMessage.getDefaultInstance();
+    case RpcType.SERVER_META_VALUE:
+      return GetServerMetaResp.getDefaultInstance();
     }
     throw new RpcException(String.format("Unable to deal with RpcType of %d", rpcType));
   }

http://git-wip-us.apache.org/repos/asf/drill/blob/d2e0f415/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/user/UserRpcConfig.java
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/user/UserRpcConfig.java b/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/user/UserRpcConfig.java
index ecf15dd..357f633 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/user/UserRpcConfig.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/user/UserRpcConfig.java
@@ -37,6 +37,8 @@ import org.apache.drill.exec.proto.UserProtos.GetColumnsResp;
 import org.apache.drill.exec.proto.UserProtos.GetQueryPlanFragments;
 import org.apache.drill.exec.proto.UserProtos.GetSchemasReq;
 import org.apache.drill.exec.proto.UserProtos.GetSchemasResp;
+import org.apache.drill.exec.proto.UserProtos.GetServerMetaReq;
+import org.apache.drill.exec.proto.UserProtos.GetServerMetaResp;
 import org.apache.drill.exec.proto.UserProtos.GetTablesReq;
 import org.apache.drill.exec.proto.UserProtos.GetTablesResp;
 import org.apache.drill.exec.proto.UserProtos.QueryPlanFragments;
@@ -71,6 +73,7 @@ public class UserRpcConfig {
         .add(RpcType.CREATE_PREPARED_STATEMENT, CreatePreparedStatementReq.class,
             RpcType.PREPARED_STATEMENT, CreatePreparedStatementResp.class) // user to bit
         .add(RpcType.SASL_MESSAGE, SaslMessage.class, RpcType.SASL_MESSAGE, SaslMessage.class) // user <-> bit
+        .add(RpcType.GET_SERVER_META, GetServerMetaReq.class, RpcType.SERVER_META, GetServerMetaResp.class) // user to bit
         .build();
   }
 
@@ -88,7 +91,7 @@ public class UserRpcConfig {
         .<RpcType> builder()
         .add(RpcType.RUN_QUERY, RpcType.CANCEL_QUERY, RpcType.GET_QUERY_PLAN_FRAGMENTS, RpcType.RESUME_PAUSED_QUERY,
           RpcType.GET_CATALOGS, RpcType.GET_SCHEMAS, RpcType.GET_TABLES, RpcType.GET_COLUMNS,
-          RpcType.CREATE_PREPARED_STATEMENT)
+          RpcType.CREATE_PREPARED_STATEMENT, RpcType.GET_SERVER_META)
         .build()
         );
 }

http://git-wip-us.apache.org/repos/asf/drill/blob/d2e0f415/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/user/UserRpcUtils.java
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/user/UserRpcUtils.java b/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/user/UserRpcUtils.java
index c513d11..43e1c7f 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/user/UserRpcUtils.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/user/UserRpcUtils.java
@@ -18,7 +18,6 @@
 package org.apache.drill.exec.rpc.user;
 
 import java.lang.management.ManagementFactory;
-import java.lang.management.RuntimeMXBean;
 
 import org.apache.drill.common.Version;
 import org.apache.drill.common.util.DrillVersionInfo;
@@ -33,6 +32,23 @@ import com.google.common.base.Preconditions;
 public final class UserRpcUtils {
   private UserRpcUtils() {}
 
+  /*
+   * Template for the endpoint infos.
+   *
+   * It speeds up things not to check application JMX for
+   * each connection.
+   */
+  private static final RpcEndpointInfos INFOS_TEMPLATE =
+      RpcEndpointInfos.newBuilder()
+        .setApplication(ManagementFactory.getRuntimeMXBean().getName())
+        .setVersion(DrillVersionInfo.getVersion())
+        .setMajorVersion(DrillVersionInfo.getMajorVersion())
+        .setMinorVersion(DrillVersionInfo.getMinorVersion())
+        .setPatchVersion(DrillVersionInfo.getPatchVersion())
+        .setBuildNumber(DrillVersionInfo.getBuildNumber())
+        .setVersionQualifier(DrillVersionInfo.getQualifier())
+        .buildPartial();
+
   /**
    * Returns a {@code RpcEndpointInfos} instance
    *
@@ -45,16 +61,8 @@ public final class UserRpcUtils {
    * @throws NullPointerException if name is null
    */
   public static RpcEndpointInfos getRpcEndpointInfos(String name) {
-    RuntimeMXBean mxBean = ManagementFactory.getRuntimeMXBean();
-    RpcEndpointInfos infos = RpcEndpointInfos.newBuilder()
+    RpcEndpointInfos infos = RpcEndpointInfos.newBuilder(INFOS_TEMPLATE)
         .setName(Preconditions.checkNotNull(name))
-        .setApplication(mxBean.getName())
-        .setVersion(DrillVersionInfo.getVersion())
-        .setMajorVersion(DrillVersionInfo.getMajorVersion())
-        .setMinorVersion(DrillVersionInfo.getMinorVersion())
-        .setPatchVersion(DrillVersionInfo.getPatchVersion())
-        .setBuildNumber(DrillVersionInfo.getBuildNumber())
-        .setVersionQualifier(DrillVersionInfo.getQualifier())
         .build();
 
     return infos;

http://git-wip-us.apache.org/repos/asf/drill/blob/d2e0f415/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/user/UserServer.java
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/user/UserServer.java b/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/user/UserServer.java
index e917b3e..9f0d502 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/user/UserServer.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/user/UserServer.java
@@ -21,8 +21,8 @@ import java.io.IOException;
 import java.net.SocketAddress;
 import java.util.UUID;
 
-import io.netty.util.concurrent.Future;
-import io.netty.util.concurrent.GenericFutureListener;
+import javax.security.sasl.SaslException;
+
 import org.apache.drill.common.config.DrillProperties;
 import org.apache.drill.exec.exception.DrillbitStartupException;
 import org.apache.drill.exec.memory.BufferAllocator;
@@ -39,19 +39,21 @@ import org.apache.drill.exec.proto.UserProtos.SaslSupport;
 import org.apache.drill.exec.proto.UserProtos.UserProperties;
 import org.apache.drill.exec.proto.UserProtos.UserToBitHandshake;
 import org.apache.drill.exec.rpc.AbstractRemoteConnection;
+import org.apache.drill.exec.rpc.AbstractServerConnection;
 import org.apache.drill.exec.rpc.BasicServer;
 import org.apache.drill.exec.rpc.OutOfMemoryHandler;
 import org.apache.drill.exec.rpc.OutboundRpcMessage;
 import org.apache.drill.exec.rpc.ProtobufLengthDecoder;
 import org.apache.drill.exec.rpc.RpcException;
 import org.apache.drill.exec.rpc.RpcOutcomeListener;
-import org.apache.drill.exec.rpc.AbstractServerConnection;
 import org.apache.drill.exec.rpc.security.ServerAuthenticationHandler;
-import org.apache.drill.exec.rpc.user.UserServer.BitToUserConnection;
 import org.apache.drill.exec.rpc.security.plain.PlainFactory;
+import org.apache.drill.exec.rpc.user.UserServer.BitToUserConnection;
 import org.apache.drill.exec.rpc.user.security.UserAuthenticationException;
 import org.apache.drill.exec.server.BootStrapContext;
 import org.apache.drill.exec.work.user.UserWorker;
+import org.apache.hadoop.security.HadoopKerberosName;
+import org.slf4j.Logger;
 
 import com.google.protobuf.MessageLite;
 
@@ -59,10 +61,8 @@ import io.netty.channel.ChannelFuture;
 import io.netty.channel.ChannelHandlerContext;
 import io.netty.channel.EventLoopGroup;
 import io.netty.channel.socket.SocketChannel;
-import org.apache.hadoop.security.HadoopKerberosName;
-import org.slf4j.Logger;
-
-import javax.security.sasl.SaslException;
+import io.netty.util.concurrent.Future;
+import io.netty.util.concurrent.GenericFutureListener;
 
 public class UserServer extends BasicServer<RpcType, BitToUserConnection> {
   private static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(UserServer.class);

http://git-wip-us.apache.org/repos/asf/drill/blob/d2e0f415/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/user/UserServerRequestHandler.java
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/user/UserServerRequestHandler.java b/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/user/UserServerRequestHandler.java
index 1c44176..0be4b2c 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/user/UserServerRequestHandler.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/user/UserServerRequestHandler.java
@@ -17,9 +17,6 @@
  */
 package org.apache.drill.exec.rpc.user;
 
-import com.google.protobuf.InvalidProtocolBufferException;
-import io.netty.buffer.ByteBuf;
-import io.netty.buffer.ByteBufInputStream;
 import org.apache.drill.exec.proto.GeneralRPCProtos.Ack;
 import org.apache.drill.exec.proto.UserBitShared.QueryId;
 import org.apache.drill.exec.proto.UserProtos.CreatePreparedStatementReq;
@@ -27,16 +24,22 @@ import org.apache.drill.exec.proto.UserProtos.GetCatalogsReq;
 import org.apache.drill.exec.proto.UserProtos.GetColumnsReq;
 import org.apache.drill.exec.proto.UserProtos.GetQueryPlanFragments;
 import org.apache.drill.exec.proto.UserProtos.GetSchemasReq;
+import org.apache.drill.exec.proto.UserProtos.GetServerMetaReq;
 import org.apache.drill.exec.proto.UserProtos.GetTablesReq;
 import org.apache.drill.exec.proto.UserProtos.RpcType;
 import org.apache.drill.exec.proto.UserProtos.RunQuery;
+import org.apache.drill.exec.rpc.RequestHandler;
 import org.apache.drill.exec.rpc.Response;
 import org.apache.drill.exec.rpc.ResponseSender;
 import org.apache.drill.exec.rpc.RpcException;
-import org.apache.drill.exec.rpc.RequestHandler;
 import org.apache.drill.exec.rpc.user.UserServer.BitToUserConnection;
 import org.apache.drill.exec.work.user.UserWorker;
 
+import com.google.protobuf.InvalidProtocolBufferException;
+
+import io.netty.buffer.ByteBuf;
+import io.netty.buffer.ByteBufInputStream;
+
 /**
  * Should create only one instance of this class per Drillbit service.
  */
@@ -135,6 +138,15 @@ class UserServerRequestHandler implements RequestHandler<BitToUserConnection> {
       } catch (final InvalidProtocolBufferException e) {
         throw new RpcException("Failure while decoding CreatePreparedStatementReq body.", e);
       }
+    case RpcType.GET_SERVER_META_VALUE:
+      try {
+        final GetServerMetaReq req =
+            GetServerMetaReq.PARSER.parseFrom(new ByteBufInputStream(pBody));
+        worker.submitServerMetadataWork(connection.getSession(), req, responseSender);
+        break;
+      } catch (final InvalidProtocolBufferException e) {
+        throw new RpcException("Failure while decoding CreatePreparedStatementReq body.", e);
+      }
     default:
       throw new UnsupportedOperationException(
           String.format("UserServerRequestHandler received rpc of unknown type. Type was %d.", rpcType));

http://git-wip-us.apache.org/repos/asf/drill/blob/d2e0f415/exec/java-exec/src/main/java/org/apache/drill/exec/work/metadata/MetadataProvider.java
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/work/metadata/MetadataProvider.java b/exec/java-exec/src/main/java/org/apache/drill/exec/work/metadata/MetadataProvider.java
index 6ababf4..cf64b20 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/work/metadata/MetadataProvider.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/work/metadata/MetadataProvider.java
@@ -585,7 +585,7 @@ public class MetadataProvider {
    * @param ex Exception thrown
    * @return
    */
-  private static DrillPBError createPBError(final String failedFunction, final Throwable ex) {
+  static DrillPBError createPBError(final String failedFunction, final Throwable ex) {
     final String errorId = UUID.randomUUID().toString();
     logger.error("Failed to {}. ErrorId: {}", failedFunction, errorId, ex);
 

http://git-wip-us.apache.org/repos/asf/drill/blob/d2e0f415/exec/java-exec/src/main/java/org/apache/drill/exec/work/metadata/ServerMetaProvider.java
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/work/metadata/ServerMetaProvider.java b/exec/java-exec/src/main/java/org/apache/drill/exec/work/metadata/ServerMetaProvider.java
new file mode 100644
index 0000000..41421e3
--- /dev/null
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/work/metadata/ServerMetaProvider.java
@@ -0,0 +1,168 @@
+/*
+ * 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
+ * <p/>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p/>
+ * 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.drill.exec.work.metadata;
+
+import java.util.Arrays;
+
+import org.apache.calcite.avatica.util.Casing;
+import org.apache.calcite.sql.SqlJdbcFunctionCall;
+import org.apache.calcite.sql.parser.SqlAbstractParserImpl.Metadata;
+import org.apache.calcite.sql.parser.SqlParser;
+import org.apache.drill.common.types.TypeProtos.MinorType;
+import org.apache.drill.exec.planner.physical.PlannerSettings;
+import org.apache.drill.exec.planner.sql.DrillParserConfig;
+import org.apache.drill.exec.proto.UserProtos.ConvertSupport;
+import org.apache.drill.exec.proto.UserProtos.CorrelationNamesSupport;
+import org.apache.drill.exec.proto.UserProtos.DateTimeLiteralsSupport;
+import org.apache.drill.exec.proto.UserProtos.GetServerMetaReq;
+import org.apache.drill.exec.proto.UserProtos.GetServerMetaResp;
+import org.apache.drill.exec.proto.UserProtos.GroupBySupport;
+import org.apache.drill.exec.proto.UserProtos.IdentifierCasing;
+import org.apache.drill.exec.proto.UserProtos.NullCollation;
+import org.apache.drill.exec.proto.UserProtos.OrderBySupport;
+import org.apache.drill.exec.proto.UserProtos.OuterJoinSupport;
+import org.apache.drill.exec.proto.UserProtos.RequestStatus;
+import org.apache.drill.exec.proto.UserProtos.RpcType;
+import org.apache.drill.exec.proto.UserProtos.ServerMeta;
+import org.apache.drill.exec.proto.UserProtos.SubQuerySupport;
+import org.apache.drill.exec.proto.UserProtos.UnionSupport;
+import org.apache.drill.exec.resolver.TypeCastRules;
+import org.apache.drill.exec.rpc.Response;
+import org.apache.drill.exec.rpc.ResponseSender;
+import org.apache.drill.exec.rpc.user.UserSession;
+import org.apache.drill.exec.server.DrillbitContext;
+
+import com.google.common.base.Splitter;
+import com.google.common.collect.ImmutableList;
+
+/**
+ * Contains worker {@link Runnable} for returning server meta information
+ */
+public class ServerMetaProvider {
+  private static ServerMeta DEFAULT = ServerMeta.newBuilder()
+      .addAllConvertSupport(getSupportedConvertOps())
+      .addAllDateTimeFunctions(Splitter.on(",").split(SqlJdbcFunctionCall.getTimeDateFunctions()))
+      .addAllDateTimeLiteralsSupport(Arrays.asList(DateTimeLiteralsSupport.values()))
+      .addAllNumericFunctions(Splitter.on(",").split(SqlJdbcFunctionCall.getNumericFunctions()))
+      .addAllOrderBySupport(Arrays.asList(OrderBySupport.OB_UNRELATED, OrderBySupport.OB_EXPRESSION))
+      .addAllOuterJoinSupport(Arrays.asList(OuterJoinSupport.OJ_LEFT, OuterJoinSupport.OJ_RIGHT, OuterJoinSupport.OJ_FULL))
+      .addAllStringFunctions(Splitter.on(",").split(SqlJdbcFunctionCall.getStringFunctions()))
+      .addAllSystemFunctions(Splitter.on(",").split(SqlJdbcFunctionCall.getSystemFunctions()))
+      .addAllSubquerySupport(Arrays.asList(SubQuerySupport.SQ_CORRELATED, SubQuerySupport.SQ_IN_COMPARISON, SubQuerySupport.SQ_IN_EXISTS, SubQuerySupport.SQ_IN_QUANTIFIED))
+      .addAllUnionSupport(Arrays.asList(UnionSupport.U_UNION, UnionSupport.U_UNION_ALL))
+      .setAllTablesSelectable(false)
+      .setBlobIncludedInMaxRowSize(true)
+      .setCatalogAtStart(true)
+      .setCatalogSeparator(".")
+      .setCatalogTerm("catalog")
+      .setColumnAliasingSupported(true)
+      .setNullPlusNonNullEqualsNull(true)
+      .setCorrelationNamesSupport(CorrelationNamesSupport.CN_ANY)
+      .setReadOnly(false)
+      .setGroupBySupport(GroupBySupport.GB_UNRELATED)
+      .setLikeEscapeClauseSupported(true)
+      .setNullCollation(NullCollation.NC_AT_END)
+      .setSchemaTerm("schema")
+      .setSearchEscapeString("\\")
+      .setTableTerm("table")
+      .build();
+
+
+  private static final Iterable<ConvertSupport> getSupportedConvertOps() {
+    // A set would be more appropriate but it's not possible to produce
+    // duplicates, and an iterable is all we need.
+    ImmutableList.Builder<ConvertSupport> supportedConvertedOps = ImmutableList.builder();
+
+    for(MinorType from: MinorType.values()) {
+      for(MinorType to: MinorType.values()) {
+        if (TypeCastRules.isCastable(from, to)) {
+          supportedConvertedOps.add(ConvertSupport.newBuilder().setFrom(from).setTo(to).build());
+        }
+      }
+    }
+
+    return supportedConvertedOps.build();
+  }
+  /**
+   * Runnable that creates server meta information for given {@code ServerMetaReq} and
+   * sends the response at the end.
+   */
+  public static class ServerMetaWorker implements Runnable {
+    private final UserSession session;
+    private final DrillbitContext context;
+    @SuppressWarnings("unused")
+    private final GetServerMetaReq req;
+    private final ResponseSender responseSender;
+
+    public ServerMetaWorker(final UserSession session, final DrillbitContext context,
+        final GetServerMetaReq req, final ResponseSender responseSender) {
+      this.session = session;
+      this.context = context;
+      this.req = req;
+      this.responseSender = responseSender;
+    }
+
+    @Override
+    public void run() {
+      final GetServerMetaResp.Builder respBuilder = GetServerMetaResp.newBuilder();
+      try {
+        final ServerMeta.Builder metaBuilder = ServerMeta.newBuilder(DEFAULT);
+        PlannerSettings plannerSettings = new PlannerSettings(session.getOptions(), context.getFunctionImplementationRegistry());
+
+        DrillParserConfig config = new DrillParserConfig(plannerSettings);
+
+        int identifierMaxLength = config.identifierMaxLength();
+        Metadata metadata = SqlParser.create("", config).getMetadata();
+        metaBuilder
+          .setMaxCatalogNameLength(identifierMaxLength)
+          .setMaxColumnNameLength(identifierMaxLength)
+          .setMaxCursorNameLength(identifierMaxLength)
+          .setMaxSchemaNameLength(identifierMaxLength)
+          .setMaxTableNameLength(identifierMaxLength)
+          .setMaxUserNameLength(identifierMaxLength)
+          .setIdentifierQuoteString(config.quoting().string)
+          .setIdentifierCasing(getIdentifierCasing(config.unquotedCasing(), config.caseSensitive()))
+          .setQuotedIdentifierCasing(getIdentifierCasing(config.quotedCasing(), config.caseSensitive()))
+          .addAllSqlKeywords(Splitter.on(",").split(metadata.getJdbcKeywords()));
+        respBuilder.setServerMeta(metaBuilder);
+        respBuilder.setStatus(RequestStatus.OK);
+      } catch(Throwable t) {
+        respBuilder.setStatus(RequestStatus.FAILED);
+        respBuilder.setError(MetadataProvider.createPBError("server meta", t));
+      } finally {
+        responseSender.send(new Response(RpcType.SERVER_META, respBuilder.build()));
+      }
+    }
+
+    public static IdentifierCasing getIdentifierCasing(Casing casing, boolean caseSensitive) {
+      switch(casing) {
+      case TO_LOWER:
+        return IdentifierCasing.IC_STORES_LOWER;
+
+      case TO_UPPER:
+        return IdentifierCasing.IC_STORES_UPPER;
+
+      case UNCHANGED:
+        return caseSensitive ? IdentifierCasing.IC_SUPPORTS_MIXED : IdentifierCasing.IC_STORES_MIXED;
+
+      default:
+        throw new AssertionError("Unknown casing:" + casing);
+      }
+    }
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/drill/blob/d2e0f415/exec/java-exec/src/main/java/org/apache/drill/exec/work/user/UserWorker.java
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/work/user/UserWorker.java b/exec/java-exec/src/main/java/org/apache/drill/exec/work/user/UserWorker.java
index c1fa7a0..b90b4d2 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/work/user/UserWorker.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/work/user/UserWorker.java
@@ -26,6 +26,7 @@ import org.apache.drill.exec.proto.UserProtos.GetCatalogsReq;
 import org.apache.drill.exec.proto.UserProtos.GetColumnsReq;
 import org.apache.drill.exec.proto.UserProtos.GetQueryPlanFragments;
 import org.apache.drill.exec.proto.UserProtos.GetSchemasReq;
+import org.apache.drill.exec.proto.UserProtos.GetServerMetaReq;
 import org.apache.drill.exec.proto.UserProtos.GetTablesReq;
 import org.apache.drill.exec.proto.UserProtos.QueryPlanFragments;
 import org.apache.drill.exec.proto.UserProtos.RunQuery;
@@ -38,6 +39,7 @@ import org.apache.drill.exec.server.options.OptionManager;
 import org.apache.drill.exec.work.WorkManager.WorkerBee;
 import org.apache.drill.exec.work.foreman.Foreman;
 import org.apache.drill.exec.work.metadata.MetadataProvider;
+import org.apache.drill.exec.work.metadata.ServerMetaProvider.ServerMetaWorker;
 import org.apache.drill.exec.work.prepare.PreparedStatementProvider.PreparedStatementWorker;
 
 public class UserWorker{
@@ -125,4 +127,9 @@ public class UserWorker{
       final ResponseSender sender) {
     bee.addNewWork(new PreparedStatementWorker(connection, this, sender, req));
   }
+
+  public void submitServerMetadataWork(final UserSession session, final GetServerMetaReq req,
+      final ResponseSender sender) {
+    bee.addNewWork(new ServerMetaWorker(session, bee.getContext(), req, sender));
+  }
 }

http://git-wip-us.apache.org/repos/asf/drill/blob/d2e0f415/exec/java-exec/src/test/java/org/apache/drill/exec/work/metadata/TestServerMetaProvider.java
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/test/java/org/apache/drill/exec/work/metadata/TestServerMetaProvider.java b/exec/java-exec/src/test/java/org/apache/drill/exec/work/metadata/TestServerMetaProvider.java
new file mode 100644
index 0000000..c1fd38b
--- /dev/null
+++ b/exec/java-exec/src/test/java/org/apache/drill/exec/work/metadata/TestServerMetaProvider.java
@@ -0,0 +1,48 @@
+/*
+ * 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
+ * <p/>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p/>
+ * 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.drill.exec.work.metadata;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+import org.apache.calcite.avatica.util.Quoting;
+import org.apache.drill.BaseTestQuery;
+import org.apache.drill.exec.proto.UserProtos.GetServerMetaResp;
+import org.apache.drill.exec.proto.UserProtos.RequestStatus;
+import org.apache.drill.exec.proto.UserProtos.ServerMeta;
+import org.junit.Test;
+
+/**
+ * Tests for server metadata provider APIs.
+ */
+public class TestServerMetaProvider extends BaseTestQuery {
+  private static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(TestServerMetaProvider.class);
+
+  @Test
+  public void testServerMeta() throws Exception {
+    GetServerMetaResp resp = client.getServerMeta().get();
+    assertNotNull(resp);
+    assertEquals(RequestStatus.OK, resp.getStatus());
+    assertNotNull(resp.getServerMeta());
+
+    ServerMeta serverMeta = resp.getServerMeta();
+    logger.trace("Server metadata: {}", serverMeta);
+
+    assertEquals(Quoting.BACK_TICK.string, serverMeta.getIdentifierQuoteString());
+  }
+}

http://git-wip-us.apache.org/repos/asf/drill/blob/d2e0f415/exec/jdbc/src/main/java/org/apache/drill/jdbc/DrillConnectionConfig.java
----------------------------------------------------------------------
diff --git a/exec/jdbc/src/main/java/org/apache/drill/jdbc/DrillConnectionConfig.java b/exec/jdbc/src/main/java/org/apache/drill/jdbc/DrillConnectionConfig.java
index 15f676c..c225895 100644
--- a/exec/jdbc/src/main/java/org/apache/drill/jdbc/DrillConnectionConfig.java
+++ b/exec/jdbc/src/main/java/org/apache/drill/jdbc/DrillConnectionConfig.java
@@ -66,12 +66,11 @@ public class DrillConnectionConfig extends ConnectionConfigImpl {
     return TimeZone.getDefault();
   }
 
-  public boolean disableServerPreparedStatement() {
+  public boolean isServerPreparedStatementDisabled() {
     return Boolean.valueOf(props.getProperty("server.preparedstatement.disabled"));
   }
 
-  public boolean disableServerMetadata() {
+  public boolean isServerMetadataDisabled() {
     return Boolean.valueOf(props.getProperty("server.metadata.disabled"));
   }
-
 }

http://git-wip-us.apache.org/repos/asf/drill/blob/d2e0f415/exec/jdbc/src/main/java/org/apache/drill/jdbc/impl/DrillDatabaseMetaDataImpl.java
----------------------------------------------------------------------
diff --git a/exec/jdbc/src/main/java/org/apache/drill/jdbc/impl/DrillDatabaseMetaDataImpl.java b/exec/jdbc/src/main/java/org/apache/drill/jdbc/impl/DrillDatabaseMetaDataImpl.java
index 3d19f82..eeb7847 100644
--- a/exec/jdbc/src/main/java/org/apache/drill/jdbc/impl/DrillDatabaseMetaDataImpl.java
+++ b/exec/jdbc/src/main/java/org/apache/drill/jdbc/impl/DrillDatabaseMetaDataImpl.java
@@ -23,15 +23,35 @@ import java.sql.ResultSet;
 import java.sql.RowIdLifetime;
 import java.sql.SQLException;
 import java.sql.SQLFeatureNotSupportedException;
+import java.util.Objects;
+import java.util.Set;
+import java.util.concurrent.ExecutionException;
 
-import org.apache.calcite.avatica.AvaticaConnection;
 import org.apache.calcite.avatica.AvaticaDatabaseMetaData;
 import org.apache.drill.common.Version;
 import org.apache.drill.common.exceptions.DrillRuntimeException;
+import org.apache.drill.common.types.TypeProtos.MinorType;
+import org.apache.drill.common.types.Types;
+import org.apache.drill.exec.client.ServerMethod;
+import org.apache.drill.exec.proto.UserBitShared.DrillPBError;
+import org.apache.drill.exec.proto.UserProtos.ConvertSupport;
+import org.apache.drill.exec.proto.UserProtos.CorrelationNamesSupport;
+import org.apache.drill.exec.proto.UserProtos.GetServerMetaResp;
+import org.apache.drill.exec.proto.UserProtos.GroupBySupport;
+import org.apache.drill.exec.proto.UserProtos.IdentifierCasing;
+import org.apache.drill.exec.proto.UserProtos.NullCollation;
+import org.apache.drill.exec.proto.UserProtos.OrderBySupport;
+import org.apache.drill.exec.proto.UserProtos.OuterJoinSupport;
+import org.apache.drill.exec.proto.UserProtos.RequestStatus;
+import org.apache.drill.exec.proto.UserProtos.ServerMeta;
+import org.apache.drill.exec.proto.UserProtos.SubQuerySupport;
+import org.apache.drill.exec.proto.UserProtos.UnionSupport;
 import org.apache.drill.jdbc.AlreadyClosedSqlException;
 import org.apache.drill.jdbc.DrillDatabaseMetaData;
 
+import com.google.common.base.Joiner;
 import com.google.common.base.Throwables;
+import com.google.common.collect.ImmutableSet;
 
 
 /**
@@ -40,8 +60,64 @@ import com.google.common.base.Throwables;
 class DrillDatabaseMetaDataImpl extends AvaticaDatabaseMetaData
                                 implements DrillDatabaseMetaData {
 
-  protected DrillDatabaseMetaDataImpl( AvaticaConnection connection ) {
+
+  /**
+   * Holds allowed conversion between SQL types
+   *
+   */
+  private static final class SQLConvertSupport {
+    public final int from;
+    public final int to;
+
+    public SQLConvertSupport(int from, int to) {
+      this.from = from;
+      this.to = to;
+    }
+
+    @Override
+    public int hashCode() {
+      return Objects.hash(from, to);
+    }
+
+    @Override public boolean equals(Object obj) {
+      if (this == obj) {
+        return true;
+      }
+
+      if (!(obj instanceof SQLConvertSupport)) {
+        return false;
+      }
+
+      SQLConvertSupport other = (SQLConvertSupport) obj;
+      return from == other.from && to == other.to;
+    }
+
+    public static final Set<SQLConvertSupport> toSQLConvertSupport(Iterable<ConvertSupport> convertSupportIterable) {
+      ImmutableSet.Builder<SQLConvertSupport> sqlConvertSupportSet = ImmutableSet.builder();
+      for(ConvertSupport convertSupport: convertSupportIterable) {
+        try {
+          sqlConvertSupportSet.add(new SQLConvertSupport(
+              toSQLType(convertSupport.getFrom()),
+              toSQLType(convertSupport.getTo())));
+        } catch(IllegalArgumentException e) {
+          // Ignore unknown types...
+        }
+      }
+      return sqlConvertSupportSet.build();
+    }
+
+    private static int toSQLType(MinorType minorType) {
+      String sqlTypeName = Types.getSqlTypeName(Types.optional(minorType));
+      return Types.getJdbcTypeCode(sqlTypeName);
+    }
+  }
+
+  private volatile ServerMeta serverMeta;
+  private volatile Set<SQLConvertSupport> convertSupport;
+
+  protected DrillDatabaseMetaDataImpl( DrillConnectionImpl connection ) {
     super( connection );
+
   }
 
   /**
@@ -58,6 +134,13 @@ class DrillDatabaseMetaDataImpl extends AvaticaDatabaseMetaData
     }
   }
 
+  private boolean getServerMetaSupported() throws SQLException {
+    DrillConnectionImpl connection = (DrillConnectionImpl) getConnection();
+    return
+        !connection.getConfig().isServerMetadataDisabled()
+        && connection.getClient().getSupportedMethods().contains(ServerMethod.SERVER_META);
+  }
+
   private String getServerName() throws SQLException {
     DrillConnectionImpl connection = (DrillConnectionImpl) getConnection();
     return connection.getClient().getServerName();
@@ -68,6 +151,39 @@ class DrillDatabaseMetaDataImpl extends AvaticaDatabaseMetaData
     return connection.getClient().getServerVersion();
   }
 
+  private ServerMeta getServerMeta() throws SQLException {
+    assert getServerMetaSupported();
+
+    if (serverMeta == null) {
+      synchronized(this) {
+        if (serverMeta == null) {
+          DrillConnectionImpl connection = (DrillConnectionImpl) getConnection();
+
+          try {
+            GetServerMetaResp resp = connection.getClient().getServerMeta().get();
+            if (resp.getStatus() != RequestStatus.OK) {
+              DrillPBError drillError = resp.getError();
+              throw new SQLException("Error when getting server meta: " + drillError.getMessage());
+            }
+            serverMeta = resp.getServerMeta();
+            convertSupport = SQLConvertSupport.toSQLConvertSupport(serverMeta.getConvertSupportList());
+          } catch (InterruptedException e) {
+            throw new SQLException("Interrupted when getting server meta", e);
+          } catch (ExecutionException e) {
+            Throwable cause =  e.getCause();
+            if (cause == null) {
+              throw new AssertionError("Something unknown happened", e);
+            }
+            Throwables.propagateIfPossible(cause);
+            throw new SQLException("Error when getting server meta", cause);
+          }
+        }
+      }
+    }
+
+    return serverMeta;
+  }
+
   // Note:  Dynamic proxies could be used to reduce the quantity (450?) of
   // method overrides by eliminating those that exist solely to check whether
   // the object is closed.  (Check performance before applying to frequently
@@ -87,7 +203,10 @@ class DrillDatabaseMetaDataImpl extends AvaticaDatabaseMetaData
   @Override
   public boolean allTablesAreSelectable() throws SQLException {
     throwIfClosed();
-    return super.allTablesAreSelectable();
+    if (!getServerMetaSupported()) {
+      return super.allTablesAreSelectable();
+    }
+    return getServerMeta().getAllTablesSelectable();
   }
 
   @Override
@@ -105,7 +224,10 @@ class DrillDatabaseMetaDataImpl extends AvaticaDatabaseMetaData
   @Override
   public boolean isReadOnly() throws SQLException {
     throwIfClosed();
-    return super.isReadOnly();
+    if (!getServerMetaSupported()) {
+      return super.isReadOnly();
+    }
+    return getServerMeta().getReadOnly();
   }
 
 
@@ -114,25 +236,37 @@ class DrillDatabaseMetaDataImpl extends AvaticaDatabaseMetaData
   @Override
   public boolean nullsAreSortedHigh() throws SQLException {
     throwIfClosed();
-    return true;
+    if (!getServerMetaSupported()) {
+      return true;
+    }
+    return getServerMeta().getNullCollation() == NullCollation.NC_HIGH;
   }
 
   @Override
   public boolean nullsAreSortedLow() throws SQLException {
     throwIfClosed();
-    return false;
+    if (!getServerMetaSupported()) {
+      return false;
+    }
+    return getServerMeta().getNullCollation() == NullCollation.NC_LOW;
   }
 
   @Override
   public boolean nullsAreSortedAtStart() throws SQLException {
     throwIfClosed();
-    return false;
+    if (!getServerMetaSupported()) {
+      return false;
+    }
+    return getServerMeta().getNullCollation() == NullCollation.NC_AT_START;
   }
 
   @Override
   public boolean nullsAreSortedAtEnd() throws SQLException {
     throwIfClosed();
-    return false;
+    if (!getServerMetaSupported()) {
+      return false;
+    }
+    return getServerMeta().getNullCollation() == NullCollation.NC_AT_END;
   }
 
   @Override
@@ -194,98 +328,146 @@ class DrillDatabaseMetaDataImpl extends AvaticaDatabaseMetaData
   @Override
   public boolean supportsMixedCaseIdentifiers() throws SQLException {
     throwIfClosed();
-    return super.supportsMixedCaseIdentifiers();
+    if (!getServerMetaSupported()) {
+      return super.supportsMixedCaseIdentifiers();
+    }
+    return getServerMeta().getIdentifierCasing() == IdentifierCasing.IC_SUPPORTS_MIXED;
   }
 
   @Override
   public boolean storesUpperCaseIdentifiers() throws SQLException {
     throwIfClosed();
-    return super.storesUpperCaseIdentifiers();
+    if (!getServerMetaSupported()) {
+      return super.storesUpperCaseIdentifiers();
+    }
+    return getServerMeta().getIdentifierCasing() == IdentifierCasing.IC_STORES_UPPER;
   }
 
   @Override
   public boolean storesLowerCaseIdentifiers() throws SQLException {
     throwIfClosed();
-    return super.storesLowerCaseIdentifiers();
+    if (!getServerMetaSupported()) {
+      return super.storesLowerCaseIdentifiers();
+    }
+    return getServerMeta().getIdentifierCasing() == IdentifierCasing.IC_STORES_LOWER;
   }
 
   @Override
   public boolean storesMixedCaseIdentifiers() throws SQLException {
     throwIfClosed();
-    return super.storesMixedCaseIdentifiers();
+    if (!getServerMetaSupported()) {
+      return super.storesMixedCaseIdentifiers();
+    }
+    return getServerMeta().getIdentifierCasing() == IdentifierCasing.IC_STORES_MIXED;
   }
 
   @Override
   public boolean supportsMixedCaseQuotedIdentifiers() throws SQLException {
     throwIfClosed();
-    return super.supportsMixedCaseQuotedIdentifiers();
+    if (!getServerMetaSupported()) {
+      return super.supportsMixedCaseQuotedIdentifiers();
+    }
+    return getServerMeta().getQuotedIdentifierCasing() == IdentifierCasing.IC_SUPPORTS_MIXED;
   }
 
   @Override
   public boolean storesUpperCaseQuotedIdentifiers() throws SQLException {
     throwIfClosed();
-    return super.storesUpperCaseQuotedIdentifiers();
+    if (!getServerMetaSupported()) {
+      return super.storesUpperCaseQuotedIdentifiers();
+    }
+    return getServerMeta().getQuotedIdentifierCasing() == IdentifierCasing.IC_STORES_UPPER;
   }
 
   @Override
   public boolean storesLowerCaseQuotedIdentifiers() throws SQLException {
     throwIfClosed();
-    return super.storesLowerCaseQuotedIdentifiers();
+    if (!getServerMetaSupported()) {
+      return super.storesLowerCaseQuotedIdentifiers();
+    }
+    return getServerMeta().getQuotedIdentifierCasing() == IdentifierCasing.IC_STORES_LOWER;
   }
 
   @Override
   public boolean storesMixedCaseQuotedIdentifiers() throws SQLException {
     throwIfClosed();
-    return super.storesMixedCaseQuotedIdentifiers();
+    if (!getServerMetaSupported()) {
+      return super.storesMixedCaseQuotedIdentifiers();
+    }
+    return getServerMeta().getQuotedIdentifierCasing() == IdentifierCasing.IC_STORES_MIXED;
   }
 
   // TODO(DRILL-3510):  Update when Drill accepts standard SQL's double quote.
   @Override
   public String getIdentifierQuoteString() throws SQLException {
     throwIfClosed();
-    return "`";
+    if (!getServerMetaSupported()) {
+      return "`";
+    }
+    return getServerMeta().getIdentifierQuoteString();
   }
 
   @Override
   public String getSQLKeywords() throws SQLException {
     throwIfClosed();
-    return super.getSQLKeywords();
+    if (!getServerMetaSupported()) {
+      return super.getSQLKeywords();
+    }
+    return Joiner.on(",").join(getServerMeta().getSqlKeywordsList());
   }
 
   @Override
   public String getNumericFunctions() throws SQLException {
     throwIfClosed();
-    return super.getNumericFunctions();
+    if (!getServerMetaSupported()) {
+      return super.getNumericFunctions();
+    }
+    return Joiner.on(",").join(getServerMeta().getNumericFunctionsList());
   }
 
   @Override
   public String getStringFunctions() throws SQLException {
     throwIfClosed();
-    return super.getStringFunctions();
+    if (!getServerMetaSupported()) {
+      return super.getStringFunctions();
+    }
+    return Joiner.on(",").join(getServerMeta().getStringFunctionsList());
   }
 
   @Override
   public String getSystemFunctions() throws SQLException {
     throwIfClosed();
-    return super.getSystemFunctions();
+    if (!getServerMetaSupported()) {
+      return super.getSystemFunctions();
+    }
+    return Joiner.on(",").join(getServerMeta().getSystemFunctionsList());
   }
 
   @Override
   public String getTimeDateFunctions() throws SQLException {
     throwIfClosed();
-    return super.getTimeDateFunctions();
+    if (!getServerMetaSupported()) {
+      return super.getTimeDateFunctions();
+    }
+    return Joiner.on(",").join(getServerMeta().getDateTimeFunctionsList());
   }
 
   @Override
   public String getSearchStringEscape() throws SQLException {
     throwIfClosed();
-    return super.getSearchStringEscape();
+    if (!getServerMetaSupported()) {
+      return super.getSearchStringEscape();
+    }
+    return getServerMeta().getSearchEscapeString();
   }
 
   @Override
   public String getExtraNameCharacters() throws SQLException {
     throwIfClosed();
-    return super.getExtraNameCharacters();
+    if (!getServerMetaSupported()) {
+      return super.getExtraNameCharacters();
+    }
+    return getServerMeta().getSpecialCharacters();
   }
 
   @Override
@@ -303,73 +485,114 @@ class DrillDatabaseMetaDataImpl extends AvaticaDatabaseMetaData
   @Override
   public boolean supportsColumnAliasing() throws SQLException {
     throwIfClosed();
-    return super.supportsColumnAliasing();
+    if (!getServerMetaSupported()) {
+      return super.supportsColumnAliasing();
+    }
+    return getServerMeta().getColumnAliasingSupported();
   }
 
   @Override
   public boolean nullPlusNonNullIsNull() throws SQLException {
     throwIfClosed();
-    return super.nullPlusNonNullIsNull();
+    if (!getServerMetaSupported()) {
+      return super.nullPlusNonNullIsNull();
+    }
+    return getServerMeta().getNullPlusNonNullEqualsNull();
   }
 
   @Override
   public boolean supportsConvert() throws SQLException {
     throwIfClosed();
-    return super.supportsConvert();
+    if (!getServerMetaSupported()) {
+      return super.supportsConvert();
+    }
+    // Make sure the convert table is loaded
+    getServerMeta();
+    return !convertSupport.isEmpty();
   }
 
   @Override
   public boolean supportsConvert(int fromType, int toType) throws SQLException {
     throwIfClosed();
-    return super.supportsConvert(fromType, toType);
+    if (!getServerMetaSupported()) {
+      return super.supportsConvert(fromType, toType);
+    }
+    // Make sure the convert table is loaded
+    getServerMeta();
+    return convertSupport.contains(new SQLConvertSupport(fromType, toType));
   }
 
   @Override
   public boolean supportsTableCorrelationNames() throws SQLException {
     throwIfClosed();
-    return super.supportsTableCorrelationNames();
+    if (!getServerMetaSupported()) {
+      return super.supportsTableCorrelationNames();
+    }
+    return getServerMeta().getCorrelationNamesSupport() == CorrelationNamesSupport.CN_ANY
+        || getServerMeta().getCorrelationNamesSupport() == CorrelationNamesSupport.CN_DIFFERENT_NAMES;
   }
 
   @Override
   public boolean supportsDifferentTableCorrelationNames() throws SQLException {
     throwIfClosed();
-    return super.supportsDifferentTableCorrelationNames();
+    if (!getServerMetaSupported()) {
+      return super.supportsDifferentTableCorrelationNames();
+    }
+    return getServerMeta().getCorrelationNamesSupport() == CorrelationNamesSupport.CN_DIFFERENT_NAMES;
   }
 
   @Override
   public boolean supportsExpressionsInOrderBy() throws SQLException {
     throwIfClosed();
-    return super.supportsExpressionsInOrderBy();
+    if (!getServerMetaSupported()) {
+      return super.supportsExpressionsInOrderBy();
+    }
+    return getServerMeta().getOrderBySupportList().contains(OrderBySupport.OB_EXPRESSION);
   }
 
   @Override
   public boolean supportsOrderByUnrelated() throws SQLException {
     throwIfClosed();
-    return super.supportsOrderByUnrelated();
+    if (!getServerMetaSupported()) {
+      return super.supportsOrderByUnrelated();
+    }
+    return getServerMeta().getOrderBySupportList().contains(OrderBySupport.OB_UNRELATED);
   }
 
   @Override
   public boolean supportsGroupBy() throws SQLException {
     throwIfClosed();
-    return super.supportsGroupBy();
+    if (!getServerMetaSupported()) {
+      return super.supportsGroupBy();
+    }
+    return getServerMeta().getGroupBySupport() != GroupBySupport.GB_NONE;
   }
 
   @Override
   public boolean supportsGroupByUnrelated() throws SQLException {
     throwIfClosed();
-    return super.supportsGroupByUnrelated();
+    if (!getServerMetaSupported()) {
+      return super.supportsGroupByUnrelated();
+    }
+    return getServerMeta().getGroupBySupport() == GroupBySupport.GB_UNRELATED;
   }
 
   @Override
   public boolean supportsGroupByBeyondSelect() throws SQLException {
     throwIfClosed();
-    return super.supportsGroupByBeyondSelect();
+    if (!getServerMetaSupported()) {
+      return super.supportsGroupByBeyondSelect();
+    }
+    return getServerMeta().getGroupBySupport() == GroupBySupport.GB_BEYOND_SELECT;
   }
 
   @Override
   public boolean supportsLikeEscapeClause() throws SQLException {
     throwIfClosed();
-    return super.supportsLikeEscapeClause();
+    if (!getServerMetaSupported()) {
+      return super.supportsLikeEscapeClause();
+    }
+    return getServerMeta().getLikeEscapeClauseSupported();
   }
 
   @Override
@@ -435,25 +658,38 @@ class DrillDatabaseMetaDataImpl extends AvaticaDatabaseMetaData
   @Override
   public boolean supportsOuterJoins() throws SQLException {
     throwIfClosed();
-    return super.supportsOuterJoins();
+    if (!getServerMetaSupported()) {
+      return super.supportsOuterJoins();
+    }
+    return getServerMeta().getOuterJoinSupportCount() > 0;
   }
 
   @Override
   public boolean supportsFullOuterJoins() throws SQLException {
     throwIfClosed();
-    return super.supportsFullOuterJoins();
+    if (!getServerMetaSupported()) {
+      return super.supportsFullOuterJoins();
+    }
+    return getServerMeta().getOuterJoinSupportList().contains(OuterJoinSupport.OJ_FULL);
   }
 
   @Override
   public boolean supportsLimitedOuterJoins() throws SQLException {
     throwIfClosed();
-    return super.supportsLimitedOuterJoins();
+    if (!getServerMetaSupported()) {
+      return super.supportsFullOuterJoins();
+    }
+    return getServerMeta().getOuterJoinSupportCount() > 0
+        && !(getServerMeta().getOuterJoinSupportList().contains(OuterJoinSupport.OJ_FULL));
   }
 
   @Override
   public String getSchemaTerm() throws SQLException {
     throwIfClosed();
-    return super.getSchemaTerm();
+    if (!getServerMetaSupported()) {
+      return super.getSchemaTerm();
+    }
+    return getServerMeta().getSchemaTerm();
   }
 
   @Override
@@ -465,19 +701,28 @@ class DrillDatabaseMetaDataImpl extends AvaticaDatabaseMetaData
   @Override
   public String getCatalogTerm() throws SQLException {
     throwIfClosed();
-    return super.getCatalogTerm();
+    if (!getServerMetaSupported()) {
+      return super.getCatalogTerm();
+    }
+    return getServerMeta().getCatalogTerm();
   }
 
   @Override
   public boolean isCatalogAtStart() throws SQLException {
     throwIfClosed();
-    return super.isCatalogAtStart();
+    if (!getServerMetaSupported()) {
+      return super.isCatalogAtStart();
+    }
+    return getServerMeta().getCatalogAtStart();
   }
 
   @Override
   public String getCatalogSeparator() throws SQLException {
     throwIfClosed();
-    return super.getCatalogSeparator();
+    if (!getServerMetaSupported()) {
+      return super.getCatalogSeparator();
+    }
+    return getServerMeta().getCatalogSeparator();
   }
 
   @Override
@@ -555,7 +800,10 @@ class DrillDatabaseMetaDataImpl extends AvaticaDatabaseMetaData
   @Override
   public boolean supportsSelectForUpdate() throws SQLException {
     throwIfClosed();
-    return super.supportsSelectForUpdate();
+    if (!getServerMetaSupported()) {
+      return super.supportsSelectForUpdate();
+    }
+    return getServerMeta().getSelectForUpdateSupported();
   }
 
   @Override
@@ -567,43 +815,64 @@ class DrillDatabaseMetaDataImpl extends AvaticaDatabaseMetaData
   @Override
   public boolean supportsSubqueriesInComparisons() throws SQLException {
     throwIfClosed();
-    return super.supportsSubqueriesInComparisons();
+    if (!getServerMetaSupported()) {
+      return super.supportsSubqueriesInComparisons();
+    }
+    return getServerMeta().getSubquerySupportList().contains(SubQuerySupport.SQ_IN_COMPARISON);
   }
 
   @Override
   public boolean supportsSubqueriesInExists() throws SQLException {
     throwIfClosed();
-    return super.supportsSubqueriesInExists();
+    if (!getServerMetaSupported()) {
+      return super.supportsSubqueriesInExists();
+    }
+    return getServerMeta().getSubquerySupportList().contains(SubQuerySupport.SQ_IN_EXISTS);
   }
 
   @Override
   public boolean supportsSubqueriesInIns() throws SQLException {
     throwIfClosed();
-    return super.supportsSubqueriesInIns();
+    if (!getServerMetaSupported()) {
+      return super.supportsSubqueriesInIns();
+    }
+    return getServerMeta().getSubquerySupportList().contains(SubQuerySupport.SQ_IN_INSERT);
   }
 
   @Override
   public boolean supportsSubqueriesInQuantifieds() throws SQLException {
     throwIfClosed();
-    return super.supportsSubqueriesInQuantifieds();
+    if (!getServerMetaSupported()) {
+      return super.supportsSubqueriesInQuantifieds();
+    }
+    return getServerMeta().getSubquerySupportList().contains(SubQuerySupport.SQ_IN_QUANTIFIED);
   }
 
   @Override
   public boolean supportsCorrelatedSubqueries() throws SQLException {
     throwIfClosed();
-    return super.supportsCorrelatedSubqueries();
+    if (!getServerMetaSupported()) {
+      return super.supportsCorrelatedSubqueries();
+    }
+    return getServerMeta().getSubquerySupportList().contains(SubQuerySupport.SQ_CORRELATED);
   }
 
   @Override
   public boolean supportsUnion() throws SQLException {
     throwIfClosed();
-    return super.supportsUnion();
+    if (!getServerMetaSupported()) {
+      return super.supportsUnion();
+    }
+    return getServerMeta().getUnionSupportList().contains(UnionSupport.U_UNION);
   }
 
   @Override
   public boolean supportsUnionAll() throws SQLException {
     throwIfClosed();
-    return super.supportsUnionAll();
+    if (!getServerMetaSupported()) {
+      return super.supportsUnionAll();
+    }
+    return getServerMeta().getUnionSupportList().contains(UnionSupport.U_UNION_ALL);
   }
 
   @Override
@@ -633,25 +902,37 @@ class DrillDatabaseMetaDataImpl extends AvaticaDatabaseMetaData
   @Override
   public int getMaxBinaryLiteralLength() throws SQLException {
     throwIfClosed();
-    return super.getMaxBinaryLiteralLength();
+    if (!getServerMetaSupported()) {
+      return super.getMaxBinaryLiteralLength();
+    }
+    return getServerMeta().getMaxBinaryLiteralLength();
   }
 
   @Override
   public int getMaxCharLiteralLength() throws SQLException {
     throwIfClosed();
-    return super.getMaxCharLiteralLength();
+    if (!getServerMetaSupported()) {
+      return super.getMaxCharLiteralLength();
+    }
+    return getServerMeta().getMaxCharLiteralLength();
   }
 
   @Override
   public int getMaxColumnNameLength() throws SQLException {
     throwIfClosed();
-    return super.getMaxColumnNameLength();
+    if (!getServerMetaSupported()) {
+      return super.getMaxColumnNameLength();
+    }
+    return getServerMeta().getMaxColumnNameLength();
   }
 
   @Override
   public int getMaxColumnsInGroupBy() throws SQLException {
     throwIfClosed();
-    return super.getMaxColumnsInGroupBy();
+    if (!getServerMetaSupported()) {
+      return super.getMaxColumnsInGroupBy();
+    }
+    return getServerMeta().getMaxColumnsInGroupBy();
   }
 
   @Override
@@ -663,13 +944,19 @@ class DrillDatabaseMetaDataImpl extends AvaticaDatabaseMetaData
   @Override
   public int getMaxColumnsInOrderBy() throws SQLException {
     throwIfClosed();
-    return super.getMaxColumnsInOrderBy();
+    if (!getServerMetaSupported()) {
+      return super.getMaxColumnsInOrderBy();
+    }
+    return getServerMeta().getMaxColumnsInOrderBy();
   }
 
   @Override
   public int getMaxColumnsInSelect() throws SQLException {
     throwIfClosed();
-    return super.getMaxColumnsInSelect();
+    if (!getServerMetaSupported()) {
+      return super.getMaxColumnsInSelect();
+    }
+    return getServerMeta().getMaxColumnsInSelect();
   }
 
   @Override
@@ -687,7 +974,10 @@ class DrillDatabaseMetaDataImpl extends AvaticaDatabaseMetaData
   @Override
   public int getMaxCursorNameLength() throws SQLException {
     throwIfClosed();
-    return super.getMaxCursorNameLength();
+    if (!getServerMetaSupported()) {
+      return super.getMaxCursorNameLength();
+    }
+    return getServerMeta().getMaxCursorNameLength();
   }
 
   @Override
@@ -699,7 +989,10 @@ class DrillDatabaseMetaDataImpl extends AvaticaDatabaseMetaData
   @Override
   public int getMaxSchemaNameLength() throws SQLException {
     throwIfClosed();
-    return super.getMaxSchemaNameLength();
+    if (!getServerMetaSupported()) {
+      return super.getMaxSchemaNameLength();
+    }
+    return getServerMeta().getMaxSchemaNameLength();
   }
 
   @Override
@@ -711,49 +1004,73 @@ class DrillDatabaseMetaDataImpl extends AvaticaDatabaseMetaData
   @Override
   public int getMaxCatalogNameLength() throws SQLException {
     throwIfClosed();
-    return super.getMaxCatalogNameLength();
+    if (!getServerMetaSupported()) {
+      return super.getMaxCatalogNameLength();
+    }
+    return getServerMeta().getMaxCatalogNameLength();
   }
 
   @Override
   public int getMaxRowSize() throws SQLException {
     throwIfClosed();
-    return super.getMaxRowSize();
+    if (!getServerMetaSupported()) {
+      return super.getMaxRowSize();
+    }
+    return getServerMeta().getMaxRowSize();
   }
 
   @Override
   public boolean doesMaxRowSizeIncludeBlobs() throws SQLException {
     throwIfClosed();
-    return super.doesMaxRowSizeIncludeBlobs();
+    if (!getServerMetaSupported()) {
+      return super.doesMaxRowSizeIncludeBlobs();
+    }
+    return getServerMeta().getBlobIncludedInMaxRowSize();
   }
 
   @Override
   public int getMaxStatementLength() throws SQLException {
     throwIfClosed();
-    return super.getMaxStatementLength();
+    if (!getServerMetaSupported()) {
+      return super.getMaxStatementLength();
+    }
+    return getServerMeta().getMaxStatementLength();
   }
 
   @Override
   public int getMaxStatements() throws SQLException {
     throwIfClosed();
-    return super.getMaxStatements();
+    if (!getServerMetaSupported()) {
+      return super.getMaxStatements();
+    }
+    return getServerMeta().getMaxStatements();
   }
 
   @Override
   public int getMaxTableNameLength() throws SQLException {
     throwIfClosed();
-    return super.getMaxTableNameLength();
+    if (!getServerMetaSupported()) {
+      return super.getMaxTableNameLength();
+    }
+    return getServerMeta().getMaxTableNameLength();
   }
 
   @Override
   public int getMaxTablesInSelect() throws SQLException {
     throwIfClosed();
-    return super.getMaxTablesInSelect();
+    if (!getServerMetaSupported()) {
+      return super.getMaxTablesInSelect();
+    }
+    return getServerMeta().getMaxTablesInSelect();
   }
 
   @Override
   public int getMaxUserNameLength() throws SQLException {
     throwIfClosed();
-    return super.getMaxUserNameLength();
+    if (!getServerMetaSupported()) {
+      return super.getMaxUserNameLength();
+    }
+    return getServerMeta().getMaxUserNameLength();
   }
 
   @Override
@@ -765,7 +1082,10 @@ class DrillDatabaseMetaDataImpl extends AvaticaDatabaseMetaData
   @Override
   public boolean supportsTransactions() throws SQLException {
     throwIfClosed();
-    return super.supportsTransactions();
+    if (!getServerMetaSupported()) {
+      return super.supportsTransactions();
+    }
+    return getServerMeta().getTransactionSupported();
   }
 
   @Override

http://git-wip-us.apache.org/repos/asf/drill/blob/d2e0f415/exec/jdbc/src/main/java/org/apache/drill/jdbc/impl/DrillJdbc41Factory.java
----------------------------------------------------------------------
diff --git a/exec/jdbc/src/main/java/org/apache/drill/jdbc/impl/DrillJdbc41Factory.java b/exec/jdbc/src/main/java/org/apache/drill/jdbc/impl/DrillJdbc41Factory.java
index 28a4372..629e47b 100644
--- a/exec/jdbc/src/main/java/org/apache/drill/jdbc/impl/DrillJdbc41Factory.java
+++ b/exec/jdbc/src/main/java/org/apache/drill/jdbc/impl/DrillJdbc41Factory.java
@@ -74,7 +74,7 @@ public class DrillJdbc41Factory extends DrillFactory {
 
   @Override
   public DrillDatabaseMetaDataImpl newDatabaseMetaData(AvaticaConnection connection) {
-    return new DrillDatabaseMetaDataImpl(connection);
+    return new DrillDatabaseMetaDataImpl((DrillConnectionImpl) connection);
   }
 
 
@@ -101,7 +101,7 @@ public class DrillJdbc41Factory extends DrillFactory {
       throws SQLException {
     DrillConnectionImpl drillConnection = (DrillConnectionImpl) connection;
     DrillClient client = drillConnection.getClient();
-    if (drillConnection.getConfig().disableServerPreparedStatement() || !client.getSupportedMethods().contains(ServerMethod.PREPARED_STATEMENT)) {
+    if (drillConnection.getConfig().isServerPreparedStatementDisabled() || !client.getSupportedMethods().contains(ServerMethod.PREPARED_STATEMENT)) {
       // fallback to client side prepared statement
       return new DrillJdbc41PreparedStatement(drillConnection, h, signature, null, resultSetType, resultSetConcurrency, resultSetHoldability);
     }

http://git-wip-us.apache.org/repos/asf/drill/blob/d2e0f415/exec/jdbc/src/main/java/org/apache/drill/jdbc/impl/DrillMetaImpl.java
----------------------------------------------------------------------
diff --git a/exec/jdbc/src/main/java/org/apache/drill/jdbc/impl/DrillMetaImpl.java b/exec/jdbc/src/main/java/org/apache/drill/jdbc/impl/DrillMetaImpl.java
index 10d4225..b78e93a 100644
--- a/exec/jdbc/src/main/java/org/apache/drill/jdbc/impl/DrillMetaImpl.java
+++ b/exec/jdbc/src/main/java/org/apache/drill/jdbc/impl/DrillMetaImpl.java
@@ -421,7 +421,7 @@ class DrillMetaImpl extends MetaImpl {
   @Override
   public MetaResultSet getTables(String catalog, final Pat schemaPattern, final Pat tableNamePattern,
       final List<String> typeList) {
-    if (connection.getConfig().disableServerMetadata() || ! connection.getClient().getSupportedMethods().contains(ServerMethod.GET_TABLES)) {
+    if (connection.getConfig().isServerMetadataDisabled() || ! connection.getClient().getSupportedMethods().contains(ServerMethod.GET_TABLES)) {
       return clientGetTables(catalog, schemaPattern, tableNamePattern, typeList);
     }
 
@@ -964,7 +964,7 @@ class DrillMetaImpl extends MetaImpl {
   @Override
   public MetaResultSet getColumns(String catalog, Pat schemaPattern,
                               Pat tableNamePattern, Pat columnNamePattern) {
-    if (connection.getConfig().disableServerMetadata() || ! connection.getClient().getSupportedMethods().contains(ServerMethod.GET_COLUMNS)) {
+    if (connection.getConfig().isServerMetadataDisabled() || ! connection.getClient().getSupportedMethods().contains(ServerMethod.GET_COLUMNS)) {
       return clientGetColumns(catalog, schemaPattern, tableNamePattern, columnNamePattern);
     }
 
@@ -1023,7 +1023,7 @@ class DrillMetaImpl extends MetaImpl {
    */
   @Override
   public MetaResultSet getSchemas(String catalog, Pat schemaPattern) {
-    if (connection.getConfig().disableServerMetadata() || ! connection.getClient().getSupportedMethods().contains(ServerMethod.GET_SCHEMAS)) {
+    if (connection.getConfig().isServerMetadataDisabled() || ! connection.getClient().getSupportedMethods().contains(ServerMethod.GET_SCHEMAS)) {
       return clientGetSchemas(catalog, schemaPattern);
     }
 
@@ -1070,7 +1070,7 @@ class DrillMetaImpl extends MetaImpl {
    */
   @Override
   public MetaResultSet getCatalogs() {
-    if (connection.getConfig().disableServerMetadata() || ! connection.getClient().getSupportedMethods().contains(ServerMethod.GET_CATALOGS)) {
+    if (connection.getConfig().isServerMetadataDisabled() || ! connection.getClient().getSupportedMethods().contains(ServerMethod.GET_CATALOGS)) {
       return clientGetCatalogs();
     }
 

http://git-wip-us.apache.org/repos/asf/drill/blob/d2e0f415/logical/src/main/java/org/apache/drill/common/expression/fn/CastFunctions.java
----------------------------------------------------------------------
diff --git a/logical/src/main/java/org/apache/drill/common/expression/fn/CastFunctions.java b/logical/src/main/java/org/apache/drill/common/expression/fn/CastFunctions.java
index 43b3b2e..c026b9f 100644
--- a/logical/src/main/java/org/apache/drill/common/expression/fn/CastFunctions.java
+++ b/logical/src/main/java/org/apache/drill/common/expression/fn/CastFunctions.java
@@ -21,6 +21,7 @@ import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Map;
 import java.util.Set;
+
 import org.apache.drill.common.types.TypeProtos.DataMode;
 import org.apache.drill.common.types.TypeProtos.MinorType;
 
@@ -142,7 +143,7 @@ public class CastFunctions {
       return func;
     }
 
-    throw new RuntimeException(
+    throw new IllegalArgumentException(
       String.format("cast function for type %s is not defined", targetMinorType.name()));
   }
 


Mime
View raw message