embulk-output-td 0.1.4 → 0.1.5
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 +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
|
+
}
|