Skip to content

Commit f084994

Browse files
Merge remote-tracking branch 'origin/master' into UserInInterpreterContext
# Conflicts: # zeppelin-server/src/test/java/org/apache/zeppelin/integration/ZeppelinIT.java
2 parents 3c979d2 + d2f9e64 commit f084994

File tree

18 files changed

+477
-75
lines changed

18 files changed

+477
-75
lines changed

bin/common.sh

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,6 @@ if [[ -z "${ZEPPELIN_LOG_DIR}" ]]; then
3636
export ZEPPELIN_LOG_DIR="${ZEPPELIN_HOME}/logs"
3737
fi
3838

39-
if [[ -z "${ZEPPELIN_NOTEBOOK_DIR}" ]]; then
40-
export ZEPPELIN_NOTEBOOK_DIR="${ZEPPELIN_HOME}/notebook"
41-
fi
42-
4339
if [[ -z "$ZEPPELIN_PID_DIR" ]]; then
4440
export ZEPPELIN_PID_DIR="${ZEPPELIN_HOME}/run"
4541
fi

bin/functions.sh

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
#!/bin/bash
22
#
3-
# Copyright 2007 The Apache Software Foundation
4-
#
53
# Licensed to the Apache Software Foundation (ASF) under one
64
# or more contributor license agreements. See the NOTICE file
75
# distributed with this work for additional information

bin/zeppelin-daemon.sh

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
#!/bin/bash
22
#
3-
# Copyright 2007 The Apache Software Foundation
4-
#
53
# Licensed to the Apache Software Foundation (ASF) under one
64
# or more contributor license agreements. See the NOTICE file
75
# distributed with this work for additional information
@@ -21,7 +19,7 @@
2119
# description: Start and stop daemon script for.
2220
#
2321

24-
USAGE="Usage: zeppelin-daemon.sh [--config <conf-dir>] {start|stop|restart|reload|status}"
22+
USAGE="Usage: zeppelin-daemon.sh [--config <conf-dir>] {start|stop|upstart|restart|reload|status}"
2523

2624
if [[ "$1" == "--config" ]]; then
2725
shift
@@ -93,11 +91,6 @@ function initialize_default_directories() {
9391
echo "Pid dir doesn't exist, create ${ZEPPELIN_PID_DIR}"
9492
$(mkdir -p "${ZEPPELIN_PID_DIR}")
9593
fi
96-
97-
if [[ ! -d "${ZEPPELIN_NOTEBOOK_DIR}" ]]; then
98-
echo "Notebook dir doesn't exist, create ${ZEPPELIN_NOTEBOOK_DIR}"
99-
$(mkdir -p "${ZEPPELIN_NOTEBOOK_DIR}")
100-
fi
10194
}
10295

10396
function wait_for_zeppelin_to_die() {
@@ -159,6 +152,16 @@ function check_if_process_is_alive() {
159152
fi
160153
}
161154

155+
function upstart() {
156+
157+
# upstart() allows zeppelin to be run and managed as a service
158+
# for example, this could be called from an upstart script in /etc/init
159+
# where the service manager starts and stops the process
160+
initialize_default_directories
161+
162+
$ZEPPELIN_RUNNER $JAVA_OPTS -cp $ZEPPELIN_CLASSPATH_OVERRIDES:$CLASSPATH $ZEPPELIN_MAIN >> "${ZEPPELIN_OUTFILE}"
163+
}
164+
162165
function start() {
163166
local pid
164167

@@ -241,6 +244,9 @@ case "${1}" in
241244
stop)
242245
stop
243246
;;
247+
upstart)
248+
upstart
249+
;;
244250
reload)
245251
stop
246252
start

bin/zeppelin.sh

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
#!/bin/bash
22
#
3-
# Copyright 2007 The Apache Software Foundation
4-
#
53
# Licensed to the Apache Software Foundation (ASF) under one
64
# or more contributor license agreements. See the NOTICE file
75
# distributed with this work for additional information
103 KB
Loading
80 KB
Loading

docs/install/install.md

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -235,3 +235,39 @@ After successful start, visit [http://localhost:8080](http://localhost:8080) wit
235235
```
236236
bin/zeppelin-daemon.sh stop
237237
```
238+
239+
#### Start Zeppelin with a service manager such as upstart
240+
241+
Zeppelin can auto start as a service with an init script, such as services managed by upstart.
242+
243+
The following is an example upstart script to be saved as `/etc/init/zeppelin.conf`
244+
This example has been tested with Ubuntu Linux.
245+
This also allows the service to be managed with commands such as
246+
247+
`sudo service zeppelin start`
248+
`sudo service zeppelin stop`
249+
`sudo service zeppelin restart`
250+
251+
Other service managers could use a similar approach with the `upstart` argument passed to the zeppelin-daemon.sh script: `bin/zeppelin-daemon.sh upstart`
252+
253+
##### zeppelin.conf
254+
255+
```
256+
description "zeppelin"
257+
258+
start on (local-filesystems and net-device-up IFACE!=lo)
259+
stop on shutdown
260+
261+
# Respawn the process on unexpected termination
262+
respawn
263+
264+
# respawn the job up to 7 times within a 5 second period.
265+
# If the job exceeds these values, it will be stopped and marked as failed.
266+
respawn limit 7 5
267+
268+
# zeppelin was installed in /usr/share/zeppelin in this example
269+
chdir /usr/share/zeppelin
270+
exec bin/zeppelin-daemon.sh upstart
271+
```
272+
273+

docs/interpreter/jdbc.md

Lines changed: 18 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -56,14 +56,15 @@ It is not necessary to add driver jar to the classpath for PostgreSQL as it is i
5656

5757
#### Simple connection
5858

59-
Before creating the interpreter it is necessary to add to the Zeppelin classpath the path of the JDBC you want to use, to do it you must edit the file `zeppelin-daemon.sh` as shown:
59+
Prior to creating the interpreter it is necessary to add maven coordinate or path of the JDBC driver to the Zeppelin classpath. To do this you must edit dependencies artifact(ex. `mysql:mysql-connector-java:5.1.38`) in interpreter menu as shown:
6060

61-
```
62-
# Add jdbc connector jar
63-
ZEPPELIN_CLASSPATH+=":${ZEPPELIN_HOME}/jdbc/jars/mysql-connector-java-5.1.6.jar"
64-
```
61+
<div class="row">
62+
<div class="col-md-11">
63+
<img src="../assets/themes/zeppelin/img/docs-img/jdbc-simple-connection-setting.png" />
64+
</div>
65+
</div>
6566

66-
For create the interpreter you need to specify connection parameters as shown in the table.
67+
To create the interpreter you need to specify connection parameters as shown in the table.
6768

6869
<table class="table-configuration">
6970
<tr>
@@ -94,14 +95,15 @@ For create the interpreter you need to specify connection parameters as shown in
9495

9596
#### Multiple connections
9697

97-
This JDBC interpreter also allows connections to multiple data sources. For every connection is necessary a prefix for reference in the paragraph this way `%jdbc(prefix)`. Before creating the interpreter it is necessary to add to the Zeppelin classpath all paths to access to each driver's jar file you want to use, to do it you must edit the file `zeppelin-daemon.sh` as following:
98+
JDBC interpreter also allows connections to multiple data sources. It is necessary to set a prefix for each connection to reference it in the paragraph in the form of `%jdbc(prefix)`. Before you create the interpreter it is necessary to add each driver's maven coordinates or JDBC driver's jar file path to the Zeppelin classpath. To do this you must edit the dependencies of JDBC interpreter in interpreter menu as following:
9899

99-
```
100-
# Add jdbc connector jar
101-
ZEPPELIN_CLASSPATH+=":${ZEPPELIN_HOME}/jdbc/jars/RedshiftJDBC41-1.1.10.1010.jar"
102-
ZEPPELIN_CLASSPATH+=":${ZEPPELIN_HOME}/jdbc/jars/mysql-connector-java-5.1.6.jar"
103-
```
104-
You can add all the jars you need to make multiple connections into the same interpreter. To create the interpreter you must specify the parameters, for example we will create two connections to PostgreSQL and Redshift, the respective prefixes are `default` and `redshift`:
100+
<div class="row">
101+
<div class="col-md-11">
102+
<img src="../assets/themes/zeppelin/img/docs-img/jdbc-multi-connection-setting.png" />
103+
</div>
104+
</div>
105+
106+
You can add all the jars you need to make multiple connections into the same JDBC interpreter. To create the interpreter you must specify the parameters. For example we will create two connections to MySQL and Redshift, the respective prefixes are `default` and `redshift`:
105107

106108
<table class="table-configuration">
107109
<tr>
@@ -114,19 +116,19 @@ You can add all the jars you need to make multiple connections into the same int
114116
</tr>
115117
<tr>
116118
<td>default.driver</td>
117-
<td>org.postgresql.Driver</td>
119+
<td>com.mysql.jdbc.Driver</td>
118120
</tr>
119121
<tr>
120122
<td>default.password</td>
121123
<td>********</td>
122124
</tr>
123125
<tr>
124126
<td>default.url</td>
125-
<td>jdbc:postgresql://localhost:5432/</td>
127+
<td>jdbc:mysql://localhost:3306/</td>
126128
</tr>
127129
<tr>
128130
<td>default.user</td>
129-
<td>gpadmin</td>
131+
<td>mysql-user</td>
130132
</tr>
131133
<tr>
132134
<td>redshift.driver</td>

jdbc/src/main/java/org/apache/zeppelin/jdbc/JDBCInterpreter.java

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -305,7 +305,15 @@ private InterpreterResult executeSql(String propertyKey, String sql,
305305
int displayRowCount = 0;
306306
while (resultSet.next() && displayRowCount < getMaxResult()) {
307307
for (int i = 1; i < md.getColumnCount() + 1; i++) {
308-
msg.append(replaceReservedChars(isTableType, resultSet.getString(i)));
308+
Object resultObject;
309+
String resultValue;
310+
resultObject = resultSet.getObject(i);
311+
if (resultObject == null) {
312+
resultValue = "null";
313+
} else {
314+
resultValue = resultSet.getString(i);
315+
}
316+
msg.append(replaceReservedChars(isTableType, resultValue));
309317
if (i != md.getColumnCount()) {
310318
msg.append(TAB);
311319
}

jdbc/src/test/java/org/apache/zeppelin/jdbc/JDBCInterpreterTest.java

Lines changed: 28 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,7 @@
2626
import java.io.IOException;
2727
import java.nio.file.Files;
2828
import java.nio.file.Path;
29-
import java.sql.Connection;
30-
import java.sql.DriverManager;
31-
import java.sql.SQLException;
32-
import java.sql.Statement;
29+
import java.sql.*;
3330
import java.util.Properties;
3431

3532
import org.apache.zeppelin.interpreter.InterpreterContext;
@@ -64,9 +61,10 @@ public void setUp() throws Exception {
6461
statement.execute(
6562
"DROP TABLE IF EXISTS test_table; " +
6663
"CREATE TABLE test_table(id varchar(255), name varchar(255));");
67-
statement.execute(
68-
"insert into test_table(id, name) values ('a', 'a_name'),('b', 'b_name');"
69-
);
64+
65+
PreparedStatement insertStatement = connection.prepareStatement("insert into test_table(id, name) values ('a', 'a_name'),('b', 'b_name'),('c', ?);");
66+
insertStatement.setString(1, null);
67+
insertStatement.execute();
7068
}
7169

7270

@@ -139,7 +137,7 @@ public void testSelectQuery() throws SQLException, IOException {
139137
JDBCInterpreter t = new JDBCInterpreter(properties);
140138
t.open();
141139

142-
String sqlQuery = "select * from test_table";
140+
String sqlQuery = "select * from test_table WHERE ID in ('a', 'b')";
143141

144142
InterpreterResult interpreterResult = t.interpret(sqlQuery, new InterpreterContext("", "1", "", "", null, null, null, null, null, null, null));
145143

@@ -148,6 +146,28 @@ public void testSelectQuery() throws SQLException, IOException {
148146
assertEquals("ID\tNAME\na\ta_name\nb\tb_name\n", interpreterResult.message());
149147
}
150148

149+
@Test
150+
public void testSelectQueryWithNull() throws SQLException, IOException {
151+
Properties properties = new Properties();
152+
properties.setProperty("common.max_count", "1000");
153+
properties.setProperty("common.max_retry", "3");
154+
properties.setProperty("default.driver", "org.h2.Driver");
155+
properties.setProperty("default.url", getJdbcConnection());
156+
properties.setProperty("default.user", "");
157+
properties.setProperty("default.password", "");
158+
JDBCInterpreter t = new JDBCInterpreter(properties);
159+
t.open();
160+
161+
String sqlQuery = "select * from test_table WHERE ID = 'c'";
162+
163+
InterpreterResult interpreterResult = t.interpret(sqlQuery, new InterpreterContext("", "1", "","", null,null,null,null,null,null));
164+
165+
assertEquals(InterpreterResult.Code.SUCCESS, interpreterResult.code());
166+
assertEquals(InterpreterResult.Type.TABLE, interpreterResult.type());
167+
assertEquals("ID\tNAME\nc\tnull\n", interpreterResult.message());
168+
}
169+
170+
151171
@Test
152172
public void testSelectQueryMaxResult() throws SQLException, IOException {
153173

0 commit comments

Comments
 (0)