embulk-input-athena 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +13 -0
- data/Dockerfile +8 -0
- data/LICENSE +21 -0
- data/README.md +46 -0
- data/build.gradle +101 -0
- data/config/checkstyle/checkstyle.xml +128 -0
- data/config/checkstyle/default.xml +108 -0
- data/docker-compose.yml +10 -0
- data/gradle/wrapper/gradle-wrapper.jar +0 -0
- data/gradle/wrapper/gradle-wrapper.properties +5 -0
- data/gradlew +172 -0
- data/gradlew.bat +84 -0
- data/lib/embulk/input/athena.rb +3 -0
- data/src/main/java/org/embulk/input/athena/AthenaInputConnection.java +49 -0
- data/src/main/java/org/embulk/input/athena/AthenaInputPlugin.java +202 -0
- data/src/main/java/org/embulk/input/athena/AthenaInputPlugin.java.tmp1 +192 -0
- data/src/main/java/org/embulk/input/jdbc/AbstractJdbcInputPlugin.java +674 -0
- data/src/main/java/org/embulk/input/jdbc/JdbcColumn.java +58 -0
- data/src/main/java/org/embulk/input/jdbc/JdbcColumnOption.java +31 -0
- data/src/main/java/org/embulk/input/jdbc/JdbcInputConnection.java +397 -0
- data/src/main/java/org/embulk/input/jdbc/JdbcLiteral.java +38 -0
- data/src/main/java/org/embulk/input/jdbc/JdbcSchema.java +55 -0
- data/src/main/java/org/embulk/input/jdbc/Ssl.java +37 -0
- data/src/main/java/org/embulk/input/jdbc/ToString.java +54 -0
- data/src/main/java/org/embulk/input/jdbc/ToStringMap.java +35 -0
- data/src/main/java/org/embulk/input/jdbc/getter/AbstractColumnGetter.java +105 -0
- data/src/main/java/org/embulk/input/jdbc/getter/AbstractIncrementalHandler.java +45 -0
- data/src/main/java/org/embulk/input/jdbc/getter/AbstractTimestampColumnGetter.java +38 -0
- data/src/main/java/org/embulk/input/jdbc/getter/BigDecimalColumnGetter.java +59 -0
- data/src/main/java/org/embulk/input/jdbc/getter/BooleanColumnGetter.java +56 -0
- data/src/main/java/org/embulk/input/jdbc/getter/ColumnGetter.java +21 -0
- data/src/main/java/org/embulk/input/jdbc/getter/ColumnGetterFactory.java +207 -0
- data/src/main/java/org/embulk/input/jdbc/getter/DateColumnGetter.java +37 -0
- data/src/main/java/org/embulk/input/jdbc/getter/DoubleColumnGetter.java +66 -0
- data/src/main/java/org/embulk/input/jdbc/getter/FloatColumnGetter.java +66 -0
- data/src/main/java/org/embulk/input/jdbc/getter/JsonColumnGetter.java +57 -0
- data/src/main/java/org/embulk/input/jdbc/getter/LongColumnGetter.java +70 -0
- data/src/main/java/org/embulk/input/jdbc/getter/StringColumnGetter.java +96 -0
- data/src/main/java/org/embulk/input/jdbc/getter/TimeColumnGetter.java +37 -0
- data/src/main/java/org/embulk/input/jdbc/getter/TimestampColumnGetter.java +36 -0
- data/src/main/java/org/embulk/input/jdbc/getter/TimestampWithTimeZoneIncrementalHandler.java +83 -0
- data/src/main/java/org/embulk/input/jdbc/getter/TimestampWithoutTimeZoneIncrementalHandler.java +75 -0
- data/src/test/java/org/embulk/input/athena/TestAthenaInputPlugin.java +5 -0
- metadata +258 -0
@@ -0,0 +1,58 @@
|
|
1
|
+
package org.embulk.input.jdbc;
|
2
|
+
|
3
|
+
import com.fasterxml.jackson.annotation.JsonCreator;
|
4
|
+
import com.fasterxml.jackson.annotation.JsonProperty;
|
5
|
+
|
6
|
+
public class JdbcColumn
|
7
|
+
{
|
8
|
+
private String name;
|
9
|
+
private String typeName;
|
10
|
+
private int sqlType;
|
11
|
+
private int precision;
|
12
|
+
private int scale;
|
13
|
+
|
14
|
+
@JsonCreator
|
15
|
+
public JdbcColumn(
|
16
|
+
@JsonProperty("name") String name,
|
17
|
+
@JsonProperty("typeName") String typeName,
|
18
|
+
@JsonProperty("sqlType") int sqlType,
|
19
|
+
@JsonProperty("precision") int precision,
|
20
|
+
@JsonProperty("scale") int scale)
|
21
|
+
{
|
22
|
+
this.name = name;
|
23
|
+
this.typeName = typeName;
|
24
|
+
this.sqlType = sqlType;
|
25
|
+
this.precision = precision;
|
26
|
+
this.scale = scale;
|
27
|
+
}
|
28
|
+
|
29
|
+
@JsonProperty("name")
|
30
|
+
public String getName()
|
31
|
+
{
|
32
|
+
return name;
|
33
|
+
}
|
34
|
+
|
35
|
+
@JsonProperty("typeName")
|
36
|
+
public String getTypeName()
|
37
|
+
{
|
38
|
+
return typeName;
|
39
|
+
}
|
40
|
+
|
41
|
+
@JsonProperty("sqlType")
|
42
|
+
public int getSqlType()
|
43
|
+
{
|
44
|
+
return sqlType;
|
45
|
+
}
|
46
|
+
|
47
|
+
@JsonProperty("precision")
|
48
|
+
public int getPrecision()
|
49
|
+
{
|
50
|
+
return precision;
|
51
|
+
}
|
52
|
+
|
53
|
+
@JsonProperty("scale")
|
54
|
+
public int getScale()
|
55
|
+
{
|
56
|
+
return scale;
|
57
|
+
}
|
58
|
+
}
|
@@ -0,0 +1,31 @@
|
|
1
|
+
package org.embulk.input.jdbc;
|
2
|
+
|
3
|
+
import org.embulk.config.Config;
|
4
|
+
import org.embulk.config.ConfigDefault;
|
5
|
+
import org.embulk.config.ConfigInject;
|
6
|
+
import org.embulk.config.Task;
|
7
|
+
import org.embulk.spi.time.TimestampFormat;
|
8
|
+
import org.embulk.spi.type.Type;
|
9
|
+
import org.joda.time.DateTimeZone;
|
10
|
+
|
11
|
+
import com.google.common.base.Optional;
|
12
|
+
|
13
|
+
public interface JdbcColumnOption
|
14
|
+
extends Task
|
15
|
+
{
|
16
|
+
@Config("value_type")
|
17
|
+
@ConfigDefault("\"coalesce\"")
|
18
|
+
public String getValueType();
|
19
|
+
|
20
|
+
@Config("type")
|
21
|
+
@ConfigDefault("null")
|
22
|
+
public Optional<Type> getType();
|
23
|
+
|
24
|
+
@Config("timestamp_format")
|
25
|
+
@ConfigDefault("null")
|
26
|
+
public Optional<TimestampFormat> getTimestampFormat();
|
27
|
+
|
28
|
+
@Config("timezone")
|
29
|
+
@ConfigDefault("null")
|
30
|
+
public Optional<DateTimeZone> getTimeZone();
|
31
|
+
}
|
@@ -0,0 +1,397 @@
|
|
1
|
+
package org.embulk.input.jdbc;
|
2
|
+
|
3
|
+
import java.sql.Connection;
|
4
|
+
import java.sql.DatabaseMetaData;
|
5
|
+
import java.sql.PreparedStatement;
|
6
|
+
import java.sql.ResultSet;
|
7
|
+
import java.sql.ResultSetMetaData;
|
8
|
+
import java.sql.SQLException;
|
9
|
+
import java.sql.Statement;
|
10
|
+
import java.util.Locale;
|
11
|
+
import java.util.Set;
|
12
|
+
|
13
|
+
import org.embulk.config.ConfigException;
|
14
|
+
import org.embulk.spi.Exec;
|
15
|
+
import org.embulk.input.jdbc.getter.ColumnGetter;
|
16
|
+
import org.slf4j.Logger;
|
17
|
+
|
18
|
+
import java.util.List;
|
19
|
+
import java.util.ArrayList;
|
20
|
+
import static java.util.Locale.ENGLISH;
|
21
|
+
|
22
|
+
import com.fasterxml.jackson.annotation.JsonCreator;
|
23
|
+
import com.fasterxml.jackson.annotation.JsonProperty;
|
24
|
+
import com.fasterxml.jackson.databind.JsonNode;
|
25
|
+
import com.google.common.base.Optional;
|
26
|
+
import com.google.common.collect.ImmutableList;
|
27
|
+
import com.google.common.collect.ImmutableSet;
|
28
|
+
|
29
|
+
public class JdbcInputConnection
|
30
|
+
implements AutoCloseable
|
31
|
+
{
|
32
|
+
protected final Logger logger = Exec.getLogger(getClass());
|
33
|
+
|
34
|
+
protected final Connection connection;
|
35
|
+
protected final String schemaName;
|
36
|
+
protected final DatabaseMetaData databaseMetaData;
|
37
|
+
protected String identifierQuoteString;
|
38
|
+
|
39
|
+
public JdbcInputConnection(Connection connection, String schemaName)
|
40
|
+
throws SQLException
|
41
|
+
{
|
42
|
+
this.connection = connection;
|
43
|
+
this.schemaName = schemaName;
|
44
|
+
this.databaseMetaData = connection.getMetaData();
|
45
|
+
this.identifierQuoteString = databaseMetaData.getIdentifierQuoteString();
|
46
|
+
if (schemaName != null) {
|
47
|
+
setSearchPath(schemaName);
|
48
|
+
}
|
49
|
+
|
50
|
+
// java.sql.SQLFeatureNotSupportedException: Disabling auto-commit mode not supported
|
51
|
+
// connection.setAutoCommit(false);
|
52
|
+
}
|
53
|
+
|
54
|
+
protected void setSearchPath(String schema) throws SQLException
|
55
|
+
{
|
56
|
+
String sql = "SET search_path TO " + quoteIdentifierString(schema);
|
57
|
+
executeUpdate(sql);
|
58
|
+
}
|
59
|
+
|
60
|
+
public JdbcSchema getSchemaOfQuery(String query) throws SQLException
|
61
|
+
{
|
62
|
+
PreparedStatement stmt = connection.prepareStatement(query);
|
63
|
+
try {
|
64
|
+
return getSchemaOfResultMetadata(stmt.getMetaData());
|
65
|
+
} finally {
|
66
|
+
stmt.close();
|
67
|
+
}
|
68
|
+
}
|
69
|
+
|
70
|
+
public List<String> getPrimaryKeys(String tableName) throws SQLException
|
71
|
+
{
|
72
|
+
ResultSet rs = databaseMetaData.getPrimaryKeys(null, schemaName, tableName);
|
73
|
+
ImmutableList.Builder<String> builder = ImmutableList.builder();
|
74
|
+
try {
|
75
|
+
while(rs.next()) {
|
76
|
+
builder.add(rs.getString("COLUMN_NAME"));
|
77
|
+
}
|
78
|
+
} finally {
|
79
|
+
rs.close();
|
80
|
+
}
|
81
|
+
return builder.build();
|
82
|
+
}
|
83
|
+
|
84
|
+
protected JdbcSchema getSchemaOfResultMetadata(ResultSetMetaData metadata) throws SQLException
|
85
|
+
{
|
86
|
+
ImmutableList.Builder<JdbcColumn> columns = ImmutableList.builder();
|
87
|
+
for (int i=0; i < metadata.getColumnCount(); i++) {
|
88
|
+
int index = i + 1; // JDBC column index begins from 1
|
89
|
+
String name = metadata.getColumnLabel(index);
|
90
|
+
String typeName = metadata.getColumnTypeName(index);
|
91
|
+
int sqlType = metadata.getColumnType(index);
|
92
|
+
int scale = metadata.getScale(index);
|
93
|
+
int precision = metadata.getPrecision(index);
|
94
|
+
columns.add(new JdbcColumn(name, typeName, sqlType, precision, scale));
|
95
|
+
}
|
96
|
+
return new JdbcSchema(columns.build());
|
97
|
+
}
|
98
|
+
|
99
|
+
public static class PreparedQuery
|
100
|
+
{
|
101
|
+
private final String query;
|
102
|
+
private final List<JdbcLiteral> parameters;
|
103
|
+
|
104
|
+
@JsonCreator
|
105
|
+
public PreparedQuery(
|
106
|
+
@JsonProperty("query") String query,
|
107
|
+
@JsonProperty("parameters") List<JdbcLiteral> parameters)
|
108
|
+
{
|
109
|
+
this.query = query;
|
110
|
+
this.parameters = parameters;
|
111
|
+
}
|
112
|
+
|
113
|
+
@JsonProperty("query")
|
114
|
+
public String getQuery()
|
115
|
+
{
|
116
|
+
return query;
|
117
|
+
}
|
118
|
+
|
119
|
+
@JsonProperty("parameters")
|
120
|
+
public List<JdbcLiteral> getParameters()
|
121
|
+
{
|
122
|
+
return parameters;
|
123
|
+
}
|
124
|
+
}
|
125
|
+
|
126
|
+
public BatchSelect newSelectCursor(PreparedQuery preparedQuery,
|
127
|
+
List<ColumnGetter> getters,
|
128
|
+
int fetchRows, int queryTimeout) throws SQLException
|
129
|
+
{
|
130
|
+
return newBatchSelect(preparedQuery, getters, fetchRows, queryTimeout);
|
131
|
+
}
|
132
|
+
|
133
|
+
protected BatchSelect newBatchSelect(PreparedQuery preparedQuery,
|
134
|
+
List<ColumnGetter> getters,
|
135
|
+
int fetchRows, int queryTimeout) throws SQLException
|
136
|
+
{
|
137
|
+
String query = preparedQuery.getQuery();
|
138
|
+
List<JdbcLiteral> params = preparedQuery.getParameters();
|
139
|
+
|
140
|
+
PreparedStatement stmt = connection.prepareStatement(query);
|
141
|
+
stmt.setFetchSize(fetchRows);
|
142
|
+
stmt.setQueryTimeout(queryTimeout);
|
143
|
+
logger.info("SQL: " + query);
|
144
|
+
if (!params.isEmpty()) {
|
145
|
+
logger.info("Parameters: {}", params);
|
146
|
+
prepareParameters(stmt, getters, params);
|
147
|
+
}
|
148
|
+
return new SingleSelect(stmt);
|
149
|
+
}
|
150
|
+
|
151
|
+
protected void prepareParameters(PreparedStatement stmt, List<ColumnGetter> getters,
|
152
|
+
List<JdbcLiteral> parameters)
|
153
|
+
throws SQLException
|
154
|
+
{
|
155
|
+
for (int i = 0; i < parameters.size(); i++) {
|
156
|
+
JdbcLiteral literal = parameters.get(i);
|
157
|
+
ColumnGetter getter = getters.get(literal.getColumnIndex());
|
158
|
+
int index = i + 1; // JDBC column index begins from 1
|
159
|
+
getter.decodeFromJsonTo(stmt, index, literal.getValue());
|
160
|
+
}
|
161
|
+
}
|
162
|
+
|
163
|
+
public interface BatchSelect
|
164
|
+
extends AutoCloseable
|
165
|
+
{
|
166
|
+
public ResultSet fetch() throws SQLException;
|
167
|
+
|
168
|
+
@Override
|
169
|
+
public void close() throws SQLException;
|
170
|
+
}
|
171
|
+
|
172
|
+
public class SingleSelect
|
173
|
+
implements BatchSelect
|
174
|
+
{
|
175
|
+
private final PreparedStatement fetchStatement;
|
176
|
+
private boolean fetched = false;
|
177
|
+
|
178
|
+
public SingleSelect(PreparedStatement fetchStatement)
|
179
|
+
{
|
180
|
+
this.fetchStatement = fetchStatement;
|
181
|
+
}
|
182
|
+
|
183
|
+
public ResultSet fetch() throws SQLException
|
184
|
+
{
|
185
|
+
if (fetched == true) {
|
186
|
+
return null;
|
187
|
+
}
|
188
|
+
|
189
|
+
long startTime = System.currentTimeMillis();
|
190
|
+
|
191
|
+
ResultSet rs = fetchStatement.executeQuery();
|
192
|
+
|
193
|
+
double seconds = (System.currentTimeMillis() - startTime) / 1000.0;
|
194
|
+
logger.info(String.format("> %.2f seconds", seconds));
|
195
|
+
fetched = true;
|
196
|
+
return rs;
|
197
|
+
}
|
198
|
+
|
199
|
+
public void close() throws SQLException
|
200
|
+
{
|
201
|
+
// TODO close?
|
202
|
+
}
|
203
|
+
}
|
204
|
+
|
205
|
+
@Override
|
206
|
+
public void close() throws SQLException
|
207
|
+
{
|
208
|
+
connection.close();
|
209
|
+
}
|
210
|
+
|
211
|
+
protected void executeUpdate(String sql) throws SQLException
|
212
|
+
{
|
213
|
+
logger.info("SQL: " + sql);
|
214
|
+
Statement stmt = connection.createStatement();
|
215
|
+
try {
|
216
|
+
stmt.executeUpdate(sql);
|
217
|
+
} finally {
|
218
|
+
stmt.close();
|
219
|
+
}
|
220
|
+
}
|
221
|
+
|
222
|
+
// TODO share code with embulk-output-jdbc
|
223
|
+
protected String quoteIdentifierString(String str)
|
224
|
+
{
|
225
|
+
return identifierQuoteString + str + identifierQuoteString;
|
226
|
+
}
|
227
|
+
|
228
|
+
protected String buildTableName(String tableName)
|
229
|
+
{
|
230
|
+
return quoteIdentifierString(tableName);
|
231
|
+
}
|
232
|
+
|
233
|
+
public String buildSelectQuery(String tableName,
|
234
|
+
Optional<String> selectExpression, Optional<String> whereCondition,
|
235
|
+
Optional<String> orderByExpression) throws SQLException
|
236
|
+
{
|
237
|
+
StringBuilder sb = new StringBuilder();
|
238
|
+
|
239
|
+
sb.append("SELECT ");
|
240
|
+
sb.append(selectExpression.or("*"));
|
241
|
+
sb.append(" FROM ").append(buildTableName(tableName));
|
242
|
+
|
243
|
+
if (whereCondition.isPresent()) {
|
244
|
+
sb.append(" WHERE ").append(whereCondition.get());
|
245
|
+
}
|
246
|
+
|
247
|
+
if (orderByExpression.isPresent()) {
|
248
|
+
sb.append(" ORDER BY ").append(orderByExpression.get());
|
249
|
+
}
|
250
|
+
|
251
|
+
return sb.toString();
|
252
|
+
}
|
253
|
+
|
254
|
+
public PreparedQuery rebuildIncrementalQuery(String tableName,
|
255
|
+
Optional<String> selectExpression, Optional<String> whereCondition,
|
256
|
+
JdbcSchema querySchema,
|
257
|
+
List<Integer> incrementalColumnIndexes, List<JsonNode> incrementalValues) throws SQLException
|
258
|
+
{
|
259
|
+
List<JdbcLiteral> parameters = ImmutableList.of();
|
260
|
+
|
261
|
+
Optional<String> newWhereCondition;
|
262
|
+
if (incrementalValues != null) {
|
263
|
+
StringBuilder sb = new StringBuilder();
|
264
|
+
|
265
|
+
if (whereCondition.isPresent()) {
|
266
|
+
sb.append("(");
|
267
|
+
sb.append(whereCondition.get());
|
268
|
+
sb.append(") AND ");
|
269
|
+
}
|
270
|
+
|
271
|
+
sb.append("(");
|
272
|
+
parameters = buildIncrementalConditionTo(sb,
|
273
|
+
querySchema, incrementalColumnIndexes, incrementalValues);
|
274
|
+
sb.append(")");
|
275
|
+
|
276
|
+
newWhereCondition = Optional.of(sb.toString());
|
277
|
+
}
|
278
|
+
else {
|
279
|
+
newWhereCondition = whereCondition;
|
280
|
+
}
|
281
|
+
|
282
|
+
Optional<String> newOrderByExpression;
|
283
|
+
{
|
284
|
+
StringBuilder sb = new StringBuilder();
|
285
|
+
buildIncrementalOrderTo(sb, querySchema, incrementalColumnIndexes);
|
286
|
+
newOrderByExpression = Optional.of(sb.toString());
|
287
|
+
}
|
288
|
+
|
289
|
+
String newQuery = buildSelectQuery(
|
290
|
+
tableName, selectExpression, newWhereCondition,
|
291
|
+
newOrderByExpression);
|
292
|
+
|
293
|
+
return new PreparedQuery(newQuery, parameters);
|
294
|
+
}
|
295
|
+
|
296
|
+
public PreparedQuery wrapIncrementalQuery(String rawQuery, JdbcSchema querySchema,
|
297
|
+
List<Integer> incrementalColumnIndexes, List<JsonNode> incrementalValues) throws SQLException
|
298
|
+
{
|
299
|
+
StringBuilder sb = new StringBuilder();
|
300
|
+
List<JdbcLiteral> parameters = ImmutableList.of();
|
301
|
+
|
302
|
+
sb.append("SELECT * FROM (");
|
303
|
+
sb.append(truncateStatementDelimiter(rawQuery));
|
304
|
+
sb.append(") embulk_incremental_");
|
305
|
+
|
306
|
+
if (incrementalValues != null) {
|
307
|
+
sb.append(" WHERE ");
|
308
|
+
parameters = buildIncrementalConditionTo(sb,
|
309
|
+
querySchema, incrementalColumnIndexes, incrementalValues);
|
310
|
+
}
|
311
|
+
|
312
|
+
sb.append(" ORDER BY ");
|
313
|
+
buildIncrementalOrderTo(sb, querySchema, incrementalColumnIndexes);
|
314
|
+
|
315
|
+
return new PreparedQuery(sb.toString(), parameters);
|
316
|
+
}
|
317
|
+
|
318
|
+
private List<JdbcLiteral> buildIncrementalConditionTo(
|
319
|
+
StringBuilder sb,
|
320
|
+
JdbcSchema querySchema,
|
321
|
+
List<Integer> incrementalColumnIndexes, List<JsonNode> incrementalValues) throws SQLException
|
322
|
+
{
|
323
|
+
ImmutableList.Builder<JdbcLiteral> parameters = ImmutableList.builder();
|
324
|
+
|
325
|
+
List<String> leftColumnNames = new ArrayList<>();
|
326
|
+
List<JdbcLiteral> rightLiterals = new ArrayList<>();
|
327
|
+
for (int n = 0; n < incrementalColumnIndexes.size(); n++) {
|
328
|
+
int columnIndex = incrementalColumnIndexes.get(n);
|
329
|
+
JsonNode value = incrementalValues.get(n);
|
330
|
+
leftColumnNames.add(querySchema.getColumnName(columnIndex));
|
331
|
+
rightLiterals.add(new JdbcLiteral(columnIndex, value));
|
332
|
+
}
|
333
|
+
|
334
|
+
for (int n = 0; n < leftColumnNames.size(); n++) {
|
335
|
+
if (n > 0) {
|
336
|
+
sb.append(" OR ");
|
337
|
+
}
|
338
|
+
sb.append("(");
|
339
|
+
|
340
|
+
for (int i = 0; i < n; i++) {
|
341
|
+
sb.append(quoteIdentifierString(leftColumnNames.get(i)));
|
342
|
+
sb.append(" = ?");
|
343
|
+
parameters.add(rightLiterals.get(i));
|
344
|
+
sb.append(" AND ");
|
345
|
+
}
|
346
|
+
sb.append(quoteIdentifierString(leftColumnNames.get(n)));
|
347
|
+
sb.append(" > ?");
|
348
|
+
parameters.add(rightLiterals.get(n));
|
349
|
+
|
350
|
+
sb.append(")");
|
351
|
+
}
|
352
|
+
|
353
|
+
return parameters.build();
|
354
|
+
}
|
355
|
+
|
356
|
+
private void buildIncrementalOrderTo(StringBuilder sb,
|
357
|
+
JdbcSchema querySchema, List<Integer> incrementalColumnIndexes)
|
358
|
+
{
|
359
|
+
boolean first = true;
|
360
|
+
for (int i : incrementalColumnIndexes) {
|
361
|
+
if (first) {
|
362
|
+
first = false;
|
363
|
+
} else {
|
364
|
+
sb.append(", ");
|
365
|
+
}
|
366
|
+
sb.append(quoteIdentifierString(querySchema.getColumnName(i)));
|
367
|
+
}
|
368
|
+
}
|
369
|
+
|
370
|
+
protected String truncateStatementDelimiter(String rawQuery) throws SQLException
|
371
|
+
{
|
372
|
+
return rawQuery.replaceAll(";\\s*$", "");
|
373
|
+
}
|
374
|
+
|
375
|
+
public boolean tableExists(String tableName) throws SQLException
|
376
|
+
{
|
377
|
+
try (ResultSet rs = connection.getMetaData().getTables(null, schemaName, tableName, null)) {
|
378
|
+
return rs.next();
|
379
|
+
}
|
380
|
+
}
|
381
|
+
|
382
|
+
private Set<String> getColumnNames(String tableName) throws SQLException
|
383
|
+
{
|
384
|
+
ImmutableSet.Builder<String> columnNamesBuilder = ImmutableSet.builder();
|
385
|
+
try (ResultSet rs = connection.getMetaData().getColumns(null, schemaName, tableName, null)) {
|
386
|
+
while (rs.next()) {
|
387
|
+
columnNamesBuilder.add(rs.getString("COLUMN_NAME"));
|
388
|
+
}
|
389
|
+
return columnNamesBuilder.build();
|
390
|
+
}
|
391
|
+
}
|
392
|
+
|
393
|
+
public void showDriverVersion() throws SQLException {
|
394
|
+
DatabaseMetaData meta = connection.getMetaData();
|
395
|
+
logger.info(String.format(Locale.ENGLISH,"Using JDBC Driver %s",meta.getDriverVersion()));
|
396
|
+
}
|
397
|
+
}
|