|
11 | 11 | import net.snowflake.client.jdbc.internal.org.bouncycastle.pkcs.PKCSException; |
12 | 12 | import org.embulk.config.ConfigDiff; |
13 | 13 | import org.embulk.config.ConfigException; |
| 14 | +import org.embulk.config.ConfigSource; |
14 | 15 | import org.embulk.config.TaskSource; |
15 | 16 | import org.embulk.output.jdbc.*; |
16 | 17 | import org.embulk.output.snowflake.PrivateKeyReader; |
|
27 | 28 | import org.embulk.util.config.ConfigDefault; |
28 | 29 |
|
29 | 30 | public class SnowflakeOutputPlugin extends AbstractJdbcOutputPlugin { |
30 | | - private StageIdentifier stageIdentifier; |
31 | | - |
32 | 31 | public interface SnowflakePluginTask extends PluginTask { |
33 | 32 | @Config("driver_path") |
34 | 33 | @ConfigDefault("null") |
@@ -79,6 +78,10 @@ public interface SnowflakePluginTask extends PluginTask { |
79 | 78 | @ConfigDefault("true") |
80 | 79 | public boolean getEmtpyFieldAsNull(); |
81 | 80 |
|
| 81 | + @Config("delete_stage_on_error") |
| 82 | + @ConfigDefault("false") |
| 83 | + public boolean getDeleteStageOnError(); |
| 84 | + |
82 | 85 | @Config("match_by_column_name") |
83 | 86 | @ConfigDefault("\"none\"") |
84 | 87 | public MatchByColumnName getMatchByColumnName(); |
@@ -188,25 +191,39 @@ protected JdbcOutputConnector getConnector(PluginTask task, boolean retryableMet |
188 | 191 | } |
189 | 192 |
|
190 | 193 | @Override |
191 | | - public ConfigDiff resume( |
192 | | - TaskSource taskSource, Schema schema, int taskCount, OutputPlugin.Control control) { |
193 | | - throw new UnsupportedOperationException("snowflake output plugin does not support resuming"); |
194 | | - } |
195 | | - |
196 | | - @Override |
197 | | - protected void doCommit(JdbcOutputConnection con, PluginTask task, int taskCount) |
198 | | - throws SQLException { |
199 | | - super.doCommit(con, task, taskCount); |
200 | | - SnowflakeOutputConnection snowflakeCon = (SnowflakeOutputConnection) con; |
201 | | - |
| 194 | + public ConfigDiff transaction( |
| 195 | + ConfigSource config, Schema schema, int taskCount, OutputPlugin.Control control) { |
| 196 | + PluginTask task = CONFIG_MAPPER.map(config, this.getTaskClass()); |
202 | 197 | SnowflakePluginTask t = (SnowflakePluginTask) task; |
203 | | - if (this.stageIdentifier == null) { |
204 | | - this.stageIdentifier = StageIdentifierHolder.getStageIdentifier(t); |
| 198 | + StageIdentifier stageIdentifier = StageIdentifierHolder.getStageIdentifier(t); |
| 199 | + ConfigDiff configDiff; |
| 200 | + SnowflakeOutputConnection snowflakeCon = null; |
| 201 | + |
| 202 | + try { |
| 203 | + snowflakeCon = (SnowflakeOutputConnection) getConnector(task, true).connect(true); |
| 204 | + snowflakeCon.runCreateStage(stageIdentifier); |
| 205 | + configDiff = super.transaction(config, schema, taskCount, control); |
| 206 | + if (t.getDeleteStage()) { |
| 207 | + snowflakeCon.runDropStage(stageIdentifier); |
| 208 | + } |
| 209 | + } catch (Exception e) { |
| 210 | + if (t.getDeleteStage() && t.getDeleteStageOnError()) { |
| 211 | + try { |
| 212 | + snowflakeCon.runDropStage(stageIdentifier); |
| 213 | + } catch (SQLException ex) { |
| 214 | + throw new RuntimeException(ex); |
| 215 | + } |
| 216 | + } |
| 217 | + throw new RuntimeException(e); |
205 | 218 | } |
206 | 219 |
|
207 | | - if (t.getDeleteStage()) { |
208 | | - snowflakeCon.runDropStage(this.stageIdentifier); |
209 | | - } |
| 220 | + return configDiff; |
| 221 | + } |
| 222 | + |
| 223 | + @Override |
| 224 | + public ConfigDiff resume( |
| 225 | + TaskSource taskSource, Schema schema, int taskCount, OutputPlugin.Control control) { |
| 226 | + throw new UnsupportedOperationException("snowflake output plugin does not support resuming"); |
210 | 227 | } |
211 | 228 |
|
212 | 229 | @Override |
@@ -255,20 +272,11 @@ protected BatchInsert newBatchInsert(PluginTask task, Optional<MergeConfig> merg |
255 | 272 | throw new UnsupportedOperationException( |
256 | 273 | "Snowflake output plugin doesn't support 'merge_direct' mode."); |
257 | 274 | } |
258 | | - |
259 | | - SnowflakePluginTask t = (SnowflakePluginTask) task; |
260 | | - // TODO: put some where executes once |
261 | | - if (this.stageIdentifier == null) { |
262 | | - SnowflakeOutputConnection snowflakeCon = |
263 | | - (SnowflakeOutputConnection) getConnector(task, true).connect(true); |
264 | | - this.stageIdentifier = StageIdentifierHolder.getStageIdentifier(t); |
265 | | - snowflakeCon.runCreateStage(this.stageIdentifier); |
266 | | - } |
267 | 275 | SnowflakePluginTask pluginTask = (SnowflakePluginTask) task; |
268 | 276 |
|
269 | 277 | return new SnowflakeCopyBatchInsert( |
270 | 278 | getConnector(task, true), |
271 | | - this.stageIdentifier, |
| 279 | + StageIdentifierHolder.getStageIdentifier(pluginTask), |
272 | 280 | pluginTask.getCopyIntoTableColumnNames(), |
273 | 281 | pluginTask.getCopyIntoCSVColumnNumbers(), |
274 | 282 | false, |
|
0 commit comments