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.
@@ -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 convertTypeName(String typeName)
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 upsert AS (UPDATE ").append(table).append(" SET ");
67
-
68
- for (int i=0; i < size; i++) {
69
- JdbcColumn c = toTableSchema.getColumn(i);
70
- if (!c.isPrimaryKey()) {
71
- if(idx != 0) { sb.append(", "); }
72
- idx++;
73
- quoteIdentifierString(sb, toTableSchema.getColumnName(i));
74
- sb.append("=?");
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
- idx = 0;
80
- for(int i=0; i < size; i++) {
81
- JdbcColumn c = toTableSchema.getColumn(i);
82
- if (c.isPrimaryKey()) {
83
- if(idx != 0) { sb.append(" AND "); }
84
- idx++;
85
- quoteIdentifierString(sb, toTableSchema.getColumnName(i));
86
- sb.append("=?");
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 true as result)");
90
-
91
- sb.append(" INSERT INTO ").append(table).append(" (");
92
- for (int i=0; i < size; i++) {
93
- if(i != 0) { sb.append(", "); }
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(" SELECT ");
99
- for (int i=0; i < size; i++) {
100
- if(i != 0) { sb.append(", "); }
101
- sb.append("?");
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(" WHERE (SELECT result FROM upsert) is null");
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.2.4
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-12 00:00:00.000000000 Z
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
- - src/main/java/org/embulk/output/postgresql/PostgresqlBatchUpsert.java
29
- - classpath/embulk-output-jdbc-0.2.4.jar
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
@@ -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
- }