Skip to content

Commit c255de9

Browse files
committed
Merge branch 'v2' into sp-159-upgrading-sailor
# Conflicts: # .gitignore # README.md # build.gradle # component.json # src/main/java/io/elastic/jdbc/ColumnNamesProvider.java # src/main/java/io/elastic/jdbc/Engines.java # src/main/java/io/elastic/jdbc/QueryBuilders/MSSQL.java # src/main/java/io/elastic/jdbc/QueryBuilders/MySQL.java # src/main/java/io/elastic/jdbc/QueryBuilders/Oracle.java # src/main/java/io/elastic/jdbc/QueryBuilders/Query.java # src/main/java/io/elastic/jdbc/TableNameProvider.java # src/main/java/io/elastic/jdbc/TriggerQueryFactory.java # src/main/java/io/elastic/jdbc/Utils.java # src/test/groovy/io/elastic/jdbc/ColumnNamesProviderMSSQLSpec.groovy # src/test/groovy/io/elastic/jdbc/TableNameProviderMSSQLSpec.groovy
2 parents d126d24 + c54c814 commit c255de9

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+4921
-0
lines changed

config/intellij-java-google-style.xml

Lines changed: 598 additions & 0 deletions
Large diffs are not rendered by default.

lib/ojdbc6.jar

176 KB
Binary file not shown.

lib/sqljdbc4.jar

-571 KB
Binary file not shown.
Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
package io.elastic.jdbc;
2+
3+
import io.elastic.api.DynamicMetadataProvider;
4+
import io.elastic.api.SelectModelProvider;
5+
import java.sql.Connection;
6+
import java.sql.DatabaseMetaData;
7+
import java.sql.ResultSet;
8+
import java.sql.SQLException;
9+
import java.sql.Types;
10+
import java.util.Map;
11+
import javax.json.Json;
12+
import javax.json.JsonObject;
13+
import javax.json.JsonObjectBuilder;
14+
import javax.json.JsonValue;
15+
import org.slf4j.Logger;
16+
import org.slf4j.LoggerFactory;
17+
18+
public class ColumnNamesProvider implements DynamicMetadataProvider, SelectModelProvider {
19+
20+
private static final Logger logger = LoggerFactory.getLogger(ColumnNamesProvider.class);
21+
22+
@Override
23+
public JsonObject getSelectModel(JsonObject configuration) {
24+
JsonObjectBuilder result = Json.createObjectBuilder();
25+
JsonObject properties = getColumns(configuration);
26+
for (Map.Entry<String, JsonValue> entry : properties.entrySet()) {
27+
JsonValue field = entry.getValue();
28+
result.add(entry.getKey(), entry.getKey());
29+
}
30+
return result.build();
31+
}
32+
33+
/**
34+
* Returns Columns list as metadata
35+
*/
36+
37+
@Override
38+
public JsonObject getMetaModel(JsonObject configuration) {
39+
JsonObjectBuilder result = Json.createObjectBuilder();
40+
JsonObjectBuilder inMetadata = Json.createObjectBuilder();
41+
JsonObjectBuilder outMetadata = Json.createObjectBuilder();
42+
JsonObject properties = getColumns(configuration);
43+
inMetadata.add("type", "object").add("properties", properties);
44+
outMetadata.add("type", "object").add("properties", properties);
45+
result.add("out", outMetadata.build()).add("in", inMetadata.build());
46+
return result.build();
47+
}
48+
49+
public JsonObject getColumns(JsonObject configuration) {
50+
if (configuration.getString("tableName") == null || configuration.getString("tableName")
51+
.isEmpty()) {
52+
throw new RuntimeException("Table name is required");
53+
}
54+
String tableName = configuration.getString("tableName");
55+
JsonObjectBuilder properties = Json.createObjectBuilder();
56+
Connection connection = null;
57+
ResultSet rs = null;
58+
String schemaName = null;
59+
boolean isEmpty = true;
60+
Boolean isOracle = (configuration.getString("dbEngine").equals("oracle")) ? true : false;
61+
Boolean isMssql = (configuration.getString("dbEngine").equals("mssql")) ? true : false;
62+
try {
63+
connection = Utils.getConnection(configuration);
64+
DatabaseMetaData dbMetaData = connection.getMetaData();
65+
rs = dbMetaData.getPrimaryKeys(null, null, tableName);
66+
if (tableName.contains(".")) {
67+
schemaName = tableName.split("\\.")[0];
68+
tableName = tableName.split("\\.")[1];
69+
}
70+
rs = dbMetaData.getColumns(null, schemaName, tableName, "%");
71+
while (rs.next()) {
72+
JsonObjectBuilder field = Json.createObjectBuilder();
73+
String name = rs.getString("COLUMN_NAME");
74+
Boolean isRequired = false;
75+
if (isMssql) {
76+
String isAutoincrement =
77+
(rs.getString("IS_AUTOINCREMENT") != null) ? rs.getString("IS_AUTOINCREMENT") : "";
78+
Integer isNullable = (rs.getObject("NULLABLE") != null) ? rs.getInt("NULLABLE") : 1;
79+
isRequired = isNullable == 0 && !isAutoincrement.equals("YES");
80+
} else {
81+
isRequired = false;
82+
}
83+
field.add("required", isRequired)
84+
.add("title", name)
85+
.add("type", convertType(rs.getInt("DATA_TYPE")));
86+
properties.add(name, field.build());
87+
isEmpty = false;
88+
}
89+
if (isEmpty) {
90+
properties.add("empty dataset", "no columns");
91+
}
92+
93+
} catch (SQLException e) {
94+
throw new RuntimeException(e);
95+
} finally {
96+
if (rs != null) {
97+
try {
98+
rs.close();
99+
} catch (SQLException e) {
100+
logger.error("Failed to close result set {}", e.toString());
101+
}
102+
}
103+
if (connection != null) {
104+
try {
105+
connection.close();
106+
} catch (SQLException e) {
107+
logger.error("Failed to close connection {}", e.toString());
108+
}
109+
}
110+
}
111+
return properties.build();
112+
}
113+
114+
/**
115+
* Converts JDBC column type name to js type according to http://db.apache.org/ojb/docu/guides/jdbc-types.html
116+
*
117+
* @param sqlType JDBC column type
118+
* @url http://db.apache.org/ojb/docu/guides/jdbc-types.html
119+
*/
120+
private String convertType(Integer sqlType) {
121+
if (sqlType == Types.NUMERIC || sqlType == Types.DECIMAL || sqlType == Types.TINYINT
122+
|| sqlType == Types.SMALLINT || sqlType == Types.INTEGER || sqlType == Types.BIGINT
123+
|| sqlType == Types.REAL || sqlType == Types.FLOAT || sqlType == Types.DOUBLE) {
124+
return "number";
125+
}
126+
if (sqlType == Types.BIT || sqlType == Types.BOOLEAN) {
127+
return "boolean";
128+
}
129+
return "string";
130+
}
131+
}
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
package io.elastic.jdbc;
2+
3+
public enum Engines {
4+
MYSQL("com.mysql.cj.jdbc.Driver", 3306) {
5+
@Override
6+
protected String getSubprotocol(String host, Integer port, String db) {
7+
return "mysql";
8+
}
9+
10+
@Override
11+
protected String getSubname(String host, Integer port, String db) {
12+
return String.format("//%s:%s/%s", host, port, db);
13+
}
14+
},
15+
16+
HSQLDB("org.hsqldb.jdbcDriver", null) {
17+
@Override
18+
protected String getSubprotocol(String host, Integer port, String db) {
19+
return "hsqldb";
20+
}
21+
22+
@Override
23+
protected String getSubname(String host, Integer port, String db) {
24+
return db;
25+
}
26+
},
27+
28+
POSTGRESQL("org.postgresql.Driver", 5432) {
29+
@Override
30+
protected String getSubprotocol(String host, Integer port, String db) {
31+
return "postgresql";
32+
}
33+
},
34+
35+
ORACLE("oracle.jdbc.driver.OracleDriver", 1521) {
36+
@Override
37+
protected String getSubprotocol(String host, Integer port, String db) {
38+
return "oracle:thin";
39+
}
40+
41+
@Override
42+
protected String getSubname(String host, Integer port, String db) {
43+
return String.format("@//%s:%s", host, port);
44+
}
45+
},
46+
47+
MSSQL("com.microsoft.sqlserver.jdbc.SQLServerDriver", 1433) {
48+
@Override
49+
protected String getSubprotocol(String host, Integer port, String db) {
50+
return "sqlserver";
51+
}
52+
53+
@Override
54+
protected String getSubname(String host, Integer port, String db) {
55+
return String.format("//%s:%s;databaseName=%s", host, port, db);
56+
}
57+
};
58+
59+
private final String driverClassName;
60+
private Integer defaultPort;
61+
62+
Engines(final String driverClassName, final Integer defaultPort) {
63+
this.driverClassName = driverClassName;
64+
this.defaultPort = defaultPort;
65+
}
66+
67+
protected abstract String getSubprotocol(String host, Integer port, String db);
68+
69+
protected String getSubname(String host, Integer port, String db) {
70+
return String.format("//%s:%s/%s", host, port, db);
71+
}
72+
73+
public String getConnectionString(String host, Integer port, String db) {
74+
return String.format("jdbc:%s:%s",
75+
getSubprotocol(host, port, db),
76+
getSubname(host, port, db));
77+
}
78+
79+
public void loadDriverClass() {
80+
try {
81+
Class.forName(driverClassName);
82+
} catch (ClassNotFoundException e) {
83+
throw new RuntimeException(e);
84+
}
85+
}
86+
87+
public Integer defaultPort() {
88+
return defaultPort;
89+
}
90+
}
Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
package io.elastic.jdbc;
2+
3+
import io.elastic.api.DynamicMetadataProvider;
4+
import io.elastic.api.SelectModelProvider;
5+
import java.sql.Connection;
6+
import java.sql.DatabaseMetaData;
7+
import java.sql.ResultSet;
8+
import java.sql.SQLException;
9+
import java.sql.Types;
10+
import java.util.ArrayList;
11+
import java.util.List;
12+
import java.util.Map;
13+
import javax.json.Json;
14+
import javax.json.JsonObject;
15+
import javax.json.JsonObjectBuilder;
16+
import javax.json.JsonValue;
17+
import org.slf4j.Logger;
18+
import org.slf4j.LoggerFactory;
19+
20+
public class PrimaryColumnNamesProvider implements DynamicMetadataProvider, SelectModelProvider {
21+
22+
private static final Logger logger = LoggerFactory.getLogger(PrimaryColumnNamesProvider.class);
23+
24+
public JsonObject getSelectModel(JsonObject configuration) {
25+
JsonObject result = Json.createObjectBuilder().build();
26+
JsonObject properties = getPrimaryColumns(configuration);
27+
for (Map.Entry<String, JsonValue> entry : properties.entrySet()) {
28+
JsonValue field = entry.getValue();
29+
result = Json.createObjectBuilder().add(entry.getKey(), field.toString()).build();
30+
}
31+
return result;
32+
}
33+
34+
/**
35+
* Returns Columns list as metadata
36+
*/
37+
38+
public JsonObject getMetaModel(JsonObject configuration) {
39+
JsonObject result = Json.createObjectBuilder().build();
40+
JsonObject inMetadata = Json.createObjectBuilder().build();
41+
JsonObject properties = getPrimaryColumns(configuration);
42+
inMetadata = Json.createObjectBuilder().add("type", "object")
43+
.add("properties", properties).build();
44+
result = Json.createObjectBuilder().add("out", inMetadata)
45+
.add("in", inMetadata).build();
46+
return result;
47+
}
48+
49+
public JsonObject getPrimaryColumns(JsonObject configuration) {
50+
if (configuration.getString("tableName") == null || configuration.getString("tableName")
51+
.isEmpty()) {
52+
throw new RuntimeException("Table name is required");
53+
}
54+
String tableName = configuration.getString("tableName");
55+
JsonObject properties = Json.createObjectBuilder().build();
56+
Connection connection = null;
57+
ResultSet rs = null;
58+
String schemaName = null;
59+
Boolean isEmpty = true;
60+
Boolean isOracle = (configuration.getString("dbEngine").equals("oracle")) ? true : false;
61+
Boolean isMssql = (configuration.getString("dbEngine").equals("mssql")) ? true : false;
62+
List<String> primaryKeys = new ArrayList();
63+
try {
64+
connection = Utils.getConnection(configuration);
65+
DatabaseMetaData dbMetaData = connection.getMetaData();
66+
if (tableName.contains(".")) {
67+
schemaName =
68+
(isOracle) ? tableName.split("\\.")[0].toUpperCase() : tableName.split("\\.")[0];
69+
tableName =
70+
(isOracle) ? tableName.split("\\.")[1].toUpperCase() : tableName.split("\\.")[1];
71+
}
72+
rs = dbMetaData
73+
.getPrimaryKeys(null, ((isOracle && !schemaName.isEmpty()) ? schemaName : null),
74+
tableName);
75+
while (rs.next()) {
76+
primaryKeys.add(rs.getString("COLUMN_NAME"));
77+
logger.info("Primary Key: {}", rs.getString("COLUMN_NAME"));
78+
}
79+
rs = dbMetaData
80+
.getColumns(null, ((isOracle && !schemaName.isEmpty()) ? schemaName : null), tableName,
81+
"%");
82+
while (rs.next()) {
83+
if (primaryKeys.contains(rs.getString("COLUMN_NAME"))) {
84+
JsonObjectBuilder field = Json.createObjectBuilder();
85+
String name = rs.getString("COLUMN_NAME");
86+
Boolean isRequired = false;
87+
if (isMssql) {
88+
String isAutoincrement =
89+
(rs.getString("IS_AUTOINCREMENT") != null) ? rs.getString("IS_AUTOINCREMENT") : "";
90+
Integer isNullable = (rs.getObject("NULLABLE") != null) ? rs.getInt("NULLABLE") : 1;
91+
isRequired = isNullable == 0 && !isAutoincrement.equals("YES");
92+
} else {
93+
isRequired = true;
94+
}
95+
field.add("required", isRequired)
96+
.add("title", name)
97+
.add("type", convertType(rs.getInt("DATA_TYPE")));
98+
properties = Json.createObjectBuilder().add(name, field.build()).build();
99+
isEmpty = false;
100+
}
101+
}
102+
if (isEmpty) {
103+
logger.info("Empty PK list - no primary keys");
104+
throw new IllegalStateException("No Primary Keys");
105+
}
106+
107+
} catch (SQLException e) {
108+
throw new RuntimeException(e);
109+
} finally {
110+
if (rs != null) {
111+
try {
112+
rs.close();
113+
} catch (SQLException e) {
114+
logger.error("Failed to close result set", e.toString());
115+
}
116+
}
117+
if (connection != null) {
118+
try {
119+
connection.close();
120+
} catch (SQLException e) {
121+
logger.error("Failed to close connection", e.toString());
122+
}
123+
}
124+
}
125+
return properties;
126+
}
127+
128+
/**
129+
* Converts JDBC column type name to js type according to http://db.apache.org/ojb/docu/guides/jdbc-types.html
130+
*
131+
* @param sqlType JDBC column type
132+
* @url http://db.apache.org/ojb/docu/guides/jdbc-types.html
133+
*/
134+
private String convertType(Integer sqlType) {
135+
if (sqlType == Types.NUMERIC || sqlType == Types.DECIMAL || sqlType == Types.TINYINT
136+
|| sqlType == Types.SMALLINT || sqlType == Types.INTEGER || sqlType == Types.BIGINT
137+
|| sqlType == Types.REAL || sqlType == Types.FLOAT || sqlType == Types.DOUBLE) {
138+
return "number";
139+
}
140+
if (sqlType == Types.BIT || sqlType == Types.BOOLEAN) {
141+
return "boolean";
142+
}
143+
return "string";
144+
}
145+
}

0 commit comments

Comments
 (0)