embulk-output-sqlserver 0.5.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/README.md +95 -0
- data/build.gradle +6 -0
- data/classpath/embulk-output-jdbc-0.5.0.jar +0 -0
- data/classpath/embulk-output-sqlserver-0.5.0.jar +0 -0
- data/lib/embulk/output/sqlserver.rb +3 -0
- data/src/main/java/org/embulk/output/SQLServerOutputPlugin.java +151 -0
- data/src/main/java/org/embulk/output/sqlserver/SQLServerOutputConnection.java +124 -0
- data/src/main/java/org/embulk/output/sqlserver/SQLServerOutputConnector.java +49 -0
- data/src/main/java/org/embulk/output/sqlserver/setter/SQLServerByteColumnSetter.java +46 -0
- data/src/main/java/org/embulk/output/sqlserver/setter/SQLServerColumnSetterFactory.java +50 -0
- data/src/main/java/org/embulk/output/sqlserver/setter/SQLServerSqlTimeColumnSetter.java +29 -0
- data/src/test/java/org/embulk/output/sqlserver/PreciseTime.java +48 -0
- data/src/test/java/org/embulk/output/sqlserver/SQLServerOutputPluginTest.java +510 -0
- data/src/test/resources/sqlserver/data/test1/test1.csv +3 -0
- data/src/test/resources/sqlserver/yml/test-insert-direct.yml +43 -0
- data/src/test/resources/sqlserver/yml/test-insert.yml +43 -0
- data/src/test/resources/sqlserver/yml/test-replace-long-name.yml +43 -0
- data/src/test/resources/sqlserver/yml/test-replace.yml +43 -0
- data/src/test/resources/sqlserver/yml/test-string-timestamp.yml +46 -0
- data/src/test/resources/sqlserver/yml/test-truncate-insert.yml +43 -0
- metadata +64 -0
@@ -0,0 +1,46 @@
|
|
1
|
+
package org.embulk.output.sqlserver.setter;
|
2
|
+
|
3
|
+
import java.io.IOException;
|
4
|
+
import java.sql.SQLException;
|
5
|
+
|
6
|
+
import org.embulk.output.jdbc.BatchInsert;
|
7
|
+
import org.embulk.output.jdbc.JdbcColumn;
|
8
|
+
import org.embulk.output.jdbc.setter.ByteColumnSetter;
|
9
|
+
import org.embulk.output.jdbc.setter.DefaultValueSetter;
|
10
|
+
|
11
|
+
public class SQLServerByteColumnSetter
|
12
|
+
extends ByteColumnSetter
|
13
|
+
{
|
14
|
+
private static final short MIN_VALUE = 0;
|
15
|
+
private static final short MAX_VALUE = 255;
|
16
|
+
|
17
|
+
public SQLServerByteColumnSetter(BatchInsert batch, JdbcColumn column,
|
18
|
+
DefaultValueSetter defaultValue)
|
19
|
+
{
|
20
|
+
super(batch, column, defaultValue);
|
21
|
+
}
|
22
|
+
|
23
|
+
@Override
|
24
|
+
public void longValue(long v) throws IOException, SQLException
|
25
|
+
{
|
26
|
+
// SQLServer TINYINT value is from 0 to 255
|
27
|
+
if (v > MAX_VALUE || v < MIN_VALUE) {
|
28
|
+
defaultValue.setByte();
|
29
|
+
} else {
|
30
|
+
batch.setShort((short) v);
|
31
|
+
}
|
32
|
+
}
|
33
|
+
|
34
|
+
@Override
|
35
|
+
public void stringValue(String v) throws IOException, SQLException
|
36
|
+
{
|
37
|
+
short sv;
|
38
|
+
try {
|
39
|
+
sv = Short.parseShort(v);
|
40
|
+
} catch (NumberFormatException e) {
|
41
|
+
defaultValue.setByte();
|
42
|
+
return;
|
43
|
+
}
|
44
|
+
longValue(sv);
|
45
|
+
}
|
46
|
+
}
|
@@ -0,0 +1,50 @@
|
|
1
|
+
package org.embulk.output.sqlserver.setter;
|
2
|
+
|
3
|
+
import java.sql.Types;
|
4
|
+
|
5
|
+
import org.embulk.output.jdbc.BatchInsert;
|
6
|
+
import org.embulk.output.jdbc.JdbcColumn;
|
7
|
+
import org.embulk.output.jdbc.JdbcColumnOption;
|
8
|
+
import org.embulk.output.jdbc.setter.ColumnSetter;
|
9
|
+
import org.embulk.output.jdbc.setter.ColumnSetterFactory;
|
10
|
+
import org.joda.time.DateTimeZone;
|
11
|
+
|
12
|
+
public class SQLServerColumnSetterFactory
|
13
|
+
extends ColumnSetterFactory
|
14
|
+
{
|
15
|
+
public SQLServerColumnSetterFactory(BatchInsert batch, DateTimeZone defaultTimeZone)
|
16
|
+
{
|
17
|
+
super(batch, defaultTimeZone);
|
18
|
+
}
|
19
|
+
|
20
|
+
@Override
|
21
|
+
public ColumnSetter newCoalesceColumnSetter(JdbcColumn column, JdbcColumnOption option)
|
22
|
+
{
|
23
|
+
switch (column.getSqlType()) {
|
24
|
+
case Types.TINYINT:
|
25
|
+
return new SQLServerByteColumnSetter(batch, column, newDefaultValueSetter(column, option));
|
26
|
+
|
27
|
+
case Types.TIME:
|
28
|
+
return new SQLServerSqlTimeColumnSetter(batch, column, newDefaultValueSetter(column, option), newCalendar(option));
|
29
|
+
|
30
|
+
default:
|
31
|
+
return super.newCoalesceColumnSetter(column, option);
|
32
|
+
}
|
33
|
+
}
|
34
|
+
|
35
|
+
@Override
|
36
|
+
public ColumnSetter newColumnSetter(JdbcColumn column, JdbcColumnOption option)
|
37
|
+
{
|
38
|
+
switch (option.getValueType()) {
|
39
|
+
case "byte":
|
40
|
+
return new SQLServerByteColumnSetter(batch, column, newDefaultValueSetter(column, option));
|
41
|
+
|
42
|
+
case "time":
|
43
|
+
return new SQLServerSqlTimeColumnSetter(batch, column, newDefaultValueSetter(column, option), newCalendar(option));
|
44
|
+
|
45
|
+
default:
|
46
|
+
return super.newColumnSetter(column, option);
|
47
|
+
}
|
48
|
+
}
|
49
|
+
|
50
|
+
}
|
@@ -0,0 +1,29 @@
|
|
1
|
+
package org.embulk.output.sqlserver.setter;
|
2
|
+
|
3
|
+
import java.io.IOException;
|
4
|
+
import java.sql.SQLException;
|
5
|
+
import java.util.Calendar;
|
6
|
+
|
7
|
+
import org.embulk.output.jdbc.BatchInsert;
|
8
|
+
import org.embulk.output.jdbc.JdbcColumn;
|
9
|
+
import org.embulk.output.jdbc.setter.DefaultValueSetter;
|
10
|
+
import org.embulk.output.jdbc.setter.SqlTimeColumnSetter;
|
11
|
+
import org.embulk.spi.time.Timestamp;
|
12
|
+
|
13
|
+
public class SQLServerSqlTimeColumnSetter
|
14
|
+
extends SqlTimeColumnSetter
|
15
|
+
{
|
16
|
+
public SQLServerSqlTimeColumnSetter(BatchInsert batch, JdbcColumn column,
|
17
|
+
DefaultValueSetter defaultValue,
|
18
|
+
Calendar calendar)
|
19
|
+
{
|
20
|
+
super(batch, column, defaultValue, calendar);
|
21
|
+
}
|
22
|
+
|
23
|
+
@Override
|
24
|
+
public void timestampValue(Timestamp v) throws IOException, SQLException
|
25
|
+
{
|
26
|
+
// fractional precision of SQLServer TIME is 7, but that of java.sql.Time is only 3.
|
27
|
+
batch.setSqlTimestamp(v, calendar);
|
28
|
+
}
|
29
|
+
}
|
@@ -0,0 +1,48 @@
|
|
1
|
+
package org.embulk.output.sqlserver;
|
2
|
+
|
3
|
+
import java.sql.Time;
|
4
|
+
import java.sql.Timestamp;
|
5
|
+
|
6
|
+
public class PreciseTime extends Time
|
7
|
+
{
|
8
|
+
private final int nanos;
|
9
|
+
|
10
|
+
public PreciseTime(long time, int nanos)
|
11
|
+
{
|
12
|
+
super(time);
|
13
|
+
|
14
|
+
this.nanos = nanos;
|
15
|
+
}
|
16
|
+
|
17
|
+
public PreciseTime(Time time, int nanos)
|
18
|
+
{
|
19
|
+
this(time.getTime(), nanos);
|
20
|
+
}
|
21
|
+
|
22
|
+
public PreciseTime(Timestamp timestamp)
|
23
|
+
{
|
24
|
+
this(timestamp.getTime(), timestamp.getNanos());
|
25
|
+
}
|
26
|
+
|
27
|
+
public int getNanos()
|
28
|
+
{
|
29
|
+
return nanos;
|
30
|
+
}
|
31
|
+
|
32
|
+
@Override
|
33
|
+
public boolean equals(Object o)
|
34
|
+
{
|
35
|
+
if (!(o instanceof PreciseTime)) {
|
36
|
+
return false;
|
37
|
+
}
|
38
|
+
|
39
|
+
return toString().equals(o.toString());
|
40
|
+
}
|
41
|
+
|
42
|
+
@Override
|
43
|
+
public String toString()
|
44
|
+
{
|
45
|
+
return String.format("%s.%09d", super.toString(), nanos);
|
46
|
+
}
|
47
|
+
|
48
|
+
}
|
@@ -0,0 +1,510 @@
|
|
1
|
+
package org.embulk.output.sqlserver;
|
2
|
+
|
3
|
+
import static org.junit.Assert.assertEquals;
|
4
|
+
|
5
|
+
import java.math.BigDecimal;
|
6
|
+
import java.sql.Connection;
|
7
|
+
import java.sql.DriverManager;
|
8
|
+
import java.sql.ResultSet;
|
9
|
+
import java.sql.SQLException;
|
10
|
+
import java.sql.Timestamp;
|
11
|
+
import java.text.DateFormat;
|
12
|
+
import java.text.ParseException;
|
13
|
+
import java.text.SimpleDateFormat;
|
14
|
+
import java.util.Date;
|
15
|
+
import java.util.Iterator;
|
16
|
+
import java.util.List;
|
17
|
+
|
18
|
+
import org.embulk.output.AbstractJdbcOutputPluginTest;
|
19
|
+
import org.embulk.output.SQLServerOutputPlugin;
|
20
|
+
import org.embulk.output.tester.EmbulkPluginTester;
|
21
|
+
import org.embulk.spi.OutputPlugin;
|
22
|
+
import org.junit.BeforeClass;
|
23
|
+
import org.junit.Test;
|
24
|
+
|
25
|
+
|
26
|
+
public class SQLServerOutputPluginTest extends AbstractJdbcOutputPluginTest
|
27
|
+
{
|
28
|
+
private static boolean canTest;
|
29
|
+
private static EmbulkPluginTester tester = new EmbulkPluginTester();
|
30
|
+
static {
|
31
|
+
tester.addPlugin(OutputPlugin.class, "sqlserver", SQLServerOutputPlugin.class);
|
32
|
+
}
|
33
|
+
|
34
|
+
@BeforeClass
|
35
|
+
public static void beforeClass()
|
36
|
+
{
|
37
|
+
try {
|
38
|
+
new SQLServerOutputPluginTest().connect();
|
39
|
+
canTest = true;
|
40
|
+
} catch (Throwable t) {
|
41
|
+
System.out.println(t);
|
42
|
+
} finally {
|
43
|
+
if (!canTest) {
|
44
|
+
System.out.println("Warning: you should put sqljdbc41.jar on classpath and prepare database.");
|
45
|
+
System.out.println("(server = localhost, port = 1433, instance = SQLEXPRESS, database = TESTDB, user = TEST_USER, password = TEST_PW)");
|
46
|
+
}
|
47
|
+
}
|
48
|
+
}
|
49
|
+
|
50
|
+
@Test
|
51
|
+
public void testInsertDirect() throws Exception
|
52
|
+
{
|
53
|
+
if (!canTest) {
|
54
|
+
return;
|
55
|
+
}
|
56
|
+
|
57
|
+
String table = "TEST1";
|
58
|
+
|
59
|
+
dropTable(table);
|
60
|
+
createTable(table);
|
61
|
+
insertRecord(table);
|
62
|
+
|
63
|
+
tester.run(convertYml("/sqlserver/yml/test-insert-direct.yml"));
|
64
|
+
|
65
|
+
assertTable(1, table);
|
66
|
+
}
|
67
|
+
|
68
|
+
@Test
|
69
|
+
public void testInsertDirectCreate() throws Exception
|
70
|
+
{
|
71
|
+
if (!canTest) {
|
72
|
+
return;
|
73
|
+
}
|
74
|
+
|
75
|
+
String table = "TEST1";
|
76
|
+
|
77
|
+
dropTable(table);
|
78
|
+
|
79
|
+
tester.run(convertYml("/sqlserver/yml/test-insert-direct.yml"));
|
80
|
+
|
81
|
+
assertGeneratedTable(table);
|
82
|
+
}
|
83
|
+
|
84
|
+
@Test
|
85
|
+
public void testInsert() throws Exception
|
86
|
+
{
|
87
|
+
if (!canTest) {
|
88
|
+
return;
|
89
|
+
}
|
90
|
+
|
91
|
+
String table = "TEST1";
|
92
|
+
|
93
|
+
dropTable(table);
|
94
|
+
createTable(table);
|
95
|
+
insertRecord(table);
|
96
|
+
|
97
|
+
tester.run(convertYml("/sqlserver/yml/test-insert.yml"));
|
98
|
+
|
99
|
+
assertTable(1, table);
|
100
|
+
}
|
101
|
+
|
102
|
+
@Test
|
103
|
+
public void testInsertCreate() throws Exception
|
104
|
+
{
|
105
|
+
if (!canTest) {
|
106
|
+
return;
|
107
|
+
}
|
108
|
+
|
109
|
+
String table = "TEST1";
|
110
|
+
|
111
|
+
dropTable(table);
|
112
|
+
|
113
|
+
tester.run(convertYml("/sqlserver/yml/test-insert.yml"));
|
114
|
+
|
115
|
+
assertGeneratedTable(table);
|
116
|
+
}
|
117
|
+
|
118
|
+
@Test
|
119
|
+
public void testTruncateInsert() throws Exception
|
120
|
+
{
|
121
|
+
if (!canTest) {
|
122
|
+
return;
|
123
|
+
}
|
124
|
+
|
125
|
+
String table = "TEST1";
|
126
|
+
|
127
|
+
dropTable(table);
|
128
|
+
createTable(table);
|
129
|
+
insertRecord(table);
|
130
|
+
|
131
|
+
tester.run(convertYml("/sqlserver/yml/test-truncate-insert.yml"));
|
132
|
+
|
133
|
+
assertTable(0, table);
|
134
|
+
}
|
135
|
+
|
136
|
+
@Test
|
137
|
+
public void testReplace() throws Exception
|
138
|
+
{
|
139
|
+
if (!canTest) {
|
140
|
+
return;
|
141
|
+
}
|
142
|
+
|
143
|
+
String table = "TEST1";
|
144
|
+
|
145
|
+
dropTable(table);
|
146
|
+
createTable(table);
|
147
|
+
insertRecord(table);
|
148
|
+
|
149
|
+
tester.run(convertYml("/sqlserver/yml/test-replace.yml"));
|
150
|
+
|
151
|
+
assertGeneratedTable(table);
|
152
|
+
}
|
153
|
+
|
154
|
+
@Test
|
155
|
+
public void testReplaceLongName() throws Exception
|
156
|
+
{
|
157
|
+
if (!canTest) {
|
158
|
+
return;
|
159
|
+
}
|
160
|
+
|
161
|
+
String table = "TEST___A123456789B123456789C123456789D123456789E123456789F123456789G123456789H123456789I123456789J123456789K123456789L123456789";
|
162
|
+
assertEquals(127, table.length());
|
163
|
+
|
164
|
+
dropTable(table);
|
165
|
+
createTable(table);
|
166
|
+
insertRecord(table);
|
167
|
+
|
168
|
+
tester.run(convertYml("/sqlserver/yml/test-replace-long-name.yml"));
|
169
|
+
|
170
|
+
assertGeneratedTable(table);
|
171
|
+
}
|
172
|
+
|
173
|
+
@Test
|
174
|
+
public void testReplaceCreate() throws Exception
|
175
|
+
{
|
176
|
+
if (!canTest) {
|
177
|
+
return;
|
178
|
+
}
|
179
|
+
|
180
|
+
String table = "TEST1";
|
181
|
+
|
182
|
+
dropTable(table);
|
183
|
+
|
184
|
+
tester.run(convertYml("/sqlserver/yml/test-replace.yml"));
|
185
|
+
|
186
|
+
assertGeneratedTable(table);
|
187
|
+
}
|
188
|
+
|
189
|
+
@Test
|
190
|
+
public void testStringToTimestamp() throws Exception
|
191
|
+
{
|
192
|
+
if (!canTest) {
|
193
|
+
return;
|
194
|
+
}
|
195
|
+
|
196
|
+
String table = "TEST1";
|
197
|
+
|
198
|
+
dropTable(table);
|
199
|
+
createTable(table);
|
200
|
+
insertRecord(table);
|
201
|
+
|
202
|
+
tester.run(convertYml("/sqlserver/yml/test-string-timestamp.yml"));
|
203
|
+
|
204
|
+
assertTable(1, table, true);
|
205
|
+
}
|
206
|
+
|
207
|
+
private void assertTable(int skip, String table) throws Exception
|
208
|
+
{
|
209
|
+
assertTable(skip, table, false);
|
210
|
+
}
|
211
|
+
|
212
|
+
private void assertTable(int skip, String table, boolean precise) throws Exception
|
213
|
+
{
|
214
|
+
List<List<Object>> rows = select(table);
|
215
|
+
assertEquals(skip + 3, rows.size());
|
216
|
+
rows = rows.subList(skip, skip + 3);
|
217
|
+
|
218
|
+
Iterator<List<Object>> i1 = rows.iterator();
|
219
|
+
{
|
220
|
+
Iterator<Object> i2 = i1.next().iterator();
|
221
|
+
assertEquals("A001", i2.next());
|
222
|
+
assertEquals(Short.valueOf((short)0), i2.next());
|
223
|
+
assertEquals(Short.valueOf((short)1234), i2.next());
|
224
|
+
assertEquals(Integer.valueOf(123456), i2.next());
|
225
|
+
assertEquals(Long.valueOf(12345678901L), i2.next());
|
226
|
+
assertEquals(Boolean.FALSE, i2.next());
|
227
|
+
assertEquals(new BigDecimal("1.23"), i2.next());
|
228
|
+
assertEquals(new BigDecimal("3.456"), i2.next());
|
229
|
+
assertEquals(new BigDecimal("12.3400"), i2.next());
|
230
|
+
assertEquals(new BigDecimal("123.4567"), i2.next());
|
231
|
+
assertEquals(Float.valueOf(0.1234567F), i2.next());
|
232
|
+
assertEquals(Double.valueOf(0.12345678901234D), i2.next());
|
233
|
+
assertEquals("a ", i2.next());
|
234
|
+
assertEquals("b", i2.next());
|
235
|
+
assertEquals("c", i2.next());
|
236
|
+
assertEquals("A ", i2.next());
|
237
|
+
assertEquals("B", i2.next());
|
238
|
+
assertEquals("C", i2.next());
|
239
|
+
assertEquals(createDate("2016/01/01"), i2.next());
|
240
|
+
assertEquals(createTimestamp("2017/01/01 01:02:03", 123000000), i2.next());
|
241
|
+
// Embulk timestamp doesn't support values under microseconds.
|
242
|
+
assertEquals(createTimestamp("2018/01/01 01:02:03", precise? 123456700 : 123456000), i2.next());
|
243
|
+
assertEquals(createTimestamp("2019/01/01 01:02:03", 120000000), i2.next());
|
244
|
+
assertEquals(createTimestamp("2020/01/01 01:02:00", 0), i2.next());
|
245
|
+
// Embulk timestamp doesn't support values under microseconds.
|
246
|
+
assertEquals(createTime("03:04:05", precise? 123456700 : 123456000), i2.next());
|
247
|
+
assertEquals(createTime("06:07:08", 120000000), i2.next());
|
248
|
+
}
|
249
|
+
{
|
250
|
+
Iterator<Object> i2 = i1.next().iterator();
|
251
|
+
assertEquals("A002", i2.next());
|
252
|
+
assertEquals(Short.valueOf((short)255), i2.next());
|
253
|
+
assertEquals(Short.valueOf((short)-32768), i2.next());
|
254
|
+
assertEquals(Integer.valueOf(-2147483648), i2.next());
|
255
|
+
assertEquals(Long.valueOf(-9223372036854775808L), i2.next());
|
256
|
+
assertEquals(Boolean.TRUE, i2.next());
|
257
|
+
assertEquals(new BigDecimal("-9999999999.99"), i2.next());
|
258
|
+
assertEquals(new BigDecimal("-99.999"), i2.next());
|
259
|
+
assertEquals(new BigDecimal("-214748.3648"), i2.next());
|
260
|
+
assertEquals(new BigDecimal("-922337203685477.5808"), i2.next());
|
261
|
+
assertEquals(Float.valueOf(-9999000000F), i2.next());
|
262
|
+
assertEquals(Double.valueOf(-999999999999000000D), i2.next());
|
263
|
+
assertEquals("あい", i2.next());
|
264
|
+
assertEquals("あいうえ", i2.next());
|
265
|
+
assertEquals("あいうえお", i2.next());
|
266
|
+
assertEquals("かき ", i2.next());
|
267
|
+
assertEquals("かきくけ", i2.next());
|
268
|
+
assertEquals("かきくけこ", i2.next());
|
269
|
+
assertEquals(createDate("2016/12/31"), i2.next());
|
270
|
+
assertEquals(createTimestamp("2017/12/31 23:59:59", 997000000), i2.next());
|
271
|
+
// Embulk timestamp doesn't support values under microseconds.
|
272
|
+
assertEquals(createTimestamp("2018/12/31 23:59:59", precise? 999999900 : 999999000), i2.next());
|
273
|
+
assertEquals(createTimestamp("2019/12/31 23:59:59", 990000000), i2.next());
|
274
|
+
assertEquals(createTimestamp("2021/01/01 00:00:00", 0), i2.next());
|
275
|
+
// Embulk timestamp doesn't support values under microseconds.
|
276
|
+
assertEquals(createTime("23:59:59", precise? 999999900 : 999999000), i2.next());
|
277
|
+
assertEquals(createTime("23:59:59", 990000000), i2.next());
|
278
|
+
}
|
279
|
+
{
|
280
|
+
Iterator<Object> i2 = i1.next().iterator();
|
281
|
+
assertEquals("A003", i2.next());
|
282
|
+
assertEquals(null, i2.next());
|
283
|
+
assertEquals(null, i2.next());
|
284
|
+
assertEquals(null, i2.next());
|
285
|
+
assertEquals(null, i2.next());
|
286
|
+
assertEquals(null, i2.next());
|
287
|
+
assertEquals(null, i2.next());
|
288
|
+
assertEquals(null, i2.next());
|
289
|
+
assertEquals(null, i2.next());
|
290
|
+
assertEquals(null, i2.next());
|
291
|
+
assertEquals(null, i2.next());
|
292
|
+
assertEquals(null, i2.next());
|
293
|
+
assertEquals(null, i2.next());
|
294
|
+
assertEquals(null, i2.next());
|
295
|
+
assertEquals(null, i2.next());
|
296
|
+
assertEquals(null, i2.next());
|
297
|
+
assertEquals(null, i2.next());
|
298
|
+
assertEquals(null, i2.next());
|
299
|
+
assertEquals(null, i2.next());
|
300
|
+
assertEquals(null, i2.next());
|
301
|
+
assertEquals(null, i2.next());
|
302
|
+
assertEquals(null, i2.next());
|
303
|
+
assertEquals(null, i2.next());
|
304
|
+
assertEquals(null, i2.next());
|
305
|
+
}
|
306
|
+
}
|
307
|
+
|
308
|
+
private void assertGeneratedTable(String table) throws Exception
|
309
|
+
{
|
310
|
+
List<List<Object>> rows = select(table);
|
311
|
+
assertEquals(3, rows.size());
|
312
|
+
|
313
|
+
Iterator<List<Object>> i1 = rows.iterator();
|
314
|
+
{
|
315
|
+
Iterator<Object> i2 = i1.next().iterator();
|
316
|
+
assertEquals("A001", i2.next());
|
317
|
+
assertEquals(Long.valueOf(0), i2.next());
|
318
|
+
assertEquals(Long.valueOf(1234), i2.next());
|
319
|
+
assertEquals(Long.valueOf(123456), i2.next());
|
320
|
+
assertEquals(Long.valueOf(12345678901L), i2.next());
|
321
|
+
assertEquals(Boolean.FALSE, i2.next());
|
322
|
+
assertEquals("1.23", i2.next());
|
323
|
+
assertEquals("3.456", i2.next());
|
324
|
+
assertEquals("12.34", i2.next());
|
325
|
+
assertEquals("123.4567", i2.next());
|
326
|
+
assertEquals(Double.valueOf(0.1234567D), i2.next());
|
327
|
+
assertEquals(Double.valueOf(0.12345678901234D), i2.next());
|
328
|
+
assertEquals("a", i2.next());
|
329
|
+
assertEquals("b", i2.next());
|
330
|
+
assertEquals("c", i2.next());
|
331
|
+
assertEquals("A", i2.next());
|
332
|
+
assertEquals("B", i2.next());
|
333
|
+
assertEquals("C", i2.next());
|
334
|
+
assertEquals(createTimestamp("2016/01/01 00:00:00", 0), i2.next());
|
335
|
+
assertEquals(createTimestamp("2017/01/01 01:02:03", 123000000), i2.next());
|
336
|
+
// Embulk timestamp doesn't support values under microseconds.
|
337
|
+
//assertEquals(createTimestamp("2018/01/01 01:02:03", 123456700), i2.next());
|
338
|
+
assertEquals(createTimestamp("2018/01/01 01:02:03", 123456000), i2.next());
|
339
|
+
assertEquals(createTimestamp("2019/01/01 01:02:03", 120000000), i2.next());
|
340
|
+
assertEquals(createTimestamp("2020/01/01 01:02:03", 0), i2.next());
|
341
|
+
// Embulk timestamp doesn't support values under microseconds.
|
342
|
+
//assertEquals(createTime("03:04:05", 123456700), new PreciseTime((Timestamp)i2.next()));
|
343
|
+
assertEquals(createTime("03:04:05", 123456000), new PreciseTime((Timestamp)i2.next()));
|
344
|
+
assertEquals(createTime("06:07:08", 120000000), new PreciseTime((Timestamp)i2.next()));
|
345
|
+
}
|
346
|
+
{
|
347
|
+
Iterator<Object> i2 = i1.next().iterator();
|
348
|
+
assertEquals("A002", i2.next());
|
349
|
+
assertEquals(Long.valueOf((short)255), i2.next());
|
350
|
+
assertEquals(Long.valueOf((short)-32768), i2.next());
|
351
|
+
assertEquals(Long.valueOf(-2147483648), i2.next());
|
352
|
+
assertEquals(Long.valueOf(-9223372036854775808L), i2.next());
|
353
|
+
assertEquals(Boolean.TRUE, i2.next());
|
354
|
+
assertEquals("-9999999999.99", i2.next());
|
355
|
+
assertEquals("-99.999", i2.next());
|
356
|
+
assertEquals("-214748.3648", i2.next());
|
357
|
+
assertEquals("-922337203685477.5808", i2.next());
|
358
|
+
assertEquals(Double.valueOf(-9999000000D), i2.next());
|
359
|
+
assertEquals(Double.valueOf(-999999999999000000D), i2.next());
|
360
|
+
assertEquals("あい", i2.next());
|
361
|
+
assertEquals("あいうえ", i2.next());
|
362
|
+
assertEquals("あいうえお", i2.next());
|
363
|
+
assertEquals("かき", i2.next());
|
364
|
+
assertEquals("かきくけ", i2.next());
|
365
|
+
assertEquals("かきくけこ", i2.next());
|
366
|
+
assertEquals(createTimestamp("2016/12/31 00:00:00", 0), i2.next());
|
367
|
+
assertEquals(createTimestamp("2017/12/31 23:59:59", 997000000), i2.next());
|
368
|
+
// Embulk timestamp doesn't support values under microseconds.
|
369
|
+
//assertEquals(createTimestamp("2018/12/31 23:59:59", 999999900), i2.next());
|
370
|
+
assertEquals(createTimestamp("2018/12/31 23:59:59", 999999000), i2.next());
|
371
|
+
assertEquals(createTimestamp("2019/12/31 23:59:59", 990000000), i2.next());
|
372
|
+
assertEquals(createTimestamp("2020/12/31 23:59:59", 0), i2.next());
|
373
|
+
// Embulk timestamp doesn't support values under microseconds.
|
374
|
+
//assertEquals(createTime("23:59:59", 999999900), new PreciseTime((Timestamp)i2.next()));
|
375
|
+
assertEquals(createTime("23:59:59", 999999000), new PreciseTime((Timestamp)i2.next()));
|
376
|
+
assertEquals(createTime("23:59:59", 990000000), new PreciseTime((Timestamp)i2.next()));
|
377
|
+
}
|
378
|
+
{
|
379
|
+
Iterator<Object> i2 = i1.next().iterator();
|
380
|
+
assertEquals("A003", i2.next());
|
381
|
+
assertEquals(null, i2.next());
|
382
|
+
assertEquals(null, i2.next());
|
383
|
+
assertEquals(null, i2.next());
|
384
|
+
assertEquals(null, i2.next());
|
385
|
+
assertEquals(null, i2.next());
|
386
|
+
assertEquals(null, i2.next());
|
387
|
+
assertEquals(null, i2.next());
|
388
|
+
assertEquals(null, i2.next());
|
389
|
+
assertEquals(null, i2.next());
|
390
|
+
assertEquals(null, i2.next());
|
391
|
+
assertEquals(null, i2.next());
|
392
|
+
assertEquals(null, i2.next());
|
393
|
+
assertEquals(null, i2.next());
|
394
|
+
assertEquals(null, i2.next());
|
395
|
+
assertEquals(null, i2.next());
|
396
|
+
assertEquals(null, i2.next());
|
397
|
+
assertEquals(null, i2.next());
|
398
|
+
assertEquals(null, i2.next());
|
399
|
+
assertEquals(null, i2.next());
|
400
|
+
assertEquals(null, i2.next());
|
401
|
+
assertEquals(null, i2.next());
|
402
|
+
assertEquals(null, i2.next());
|
403
|
+
assertEquals(null, i2.next());
|
404
|
+
assertEquals(null, i2.next());
|
405
|
+
}
|
406
|
+
}
|
407
|
+
|
408
|
+
@Override
|
409
|
+
protected Object getValue(ResultSet resultSet, int index) throws SQLException {
|
410
|
+
if (resultSet.getMetaData().getColumnTypeName(index).equals("time")) {
|
411
|
+
Timestamp timestamp = resultSet.getTimestamp(index);
|
412
|
+
if (timestamp == null) {
|
413
|
+
return null;
|
414
|
+
}
|
415
|
+
return new PreciseTime(timestamp);
|
416
|
+
}
|
417
|
+
return super.getValue(resultSet, index);
|
418
|
+
}
|
419
|
+
|
420
|
+
private java.sql.Date createDate(String s) throws ParseException
|
421
|
+
{
|
422
|
+
DateFormat format = new SimpleDateFormat("yyyy/MM/dd");
|
423
|
+
Date date = format.parse(s);
|
424
|
+
return new java.sql.Date(date.getTime());
|
425
|
+
}
|
426
|
+
|
427
|
+
private Timestamp createTimestamp(String s, int nanos) throws ParseException
|
428
|
+
{
|
429
|
+
DateFormat format = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
|
430
|
+
Date date = format.parse(s);
|
431
|
+
Timestamp timestamp = new Timestamp(date.getTime());
|
432
|
+
timestamp.setNanos(nanos);
|
433
|
+
return timestamp;
|
434
|
+
}
|
435
|
+
|
436
|
+
private PreciseTime createTime(String s, int nanos) throws ParseException
|
437
|
+
{
|
438
|
+
DateFormat format = new SimpleDateFormat("HH:mm:ss");
|
439
|
+
Date date = format.parse(s);
|
440
|
+
return new PreciseTime(date.getTime(), nanos);
|
441
|
+
}
|
442
|
+
|
443
|
+
private void createTable(String table) throws SQLException
|
444
|
+
{
|
445
|
+
String sql = String.format("CREATE TABLE %s ("
|
446
|
+
+ "ID CHAR(4),"
|
447
|
+
+ "TINYINT_ITEM TINYINT,"
|
448
|
+
+ "SMALLINT_ITEM SMALLINT,"
|
449
|
+
+ "INT_ITEM INT,"
|
450
|
+
+ "BIGINT_ITEM BIGINT,"
|
451
|
+
+ "BIT_ITEM BIT,"
|
452
|
+
+ "DECIMAL_ITEM DECIMAL(12,2),"
|
453
|
+
+ "NUMERIC_ITEM NUMERIC(5,3),"
|
454
|
+
+ "SMALLMONEY_ITEM SMALLMONEY,"
|
455
|
+
+ "MONEY_ITEM MONEY,"
|
456
|
+
+ "REAL_ITEM REAL,"
|
457
|
+
+ "FLOAT_ITEM FLOAT,"
|
458
|
+
+ "CHAR_ITEM CHAR(4),"
|
459
|
+
+ "VARCHAR_ITEM VARCHAR(8),"
|
460
|
+
+ "TEXT_ITEM TEXT,"
|
461
|
+
+ "NCHAR_ITEM NCHAR(4),"
|
462
|
+
+ "NVARCHAR_ITEM NVARCHAR(8),"
|
463
|
+
+ "NTEXT_ITEM NTEXT,"
|
464
|
+
+ "DATE_ITEM DATE,"
|
465
|
+
+ "DATETIME_ITEM DATETIME,"
|
466
|
+
+ "DATETIME2_ITEM DATETIME2,"
|
467
|
+
+ "DATETIME2_2_ITEM DATETIME2(2),"
|
468
|
+
+ "SMALLDATETIME_ITEM SMALLDATETIME,"
|
469
|
+
+ "TIME_ITEM TIME,"
|
470
|
+
+ "TIME_2_ITEM TIME(2),"
|
471
|
+
+ "PRIMARY KEY (ID))", table);
|
472
|
+
executeSQL(sql);
|
473
|
+
}
|
474
|
+
|
475
|
+
private void insertRecord(String table) throws SQLException
|
476
|
+
{
|
477
|
+
executeSQL(String.format("INSERT INTO %s VALUES('9999',"
|
478
|
+
+ "NULL,"
|
479
|
+
+ "NULL,"
|
480
|
+
+ "NULL,"
|
481
|
+
+ "NULL,"
|
482
|
+
+ "NULL,"
|
483
|
+
+ "NULL,"
|
484
|
+
+ "NULL,"
|
485
|
+
+ "NULL,"
|
486
|
+
+ "NULL,"
|
487
|
+
+ "NULL,"
|
488
|
+
+ "NULL,"
|
489
|
+
+ "NULL,"
|
490
|
+
+ "NULL,"
|
491
|
+
+ "NULL,"
|
492
|
+
+ "NULL,"
|
493
|
+
+ "NULL,"
|
494
|
+
+ "NULL,"
|
495
|
+
+ "NULL,"
|
496
|
+
+ "NULL,"
|
497
|
+
+ "NULL,"
|
498
|
+
+ "NULL,"
|
499
|
+
+ "NULL,"
|
500
|
+
+ "NULL,"
|
501
|
+
+ "NULL)", table));
|
502
|
+
}
|
503
|
+
|
504
|
+
@Override
|
505
|
+
protected Connection connect() throws SQLException
|
506
|
+
{
|
507
|
+
return DriverManager.getConnection("jdbc:sqlserver://localhost\\SQLEXPRESS:1433;databasename=TESTDB", "TEST_USER", "test_pw");
|
508
|
+
}
|
509
|
+
|
510
|
+
}
|