embulk-output-redshift 0.2.3 → 0.2.4

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: 3ff2fd199953ea0ebd7ac862ff8418663cfbf036
4
- data.tar.gz: 3d74746d1268d79795e6e688c7e0b4c9c19ab559
3
+ metadata.gz: 58358c6f921e03a15a58929b8241a40cc97f5ff1
4
+ data.tar.gz: a7b29d7fdd1247da37dac5687c132eef280e6b30
5
5
  SHA512:
6
- metadata.gz: 6b87622b0cf0964548b343552fb7b428446f2f72d7c384a67a537816b8d7c30f826a69a01c0f25be23c8d5030ca1ad24c2c295a3b50eae559be8836611b5935a
7
- data.tar.gz: 3ca0ba498a1f26c764388b6cf7e4a3ed1bce4d602c3b5c01e09c96e89e219c768cf31ea8b238248fe9ee3249f0ad7079d788801b937dd9c13abbdeb375ee2071
6
+ metadata.gz: e2f87d3cc3f9a1d5aa1c94b8a9b00fabc8deef097a2c9e6b8da7d3ddf81a3a5907094ef22ec675f49d4567d274a848ce6161424f9ba5edbbd885d98a9a6940ec
7
+ data.tar.gz: 37db160a1993e53804837b379530ffb746f9c77e535e4d5f6f723a060e0135be1854e8c85dde3ea7ba23351791cf9ac4a1d704c8631fbdf2674fd5bd2ebf203b
data/README.md CHANGED
@@ -1,47 +1,47 @@
1
- # Redshift output plugins for Embulk
2
-
3
- Redshift output plugins for Embulk loads records to Redshift.
4
-
5
- ## Overview
6
-
7
- * **Plugin type**: output
8
- * **Load all or nothing**: depnds on the mode:
9
- * **insert**: no
10
- * **replace**: yes
11
- * **Resume supported**: no
12
-
13
- ## Configuration
14
-
15
- - **host**: database host name (string, required)
16
- - **port**: database port number (integer, default: 5439)
17
- - **user**: database login user name (string, required)
18
- - **password**: database login password (string, default: "")
19
- - **database**: destination database name (string, required)
20
- - **schema**: destination schema name (string, default: "public")
21
- - **table**: destination table name (string, required)
22
- - **mode**: "replace" or "insert" (string, required)
23
- - **batch_size**: size of a single batch insert (integer, default: 16777216)
24
- - **options**: extra connection properties (hash, default: {})
25
-
26
- ### Example
27
-
28
- ```yaml
29
- out:
30
- type: redshift
31
- host: myinstance.us-west-2.redshift.amazonaws.com
32
- user: pg
33
- password: ""
34
- database: my_database
35
- table: my_table
36
- access_key_id: ABCXYZ123ABCXYZ123
37
- secret_access_key: AbCxYz123aBcXyZ123
38
- s3_bucket: my-redshift-transfer-bucket
39
- iam_user_name: my-s3-read-only
40
- mode: insert
41
- ```
42
-
43
- ### Build
44
-
45
- ```
46
- $ ./gradlew gem
47
- ```
1
+ # Redshift output plugins for Embulk
2
+
3
+ Redshift output plugins for Embulk loads records to Redshift.
4
+
5
+ ## Overview
6
+
7
+ * **Plugin type**: output
8
+ * **Load all or nothing**: depnds on the mode:
9
+ * **insert**: no
10
+ * **replace**: yes
11
+ * **Resume supported**: no
12
+
13
+ ## Configuration
14
+
15
+ - **host**: database host name (string, required)
16
+ - **port**: database port number (integer, default: 5439)
17
+ - **user**: database login user name (string, required)
18
+ - **password**: database login password (string, default: "")
19
+ - **database**: destination database name (string, required)
20
+ - **schema**: destination schema name (string, default: "public")
21
+ - **table**: destination table name (string, required)
22
+ - **mode**: "replace" or "insert" (string, required)
23
+ - **batch_size**: size of a single batch insert (integer, default: 16777216)
24
+ - **options**: extra connection properties (hash, default: {})
25
+
26
+ ### Example
27
+
28
+ ```yaml
29
+ out:
30
+ type: redshift
31
+ host: myinstance.us-west-2.redshift.amazonaws.com
32
+ user: pg
33
+ password: ""
34
+ database: my_database
35
+ table: my_table
36
+ access_key_id: ABCXYZ123ABCXYZ123
37
+ secret_access_key: AbCxYz123aBcXyZ123
38
+ s3_bucket: my-redshift-transfer-bucket
39
+ iam_user_name: my-s3-read-only
40
+ mode: insert
41
+ ```
42
+
43
+ ### Build
44
+
45
+ ```
46
+ $ ./gradlew gem
47
+ ```
data/build.gradle CHANGED
@@ -1,9 +1,9 @@
1
- dependencies {
2
- compile project(':embulk-output-jdbc')
3
- compile project(':embulk-output-postgresql')
4
-
5
- compile "com.amazonaws:aws-java-sdk-s3:1.9.17"
6
- compile "com.amazonaws:aws-java-sdk-sts:1.9.17"
7
-
8
- testCompile project(':embulk-output-jdbc').sourceSets.test.output
9
- }
1
+ dependencies {
2
+ compile project(':embulk-output-jdbc')
3
+ compile project(':embulk-output-postgresql')
4
+
5
+ compile "com.amazonaws:aws-java-sdk-s3:1.9.17"
6
+ compile "com.amazonaws:aws-java-sdk-sts:1.9.17"
7
+
8
+ testCompile project(':embulk-output-jdbc').sourceSets.test.output
9
+ }
@@ -1,3 +1,3 @@
1
- Embulk::JavaPlugin.register_output(
2
- :redshift, "org.embulk.output.RedshiftOutputPlugin",
3
- File.expand_path('../../../../classpath', __FILE__))
1
+ Embulk::JavaPlugin.register_output(
2
+ :redshift, "org.embulk.output.RedshiftOutputPlugin",
3
+ File.expand_path('../../../../classpath', __FILE__))
@@ -1,216 +1,216 @@
1
- package org.embulk.output.redshift;
2
-
3
- import java.util.zip.GZIPOutputStream;
4
- import java.util.concurrent.Callable;
5
- import java.util.UUID;
6
- import java.io.File;
7
- import java.io.IOException;
8
- import java.io.FileOutputStream;
9
- import java.io.OutputStreamWriter;
10
- import java.io.Closeable;
11
- import java.io.Writer;
12
- import java.io.BufferedWriter;
13
- import java.sql.Connection;
14
- import java.sql.SQLException;
15
- import com.amazonaws.auth.AWSCredentials;
16
- import com.amazonaws.auth.BasicSessionCredentials;
17
- import com.amazonaws.auth.policy.Policy;
18
- import com.amazonaws.auth.policy.Resource;
19
- import com.amazonaws.auth.policy.Statement;
20
- import com.amazonaws.auth.policy.Statement.Effect;
21
- import com.amazonaws.auth.policy.actions.S3Actions;
22
- import com.amazonaws.services.s3.AmazonS3Client;
23
- import com.amazonaws.services.securitytoken.AWSSecurityTokenServiceClient;
24
- import com.amazonaws.services.securitytoken.model.GetFederationTokenRequest;
25
- import com.amazonaws.services.securitytoken.model.GetFederationTokenResult;
26
- import com.amazonaws.services.securitytoken.model.Credentials;
27
- import org.slf4j.Logger;
28
- import org.embulk.spi.Exec;
29
- import org.embulk.output.jdbc.JdbcSchema;
30
- import org.embulk.output.postgresql.AbstractPostgreSQLCopyBatchInsert;
31
-
32
- public class RedshiftCopyBatchInsert
33
- extends AbstractPostgreSQLCopyBatchInsert
34
- {
35
- private final Logger logger = Exec.getLogger(RedshiftCopyBatchInsert.class);
36
- private final RedshiftOutputConnector connector;
37
- private final AWSCredentials awsCredentials;
38
- private final String s3BucketName;
39
- private final String iamReaderUserName;
40
- private final AmazonS3Client s3;
41
- private final AWSSecurityTokenServiceClient sts;
42
-
43
- private RedshiftOutputConnection connection = null;
44
- private String copySqlBeforeFrom = null;
45
- private long totalRows;
46
- private int fileCount;
47
-
48
- public static final String COPY_AFTER_FROM = "GZIP DELIMITER '\\t' NULL '\\N' ESCAPE TRUNCATECOLUMNS ACCEPTINVCHARS STATUPDATE OFF COMPUPDATE OFF";
49
-
50
- public RedshiftCopyBatchInsert(RedshiftOutputConnector connector,
51
- AWSCredentials awsCredentials, String s3BucketName,
52
- String iamReaderUserName) throws IOException, SQLException
53
- {
54
- super();
55
- this.connector = connector;
56
- this.awsCredentials = awsCredentials;
57
- this.s3BucketName = s3BucketName;
58
- this.iamReaderUserName = iamReaderUserName;
59
- this.s3 = new AmazonS3Client(awsCredentials); // TODO options
60
- this.sts = new AWSSecurityTokenServiceClient(awsCredentials); // options
61
- }
62
-
63
- @Override
64
- public void prepare(String loadTable, JdbcSchema insertSchema) throws SQLException
65
- {
66
- this.connection = connector.connect(true);
67
- this.copySqlBeforeFrom = connection.buildCopySQLBeforeFrom(loadTable, insertSchema);
68
- logger.info("Copy SQL: "+copySqlBeforeFrom+" ? "+COPY_AFTER_FROM);
69
- }
70
-
71
- @Override
72
- protected BufferedWriter openWriter(File newFile) throws IOException
73
- {
74
- // Redshift supports gzip
75
- return new BufferedWriter(
76
- new OutputStreamWriter(
77
- new GZIPOutputStream(new FileOutputStream(newFile)),
78
- FILE_CHARSET)
79
- );
80
- }
81
-
82
- @Override
83
- public void flush() throws IOException, SQLException
84
- {
85
- File file = closeCurrentFile(); // flush buffered data in writer
86
-
87
- // TODO multi-threading
88
- new UploadAndCopyTask(file, batchRows, UUID.randomUUID().toString()).call();
89
- new DeleteFileFinalizer(file).close();
90
-
91
- fileCount++;
92
- totalRows += batchRows;
93
- batchRows = 0;
94
-
95
- openNewFile();
96
- file.delete();
97
- }
98
-
99
- @Override
100
- public void finish() throws IOException, SQLException
101
- {
102
- super.finish();
103
- logger.info("Loaded {} files.", fileCount);
104
- }
105
-
106
- @Override
107
- public void close() throws IOException, SQLException
108
- {
109
- s3.shutdown();
110
- closeCurrentFile().delete();
111
- if (connection != null) {
112
- connection.close();
113
- connection = null;
114
- }
115
- }
116
-
117
- private BasicSessionCredentials generateReaderSessionCredentials(String s3KeyName)
118
- {
119
- Policy policy = new Policy()
120
- .withStatements(
121
- new Statement(Effect.Allow)
122
- .withActions(S3Actions.ListObjects)
123
- .withResources(new Resource("arn:aws:s3:::"+s3BucketName)),
124
- new Statement(Effect.Allow)
125
- .withActions(S3Actions.GetObject)
126
- .withResources(new Resource("arn:aws:s3:::"+s3BucketName+"/"+s3KeyName)) // TODO encode file name using percent encoding
127
- );
128
- GetFederationTokenRequest req = new GetFederationTokenRequest();
129
- req.setDurationSeconds(86400); // 3600 - 129600
130
- req.setName(iamReaderUserName);
131
- req.setPolicy(policy.toJson());
132
-
133
- GetFederationTokenResult res = sts.getFederationToken(req);
134
- Credentials c = res.getCredentials();
135
-
136
- return new BasicSessionCredentials(
137
- c.getAccessKeyId(),
138
- c.getSecretAccessKey(),
139
- c.getSessionToken());
140
- }
141
-
142
- private class UploadAndCopyTask implements Callable<Void>
143
- {
144
- private final File file;
145
- private final int batchRows;
146
- private final String s3KeyName;
147
-
148
- public UploadAndCopyTask(File file, int batchRows, String s3KeyName)
149
- {
150
- this.file = file;
151
- this.batchRows = batchRows;
152
- this.s3KeyName = s3KeyName;
153
- }
154
-
155
- public Void call() throws SQLException {
156
- logger.info(String.format("Uploading file id %s to S3 (%,d bytes %,d rows)",
157
- s3KeyName, file.length(), batchRows));
158
- s3.putObject(s3BucketName, s3KeyName, file);
159
-
160
- RedshiftOutputConnection con = connector.connect(true);
161
- try {
162
- logger.info("Running COPY from file {}", s3KeyName);
163
-
164
- // create temporary credential right before COPY operation because
165
- // it has timeout.
166
- // TODO skip this step if iamReaderUserName is not set
167
- BasicSessionCredentials creds = generateReaderSessionCredentials(s3KeyName);
168
-
169
- long startTime = System.currentTimeMillis();
170
- con.runCopy(buildCopySQL(creds));
171
- double seconds = (System.currentTimeMillis() - startTime) / 1000.0;
172
-
173
- logger.info(String.format("Loaded file %s (%.2f seconds for COPY)", s3KeyName, seconds));
174
-
175
- } finally {
176
- con.close();
177
- }
178
-
179
- return null;
180
- }
181
-
182
- private String buildCopySQL(BasicSessionCredentials creds)
183
- {
184
- StringBuilder sb = new StringBuilder();
185
- sb.append(copySqlBeforeFrom);
186
- sb.append(" FROM 's3://");
187
- sb.append(s3BucketName);
188
- sb.append("/");
189
- sb.append(s3KeyName);
190
- sb.append("' CREDENTIALS '");
191
- sb.append("aws_access_key_id=");
192
- sb.append(creds.getAWSAccessKeyId());
193
- sb.append(";aws_secret_access_key=");
194
- sb.append(creds.getAWSSecretKey());
195
- sb.append(";token=");
196
- sb.append(creds.getSessionToken());
197
- sb.append("' ");
198
- sb.append(COPY_AFTER_FROM);
199
- return sb.toString();
200
- }
201
- }
202
-
203
- private static class DeleteFileFinalizer implements Closeable
204
- {
205
- private File file;
206
-
207
- public DeleteFileFinalizer(File file) {
208
- this.file = file;
209
- }
210
-
211
- @Override
212
- public void close() throws IOException {
213
- file.delete();
214
- }
215
- }
216
- }
1
+ package org.embulk.output.redshift;
2
+
3
+ import java.util.zip.GZIPOutputStream;
4
+ import java.util.concurrent.Callable;
5
+ import java.util.UUID;
6
+ import java.io.File;
7
+ import java.io.IOException;
8
+ import java.io.FileOutputStream;
9
+ import java.io.OutputStreamWriter;
10
+ import java.io.Closeable;
11
+ import java.io.Writer;
12
+ import java.io.BufferedWriter;
13
+ import java.sql.Connection;
14
+ import java.sql.SQLException;
15
+ import com.amazonaws.auth.AWSCredentials;
16
+ import com.amazonaws.auth.BasicSessionCredentials;
17
+ import com.amazonaws.auth.policy.Policy;
18
+ import com.amazonaws.auth.policy.Resource;
19
+ import com.amazonaws.auth.policy.Statement;
20
+ import com.amazonaws.auth.policy.Statement.Effect;
21
+ import com.amazonaws.auth.policy.actions.S3Actions;
22
+ import com.amazonaws.services.s3.AmazonS3Client;
23
+ import com.amazonaws.services.securitytoken.AWSSecurityTokenServiceClient;
24
+ import com.amazonaws.services.securitytoken.model.GetFederationTokenRequest;
25
+ import com.amazonaws.services.securitytoken.model.GetFederationTokenResult;
26
+ import com.amazonaws.services.securitytoken.model.Credentials;
27
+ import org.slf4j.Logger;
28
+ import org.embulk.spi.Exec;
29
+ import org.embulk.output.jdbc.JdbcSchema;
30
+ import org.embulk.output.postgresql.AbstractPostgreSQLCopyBatchInsert;
31
+
32
+ public class RedshiftCopyBatchInsert
33
+ extends AbstractPostgreSQLCopyBatchInsert
34
+ {
35
+ private final Logger logger = Exec.getLogger(RedshiftCopyBatchInsert.class);
36
+ private final RedshiftOutputConnector connector;
37
+ private final AWSCredentials awsCredentials;
38
+ private final String s3BucketName;
39
+ private final String iamReaderUserName;
40
+ private final AmazonS3Client s3;
41
+ private final AWSSecurityTokenServiceClient sts;
42
+
43
+ private RedshiftOutputConnection connection = null;
44
+ private String copySqlBeforeFrom = null;
45
+ private long totalRows;
46
+ private int fileCount;
47
+
48
+ public static final String COPY_AFTER_FROM = "GZIP DELIMITER '\\t' NULL '\\N' ESCAPE TRUNCATECOLUMNS ACCEPTINVCHARS STATUPDATE OFF COMPUPDATE OFF";
49
+
50
+ public RedshiftCopyBatchInsert(RedshiftOutputConnector connector,
51
+ AWSCredentials awsCredentials, String s3BucketName,
52
+ String iamReaderUserName) throws IOException, SQLException
53
+ {
54
+ super();
55
+ this.connector = connector;
56
+ this.awsCredentials = awsCredentials;
57
+ this.s3BucketName = s3BucketName;
58
+ this.iamReaderUserName = iamReaderUserName;
59
+ this.s3 = new AmazonS3Client(awsCredentials); // TODO options
60
+ this.sts = new AWSSecurityTokenServiceClient(awsCredentials); // options
61
+ }
62
+
63
+ @Override
64
+ public void prepare(String loadTable, JdbcSchema insertSchema) throws SQLException
65
+ {
66
+ this.connection = connector.connect(true);
67
+ this.copySqlBeforeFrom = connection.buildCopySQLBeforeFrom(loadTable, insertSchema);
68
+ logger.info("Copy SQL: "+copySqlBeforeFrom+" ? "+COPY_AFTER_FROM);
69
+ }
70
+
71
+ @Override
72
+ protected BufferedWriter openWriter(File newFile) throws IOException
73
+ {
74
+ // Redshift supports gzip
75
+ return new BufferedWriter(
76
+ new OutputStreamWriter(
77
+ new GZIPOutputStream(new FileOutputStream(newFile)),
78
+ FILE_CHARSET)
79
+ );
80
+ }
81
+
82
+ @Override
83
+ public void flush() throws IOException, SQLException
84
+ {
85
+ File file = closeCurrentFile(); // flush buffered data in writer
86
+
87
+ // TODO multi-threading
88
+ new UploadAndCopyTask(file, batchRows, UUID.randomUUID().toString()).call();
89
+ new DeleteFileFinalizer(file).close();
90
+
91
+ fileCount++;
92
+ totalRows += batchRows;
93
+ batchRows = 0;
94
+
95
+ openNewFile();
96
+ file.delete();
97
+ }
98
+
99
+ @Override
100
+ public void finish() throws IOException, SQLException
101
+ {
102
+ super.finish();
103
+ logger.info("Loaded {} files.", fileCount);
104
+ }
105
+
106
+ @Override
107
+ public void close() throws IOException, SQLException
108
+ {
109
+ s3.shutdown();
110
+ closeCurrentFile().delete();
111
+ if (connection != null) {
112
+ connection.close();
113
+ connection = null;
114
+ }
115
+ }
116
+
117
+ private BasicSessionCredentials generateReaderSessionCredentials(String s3KeyName)
118
+ {
119
+ Policy policy = new Policy()
120
+ .withStatements(
121
+ new Statement(Effect.Allow)
122
+ .withActions(S3Actions.ListObjects)
123
+ .withResources(new Resource("arn:aws:s3:::"+s3BucketName)),
124
+ new Statement(Effect.Allow)
125
+ .withActions(S3Actions.GetObject)
126
+ .withResources(new Resource("arn:aws:s3:::"+s3BucketName+"/"+s3KeyName)) // TODO encode file name using percent encoding
127
+ );
128
+ GetFederationTokenRequest req = new GetFederationTokenRequest();
129
+ req.setDurationSeconds(86400); // 3600 - 129600
130
+ req.setName(iamReaderUserName);
131
+ req.setPolicy(policy.toJson());
132
+
133
+ GetFederationTokenResult res = sts.getFederationToken(req);
134
+ Credentials c = res.getCredentials();
135
+
136
+ return new BasicSessionCredentials(
137
+ c.getAccessKeyId(),
138
+ c.getSecretAccessKey(),
139
+ c.getSessionToken());
140
+ }
141
+
142
+ private class UploadAndCopyTask implements Callable<Void>
143
+ {
144
+ private final File file;
145
+ private final int batchRows;
146
+ private final String s3KeyName;
147
+
148
+ public UploadAndCopyTask(File file, int batchRows, String s3KeyName)
149
+ {
150
+ this.file = file;
151
+ this.batchRows = batchRows;
152
+ this.s3KeyName = s3KeyName;
153
+ }
154
+
155
+ public Void call() throws SQLException {
156
+ logger.info(String.format("Uploading file id %s to S3 (%,d bytes %,d rows)",
157
+ s3KeyName, file.length(), batchRows));
158
+ s3.putObject(s3BucketName, s3KeyName, file);
159
+
160
+ RedshiftOutputConnection con = connector.connect(true);
161
+ try {
162
+ logger.info("Running COPY from file {}", s3KeyName);
163
+
164
+ // create temporary credential right before COPY operation because
165
+ // it has timeout.
166
+ // TODO skip this step if iamReaderUserName is not set
167
+ BasicSessionCredentials creds = generateReaderSessionCredentials(s3KeyName);
168
+
169
+ long startTime = System.currentTimeMillis();
170
+ con.runCopy(buildCopySQL(creds));
171
+ double seconds = (System.currentTimeMillis() - startTime) / 1000.0;
172
+
173
+ logger.info(String.format("Loaded file %s (%.2f seconds for COPY)", s3KeyName, seconds));
174
+
175
+ } finally {
176
+ con.close();
177
+ }
178
+
179
+ return null;
180
+ }
181
+
182
+ private String buildCopySQL(BasicSessionCredentials creds)
183
+ {
184
+ StringBuilder sb = new StringBuilder();
185
+ sb.append(copySqlBeforeFrom);
186
+ sb.append(" FROM 's3://");
187
+ sb.append(s3BucketName);
188
+ sb.append("/");
189
+ sb.append(s3KeyName);
190
+ sb.append("' CREDENTIALS '");
191
+ sb.append("aws_access_key_id=");
192
+ sb.append(creds.getAWSAccessKeyId());
193
+ sb.append(";aws_secret_access_key=");
194
+ sb.append(creds.getAWSSecretKey());
195
+ sb.append(";token=");
196
+ sb.append(creds.getSessionToken());
197
+ sb.append("' ");
198
+ sb.append(COPY_AFTER_FROM);
199
+ return sb.toString();
200
+ }
201
+ }
202
+
203
+ private static class DeleteFileFinalizer implements Closeable
204
+ {
205
+ private File file;
206
+
207
+ public DeleteFileFinalizer(File file) {
208
+ this.file = file;
209
+ }
210
+
211
+ @Override
212
+ public void close() throws IOException {
213
+ file.delete();
214
+ }
215
+ }
216
+ }
@@ -1,122 +1,122 @@
1
- package org.embulk.output.redshift;
2
-
3
- import java.sql.Connection;
4
- import java.sql.SQLException;
5
- import java.sql.Statement;
6
- import org.slf4j.Logger;
7
- import org.embulk.spi.Exec;
8
- import org.embulk.output.jdbc.JdbcOutputConnection;
9
- import org.embulk.output.jdbc.JdbcColumn;
10
- import org.embulk.output.jdbc.JdbcSchema;
11
-
12
- public class RedshiftOutputConnection
13
- extends JdbcOutputConnection
14
- {
15
- private final Logger logger = Exec.getLogger(RedshiftOutputConnection.class);
16
-
17
- public RedshiftOutputConnection(Connection connection, String schemaName, boolean autoCommit)
18
- throws SQLException
19
- {
20
- super(connection, schemaName);
21
- connection.setAutoCommit(autoCommit);
22
- }
23
-
24
- // Redshift does not support DROP TABLE IF EXISTS.
25
- // Here runs DROP TABLE and ignores errors.
26
- @Override
27
- public void dropTableIfExists(String tableName) throws SQLException
28
- {
29
- Statement stmt = connection.createStatement();
30
- try {
31
- String sql = String.format("DROP TABLE IF EXISTS %s", quoteIdentifierString(tableName));
32
- executeUpdate(stmt, sql);
33
- commitIfNecessary(connection);
34
- } catch (SQLException ex) {
35
- // ignore errors.
36
- // TODO here should ignore only 'table "XXX" does not exist' errors.
37
- SQLException ignored = safeRollback(connection, ex);
38
- } finally {
39
- stmt.close();
40
- }
41
- }
42
-
43
- // Redshift does not support DROP TABLE IF EXISTS.
44
- // Dropping part runs DROP TABLE and ignores errors.
45
- @Override
46
- public void replaceTable(String fromTable, JdbcSchema schema, String toTable) throws SQLException
47
- {
48
- Statement stmt = connection.createStatement();
49
- try {
50
- try {
51
- StringBuilder sb = new StringBuilder();
52
- sb.append("DROP TABLE ");
53
- quoteIdentifierString(sb, toTable);
54
- String sql = sb.toString();
55
- executeUpdate(stmt, sql);
56
- } catch (SQLException ex) {
57
- // ignore errors.
58
- // TODO here should ignore only 'table "XXX" does not exist' errors.
59
- // rollback or comimt is required to recover failed transaction
60
- SQLException ignored = safeRollback(connection, ex);
61
- }
62
-
63
- {
64
- StringBuilder sb = new StringBuilder();
65
- sb.append("ALTER TABLE ");
66
- quoteIdentifierString(sb, fromTable);
67
- sb.append(" RENAME TO ");
68
- quoteIdentifierString(sb, toTable);
69
- String sql = sb.toString();
70
- executeUpdate(stmt, sql);
71
- }
72
-
73
- commitIfNecessary(connection);
74
- } catch (SQLException ex) {
75
- throw safeRollback(connection, ex);
76
- } finally {
77
- stmt.close();
78
- }
79
- }
80
-
81
- @Override
82
- protected String convertTypeName(String typeName)
83
- {
84
- // Redshift does not support TEXT type.
85
- switch(typeName) {
86
- case "CLOB":
87
- return "VARCHAR(65535)";
88
- case "TEXT":
89
- return "VARCHAR(65535)";
90
- case "BLOB":
91
- return "BYTEA";
92
- default:
93
- return typeName;
94
- }
95
- }
96
-
97
- public String buildCopySQLBeforeFrom(String tableName, JdbcSchema tableSchema)
98
- {
99
- StringBuilder sb = new StringBuilder();
100
-
101
- sb.append("COPY ");
102
- quoteIdentifierString(sb, tableName);
103
- sb.append(" (");
104
- for(int i=0; i < tableSchema.getCount(); i++) {
105
- if(i != 0) { sb.append(", "); }
106
- quoteIdentifierString(sb, tableSchema.getColumnName(i));
107
- }
108
- sb.append(")");
109
-
110
- return sb.toString();
111
- }
112
-
113
- public void runCopy(String sql) throws SQLException
114
- {
115
- Statement stmt = connection.createStatement();
116
- try {
117
- stmt.executeUpdate(sql);
118
- } finally {
119
- stmt.close();
120
- }
121
- }
122
- }
1
+ package org.embulk.output.redshift;
2
+
3
+ import java.sql.Connection;
4
+ import java.sql.SQLException;
5
+ import java.sql.Statement;
6
+ import org.slf4j.Logger;
7
+ import org.embulk.spi.Exec;
8
+ import org.embulk.output.jdbc.JdbcOutputConnection;
9
+ import org.embulk.output.jdbc.JdbcColumn;
10
+ import org.embulk.output.jdbc.JdbcSchema;
11
+
12
+ public class RedshiftOutputConnection
13
+ extends JdbcOutputConnection
14
+ {
15
+ private final Logger logger = Exec.getLogger(RedshiftOutputConnection.class);
16
+
17
+ public RedshiftOutputConnection(Connection connection, String schemaName, boolean autoCommit)
18
+ throws SQLException
19
+ {
20
+ super(connection, schemaName);
21
+ connection.setAutoCommit(autoCommit);
22
+ }
23
+
24
+ // Redshift does not support DROP TABLE IF EXISTS.
25
+ // Here runs DROP TABLE and ignores errors.
26
+ @Override
27
+ public void dropTableIfExists(String tableName) throws SQLException
28
+ {
29
+ Statement stmt = connection.createStatement();
30
+ try {
31
+ String sql = String.format("DROP TABLE IF EXISTS %s", quoteIdentifierString(tableName));
32
+ executeUpdate(stmt, sql);
33
+ commitIfNecessary(connection);
34
+ } catch (SQLException ex) {
35
+ // ignore errors.
36
+ // TODO here should ignore only 'table "XXX" does not exist' errors.
37
+ SQLException ignored = safeRollback(connection, ex);
38
+ } finally {
39
+ stmt.close();
40
+ }
41
+ }
42
+
43
+ // Redshift does not support DROP TABLE IF EXISTS.
44
+ // Dropping part runs DROP TABLE and ignores errors.
45
+ @Override
46
+ public void replaceTable(String fromTable, JdbcSchema schema, String toTable) throws SQLException
47
+ {
48
+ Statement stmt = connection.createStatement();
49
+ try {
50
+ try {
51
+ StringBuilder sb = new StringBuilder();
52
+ sb.append("DROP TABLE ");
53
+ quoteIdentifierString(sb, toTable);
54
+ String sql = sb.toString();
55
+ executeUpdate(stmt, sql);
56
+ } catch (SQLException ex) {
57
+ // ignore errors.
58
+ // TODO here should ignore only 'table "XXX" does not exist' errors.
59
+ // rollback or comimt is required to recover failed transaction
60
+ SQLException ignored = safeRollback(connection, ex);
61
+ }
62
+
63
+ {
64
+ StringBuilder sb = new StringBuilder();
65
+ sb.append("ALTER TABLE ");
66
+ quoteIdentifierString(sb, fromTable);
67
+ sb.append(" RENAME TO ");
68
+ quoteIdentifierString(sb, toTable);
69
+ String sql = sb.toString();
70
+ executeUpdate(stmt, sql);
71
+ }
72
+
73
+ commitIfNecessary(connection);
74
+ } catch (SQLException ex) {
75
+ throw safeRollback(connection, ex);
76
+ } finally {
77
+ stmt.close();
78
+ }
79
+ }
80
+
81
+ @Override
82
+ protected String convertTypeName(String typeName)
83
+ {
84
+ // Redshift does not support TEXT type.
85
+ switch(typeName) {
86
+ case "CLOB":
87
+ return "VARCHAR(65535)";
88
+ case "TEXT":
89
+ return "VARCHAR(65535)";
90
+ case "BLOB":
91
+ return "BYTEA";
92
+ default:
93
+ return typeName;
94
+ }
95
+ }
96
+
97
+ public String buildCopySQLBeforeFrom(String tableName, JdbcSchema tableSchema)
98
+ {
99
+ StringBuilder sb = new StringBuilder();
100
+
101
+ sb.append("COPY ");
102
+ quoteIdentifierString(sb, tableName);
103
+ sb.append(" (");
104
+ for(int i=0; i < tableSchema.getCount(); i++) {
105
+ if(i != 0) { sb.append(", "); }
106
+ quoteIdentifierString(sb, tableSchema.getColumnName(i));
107
+ }
108
+ sb.append(")");
109
+
110
+ return sb.toString();
111
+ }
112
+
113
+ public void runCopy(String sql) throws SQLException
114
+ {
115
+ Statement stmt = connection.createStatement();
116
+ try {
117
+ stmt.executeUpdate(sql);
118
+ } finally {
119
+ stmt.close();
120
+ }
121
+ }
122
+ }
@@ -1,40 +1,40 @@
1
- package org.embulk.output.redshift;
2
-
3
- import java.util.Properties;
4
- import java.sql.Driver;
5
- import java.sql.Connection;
6
- import java.sql.SQLException;
7
- import org.embulk.output.jdbc.JdbcOutputConnector;
8
- import org.embulk.output.jdbc.JdbcOutputConnection;
9
-
10
- public class RedshiftOutputConnector
11
- implements JdbcOutputConnector
12
- {
13
- private static final Driver driver = new org.postgresql.Driver();
14
-
15
- private final String url;
16
- private final Properties properties;
17
- private final String schemaName;
18
-
19
- public RedshiftOutputConnector(String url, Properties properties, String schemaName)
20
- {
21
- this.url = url;
22
- this.properties = properties;
23
- this.schemaName = schemaName;
24
- }
25
-
26
- @Override
27
- public RedshiftOutputConnection connect(boolean autoCommit) throws SQLException
28
- {
29
- Connection c = driver.connect(url, properties);
30
- try {
31
- RedshiftOutputConnection con = new RedshiftOutputConnection(c, schemaName, autoCommit);
32
- c = null;
33
- return con;
34
- } finally {
35
- if (c != null) {
36
- c.close();
37
- }
38
- }
39
- }
40
- }
1
+ package org.embulk.output.redshift;
2
+
3
+ import java.util.Properties;
4
+ import java.sql.Driver;
5
+ import java.sql.Connection;
6
+ import java.sql.SQLException;
7
+ import org.embulk.output.jdbc.JdbcOutputConnector;
8
+ import org.embulk.output.jdbc.JdbcOutputConnection;
9
+
10
+ public class RedshiftOutputConnector
11
+ implements JdbcOutputConnector
12
+ {
13
+ private static final Driver driver = new org.postgresql.Driver();
14
+
15
+ private final String url;
16
+ private final Properties properties;
17
+ private final String schemaName;
18
+
19
+ public RedshiftOutputConnector(String url, Properties properties, String schemaName)
20
+ {
21
+ this.url = url;
22
+ this.properties = properties;
23
+ this.schemaName = schemaName;
24
+ }
25
+
26
+ @Override
27
+ public RedshiftOutputConnection connect(boolean autoCommit) throws SQLException
28
+ {
29
+ Connection c = driver.connect(url, properties);
30
+ try {
31
+ RedshiftOutputConnection con = new RedshiftOutputConnection(c, schemaName, autoCommit);
32
+ c = null;
33
+ return con;
34
+ } finally {
35
+ if (c != null) {
36
+ c.close();
37
+ }
38
+ }
39
+ }
40
+ }
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: embulk-output-redshift
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.3
4
+ version: 0.2.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sadayuki Furuhashi
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-04-23 00:00:00.000000000 Z
11
+ date: 2015-05-12 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: Inserts or updates records to a table.
14
14
  email:
@@ -24,21 +24,21 @@ files:
24
24
  - src/main/java/org/embulk/output/redshift/RedshiftCopyBatchInsert.java
25
25
  - src/main/java/org/embulk/output/redshift/RedshiftOutputConnection.java
26
26
  - src/main/java/org/embulk/output/redshift/RedshiftOutputConnector.java
27
- - classpath/embulk-output-jdbc-0.2.3.jar
28
- - classpath/commons-logging-1.1.3.jar
29
- - classpath/httpcore-4.3.2.jar
30
- - classpath/postgresql-9.4-1200-jdbc41.jar
27
+ - classpath/aws-java-sdk-core-1.9.17.jar
31
28
  - classpath/aws-java-sdk-kms-1.9.17.jar
32
- - classpath/embulk-output-postgresql-0.2.3.jar
33
- - classpath/aws-java-sdk-sts-1.9.17.jar
34
- - classpath/embulk-output-redshift-0.2.3.jar
35
29
  - classpath/aws-java-sdk-s3-1.9.17.jar
36
- - classpath/slf4j-simple-1.7.7.jar
37
- - classpath/aws-java-sdk-core-1.9.17.jar
38
- - classpath/jna-platform-4.1.0.jar
30
+ - classpath/aws-java-sdk-sts-1.9.17.jar
31
+ - classpath/commons-codec-1.6.jar
32
+ - classpath/commons-logging-1.1.3.jar
33
+ - classpath/embulk-output-jdbc-0.2.4.jar
34
+ - classpath/embulk-output-postgresql-0.2.4.jar
35
+ - classpath/embulk-output-redshift-0.2.4.jar
39
36
  - classpath/httpclient-4.3.4.jar
37
+ - classpath/httpcore-4.3.2.jar
40
38
  - classpath/jna-4.1.0.jar
41
- - classpath/commons-codec-1.6.jar
39
+ - classpath/jna-platform-4.1.0.jar
40
+ - classpath/postgresql-9.4-1200-jdbc41.jar
41
+ - classpath/slf4j-simple-1.7.7.jar
42
42
  - classpath/waffle-jna-1.7.jar
43
43
  homepage: https://github.com/embulk/embulk-output-jdbc
44
44
  licenses: