embulk-output-td 0.1.4 → 0.1.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +7 -0
- data/CHANGELOG.md +4 -0
- data/README.md +1 -0
- data/build.gradle +5 -1
- data/config/checkstyle/checkstyle.xml +117 -0
- data/embulk-output-td.gemspec +1 -1
- data/gradle/check.gradle +34 -0
- data/src/main/java/com/treasuredata/api/TdApiClient.java +47 -23
- data/src/main/java/com/treasuredata/api/TdApiClientConfig.java +3 -3
- data/src/main/java/com/treasuredata/api/TdApiConstants.java +6 -2
- data/src/main/java/com/treasuredata/api/TdApiExecutionInterruptedException.java +2 -1
- data/src/main/java/com/treasuredata/api/TdApiExecutionTimeoutException.java +2 -1
- data/src/main/java/com/treasuredata/api/model/TDArrayColumnType.java +1 -1
- data/src/main/java/com/treasuredata/api/model/TDBulkImportSession.java +6 -4
- data/src/main/java/com/treasuredata/api/model/TDColumn.java +4 -2
- data/src/main/java/com/treasuredata/api/model/TDColumnTypeDeserializer.java +26 -13
- data/src/main/java/com/treasuredata/api/model/TDDatabase.java +2 -1
- data/src/main/java/com/treasuredata/api/model/TDMapColumnType.java +1 -1
- data/src/main/java/com/treasuredata/api/model/TDTablePermission.java +4 -2
- data/src/main/java/com/treasuredata/api/model/TDTableType.java +2 -1
- data/src/main/java/org/embulk/output/td/FinalizableExecutorService.java +35 -17
- data/src/main/java/org/embulk/output/td/MsgpackGZFileBuilder.java +13 -7
- data/src/main/java/org/embulk/output/td/RecordWriter.java +21 -382
- data/src/main/java/org/embulk/output/td/TdOutputPlugin.java +175 -40
- data/src/main/java/org/embulk/output/td/writer/BooleanFieldWriter.java +23 -0
- data/src/main/java/org/embulk/output/td/writer/DoubleFieldWriter.java +23 -0
- data/src/main/java/org/embulk/output/td/writer/FieldWriter.java +38 -0
- data/src/main/java/org/embulk/output/td/writer/FieldWriterSet.java +206 -0
- data/src/main/java/org/embulk/output/td/writer/LongFieldWriter.java +23 -0
- data/src/main/java/org/embulk/output/td/writer/StringFieldWriter.java +23 -0
- data/src/main/java/org/embulk/output/td/writer/TimestampFieldLongDuplicator.java +28 -0
- data/src/main/java/org/embulk/output/td/writer/TimestampLongFieldWriter.java +23 -0
- data/src/main/java/org/embulk/output/td/writer/TimestampStringFieldWriter.java +27 -0
- data/src/main/java/org/embulk/output/td/writer/UnixTimestampFieldDuplicator.java +27 -0
- data/src/main/java/org/embulk/output/td/writer/UnixTimestampLongFieldWriter.java +26 -0
- data/src/test/java/com/treasuredata/api/TestTdApiClient.java +1 -1
- data/src/test/java/org/embulk/output/td/TestRecordWriter.java +198 -0
- data/src/test/java/org/embulk/output/td/TestTdOutputPlugin.java +529 -0
- data/src/test/java/org/embulk/output/td/writer/TestFieldWriterSet.java +146 -0
- metadata +29 -14
- data/src/test/java/org/embulk/output/td/TestFieldWriter.java +0 -105
@@ -0,0 +1,38 @@
|
|
1
|
+
package org.embulk.output.td.writer;
|
2
|
+
|
3
|
+
import org.embulk.output.td.MsgpackGZFileBuilder;
|
4
|
+
import org.embulk.spi.Column;
|
5
|
+
import org.embulk.spi.PageReader;
|
6
|
+
|
7
|
+
import java.io.IOException;
|
8
|
+
|
9
|
+
public abstract class FieldWriter
|
10
|
+
{
|
11
|
+
private final String keyName;
|
12
|
+
|
13
|
+
protected FieldWriter(String keyName)
|
14
|
+
{
|
15
|
+
this.keyName = keyName;
|
16
|
+
}
|
17
|
+
|
18
|
+
public void writeKeyValue(MsgpackGZFileBuilder builder, PageReader reader, Column column)
|
19
|
+
throws IOException
|
20
|
+
{
|
21
|
+
writeKey(builder);
|
22
|
+
if (reader.isNull(column)) {
|
23
|
+
builder.writeNil();
|
24
|
+
}
|
25
|
+
else {
|
26
|
+
writeValue(builder, reader, column);
|
27
|
+
}
|
28
|
+
}
|
29
|
+
|
30
|
+
private void writeKey(MsgpackGZFileBuilder builder)
|
31
|
+
throws IOException
|
32
|
+
{
|
33
|
+
builder.writeString(keyName);
|
34
|
+
}
|
35
|
+
|
36
|
+
protected abstract void writeValue(MsgpackGZFileBuilder builder, PageReader reader, Column column)
|
37
|
+
throws IOException;
|
38
|
+
}
|
@@ -0,0 +1,206 @@
|
|
1
|
+
package org.embulk.output.td.writer;
|
2
|
+
|
3
|
+
import com.google.common.base.Optional;
|
4
|
+
import org.embulk.config.ConfigException;
|
5
|
+
import org.embulk.output.td.TdOutputPlugin;
|
6
|
+
import org.embulk.spi.Column;
|
7
|
+
import org.embulk.spi.Schema;
|
8
|
+
import org.embulk.spi.time.TimestampFormatter;
|
9
|
+
import org.embulk.spi.type.BooleanType;
|
10
|
+
import org.embulk.spi.type.DoubleType;
|
11
|
+
import org.embulk.spi.type.LongType;
|
12
|
+
import org.embulk.spi.type.StringType;
|
13
|
+
import org.embulk.spi.type.TimestampType;
|
14
|
+
import org.embulk.spi.type.Type;
|
15
|
+
import org.embulk.spi.util.Timestamps;
|
16
|
+
import org.slf4j.Logger;
|
17
|
+
|
18
|
+
public class FieldWriterSet
|
19
|
+
{
|
20
|
+
private enum ColumnWriterMode
|
21
|
+
{
|
22
|
+
PRIMARY_KEY,
|
23
|
+
SIMPLE_VALUE,
|
24
|
+
DUPLICATE_PRIMARY_KEY;
|
25
|
+
}
|
26
|
+
|
27
|
+
private final int fieldCount;
|
28
|
+
private final FieldWriter[] fieldWriters;
|
29
|
+
|
30
|
+
public FieldWriterSet(Logger log, TdOutputPlugin.PluginTask task, Schema schema)
|
31
|
+
{
|
32
|
+
Optional<String> userDefinedPrimaryKeySourceColumnName = task.getTimeColumn();
|
33
|
+
boolean hasPkWriter = false;
|
34
|
+
int duplicatePrimaryKeySourceIndex = -1;
|
35
|
+
int firstTimestampColumnIndex = -1;
|
36
|
+
|
37
|
+
int fc = 0;
|
38
|
+
fieldWriters = new FieldWriter[schema.size()];
|
39
|
+
TimestampFormatter[] timestampFormatters = Timestamps.newTimestampColumnFormatters(task, schema, task.getColumnOptions());
|
40
|
+
|
41
|
+
for (int i = 0; i < schema.size(); i++) {
|
42
|
+
String columnName = schema.getColumnName(i);
|
43
|
+
Type columnType = schema.getColumnType(i);
|
44
|
+
|
45
|
+
// choose the mode
|
46
|
+
final ColumnWriterMode mode;
|
47
|
+
|
48
|
+
if (userDefinedPrimaryKeySourceColumnName.isPresent() &&
|
49
|
+
columnName.equals(userDefinedPrimaryKeySourceColumnName.get())) {
|
50
|
+
// found time_column
|
51
|
+
if ("time".equals(userDefinedPrimaryKeySourceColumnName.get())) {
|
52
|
+
mode = ColumnWriterMode.PRIMARY_KEY;
|
53
|
+
}
|
54
|
+
else {
|
55
|
+
mode = ColumnWriterMode.DUPLICATE_PRIMARY_KEY;
|
56
|
+
}
|
57
|
+
}
|
58
|
+
else if ("time".equals(columnName)) {
|
59
|
+
// the column name is same with the primary key name.
|
60
|
+
if (userDefinedPrimaryKeySourceColumnName.isPresent()) {
|
61
|
+
columnName = newColumnUniqueName(columnName, schema);
|
62
|
+
mode = ColumnWriterMode.SIMPLE_VALUE;
|
63
|
+
log.warn("time_column '{}' is set but 'time' column also exists. The existent 'time' column is renamed to {}",
|
64
|
+
userDefinedPrimaryKeySourceColumnName.get(), "time", "time", columnName);
|
65
|
+
}
|
66
|
+
else {
|
67
|
+
mode = ColumnWriterMode.PRIMARY_KEY;
|
68
|
+
}
|
69
|
+
}
|
70
|
+
else {
|
71
|
+
mode = ColumnWriterMode.SIMPLE_VALUE;
|
72
|
+
}
|
73
|
+
|
74
|
+
// create the fieldWriters writer depending on the mode
|
75
|
+
final FieldWriter writer;
|
76
|
+
|
77
|
+
switch (mode) {
|
78
|
+
case PRIMARY_KEY:
|
79
|
+
log.info("Using {}:{} column as the data partitioning key", columnName, columnType);
|
80
|
+
if (columnType instanceof LongType) {
|
81
|
+
if (task.getUnixTimestampUnit() != TdOutputPlugin.UnixTimestampUnit.SEC) {
|
82
|
+
log.warn("time column is converted from {} to seconds", task.getUnixTimestampUnit());
|
83
|
+
}
|
84
|
+
writer = new UnixTimestampLongFieldWriter(columnName, task.getUnixTimestampUnit().getFractionUnit());
|
85
|
+
hasPkWriter = true;
|
86
|
+
}
|
87
|
+
else if (columnType instanceof TimestampType) {
|
88
|
+
writer = new TimestampLongFieldWriter(columnName);
|
89
|
+
|
90
|
+
hasPkWriter = true;
|
91
|
+
}
|
92
|
+
else {
|
93
|
+
throw new ConfigException(String.format("Type of '%s' column must be long or timestamp but got %s",
|
94
|
+
columnName, columnType));
|
95
|
+
}
|
96
|
+
break;
|
97
|
+
|
98
|
+
case SIMPLE_VALUE:
|
99
|
+
if (columnType instanceof BooleanType) {
|
100
|
+
writer = new BooleanFieldWriter(columnName);
|
101
|
+
}
|
102
|
+
else if (columnType instanceof LongType) {
|
103
|
+
writer = new LongFieldWriter(columnName);
|
104
|
+
}
|
105
|
+
else if (columnType instanceof DoubleType) {
|
106
|
+
writer = new DoubleFieldWriter(columnName);
|
107
|
+
}
|
108
|
+
else if (columnType instanceof StringType) {
|
109
|
+
writer = new StringFieldWriter(columnName);
|
110
|
+
}
|
111
|
+
else if (columnType instanceof TimestampType) {
|
112
|
+
writer = new TimestampStringFieldWriter(timestampFormatters[i], columnName);
|
113
|
+
if (firstTimestampColumnIndex < 0) {
|
114
|
+
firstTimestampColumnIndex = i;
|
115
|
+
}
|
116
|
+
}
|
117
|
+
else {
|
118
|
+
throw new ConfigException("Unsupported type: " + columnType);
|
119
|
+
}
|
120
|
+
break;
|
121
|
+
|
122
|
+
case DUPLICATE_PRIMARY_KEY:
|
123
|
+
duplicatePrimaryKeySourceIndex = i;
|
124
|
+
writer = null; // handle later
|
125
|
+
break;
|
126
|
+
|
127
|
+
default:
|
128
|
+
throw new AssertionError();
|
129
|
+
}
|
130
|
+
|
131
|
+
fieldWriters[i] = writer;
|
132
|
+
fc += 1;
|
133
|
+
}
|
134
|
+
|
135
|
+
if (!hasPkWriter) {
|
136
|
+
// PRIMARY_KEY was not found.
|
137
|
+
if (duplicatePrimaryKeySourceIndex < 0) {
|
138
|
+
if (userDefinedPrimaryKeySourceColumnName.isPresent()) {
|
139
|
+
throw new ConfigException(String.format("time_column '%s' does not exist", userDefinedPrimaryKeySourceColumnName.get()));
|
140
|
+
}
|
141
|
+
else if (firstTimestampColumnIndex >= 0) {
|
142
|
+
// if time is not found, use the first timestamp column
|
143
|
+
duplicatePrimaryKeySourceIndex = firstTimestampColumnIndex;
|
144
|
+
}
|
145
|
+
else {
|
146
|
+
throw new ConfigException(String.format("TD output plugin requires at least one timestamp column, or a long column named 'time'"));
|
147
|
+
}
|
148
|
+
}
|
149
|
+
|
150
|
+
String columnName = schema.getColumnName(duplicatePrimaryKeySourceIndex);
|
151
|
+
Type columnType = schema.getColumnType(duplicatePrimaryKeySourceIndex);
|
152
|
+
|
153
|
+
FieldWriter writer;
|
154
|
+
if (columnType instanceof LongType) {
|
155
|
+
log.info("Duplicating {}:{} column (unix timestamp {}) to 'time' column as seconds for the data partitioning",
|
156
|
+
columnName, columnType, task.getUnixTimestampUnit());
|
157
|
+
writer = new UnixTimestampFieldDuplicator(columnName, "time", task.getUnixTimestampUnit().getFractionUnit());
|
158
|
+
}
|
159
|
+
else if (columnType instanceof TimestampType) {
|
160
|
+
log.info("Duplicating {}:{} column to 'time' column as seconds for the data partitioning",
|
161
|
+
columnName, columnType);
|
162
|
+
writer = new TimestampFieldLongDuplicator(timestampFormatters[duplicatePrimaryKeySourceIndex], columnName, "time");
|
163
|
+
}
|
164
|
+
else {
|
165
|
+
throw new ConfigException(String.format("Type of '%s' column must be long or timestamp but got %s",
|
166
|
+
columnName, columnType));
|
167
|
+
}
|
168
|
+
|
169
|
+
// replace existint writer
|
170
|
+
fieldWriters[duplicatePrimaryKeySourceIndex] = writer;
|
171
|
+
fc += 1;
|
172
|
+
}
|
173
|
+
|
174
|
+
fieldCount = fc;
|
175
|
+
}
|
176
|
+
|
177
|
+
private static String newColumnUniqueName(String originalName, Schema schema)
|
178
|
+
{
|
179
|
+
String name = originalName;
|
180
|
+
do {
|
181
|
+
name += "_";
|
182
|
+
}
|
183
|
+
while (containsColumnName(schema, name));
|
184
|
+
return name;
|
185
|
+
}
|
186
|
+
|
187
|
+
private static boolean containsColumnName(Schema schema, String name)
|
188
|
+
{
|
189
|
+
for (Column c : schema.getColumns()) {
|
190
|
+
if (c.getName().equals(name)) {
|
191
|
+
return true;
|
192
|
+
}
|
193
|
+
}
|
194
|
+
return false;
|
195
|
+
}
|
196
|
+
|
197
|
+
public FieldWriter getFieldWriter(int index)
|
198
|
+
{
|
199
|
+
return fieldWriters[index];
|
200
|
+
}
|
201
|
+
|
202
|
+
public int getFieldCount()
|
203
|
+
{
|
204
|
+
return fieldCount;
|
205
|
+
}
|
206
|
+
}
|
@@ -0,0 +1,23 @@
|
|
1
|
+
package org.embulk.output.td.writer;
|
2
|
+
|
3
|
+
import org.embulk.output.td.MsgpackGZFileBuilder;
|
4
|
+
import org.embulk.spi.Column;
|
5
|
+
import org.embulk.spi.PageReader;
|
6
|
+
|
7
|
+
import java.io.IOException;
|
8
|
+
|
9
|
+
public class LongFieldWriter
|
10
|
+
extends FieldWriter
|
11
|
+
{
|
12
|
+
LongFieldWriter(String keyName)
|
13
|
+
{
|
14
|
+
super(keyName);
|
15
|
+
}
|
16
|
+
|
17
|
+
@Override
|
18
|
+
public void writeValue(MsgpackGZFileBuilder builder, PageReader reader, Column column)
|
19
|
+
throws IOException
|
20
|
+
{
|
21
|
+
builder.writeLong(reader.getLong(column));
|
22
|
+
}
|
23
|
+
}
|
@@ -0,0 +1,23 @@
|
|
1
|
+
package org.embulk.output.td.writer;
|
2
|
+
|
3
|
+
import org.embulk.output.td.MsgpackGZFileBuilder;
|
4
|
+
import org.embulk.spi.Column;
|
5
|
+
import org.embulk.spi.PageReader;
|
6
|
+
|
7
|
+
import java.io.IOException;
|
8
|
+
|
9
|
+
public class StringFieldWriter
|
10
|
+
extends FieldWriter
|
11
|
+
{
|
12
|
+
public StringFieldWriter(String keyName)
|
13
|
+
{
|
14
|
+
super(keyName);
|
15
|
+
}
|
16
|
+
|
17
|
+
@Override
|
18
|
+
public void writeValue(MsgpackGZFileBuilder builder, PageReader reader, Column column)
|
19
|
+
throws IOException
|
20
|
+
{
|
21
|
+
builder.writeString(reader.getString(column));
|
22
|
+
}
|
23
|
+
}
|
@@ -0,0 +1,28 @@
|
|
1
|
+
package org.embulk.output.td.writer;
|
2
|
+
|
3
|
+
import org.embulk.output.td.MsgpackGZFileBuilder;
|
4
|
+
import org.embulk.spi.Column;
|
5
|
+
import org.embulk.spi.PageReader;
|
6
|
+
import org.embulk.spi.time.TimestampFormatter;
|
7
|
+
|
8
|
+
import java.io.IOException;
|
9
|
+
|
10
|
+
public class TimestampFieldLongDuplicator
|
11
|
+
extends TimestampStringFieldWriter
|
12
|
+
{
|
13
|
+
private final TimestampLongFieldWriter timeFieldWriter;
|
14
|
+
|
15
|
+
public TimestampFieldLongDuplicator(TimestampFormatter formatter, String keyName, String longDuplicateKeyName)
|
16
|
+
{
|
17
|
+
super(formatter, keyName);
|
18
|
+
timeFieldWriter = new TimestampLongFieldWriter(longDuplicateKeyName);
|
19
|
+
}
|
20
|
+
|
21
|
+
@Override
|
22
|
+
public void writeValue(MsgpackGZFileBuilder builder, PageReader reader, Column column)
|
23
|
+
throws IOException
|
24
|
+
{
|
25
|
+
super.writeValue(builder, reader, column);
|
26
|
+
timeFieldWriter.writeKeyValue(builder, reader, column);
|
27
|
+
}
|
28
|
+
}
|
@@ -0,0 +1,23 @@
|
|
1
|
+
package org.embulk.output.td.writer;
|
2
|
+
|
3
|
+
import org.embulk.output.td.MsgpackGZFileBuilder;
|
4
|
+
import org.embulk.spi.Column;
|
5
|
+
import org.embulk.spi.PageReader;
|
6
|
+
|
7
|
+
import java.io.IOException;
|
8
|
+
|
9
|
+
public class TimestampLongFieldWriter
|
10
|
+
extends FieldWriter
|
11
|
+
{
|
12
|
+
public TimestampLongFieldWriter(String keyName)
|
13
|
+
{
|
14
|
+
super(keyName);
|
15
|
+
}
|
16
|
+
|
17
|
+
@Override
|
18
|
+
public void writeValue(MsgpackGZFileBuilder builder, PageReader reader, Column column)
|
19
|
+
throws IOException
|
20
|
+
{
|
21
|
+
builder.writeLong(reader.getTimestamp(column).getEpochSecond());
|
22
|
+
}
|
23
|
+
}
|
@@ -0,0 +1,27 @@
|
|
1
|
+
package org.embulk.output.td.writer;
|
2
|
+
|
3
|
+
import org.embulk.output.td.MsgpackGZFileBuilder;
|
4
|
+
import org.embulk.spi.Column;
|
5
|
+
import org.embulk.spi.PageReader;
|
6
|
+
import org.embulk.spi.time.TimestampFormatter;
|
7
|
+
|
8
|
+
import java.io.IOException;
|
9
|
+
|
10
|
+
public class TimestampStringFieldWriter
|
11
|
+
extends FieldWriter
|
12
|
+
{
|
13
|
+
private final TimestampFormatter formatter;
|
14
|
+
|
15
|
+
public TimestampStringFieldWriter(TimestampFormatter formatter, String keyName)
|
16
|
+
{
|
17
|
+
super(keyName);
|
18
|
+
this.formatter = formatter;
|
19
|
+
}
|
20
|
+
|
21
|
+
@Override
|
22
|
+
public void writeValue(MsgpackGZFileBuilder builder, PageReader reader, Column column)
|
23
|
+
throws IOException
|
24
|
+
{
|
25
|
+
builder.writeString(formatter.format(reader.getTimestamp(column)));
|
26
|
+
}
|
27
|
+
}
|
@@ -0,0 +1,27 @@
|
|
1
|
+
package org.embulk.output.td.writer;
|
2
|
+
|
3
|
+
import org.embulk.output.td.MsgpackGZFileBuilder;
|
4
|
+
import org.embulk.spi.Column;
|
5
|
+
import org.embulk.spi.PageReader;
|
6
|
+
|
7
|
+
import java.io.IOException;
|
8
|
+
|
9
|
+
public class UnixTimestampFieldDuplicator
|
10
|
+
extends LongFieldWriter
|
11
|
+
{
|
12
|
+
private final UnixTimestampLongFieldWriter timeFieldWriter;
|
13
|
+
|
14
|
+
public UnixTimestampFieldDuplicator(String keyName, String duplicateKeyName, int fractionUnit)
|
15
|
+
{
|
16
|
+
super(keyName);
|
17
|
+
timeFieldWriter = new UnixTimestampLongFieldWriter(duplicateKeyName, fractionUnit);
|
18
|
+
}
|
19
|
+
|
20
|
+
@Override
|
21
|
+
public void writeValue(MsgpackGZFileBuilder builder, PageReader reader, Column column)
|
22
|
+
throws IOException
|
23
|
+
{
|
24
|
+
super.writeValue(builder, reader, column);
|
25
|
+
timeFieldWriter.writeKeyValue(builder, reader, column);
|
26
|
+
}
|
27
|
+
}
|
@@ -0,0 +1,26 @@
|
|
1
|
+
package org.embulk.output.td.writer;
|
2
|
+
|
3
|
+
import org.embulk.output.td.MsgpackGZFileBuilder;
|
4
|
+
import org.embulk.spi.Column;
|
5
|
+
import org.embulk.spi.PageReader;
|
6
|
+
|
7
|
+
import java.io.IOException;
|
8
|
+
|
9
|
+
public class UnixTimestampLongFieldWriter
|
10
|
+
extends FieldWriter
|
11
|
+
{
|
12
|
+
private final int fractionUnit;
|
13
|
+
|
14
|
+
UnixTimestampLongFieldWriter(String keyName, int fractionUnit)
|
15
|
+
{
|
16
|
+
super(keyName);
|
17
|
+
this.fractionUnit = fractionUnit;
|
18
|
+
}
|
19
|
+
|
20
|
+
@Override
|
21
|
+
public void writeValue(MsgpackGZFileBuilder builder, PageReader reader, Column column)
|
22
|
+
throws IOException
|
23
|
+
{
|
24
|
+
builder.writeLong(reader.getLong(column) / fractionUnit);
|
25
|
+
}
|
26
|
+
}
|
@@ -0,0 +1,198 @@
|
|
1
|
+
package org.embulk.output.td;
|
2
|
+
|
3
|
+
import com.treasuredata.api.TdApiClient;
|
4
|
+
import org.embulk.EmbulkTestRuntime;
|
5
|
+
import org.embulk.output.td.TdOutputPlugin.PluginTask;
|
6
|
+
import org.embulk.output.td.writer.FieldWriterSet;
|
7
|
+
import org.embulk.spi.Page;
|
8
|
+
import org.embulk.spi.PageTestUtils;
|
9
|
+
import org.embulk.spi.Schema;
|
10
|
+
import org.embulk.spi.time.Timestamp;
|
11
|
+
import org.embulk.spi.type.Types;
|
12
|
+
import org.junit.Before;
|
13
|
+
import org.junit.Rule;
|
14
|
+
import org.junit.Test;
|
15
|
+
import org.msgpack.MessagePack;
|
16
|
+
import org.msgpack.type.MapValue;
|
17
|
+
import org.msgpack.unpacker.Unpacker;
|
18
|
+
import org.slf4j.Logger;
|
19
|
+
|
20
|
+
import java.io.File;
|
21
|
+
import java.io.FileInputStream;
|
22
|
+
import java.util.zip.GZIPInputStream;
|
23
|
+
|
24
|
+
import static org.embulk.output.td.TestTdOutputPlugin.config;
|
25
|
+
import static org.embulk.output.td.TestTdOutputPlugin.fieldWriters;
|
26
|
+
import static org.embulk.output.td.TestTdOutputPlugin.plugin;
|
27
|
+
import static org.embulk.output.td.TestTdOutputPlugin.pluginTask;
|
28
|
+
import static org.embulk.output.td.TestTdOutputPlugin.schema;
|
29
|
+
import static org.embulk.output.td.TestTdOutputPlugin.recordWriter;
|
30
|
+
import static org.junit.Assert.assertEquals;
|
31
|
+
import static org.junit.Assert.assertTrue;
|
32
|
+
import static org.mockito.Matchers.any;
|
33
|
+
import static org.mockito.Matchers.anyString;
|
34
|
+
import static org.mockito.Mockito.doNothing;
|
35
|
+
import static org.mockito.Mockito.spy;
|
36
|
+
import static org.msgpack.type.ValueFactory.createRawValue;
|
37
|
+
|
38
|
+
public class TestRecordWriter
|
39
|
+
{
|
40
|
+
@Rule
|
41
|
+
public EmbulkTestRuntime runtime = new EmbulkTestRuntime();
|
42
|
+
|
43
|
+
private MessagePack msgpack;
|
44
|
+
private Logger log;
|
45
|
+
private Schema schema;
|
46
|
+
private TdOutputPlugin plugin; // mock
|
47
|
+
private PluginTask task;
|
48
|
+
private RecordWriter recordWriter; // mock
|
49
|
+
|
50
|
+
@Before
|
51
|
+
public void createResources()
|
52
|
+
{
|
53
|
+
msgpack = new MessagePack();
|
54
|
+
log = runtime.getExec().getLogger(TestRecordWriter.class);
|
55
|
+
|
56
|
+
schema = schema("time", Types.LONG, "_c0", Types.LONG, "_c1", Types.STRING,
|
57
|
+
"_c2", Types.BOOLEAN, "_c3", Types.DOUBLE, "_c4", Types.TIMESTAMP);
|
58
|
+
|
59
|
+
plugin = plugin();
|
60
|
+
task = pluginTask(config().set("session_name", "my_session"));
|
61
|
+
|
62
|
+
TdApiClient client = plugin.newTdApiClient(task);
|
63
|
+
FieldWriterSet fieldWriters = fieldWriters(log, task, schema);
|
64
|
+
recordWriter = recordWriter(task, client, fieldWriters);
|
65
|
+
}
|
66
|
+
|
67
|
+
@Test
|
68
|
+
public void checkOpenAndClose()
|
69
|
+
throws Exception
|
70
|
+
{
|
71
|
+
// confirm that no error happens
|
72
|
+
try {
|
73
|
+
recordWriter.open(schema);
|
74
|
+
}
|
75
|
+
finally {
|
76
|
+
recordWriter.close();
|
77
|
+
}
|
78
|
+
}
|
79
|
+
|
80
|
+
@Test
|
81
|
+
public void checkFlushAndFinish()
|
82
|
+
throws Exception
|
83
|
+
{
|
84
|
+
TdApiClient client = spy(plugin.newTdApiClient(task));
|
85
|
+
|
86
|
+
{ // add no record
|
87
|
+
RecordWriter recordWriter = recordWriter(task, client, fieldWriters(log, task, schema));
|
88
|
+
try {
|
89
|
+
recordWriter.open(schema);
|
90
|
+
}
|
91
|
+
finally {
|
92
|
+
recordWriter.finish();
|
93
|
+
}
|
94
|
+
}
|
95
|
+
|
96
|
+
{ // add 1 record
|
97
|
+
doNothing().when(client).uploadBulkImportPart(anyString(), anyString(), any(File.class));
|
98
|
+
|
99
|
+
RecordWriter recordWriter = recordWriter(task, client, fieldWriters(log, task, schema));
|
100
|
+
try {
|
101
|
+
recordWriter.open(schema);
|
102
|
+
|
103
|
+
// values are not null
|
104
|
+
for (Page page : PageTestUtils.buildPage(runtime.getBufferAllocator(), schema,
|
105
|
+
1442595600L, 0L, "v", true, 0.0, Timestamp.ofEpochSecond(1442595600L))) {
|
106
|
+
recordWriter.add(page);
|
107
|
+
}
|
108
|
+
}
|
109
|
+
finally {
|
110
|
+
recordWriter.finish();
|
111
|
+
}
|
112
|
+
}
|
113
|
+
}
|
114
|
+
|
115
|
+
@Test
|
116
|
+
public void addNonNullValues()
|
117
|
+
throws Exception
|
118
|
+
{
|
119
|
+
try {
|
120
|
+
recordWriter.open(schema);
|
121
|
+
|
122
|
+
// values are not null
|
123
|
+
for (Page page : PageTestUtils.buildPage(runtime.getBufferAllocator(), schema,
|
124
|
+
1442595600L, 0L, "v", true, 0.0, Timestamp.ofEpochSecond(1442595600L))) {
|
125
|
+
recordWriter.add(page);
|
126
|
+
}
|
127
|
+
|
128
|
+
MsgpackGZFileBuilder builder = recordWriter.getBuilder();
|
129
|
+
builder.finish();
|
130
|
+
|
131
|
+
// record count 1
|
132
|
+
assertEquals(1, builder.getRecordCount());
|
133
|
+
|
134
|
+
Unpacker u = msgpack.createUnpacker(new GZIPInputStream(new FileInputStream(builder.getFile())));
|
135
|
+
MapValue v = u.readValue().asMapValue();
|
136
|
+
|
137
|
+
// compare actual values
|
138
|
+
assertEquals(1442595600L, v.get(createRawValue("time")).asIntegerValue().getLong());
|
139
|
+
assertEquals(0L, v.get(createRawValue("_c0")).asIntegerValue().getLong());
|
140
|
+
assertEquals("v", v.get(createRawValue("_c1")).asRawValue().getString());
|
141
|
+
assertEquals(true, v.get(createRawValue("_c2")).asBooleanValue().getBoolean());
|
142
|
+
assertEquals(0.0, v.get(createRawValue("_c3")).asFloatValue().getDouble(), 0.000001);
|
143
|
+
assertEquals("2015-09-18 17:00:00.000", v.get(createRawValue("_c4")).asRawValue().getString());
|
144
|
+
|
145
|
+
}
|
146
|
+
finally {
|
147
|
+
recordWriter.close();
|
148
|
+
}
|
149
|
+
}
|
150
|
+
|
151
|
+
@Test
|
152
|
+
public void addNullValues()
|
153
|
+
throws Exception
|
154
|
+
{
|
155
|
+
try {
|
156
|
+
recordWriter.open(schema);
|
157
|
+
|
158
|
+
// values are not null
|
159
|
+
for (Page page : PageTestUtils.buildPage(runtime.getBufferAllocator(), schema,
|
160
|
+
1442595600L, null, null, null, null, null)) {
|
161
|
+
recordWriter.add(page);
|
162
|
+
}
|
163
|
+
|
164
|
+
MsgpackGZFileBuilder builder = recordWriter.getBuilder();
|
165
|
+
builder.finish();
|
166
|
+
|
167
|
+
// record count 1
|
168
|
+
assertEquals(1, builder.getRecordCount());
|
169
|
+
|
170
|
+
Unpacker u = msgpack.createUnpacker(new GZIPInputStream(new FileInputStream(builder.getFile())));
|
171
|
+
MapValue v = u.readValue().asMapValue();
|
172
|
+
|
173
|
+
// compare actual values
|
174
|
+
assertTrue(v.get(createRawValue("_c0")).isNilValue());
|
175
|
+
assertTrue(v.get(createRawValue("_c1")).isNilValue());
|
176
|
+
assertTrue(v.get(createRawValue("_c2")).isNilValue());
|
177
|
+
assertTrue(v.get(createRawValue("_c3")).isNilValue());
|
178
|
+
assertTrue(v.get(createRawValue("_c4")).isNilValue());
|
179
|
+
|
180
|
+
}
|
181
|
+
finally {
|
182
|
+
recordWriter.close();
|
183
|
+
}
|
184
|
+
}
|
185
|
+
|
186
|
+
@Test
|
187
|
+
public void doAbortNorthing()
|
188
|
+
{
|
189
|
+
recordWriter.abort();
|
190
|
+
// no error happen
|
191
|
+
}
|
192
|
+
|
193
|
+
@Test
|
194
|
+
public void checkCommitReport()
|
195
|
+
{
|
196
|
+
assertTrue(recordWriter.commit().isEmpty());
|
197
|
+
}
|
198
|
+
}
|