embulk-output-postgresql 0.2.4 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +89 -43
- data/build.gradle +7 -7
- data/classpath/embulk-output-jdbc-0.3.0.jar +0 -0
- data/classpath/embulk-output-postgresql-0.3.0.jar +0 -0
- data/lib/embulk/output/postgresql.rb +3 -3
- data/src/main/java/org/embulk/output/PostgreSQLOutputPlugin.java +109 -142
- data/src/main/java/org/embulk/output/postgresql/AbstractPostgreSQLCopyBatchInsert.java +215 -217
- data/src/main/java/org/embulk/output/postgresql/PostgreSQLCopyBatchInsert.java +73 -73
- data/src/main/java/org/embulk/output/postgresql/PostgreSQLOutputConnection.java +98 -49
- data/src/main/java/org/embulk/output/postgresql/PostgreSQLOutputConnector.java +40 -40
- metadata +4 -5
- data/classpath/embulk-output-jdbc-0.2.4.jar +0 -0
- data/classpath/embulk-output-postgresql-0.2.4.jar +0 -0
- data/src/main/java/org/embulk/output/postgresql/PostgresqlBatchUpsert.java +0 -24
@@ -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
|
+
}
|
@@ -1,5 +1,6 @@
|
|
1
1
|
package org.embulk.output.postgresql;
|
2
2
|
|
3
|
+
import java.util.List;
|
3
4
|
import java.sql.Connection;
|
4
5
|
import java.sql.SQLException;
|
5
6
|
import java.sql.Statement;
|
@@ -28,7 +29,7 @@ public class PostgreSQLOutputConnection
|
|
28
29
|
quoteIdentifierString(sb, toTable);
|
29
30
|
sb.append(" (");
|
30
31
|
for (int i=0; i < toTableSchema.getCount(); i++) {
|
31
|
-
if(i != 0) { sb.append(", "); }
|
32
|
+
if (i != 0) { sb.append(", "); }
|
32
33
|
quoteIdentifierString(sb, toTableSchema.getColumnName(i));
|
33
34
|
}
|
34
35
|
sb.append(") ");
|
@@ -43,66 +44,114 @@ public class PostgreSQLOutputConnection
|
|
43
44
|
}
|
44
45
|
|
45
46
|
@Override
|
46
|
-
protected String
|
47
|
-
{
|
48
|
-
switch(typeName) {
|
49
|
-
case "CLOB":
|
50
|
-
return "TEXT";
|
51
|
-
case "BLOB":
|
52
|
-
return "BYTEA";
|
53
|
-
default:
|
54
|
-
return typeName;
|
55
|
-
}
|
56
|
-
}
|
57
|
-
|
58
|
-
@Override
|
59
|
-
protected String buildPrepareUpsertSql(String toTable, JdbcSchema toTableSchema) throws SQLException
|
47
|
+
protected String buildCollectMergeSql(List<String> fromTables, JdbcSchema schema, String toTable, List<String> mergeKeys) throws SQLException
|
60
48
|
{
|
61
49
|
StringBuilder sb = new StringBuilder();
|
62
|
-
int size = toTableSchema.getCount();
|
63
|
-
String table = quoteIdentifierString(toTable);
|
64
|
-
int idx = 0;
|
65
50
|
|
66
|
-
sb.append("WITH
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
51
|
+
sb.append("WITH updated AS (");
|
52
|
+
sb.append("UPDATE ");
|
53
|
+
quoteIdentifierString(sb, toTable);
|
54
|
+
sb.append(" SET ");
|
55
|
+
for (int i=0; i < schema.getCount(); i++) {
|
56
|
+
if (i != 0) { sb.append(", "); }
|
57
|
+
quoteIdentifierString(sb, schema.getColumnName(i));
|
58
|
+
sb.append(" = S.");
|
59
|
+
quoteIdentifierString(sb, schema.getColumnName(i));
|
60
|
+
}
|
61
|
+
sb.append(" FROM (");
|
62
|
+
for (int i=0; i < fromTables.size(); i++) {
|
63
|
+
if (i != 0) { sb.append(" UNION ALL "); }
|
64
|
+
sb.append("SELECT ");
|
65
|
+
for(int j=0; j < schema.getCount(); j++) {
|
66
|
+
if (j != 0) { sb.append(", "); }
|
67
|
+
quoteIdentifierString(sb, schema.getColumnName(j));
|
75
68
|
}
|
69
|
+
sb.append(" FROM ");
|
70
|
+
quoteIdentifierString(sb, fromTables.get(i));
|
76
71
|
}
|
77
|
-
|
72
|
+
sb.append(") S");
|
78
73
|
sb.append(" WHERE ");
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
}
|
74
|
+
for (int i=0; i < mergeKeys.size(); i++) {
|
75
|
+
if (i != 0) { sb.append(" AND "); }
|
76
|
+
quoteIdentifierString(sb, toTable);
|
77
|
+
sb.append(".");
|
78
|
+
quoteIdentifierString(sb, mergeKeys.get(i));
|
79
|
+
sb.append(" = ");
|
80
|
+
sb.append("S.");
|
81
|
+
quoteIdentifierString(sb, mergeKeys.get(i));
|
88
82
|
}
|
89
|
-
sb.append(" RETURNING
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
quoteIdentifierString(sb, toTableSchema.getColumnName(i));
|
83
|
+
sb.append(" RETURNING ");
|
84
|
+
for (int i=0; i < mergeKeys.size(); i++) {
|
85
|
+
if (i != 0) { sb.append(", "); }
|
86
|
+
sb.append("S.");
|
87
|
+
quoteIdentifierString(sb, mergeKeys.get(i));
|
95
88
|
}
|
96
|
-
sb.append(")");
|
89
|
+
sb.append(") ");
|
97
90
|
|
98
|
-
sb.append("
|
99
|
-
|
100
|
-
|
101
|
-
|
91
|
+
sb.append("INSERT INTO ");
|
92
|
+
quoteIdentifierString(sb, toTable);
|
93
|
+
sb.append(" (");
|
94
|
+
for (int i=0; i < schema.getCount(); i++) {
|
95
|
+
if (i != 0) { sb.append(", "); }
|
96
|
+
quoteIdentifierString(sb, schema.getColumnName(i));
|
102
97
|
}
|
103
|
-
sb.append("
|
98
|
+
sb.append(") ");
|
99
|
+
sb.append("SELECT DISTINCT ON (");
|
100
|
+
for (int i=0; i < mergeKeys.size(); i++) {
|
101
|
+
if (i != 0) { sb.append(", "); }
|
102
|
+
quoteIdentifierString(sb, mergeKeys.get(i));
|
103
|
+
}
|
104
|
+
sb.append(") * FROM (");
|
105
|
+
for (int i=0; i < fromTables.size(); i++) {
|
106
|
+
if (i != 0) { sb.append(" UNION ALL "); }
|
107
|
+
sb.append("SELECT ");
|
108
|
+
for(int j=0; j < schema.getCount(); j++) {
|
109
|
+
if (j != 0) { sb.append(", "); }
|
110
|
+
quoteIdentifierString(sb, schema.getColumnName(j));
|
111
|
+
}
|
112
|
+
sb.append(" FROM ");
|
113
|
+
quoteIdentifierString(sb, fromTables.get(i));
|
114
|
+
}
|
115
|
+
sb.append(") S ");
|
116
|
+
sb.append("WHERE NOT EXISTS (");
|
117
|
+
sb.append("SELECT 1 FROM updated WHERE ");
|
118
|
+
for (int i=0; i < mergeKeys.size(); i++) {
|
119
|
+
if (i != 0) { sb.append(" AND "); }
|
120
|
+
sb.append("S.");
|
121
|
+
quoteIdentifierString(sb, mergeKeys.get(i));
|
122
|
+
sb.append(" = ");
|
123
|
+
sb.append("updated.");
|
124
|
+
quoteIdentifierString(sb, mergeKeys.get(i));
|
125
|
+
}
|
126
|
+
sb.append(") ");
|
104
127
|
|
105
128
|
return sb.toString();
|
106
129
|
}
|
107
130
|
|
131
|
+
protected void collectReplaceView(List<String> fromTables, JdbcSchema schema, String toTable) throws SQLException
|
132
|
+
{
|
133
|
+
Statement stmt = connection.createStatement();
|
134
|
+
try {
|
135
|
+
String sql = buildCollectInsertSql(fromTables, schema, toTable);
|
136
|
+
executeUpdate(stmt, sql);
|
137
|
+
commitIfNecessary(connection);
|
138
|
+
} catch (SQLException ex) {
|
139
|
+
throw safeRollback(connection, ex);
|
140
|
+
} finally {
|
141
|
+
stmt.close();
|
142
|
+
}
|
143
|
+
}
|
144
|
+
|
145
|
+
@Override
|
146
|
+
protected String buildColumnTypeName(JdbcColumn c)
|
147
|
+
{
|
148
|
+
switch(c.getSimpleTypeName()) {
|
149
|
+
case "CLOB":
|
150
|
+
return "TEXT";
|
151
|
+
case "BLOB":
|
152
|
+
return "BYTEA";
|
153
|
+
default:
|
154
|
+
return super.buildColumnTypeName(c);
|
155
|
+
}
|
156
|
+
}
|
108
157
|
}
|
@@ -1,40 +1,40 @@
|
|
1
|
-
package org.embulk.output.postgresql;
|
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 PostgreSQLOutputConnector
|
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 PostgreSQLOutputConnector(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 PostgreSQLOutputConnection connect(boolean autoCommit) throws SQLException
|
28
|
-
{
|
29
|
-
Connection c = driver.connect(url, properties);
|
30
|
-
try {
|
31
|
-
PostgreSQLOutputConnection con = new PostgreSQLOutputConnection(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.postgresql;
|
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 PostgreSQLOutputConnector
|
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 PostgreSQLOutputConnector(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 PostgreSQLOutputConnection connect(boolean autoCommit) throws SQLException
|
28
|
+
{
|
29
|
+
Connection c = driver.connect(url, properties);
|
30
|
+
try {
|
31
|
+
PostgreSQLOutputConnection con = new PostgreSQLOutputConnection(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-postgresql
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
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-05-
|
11
|
+
date: 2015-05-19 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: Inserts or updates records to a table.
|
14
14
|
email:
|
@@ -25,9 +25,8 @@ files:
|
|
25
25
|
- src/main/java/org/embulk/output/postgresql/PostgreSQLCopyBatchInsert.java
|
26
26
|
- src/main/java/org/embulk/output/postgresql/PostgreSQLOutputConnection.java
|
27
27
|
- src/main/java/org/embulk/output/postgresql/PostgreSQLOutputConnector.java
|
28
|
-
-
|
29
|
-
- classpath/embulk-output-
|
30
|
-
- classpath/embulk-output-postgresql-0.2.4.jar
|
28
|
+
- classpath/embulk-output-jdbc-0.3.0.jar
|
29
|
+
- classpath/embulk-output-postgresql-0.3.0.jar
|
31
30
|
- classpath/jna-4.1.0.jar
|
32
31
|
- classpath/jna-platform-4.1.0.jar
|
33
32
|
- classpath/postgresql-9.4-1200-jdbc41.jar
|
Binary file
|
Binary file
|
@@ -1,24 +0,0 @@
|
|
1
|
-
package org.embulk.output.postgresql;
|
2
|
-
|
3
|
-
import org.embulk.output.jdbc.JdbcOutputConnection;
|
4
|
-
import org.embulk.output.jdbc.JdbcOutputConnector;
|
5
|
-
import org.embulk.output.jdbc.JdbcSchema;
|
6
|
-
import org.embulk.output.jdbc.StandardBatchInsert;
|
7
|
-
|
8
|
-
import java.io.IOException;
|
9
|
-
import java.sql.PreparedStatement;
|
10
|
-
import java.sql.SQLException;
|
11
|
-
|
12
|
-
public class PostgresqlBatchUpsert extends StandardBatchInsert {
|
13
|
-
|
14
|
-
public PostgresqlBatchUpsert(JdbcOutputConnector connector) throws IOException, SQLException {
|
15
|
-
super(connector);
|
16
|
-
}
|
17
|
-
|
18
|
-
protected PreparedStatement newPreparedStatement(JdbcOutputConnection connection,
|
19
|
-
String loadTable, JdbcSchema insertSchema) throws SQLException
|
20
|
-
{
|
21
|
-
return connection.prepareUpsertSql(loadTable, insertSchema);
|
22
|
-
}
|
23
|
-
|
24
|
-
}
|