embulk-input-sqlserver 0.10.0 → 0.10.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (51) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +6 -4
  3. data/build.gradle +1 -0
  4. data/classpath/{embulk-input-jdbc-0.10.0.jar → embulk-input-jdbc-0.10.1.jar} +0 -0
  5. data/classpath/embulk-input-sqlserver-0.10.1.jar +0 -0
  6. data/classpath/mssql-jdbc-7.2.2.jre8.jar +0 -0
  7. data/src/main/java/org/embulk/input/SQLServerInputPlugin.java +36 -26
  8. data/src/main/java/org/embulk/input/sqlserver/getter/SQLServerColumnGetterFactory.java +15 -5
  9. data/src/test/java/org/embulk/input/sqlserver/BasicTest.java +9 -0
  10. data/src/test/java/org/embulk/input/sqlserver/IncrementalTest.java +149 -0
  11. data/src/test/resources/org/embulk/input/sqlserver/test/expect/basic/jtds_config.yml +3 -0
  12. data/src/test/resources/org/embulk/input/sqlserver/test/expect/incremental/char/config_1.yml +3 -0
  13. data/src/test/resources/org/embulk/input/sqlserver/test/expect/incremental/char/config_2.yml +4 -0
  14. data/src/test/resources/org/embulk/input/sqlserver/test/expect/incremental/char/expected_1.csv +4 -0
  15. data/src/test/resources/org/embulk/input/sqlserver/test/expect/incremental/char/expected_1.diff +3 -0
  16. data/src/test/resources/org/embulk/input/sqlserver/test/expect/incremental/char/expected_2.csv +2 -0
  17. data/src/test/resources/org/embulk/input/sqlserver/test/expect/incremental/char/expected_2.diff +3 -0
  18. data/src/test/resources/org/embulk/input/sqlserver/test/expect/incremental/char/insert_more.sql +6 -0
  19. data/src/test/resources/org/embulk/input/sqlserver/test/expect/incremental/char/setup.sql +11 -0
  20. data/src/test/resources/org/embulk/input/sqlserver/test/expect/incremental/datetime2/config_1.yml +4 -0
  21. data/src/test/resources/org/embulk/input/sqlserver/test/expect/incremental/datetime2/config_2.yml +4 -0
  22. data/src/test/resources/org/embulk/input/sqlserver/test/expect/incremental/datetime2/expected_1.csv +7 -0
  23. data/src/test/resources/org/embulk/input/sqlserver/test/expect/incremental/datetime2/expected_1.diff +3 -0
  24. data/src/test/resources/org/embulk/input/sqlserver/test/expect/incremental/datetime2/expected_2.csv +3 -0
  25. data/src/test/resources/org/embulk/input/sqlserver/test/expect/incremental/datetime2/expected_2.diff +3 -0
  26. data/src/test/resources/org/embulk/input/sqlserver/test/expect/incremental/datetime2/insert_more.sql +8 -0
  27. data/src/test/resources/org/embulk/input/sqlserver/test/expect/incremental/datetime2/setup.sql +14 -0
  28. data/src/test/resources/org/embulk/input/sqlserver/test/expect/incremental/int/config_1.yml +3 -0
  29. data/src/test/resources/org/embulk/input/sqlserver/test/expect/incremental/int/config_2.yml +4 -0
  30. data/src/test/resources/org/embulk/input/sqlserver/test/expect/incremental/int/expected_1.csv +4 -0
  31. data/src/test/resources/org/embulk/input/sqlserver/test/expect/incremental/int/expected_1.diff +3 -0
  32. data/src/test/resources/org/embulk/input/sqlserver/test/expect/incremental/int/expected_2.csv +2 -0
  33. data/src/test/resources/org/embulk/input/sqlserver/test/expect/incremental/int/expected_2.diff +3 -0
  34. data/src/test/resources/org/embulk/input/sqlserver/test/expect/incremental/int/insert_more.sql +6 -0
  35. data/src/test/resources/org/embulk/input/sqlserver/test/expect/incremental/int/setup.sql +11 -0
  36. data/src/test/resources/org/embulk/input/sqlserver/test/expect/incremental/query/config_1.yml +14 -0
  37. data/src/test/resources/org/embulk/input/sqlserver/test/expect/incremental/query/config_2.yml +14 -0
  38. data/src/test/resources/org/embulk/input/sqlserver/test/expect/incremental/query/expected_1.csv +4 -0
  39. data/src/test/resources/org/embulk/input/sqlserver/test/expect/incremental/query/expected_1.diff +3 -0
  40. data/src/test/resources/org/embulk/input/sqlserver/test/expect/incremental/query/expected_2.csv +2 -0
  41. data/src/test/resources/org/embulk/input/sqlserver/test/expect/incremental/query/expected_2.diff +3 -0
  42. data/src/test/resources/org/embulk/input/sqlserver/test/expect/incremental/query/insert_more.sql +5 -0
  43. data/src/test/resources/org/embulk/input/sqlserver/test/expect/incremental/query/multi_columns_config_1.yml +16 -0
  44. data/src/test/resources/org/embulk/input/sqlserver/test/expect/incremental/query/multi_columns_config_2.yml +17 -0
  45. data/src/test/resources/org/embulk/input/sqlserver/test/expect/incremental/query/multi_columns_expected_1.csv +4 -0
  46. data/src/test/resources/org/embulk/input/sqlserver/test/expect/incremental/query/multi_columns_expected_1.diff +3 -0
  47. data/src/test/resources/org/embulk/input/sqlserver/test/expect/incremental/query/multi_columns_expected_2.csv +2 -0
  48. data/src/test/resources/org/embulk/input/sqlserver/test/expect/incremental/query/multi_columns_expected_2.diff +3 -0
  49. data/src/test/resources/org/embulk/input/sqlserver/test/expect/incremental/query/setup.sql +11 -0
  50. metadata +45 -4
  51. data/classpath/embulk-input-sqlserver-0.10.0.jar +0 -0
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 22b1735cc828641cff2cbdaf378cff0ba09258dd9b56029c9c10cf3ed49369b9
4
- data.tar.gz: 1a29fa810ebf240722d13e668cf1ad7bec43e146a4086d200dbbd04c2004e6ae
3
+ metadata.gz: 04e9c70944217bbd26e88379fd303c5671420aa56a6dd514c690f0edd948ee14
4
+ data.tar.gz: d718ebd86e88a4d45d4982c744738aacb6296cfef8e3da45f42ef60261e42085
5
5
  SHA512:
6
- metadata.gz: 9a1c12af23925060435e6dee86251b6c7a475844186e91a8274f9d9da4a641bf069a272c3688fed040b9ebd73068e4f11e8b735eac442a5d365c2e736723ba11
7
- data.tar.gz: 7750ffb7e28628d6fccf80661cc29c158b734a65211ac4bbe3b0585495f7c7cdc93ea5f23fa7dae602c1b674fc24644c4e0ebbc422e2747f05b1e52324623529
6
+ metadata.gz: dfc3d01c225d6b3a8658d0d7622883e5d0b417b5f44f681a442441808c247f253cd200795354aab7e3a02c984acbd12351ecb072947b64e4864411c360a80280
7
+ data.tar.gz: 5fdce20cab127d48be9fbb005ff913dc177d804aaf15632c2a0a14dd33df634962aa6a4163d274ba09e2da21f397761ba5aa619647f53453d35e733579a850e3
data/README.md CHANGED
@@ -9,7 +9,8 @@ SQL Server input plugin for Embulk loads records from SQL Server.
9
9
 
10
10
  ## Configuration
11
11
 
12
- - **driver_path**: path to the jar file of Microsoft SQL Server JDBC driver. If not set, open-source driver (jTDS driver) is used (string)
12
+ - **driver_path**: path to the jar file of Microsoft SQL Server JDBC driver. If not set, the bundled JDBC driver (Microsoft SQL Server JDBC driver 7.2.2) will be used. (string)
13
+ - **driver_type**: the current version of embulk-input-sqlserver will use Microsoft SQL Server JDBC driver in default, but version 0.10.0 or older will use jTDS driver in default. You can still use jTDS driver by setting this option to "jtds". (string, default: "mssql-jdbc")
13
14
  - **host**: database host name (string, required if url is not set)
14
15
  - **port**: database port number (integer, default: 1433)
15
16
  - **integratedSecutiry**: whether to use integrated authentication or not. The `sqljdbc_auth.dll` must be located on Java library path if using integrated authentication. : (boolean, default: false)
@@ -38,13 +39,14 @@ embulk "-J-Djava.library.path=C:\drivers" run input-sqlserver.yml
38
39
  - **socket_timeout**: timeout for executing the query. 0 means no timeout. (integer (seconds), default: 1800)
39
40
  - **options**: extra JDBC properties (hash, default: {})
40
41
  - **incremental**: if true, enables incremental loading. See next section for details (boolean, default: false)
41
- - **incremental_columns**: column names for incremental loading (array of strings, default: use primary keys)
42
+ - **incremental_columns**: column names for incremental loading (array of strings, default: use primary keys). Columns of integer types, string types and `datetime2` are supported.
42
43
  - **last_record**: values of the last record for incremental loading (array of objects, default: load all records)
43
44
  - **default_timezone**: If the sql type of a column is `date`/`time`/`datetime` and the embulk type is `string`, column values are formatted int this default_timezone. You can overwrite timezone for each columns using column_options option. (string, default: `UTC`)
44
45
  - **default_column_options**: advanced: column_options for each JDBC type as default. key-value pairs where key is a JDBC type (e.g. 'DATE', 'BIGINT') and value is same as column_options's value.
45
46
  - **column_options**: advanced: key-value pairs where key is a column name and value is options for the column.
46
47
  - **value_type**: embulk get values from database as this value_type. Typically, the value_type determines `getXXX` method of `java.sql.PreparedStatement`.
47
48
  (string, default: depends on the sql type of the column. Available values options are: `long`, `double`, `float`, `decimal`, `boolean`, `string`, `json`, `date`, `time`, `timestamp`)
49
+ NOTE: the default value_type for DATE, TIME and DATETIME2 is `string`, because jTDS driver, default JDBC driver for older embulk-input-sqlserver, returns Types.VARCHAR as JDBC type for these types.
48
50
  - **type**: Column values are converted to this embulk type.
49
51
  Available values options are: `boolean`, `long`, `double`, `string`, `json`, `timestamp`).
50
52
  By default, the embulk type is determined according to the sql type of the column (or value_type if specified).
@@ -71,13 +73,13 @@ ORDER BY updated_at, id
71
73
 
72
74
  When bulk data loading finishes successfully, it outputs `last_record: ` paramater as config-diff so that next execution uses it.
73
75
 
74
- At the next execution, when `last_record: ` is also set, this plugin generates additional WHERE conditions to load records larger than the last record. For example, if `last_record: ["2017-01-01 00:32:12", 5291]` is set,
76
+ At the next execution, when `last_record: ` is also set, this plugin generates additional WHERE conditions to load records larger than the last record. For example, if `last_record: ["2017-01-01 00:32:12.4876590", 5291]` is set,
75
77
 
76
78
  ```
77
79
  SELECT * FROM (
78
80
  ...original query is here...
79
81
  )
80
- WHERE updated_at > '2017-01-01 00:32:12' OR (updated_at = '2017-01-01 00:32:12' AND id > 5291)
82
+ WHERE updated_at > '2017-01-01 00:32:12.4876590' OR (updated_at = '2017-01-01 00:32:12.4876590' AND id > 5291)
81
83
  ORDER BY updated_at, id
82
84
  ```
83
85
 
@@ -1,5 +1,6 @@
1
1
  dependencies {
2
2
  compile project(':embulk-input-jdbc')
3
+ compile 'com.microsoft.sqlserver:mssql-jdbc:7.2.2.jre8'
3
4
  compile 'net.sourceforge.jtds:jtds:1.3.1'
4
5
 
5
6
  testCompile 'org.embulk:embulk-standards:0.9.12'
@@ -33,6 +33,10 @@ public class SQLServerInputPlugin
33
33
  @ConfigDefault("null")
34
34
  public Optional<String> getDriverPath();
35
35
 
36
+ @Config("driver_type")
37
+ @ConfigDefault("\"mssql-jdbc\"")
38
+ public String getDriverType();
39
+
36
40
  @Config("host")
37
41
  @ConfigDefault("null")
38
42
  public Optional<String> getHost();
@@ -113,26 +117,29 @@ public class SQLServerInputPlugin
113
117
  SQLServerPluginTask sqlServerTask = (SQLServerPluginTask) task;
114
118
 
115
119
  Driver driver;
116
- boolean useJtdsDriver = false;
117
120
  if (sqlServerTask.getDriverPath().isPresent()) {
118
121
  addDriverJarToClasspath(sqlServerTask.getDriverPath().get());
122
+ }
123
+
124
+ boolean useJtdsDriver;
125
+ if (sqlServerTask.getDriverType().equalsIgnoreCase("mssql-jdbc")) {
126
+ useJtdsDriver = false;
119
127
  try {
120
128
  driver = (Driver) Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver").newInstance();
121
129
  }
122
130
  catch (Exception e) {
123
- throw new ConfigException("Driver set at field 'driver_path' doesn't include Microsoft SQLServerDriver", e);
131
+ throw new ConfigException("Can't load Microsoft SQLServerDriver from classpath", e);
124
132
  }
125
- }
126
- else {
127
- // prefer Microsoft SQLServerDriver if it is in classpath
133
+ } else if (sqlServerTask.getDriverType().equalsIgnoreCase("jtds")) {
134
+ useJtdsDriver = true;
128
135
  try {
129
- driver = (Driver) Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver").newInstance();
136
+ driver = (Driver) Class.forName("net.sourceforge.jtds.jdbc.Driver").newInstance();
130
137
  }
131
- catch (Exception ex) {
132
- logger.info("Using jTDS Driver");
133
- driver = new net.sourceforge.jtds.jdbc.Driver();
134
- useJtdsDriver = true;
138
+ catch (Exception e) {
139
+ throw new ConfigException("Can't load jTDS Driver from classpath", e);
135
140
  }
141
+ } else {
142
+ throw new ConfigException("Unknown driver_type : " + sqlServerTask.getDriverType());
136
143
  }
137
144
 
138
145
  UrlAndProperties urlAndProps = buildUrlAndProperties(sqlServerTask, useJtdsDriver);
@@ -141,18 +148,21 @@ public class SQLServerInputPlugin
141
148
  props.putAll(sqlServerTask.getOptions());
142
149
  logConnectionProperties(urlAndProps.getUrl(), props);
143
150
 
144
- Connection con = driver.connect(urlAndProps.getUrl(), props);
145
- try {
146
- SQLServerInputConnection c = new SQLServerInputConnection(con, sqlServerTask.getSchema().orNull(),
147
- sqlServerTask.getTransactionIsolationLevel().orNull());
148
- con = null;
149
- return c;
150
- }
151
- finally {
152
- if (con != null) {
153
- con.close();
151
+ if (driver != null) {
152
+ Connection con = driver.connect(urlAndProps.getUrl(), props);
153
+ try {
154
+ SQLServerInputConnection c = new SQLServerInputConnection(con, sqlServerTask.getSchema().orNull(),
155
+ sqlServerTask.getTransactionIsolationLevel().orNull());
156
+ con = null;
157
+ return c;
158
+ }
159
+ finally {
160
+ if (con != null) {
161
+ con.close();
162
+ }
154
163
  }
155
164
  }
165
+ throw new ConfigException("Fail to create new connection");
156
166
  }
157
167
 
158
168
  @Override
@@ -166,7 +176,6 @@ public class SQLServerInputPlugin
166
176
  Properties props = new Properties();
167
177
 
168
178
  // common properties
169
-
170
179
  if (sqlServerTask.getUser().isPresent()) {
171
180
  props.setProperty("user", sqlServerTask.getUser().get());
172
181
  }
@@ -185,6 +194,7 @@ public class SQLServerInputPlugin
185
194
  else {
186
195
  // SQLServerDriver properties
187
196
  props.setProperty("loginTimeout", String.valueOf(sqlServerTask.getConnectTimeout())); // seconds
197
+ props.setProperty("socketTimeout", String.valueOf(sqlServerTask.getSocketTimeout() * 1000L)); // milliseconds
188
198
 
189
199
  props.setProperty("applicationName", sqlServerTask.getApplicationName());
190
200
 
@@ -196,9 +206,8 @@ public class SQLServerInputPlugin
196
206
  if (sqlServerTask.getUrl().isPresent()) {
197
207
  if (sqlServerTask.getHost().isPresent()
198
208
  || sqlServerTask.getInstance().isPresent()
199
- || sqlServerTask.getDatabase().isPresent()
200
- || sqlServerTask.getIntegratedSecurity()) {
201
- throw new ConfigException("'host', 'port', 'instance', 'database' and 'integratedSecurity' options are invalid if 'url' option is set.");
209
+ || sqlServerTask.getDatabase().isPresent()) {
210
+ throw new ConfigException("'host', 'instance' and 'database' options are invalid if 'url' option is set.");
202
211
  }
203
212
 
204
213
  return new UrlAndProperties(sqlServerTask.getUrl().get(), props);
@@ -240,7 +249,7 @@ public class SQLServerInputPlugin
240
249
  }
241
250
  }
242
251
  else {
243
- // SQLServerDriver URL: host:port[;databaseName=] or host\instance[;databaseName=]
252
+ // SQLServerDriver URL: host:port[;databaseName=database] or host\instance[;databaseName=database]
244
253
  // host\instance:port[;databaseName] is allowed but \instance will be ignored in this case.
245
254
  if (sqlServerTask.getInstance().isPresent()) {
246
255
  if (sqlServerTask.getPort() != DEFAULT_PORT) {
@@ -252,7 +261,7 @@ public class SQLServerInputPlugin
252
261
  url = String.format(ENGLISH, "jdbc:sqlserver://%s:%d", sqlServerTask.getHost().get(), sqlServerTask.getPort());
253
262
  }
254
263
 
255
- // ;databaseName=
264
+ // ;databaseName=database
256
265
  if (sqlServerTask.getDatabase().isPresent()) {
257
266
  props.setProperty("databaseName", sqlServerTask.getDatabase().get());
258
267
  }
@@ -263,6 +272,7 @@ public class SQLServerInputPlugin
263
272
  throw new ConfigException("'user' options are invalid if 'integratedSecutiry' option is set.");
264
273
  }
265
274
  props.setProperty("integratedSecurity", "true");
275
+ props.setProperty("authenticationScheme", "JavaKerberos");
266
276
  }
267
277
  else {
268
278
  if (!sqlServerTask.getUser().isPresent()) {
@@ -18,12 +18,22 @@ public class SQLServerColumnGetterFactory extends ColumnGetterFactory {
18
18
  @Override
19
19
  public ColumnGetter newColumnGetter(JdbcInputConnection con, AbstractJdbcInputPlugin.PluginTask task, JdbcColumn column, JdbcColumnOption option)
20
20
  {
21
- ColumnGetter getter = super.newColumnGetter(con, task, column, option);
22
21
  switch (column.getTypeName()) {
23
- case "datetime":
24
- return new TimestampWithoutTimeZoneIncrementalHandler(getter);
25
- default:
26
- return getter;
22
+ case "date":
23
+ case "datetime2":
24
+ case "time":
25
+ case "sql_variant":
26
+ // DateTimeOffset is available only in MSSQL
27
+ case "datetimeoffset":
28
+ // because jTDS driver, default JDBC driver for older embulk-input-sqlserver, returns Types.VARCHAR as JDBC type for these types.
29
+ return new StringColumnGetter(to, getToType(option));
30
+
31
+ case "datetime":
32
+ ColumnGetter getter = super.newColumnGetter(con, task, column, option);
33
+ return new TimestampWithoutTimeZoneIncrementalHandler(getter);
34
+
35
+ default:
36
+ return super.newColumnGetter(con, task, column, option);
27
37
  }
28
38
  }
29
39
 
@@ -53,4 +53,13 @@ public class BasicTest
53
53
  assertThat(readSortedFile(out1), is(readResource("test_expected.csv")));
54
54
  assertThat(result1.getConfigDiff(), is((ConfigDiff) loadYamlResource(embulk, "test_expected.diff")));
55
55
  }
56
+
57
+ @Test
58
+ public void testJTDS() throws Exception
59
+ {
60
+ Path out1 = embulk.createTempFile("csv");
61
+ TestingEmbulk.RunResult result1 = embulk.runInput(baseConfig.merge(loadYamlResource(embulk, "jtds_config.yml")), out1);
62
+ assertThat(readSortedFile(out1), is(readResource("test_expected.csv")));
63
+ assertThat(result1.getConfigDiff(), is((ConfigDiff) loadYamlResource(embulk, "test_expected.diff")));
64
+ }
56
65
  }
@@ -0,0 +1,149 @@
1
+ package org.embulk.input.sqlserver;
2
+
3
+ import org.embulk.config.ConfigDiff;
4
+ import org.embulk.config.ConfigSource;
5
+ import org.embulk.input.SQLServerInputPlugin;
6
+ import org.embulk.spi.InputPlugin;
7
+ import org.embulk.test.EmbulkTests;
8
+ import org.embulk.test.TestingEmbulk;
9
+ import org.embulk.test.TestingEmbulk.RunResult;
10
+ import org.junit.Before;
11
+ import org.junit.Rule;
12
+ import org.junit.Test;
13
+
14
+ import java.nio.file.Path;
15
+
16
+ import static org.embulk.input.sqlserver.SQLServerTests.execute;
17
+ import static org.embulk.test.EmbulkTests.readSortedFile;
18
+ import static org.hamcrest.Matchers.is;
19
+ import static org.junit.Assert.assertThat;
20
+
21
+ public class IncrementalTest
22
+ {
23
+ private static final String BASIC_RESOURCE_PATH = "org/embulk/input/sqlserver/test/expect/incremental/";
24
+
25
+ private static ConfigSource loadYamlResource(TestingEmbulk embulk, String fileName)
26
+ {
27
+ return embulk.loadYamlResource(BASIC_RESOURCE_PATH + fileName);
28
+ }
29
+
30
+ private static String readResource(String fileName)
31
+ {
32
+ return EmbulkTests.readResource(BASIC_RESOURCE_PATH + fileName);
33
+ }
34
+
35
+ @Rule
36
+ public TestingEmbulk embulk = TestingEmbulk.builder()
37
+ .registerPlugin(InputPlugin.class, "sqlserver", SQLServerInputPlugin.class)
38
+ .build();
39
+
40
+ private ConfigSource baseConfig;
41
+
42
+ @Before
43
+ public void setup()
44
+ {
45
+ baseConfig = SQLServerTests.baseConfig();
46
+ }
47
+
48
+ @Test
49
+ public void testInt() throws Exception
50
+ {
51
+ // setup first rows
52
+ execute(readResource("int/setup.sql"));
53
+
54
+ Path out1 = embulk.createTempFile("csv");
55
+ RunResult result1 = embulk.runInput(baseConfig.merge(loadYamlResource(embulk, "int/config_1.yml")), out1);
56
+ assertThat(readSortedFile(out1), is(readResource("int/expected_1.csv")));
57
+ assertThat(result1.getConfigDiff(), is((ConfigDiff) loadYamlResource(embulk, "int/expected_1.diff")));
58
+
59
+ // insert more rows
60
+ execute(readResource("int/insert_more.sql"));
61
+
62
+ Path out2 = embulk.createTempFile("csv");
63
+ RunResult result2 = embulk.runInput(baseConfig.merge(loadYamlResource(embulk, "int/config_2.yml")), out2);
64
+ assertThat(readSortedFile(out2), is(readResource("int/expected_2.csv")));
65
+ assertThat(result2.getConfigDiff(), is((ConfigDiff) loadYamlResource(embulk, "int/expected_2.diff")));
66
+ }
67
+
68
+ @Test
69
+ public void testChar() throws Exception
70
+ {
71
+ // setup first rows
72
+ execute(readResource("char/setup.sql"));
73
+
74
+ Path out1 = embulk.createTempFile("csv");
75
+ RunResult result1 = embulk.runInput(baseConfig.merge(loadYamlResource(embulk, "char/config_1.yml")), out1);
76
+ assertThat(readSortedFile(out1), is(readResource("char/expected_1.csv")));
77
+ assertThat(result1.getConfigDiff(), is((ConfigDiff) loadYamlResource(embulk, "char/expected_1.diff")));
78
+
79
+ // insert more rows
80
+ execute(readResource("char/insert_more.sql"));
81
+
82
+ Path out2 = embulk.createTempFile("csv");
83
+ RunResult result2 = embulk.runInput(baseConfig.merge(loadYamlResource(embulk, "char/config_2.yml")), out2);
84
+ assertThat(readSortedFile(out2), is(readResource("char/expected_2.csv")));
85
+ assertThat(result2.getConfigDiff(), is((ConfigDiff) loadYamlResource(embulk, "char/expected_2.diff")));
86
+ }
87
+
88
+ @Test
89
+ public void testDateTime2() throws Exception
90
+ {
91
+ // setup first rows
92
+ execute(readResource("datetime2/setup.sql"));
93
+
94
+ Path out1 = embulk.createTempFile("csv");
95
+ RunResult result1 = embulk.runInput(baseConfig.merge(loadYamlResource(embulk, "datetime2/config_1.yml")), out1);
96
+ assertThat(readSortedFile(out1), is(readResource("datetime2/expected_1.csv")));
97
+ // SQL Server datetime2 type is mapped to StringColumnGetter, not to TimestampWithoutTimeZoneIncrementalHandler, for compatibility.
98
+ // So a timestamp value in JSON will be like 'yyyy-MM-dd HH:mm:ss.SSSSSSS', not like 'yyyy-MM-ddTHH:mm:ss.SSSSSS'.
99
+ assertThat(result1.getConfigDiff(), is((ConfigDiff) loadYamlResource(embulk, "datetime2/expected_1.diff")));
100
+
101
+ // insert more rows
102
+ execute(readResource("datetime2/insert_more.sql"));
103
+
104
+ Path out2 = embulk.createTempFile("csv");
105
+ RunResult result2 = embulk.runInput(baseConfig.merge(loadYamlResource(embulk, "datetime2/config_2.yml")), out2);
106
+ assertThat(readSortedFile(out2), is(readResource("datetime2/expected_2.csv")));
107
+ assertThat(result2.getConfigDiff(), is((ConfigDiff) loadYamlResource(embulk, "datetime2/expected_2.diff")));
108
+ }
109
+
110
+ @Test
111
+ public void testQueryWithPlaceholder() throws Exception
112
+ {
113
+ // setup first rows
114
+ execute(readResource("query/setup.sql"));
115
+
116
+ Path out1 = embulk.createTempFile("csv");
117
+ RunResult result1 = embulk.runInput(baseConfig.merge(loadYamlResource(embulk, "query/config_1.yml")), out1);
118
+ assertThat(readSortedFile(out1), is(readResource("query/expected_1.csv")));
119
+ assertThat(result1.getConfigDiff(), is((ConfigDiff) loadYamlResource(embulk, "query/expected_1.diff")));
120
+
121
+ // insert more rows
122
+ execute(readResource("query/insert_more.sql"));
123
+
124
+ Path out2 = embulk.createTempFile("csv");
125
+ RunResult result2 = embulk.runInput(baseConfig.merge(loadYamlResource(embulk, "query/config_2.yml")), out2);
126
+ assertThat(readSortedFile(out2), is(readResource("query/expected_2.csv")));
127
+ assertThat(result2.getConfigDiff(), is((ConfigDiff) loadYamlResource(embulk, "query/expected_2.diff")));
128
+ }
129
+
130
+ @Test
131
+ public void testQueryWithPlaceholderAndMultiColumns() throws Exception
132
+ {
133
+ // setup first rows
134
+ execute(readResource("query/setup.sql"));
135
+
136
+ Path out1 = embulk.createTempFile("csv");
137
+ RunResult result1 = embulk.runInput(baseConfig.merge(loadYamlResource(embulk, "query/multi_columns_config_1.yml")), out1);
138
+ assertThat(readSortedFile(out1), is(readResource("query/multi_columns_expected_1.csv")));
139
+ assertThat(result1.getConfigDiff(), is((ConfigDiff) loadYamlResource(embulk, "query/multi_columns_expected_1.diff")));
140
+
141
+ // insert more rows
142
+ execute(readResource("query/insert_more.sql"));
143
+
144
+ Path out2 = embulk.createTempFile("csv");
145
+ RunResult result2 = embulk.runInput(baseConfig.merge(loadYamlResource(embulk, "query/multi_columns_config_2.yml")), out2);
146
+ assertThat(readSortedFile(out2), is(readResource("query/multi_columns_expected_2.csv")));
147
+ assertThat(result2.getConfigDiff(), is((ConfigDiff) loadYamlResource(embulk, "query/multi_columns_expected_2.diff")));
148
+ }
149
+ }
@@ -0,0 +1,3 @@
1
+ table: TEST1
2
+ order_by: 'ID'
3
+ driver_type: jtds
@@ -0,0 +1,3 @@
1
+ table: CHAR_LOAD
2
+ incremental: true
3
+ incremental_columns: [NAME]
@@ -0,0 +1,4 @@
1
+ table: CHAR_LOAD
2
+ last_record: ['A4']
3
+ incremental: true
4
+ incremental_columns: [NAME]
@@ -0,0 +1,6 @@
1
+
2
+ INSERT INTO CHAR_LOAD (NAME, NOTE) VALUES ('A0', 'more_skip');
3
+ INSERT INTO CHAR_LOAD (NAME, NOTE) VALUES ('A4', 'more_skip');
4
+ INSERT INTO CHAR_LOAD (NAME, NOTE) VALUES ('A9', 'more_load');
5
+ INSERT INTO CHAR_LOAD (NAME, NOTE) VALUES ('A5', 'more_load');
6
+
@@ -0,0 +1,11 @@
1
+ DROP TABLE CHAR_LOAD
2
+ CREATE TABLE CHAR_LOAD (
3
+ NAME CHAR(2) NOT NULL,
4
+ NOTE TEXT
5
+ );
6
+
7
+ INSERT INTO CHAR_LOAD (NAME, NOTE) VALUES ('A3', 'first');
8
+ INSERT INTO CHAR_LOAD (NAME, NOTE) VALUES ('A4', 'first');
9
+ INSERT INTO CHAR_LOAD (NAME, NOTE) VALUES ('A2', 'first');
10
+ INSERT INTO CHAR_LOAD (NAME, NOTE) VALUES ('A1', 'first');
11
+
@@ -0,0 +1,4 @@
1
+ table: DT_LOAD
2
+ default_time_zone: +0300 # should be ignored
3
+ incremental: true
4
+ incremental_columns: [TIME]
@@ -0,0 +1,4 @@
1
+ table: DT_LOAD
2
+ last_record: ['2016-11-02 04:00:05.3330030']
3
+ incremental: true
4
+ incremental_columns: [TIME]
@@ -0,0 +1,7 @@
1
+ 2016-11-02 01:00:01.0000000,first
2
+ 2016-11-02 02:00:02.0000000,first
3
+ 2016-11-02 03:00:03.0000000,first
4
+ 2016-11-02 04:00:04.0000000,first
5
+ 2016-11-02 04:00:05.1110010,first
6
+ 2016-11-02 04:00:05.2220020,first
7
+ 2016-11-02 04:00:05.3330030,first
@@ -0,0 +1,3 @@
1
+ in:
2
+ last_record: ['2016-11-02 04:00:05.3330030']
3
+ out: {}
@@ -0,0 +1,3 @@
1
+ 2016-11-02 04:00:05.3330040,more_load
2
+ 2016-11-02 04:00:06.0000000,more_load
3
+ 2016-11-02 04:00:06.0000000,more_load
@@ -0,0 +1,3 @@
1
+ in:
2
+ last_record: ['2016-11-02 04:00:06.0000000']
3
+ out: {}
@@ -0,0 +1,8 @@
1
+
2
+ INSERT INTO DT_LOAD (TIME, NOTE) VALUES ('2016-11-02 04:00:00', 'more_skip');
3
+ INSERT INTO DT_LOAD (TIME, NOTE) VALUES ('2016-11-02 04:00:05.333000', 'more_skip');
4
+ INSERT INTO DT_LOAD (TIME, NOTE) VALUES ('2016-11-02 04:00:05.333003', 'more_skip');
5
+ INSERT INTO DT_LOAD (TIME, NOTE) VALUES ('2016-11-02 04:00:05.333004', 'more_load');
6
+ INSERT INTO DT_LOAD (TIME, NOTE) VALUES ('2016-11-02 04:00:06', 'more_load');
7
+ INSERT INTO DT_LOAD (TIME, NOTE) VALUES ('2016-11-02 04:00:06', 'more_load');
8
+
@@ -0,0 +1,14 @@
1
+ DROP TABLE DT_LOAD
2
+ CREATE TABLE DT_LOAD (
3
+ TIME DATETIME2 NOT NULL,
4
+ NOTE TEXT
5
+ );
6
+
7
+ INSERT INTO DT_LOAD (TIME, NOTE) VALUES ('2016-11-02 01:00:01', 'first');
8
+ INSERT INTO DT_LOAD (TIME, NOTE) VALUES ('2016-11-02 02:00:02', 'first');
9
+ INSERT INTO DT_LOAD (TIME, NOTE) VALUES ('2016-11-02 03:00:03', 'first');
10
+ INSERT INTO DT_LOAD (TIME, NOTE) VALUES ('2016-11-02 04:00:04', 'first');
11
+ INSERT INTO DT_LOAD (TIME, NOTE) VALUES ('2016-11-02 04:00:05.111001', 'first');
12
+ INSERT INTO DT_LOAD (TIME, NOTE) VALUES ('2016-11-02 04:00:05.222002', 'first');
13
+ INSERT INTO DT_LOAD (TIME, NOTE) VALUES ('2016-11-02 04:00:05.333003', 'first');
14
+
@@ -0,0 +1,3 @@
1
+ table: INT_LOAD
2
+ incremental: true
3
+ incremental_columns: [NUM]
@@ -0,0 +1,4 @@
1
+ table: INT_LOAD
2
+ last_record: [4]
3
+ incremental: true
4
+ incremental_columns: [NUM]
@@ -0,0 +1,6 @@
1
+
2
+ INSERT INTO INT_LOAD (NUM, NOTE) VALUES (0, 'more_skip');
3
+ INSERT INTO INT_LOAD (NUM, NOTE) VALUES (4, 'more_skip');
4
+ INSERT INTO INT_LOAD (NUM, NOTE) VALUES (9, 'more_load');
5
+ INSERT INTO INT_LOAD (NUM, NOTE) VALUES (5, 'more_load');
6
+
@@ -0,0 +1,11 @@
1
+ DROP TABLE INT_LOAD
2
+ CREATE TABLE INT_LOAD (
3
+ NUM INT NOT NULL,
4
+ NOTE TEXT
5
+ );
6
+
7
+ INSERT INTO INT_LOAD (NUM, NOTE) VALUES (3, 'first');
8
+ INSERT INTO INT_LOAD (NUM, NOTE) VALUES (4, 'first');
9
+ INSERT INTO INT_LOAD (NUM, NOTE) VALUES (2, 'first');
10
+ INSERT INTO INT_LOAD (NUM, NOTE) VALUES (1, 'first');
11
+
@@ -0,0 +1,14 @@
1
+ last_record: [0]
2
+ incremental: true
3
+ incremental_columns: [NUM]
4
+ use_raw_query_with_incremental: true
5
+ query: |
6
+ SELECT
7
+ NUM,NOTE
8
+ FROM
9
+ QUERY_LOAD
10
+ WHERE
11
+ NUM IS NOT NULL
12
+ AND NUM > :NUM
13
+ ORDER BY
14
+ NUM ASC
@@ -0,0 +1,14 @@
1
+ last_record: [4]
2
+ incremental: true
3
+ incremental_columns: [NUM]
4
+ use_raw_query_with_incremental: true
5
+ query: |
6
+ SELECT
7
+ NUM,NOTE
8
+ FROM
9
+ QUERY_LOAD
10
+ WHERE
11
+ NUM IS NOT NULL
12
+ AND NUM > :NUM
13
+ ORDER BY
14
+ NUM ASC
@@ -0,0 +1,5 @@
1
+
2
+ INSERT INTO QUERY_LOAD (NUM, NUM2, NOTE) VALUES (0, 100, 'more_skip');
3
+ INSERT INTO QUERY_LOAD (NUM, NUM2, NOTE) VALUES (4, 104, 'more_skip');
4
+ INSERT INTO QUERY_LOAD (NUM, NUM2, NOTE) VALUES (9, 109, 'more_load');
5
+ INSERT INTO QUERY_LOAD (NUM, NUM2, NOTE) VALUES (5, 105, 'more_load');
@@ -0,0 +1,16 @@
1
+ last_record: [0,0]
2
+ incremental: true
3
+ incremental_columns: [NUM,NUM2]
4
+ use_raw_query_with_incremental: true
5
+ query: |
6
+ SELECT
7
+ *
8
+ FROM
9
+ QUERY_LOAD
10
+ WHERE
11
+ NUM IS NOT NULL
12
+ AND NUM > :NUM
13
+ OR (NUM = :NUM AND NUM2 > :NUM2)
14
+ ORDER BY
15
+ NUM ASC,
16
+ NUM2 ASC
@@ -0,0 +1,17 @@
1
+ last_record: [4,104]
2
+ incremental: true
3
+ incremental_columns: [NUM,NUM2]
4
+ use_raw_query_with_incremental: true
5
+ query: |
6
+ SELECT
7
+ *
8
+ FROM
9
+ QUERY_LOAD
10
+ WHERE
11
+ NUM IS NOT NULL
12
+ AND NUM > :NUM
13
+ AND NUM2 IS NOT NULL
14
+ OR (NUM = :NUM AND NUM2 > :NUM2)
15
+ ORDER BY
16
+ NUM ASC,
17
+ NUM2 ASC
@@ -0,0 +1,11 @@
1
+ DROP TABLE QUERY_LOAD
2
+ CREATE TABLE QUERY_LOAD (
3
+ NUM INT NOT NULL,
4
+ NUM2 INT NOT NULL,
5
+ NOTE TEXT
6
+ );
7
+
8
+ INSERT INTO QUERY_LOAD (NUM, NUM2, NOTE) VALUES (3, 103, 'first');
9
+ INSERT INTO QUERY_LOAD (NUM, NUM2, NOTE) VALUES (4, 104, 'first');
10
+ INSERT INTO QUERY_LOAD (NUM, NUM2, NOTE) VALUES (2, 102, 'first');
11
+ INSERT INTO QUERY_LOAD (NUM, NUM2, NOTE) VALUES (1, 101, 'first');
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: embulk-input-sqlserver
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.10.0
4
+ version: 0.10.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sadayuki Furuhashi
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-05-23 00:00:00.000000000 Z
11
+ date: 2019-09-06 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: Selects records from a table.
14
14
  email:
@@ -19,19 +19,60 @@ extra_rdoc_files: []
19
19
  files:
20
20
  - README.md
21
21
  - build.gradle
22
- - classpath/embulk-input-jdbc-0.10.0.jar
23
- - classpath/embulk-input-sqlserver-0.10.0.jar
22
+ - classpath/embulk-input-jdbc-0.10.1.jar
23
+ - classpath/embulk-input-sqlserver-0.10.1.jar
24
24
  - classpath/jtds-1.3.1.jar
25
+ - classpath/mssql-jdbc-7.2.2.jre8.jar
25
26
  - lib/embulk/input/sqlserver.rb
26
27
  - src/main/java/org/embulk/input/SQLServerInputPlugin.java
27
28
  - src/main/java/org/embulk/input/sqlserver/SQLServerInputConnection.java
28
29
  - src/main/java/org/embulk/input/sqlserver/getter/SQLServerColumnGetterFactory.java
29
30
  - src/test/java/org/embulk/input/sqlserver/BasicTest.java
31
+ - src/test/java/org/embulk/input/sqlserver/IncrementalTest.java
30
32
  - src/test/java/org/embulk/input/sqlserver/SQLServerTests.java
33
+ - src/test/resources/org/embulk/input/sqlserver/test/expect/basic/jtds_config.yml
31
34
  - src/test/resources/org/embulk/input/sqlserver/test/expect/basic/setup.sql
32
35
  - src/test/resources/org/embulk/input/sqlserver/test/expect/basic/test_config.yml
33
36
  - src/test/resources/org/embulk/input/sqlserver/test/expect/basic/test_expected.csv
34
37
  - src/test/resources/org/embulk/input/sqlserver/test/expect/basic/test_expected.diff
38
+ - src/test/resources/org/embulk/input/sqlserver/test/expect/incremental/char/config_1.yml
39
+ - src/test/resources/org/embulk/input/sqlserver/test/expect/incremental/char/config_2.yml
40
+ - src/test/resources/org/embulk/input/sqlserver/test/expect/incremental/char/expected_1.csv
41
+ - src/test/resources/org/embulk/input/sqlserver/test/expect/incremental/char/expected_1.diff
42
+ - src/test/resources/org/embulk/input/sqlserver/test/expect/incremental/char/expected_2.csv
43
+ - src/test/resources/org/embulk/input/sqlserver/test/expect/incremental/char/expected_2.diff
44
+ - src/test/resources/org/embulk/input/sqlserver/test/expect/incremental/char/insert_more.sql
45
+ - src/test/resources/org/embulk/input/sqlserver/test/expect/incremental/char/setup.sql
46
+ - src/test/resources/org/embulk/input/sqlserver/test/expect/incremental/datetime2/config_1.yml
47
+ - src/test/resources/org/embulk/input/sqlserver/test/expect/incremental/datetime2/config_2.yml
48
+ - src/test/resources/org/embulk/input/sqlserver/test/expect/incremental/datetime2/expected_1.csv
49
+ - src/test/resources/org/embulk/input/sqlserver/test/expect/incremental/datetime2/expected_1.diff
50
+ - src/test/resources/org/embulk/input/sqlserver/test/expect/incremental/datetime2/expected_2.csv
51
+ - src/test/resources/org/embulk/input/sqlserver/test/expect/incremental/datetime2/expected_2.diff
52
+ - src/test/resources/org/embulk/input/sqlserver/test/expect/incremental/datetime2/insert_more.sql
53
+ - src/test/resources/org/embulk/input/sqlserver/test/expect/incremental/datetime2/setup.sql
54
+ - src/test/resources/org/embulk/input/sqlserver/test/expect/incremental/int/config_1.yml
55
+ - src/test/resources/org/embulk/input/sqlserver/test/expect/incremental/int/config_2.yml
56
+ - src/test/resources/org/embulk/input/sqlserver/test/expect/incremental/int/expected_1.csv
57
+ - src/test/resources/org/embulk/input/sqlserver/test/expect/incremental/int/expected_1.diff
58
+ - src/test/resources/org/embulk/input/sqlserver/test/expect/incremental/int/expected_2.csv
59
+ - src/test/resources/org/embulk/input/sqlserver/test/expect/incremental/int/expected_2.diff
60
+ - src/test/resources/org/embulk/input/sqlserver/test/expect/incremental/int/insert_more.sql
61
+ - src/test/resources/org/embulk/input/sqlserver/test/expect/incremental/int/setup.sql
62
+ - src/test/resources/org/embulk/input/sqlserver/test/expect/incremental/query/config_1.yml
63
+ - src/test/resources/org/embulk/input/sqlserver/test/expect/incremental/query/config_2.yml
64
+ - src/test/resources/org/embulk/input/sqlserver/test/expect/incremental/query/expected_1.csv
65
+ - src/test/resources/org/embulk/input/sqlserver/test/expect/incremental/query/expected_1.diff
66
+ - src/test/resources/org/embulk/input/sqlserver/test/expect/incremental/query/expected_2.csv
67
+ - src/test/resources/org/embulk/input/sqlserver/test/expect/incremental/query/expected_2.diff
68
+ - src/test/resources/org/embulk/input/sqlserver/test/expect/incremental/query/insert_more.sql
69
+ - src/test/resources/org/embulk/input/sqlserver/test/expect/incremental/query/multi_columns_config_1.yml
70
+ - src/test/resources/org/embulk/input/sqlserver/test/expect/incremental/query/multi_columns_config_2.yml
71
+ - src/test/resources/org/embulk/input/sqlserver/test/expect/incremental/query/multi_columns_expected_1.csv
72
+ - src/test/resources/org/embulk/input/sqlserver/test/expect/incremental/query/multi_columns_expected_1.diff
73
+ - src/test/resources/org/embulk/input/sqlserver/test/expect/incremental/query/multi_columns_expected_2.csv
74
+ - src/test/resources/org/embulk/input/sqlserver/test/expect/incremental/query/multi_columns_expected_2.diff
75
+ - src/test/resources/org/embulk/input/sqlserver/test/expect/incremental/query/setup.sql
35
76
  homepage: https://github.com/embulk/embulk-input-jdbc
36
77
  licenses:
37
78
  - Apache 2.0