|
1 | 1 | package org.embulk.output.mysql;
|
2 | 2 |
|
| 3 | +import java.sql.Statement; |
3 | 4 | import java.util.List;
|
4 | 5 | import java.sql.Connection;
|
5 | 6 | import java.sql.SQLException;
|
| 7 | +import java.util.Optional; |
6 | 8 |
|
7 | 9 | import org.embulk.output.MySQLTimeZoneComparison;
|
8 | 10 | import org.embulk.output.jdbc.JdbcColumn;
|
@@ -101,6 +103,56 @@ protected String buildCollectMergeSql(List<TableIdentifier> fromTables, JdbcSche
|
101 | 103 | return sb.toString();
|
102 | 104 | }
|
103 | 105 |
|
| 106 | + private String buildSwapTableSql(TableIdentifier fromTable, TableIdentifier toTable) |
| 107 | + { |
| 108 | + String suffix = "_embulk_swap_tmp"; |
| 109 | + String uniqueName = String.format("%016x", System.currentTimeMillis()) + suffix; |
| 110 | + // NOTE: The table name should be always shorter than 64 characters |
| 111 | + // See also: https://dev.mysql.com/doc/refman/8.0/en/identifier-length.html |
| 112 | + TableIdentifier tmpTable = new TableIdentifier(fromTable.getDatabase(), fromTable.getSchemaName(), uniqueName); |
| 113 | + |
| 114 | + StringBuilder sb = new StringBuilder(); |
| 115 | + sb.append("RENAME TABLE "); |
| 116 | + quoteTableIdentifier(sb, fromTable); |
| 117 | + sb.append(" TO "); |
| 118 | + quoteTableIdentifier(sb, tmpTable); |
| 119 | + |
| 120 | + sb.append(", "); |
| 121 | + quoteTableIdentifier(sb, toTable); |
| 122 | + sb.append(" TO "); |
| 123 | + quoteTableIdentifier(sb, fromTable); |
| 124 | + |
| 125 | + sb.append(", "); |
| 126 | + quoteTableIdentifier(sb, tmpTable); |
| 127 | + sb.append(" TO "); |
| 128 | + quoteTableIdentifier(sb, toTable); |
| 129 | + |
| 130 | + return sb.toString(); |
| 131 | + } |
| 132 | + |
| 133 | + @Override |
| 134 | + public void replaceTable(TableIdentifier fromTable, JdbcSchema schema, TableIdentifier toTable, Optional<String> postSql) throws SQLException |
| 135 | + { |
| 136 | + Statement stmt = connection.createStatement(); |
| 137 | + try { |
| 138 | + // "DROP TABLE" causes an implicit commit in MySQL, so we rename the table at first. |
| 139 | + // See also: https://dev.mysql.com/doc/refman/8.0/en/implicit-commit.html |
| 140 | + executeUpdate(stmt, buildSwapTableSql(fromTable, toTable)); |
| 141 | + |
| 142 | + dropTableIfExists(stmt, fromTable); |
| 143 | + |
| 144 | + if (postSql.isPresent()) { |
| 145 | + execute(stmt, postSql.get()); |
| 146 | + } |
| 147 | + |
| 148 | + commitIfNecessary(connection); |
| 149 | + } catch (SQLException ex) { |
| 150 | + throw safeRollback(connection, ex); |
| 151 | + } finally { |
| 152 | + stmt.close(); |
| 153 | + } |
| 154 | + } |
| 155 | + |
104 | 156 | @Override
|
105 | 157 | protected String buildColumnTypeName(JdbcColumn c)
|
106 | 158 | {
|
|
0 commit comments