aboutsummaryrefslogtreecommitdiff
path: root/exec
diff options
context:
space:
mode:
authorJacques Nadeau <jacques@apache.org>2014-08-28 22:58:31 -0700
committerJacques Nadeau <jacques@apache.org>2014-08-29 08:53:41 -0700
commit967fef5ade88d7be30f745cc884f34b911f0bbb3 (patch)
tree3eba98b25067e9b6bb53cdb9923f171e3ceb8bf5 /exec
parent8bf3c4e0d8f3b2d7dc5b798f31272afa3d7eaf15 (diff)
DRILL-1340: Add support for JDBC metadata.
Diffstat (limited to 'exec')
-rw-r--r--exec/jdbc/src/main/java/org/apache/drill/jdbc/MetaImpl.java135
-rw-r--r--exec/jdbc/src/test/java/org/apache/drill/jdbc/test/JdbcTestActionBase.java136
-rw-r--r--exec/jdbc/src/test/java/org/apache/drill/jdbc/test/TestJdbcMetadata.java93
3 files changed, 358 insertions, 6 deletions
diff --git a/exec/jdbc/src/main/java/org/apache/drill/jdbc/MetaImpl.java b/exec/jdbc/src/main/java/org/apache/drill/jdbc/MetaImpl.java
index 5d8b6a791..86cdefe23 100644
--- a/exec/jdbc/src/main/java/org/apache/drill/jdbc/MetaImpl.java
+++ b/exec/jdbc/src/main/java/org/apache/drill/jdbc/MetaImpl.java
@@ -17,6 +17,7 @@
*/
package org.apache.drill.jdbc;
+import java.sql.DatabaseMetaData;
import java.sql.ResultSet;
import java.util.List;
@@ -25,10 +26,15 @@ import net.hydromatic.avatica.AvaticaResultSet;
import net.hydromatic.avatica.AvaticaStatement;
import net.hydromatic.avatica.Cursor;
import net.hydromatic.avatica.Meta;
-import net.hydromatic.linq4j.Linq4j;
+
+import org.apache.commons.lang.StringEscapeUtils;
+import org.apache.drill.common.exceptions.DrillRuntimeException;
+
public class MetaImpl implements Meta {
-
+
+ static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(MetaImpl.class);
+
static final Driver DRIVER = new Driver();
final DrillConnectionImpl connection;
@@ -61,21 +67,138 @@ public class MetaImpl implements Meta {
return null;
}
+ private ResultSet s(String s){
+ try{
+ logger.debug("Running {}", s);
+ AvaticaStatement statement = connection.createStatement();
+ statement.execute(s);
+ return statement.getResultSet();
+
+ }catch(Exception e){
+ throw new DrillRuntimeException("Failure while attempting to get DatabaseMetadata.", e);
+ }
+
+ }
+
public ResultSet getTables(String catalog, final Pat schemaPattern, final Pat tableNamePattern,
final List<String> typeList) {
- return getEmptyResultSet();
+ StringBuilder sb = new StringBuilder();
+ sb.append("select "
+ + "TABLE_CATALOG as TABLE_CAT, "
+ + "TABLE_SCHEMA as TABLE_SCHEM, "
+ + "TABLE_NAME, "
+ + "TABLE_TYPE, "
+ + "'' as REMARKS, "
+ + "'' as TYPE_CAT, "
+ + "'' as TYPE_SCHEM, "
+ + "'' as TYPE_NAME, "
+ + "'' as SELF_REFERENCING_COL_NAME, "
+ + "'' as REF_GENERATION "
+ + "FROM INFORMATION_SCHEMA.`TABLES` WHERE 1=1 ");
+
+ if(catalog != null){
+ sb.append(" AND TABLE_CATALOG = '" + StringEscapeUtils.escapeSql(catalog) + "' ");
+ }
+
+ if(schemaPattern.s != null){
+ sb.append(" AND TABLE_SCHEMA like '" + StringEscapeUtils.escapeSql(schemaPattern.s) + "'");
+ }
+
+ if(tableNamePattern.s != null){
+ sb.append(" AND TABLE_NAME like '" + StringEscapeUtils.escapeSql(tableNamePattern.s) + "'");
+ }
+
+ if(typeList != null && typeList.size() > 0){
+ sb.append("AND (");
+ for(int t = 0; t < typeList.size(); t++){
+ if(t != 0) sb.append(" OR ");
+ sb.append(" TABLE_TYPE LIKE '" + StringEscapeUtils.escapeSql(typeList.get(t)) + "' ");
+ }
+ sb.append(")");
+ }
+
+ sb.append(" ORDER BY TABLE_TYPE, TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME");
+
+ return s(sb.toString());
}
public ResultSet getColumns(String catalog, Pat schemaPattern, Pat tableNamePattern, Pat columnNamePattern) {
- return getEmptyResultSet();
+
+ StringBuilder sb = new StringBuilder();
+ sb.append("select "
+ + "TABLE_CATALOG as TABLE_CAT, "
+ + "TABLE_SCHEMA as TABLE_SCHEM, "
+ + "TABLE_NAME, "
+ + "COLUMN_NAME, "
+ + "DATA_TYPE, "
+ + "CHARACTER_MAXIMUM_LENGTH as BUFFER_LENGTH, "
+ + "NUMERIC_PRECISION as DECIMAL_PRECISION, "
+ + "NUMERIC_PRECISION_RADIX as NUM_PREC_RADIX, "
+ + DatabaseMetaData.columnNullableUnknown
+ + " as NULLABLE, "
+ + "'' as REMARKS, "
+ + "'' as COLUMN_DEF, "
+ + "0 as SQL_DATA_TYPE, "
+ + "0 as SQL_DATETIME_SUB, "
+ + "4 as CHAR_OCTET_LENGTH, "
+ + "1 as ORDINAL_POSITION, "
+ + "'YES' as IS_NULLABLE, "
+ + "'' as SCOPE_CATALOG,"
+ + "'' as SCOPE_SCHEMA, "
+ + "'' as SCOPE_TABLE, "
+ + "'' as SOURCE_DATA_TYPE, "
+ + "'' as IS_AUTOINCREMENT, "
+ + "'' as IS_GENERATEDCOLUMN "
+ + "FROM INFORMATION_SCHEMA.COLUMNS "
+ + "WHERE 1=1 ");
+
+ if(catalog != null){
+ sb.append(" AND TABLE_CATALOG = '" + StringEscapeUtils.escapeSql(catalog) + "' ");
+ }
+ if(schemaPattern.s != null){
+ sb.append(" AND TABLE_SCHEMA like '" + StringEscapeUtils.escapeSql(schemaPattern.s) + "'");
+ }
+
+ if(tableNamePattern.s != null){
+ sb.append(" AND TABLE_NAME like '" + StringEscapeUtils.escapeSql(tableNamePattern.s) + "'");
+ }
+
+ if(columnNamePattern.s != null){
+ sb.append(" AND COLUMN_NAME like '" + StringEscapeUtils.escapeSql(columnNamePattern.s) + "'");
+ }
+
+ sb.append(" ORDER BY TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, COLUMN_NAME");
+
+ return s(sb.toString());
}
public ResultSet getSchemas(String catalog, Pat schemaPattern) {
- return getEmptyResultSet();
+ StringBuilder sb = new StringBuilder();
+ sb.append("select "
+ + "SCHEMA_NAME as TABLE_SCHEM, "
+ + "CATALOG_NAME as TABLE_CAT "
+ + " FROM INFORMATION_SCHEMA.SCHEMATA WHERE 1=1 ");
+
+ if(catalog != null){
+ sb.append(" AND CATALOG_NAME = '" + StringEscapeUtils.escapeSql(catalog) + "' ");
+ }
+ if(schemaPattern.s != null){
+ sb.append(" AND SCHEMA_NAME like '" + StringEscapeUtils.escapeSql(schemaPattern.s) + "'");
+ }
+ sb.append(" ORDER BY CATALOG_NAME, SCHEMA_NAME");
+
+ return s(sb.toString());
}
public ResultSet getCatalogs() {
- return getEmptyResultSet();
+ StringBuilder sb = new StringBuilder();
+ sb.append("select "
+ + "CATALOG_NAME as TABLE_CAT "
+ + " FROM INFORMATION_SCHEMA.CATALOGS ");
+
+ sb.append(" ORDER BY CATALOG_NAME");
+
+ return s(sb.toString());
}
public ResultSet getTableTypes() {
diff --git a/exec/jdbc/src/test/java/org/apache/drill/jdbc/test/JdbcTestActionBase.java b/exec/jdbc/src/test/java/org/apache/drill/jdbc/test/JdbcTestActionBase.java
new file mode 100644
index 000000000..5c0a2e3d9
--- /dev/null
+++ b/exec/jdbc/src/test/java/org/apache/drill/jdbc/test/JdbcTestActionBase.java
@@ -0,0 +1,136 @@
+/**
+ * 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.jdbc.test;
+
+import java.io.IOException;
+import java.nio.file.Paths;
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.ResultSet;
+import java.sql.ResultSetMetaData;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.util.concurrent.TimeUnit;
+
+import org.apache.drill.common.util.TestTools;
+import org.apache.drill.jdbc.Driver;
+import org.apache.drill.jdbc.JdbcTest;
+import org.junit.AfterClass;
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.junit.Rule;
+import org.junit.rules.TestRule;
+import org.junit.rules.TestWatcher;
+import org.junit.runner.Description;
+
+import com.google.common.base.Stopwatch;
+
+public class JdbcTestActionBase extends JdbcTest {
+ // Set a timeout unless we're debugging.
+ @Rule
+ public TestRule TIMEOUT = TestTools.getTimeoutRule(40000);
+
+ protected static final String WORKING_PATH;
+ static {
+ Driver.load();
+ WORKING_PATH = Paths.get("").toAbsolutePath().toString();
+
+ }
+
+ protected void testQuery(final String sql) throws Exception {
+ testAction(new JdbcAction() {
+
+ @Override
+ public ResultSet getResult(Connection c) throws SQLException {
+ Statement s = c.createStatement();
+ ResultSet r = s.executeQuery(sql);
+ return r;
+ }
+
+ });
+ }
+
+ protected void testAction(JdbcAction action) throws Exception {
+ testAction(action, -1);
+ }
+
+ protected void testAction(JdbcAction action, long rowcount) throws Exception {
+ int rows = 0;
+ Stopwatch watch = new Stopwatch().start();
+ ResultSet r = action.getResult(connection);
+ boolean first = true;
+ while (r.next()) {
+ rows++;
+ ResultSetMetaData md = r.getMetaData();
+ if (first == true) {
+ for (int i = 1; i <= md.getColumnCount(); i++) {
+ System.out.print(md.getColumnName(i));
+ System.out.print('\t');
+ }
+ System.out.println();
+ first = false;
+ }
+
+ for (int i = 1; i <= md.getColumnCount(); i++) {
+ System.out.print(r.getObject(i));
+ System.out.print('\t');
+ }
+ System.out.println();
+ }
+
+ System.out.println(String.format("Query completed in %d millis.", watch.elapsed(TimeUnit.MILLISECONDS)));
+
+ if (rowcount != -1)
+ Assert.assertEquals((long) rowcount, (long) rows);
+
+ System.out.println("\n\n\n");
+
+ }
+
+ public static interface JdbcAction {
+ ResultSet getResult(Connection c) throws SQLException;
+ }
+
+ static void resetConnection() throws Exception {
+ closeClient();
+ openClient();
+ }
+
+ static Connection connection;
+
+ @BeforeClass
+ public static void openClient() throws Exception {
+ connection = DriverManager.getConnection("jdbc:drill:zk=local", null);
+ }
+
+ @AfterClass
+ public static void closeClient() throws IOException, SQLException {
+ connection.close();
+ }
+
+ public final TestRule resetWatcher = new TestWatcher() {
+ @Override
+ protected void failed(Throwable e, Description description) {
+ try {
+ resetConnection();
+ } catch (Exception e1) {
+ throw new RuntimeException("Failure while resetting client.", e1);
+ }
+ }
+ };
+}
diff --git a/exec/jdbc/src/test/java/org/apache/drill/jdbc/test/TestJdbcMetadata.java b/exec/jdbc/src/test/java/org/apache/drill/jdbc/test/TestJdbcMetadata.java
new file mode 100644
index 000000000..24372a7d6
--- /dev/null
+++ b/exec/jdbc/src/test/java/org/apache/drill/jdbc/test/TestJdbcMetadata.java
@@ -0,0 +1,93 @@
+/**
+ * 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.jdbc.test;
+
+import java.sql.Connection;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+
+import org.junit.Test;
+
+
+public class TestJdbcMetadata extends JdbcTestActionBase {
+ static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(TestJdbcMetadata.class);
+
+
+ @Test
+ public void catalogs() throws Exception{
+ this.testAction(new JdbcAction(){
+ public ResultSet getResult(Connection c) throws SQLException {
+ return c.getMetaData().getCatalogs();
+ }
+ }, 1);
+ }
+
+ @Test
+ public void allSchemas() throws Exception{
+ this.testAction(new JdbcAction(){
+ public ResultSet getResult(Connection c) throws SQLException {
+ return c.getMetaData().getSchemas();
+ }
+ });
+ }
+
+ @Test
+ public void schemasWithConditions() throws Exception{
+ this.testAction(new JdbcAction(){
+ public ResultSet getResult(Connection c) throws SQLException {
+ return c.getMetaData().getSchemas("DRILL", "%fs%");
+ }
+ }, 6);
+ }
+
+ @Test
+ public void allTables() throws Exception{
+ this.testAction(new JdbcAction(){
+ public ResultSet getResult(Connection c) throws SQLException {
+ return c.getMetaData().getTables(null, null, null, null);
+ }
+ });
+ }
+
+ @Test
+ public void tablesWithConditions() throws Exception{
+ this.testAction(new JdbcAction(){
+ public ResultSet getResult(Connection c) throws SQLException {
+ return c.getMetaData().getTables("DRILL", "sys", "opt%", new String[]{"TABLE", "VIEW"});
+ }
+ }, 1);
+ }
+
+ @Test
+ public void allColumns() throws Exception{
+ this.testAction(new JdbcAction(){
+ public ResultSet getResult(Connection c) throws SQLException {
+ return c.getMetaData().getColumns(null, null, null, null);
+ }
+ });
+ }
+
+ @Test
+ public void columnsWithConditions() throws Exception{
+ this.testAction(new JdbcAction(){
+ public ResultSet getResult(Connection c) throws SQLException {
+ return c.getMetaData().getColumns("DRILL", "sys", "opt%", "%ame");
+ }
+ }, 1);
+ }
+}