Skip to content

Commit

Permalink
Add a simple DataSource implementation
Browse files Browse the repository at this point in the history
Implement the DataSource interface to be more compatible with JDBC spec.

Add JDBC standard and Tarantool specific properties (getters/setters) to
follow enterprise features (according to JavaBeans spec).

Fix a JDBC URL scheme. Now correct scheme has the format like
'jdbc:tarantool://' where `tarantool` is JDBC sub-protocol. Old scheme
version `tarantool://` was not JDBC-compatible.

Closes: #175
  • Loading branch information
nicktorwald committed May 21, 2019
1 parent e32b3d8 commit 2c9cd80
Show file tree
Hide file tree
Showing 14 changed files with 416 additions and 25 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -138,13 +138,13 @@ To configure socket channel provider you should implements SocketChannelProvider
For example:

```
tarantool://localhost:3301?user=test&password=test&socketProvider=abc.xyz.MySocketProvider
jdbc:tarantool://localhost:3301?user=test&password=test&socketProvider=abc.xyz.MySocketProvider
```

Here is an example how you can use the driver covered by Spring `DriverManagerDataSource`:

```java
NamedParameterJdbcTemplate template = new NamedParameterJdbcTemplate(new DriverManagerDataSource("tarantool://localhost:3301?user=test&password=test"));
NamedParameterJdbcTemplate template = new NamedParameterJdbcTemplate(new DriverManagerDataSource("jdbc:tarantool://localhost:3301?user=test&password=test"));
RowMapper<Object> rowMapper = new RowMapper<Object>() {
@Override
public Object mapRow(ResultSet resultSet, int i) throws SQLException {
Expand Down
2 changes: 1 addition & 1 deletion src/it/java/org/tarantool/TestSql.java
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
//
// public static void main(String[] args) throws IOException, SQLException {
//
// NamedParameterJdbcTemplate template = new NamedParameterJdbcTemplate(new DriverManagerDataSource("tarantool://localhost:3301?username=test&password=test&socketProvider=org.tarantool.TestSql$TestSocketProvider"));
// NamedParameterJdbcTemplate template = new NamedParameterJdbcTemplate(new DriverManagerDataSource("jdbc:tarantool://localhost:3301?username=test&password=test&socketProvider=org.tarantool.TestSql$TestSocketProvider"));
// RowMapper<Object> rowMapper = new RowMapper<Object>() {
// @Override
// public Object mapRow(ResultSet resultSet, int i) throws SQLException {
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/org/tarantool/jdbc/SQLConnection.java
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ public class SQLConnection implements Connection {
private DatabaseMetaData cachedMetadata;
private int resultSetHoldability = UNSET_HOLDABILITY;

SQLConnection(String url, Properties properties) throws SQLException {
public SQLConnection(String url, Properties properties) throws SQLException {
this.url = url;
this.properties = properties;

Expand Down
10 changes: 10 additions & 0 deletions src/main/java/org/tarantool/jdbc/SQLConstant.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package org.tarantool.jdbc;

public class SQLConstant {

private SQLConstant() {
}

public static final String DRIVER_NAME = "Tarantool JDBC Driver";

}
2 changes: 1 addition & 1 deletion src/main/java/org/tarantool/jdbc/SQLDatabaseMetadata.java
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ public String getDatabaseProductVersion() throws SQLException {

@Override
public String getDriverName() throws SQLException {
return "tarantool-java";
return SQLConstant.DRIVER_NAME;
}

@Override
Expand Down
5 changes: 4 additions & 1 deletion src/main/java/org/tarantool/jdbc/SQLDriver.java
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,9 @@ protected SQLTarantoolClientImpl makeSqlClient(String address, TarantoolClientCo
protected Properties parseQueryString(URI uri, Properties info) throws SQLException {
Properties urlProperties = new Properties();

// get scheme specific part (after the scheme part "jdbc:")
// to correct parse remaining URL
uri = URI.create(uri.getSchemeSpecificPart());
String userInfo = uri.getUserInfo();
if (userInfo != null) {
// Get user and password from the corresponding part of the URI, i.e. before @ sign.
Expand Down Expand Up @@ -140,7 +143,7 @@ protected SocketChannelProvider getSocketProviderInstance(String className) thro

@Override
public boolean acceptsURL(String url) throws SQLException {
return url.toLowerCase().startsWith("tarantool:");
return url.toLowerCase().startsWith("jdbc:tarantool:");
}

@Override
Expand Down
6 changes: 5 additions & 1 deletion src/main/java/org/tarantool/jdbc/SQLProperty.java
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ public enum SQLProperty {
LOGIN_TIMEOUT(
"loginTimeout",
"The number of milliseconds to wait for connection establishment. " +
"The default value is 60000 (1 minute).",
"The default system value is 60000 (1 minute).",
"60000",
null,
false
Expand Down Expand Up @@ -84,6 +84,10 @@ public String getDefaultValue() {
return defaultValue;
}

public int getDefaultIntValue() {
return Integer.parseInt(defaultValue);
}

public boolean isRequired() {
return required;
}
Expand Down
159 changes: 159 additions & 0 deletions src/main/java/org/tarantool/jdbc/ds/SQLDataSource.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
package org.tarantool.jdbc.ds;

import org.tarantool.jdbc.SQLConnection;
import org.tarantool.jdbc.SQLConstant;
import org.tarantool.jdbc.SQLProperty;

import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.SQLFeatureNotSupportedException;
import java.sql.SQLNonTransientException;
import java.util.Properties;
import java.util.concurrent.TimeUnit;
import java.util.logging.Logger;
import javax.sql.DataSource;

/**
* Simple {@code java.sql.DataSource} implementation.
*/
public class SQLDataSource implements TarantoolDataSource, DataSource {

private PrintWriter logWriter;
private String name = "Tarantool basic data source";

private Properties properties = new Properties();

@Override
public Connection getConnection() throws SQLException {
return new SQLConnection(makeUrl(), new Properties(properties));
}

@Override
public Connection getConnection(String username, String password) throws SQLException {
Properties copyProperties = new Properties(properties);
SQLProperty.USER.setString(copyProperties, username);
SQLProperty.PASSWORD.setString(copyProperties, password);
return new SQLConnection(makeUrl(), copyProperties);
}

@Override
public PrintWriter getLogWriter() {
return logWriter;
}

@Override
public void setLogWriter(PrintWriter out) {
logWriter = out;
}

@Override
public void setLoginTimeout(int seconds) {
SQLProperty.LOGIN_TIMEOUT.setInt(properties, (int) TimeUnit.SECONDS.toMillis(seconds));
}

@Override
public int getLoginTimeout() throws SQLException {
return (int) TimeUnit.MILLISECONDS.toSeconds(SQLProperty.LOGIN_TIMEOUT.getInt(properties));
}

@Override
public Logger getParentLogger() throws SQLFeatureNotSupportedException {
throw new SQLFeatureNotSupportedException();
}

@Override
public <T> T unwrap(Class<T> type) throws SQLException {
if (isWrapperFor(type)) {
return type.cast(this);
}
throw new SQLNonTransientException("SQLDataSource does not wrap " + type.getName());
}

@Override
public boolean isWrapperFor(Class<?> type) {
return type.isAssignableFrom(this.getClass());
}

@Override
public String getServerName() {
return SQLProperty.HOST.getString(properties);
}

@Override
public void setServerName(String serverName) {
SQLProperty.HOST.setString(properties, serverName);
}

@Override
public int getPortNumber() throws SQLException {
return SQLProperty.PORT.getInt(properties);
}

@Override
public void setPortNumber(int port) {
SQLProperty.PORT.setInt(properties, port);
}

@Override
public String getUser() {
return SQLProperty.USER.getString(properties);
}

@Override
public void setUser(String userName) {
SQLProperty.USER.setString(properties, userName);
}

@Override
public String getPassword() {
return SQLProperty.PASSWORD.getString(properties);
}

@Override
public void setPassword(String password) {
SQLProperty.PASSWORD.setString(properties, password);
}

@Override
public String getDescription() {
return "Basic DataSource implementation - produces a standard Connection object. " +
SQLConstant.DRIVER_NAME + ".";
}

@Override
public String getDataSourceName() {
return name;
}

@Override
public void setDataSourceName(String name) {
this.name = name;
}

@Override
public String getSocketChannelProvider() {
return SQLProperty.SOCKET_CHANNEL_PROVIDER.getString(properties);
}

@Override
public void setSocketChannelProvider(String classFqdn) {
SQLProperty.SOCKET_CHANNEL_PROVIDER.setString(properties, classFqdn);
}

@Override
public int getQueryTimeout() throws SQLException {
return (int) TimeUnit.MILLISECONDS.toSeconds(SQLProperty.QUERY_TIMEOUT.getInt(properties));
}

@Override
public void setQueryTimeout(int seconds) {
SQLProperty.QUERY_TIMEOUT.setInt(properties, (int) TimeUnit.SECONDS.toMillis(seconds));
}

private String makeUrl() {
return "jdbc:tarantool://" +
SQLProperty.HOST.getString(properties) + ":" + SQLProperty.PORT.getString(properties);
}

}
40 changes: 40 additions & 0 deletions src/main/java/org/tarantool/jdbc/ds/TarantoolDataSource.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package org.tarantool.jdbc.ds;

import java.sql.SQLException;

/**
* JDBC standard Tarantool specific data source properties.
*/
public interface TarantoolDataSource {

String getServerName() throws SQLException;

void setServerName(String serverName) throws SQLException;

int getPortNumber() throws SQLException;

void setPortNumber(int port) throws SQLException;

String getUser() throws SQLException;

void setUser(String userName) throws SQLException;

String getPassword() throws SQLException;

void setPassword(String password) throws SQLException;

String getDescription() throws SQLException;

String getDataSourceName() throws SQLException;

void setDataSourceName(String name) throws SQLException;

String getSocketChannelProvider() throws SQLException;

void setSocketChannelProvider(String classFqdn) throws SQLException;

int getQueryTimeout() throws SQLException;

void setQueryTimeout(int seconds) throws SQLException;

}
2 changes: 1 addition & 1 deletion src/test/java/org/tarantool/jdbc/AbstractJdbcIT.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ public abstract class AbstractJdbcIT {
private static final Integer port = Integer.valueOf(System.getProperty("tntPort", "3301"));
private static final String user = System.getProperty("tntUser", "test_admin");
private static final String pass = System.getProperty("tntPass", "4pWBZmLEgkmKK5WP");
private static String URL = String.format("tarantool://%s:%d?user=%s&password=%s", host, port, user, pass);
private static String URL = String.format("jdbc:tarantool://%s:%d?user=%s&password=%s", host, port, user, pass);

protected static final String LUA_FILE = "jdk-testing.lua";
protected static final int LISTEN = 3301;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,7 @@ public void testGetDriverNameVersion() throws SQLException {
String version = meta.getDriverVersion();

// Verify driver name.
assertEquals("tarantool-java", name);
assertEquals(SQLConstant.DRIVER_NAME, name);

// Verify driver version format.
// E.g. 1.7.6 or 1.7.6-SNAPSHOT.
Expand Down
Loading

0 comments on commit 2c9cd80

Please sign in to comment.