embulk-output-cassandra 0.2.0 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: ab4a3fa7b0b477c2c6ebed457fa48f248ce7a6ae
4
- data.tar.gz: a7355ea7423d856a3533e2b3d4dbbb50d05c60be
3
+ metadata.gz: f3a5a33db3984bac71c043a99cf1306c12aed2fa
4
+ data.tar.gz: 6351267b4e17e6d75617fa4ddda29f4c5b2551e5
5
5
  SHA512:
6
- metadata.gz: 0a8b7043a53d758515a06274ffd00955013d8533d447e512a01228f17e63e378e9d70a5f149f54e9451b52a74718951261e3e6a6493889f8d6213b06db480ea3
7
- data.tar.gz: f51f4f392c31bb8928e97b14ef4059a523578883517ea390e3beac76ffd84dc1f30b464cac999d05e478fc6ae4ad102739a26590b219dd5437901c00debc1181
6
+ metadata.gz: 45f9a322c118f1b4786d730f1db68eefbdccfb1f63fcc9c14967319c9a441bb6b003f0f06a075228c042fdd217f82064f215fb807812cd9e6152c2e76a557a02
7
+ data.tar.gz: 6a29cfbd03d3ecb2f070563af73265b711c093c0b88ffd68b57d27f98b541964f8002f9f9d59aa3dcba8c33afb8ea680fab6ce77560c44653bd390a87b48cef6
data/README.md CHANGED
@@ -67,7 +67,9 @@ For example, If input data = {id: 1, count: 5}, Executed Statement is `UPDATE ta
67
67
  - **cluster_name**: cluster name (string, default: `null`)
68
68
  - **keyspace**: target keyspace name (string, required)
69
69
  - **table**: target table name (string, required)
70
+ - **mode**: insert or update (string, default: `"insert"`)
70
71
  - **if_not_exists**: Add "IF NOT EXISTS" to INSERT query (boolean, default: `false`)
72
+ - **if_exists**: Add "IF EXISTS" to UPDATE query (boolean, default: `false`)
71
73
  - **ttl**: Add "TTL" to INSERT query (integer, default: `null`)
72
74
  - **idempotent**: Treat INSERT query as idempotent (boolean, default: `false`)
73
75
  - **connect_timeout**: Set connect timeout millisecond (integer, default: `5000`)
@@ -13,7 +13,7 @@ configurations {
13
13
  provided
14
14
  }
15
15
 
16
- version = "0.2.0"
16
+ version = "0.3.0"
17
17
 
18
18
  sourceCompatibility = 1.8
19
19
  targetCompatibility = 1.8
@@ -1,5 +1,5 @@
1
1
  <?xml version="1.0" encoding="UTF-8"?>
2
- <module external.linked.project.id="embulk-output-cassandra" external.linked.project.path="$MODULE_DIR$" external.root.project.path="$MODULE_DIR$" external.system.id="GRADLE" external.system.module.group="" external.system.module.version="0.1.1" type="JAVA_MODULE" version="4">
2
+ <module external.linked.project.id="embulk-output-cassandra" external.linked.project.path="$MODULE_DIR$" external.root.project.path="$MODULE_DIR$" external.system.id="GRADLE" external.system.module.group="" external.system.module.version="0.2.0" type="JAVA_MODULE" version="4">
3
3
  <component name="NewModuleRootManager" inherit-compiler-output="true">
4
4
  <exclude-output />
5
5
  <content url="file://$MODULE_DIR$">
@@ -13,6 +13,8 @@ import com.datastax.driver.core.querybuilder.BuiltStatement;
13
13
  import com.datastax.driver.core.querybuilder.Insert;
14
14
  import com.datastax.driver.core.querybuilder.QueryBuilder;
15
15
  import com.datastax.driver.core.querybuilder.Update;
16
+ import com.fasterxml.jackson.annotation.JsonCreator;
17
+ import com.fasterxml.jackson.annotation.JsonValue;
16
18
  import com.google.common.base.Optional;
17
19
  import com.google.common.collect.ImmutableList;
18
20
  import com.google.common.collect.ImmutableMap;
@@ -20,6 +22,7 @@ import com.google.common.collect.Lists;
20
22
  import org.embulk.config.Config;
21
23
  import org.embulk.config.ConfigDefault;
22
24
  import org.embulk.config.ConfigDiff;
25
+ import org.embulk.config.ConfigException;
23
26
  import org.embulk.config.ConfigSource;
24
27
  import org.embulk.config.Task;
25
28
  import org.embulk.config.TaskReport;
@@ -27,6 +30,7 @@ import org.embulk.config.TaskSource;
27
30
  import org.embulk.output.cassandra.setter.CassandraColumnSetter;
28
31
  import org.embulk.output.cassandra.setter.CassandraColumnSetterFactory;
29
32
  import org.embulk.output.cassandra.setter.ColumnSetterVisitor;
33
+ import org.embulk.spi.Column;
30
34
  import org.embulk.spi.Exec;
31
35
  import org.embulk.spi.OutputPlugin;
32
36
  import org.embulk.spi.Page;
@@ -37,7 +41,9 @@ import org.slf4j.Logger;
37
41
 
38
42
  import java.net.InetSocketAddress;
39
43
  import java.util.List;
44
+ import java.util.Locale;
40
45
  import java.util.Map;
46
+ import java.util.stream.Collectors;
41
47
 
42
48
  public class CassandraOutputPlugin
43
49
  implements OutputPlugin
@@ -46,7 +52,7 @@ public class CassandraOutputPlugin
46
52
  extends Task
47
53
  {
48
54
  @Config("hosts")
49
- public List<String> gethosts();
55
+ public List<String> getHosts();
50
56
 
51
57
  @Config("port")
52
58
  @ConfigDefault("9042")
@@ -70,10 +76,18 @@ public class CassandraOutputPlugin
70
76
  @Config("table")
71
77
  public String getTable();
72
78
 
79
+ @Config("mode")
80
+ @ConfigDefault("\"insert\"")
81
+ public Mode getMode();
82
+
73
83
  @Config("if_not_exists")
74
84
  @ConfigDefault("false")
75
85
  public Boolean getIfNotExists();
76
86
 
87
+ @Config("if_exists")
88
+ @ConfigDefault("false")
89
+ public Boolean getIfExists();
90
+
77
91
  @Config("ttl")
78
92
  @ConfigDefault("null")
79
93
  public Optional<Integer> getTtl();
@@ -89,10 +103,6 @@ public class CassandraOutputPlugin
89
103
  @Config("request_timeout")
90
104
  @ConfigDefault("12000")
91
105
  public int getRequestTimeout();
92
-
93
- @Config("counter_columnName")
94
- @ConfigDefault("null")
95
- public Optional<String> getCounterColumnName();
96
106
  }
97
107
 
98
108
  private final Logger logger = Exec.getLogger(CassandraOutputPlugin.class);
@@ -155,12 +165,36 @@ public class CassandraOutputPlugin
155
165
  if (column.getType().getName() == DataType.Name.COUNTER) {
156
166
  update.with(QueryBuilder.incr(column.getName(), QueryBuilder.bindMarker(column.getName())));
157
167
  }
158
- else{
168
+ else {
159
169
  update.where(QueryBuilder.eq(column.getName(), QueryBuilder.bindMarker(column.getName())));
160
170
  }
161
171
  }
162
172
  query = update;
163
173
  }
174
+ else if (task.getMode() == Mode.UPDATE) {
175
+ Update update = QueryBuilder.update(task.getKeyspace(), task.getTable());
176
+ List<String> primaryKeys = tableMetadata.getPrimaryKey().stream().map(ColumnMetadata::getName).collect(Collectors.toList());
177
+ List<String> columnNames = tableMetadata.getColumns().stream().map(ColumnMetadata::getName).collect(Collectors.toList());
178
+
179
+ if (task.getIfExists()) {
180
+ update.where().ifExists();
181
+ }
182
+ if (task.getTtl().isPresent()) {
183
+ update.using(QueryBuilder.ttl(task.getTtl().get()));
184
+ }
185
+ for (String pkey : primaryKeys) {
186
+ update.where(QueryBuilder.eq(pkey, QueryBuilder.bindMarker(pkey)));
187
+ }
188
+ for (Column col : schema.getColumns()) {
189
+ if (primaryKeys.contains(col.getName())) {
190
+ continue;
191
+ }
192
+ if (columnNames.contains(col.getName())) {
193
+ update.with(QueryBuilder.set(col.getName(), QueryBuilder.bindMarker(col.getName())));
194
+ }
195
+ }
196
+ query = update;
197
+ }
164
198
  else {
165
199
  Insert insert = QueryBuilder.insertInto(task.getKeyspace(), task.getTable());
166
200
  if (task.getIfNotExists()) {
@@ -190,7 +224,7 @@ public class CassandraOutputPlugin
190
224
  List<ColumnSetterVisitor> columnVisitors = Lists.transform(schema.getColumns(), (column) ->
191
225
  new ColumnSetterVisitor(pageReader, columnSetters.get(column.getName())));
192
226
 
193
- logger.info("Insert Query: {}", query.getQueryString());
227
+ logger.info("Query: {}", query.getQueryString());
194
228
 
195
229
  PreparedStatement prepared = session.prepare(query);
196
230
  if (task.getIdempotent()) {
@@ -203,7 +237,7 @@ public class CassandraOutputPlugin
203
237
  private Cluster getCluster(PluginTask task)
204
238
  {
205
239
  Cluster.Builder builder = Cluster.builder();
206
- for (String host : task.gethosts()) {
240
+ for (String host : task.getHosts()) {
207
241
  builder.addContactPointsWithPorts(new InetSocketAddress(host, task.getPort()));
208
242
  }
209
243
 
@@ -311,4 +345,29 @@ public class CassandraOutputPlugin
311
345
  return report;
312
346
  }
313
347
  }
348
+
349
+ public enum Mode {
350
+ INSERT,
351
+ UPDATE;
352
+
353
+ @JsonValue
354
+ @Override
355
+ public String toString()
356
+ {
357
+ return name().toLowerCase(Locale.ENGLISH);
358
+ }
359
+
360
+ @JsonCreator
361
+ public static Mode fromString(String value)
362
+ {
363
+ switch(value) {
364
+ case "insert":
365
+ return INSERT;
366
+ case "update":
367
+ return UPDATE;
368
+ default:
369
+ throw new ConfigException(String.format("Unknown mode '%s'", value));
370
+ }
371
+ }
372
+ }
314
373
  }
@@ -3,7 +3,6 @@ package org.embulk.output.cassandra;
3
3
  import com.datastax.driver.core.Cluster;
4
4
  import com.datastax.driver.core.DataType;
5
5
  import com.datastax.driver.core.LocalDate;
6
- import com.datastax.driver.core.ResultSet;
7
6
  import com.datastax.driver.core.Row;
8
7
  import com.datastax.driver.core.Session;
9
8
  import com.datastax.driver.core.TupleType;
@@ -33,7 +32,12 @@ import java.util.List;
33
32
  import java.util.Map;
34
33
  import java.util.Set;
35
34
 
36
- import static org.junit.Assert.*;
35
+ import static org.junit.Assert.assertArrayEquals;
36
+ import static org.junit.Assert.assertEquals;
37
+ import static org.junit.Assert.assertFalse;
38
+ import static org.junit.Assert.assertNotNull;
39
+ import static org.junit.Assert.assertNull;
40
+ import static org.junit.Assert.assertTrue;
37
41
 
38
42
  public class TestCassandraOutputPlugin
39
43
  {
@@ -249,6 +253,56 @@ public class TestCassandraOutputPlugin
249
253
  assertTrue(UUIDs.unixTimestamp(row1.getUUID("timeuuid_item")) < ZonedDateTime.now().toInstant().toEpochMilli());
250
254
  }
251
255
 
256
+ @Test
257
+ public void testBasicWithUpdateMode() throws IOException
258
+ {
259
+ Path input = getInputPath("test1.csv");
260
+ ConfigSource config = loadYamlResource("test_basic.yaml");
261
+ config.set("hosts", getCassandraHostAsList());
262
+ config.set("mode", "update");
263
+
264
+ assertEquals(0, session.execute("SELECT * FROM embulk_test.test_basic").all().size());
265
+
266
+ embulk.runOutput(config, input);
267
+
268
+ Row row1 = session.execute("SELECT * FROM embulk_test.test_basic WHERE id = 'A001'").one();
269
+ Row row2 = session.execute("SELECT * FROM embulk_test.test_basic WHERE id = 'A002'").one();
270
+ Row row3 = session.execute("SELECT * FROM embulk_test.test_basic WHERE id = 'A003'").one();
271
+ assertEquals("A001", row1.getString("id"));
272
+ assertEquals(9, row1.getLong("int_item"));
273
+ assertEquals(createDate(2018, 7, 1, 10, 0, 0, 0), row1.getTimestamp("timestamp_item"));
274
+ assertEquals("A002", row2.getString("id"));
275
+ assertEquals(0, row2.getLong("int_item"));
276
+ assertEquals(createDate(2018, 7, 1, 10, 0, 1, 0), row2.getTimestamp("timestamp_item"));
277
+ assertEquals("A003", row3.getString("id"));
278
+ assertEquals(9, row3.getLong("int_item"));
279
+ assertEquals(createDate(2018, 7, 1, 10, 0, 2, 0), row3.getTimestamp("timestamp_item"));
280
+ }
281
+
282
+ @Test
283
+ public void testBasicWithIfExists() throws IOException
284
+ {
285
+ Path input = getInputPath("test1.csv");
286
+ ConfigSource config = loadYamlResource("test_basic.yaml");
287
+ config.set("hosts", getCassandraHostAsList());
288
+ config.set("mode", "update");
289
+ config.set("if_exists", true);
290
+
291
+ session.execute("INSERT INTO embulk_test.test_basic (id) VALUES ('A001')");
292
+ assertEquals(1, session.execute("SELECT * FROM embulk_test.test_basic").all().size());
293
+
294
+ embulk.runOutput(config, input);
295
+
296
+ Row row1 = session.execute("SELECT * FROM embulk_test.test_basic WHERE id = 'A001'").one();
297
+ Row row2 = session.execute("SELECT * FROM embulk_test.test_basic WHERE id = 'A002'").one();
298
+ Row row3 = session.execute("SELECT * FROM embulk_test.test_basic WHERE id = 'A003'").one();
299
+ assertEquals("A001", row1.getString("id"));
300
+ assertEquals(9, row1.getLong("int_item"));
301
+ assertEquals(createDate(2018, 7, 1, 10, 0, 0, 0), row1.getTimestamp("timestamp_item"));
302
+ assertNull(row2);
303
+ assertNull(row3);
304
+ }
305
+
252
306
  @Test
253
307
  public void testComplex() throws IOException
254
308
  {
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: embulk-output-cassandra
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - joker1007
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-08-12 00:00:00.000000000 Z
11
+ date: 2018-10-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  requirement: !ruby/object:Gem::Requirement
@@ -55,7 +55,7 @@ files:
55
55
  - classpath/asm-tree-5.0.3.jar
56
56
  - classpath/asm-util-5.0.3.jar
57
57
  - classpath/cassandra-driver-core-3.5.0.jar
58
- - classpath/embulk-output-cassandra-0.2.0.jar
58
+ - classpath/embulk-output-cassandra-0.3.0.jar
59
59
  - classpath/guava-19.0.jar
60
60
  - classpath/jffi-1.2.16-native.jar
61
61
  - classpath/jffi-1.2.16.jar