embulk-output-postgresql 0.4.0 → 0.4.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,245 +1,245 @@
1
- package org.embulk.output.postgresql;
2
-
3
- import java.util.Calendar;
4
- import java.util.Locale;
5
- import java.io.File;
6
- import java.io.FileOutputStream;
7
- import java.io.Writer;
8
- import java.io.BufferedWriter;
9
- import java.io.OutputStreamWriter;
10
- import java.io.IOException;
11
- import java.nio.charset.Charset;
12
- import java.math.BigDecimal;
13
- import java.sql.Date;
14
- import java.sql.Time;
15
- import java.sql.SQLException;
16
- import org.embulk.spi.time.Timestamp;
17
- import org.embulk.output.jdbc.BatchInsert;
18
-
19
- public abstract class AbstractPostgreSQLCopyBatchInsert
20
- implements BatchInsert
21
- {
22
- protected static final Charset FILE_CHARSET = Charset.forName("UTF-8");
23
-
24
- protected static final String nullString = "\\N";
25
- protected static final String newLineString = "\n";
26
- protected static final String delimiterString = "\t";
27
-
28
- protected File currentFile;
29
- protected BufferedWriter writer;
30
- protected int index;
31
- protected int batchRows;
32
-
33
- protected AbstractPostgreSQLCopyBatchInsert() throws IOException
34
- {
35
- this.index = 0;
36
- openNewFile();
37
- }
38
-
39
- private File createTempFile() throws IOException
40
- {
41
- return File.createTempFile("embulk-output-postgres-copy-", ".tsv.tmp"); // TODO configurable temporary file path
42
- }
43
-
44
- protected File openNewFile() throws IOException
45
- {
46
- File newFile = createTempFile();
47
- File oldFile = closeCurrentFile();
48
- this.writer = openWriter(newFile);
49
- currentFile = newFile;
50
- return oldFile;
51
- }
52
-
53
- protected File closeCurrentFile() throws IOException
54
- {
55
- if(writer != null) {
56
- writer.close();
57
- writer = null;
58
- }
59
- return currentFile;
60
- }
61
-
62
- protected BufferedWriter openWriter(File newFile) throws IOException
63
- {
64
- return new BufferedWriter(new OutputStreamWriter(new FileOutputStream(newFile), FILE_CHARSET));
65
- }
66
-
67
- public int getBatchWeight()
68
- {
69
- long fsize = currentFile.length();
70
- if (fsize > Integer.MAX_VALUE) {
71
- return Integer.MAX_VALUE;
72
- } else {
73
- return (int) fsize;
74
- }
75
- }
76
-
77
- public void finish() throws IOException, SQLException
78
- {
79
- closeCurrentFile(); // this is necessary to make getBatchWeight() work
80
- if (getBatchWeight() != 0) {
81
- flush();
82
- }
83
- }
84
-
85
- public void add() throws IOException
86
- {
87
- writer.write(newLineString);
88
- batchRows++;
89
- index = 0;
90
- }
91
-
92
- private void appendDelimiter() throws IOException
93
- {
94
- if(index != 0) {
95
- writer.write(delimiterString);
96
- }
97
- index++;
98
- }
99
-
100
- public void setNull(int sqlType) throws IOException
101
- {
102
- appendDelimiter();
103
- writer.write(nullString);
104
- }
105
-
106
- public void setBoolean(boolean v) throws IOException
107
- {
108
- appendDelimiter();
109
- writer.write(String.valueOf(v));
110
- }
111
-
112
- public void setByte(byte v) throws IOException
113
- {
114
- appendDelimiter();
115
- setEscapedString(String.valueOf(v));
116
- }
117
-
118
- public void setShort(short v) throws IOException
119
- {
120
- appendDelimiter();
121
- writer.write(String.valueOf(v));
122
- }
123
-
124
- public void setInt(int v) throws IOException
125
- {
126
- appendDelimiter();
127
- writer.write(String.valueOf(v));
128
- }
129
-
130
- public void setLong(long v) throws IOException
131
- {
132
- appendDelimiter();
133
- writer.write(String.valueOf(v));
134
- }
135
-
136
- public void setFloat(float v) throws IOException
137
- {
138
- appendDelimiter();
139
- writer.write(String.valueOf(v));
140
- }
141
-
142
- public void setDouble(double v) throws IOException
143
- {
144
- appendDelimiter();
145
- writer.write(String.valueOf(v));
146
- }
147
-
148
- public void setBigDecimal(BigDecimal v) throws IOException
149
- {
150
- appendDelimiter();
151
- writer.write(String.valueOf(v));
152
- }
153
-
154
- public void setString(String v) throws IOException
155
- {
156
- appendDelimiter();
157
- setEscapedString(v);
158
- }
159
-
160
- public void setNString(String v) throws IOException
161
- {
162
- appendDelimiter();
163
- setEscapedString(v);
164
- }
165
-
166
- public void setBytes(byte[] v) throws IOException
167
- {
168
- appendDelimiter();
169
- setEscapedString(String.valueOf(v));
170
- }
171
-
172
- public void setSqlDate(Timestamp v, Calendar cal) throws IOException
173
- {
174
- appendDelimiter();
175
- cal.setTimeInMillis(v.getEpochSecond() * 1000);
176
- String f = String.format(Locale.ENGLISH, "%02d-%02d-%02d",
177
- cal.get(Calendar.YEAR),
178
- cal.get(Calendar.MONTH) + 1,
179
- cal.get(Calendar.DAY_OF_MONTH));
180
- writer.write(f);
181
- }
182
-
183
- public void setSqlTime(Timestamp v, Calendar cal) throws IOException
184
- {
185
- appendDelimiter();
186
- cal.setTimeInMillis(v.getEpochSecond() * 1000);
187
- String f = String.format(Locale.ENGLISH, "%02d:%02d:%02d.%06d",
188
- cal.get(Calendar.HOUR_OF_DAY),
189
- cal.get(Calendar.MINUTE),
190
- cal.get(Calendar.SECOND),
191
- v.getNano() / 1000);
192
- writer.write(f);
193
- }
194
-
195
- public void setSqlTimestamp(Timestamp v, Calendar cal) throws IOException
196
- {
197
- appendDelimiter();
198
- cal.setTimeInMillis(v.getEpochSecond() * 1000);
199
- int zoneOffset = cal.get(Calendar.ZONE_OFFSET) / 1000 / 60; // zone offset considering DST in minute
200
- String offset;
201
- if (zoneOffset >= 0) {
202
- offset = String.format(Locale.ENGLISH, "+%02d%02d", zoneOffset / 60, zoneOffset % 60);
203
- } else {
204
- offset = String.format(Locale.ENGLISH, "-%02d%02d", -zoneOffset / 60, -zoneOffset % 60);
205
- }
206
- String f = String.format(Locale.ENGLISH, "%d-%02d-%02d %02d:%02d:%02d.%06d%s",
207
- cal.get(Calendar.YEAR),
208
- cal.get(Calendar.MONTH) + 1,
209
- cal.get(Calendar.DAY_OF_MONTH),
210
- cal.get(Calendar.HOUR_OF_DAY),
211
- cal.get(Calendar.MINUTE),
212
- cal.get(Calendar.SECOND),
213
- v.getNano() / 1000,
214
- offset);
215
- writer.write(f);
216
- }
217
-
218
- // Escape \, \n, \t, \r
219
- // Remove \0
220
- private void setEscapedString(String v) throws IOException{
221
- for (char c : v.toCharArray()) {
222
- String s;
223
- switch (c) {
224
- case '\\':
225
- s = "\\\\";
226
- break;
227
- case '\n':
228
- s = "\\n";
229
- break;
230
- case '\t':
231
- s = "\\t";
232
- break;
233
- case '\r':
234
- s = "\\r";
235
- break;
236
- case 0:
237
- s = "";
238
- break;
239
- default:
240
- s = String.valueOf(c);
241
- }
242
- writer.write(s);
243
- }
244
- }
245
- }
1
+ package org.embulk.output.postgresql;
2
+
3
+ import java.util.Calendar;
4
+ import java.util.Locale;
5
+ import java.io.File;
6
+ import java.io.FileOutputStream;
7
+ import java.io.Writer;
8
+ import java.io.BufferedWriter;
9
+ import java.io.OutputStreamWriter;
10
+ import java.io.IOException;
11
+ import java.nio.charset.Charset;
12
+ import java.math.BigDecimal;
13
+ import java.sql.Date;
14
+ import java.sql.Time;
15
+ import java.sql.SQLException;
16
+ import org.embulk.spi.time.Timestamp;
17
+ import org.embulk.output.jdbc.BatchInsert;
18
+
19
+ public abstract class AbstractPostgreSQLCopyBatchInsert
20
+ implements BatchInsert
21
+ {
22
+ protected static final Charset FILE_CHARSET = Charset.forName("UTF-8");
23
+
24
+ protected static final String nullString = "\\N";
25
+ protected static final String newLineString = "\n";
26
+ protected static final String delimiterString = "\t";
27
+
28
+ protected File currentFile;
29
+ protected BufferedWriter writer;
30
+ protected int index;
31
+ protected int batchRows;
32
+
33
+ protected AbstractPostgreSQLCopyBatchInsert() throws IOException
34
+ {
35
+ this.index = 0;
36
+ openNewFile();
37
+ }
38
+
39
+ private File createTempFile() throws IOException
40
+ {
41
+ return File.createTempFile("embulk-output-postgres-copy-", ".tsv.tmp"); // TODO configurable temporary file path
42
+ }
43
+
44
+ protected File openNewFile() throws IOException
45
+ {
46
+ File newFile = createTempFile();
47
+ File oldFile = closeCurrentFile();
48
+ this.writer = openWriter(newFile);
49
+ currentFile = newFile;
50
+ return oldFile;
51
+ }
52
+
53
+ protected File closeCurrentFile() throws IOException
54
+ {
55
+ if(writer != null) {
56
+ writer.close();
57
+ writer = null;
58
+ }
59
+ return currentFile;
60
+ }
61
+
62
+ protected BufferedWriter openWriter(File newFile) throws IOException
63
+ {
64
+ return new BufferedWriter(new OutputStreamWriter(new FileOutputStream(newFile), FILE_CHARSET));
65
+ }
66
+
67
+ public int getBatchWeight()
68
+ {
69
+ long fsize = currentFile.length();
70
+ if (fsize > Integer.MAX_VALUE) {
71
+ return Integer.MAX_VALUE;
72
+ } else {
73
+ return (int) fsize;
74
+ }
75
+ }
76
+
77
+ public void finish() throws IOException, SQLException
78
+ {
79
+ closeCurrentFile(); // this is necessary to make getBatchWeight() work
80
+ if (getBatchWeight() != 0) {
81
+ flush();
82
+ }
83
+ }
84
+
85
+ public void add() throws IOException
86
+ {
87
+ writer.write(newLineString);
88
+ batchRows++;
89
+ index = 0;
90
+ }
91
+
92
+ private void appendDelimiter() throws IOException
93
+ {
94
+ if(index != 0) {
95
+ writer.write(delimiterString);
96
+ }
97
+ index++;
98
+ }
99
+
100
+ public void setNull(int sqlType) throws IOException
101
+ {
102
+ appendDelimiter();
103
+ writer.write(nullString);
104
+ }
105
+
106
+ public void setBoolean(boolean v) throws IOException
107
+ {
108
+ appendDelimiter();
109
+ writer.write(String.valueOf(v));
110
+ }
111
+
112
+ public void setByte(byte v) throws IOException
113
+ {
114
+ appendDelimiter();
115
+ setEscapedString(String.valueOf(v));
116
+ }
117
+
118
+ public void setShort(short v) throws IOException
119
+ {
120
+ appendDelimiter();
121
+ writer.write(String.valueOf(v));
122
+ }
123
+
124
+ public void setInt(int v) throws IOException
125
+ {
126
+ appendDelimiter();
127
+ writer.write(String.valueOf(v));
128
+ }
129
+
130
+ public void setLong(long v) throws IOException
131
+ {
132
+ appendDelimiter();
133
+ writer.write(String.valueOf(v));
134
+ }
135
+
136
+ public void setFloat(float v) throws IOException
137
+ {
138
+ appendDelimiter();
139
+ writer.write(String.valueOf(v));
140
+ }
141
+
142
+ public void setDouble(double v) throws IOException
143
+ {
144
+ appendDelimiter();
145
+ writer.write(String.valueOf(v));
146
+ }
147
+
148
+ public void setBigDecimal(BigDecimal v) throws IOException
149
+ {
150
+ appendDelimiter();
151
+ writer.write(String.valueOf(v));
152
+ }
153
+
154
+ public void setString(String v) throws IOException
155
+ {
156
+ appendDelimiter();
157
+ setEscapedString(v);
158
+ }
159
+
160
+ public void setNString(String v) throws IOException
161
+ {
162
+ appendDelimiter();
163
+ setEscapedString(v);
164
+ }
165
+
166
+ public void setBytes(byte[] v) throws IOException
167
+ {
168
+ appendDelimiter();
169
+ setEscapedString(String.valueOf(v));
170
+ }
171
+
172
+ public void setSqlDate(Timestamp v, Calendar cal) throws IOException
173
+ {
174
+ appendDelimiter();
175
+ cal.setTimeInMillis(v.getEpochSecond() * 1000);
176
+ String f = String.format(Locale.ENGLISH, "%02d-%02d-%02d",
177
+ cal.get(Calendar.YEAR),
178
+ cal.get(Calendar.MONTH) + 1,
179
+ cal.get(Calendar.DAY_OF_MONTH));
180
+ writer.write(f);
181
+ }
182
+
183
+ public void setSqlTime(Timestamp v, Calendar cal) throws IOException
184
+ {
185
+ appendDelimiter();
186
+ cal.setTimeInMillis(v.getEpochSecond() * 1000);
187
+ String f = String.format(Locale.ENGLISH, "%02d:%02d:%02d.%06d",
188
+ cal.get(Calendar.HOUR_OF_DAY),
189
+ cal.get(Calendar.MINUTE),
190
+ cal.get(Calendar.SECOND),
191
+ v.getNano() / 1000);
192
+ writer.write(f);
193
+ }
194
+
195
+ public void setSqlTimestamp(Timestamp v, Calendar cal) throws IOException
196
+ {
197
+ appendDelimiter();
198
+ cal.setTimeInMillis(v.getEpochSecond() * 1000);
199
+ int zoneOffset = cal.get(Calendar.ZONE_OFFSET) / 1000 / 60; // zone offset considering DST in minute
200
+ String offset;
201
+ if (zoneOffset >= 0) {
202
+ offset = String.format(Locale.ENGLISH, "+%02d%02d", zoneOffset / 60, zoneOffset % 60);
203
+ } else {
204
+ offset = String.format(Locale.ENGLISH, "-%02d%02d", -zoneOffset / 60, -zoneOffset % 60);
205
+ }
206
+ String f = String.format(Locale.ENGLISH, "%d-%02d-%02d %02d:%02d:%02d.%06d%s",
207
+ cal.get(Calendar.YEAR),
208
+ cal.get(Calendar.MONTH) + 1,
209
+ cal.get(Calendar.DAY_OF_MONTH),
210
+ cal.get(Calendar.HOUR_OF_DAY),
211
+ cal.get(Calendar.MINUTE),
212
+ cal.get(Calendar.SECOND),
213
+ v.getNano() / 1000,
214
+ offset);
215
+ writer.write(f);
216
+ }
217
+
218
+ // Escape \, \n, \t, \r
219
+ // Remove \0
220
+ private void setEscapedString(String v) throws IOException{
221
+ for (char c : v.toCharArray()) {
222
+ String s;
223
+ switch (c) {
224
+ case '\\':
225
+ s = "\\\\";
226
+ break;
227
+ case '\n':
228
+ s = "\\n";
229
+ break;
230
+ case '\t':
231
+ s = "\\t";
232
+ break;
233
+ case '\r':
234
+ s = "\\r";
235
+ break;
236
+ case 0:
237
+ s = "";
238
+ break;
239
+ default:
240
+ s = String.valueOf(c);
241
+ }
242
+ writer.write(s);
243
+ }
244
+ }
245
+ }
@@ -1,73 +1,73 @@
1
- package org.embulk.output.postgresql;
2
-
3
- import java.io.File;
4
- import java.io.IOException;
5
- import java.io.FileInputStream;
6
- import java.sql.Connection;
7
- import java.sql.SQLException;
8
- import org.slf4j.Logger;
9
- import org.postgresql.copy.CopyManager;
10
- import org.postgresql.core.BaseConnection;
11
- import org.embulk.spi.Exec;
12
- import org.embulk.output.jdbc.JdbcSchema;
13
-
14
- public class PostgreSQLCopyBatchInsert
15
- extends AbstractPostgreSQLCopyBatchInsert
16
- {
17
- private final Logger logger = Exec.getLogger(PostgreSQLCopyBatchInsert.class);
18
- private final PostgreSQLOutputConnector connector;
19
-
20
- private PostgreSQLOutputConnection connection = null;
21
- private CopyManager copyManager = null;
22
- private String copySql = null;
23
- private long totalRows;
24
-
25
- public PostgreSQLCopyBatchInsert(PostgreSQLOutputConnector connector) throws IOException, SQLException
26
- {
27
- super();
28
- this.connector = connector;
29
- }
30
-
31
- @Override
32
- public void prepare(String loadTable, JdbcSchema insertSchema) throws SQLException
33
- {
34
- this.connection = connector.connect(true);
35
- this.copySql = connection.buildCopySql(loadTable, insertSchema);
36
- this.copyManager = connection.newCopyManager();
37
- logger.info("Copy SQL: "+copySql);
38
- }
39
-
40
- @Override
41
- public void flush() throws IOException, SQLException
42
- {
43
- File file = closeCurrentFile(); // flush buffered data in writer
44
-
45
- logger.info(String.format("Loading %,d rows (%,d bytes)", batchRows, file.length()));
46
- long startTime = System.currentTimeMillis();
47
- FileInputStream in = new FileInputStream(file);
48
- try {
49
- // TODO check age of connection and call isValid if it's old and reconnect if it's invalid
50
- copyManager.copyIn(copySql, in);
51
- } finally {
52
- in.close();
53
- }
54
- double seconds = (System.currentTimeMillis() - startTime) / 1000.0;
55
-
56
- totalRows += batchRows;
57
- batchRows = 0;
58
- logger.info(String.format("> %.2f seconds (loaded %,d rows in total)", seconds, totalRows));
59
-
60
- openNewFile();
61
- file.delete();
62
- }
63
-
64
- @Override
65
- public void close() throws IOException, SQLException
66
- {
67
- closeCurrentFile().delete();
68
- if (connection != null) {
69
- connection.close();
70
- connection = null;
71
- }
72
- }
73
- }
1
+ package org.embulk.output.postgresql;
2
+
3
+ import java.io.File;
4
+ import java.io.IOException;
5
+ import java.io.FileInputStream;
6
+ import java.sql.Connection;
7
+ import java.sql.SQLException;
8
+ import org.slf4j.Logger;
9
+ import org.postgresql.copy.CopyManager;
10
+ import org.postgresql.core.BaseConnection;
11
+ import org.embulk.spi.Exec;
12
+ import org.embulk.output.jdbc.JdbcSchema;
13
+
14
+ public class PostgreSQLCopyBatchInsert
15
+ extends AbstractPostgreSQLCopyBatchInsert
16
+ {
17
+ private final Logger logger = Exec.getLogger(PostgreSQLCopyBatchInsert.class);
18
+ private final PostgreSQLOutputConnector connector;
19
+
20
+ private PostgreSQLOutputConnection connection = null;
21
+ private CopyManager copyManager = null;
22
+ private String copySql = null;
23
+ private long totalRows;
24
+
25
+ public PostgreSQLCopyBatchInsert(PostgreSQLOutputConnector connector) throws IOException, SQLException
26
+ {
27
+ super();
28
+ this.connector = connector;
29
+ }
30
+
31
+ @Override
32
+ public void prepare(String loadTable, JdbcSchema insertSchema) throws SQLException
33
+ {
34
+ this.connection = connector.connect(true);
35
+ this.copySql = connection.buildCopySql(loadTable, insertSchema);
36
+ this.copyManager = connection.newCopyManager();
37
+ logger.info("Copy SQL: "+copySql);
38
+ }
39
+
40
+ @Override
41
+ public void flush() throws IOException, SQLException
42
+ {
43
+ File file = closeCurrentFile(); // flush buffered data in writer
44
+
45
+ logger.info(String.format("Loading %,d rows (%,d bytes)", batchRows, file.length()));
46
+ long startTime = System.currentTimeMillis();
47
+ FileInputStream in = new FileInputStream(file);
48
+ try {
49
+ // TODO check age of connection and call isValid if it's old and reconnect if it's invalid
50
+ copyManager.copyIn(copySql, in);
51
+ } finally {
52
+ in.close();
53
+ }
54
+ double seconds = (System.currentTimeMillis() - startTime) / 1000.0;
55
+
56
+ totalRows += batchRows;
57
+ batchRows = 0;
58
+ logger.info(String.format("> %.2f seconds (loaded %,d rows in total)", seconds, totalRows));
59
+
60
+ openNewFile();
61
+ file.delete();
62
+ }
63
+
64
+ @Override
65
+ public void close() throws IOException, SQLException
66
+ {
67
+ closeCurrentFile().delete();
68
+ if (connection != null) {
69
+ connection.close();
70
+ connection = null;
71
+ }
72
+ }
73
+ }