Repository: zeppelin
Updated Branches:
  refs/heads/master 616301ae4 -> ebd5e1e9b


[ZEPPELIN-1988] add property "precode" to JDBCInterpreter

### What is this PR for?
Adds property "precode". Value of property contains SQL which executes while 
opening connection.

### What type of PR is it?
Improvement

### What is the Jira issue?
https://issues.apache.org/jira/browse/ZEPPELIN-1988

### How should this be tested?
1) Set property zeppelin.interpreter.precode =` set search_path='test, public' `
2) Execute `%jdbc show search_path`

### Questions:
* Does the licenses files need update? no
* Is there breaking changes for older versions? no
* Does this needs documentation? no

Author: Tinkoff DWH <tinkoff....@gmail.com>

Closes #2078 from tinkoff-dwh/ZEPPELIN-1988 and squashes the following commits:

cd46cce [Tinkoff DWH] [ZEPPELIN-1988] trim precode
42ffcb7 [Tinkoff DWH] [ZEPPELIN-1988] fix condition
7636b3f [Tinkoff DWH] Merge remote-tracking branch 'origin/master' into 
ZEPPELIN-1988
66d6ae4 [Tinkoff DWH] [ZEPPELIN-1988] fixes of review items
9d37bc4 [Tinkoff DWH] [ZEPPELIN-1988] fix
ba3477a [Tinkoff DWH] [ZEPPELIN-1988] add property "precode" to JDBCInterpreter


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

Branch: refs/heads/master
Commit: ebd5e1e9b6fa763859e378d1c4ad79f80a19b432
Parents: 616301a
Author: Tinkoff DWH <tinkoff....@gmail.com>
Authored: Sun Mar 5 13:00:21 2017 +0500
Committer: Felix Cheung <felixche...@apache.org>
Committed: Mon Mar 6 23:15:44 2017 -0800

----------------------------------------------------------------------
 docs/interpreter/jdbc.md                        |  4 ++
 .../apache/zeppelin/jdbc/JDBCInterpreter.java   | 41 +++++++++++++------
 .../src/main/resources/interpreter-setting.json |  6 +++
 .../zeppelin/jdbc/JDBCInterpreterTest.java      | 42 ++++++++++++++++++++
 4 files changed, 81 insertions(+), 12 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/zeppelin/blob/ebd5e1e9/docs/interpreter/jdbc.md
----------------------------------------------------------------------
diff --git a/docs/interpreter/jdbc.md b/docs/interpreter/jdbc.md
index 32adcba..346fcbb 100644
--- a/docs/interpreter/jdbc.md
+++ b/docs/interpreter/jdbc.md
@@ -167,6 +167,10 @@ There are more JDBC interpreter properties you can specify 
like below.
     <td>default.jceks.credentialKey</td>
     <td>jceks credential key</td>
   </tr>
+  <tr>
+    <td>zeppelin.jdbc.precode</td>
+    <td>Some SQL which executes while opening connection</td>
+  </tr>
 </table>
 
 You can also add more properties by using this 
[method](http://docs.oracle.com/javase/7/docs/api/java/sql/DriverManager.html#getConnection%28java.lang.String,%20java.util.Properties%29).

http://git-wip-us.apache.org/repos/asf/zeppelin/blob/ebd5e1e9/jdbc/src/main/java/org/apache/zeppelin/jdbc/JDBCInterpreter.java
----------------------------------------------------------------------
diff --git a/jdbc/src/main/java/org/apache/zeppelin/jdbc/JDBCInterpreter.java 
b/jdbc/src/main/java/org/apache/zeppelin/jdbc/JDBCInterpreter.java
index c43e392..d495224 100644
--- a/jdbc/src/main/java/org/apache/zeppelin/jdbc/JDBCInterpreter.java
+++ b/jdbc/src/main/java/org/apache/zeppelin/jdbc/JDBCInterpreter.java
@@ -14,14 +14,7 @@
  */
 package org.apache.zeppelin.jdbc;
 
-import static org.apache.commons.lang.StringUtils.containsIgnoreCase;
-import static org.apache.commons.lang.StringUtils.isEmpty;
-import static org.apache.commons.lang.StringUtils.isNotEmpty;
-import static 
org.apache.hadoop.security.UserGroupInformation.AuthenticationMethod.KERBEROS;
-import java.io.ByteArrayOutputStream;
-import java.io.PrintStream;
 import java.io.IOException;
-import java.nio.charset.StandardCharsets;
 import java.security.PrivilegedExceptionAction;
 import java.sql.Connection;
 import java.sql.DriverManager;
@@ -37,11 +30,11 @@ import java.util.Map;
 import java.util.Properties;
 import java.util.Set;
 
-import com.google.common.base.Throwables;
 import org.apache.commons.dbcp2.ConnectionFactory;
 import org.apache.commons.dbcp2.DriverManagerConnectionFactory;
 import org.apache.commons.dbcp2.PoolableConnectionFactory;
 import org.apache.commons.dbcp2.PoolingDriver;
+import org.apache.commons.lang.StringUtils;
 import org.apache.commons.pool2.ObjectPool;
 import org.apache.commons.pool2.impl.GenericObjectPool;
 import org.apache.hadoop.conf.Configuration;
@@ -49,7 +42,10 @@ import org.apache.hadoop.security.UserGroupInformation;
 import org.apache.hadoop.security.alias.CredentialProvider;
 import org.apache.hadoop.security.alias.CredentialProviderFactory;
 import org.apache.thrift.transport.TTransportException;
-import org.apache.zeppelin.interpreter.*;
+import org.apache.zeppelin.interpreter.Interpreter;
+import org.apache.zeppelin.interpreter.InterpreterContext;
+import org.apache.zeppelin.interpreter.InterpreterException;
+import org.apache.zeppelin.interpreter.InterpreterResult;
 import org.apache.zeppelin.interpreter.InterpreterResult.Code;
 import org.apache.zeppelin.interpreter.thrift.InterpreterCompletion;
 import org.apache.zeppelin.jdbc.security.JDBCSecurityImpl;
@@ -61,9 +57,13 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import com.google.common.base.Function;
+import com.google.common.base.Throwables;
 import com.google.common.collect.Lists;
-import com.google.common.collect.Sets;
-import com.google.common.collect.Sets.SetView;
+
+import static org.apache.commons.lang.StringUtils.containsIgnoreCase;
+import static org.apache.commons.lang.StringUtils.isEmpty;
+import static org.apache.commons.lang.StringUtils.isNotEmpty;
+import static 
org.apache.hadoop.security.UserGroupInformation.AuthenticationMethod.KERBEROS;
 
 /**
  * JDBC interpreter for Zeppelin. This interpreter can also be used for 
accessing HAWQ,
@@ -103,6 +103,7 @@ public class JDBCInterpreter extends Interpreter {
   static final String PASSWORD_KEY = "password";
   static final String JDBC_JCEKS_FILE = "jceks.file";
   static final String JDBC_JCEKS_CREDENTIAL_KEY = "jceks.credentialKey";
+  static final String ZEPPELIN_JDBC_PRECODE_KEY = "zeppelin.jdbc.precode";
   static final String DOT = ".";
 
   private static final char WHITESPACE = ' ';
@@ -340,6 +341,9 @@ public class JDBCInterpreter extends Interpreter {
 
     if (!getJDBCConfiguration(user).isConnectionInDBDriverPool(propertyKey)) {
       createConnectionPool(url, user, propertyKey, properties);
+      try (Connection connection = DriverManager.getConnection(jdbcDriver)) {
+        executePrecode(connection);
+      }
     }
     return DriverManager.getConnection(jdbcDriver);
   }
@@ -540,6 +544,20 @@ public class JDBCInterpreter extends Interpreter {
     return queries;
   }
 
+  private void executePrecode(Connection connection) throws SQLException {
+    String precode = getProperty(ZEPPELIN_JDBC_PRECODE_KEY);
+    if (StringUtils.isNotBlank(precode)) {
+      precode = StringUtils.trim(precode);
+      logger.info("Run SQL precode '{}'", precode);
+      try (Statement statement = connection.createStatement()) {
+        statement.execute(precode);
+        if (!connection.getAutoCommit()) {
+          connection.commit();
+        }
+      }
+    }
+  }
+
   private InterpreterResult executeSql(String propertyKey, String sql,
       InterpreterContext interpreterContext) {
     Connection connection;
@@ -761,4 +779,3 @@ public class JDBCInterpreter extends Interpreter {
     }
   }
 }
-

http://git-wip-us.apache.org/repos/asf/zeppelin/blob/ebd5e1e9/jdbc/src/main/resources/interpreter-setting.json
----------------------------------------------------------------------
diff --git a/jdbc/src/main/resources/interpreter-setting.json 
b/jdbc/src/main/resources/interpreter-setting.json
index 20a900f..6134243 100644
--- a/jdbc/src/main/resources/interpreter-setting.json
+++ b/jdbc/src/main/resources/interpreter-setting.json
@@ -63,6 +63,12 @@
         "propertyName": "zeppelin.jdbc.principal",
         "defaultValue": "",
         "description": "Kerberos principal"
+      },
+      "zeppelin.jdbc.precode": {
+        "envName": null,
+        "propertyName": "zeppelin.jdbc.precode",
+        "defaultValue": "",
+        "description": "SQL which executes while opening connection"
       }
     },
     "editor": {

http://git-wip-us.apache.org/repos/asf/zeppelin/blob/ebd5e1e9/jdbc/src/test/java/org/apache/zeppelin/jdbc/JDBCInterpreterTest.java
----------------------------------------------------------------------
diff --git 
a/jdbc/src/test/java/org/apache/zeppelin/jdbc/JDBCInterpreterTest.java 
b/jdbc/src/test/java/org/apache/zeppelin/jdbc/JDBCInterpreterTest.java
index 9a041f9..197c368 100644
--- a/jdbc/src/test/java/org/apache/zeppelin/jdbc/JDBCInterpreterTest.java
+++ b/jdbc/src/test/java/org/apache/zeppelin/jdbc/JDBCInterpreterTest.java
@@ -43,6 +43,9 @@ import org.junit.Before;
 import org.junit.Test;
 
 import com.mockrunner.jdbc.BasicJDBCTestCaseAdapter;
+
+import static 
org.apache.zeppelin.jdbc.JDBCInterpreter.ZEPPELIN_JDBC_PRECODE_KEY;
+
 /**
  * JDBC interpreter unit tests
  */
@@ -386,4 +389,43 @@ public class JDBCInterpreterTest extends 
BasicJDBCTestCaseAdapter {
     assertNull(user2JDBC2Conf.getPropertyMap("default").get("password"));
     jdbc2.close();
   }
+
+  @Test
+  public void testPrecode() throws SQLException, IOException {
+    Properties properties = new Properties();
+    properties.setProperty("default.driver", "org.h2.Driver");
+    properties.setProperty("default.url", getJdbcConnection());
+    properties.setProperty("default.user", "");
+    properties.setProperty("default.password", "");
+    properties.setProperty(ZEPPELIN_JDBC_PRECODE_KEY, "SET @testVariable=1");
+    JDBCInterpreter jdbcInterpreter = new JDBCInterpreter(properties);
+    jdbcInterpreter.open();
+
+    String sqlQuery = "select @testVariable";
+
+    InterpreterResult interpreterResult = jdbcInterpreter.interpret(sqlQuery, 
interpreterContext);
+
+    assertEquals(InterpreterResult.Code.SUCCESS, interpreterResult.code());
+    assertEquals(InterpreterResult.Type.TABLE, 
interpreterResult.message().get(0).getType());
+    assertEquals("@TESTVARIABLE\n1\n", 
interpreterResult.message().get(0).getData());
+  }
+
+  @Test
+  public void testIncorrectPrecode() throws SQLException, IOException {
+    Properties properties = new Properties();
+    properties.setProperty("default.driver", "org.h2.Driver");
+    properties.setProperty("default.url", getJdbcConnection());
+    properties.setProperty("default.user", "");
+    properties.setProperty("default.password", "");
+    properties.setProperty(ZEPPELIN_JDBC_PRECODE_KEY, "incorrect command");
+    JDBCInterpreter jdbcInterpreter = new JDBCInterpreter(properties);
+    jdbcInterpreter.open();
+
+    String sqlQuery = "select 1";
+
+    InterpreterResult interpreterResult = jdbcInterpreter.interpret(sqlQuery, 
interpreterContext);
+
+    assertEquals(InterpreterResult.Code.ERROR, interpreterResult.code());
+    assertEquals(InterpreterResult.Type.TEXT, 
interpreterResult.message().get(0).getType());
+  }
  }

Reply via email to