embulk-filter-add_time 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.
Files changed (35) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +15 -0
  3. data/.travis.yml +7 -0
  4. data/CHANGELOG.md +3 -0
  5. data/COPYING +14 -0
  6. data/README.md +212 -0
  7. data/build.gradle +82 -0
  8. data/gradle/check.gradle +34 -0
  9. data/gradle/wrapper/gradle-wrapper.jar +0 -0
  10. data/gradle/wrapper/gradle-wrapper.properties +6 -0
  11. data/gradlew +164 -0
  12. data/gradlew.bat +90 -0
  13. data/lib/embulk/filter/add_time.rb +3 -0
  14. data/src/main/java/org/embulk/filter/add_time/AddTimeFilterPlugin.java +208 -0
  15. data/src/main/java/org/embulk/filter/add_time/converter/ColumnConverter.java +14 -0
  16. data/src/main/java/org/embulk/filter/add_time/converter/ColumnDuplicator.java +72 -0
  17. data/src/main/java/org/embulk/filter/add_time/converter/LongValueCastConverter.java +33 -0
  18. data/src/main/java/org/embulk/filter/add_time/converter/SchemaConverter.java +257 -0
  19. data/src/main/java/org/embulk/filter/add_time/converter/SimpleColumnConverter.java +62 -0
  20. data/src/main/java/org/embulk/filter/add_time/converter/StringValueCastConverter.java +33 -0
  21. data/src/main/java/org/embulk/filter/add_time/converter/TimestampValueCastConverter.java +23 -0
  22. data/src/main/java/org/embulk/filter/add_time/converter/ValueCastConverter.java +108 -0
  23. data/src/main/java/org/embulk/filter/add_time/converter/ValueConverter.java +22 -0
  24. data/src/main/java/org/embulk/filter/add_time/converter/ValueNoConverter.java +46 -0
  25. data/src/main/java/org/embulk/filter/add_time/reader/AbstractColumnReader.java +55 -0
  26. data/src/main/java/org/embulk/filter/add_time/reader/BooleanColumnReader.java +35 -0
  27. data/src/main/java/org/embulk/filter/add_time/reader/ColumnReader.java +14 -0
  28. data/src/main/java/org/embulk/filter/add_time/reader/DoubleColumnReader.java +35 -0
  29. data/src/main/java/org/embulk/filter/add_time/reader/LongColumnReader.java +35 -0
  30. data/src/main/java/org/embulk/filter/add_time/reader/StringColumnReader.java +35 -0
  31. data/src/main/java/org/embulk/filter/add_time/reader/TimeValueGenerator.java +177 -0
  32. data/src/main/java/org/embulk/filter/add_time/reader/TimestampColumnReader.java +36 -0
  33. data/src/test/java/org/embulk/filter/add_time/TestAddTimeFilterPlugin.java +416 -0
  34. data/src/test/java/org/embulk/filter/add_time/converter/TestSchemaConverter.java +338 -0
  35. metadata +107 -0
@@ -0,0 +1,35 @@
1
+ package org.embulk.filter.add_time.reader;
2
+
3
+ import org.embulk.filter.add_time.converter.ValueConverter;
4
+ import org.embulk.spi.Column;
5
+ import org.embulk.spi.PageBuilder;
6
+ import org.embulk.spi.PageReader;
7
+
8
+ public class StringColumnReader
9
+ extends AbstractColumnReader<StringColumnReader>
10
+ {
11
+ protected String value;
12
+
13
+ public StringColumnReader(ValueConverter valueConverter)
14
+ {
15
+ super(valueConverter);
16
+ }
17
+
18
+ @Override
19
+ public void readNonNullValue(Column column, PageReader pageReader)
20
+ {
21
+ value = pageReader.getString(column);
22
+ }
23
+
24
+ @Override
25
+ public void convertNonNullValue(Column column, PageBuilder pageBuilder)
26
+ {
27
+ valueConverter.convertValue(column, value, pageBuilder);
28
+ }
29
+
30
+ @Override
31
+ public void copyValueTo(StringColumnReader columnReader)
32
+ {
33
+ columnReader.value = this.value;
34
+ }
35
+ }
@@ -0,0 +1,177 @@
1
+ package org.embulk.filter.add_time.reader;
2
+
3
+ import com.google.common.base.Optional;
4
+ import org.embulk.config.ConfigException;
5
+ import org.embulk.filter.add_time.AddTimeFilterPlugin.FromValueConfig;
6
+ import org.embulk.filter.add_time.AddTimeFilterPlugin.UnixTimestampUnit;
7
+ import org.embulk.filter.add_time.converter.ValueConverter;
8
+ import org.embulk.spi.Column;
9
+ import org.embulk.spi.Exec;
10
+ import org.embulk.spi.PageBuilder;
11
+ import org.embulk.spi.PageReader;
12
+ import org.embulk.spi.time.Timestamp;
13
+ import org.embulk.spi.time.TimestampParser;
14
+
15
+ public abstract class TimeValueGenerator
16
+ implements ColumnReader
17
+ {
18
+ private final ValueConverter valueConverter;
19
+
20
+ public TimeValueGenerator(ValueConverter valueConverter)
21
+ {
22
+ this.valueConverter = valueConverter;
23
+ }
24
+
25
+ protected abstract Timestamp nextTimestamp();
26
+
27
+ @Override
28
+ public void readValue(Column column, PageReader pageReader)
29
+ {
30
+ throw new AssertionError("Never call");
31
+ }
32
+
33
+ @Override
34
+ public void convertValue(Column column, PageBuilder pageBuilder)
35
+ {
36
+ valueConverter.convertValue(column, nextTimestamp(), pageBuilder);
37
+ }
38
+
39
+ @Override
40
+ public void copyTo(ColumnReader columnReader)
41
+ {
42
+ throw new AssertionError("Never call");
43
+ }
44
+
45
+ public static TimeValueGenerator newGenerator(final FromValueConfig config, ValueConverter valueConverter)
46
+ {
47
+ switch (config.getMode()) {
48
+ case "fixed_time":
49
+ require(config.getValue(), "'value'");
50
+ reject(config.getFrom(), "'from'");
51
+ reject(config.getTo(), "'to'");
52
+ return new FixedTimeValueGenerator(config, valueConverter);
53
+
54
+ case "incremental_time": // default mode
55
+ require(config.getFrom(), "'from', 'to'");
56
+ require(config.getTo(), "'to'");
57
+ reject(config.getValue(), "'value'");
58
+ return new IncrementalTimeValueGenerator(config, valueConverter);
59
+
60
+ case "upload_time":
61
+ reject(config.getFrom(), "'value'");
62
+ reject(config.getFrom(), "'from'");
63
+ reject(config.getTo(), "'to'");
64
+ return new UploadTimeValueGenerator(valueConverter);
65
+
66
+ default:
67
+ throw new ConfigException(String.format("Unknwon mode '%s'. Supported methods are incremental_time, fixed_time.", config.getMode()));
68
+ }
69
+ }
70
+
71
+ public static class IncrementalTimeValueGenerator
72
+ extends TimeValueGenerator
73
+ {
74
+ private final Timestamp from;
75
+ private final Timestamp to;
76
+
77
+ private Timestamp current;
78
+
79
+ public IncrementalTimeValueGenerator(final FromValueConfig config, ValueConverter valueConverter)
80
+ {
81
+ super(valueConverter);
82
+ current = from = toTimestamp(config, config.getFrom().get());
83
+ to = toTimestamp(config, config.getTo().get());
84
+ }
85
+
86
+ @Override
87
+ public Timestamp nextTimestamp()
88
+ {
89
+ try {
90
+ Timestamp ret = current;
91
+ current = Timestamp.ofEpochSecond(current.getEpochSecond() + 1, current.getNano());
92
+ return ret;
93
+ }
94
+ finally {
95
+ if (current.compareTo(to) > 0) {
96
+ current = from;
97
+ }
98
+ }
99
+ }
100
+ }
101
+
102
+ public static class FixedTimeValueGenerator
103
+ extends TimeValueGenerator
104
+ {
105
+ private final Timestamp value;
106
+
107
+ public FixedTimeValueGenerator(FromValueConfig config, ValueConverter valueConverter)
108
+ {
109
+ this(toTimestamp(config, config.getValue().get()), valueConverter);
110
+ }
111
+
112
+ public FixedTimeValueGenerator(Timestamp value, ValueConverter valueConverter)
113
+ {
114
+ super(valueConverter);
115
+ this.value = value;
116
+ }
117
+
118
+ @Override
119
+ public Timestamp nextTimestamp()
120
+ {
121
+ return value;
122
+ }
123
+
124
+ }
125
+
126
+ public static class UploadTimeValueGenerator
127
+ extends FixedTimeValueGenerator
128
+ {
129
+ public UploadTimeValueGenerator(ValueConverter valueConverter)
130
+ {
131
+ super(Exec.getTransactionTime(), valueConverter);
132
+ }
133
+ }
134
+
135
+ // ported from embulk-input-s3
136
+ private static <T> T require(Optional<T> value, String message)
137
+ {
138
+ if (value.isPresent()) {
139
+ return typeCheck(value.get(), message);
140
+ }
141
+ else {
142
+ throw new ConfigException("Required option is not set: " + message);
143
+ }
144
+ }
145
+
146
+ // ported from embulk-input-s3
147
+ private static <T> void reject(Optional<T> value, String message)
148
+ {
149
+ if (value.isPresent()) {
150
+ throw new ConfigException("Invalid option is set: " + message);
151
+ }
152
+ }
153
+
154
+ private static <T> T typeCheck(T value, String message)
155
+ {
156
+ if (value instanceof String || value instanceof Number) {
157
+ return value;
158
+ }
159
+ else {
160
+ throw new ConfigException("Required option must be string or long: " + message);
161
+ }
162
+ }
163
+
164
+ private static Timestamp toTimestamp(FromValueConfig config, Object time)
165
+ {
166
+ if (time instanceof String) {
167
+ return new TimestampParser(config, config).parse((String) time); // TODO optimize?
168
+ }
169
+ else if (time instanceof Number) {
170
+ long t = ((Number) time).longValue();
171
+ return UnixTimestampUnit.of(config.getUnixTimestampUnit()).toTimestamp(t);
172
+ }
173
+ else {
174
+ throw new RuntimeException();
175
+ }
176
+ }
177
+ }
@@ -0,0 +1,36 @@
1
+ package org.embulk.filter.add_time.reader;
2
+
3
+ import org.embulk.filter.add_time.converter.ValueConverter;
4
+ import org.embulk.spi.Column;
5
+ import org.embulk.spi.PageBuilder;
6
+ import org.embulk.spi.PageReader;
7
+ import org.embulk.spi.time.Timestamp;
8
+
9
+ public class TimestampColumnReader
10
+ extends AbstractColumnReader<TimestampColumnReader>
11
+ {
12
+ protected Timestamp value;
13
+
14
+ public TimestampColumnReader(ValueConverter valueConverter)
15
+ {
16
+ super(valueConverter);
17
+ }
18
+
19
+ @Override
20
+ public void readNonNullValue(Column column, PageReader pageReader)
21
+ {
22
+ value = pageReader.getTimestamp(column);
23
+ }
24
+
25
+ @Override
26
+ public void convertNonNullValue(Column column, PageBuilder pageBuilder)
27
+ {
28
+ valueConverter.convertValue(column, value, pageBuilder);
29
+ }
30
+
31
+ @Override
32
+ public void copyValueTo(TimestampColumnReader columnReader)
33
+ {
34
+ columnReader.value = this.value;
35
+ }
36
+ }
@@ -0,0 +1,416 @@
1
+ package org.embulk.filter.add_time;
2
+
3
+ import com.google.common.collect.ImmutableMap;
4
+ import org.embulk.EmbulkTestRuntime;
5
+ import org.embulk.config.ConfigSource;
6
+ import org.embulk.config.TaskSource;
7
+ import org.embulk.filter.add_time.AddTimeFilterPlugin.PluginTask;
8
+ import org.embulk.spi.FilterPlugin;
9
+ import org.embulk.spi.Page;
10
+ import org.embulk.spi.PageOutput;
11
+ import org.embulk.spi.PageTestUtils;
12
+ import org.embulk.spi.Schema;
13
+ import org.embulk.spi.TestPageBuilderReader.MockPageOutput;
14
+ import org.embulk.spi.time.Timestamp;
15
+ import org.embulk.spi.type.Type;
16
+ import org.embulk.spi.type.Types;
17
+ import org.embulk.spi.util.Pages;
18
+ import org.junit.Before;
19
+ import org.junit.Rule;
20
+ import org.junit.Test;
21
+
22
+ import java.util.List;
23
+
24
+ import static org.junit.Assert.assertEquals;
25
+ import static org.mockito.Mockito.spy;
26
+
27
+ public class TestAddTimeFilterPlugin
28
+ {
29
+ @Rule
30
+ public EmbulkTestRuntime runtime = new EmbulkTestRuntime();
31
+
32
+ private AddTimeFilterPlugin plugin;
33
+ private ConfigSource config;
34
+ private Schema inputSchema;
35
+ private List<Object[]> records;
36
+
37
+ @Before
38
+ public void createResources()
39
+ {
40
+ plugin = plugin();
41
+ config = runtime.getExec().newConfigSource();
42
+ inputSchema = schema("c0", Types.BOOLEAN, "c1", Types.LONG, "c2", Types.DOUBLE, "c3", Types.STRING, "c4", Types.TIMESTAMP);
43
+ }
44
+
45
+ @Test
46
+ public void testFromColumn()
47
+ {
48
+ { // long type
49
+ ConfigSource conf = this.config.deepCopy()
50
+ .set("to_column", ImmutableMap.of("name", "time"))
51
+ .set("from_column", ImmutableMap.of("name", "c1", "unix_timestamp_unit", "sec"));
52
+ List<Page> pages = newPages(true, 1451646671L, 0.1, "foo", Timestamp.ofEpochSecond(1451646671));
53
+
54
+ callTansaction(conf, inputSchema, pages);
55
+
56
+ assertEquals(1, records.size());
57
+ for (Object[] record : records) {
58
+ assertEquals(inputSchema.size() + 1, record.length);
59
+
60
+ assertEquals(true, record[0]);
61
+ assertEquals(1451646671L, record[1]);
62
+ assertEquals(0.1, record[2]);
63
+ assertEquals("foo", record[3]);
64
+ assertEquals(1451646671L, ((Timestamp) record[4]).getEpochSecond());
65
+ assertEquals(1451646671L, ((Timestamp) record[5]).getEpochSecond());
66
+ }
67
+ }
68
+
69
+ { // timestamp type
70
+ ConfigSource conf = this.config.deepCopy()
71
+ .set("to_column", ImmutableMap.of("name", "time"))
72
+ .set("from_column", ImmutableMap.of("name", "c4"));
73
+ List<Page> pages = newPages(true, 0L, 0.1, "foo", Timestamp.ofEpochSecond(1451646671));
74
+
75
+ callTansaction(conf, inputSchema, pages);
76
+
77
+ assertEquals(1, records.size());
78
+ for (Object[] record : records) {
79
+ assertEquals(inputSchema.size() + 1, record.length);
80
+
81
+ assertEquals(true, record[0]);
82
+ assertEquals(0L, record[1]);
83
+ assertEquals(0.1, record[2]);
84
+ assertEquals("foo", record[3]);
85
+ assertEquals(1451646671L, ((Timestamp) record[4]).getEpochSecond());
86
+ assertEquals(1451646671L, ((Timestamp) record[5]).getEpochSecond());
87
+ }
88
+ }
89
+
90
+ { // string type
91
+ ConfigSource conf = this.config.deepCopy()
92
+ .set("to_column", ImmutableMap.of("name", "time"))
93
+ .set("from_column", ImmutableMap.of("name", "c3"));
94
+ List<Page> pages = newPages(true, 0L, 0.1, "2016-01-01 11:11:11 UTC", Timestamp.ofEpochSecond(1451646671));
95
+
96
+ callTansaction(conf, inputSchema, pages);
97
+
98
+ assertEquals(1, records.size());
99
+ for (Object[] record : records) {
100
+ assertEquals(inputSchema.size() + 1, record.length);
101
+
102
+ assertEquals(true, record[0]);
103
+ assertEquals(0L, record[1]);
104
+ assertEquals(0.1, record[2]);
105
+ assertEquals("2016-01-01 11:11:11 UTC", record[3]);
106
+ assertEquals(1451646671L, ((Timestamp) record[4]).getEpochSecond());
107
+ assertEquals(1451646671L, ((Timestamp) record[5]).getEpochSecond());
108
+ }
109
+ }
110
+ }
111
+
112
+ @Test
113
+ public void testFromValue()
114
+ {
115
+ // mode: fixed_time
116
+ {
117
+ ConfigSource conf = this.config.deepCopy()
118
+ .set("to_column", ImmutableMap.of("name", "time"))
119
+ .set("from_value", ImmutableMap.of("mode", "fixed_time", "value", "2016-01-01 11:11:11 UTC"));
120
+ List<Page> pages = newPages(true, 0L, 0.1, "foo", Timestamp.ofEpochSecond(1451646671));
121
+
122
+ callTansaction(conf, inputSchema, pages);
123
+
124
+ assertEquals(1, records.size());
125
+ for (Object[] record : records) {
126
+ assertEquals(inputSchema.size() + 1, record.length);
127
+
128
+ assertEquals(true, record[0]);
129
+ assertEquals(0L, record[1]);
130
+ assertEquals(0.1, record[2]);
131
+ assertEquals("foo", record[3]);
132
+ assertEquals(1451646671L, ((Timestamp) record[4]).getEpochSecond());
133
+ assertEquals(1451646671L, ((Timestamp) record[5]).getEpochSecond());
134
+ }
135
+ }
136
+ { // specifies timestamp_format
137
+ ConfigSource conf = this.config.deepCopy()
138
+ .set("to_column", ImmutableMap.of("name", "time"))
139
+ .set("from_value", ImmutableMap.of("mode", "fixed_time", "value", "2016-01-01 11:11:11.000 UTC", "timestamp_format", "%Y-%m-%d %H:%M:%S.%N %Z"));
140
+ List<Page> pages = newPages(true, 0L, 0.1, "foo", Timestamp.ofEpochSecond(1451646671));
141
+
142
+ callTansaction(conf, inputSchema, pages);
143
+
144
+ assertEquals(1, records.size());
145
+ for (Object[] record : records) {
146
+ assertEquals(inputSchema.size() + 1, record.length);
147
+
148
+ assertEquals(true, record[0]);
149
+ assertEquals(0L, record[1]);
150
+ assertEquals(0.1, record[2]);
151
+ assertEquals("foo", record[3]);
152
+ assertEquals(1451646671L, ((Timestamp) record[4]).getEpochSecond());
153
+ assertEquals(1451646671L, ((Timestamp) record[5]).getEpochSecond());
154
+ }
155
+ }
156
+ { // specifies unix_timestamp_unit
157
+ ConfigSource conf = this.config.deepCopy()
158
+ .set("to_column", ImmutableMap.of("name", "time"))
159
+ .set("from_value", ImmutableMap.of("mode", "fixed_time", "value", 1451646671, "unix_timestamp_unit", "sec"));
160
+ List<Page> pages = newPages(true, 0L, 0.1, "foo", Timestamp.ofEpochSecond(1451646671));
161
+
162
+ callTansaction(conf, inputSchema, pages);
163
+
164
+ assertEquals(1, records.size());
165
+ for (Object[] record : records) {
166
+ assertEquals(inputSchema.size() + 1, record.length);
167
+
168
+ assertEquals(true, record[0]);
169
+ assertEquals(0L, record[1]);
170
+ assertEquals(0.1, record[2]);
171
+ assertEquals("foo", record[3]);
172
+ assertEquals(1451646671L, ((Timestamp) record[4]).getEpochSecond());
173
+ assertEquals(1451646671L, ((Timestamp) record[5]).getEpochSecond());
174
+ }
175
+ }
176
+
177
+ // mode: incremental_time
178
+ {
179
+ ConfigSource conf = this.config.deepCopy()
180
+ .set("to_column", ImmutableMap.of("name", "time"))
181
+ .set("from_value", ImmutableMap.of("mode", "incremental_time",
182
+ "from", "2016-01-01 11:11:11 UTC", "to", "2016-01-01 11:11:12 UTC"));
183
+ List<Page> pages = newPages(true, 0L, 0.1, "foo", Timestamp.ofEpochSecond(1451646671));
184
+
185
+ callTansaction(conf, inputSchema, pages);
186
+
187
+ assertEquals(1, records.size());
188
+ for (Object[] record : records) {
189
+ assertEquals(inputSchema.size() + 1, record.length);
190
+
191
+ assertEquals(true, record[0]);
192
+ assertEquals(0L, record[1]);
193
+ assertEquals(0.1, record[2]);
194
+ assertEquals("foo", record[3]);
195
+ assertEquals(1451646671L, ((Timestamp) record[4]).getEpochSecond());
196
+ assertEquals(1451646671L, ((Timestamp) record[5]).getEpochSecond());
197
+ }
198
+ }
199
+ { // specifies timestamp_format
200
+ ConfigSource conf = this.config.deepCopy()
201
+ .set("to_column", ImmutableMap.of("name", "time"))
202
+ .set("from_value", ImmutableMap.of("mode", "incremental_time",
203
+ "from", "2016-01-01 11:11:11.000 UTC", "to", "2016-01-01 11:11:12.000 UTC", "timestamp_format", "%Y-%m-%d %H:%M:%S.%N %Z"));
204
+ List<Page> pages = newPages(true, 0L, 0.1, "foo", Timestamp.ofEpochSecond(1451646671));
205
+
206
+ callTansaction(conf, inputSchema, pages);
207
+
208
+ assertEquals(1, records.size());
209
+ for (Object[] record : records) {
210
+ assertEquals(inputSchema.size() + 1, record.length);
211
+
212
+ assertEquals(true, record[0]);
213
+ assertEquals(0L, record[1]);
214
+ assertEquals(0.1, record[2]);
215
+ assertEquals("foo", record[3]);
216
+ assertEquals(1451646671L, ((Timestamp) record[4]).getEpochSecond());
217
+ assertEquals(1451646671L, ((Timestamp) record[5]).getEpochSecond());
218
+ }
219
+ }
220
+ { // specifies unix_timestamp_unit
221
+ ConfigSource conf = this.config.deepCopy()
222
+ .set("to_column", ImmutableMap.of("name", "time"))
223
+ .set("from_value", ImmutableMap.of("mode", "incremental_time",
224
+ "from", 1451646671, "to", 1451646672, "unix_timestamp_unit", "sec"));
225
+ List<Page> pages = newPages(true, 0L, 0.1, "foo", Timestamp.ofEpochSecond(1451646671));
226
+
227
+ callTansaction(conf, inputSchema, pages);
228
+
229
+ assertEquals(1, records.size());
230
+ for (Object[] record : records) {
231
+ assertEquals(inputSchema.size() + 1, record.length);
232
+
233
+ assertEquals(true, record[0]);
234
+ assertEquals(0L, record[1]);
235
+ assertEquals(0.1, record[2]);
236
+ assertEquals("foo", record[3]);
237
+ assertEquals(1451646671L, ((Timestamp) record[4]).getEpochSecond());
238
+ assertEquals(1451646671L, ((Timestamp) record[5]).getEpochSecond());
239
+ }
240
+ }
241
+
242
+ // mode: upload_time
243
+ {
244
+ ConfigSource conf = this.config.deepCopy()
245
+ .set("to_column", ImmutableMap.of("name", "time"))
246
+ .set("from_value", ImmutableMap.of("mode", "upload_time"));
247
+ List<Page> pages = newPages(true, 0L, 0.1, "foo", Timestamp.ofEpochSecond(1451646671));
248
+
249
+ callTansaction(conf, inputSchema, pages);
250
+
251
+ assertEquals(1, records.size());
252
+ for (Object[] record : records) {
253
+ assertEquals(inputSchema.size() + 1, record.length);
254
+
255
+ assertEquals(true, record[0]);
256
+ assertEquals(0L, record[1]);
257
+ assertEquals(0.1, record[2]);
258
+ assertEquals("foo", record[3]);
259
+ assertEquals(1451646671L, ((Timestamp) record[4]).getEpochSecond());
260
+ assertEquals(runtime.getExec().getTransactionTime(), record[5]);
261
+ }
262
+ }
263
+ }
264
+
265
+ @Test
266
+ public void testToColumn()
267
+ {
268
+ // timestamp type
269
+ {
270
+ ConfigSource conf = this.config.deepCopy()
271
+ .set("to_column", ImmutableMap.of("name", "time"))
272
+ .set("from_value", ImmutableMap.of("mode", "fixed_time", "value", "2016-01-01 11:11:11 UTC"));
273
+ List<Page> pages = newPages(true, 0L, 0.1, "foo", Timestamp.ofEpochSecond(1451646671));
274
+
275
+ callTansaction(conf, inputSchema, pages);
276
+
277
+ assertEquals(1, records.size());
278
+ for (Object[] record : records) {
279
+ assertEquals(inputSchema.size() + 1, record.length);
280
+
281
+ assertEquals(true, record[0]);
282
+ assertEquals(0L, record[1]);
283
+ assertEquals(0.1, record[2]);
284
+ assertEquals("foo", record[3]);
285
+ assertEquals(1451646671L, ((Timestamp) record[4]).getEpochSecond());
286
+ assertEquals(1451646671L, ((Timestamp) record[5]).getEpochSecond());
287
+ }
288
+ }
289
+
290
+ // long type
291
+ { // unix_timestamp: sec
292
+ ConfigSource conf = this.config.deepCopy()
293
+ .set("to_column", ImmutableMap.of("name", "time", "type", "long", "unix_timestamp_unit", "sec"))
294
+ .set("from_value", ImmutableMap.of("mode", "fixed_time", "value", "2016-01-01 11:11:11 UTC"));
295
+ List<Page> pages = newPages(true, 0L, 0.1, "foo", Timestamp.ofEpochSecond(1451646671));
296
+
297
+ callTansaction(conf, inputSchema, pages);
298
+
299
+ assertEquals(1, records.size());
300
+ for (Object[] record : records) {
301
+ assertEquals(inputSchema.size() + 1, record.length);
302
+
303
+ assertEquals(true, record[0]);
304
+ assertEquals(0L, record[1]);
305
+ assertEquals(0.1, record[2]);
306
+ assertEquals("foo", record[3]);
307
+ assertEquals(1451646671L, ((Timestamp) record[4]).getEpochSecond());
308
+ assertEquals(1451646671L, record[5]);
309
+ }
310
+ }
311
+ { // unix_timestamp: milli
312
+ ConfigSource conf = this.config.deepCopy()
313
+ .set("to_column", ImmutableMap.of("name", "time", "type", "long", "unix_timestamp_unit", "milli"))
314
+ .set("from_value", ImmutableMap.of("mode", "fixed_time", "value", "2016-01-01 11:11:11 UTC"));
315
+ List<Page> pages = newPages(true, 0L, 0.1, "foo", Timestamp.ofEpochSecond(1451646671));
316
+
317
+ callTansaction(conf, inputSchema, pages);
318
+
319
+ assertEquals(1, records.size());
320
+ for (Object[] record : records) {
321
+ assertEquals(inputSchema.size() + 1, record.length);
322
+
323
+ assertEquals(true, record[0]);
324
+ assertEquals(0L, record[1]);
325
+ assertEquals(0.1, record[2]);
326
+ assertEquals("foo", record[3]);
327
+ assertEquals(1451646671L, ((Timestamp) record[4]).getEpochSecond());
328
+ assertEquals(1451646671000L, record[5]);
329
+ }
330
+ }
331
+ { // unix_timestamp: micro
332
+ ConfigSource conf = this.config.deepCopy()
333
+ .set("to_column", ImmutableMap.of("name", "time", "type", "long", "unix_timestamp_unit", "micro"))
334
+ .set("from_value", ImmutableMap.of("mode", "fixed_time", "value", "2016-01-01 11:11:11 UTC"));
335
+ List<Page> pages = newPages(true, 0L, 0.1, "foo", Timestamp.ofEpochSecond(1451646671));
336
+
337
+ callTansaction(conf, inputSchema, pages);
338
+
339
+ assertEquals(1, records.size());
340
+ for (Object[] record : records) {
341
+ assertEquals(inputSchema.size() + 1, record.length);
342
+
343
+ assertEquals(true, record[0]);
344
+ assertEquals(0L, record[1]);
345
+ assertEquals(0.1, record[2]);
346
+ assertEquals("foo", record[3]);
347
+ assertEquals(1451646671L, ((Timestamp) record[4]).getEpochSecond());
348
+ assertEquals(1451646671000000L, record[5]);
349
+ }
350
+ }
351
+ { // unix_timestamp: nano
352
+ ConfigSource conf = this.config.deepCopy()
353
+ .set("to_column", ImmutableMap.of("name", "time", "type", "long", "unix_timestamp_unit", "nano"))
354
+ .set("from_value", ImmutableMap.of("mode", "fixed_time", "value", "2016-01-01 11:11:11 UTC"));
355
+ List<Page> pages = newPages(true, 0L, 0.1, "foo", Timestamp.ofEpochSecond(1451646671));
356
+
357
+ callTansaction(conf, inputSchema, pages);
358
+
359
+ assertEquals(1, records.size());
360
+ for (Object[] record : records) {
361
+ assertEquals(inputSchema.size() + 1, record.length);
362
+
363
+ assertEquals(true, record[0]);
364
+ assertEquals(0L, record[1]);
365
+ assertEquals(0.1, record[2]);
366
+ assertEquals("foo", record[3]);
367
+ assertEquals(1451646671L, ((Timestamp) record[4]).getEpochSecond());
368
+ assertEquals(1451646671000000000L, record[5]);
369
+ }
370
+ }
371
+ }
372
+
373
+ private List<Page> newPages(Object... values)
374
+ {
375
+ return PageTestUtils.buildPage(runtime.getBufferAllocator(), inputSchema, values);
376
+ }
377
+
378
+ private void callTansaction(ConfigSource conf, final Schema inputSchema, final List<Page> pages)
379
+ {
380
+ final MockPageOutput output = new MockPageOutput();
381
+ plugin.transaction(conf, inputSchema, new FilterPlugin.Control() {
382
+ @Override
383
+ public void run(TaskSource taskSource, Schema outputSchema)
384
+ {
385
+ try (PageOutput out = plugin.open(taskSource, inputSchema, outputSchema, output)) {
386
+ for (Page page : pages) {
387
+ out.add(page);
388
+ }
389
+ out.finish();
390
+ }
391
+ records = Pages.toObjects(outputSchema, output.pages);
392
+ }
393
+ });
394
+ }
395
+
396
+ public static Schema schema(Object... nameAndTypes)
397
+ {
398
+ Schema.Builder builder = Schema.builder();
399
+ for (int i = 0; i < nameAndTypes.length; i += 2) {
400
+ String name = (String) nameAndTypes[i];
401
+ Type type = (Type) nameAndTypes[i + 1];
402
+ builder.add(name, type);
403
+ }
404
+ return builder.build();
405
+ }
406
+
407
+ public static PluginTask pluginTask(ConfigSource config)
408
+ {
409
+ return config.loadConfig(PluginTask.class);
410
+ }
411
+
412
+ public static AddTimeFilterPlugin plugin()
413
+ {
414
+ return spy(new AddTimeFilterPlugin());
415
+ }
416
+ }