Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion LICENSE
Original file line number Diff line number Diff line change
Expand Up @@ -256,4 +256,12 @@ The following components are provided under the BSD 3-Clause license. See file
r/src/main/scala/org/apache/zeppelin/rinterpreter/rscala/{Package.scala, RClient.scala}

(BSD 3 Clause) portions of Scala (http://www.scala-lang.org/download) - http://www.scala-lang.org/download/#License
r/src/main/scala/scala/Console.scala
r/src/main/scala/scala/Console.scala

========================================================================
BSD 2-Clause licenses
========================================================================
The following components are provided under the BSD 3-Clause license. See file headers and project links for details.

(BSD 2 Clause) portions of SQLLine (http://sqlline.sourceforge.net/) - http://sqlline.sourceforge.net/#license
jdbc/src/main/java/org/apache/zeppelin/jdbc/SqlCompleter.java
42 changes: 42 additions & 0 deletions docs/interpreter/postgresql.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,49 @@ group: manual
---
{% include JB/setup %}

## Important Notice
Postgresql Interpreter will be deprecated and merged into JDBC Interpreter. You can use Postgresql by using JDBC Interpreter with same functionality. See the example below of settings and dependencies.

### Properties
<table class="table-configuration">
<tr>
<th>Property</th>
<th>Value</th>
</tr>
<tr>
<td>psql.driver</td>
<td>org.postgresql.Driver</td>
</tr>
<tr>
<td>psql.url</td>
<td>jdbc:postgresql://localhost:5432/</td>
</tr>
<tr>
<td>psql.user</td>
<td>psqlUser</td>
</tr>
<tr>
<td>psql.password</td>
<td>psqlPassword</td>
</tr>
</table>

### Dependencies
<table class="table-configuration">
<tr>
<th>Artifact</th>
<th>Exclude</th>
</tr>
<tr>
<td>org.postgresql:postgresql:9.4-1201-jdbc41</td>
<td></td>
</tr>
</table>

----

## PostgreSQL, HAWQ Interpreter for Apache Zeppelin

<table class="table-configuration">
<tr>
<th>Name</th>
Expand Down
90 changes: 67 additions & 23 deletions jdbc/src/main/java/org/apache/zeppelin/jdbc/JDBCInterpreter.java
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,6 @@

import org.apache.zeppelin.interpreter.Interpreter;
import org.apache.zeppelin.interpreter.InterpreterContext;
import org.apache.zeppelin.interpreter.InterpreterException;
import org.apache.zeppelin.interpreter.InterpreterPropertyBuilder;
import org.apache.zeppelin.interpreter.InterpreterResult;
import org.apache.zeppelin.interpreter.InterpreterResult.Code;
import org.apache.zeppelin.scheduler.Scheduler;
Expand All @@ -50,30 +48,29 @@
/**
* JDBC interpreter for Zeppelin. This interpreter can also be used for accessing HAWQ,
* GreenplumDB, MariaDB, MySQL, Postgres and Redshit.
*
*
* <ul>
* <li>{@code default.url} - JDBC URL to connect to.</li>
* <li>{@code default.user} - JDBC user name..</li>
* <li>{@code default.password} - JDBC password..</li>
* <li>{@code default.driver.name} - JDBC driver name.</li>
* <li>{@code common.max.result} - Max number of SQL result to display.</li>
* </ul>
*
*
* <p>
* How to use: <br/>
* {@code %jdbc.sql} <br/>
* {@code
* SELECT store_id, count(*)
* FROM retail_demo.order_lineitems_pxf
* GROUP BY store_id;
* {@code
* SELECT store_id, count(*)
* FROM retail_demo.order_lineitems_pxf
* GROUP BY store_id;
* }
* </p>
*
*/
public class JDBCInterpreter extends Interpreter {

private Logger logger = LoggerFactory.getLogger(JDBCInterpreter.class);

static final String COMMON_KEY = "common";
static final String MAX_LINE_KEY = "max_count";
static final String MAX_LINE_DEFAULT = "1000";
Expand All @@ -84,7 +81,7 @@ public class JDBCInterpreter extends Interpreter {
static final String USER_KEY = "user";
static final String PASSWORD_KEY = "password";
static final String DOT = ".";

private static final char WHITESPACE = ' ';
private static final char NEWLINE = '\n';
private static final char TAB = '\t';
Expand All @@ -100,21 +97,33 @@ public class JDBCInterpreter extends Interpreter {
static final String DEFAULT_PASSWORD = DEFAULT_KEY + DOT + PASSWORD_KEY;

static final String EMPTY_COLUMN_VALUE = "";

private final HashMap<String, Properties> propertiesMap;
private final Map<String, Statement> paragraphIdStatementMap;

private final Map<String, ArrayList<Connection>> propertyKeyUnusedConnectionListMap;
private final Map<String, Connection> paragraphIdConnectionMap;

private final Map<String, SqlCompleter> propertyKeySqlCompleterMap;

private static final Function<CharSequence, String> sequenceToStringTransformer =
new Function<CharSequence, String>() {
public String apply(CharSequence seq) {
return seq.toString();
}
};

private static final List<String> NO_COMPLETION = new ArrayList<>();

public JDBCInterpreter(Properties property) {
super(property);
propertiesMap = new HashMap<>();
propertyKeyUnusedConnectionListMap = new HashMap<>();
paragraphIdStatementMap = new HashMap<>();
paragraphIdConnectionMap = new HashMap<>();
propertyKeySqlCompleterMap = new HashMap<>();
}

public HashMap<String, Properties> getPropertiesMap() {
return propertiesMap;
}
Expand Down Expand Up @@ -154,9 +163,38 @@ public void open() {
}

logger.debug("propertiesMap: {}", propertiesMap);

Connection connection = null;
SqlCompleter sqlCompleter = null;
for (String propertyKey : propertiesMap.keySet()) {
try {
connection = getConnection(propertyKey);
sqlCompleter = createSqlCompleter(connection);
} catch (Exception e) {
sqlCompleter = createSqlCompleter(null);
}
propertyKeySqlCompleterMap.put(propertyKey, sqlCompleter);
}
}

public Connection getConnection(String propertyKey) throws ClassNotFoundException, SQLException {

private SqlCompleter createSqlCompleter(Connection jdbcConnection) {

SqlCompleter completer = null;
try {
Set<String> keywordsCompletions = SqlCompleter.getSqlKeywordsCompletions(jdbcConnection);
Set<String> dataModelCompletions =
SqlCompleter.getDataModelMetadataCompletions(jdbcConnection);
SetView<String> allCompletions = Sets.union(keywordsCompletions, dataModelCompletions);
completer = new SqlCompleter(allCompletions, dataModelCompletions);

} catch (IOException | SQLException e) {
logger.error("Cannot create SQL completer", e);
}

return completer;
}

public Connection getConnection(String propertyKey) throws ClassNotFoundException, SQLException {
Connection connection = null;
if (propertyKey == null || propertiesMap.get(propertyKey) == null) {
return null;
Expand All @@ -180,7 +218,7 @@ public Connection getConnection(String propertyKey) throws ClassNotFoundExcepti
}
return connection;
}

public Statement getStatement(String propertyKey, String paragraphId)
throws SQLException, ClassNotFoundException {
Connection connection;
Expand All @@ -189,7 +227,7 @@ public Statement getStatement(String propertyKey, String paragraphId)
} else {
connection = getConnection(propertyKey);
}

if (connection == null) {
return null;
}
Expand All @@ -213,7 +251,7 @@ private boolean isStatementClosed(Statement statement) {
return false;
}
}

@Override
public void close() {

Expand Down Expand Up @@ -241,13 +279,13 @@ public void close() {

private InterpreterResult executeSql(String propertyKey, String sql,
InterpreterContext interpreterContext) {

String paragraphId = interpreterContext.getParagraphId();

try {

Statement statement = getStatement(propertyKey, paragraphId);

if (statement == null) {
return new InterpreterResult(Code.ERROR, "Prefix not found.");
}
Expand Down Expand Up @@ -346,7 +384,7 @@ public InterpreterResult interpret(String cmd, InterpreterContext contextInterpr
if (null != propertyKey && !propertyKey.equals(DEFAULT_KEY)) {
cmd = cmd.substring(propertyKey.length() + 2);
}

cmd = cmd.trim();

logger.info("PropertyKey: {}, SQL command: '{}'", propertyKey, cmd);
Expand Down Expand Up @@ -382,7 +420,7 @@ public String getPropertyKey(String cmd) {
return DEFAULT_KEY;
}
}

@Override
public FormType getFormType() {
return FormType.SIMPLE;
Expand All @@ -401,7 +439,13 @@ public Scheduler getScheduler() {

@Override
public List<String> completion(String buf, int cursor) {
return null;
List<CharSequence> candidates = new ArrayList<>();
SqlCompleter sqlCompleter = propertyKeySqlCompleterMap.get(getPropertyKey(buf));
if (sqlCompleter != null && sqlCompleter.complete(buf, cursor, candidates) >= 0) {
return Lists.transform(candidates, sequenceToStringTransformer);
} else {
return NO_COMPLETION;
}
}

public int getMaxResult() {
Expand Down
Loading