embulk-output-sqlserver 0.8.5 → 0.8.6

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: d95b2b450eb4a21786e7f1395c2920ada8826573
4
- data.tar.gz: baa43925d9fa961ba0d0d13cb99ed4d5ec5981e4
3
+ metadata.gz: 6a2b4419d9125103b0c560157271d356377bf3ed
4
+ data.tar.gz: e9013fa22cecbc1c82980b2593fb104dc23630da
5
5
  SHA512:
6
- metadata.gz: 97c35831f60cd782bf275735f9fd73ce875daf791d4a008c7d26ed07e5e44db79454159caf5743c4eec453db3c2adf07a98ee5dd32a31c1185de9aa86dbef3bb
7
- data.tar.gz: 4d954ca104379794dd62ae5a55b50092586e88dabb42705ae87879ce54f1795663b2e94870d8b536f1a52e11c0f5b0b7c5515db0d419889e1ab1aae346f2f34b
6
+ metadata.gz: 1962baaf5f270e572fa52d3e482751270f8f5e1506864146628785f75c459caf790682f6641f32803ce58e012e9f71543a3c2a18c163203e3c999c89a46b2155
7
+ data.tar.gz: f60384f6964fd889151f82e2c8b49b00b562bd28b10976593fe585f33f0c5c09c2979dcdaab1ae8f917bae6183a8e11e944e7bc013caf28c777939e791567a5f
data/README.md CHANGED
@@ -10,8 +10,8 @@ SQL Server output plugin for Embulk loads records to SQL Server.
10
10
 
11
11
  ## Configuration
12
12
 
13
- - **driver_path**: path to the jar file of Microsoft SQL Server JDBC driver. If not set, open-source driver (jTDS driver) is used (string)
14
- - **host**: database host name (string, required)
13
+ - **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)
14
+ - **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")- **host**: database host name (string, required)
15
15
  - **port**: database port number (integer, default: 1433)
16
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)
17
17
  ```
@@ -44,11 +44,13 @@ embulk "-J-Djava.library.path=C:\drivers" run input-sqlserver.yml
44
44
  - **column_options**: advanced: a key-value pairs where key is a column name and value is options for the column.
45
45
  - **type**: type of a column when this plugin creates new tables (e.g. `VARCHAR(255)`, `INTEGER NOT NULL UNIQUE`). This used when this plugin creates intermediate tables (insert, insert_truncate and merge modes), when it creates the target table (insert_direct, merge_direct and replace modes), and when it creates nonexistent target table automatically. (string, default: depends on input column type. `BIGINT` if input column type is long, `BOOLEAN` if boolean, `DOUBLE PRECISION` if double, `CLOB` if string, `TIMESTAMP` if timestamp)
46
46
  - **value_type**: This plugin converts input column type (embulk type) into a database type to build a INSERT statement. This value_type option controls the type of the value in a INSERT statement. (string, default: depends on the sql type of the column. Available values options are: `byte`, `short`, `int`, `long`, `double`, `float`, `boolean`, `string`, `nstring`, `date`, `time`, `timestamp`, `decimal`, `json`, `null`, `pass`)
47
+ NOTE: the default value_type for DATE, TIME and DATETIME2 is `string`, because jTDS driver, default JDBC driver for older embulk-output-sqlserver, returns Types.VARCHAR as JDBC type for these types.
47
48
  - **timestamp_format**: If input column type (embulk type) is timestamp and value_type is `string` or `nstring`, this plugin needs to format the timestamp value into a string. This timestamp_format option is used to control the format of the timestamp. (string, default: `%Y-%m-%d %H:%M:%S.%6N`)
48
49
  - **timezone**: If input column type (embulk type) is timestamp, this plugin needs to format the timestamp value into a SQL string. In this cases, this timezone option is used to control the timezone. (string, value of default_timezone option is used by default)
49
50
  - **before_load**: if set, this SQL will be executed before loading all records. In truncate_insert mode, the SQL will be executed after truncating. replace mode doesn't support this option.
50
51
  - **after_load**: if set, this SQL will be executed after loading all records.
51
-
52
+ - **connect_timeout**: timeout for the driver to connect. 0 means the default of SQL Server (15 by default). (integer (seconds), optional)
53
+ - **socket_timeout**: timeout for executing the query. 0 means no timeout. (integer (seconds), optional)
52
54
  ### Modes
53
55
 
54
56
  * **insert**:
@@ -1,8 +1,8 @@
1
1
  dependencies {
2
2
  compile project(':embulk-output-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.8.22'
6
7
  testCompile project(':embulk-output-jdbc').sourceSets.test.output
7
- testCompile files('test_jdbc_driver/sqljdbc41.jar')
8
8
  }
@@ -29,9 +29,6 @@ import static java.util.Locale.ENGLISH;
29
29
  public class SQLServerOutputPlugin
30
30
  extends AbstractJdbcOutputPlugin
31
31
  {
32
- // for test
33
- public static boolean preferMicrosoftDriver = true;
34
-
35
32
  private static int DEFAULT_PORT = 1433;
36
33
 
37
34
  public interface SQLServerPluginTask
@@ -41,6 +38,10 @@ public class SQLServerOutputPlugin
41
38
  @ConfigDefault("null")
42
39
  public Optional<String> getDriverPath();
43
40
 
41
+ @Config("driver_type")
42
+ @ConfigDefault("\"mssql-jdbc\"")
43
+ public String getDriverType();
44
+
44
45
  @Config("host")
45
46
  @ConfigDefault("null")
46
47
  public Optional<String> getHost();
@@ -92,6 +93,14 @@ public class SQLServerOutputPlugin
92
93
  @Config("database_encoding")
93
94
  @ConfigDefault("\"MS932\"")
94
95
  public String getDatabaseEncoding();
96
+
97
+ @Config("connect_timeout")
98
+ @ConfigDefault("null")
99
+ public Optional<Integer> getConnectTimeout();
100
+
101
+ @Config("socket_timeout")
102
+ @ConfigDefault("null")
103
+ public Optional<Integer> getSocketTimeout();
95
104
  }
96
105
 
97
106
  private static class UrlAndProperties {
@@ -134,35 +143,30 @@ public class SQLServerOutputPlugin
134
143
  protected JdbcOutputConnector getConnector(PluginTask task, boolean retryableMetadataOperation)
135
144
  {
136
145
  SQLServerPluginTask sqlServerTask = (SQLServerPluginTask) task;
137
- boolean useJtdsDriver = false;
138
146
 
139
147
  if (sqlServerTask.getDriverPath().isPresent()) {
140
148
  addDriverJarToClasspath(sqlServerTask.getDriverPath().get());
149
+ }
150
+
151
+ boolean useJtdsDriver;
152
+ if (sqlServerTask.getDriverType().equalsIgnoreCase("mssql-jdbc")) {
153
+ useJtdsDriver = false;
141
154
  try {
142
- Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
143
- } catch (Exception e) {
144
- throw new ConfigException("Driver set at field 'driver_path' doesn't include Microsoft SQLServerDriver", e);
155
+ Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver").newInstance();
145
156
  }
146
- } else {
147
- boolean useMicrosoftDriver = false;
148
- if (preferMicrosoftDriver) {
149
- // prefer Microsoft SQLServerDriver if it is in classpath
150
- try {
151
- Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
152
- useMicrosoftDriver = true;
153
- } catch (Exception e) {
154
- }
157
+ catch (Exception e) {
158
+ throw new ConfigException("Can't load Microsoft SQLServerDriver from classpath", e);
155
159
  }
156
-
157
- if (!useMicrosoftDriver) {
158
- logger.info("Using jTDS Driver");
159
- try {
160
- Class.forName("net.sourceforge.jtds.jdbc.Driver");
161
- } catch (Exception e) {
162
- throw new ConfigException("'driver_path' doesn't set and can't find jTDS driver", e);
163
- }
164
- useJtdsDriver = true;
160
+ } else if (sqlServerTask.getDriverType().equalsIgnoreCase("jtds")) {
161
+ useJtdsDriver = true;
162
+ try {
163
+ Class.forName("net.sourceforge.jtds.jdbc.Driver").newInstance();
164
+ }
165
+ catch (Exception e) {
166
+ throw new ConfigException("Can't load jTDS Driver from classpath", e);
165
167
  }
168
+ } else {
169
+ throw new ConfigException("Unknown driver_type : " + sqlServerTask.getDriverType());
166
170
  }
167
171
 
168
172
  UrlAndProperties urlProps = getUrlAndProperties(sqlServerTask, useJtdsDriver);
@@ -191,9 +195,8 @@ public class SQLServerOutputPlugin
191
195
 
192
196
  if (sqlServerTask.getHost().isPresent()
193
197
  || sqlServerTask.getInstance().isPresent()
194
- || sqlServerTask.getDatabase().isPresent()
195
- || sqlServerTask.getIntegratedSecurity().isPresent()) {
196
- throw new IllegalArgumentException("'host', 'port', 'instance', 'database' and 'integratedSecurity' parameters are invalid if 'url' parameter is set.");
198
+ || sqlServerTask.getDatabase().isPresent()) {
199
+ throw new IllegalArgumentException("'host', 'instance' and 'database' parameters are invalid if 'url' parameter is set.");
197
200
  }
198
201
  url = sqlServerTask.getUrl().get();
199
202
  } else {
@@ -232,7 +235,11 @@ public class SQLServerOutputPlugin
232
235
  if (!sqlServerTask.getUser().isPresent()) {
233
236
  throw new ConfigException("'user' option is required but not set.");
234
237
  }
235
- }else {
238
+
239
+ if (sqlServerTask.getSocketTimeout().isPresent()) {
240
+ props.setProperty("socketTimeout", String.valueOf(sqlServerTask.getSocketTimeout().get())); // seconds
241
+ }
242
+ } else {
236
243
  StringBuilder urlBuilder = new StringBuilder();
237
244
  if (sqlServerTask.getInstance().isPresent()) {
238
245
  urlBuilder.append(String.format("jdbc:sqlserver://%s\\%s",
@@ -254,9 +261,18 @@ public class SQLServerOutputPlugin
254
261
  throw new IllegalArgumentException("Field 'password' is not set.");
255
262
  }
256
263
  }
264
+
265
+ if (sqlServerTask.getSocketTimeout().isPresent()) {
266
+ props.setProperty("socketTimeout", String.valueOf(sqlServerTask.getSocketTimeout().get() * 1000L)); // milliseconds
267
+ }
268
+
257
269
  url = urlBuilder.toString();
258
270
  }
259
271
 
272
+ if (sqlServerTask.getConnectTimeout().isPresent()) {
273
+ props.setProperty("loginTimeout", String.valueOf(sqlServerTask.getConnectTimeout().get())); // seconds
274
+ }
275
+
260
276
  return new UrlAndProperties(url, props);
261
277
  }
262
278
 
@@ -47,6 +47,15 @@ public class SQLServerOutputConnection
47
47
  return "TEXT";
48
48
  case "TIMESTAMP":
49
49
  return "DATETIME2";
50
+ case "NVARCHAR":
51
+ if(c.getSizeTypeParameter() > 4000) {
52
+ return "NVARCHAR(max)";
53
+ }
54
+ case "VARCHAR":
55
+ if(c.getSizeTypeParameter() > 8000) {
56
+ return "VARCHAR(max)";
57
+ }
58
+
50
59
  default:
51
60
  return super.buildColumnTypeName(c);
52
61
  }
@@ -7,6 +7,7 @@ import org.embulk.output.jdbc.JdbcColumn;
7
7
  import org.embulk.output.jdbc.JdbcColumnOption;
8
8
  import org.embulk.output.jdbc.setter.ColumnSetter;
9
9
  import org.embulk.output.jdbc.setter.ColumnSetterFactory;
10
+ import org.embulk.output.jdbc.setter.StringColumnSetter;
10
11
  import org.joda.time.DateTimeZone;
11
12
 
12
13
  public class SQLServerColumnSetterFactory
@@ -42,6 +43,19 @@ public class SQLServerColumnSetterFactory
42
43
  case "time":
43
44
  return new SQLServerSqlTimeColumnSetter(batch, column, newDefaultValueSetter(column, option), newCalendar(option));
44
45
 
46
+ case "coerce":
47
+ switch (column.getSimpleTypeName().toLowerCase()) {
48
+ case "date":
49
+ case "datetime2":
50
+ case "time":
51
+ case "sql_variant":
52
+ case "datetimeoffset":
53
+ // because jTDS driver, default JDBC driver for older embulk-output-sqlserver, returns Types.VARCHAR as JDBC type for these types.
54
+ return new StringColumnSetter(batch, column, newDefaultValueSetter(column, option), newTimestampFormatter(option));
55
+ default:
56
+ return super.newColumnSetter(column, option);
57
+ }
58
+
45
59
  default:
46
60
  return super.newColumnSetter(column, option);
47
61
  }
@@ -1,6 +1,7 @@
1
1
  package org.embulk.output.sqlserver;
2
2
 
3
3
  import static org.embulk.output.sqlserver.SQLServerTests.execute;
4
+ import static org.embulk.output.sqlserver.SQLServerTests.executeQuery;
4
5
  import static org.embulk.output.sqlserver.SQLServerTests.selectRecords;
5
6
  import static org.hamcrest.Matchers.is;
6
7
  import static org.junit.Assert.assertThat;
@@ -9,7 +10,9 @@ import java.io.File;
9
10
  import java.net.URISyntaxException;
10
11
  import java.net.URL;
11
12
  import java.nio.file.FileSystems;
13
+ import java.nio.file.Files;
12
14
  import java.nio.file.Path;
15
+ import java.util.Arrays;
13
16
 
14
17
  import org.embulk.config.ConfigDiff;
15
18
  import org.embulk.config.ConfigSource;
@@ -177,18 +180,31 @@ public class BasicTest
177
180
  //assertThat(result1.getConfigDiff(), is((ConfigDiff) loadYamlResource(embulk, "test_expected.diff")));
178
181
  }
179
182
 
183
+ @Test
184
+ public void testMax() throws Exception
185
+ {
186
+ Path in1 = embulk.createTempFile(".csv");
187
+ String line3 = "2," + createString('A', 8000) + "," + createString('a', 10000) + "," + createString('あ', 4000) + "," + createString('ア', 10000);
188
+ Files.write(in1, Arrays.asList("ID:long,C1:string,C2:string,C3:string,C4:string", "1,,,,", line3));
189
+ TestingEmbulk.RunResult result1 = embulk.runOutput(baseConfig.merge(loadYamlResource(embulk, "test_max.yml")), in1);
190
+ assertThat(executeQuery(embulk, "SELECT ID, LEN(C1), LEN(C2), LEN(C3), LEN(C4) FROM TEST_MAX"), is("1,NULL,NULL,NULL,NULL\n2,8000,10000,4000,10000\n"));
191
+ //assertThat(result1.getConfigDiff(), is((ConfigDiff) loadYamlResource(embulk, "test_expected.diff")));
192
+ }
193
+
194
+ private static String createString(char c, int n)
195
+ {
196
+ char[] chars = new char[n];
197
+ Arrays.fill(chars, c);
198
+ return new String(chars);
199
+ }
200
+
180
201
  @Test
181
202
  public void testJtds() throws Exception
182
203
  {
183
- SQLServerOutputPlugin.preferMicrosoftDriver = false;
184
- try {
185
- Path in1 = toPath("test1.csv");
186
- TestingEmbulk.RunResult result1 = embulk.runOutput(baseConfig.merge(loadYamlResource(embulk, "test_insert.yml")), in1);
187
- assertThat(selectRecords(embulk, "TEST1"), is(readResource("test_insert_expected.csv")));
188
- //assertThat(result1.getConfigDiff(), is((ConfigDiff) loadYamlResource(embulk, "test_expected.diff")));
189
- } finally {
190
- SQLServerOutputPlugin.preferMicrosoftDriver = true;
191
- }
204
+ Path in1 = toPath("test1.csv");
205
+ TestingEmbulk.RunResult result1 = embulk.runOutput(baseConfig.merge(loadYamlResource(embulk, "test_jtds.yml")), in1);
206
+ assertThat(selectRecords(embulk, "TEST1"), is(readResource("test_insert_expected.csv")));
207
+ //assertThat(result1.getConfigDiff(), is((ConfigDiff) loadYamlResource(embulk, "test_expected.diff")));
192
208
  }
193
209
 
194
210
  private Path toPath(String fileName) throws URISyntaxException
@@ -37,7 +37,7 @@ public class SQLServerTests
37
37
  Integer port = config.get(Integer.class, "port");
38
38
  String database = config.get(String.class, "database");
39
39
 
40
- String url = String.format("jdbc:jtds:sqlserver://%s:%d/%s", host, port, database);
40
+ String url = String.format("jdbc:sqlserver://%s:%d;databaseName=%s", host, port, database);
41
41
 
42
42
  return DriverManager.getConnection(url, user, password);
43
43
  }
@@ -79,12 +79,17 @@ public class SQLServerTests
79
79
  }
80
80
 
81
81
  public static String selectRecords(TestingEmbulk embulk, String tableName) throws IOException
82
+ {
83
+ return executeQuery(embulk, "SELECT * FROM " + tableName);
84
+ }
85
+
86
+ public static String executeQuery(TestingEmbulk embulk, String query) throws IOException
82
87
  {
83
88
  Path temp = embulk.createTempFile("txt");
84
89
  Files.delete(temp);
85
90
 
86
91
  // should not use UTF8 because of BOM
87
- execute("SET NOCOUNT ON; SELECT * FROM " + tableName, "-h", "-1", "-s", ",", "-W", "-f", "932", "-o", temp.toString());
92
+ execute("SET NOCOUNT ON; " + query, "-h", "-1", "-s", ",", "-W", "-f", "932", "-o", temp.toString());
88
93
 
89
94
  List<String> lines = Files.readAllLines(temp, Charset.forName("MS932"));
90
95
  Collections.sort(lines);
@@ -80,3 +80,13 @@ CREATE TABLE TEST_MERGE2 (
80
80
  INSERT INTO TEST_MERGE2 VALUES(10, 20, 'A');
81
81
  INSERT INTO TEST_MERGE2 VALUES(10, 21, 'B');
82
82
  INSERT INTO TEST_MERGE2 VALUES(11, 20, 'C');
83
+
84
+ DROP TABLE TEST_MAX
85
+ CREATE TABLE TEST_MAX (
86
+ ID INT,
87
+ C1 VARCHAR(8000),
88
+ C2 VARCHAR(MAX),
89
+ C3 NVARCHAR(4000),
90
+ C4 NVARCHAR(MAX),
91
+ PRIMARY KEY (ID)
92
+ );
@@ -0,0 +1,3 @@
1
+ table: TEST1
2
+ mode: insert
3
+ driver_type: jtds
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: embulk-output-sqlserver
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.8.5
4
+ version: 0.8.6
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-10 00:00:00.000000000 Z
11
+ date: 2019-08-22 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: Inserts or updates records to a table.
14
14
  email:
@@ -19,9 +19,10 @@ extra_rdoc_files: []
19
19
  files:
20
20
  - README.md
21
21
  - build.gradle
22
- - classpath/embulk-output-jdbc-0.8.5.jar
23
- - classpath/embulk-output-sqlserver-0.8.5.jar
22
+ - classpath/embulk-output-jdbc-0.8.6.jar
23
+ - classpath/embulk-output-sqlserver-0.8.6.jar
24
24
  - classpath/jtds-1.3.1.jar
25
+ - classpath/mssql-jdbc-7.2.2.jre8.jar
25
26
  - lib/embulk/output/sqlserver.rb
26
27
  - src/main/java/org/embulk/output/SQLServerOutputPlugin.java
27
28
  - src/main/java/org/embulk/output/sqlserver/InsertMethod.java
@@ -45,6 +46,8 @@ files:
45
46
  - src/test/resources/org/embulk/output/sqlserver/test/expect/basic/test_insert_create_expected.csv
46
47
  - src/test/resources/org/embulk/output/sqlserver/test/expect/basic/test_insert_direct.yml
47
48
  - src/test/resources/org/embulk/output/sqlserver/test/expect/basic/test_insert_expected.csv
49
+ - src/test/resources/org/embulk/output/sqlserver/test/expect/basic/test_jtds.yml
50
+ - src/test/resources/org/embulk/output/sqlserver/test/expect/basic/test_max.yml
48
51
  - src/test/resources/org/embulk/output/sqlserver/test/expect/basic/test_merge.csv
49
52
  - src/test/resources/org/embulk/output/sqlserver/test/expect/basic/test_merge.yml
50
53
  - src/test/resources/org/embulk/output/sqlserver/test/expect/basic/test_merge_expected.csv