embulk-output-postgresql 0.2.4 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
- }