embulk-filter-calcite 0.1.1 → 0.1.2

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.
Files changed (25) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +1 -1
  3. data/CHANGELOG.md +12 -0
  4. data/README.md +7 -0
  5. data/build.gradle +7 -11
  6. data/config/checkstyle/README.md +6 -0
  7. data/config/checkstyle/checkstyle-suppressions.xml +8 -0
  8. data/config/checkstyle/checkstyle.xml +195 -104
  9. data/config/checkstyle/google_checks.xml +218 -0
  10. data/src/main/java/org/embulk/filter/calcite/CalciteFilterPlugin.java +111 -118
  11. data/src/main/java/org/embulk/filter/calcite/PageConverter.java +19 -36
  12. data/src/main/java/org/embulk/filter/calcite/adapter/page/PageEnumerator.java +14 -15
  13. data/src/main/java/org/embulk/filter/calcite/adapter/page/PageFieldType.java +9 -15
  14. data/src/main/java/org/embulk/filter/calcite/adapter/page/PageSchema.java +4 -9
  15. data/src/main/java/org/embulk/filter/calcite/adapter/page/PageSchemaFactory.java +7 -8
  16. data/src/main/java/org/embulk/filter/calcite/adapter/page/PageTable.java +23 -14
  17. data/src/main/java/org/embulk/filter/calcite/getter/FilterColumnGetterFactory.java +23 -11
  18. data/src/main/java/org/embulk/filter/calcite/getter/FilterTimestampColumnGetter.java +10 -14
  19. data/src/test/java/org/embulk/filter/calcite/TestCalciteFilterPlugin.java +81 -55
  20. data/src/test/resources/org/embulk/filter/calcite/test/test_timestamp_conv_expected.csv +4 -0
  21. data/src/test/resources/org/embulk/filter/calcite/test/test_timestamp_conv_filter.yml +3 -0
  22. data/src/test/resources/org/embulk/filter/calcite/test/test_timestamp_conv_in.yml +18 -0
  23. data/src/test/resources/org/embulk/filter/calcite/test/test_timestamp_conv_source.csv +5 -0
  24. metadata +14 -7
  25. data/config/checkstyle/default.xml +0 -108
@@ -5,6 +5,15 @@ import com.google.common.base.Throwables;
5
5
  import com.google.common.collect.ImmutableList;
6
6
  import com.google.common.collect.ImmutableMap;
7
7
  import com.google.inject.Inject;
8
+ import java.sql.Connection;
9
+ import java.sql.ResultSet;
10
+ import java.sql.ResultSetMetaData;
11
+ import java.sql.SQLException;
12
+ import java.sql.Statement;
13
+ import java.util.List;
14
+ import java.util.Locale;
15
+ import java.util.Map;
16
+ import java.util.Properties;
8
17
  import org.apache.calcite.jdbc.Driver;
9
18
  import org.embulk.config.Config;
10
19
  import org.embulk.config.ConfigDefault;
@@ -23,65 +32,27 @@ import org.embulk.input.jdbc.JdbcSchema;
23
32
  import org.embulk.input.jdbc.getter.ColumnGetter;
24
33
  import org.embulk.input.jdbc.getter.ColumnGetterFactory;
25
34
  import org.embulk.spi.BufferAllocator;
35
+ import org.embulk.spi.Exec;
26
36
  import org.embulk.spi.FilterPlugin;
27
37
  import org.embulk.spi.Page;
28
38
  import org.embulk.spi.PageBuilder;
29
39
  import org.embulk.spi.PageOutput;
30
40
  import org.embulk.spi.Schema;
41
+ import org.embulk.spi.unit.ToStringMap;
31
42
  import org.joda.time.DateTimeZone;
32
43
  import org.slf4j.Logger;
33
44
 
34
- import java.sql.Connection;
35
- import java.sql.ResultSet;
36
- import java.sql.ResultSetMetaData;
37
- import java.sql.SQLException;
38
- import java.sql.Statement;
39
- import java.util.List;
40
- import java.util.Map;
41
- import java.util.Properties;
42
-
43
- import static java.lang.String.format;
44
- import static java.lang.Thread.currentThread;
45
- import static java.util.Locale.ENGLISH;
46
- import static org.embulk.spi.Exec.getLogger;
47
- import static org.embulk.spi.Exec.getModelManager;
48
- import static org.embulk.spi.Exec.newConfigSource;
49
-
50
- public class CalciteFilterPlugin
51
- implements FilterPlugin
52
- {
53
- public interface PluginTask
54
- extends Task
55
- {
56
- @Config("query")
57
- public String getQuery();
58
-
59
- @Config("default_timezone")
60
- @ConfigDefault("\"UTC\"")
61
- public DateTimeZone getDefaultTimeZone();
62
-
63
- public JdbcSchema getQuerySchema();
64
- public void setQuerySchema(JdbcSchema querySchema);
65
-
66
- // TODO support jdbc Url properties
67
- // TODO support column_options: option
68
- // TODO support options: option
69
-
70
- @ConfigInject
71
- public BufferAllocator getBufferAllocator();
72
- }
45
+ public class CalciteFilterPlugin implements FilterPlugin {
73
46
 
74
47
  private final Logger log;
75
48
 
76
49
  @Inject
77
- public CalciteFilterPlugin()
78
- {
79
- this.log = getLogger(getClass());
50
+ public CalciteFilterPlugin() {
51
+ this.log = Exec.getLogger(getClass());
80
52
  }
81
53
 
82
54
  @Override
83
- public void transaction(ConfigSource config, Schema inputSchema, FilterPlugin.Control control)
84
- {
55
+ public void transaction(ConfigSource config, Schema inputSchema, FilterPlugin.Control control) {
85
56
  PluginTask task = config.loadConfig(PluginTask.class);
86
57
  Properties props = System.getProperties(); // TODO should be configured as config option
87
58
  setupProperties(task, props);
@@ -91,49 +62,55 @@ public class CalciteFilterPlugin
91
62
 
92
63
  // Set page converter as TLS variable in PageTable
93
64
  PageTable.pageConverter.set(newPageConverter(task, inputSchema));
65
+
66
+ final String jdbcUrl = buildJdbcUrl();
67
+ log.info(String.format(Locale.ENGLISH, "Generated Jdbc URL: %s", jdbcUrl));
68
+
94
69
  try {
95
70
  JdbcSchema querySchema;
96
- try (Connection conn = newConnection(props)) { // SQLException thrown by conn.close()
71
+ try (Connection conn = newConnection(jdbcUrl, props)) { // SQLException by conn.close()
97
72
  querySchema = getQuerySchema(task, conn);
98
73
  task.setQuerySchema(querySchema);
99
- }
100
- catch (SQLException e) {
74
+ } catch (SQLException e) {
101
75
  throw Throwables.propagate(e);
102
76
  }
103
77
 
104
78
  control.run(task.dump(), buildOutputSchema(task, querySchema));
105
- }
106
- finally {
79
+ } finally {
107
80
  PageTable.pageConverter.remove();
108
81
  }
109
82
  }
110
83
 
111
- private void setupProperties(PluginTask task, Properties props)
112
- {
84
+ private void setupProperties(PluginTask task, Properties props) {
113
85
  // @see https://calcite.apache.org/docs/adapter.html#jdbc-connect-string-parameters
86
+ final ToStringMap options = task.getOptions();
87
+ if (!options.containsKey("caseSensitive")) {
88
+ log.warn("JDBC parameter 'caseSensitive' is implicitly set to false as default in");
89
+ log.warn("embulk-filter-calcite 0.1 but, it's scheduled to change default with true");
90
+ log.warn("in 0.2. Please use 'options' option to set 'caseSensitive' to false.");
91
+ }
114
92
  props.setProperty("caseSensitive", "false"); // Relax case-sensitive
115
93
  props.setProperty("timeZone", task.getDefaultTimeZone().getID());
94
+
95
+ // overwrites props with 'options' option
96
+ props.putAll(options);
116
97
  }
117
98
 
118
- private PageConverter newPageConverter(PluginTask task, Schema inputSchema)
119
- {
99
+ private PageConverter newPageConverter(PluginTask task, Schema inputSchema) {
120
100
  return new PageConverter(inputSchema, task.getDefaultTimeZone().toTimeZone());
121
101
  }
122
102
 
123
- private Connection newConnection(Properties props)
124
- {
125
- String jdbcUrl = buildJdbcUrl();
103
+ private Connection newConnection(String jdbcUrl, Properties props) {
126
104
  try {
127
105
  return new Driver().connect(jdbcUrl, props);
128
- }
129
- catch (SQLException e) {
130
- String message = format(ENGLISH, "Cannot create connections by Jdbc URL: %s", jdbcUrl);
106
+ } catch (SQLException e) {
107
+ String message = String.format(Locale.ENGLISH,
108
+ "Cannot create connections by Jdbc URL: %s", jdbcUrl);
131
109
  throw new IllegalStateException(message, e);
132
110
  }
133
111
  }
134
112
 
135
- private String buildJdbcUrl()
136
- {
113
+ private String buildJdbcUrl() {
137
114
  // build a json model to apply Page storage adaptor
138
115
  // @see https://github.com/apache/calcite/blob/master/example/csv/src/test/resources/model.json
139
116
  ImmutableMap.Builder<String, Object> map = ImmutableMap.builder();
@@ -146,42 +123,23 @@ public class CalciteFilterPlugin
146
123
  "factory", PageSchemaFactory.class.getName()
147
124
  )
148
125
  ));
149
- String jsonModel = getModelManager().writeObject(map.build());
126
+ String jsonModel = Exec.getModelManager().writeObject(map.build());
150
127
 
151
128
  // build Jdbc URL
152
- String jdbcUrl = format(ENGLISH, "jdbc:calcite:model=inline:%s", jsonModel);
153
- log.info(format(ENGLISH, "Generated Jdbc URL: %s", jdbcUrl));
154
- return jdbcUrl;
129
+ return String.format(Locale.ENGLISH, "jdbc:calcite:model=inline:%s", jsonModel);
155
130
  }
156
131
 
157
132
  private JdbcSchema getQuerySchema(PluginTask task, Connection conn)
158
- throws SQLException
159
- {
133
+ throws SQLException {
160
134
  try (Statement stat = conn.createStatement(); // SQLException thrown by conn.close()
161
- ResultSet result = executeQuery(stat, task.getQuery())) { // SQLException thrown by rs.close()
135
+ ResultSet result = executeQuery(stat,
136
+ task.getQuery())) { // SQLException thrown by rs.close()
162
137
  return getQuerySchema(result.getMetaData());
163
138
  }
164
139
  }
165
140
 
166
- private ResultSet executeQuery(Statement stat, String query)
167
- {
168
- // This is a workaround to avoid NPE caused by commons-compiler v2.7.6
169
- ClassLoader cl = currentThread().getContextClassLoader();
170
- currentThread().setContextClassLoader(getClass().getClassLoader());
171
- try {
172
- return stat.executeQuery(query);
173
- }
174
- catch (SQLException e) {
175
- throw new ConfigException("Cannot execute a query: " + query, e);
176
- }
177
- finally {
178
- currentThread().setContextClassLoader(cl);
179
- }
180
- }
181
-
182
141
  private JdbcSchema getQuerySchema(ResultSetMetaData metadata)
183
- throws SQLException
184
- {
142
+ throws SQLException {
185
143
  ImmutableList.Builder<JdbcColumn> columns = ImmutableList.builder();
186
144
  for (int i = 0; i < metadata.getColumnCount(); i++) {
187
145
  int index = i + 1; // JDBC column index begins from 1
@@ -195,8 +153,20 @@ public class CalciteFilterPlugin
195
153
  return new JdbcSchema(columns.build());
196
154
  }
197
155
 
198
- private Schema buildOutputSchema(PluginTask task, JdbcSchema querySchema)
199
- {
156
+ private ResultSet executeQuery(Statement stat, String query) {
157
+ // This is a workaround to avoid NPE caused by commons-compiler v2.7.6
158
+ ClassLoader cl = Thread.currentThread().getContextClassLoader();
159
+ Thread.currentThread().setContextClassLoader(getClass().getClassLoader());
160
+ try {
161
+ return stat.executeQuery(query);
162
+ } catch (SQLException e) {
163
+ throw new ConfigException("Cannot execute a query: " + query, e);
164
+ } finally {
165
+ Thread.currentThread().setContextClassLoader(cl);
166
+ }
167
+ }
168
+
169
+ private Schema buildOutputSchema(PluginTask task, JdbcSchema querySchema) {
200
170
  ColumnGetterFactory factory = newColumnGetterFactory(task, Optional.<PageBuilder>absent());
201
171
  List<ColumnGetter> getters = newColumnGetters(factory, querySchema);
202
172
 
@@ -207,18 +177,17 @@ public class CalciteFilterPlugin
207
177
  return schema.build();
208
178
  }
209
179
 
210
- private ColumnGetterFactory newColumnGetterFactory(PluginTask task, Optional<PageBuilder> pageBuilder)
211
- {
180
+ private ColumnGetterFactory newColumnGetterFactory(PluginTask task,
181
+ Optional<PageBuilder> pageBuilder) {
212
182
  if (pageBuilder.isPresent()) {
213
183
  return new FilterColumnGetterFactory(pageBuilder.get(), task.getDefaultTimeZone());
214
- }
215
- else {
184
+ } else {
216
185
  return new FilterColumnGetterFactory(null, task.getDefaultTimeZone());
217
186
  }
218
187
  }
219
188
 
220
- private List<ColumnGetter> newColumnGetters(ColumnGetterFactory factory, JdbcSchema querySchema)
221
- {
189
+ private List<ColumnGetter> newColumnGetters(ColumnGetterFactory factory,
190
+ JdbcSchema querySchema) {
222
191
  ImmutableList.Builder<ColumnGetter> getters = ImmutableList.builder();
223
192
  for (JdbcColumn column : querySchema.getColumns()) {
224
193
  getters.add(factory.newColumnGetter(null, null, column, newJdbcColumnOption()));
@@ -226,15 +195,14 @@ public class CalciteFilterPlugin
226
195
  return getters.build();
227
196
  }
228
197
 
229
- private JdbcColumnOption newJdbcColumnOption()
230
- {
198
+ private JdbcColumnOption newJdbcColumnOption() {
231
199
  // TODO need to improve for supporting column_options: option
232
- return newConfigSource().loadConfig(JdbcColumnOption.class);
200
+ return Exec.newConfigSource().loadConfig(JdbcColumnOption.class);
233
201
  }
234
202
 
235
203
  @Override
236
- public PageOutput open(TaskSource taskSource, Schema inputSchema, Schema outputSchema, PageOutput output)
237
- {
204
+ public PageOutput open(TaskSource taskSource, Schema inputSchema, Schema outputSchema,
205
+ PageOutput output) {
238
206
  PluginTask task = taskSource.loadTask(PluginTask.class);
239
207
 
240
208
  // Set input schema in PageSchema for various types of executor plugins
@@ -246,12 +214,42 @@ public class CalciteFilterPlugin
246
214
  List<ColumnGetter> getters = newColumnGetters(factory, task.getQuerySchema());
247
215
  Properties props = System.getProperties(); // TODO should be configured as config option
248
216
  setupProperties(task, props);
249
- return new FilterPageOutput(outputSchema, task.getQuery(), pageBuilder, pageConverter, getters, props);
217
+ return new FilterPageOutput(outputSchema,
218
+ task.getQuery(),
219
+ pageBuilder,
220
+ pageConverter,
221
+ getters,
222
+ props);
223
+ }
224
+
225
+ public interface PluginTask
226
+ extends Task {
227
+
228
+ @Config("query")
229
+ public String getQuery();
230
+
231
+ @Config("default_timezone")
232
+ @ConfigDefault("\"UTC\"")
233
+ public DateTimeZone getDefaultTimeZone();
234
+
235
+ public JdbcSchema getQuerySchema();
236
+
237
+ public void setQuerySchema(JdbcSchema querySchema);
238
+
239
+ // TODO support jdbc Url properties
240
+ // TODO support column_options: option
241
+
242
+ @Config("options")
243
+ @ConfigDefault("{}")
244
+ public ToStringMap getOptions();
245
+
246
+ @ConfigInject
247
+ public BufferAllocator getBufferAllocator();
250
248
  }
251
249
 
252
250
  private class FilterPageOutput
253
- implements PageOutput
254
- {
251
+ implements PageOutput {
252
+
255
253
  private final Schema outputSchema;
256
254
  private final String query;
257
255
  private final PageBuilder pageBuilder;
@@ -259,9 +257,9 @@ public class CalciteFilterPlugin
259
257
  private final List<ColumnGetter> getters;
260
258
  private final Properties props;
261
259
 
262
- private FilterPageOutput(Schema outputSchema, String query, PageBuilder pageBuilder, PageConverter pageConverter,
263
- List<ColumnGetter> getters, Properties props)
264
- {
260
+ private FilterPageOutput(Schema outputSchema, String query, PageBuilder pageBuilder,
261
+ PageConverter pageConverter,
262
+ List<ColumnGetter> getters, Properties props) {
265
263
  this.outputSchema = outputSchema;
266
264
  this.query = query;
267
265
  this.pageBuilder = pageBuilder;
@@ -271,17 +269,16 @@ public class CalciteFilterPlugin
271
269
  }
272
270
 
273
271
  @Override
274
- public void add(Page page)
275
- {
272
+ public void add(Page page) {
276
273
  // Set page converter as TLS variable in PageTable
277
274
  PageTable.pageConverter.set(pageConverter);
278
275
 
279
276
  // Set page as TLS variable in PageTable
280
277
  PageTable.page.set(page);
281
278
 
282
- try (Connection conn = newConnection(props);
283
- Statement stat = conn.createStatement();
284
- ResultSet result = executeQuery(stat, query)) {
279
+ try (Connection conn = newConnection(buildJdbcUrl(), props);
280
+ Statement stat = conn.createStatement();
281
+ ResultSet result = executeQuery(stat, query)) {
285
282
 
286
283
  while (result.next()) {
287
284
  for (int i = 0; i < getters.size(); i++) {
@@ -290,25 +287,21 @@ public class CalciteFilterPlugin
290
287
  }
291
288
  pageBuilder.addRecord();
292
289
  }
293
- }
294
- catch (SQLException e) {
290
+ } catch (SQLException e) {
295
291
  throw Throwables.propagate(e); // TODO better exception handling? error messages?
296
- }
297
- finally {
292
+ } finally {
298
293
  PageTable.pageConverter.remove();
299
294
  PageTable.page.remove();
300
295
  }
301
296
  }
302
297
 
303
298
  @Override
304
- public void finish()
305
- {
299
+ public void finish() {
306
300
  pageBuilder.finish();
307
301
  }
308
302
 
309
303
  @Override
310
- public void close()
311
- {
304
+ public void close() {
312
305
  pageBuilder.close();
313
306
  }
314
307
  }
@@ -1,100 +1,85 @@
1
1
  package org.embulk.filter.calcite;
2
2
 
3
+ import java.math.BigDecimal;
4
+ import java.util.TimeZone;
3
5
  import org.embulk.spi.Column;
4
6
  import org.embulk.spi.ColumnVisitor;
5
7
  import org.embulk.spi.PageReader;
6
8
  import org.embulk.spi.Schema;
7
9
 
8
- import java.math.BigDecimal;
9
- import java.util.TimeZone;
10
-
11
10
  /**
12
11
  * This class converts Embulk's Page values into Calcite's row types. It refers to
13
12
  * org.apache.calcite.adapter.csv.CsvEnumerator.
14
13
  */
15
- public class PageConverter
16
- implements ColumnVisitor
17
- {
14
+ public class PageConverter implements ColumnVisitor {
15
+
18
16
  private final TimeZone defaultTimeZone;
19
17
  private final Object[] row;
20
18
  private PageReader pageReader;
21
19
 
22
- public PageConverter(Schema schema, TimeZone defaultTimeZone)
23
- {
20
+ public PageConverter(Schema schema, TimeZone defaultTimeZone) {
24
21
  this.defaultTimeZone = defaultTimeZone;
25
22
  this.row = new Object[schema.getColumnCount()];
26
23
  }
27
24
 
28
- public Object[] getRow()
29
- {
25
+ public Object[] getRow() {
30
26
  return row;
31
27
  }
32
28
 
33
- public void setPageReader(PageReader pageReader)
34
- {
29
+ public void setPageReader(PageReader pageReader) {
35
30
  this.pageReader = pageReader;
36
31
  }
37
32
 
38
33
  @Override
39
- public void booleanColumn(Column column)
40
- {
34
+ public void booleanColumn(Column column) {
41
35
  // Embulk's boolean is converted into Java's boolean
42
36
  int i = column.getIndex();
43
37
  if (pageReader.isNull(i)) {
44
38
  row[i] = null;
45
- }
46
- else {
39
+ } else {
47
40
  row[i] = pageReader.getBoolean(i);
48
41
  }
49
42
  }
50
43
 
51
44
  @Override
52
- public void longColumn(Column column)
53
- {
45
+ public void longColumn(Column column) {
54
46
  // Embulk's long is converted into long type
55
47
  int i = column.getIndex();
56
48
  if (pageReader.isNull(i)) {
57
49
  row[i] = null;
58
- }
59
- else {
50
+ } else {
60
51
  row[i] = pageReader.getLong(i);
61
52
  }
62
53
  }
63
54
 
64
55
  @Override
65
- public void doubleColumn(Column column)
66
- {
56
+ public void doubleColumn(Column column) {
67
57
  // Embulk's double is converted into java.math.BigDecimal
68
58
  int i = column.getIndex();
69
59
  if (pageReader.isNull(i)) {
70
60
  row[i] = null;
71
- }
72
- else {
61
+ } else {
73
62
  row[i] = new BigDecimal(pageReader.getDouble(i));
74
63
  }
75
64
  }
76
65
 
77
66
  @Override
78
- public void stringColumn(Column column)
79
- {
67
+ public void stringColumn(Column column) {
80
68
  // Embulk's string is converted into java.lang.String
81
69
  int i = column.getIndex();
82
70
  if (pageReader.isNull(i)) {
83
71
  row[i] = null;
84
- }
85
- else {
72
+ } else {
86
73
  row[i] = pageReader.getString(i);
87
74
  }
88
75
  }
89
76
 
90
77
  @Override
91
- public void timestampColumn(Column column)
92
- {
78
+ public void timestampColumn(Column column) {
93
79
  int i = column.getIndex();
94
80
  if (pageReader.isNull(i)) {
95
81
  row[i] = null;
96
- }
97
- else {
82
+ } else {
98
83
  // Embulk's timestamp is converted into java.sql.Timestmap
99
84
  org.embulk.spi.time.Timestamp timestamp = pageReader.getTimestamp(i);
100
85
  long milliseconds = timestamp.getEpochSecond() * 1000 + timestamp.getNano() / 1000000;
@@ -105,14 +90,12 @@ public class PageConverter
105
90
  }
106
91
 
107
92
  @Override
108
- public void jsonColumn(Column column)
109
- {
93
+ public void jsonColumn(Column column) {
110
94
  // Embulk's json is converted into Java's string
111
95
  int i = column.getIndex();
112
96
  if (pageReader.isNull(i)) {
113
97
  row[i] = null;
114
- }
115
- else {
98
+ } else {
116
99
  row[i] = pageReader.getJson(i).toJson();
117
100
  }
118
101
  }