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.
- checksums.yaml +7 -0
- data/.gitignore +15 -0
- data/.travis.yml +7 -0
- data/CHANGELOG.md +3 -0
- data/COPYING +14 -0
- data/README.md +212 -0
- data/build.gradle +82 -0
- data/gradle/check.gradle +34 -0
- data/gradle/wrapper/gradle-wrapper.jar +0 -0
- data/gradle/wrapper/gradle-wrapper.properties +6 -0
- data/gradlew +164 -0
- data/gradlew.bat +90 -0
- data/lib/embulk/filter/add_time.rb +3 -0
- data/src/main/java/org/embulk/filter/add_time/AddTimeFilterPlugin.java +208 -0
- data/src/main/java/org/embulk/filter/add_time/converter/ColumnConverter.java +14 -0
- data/src/main/java/org/embulk/filter/add_time/converter/ColumnDuplicator.java +72 -0
- data/src/main/java/org/embulk/filter/add_time/converter/LongValueCastConverter.java +33 -0
- data/src/main/java/org/embulk/filter/add_time/converter/SchemaConverter.java +257 -0
- data/src/main/java/org/embulk/filter/add_time/converter/SimpleColumnConverter.java +62 -0
- data/src/main/java/org/embulk/filter/add_time/converter/StringValueCastConverter.java +33 -0
- data/src/main/java/org/embulk/filter/add_time/converter/TimestampValueCastConverter.java +23 -0
- data/src/main/java/org/embulk/filter/add_time/converter/ValueCastConverter.java +108 -0
- data/src/main/java/org/embulk/filter/add_time/converter/ValueConverter.java +22 -0
- data/src/main/java/org/embulk/filter/add_time/converter/ValueNoConverter.java +46 -0
- data/src/main/java/org/embulk/filter/add_time/reader/AbstractColumnReader.java +55 -0
- data/src/main/java/org/embulk/filter/add_time/reader/BooleanColumnReader.java +35 -0
- data/src/main/java/org/embulk/filter/add_time/reader/ColumnReader.java +14 -0
- data/src/main/java/org/embulk/filter/add_time/reader/DoubleColumnReader.java +35 -0
- data/src/main/java/org/embulk/filter/add_time/reader/LongColumnReader.java +35 -0
- data/src/main/java/org/embulk/filter/add_time/reader/StringColumnReader.java +35 -0
- data/src/main/java/org/embulk/filter/add_time/reader/TimeValueGenerator.java +177 -0
- data/src/main/java/org/embulk/filter/add_time/reader/TimestampColumnReader.java +36 -0
- data/src/test/java/org/embulk/filter/add_time/TestAddTimeFilterPlugin.java +416 -0
- data/src/test/java/org/embulk/filter/add_time/converter/TestSchemaConverter.java +338 -0
- 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
|
+
}
|