embulk-output-kintone 0.2.2 → 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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 59e8a8850c43f8ff293ca6b63d908f6e7e04b1ac
4
- data.tar.gz: 42f8ae842db0e3177b1123dc45dd7919f2cb903d
3
+ metadata.gz: 2004bfc2e202eeb6c57f3149bc7311f90343a67e
4
+ data.tar.gz: 86e036bc863ac7d8ca632488d0eb84c645658c43
5
5
  SHA512:
6
- metadata.gz: 447d0a6901e2bf7d4993fb9f20291f236199bd53e3ae4924b85444c64e8b4fa78a2bccf3c42083edde6c6d863953a6d6f1e70be4d629dd7f35ddc63ab81276de
7
- data.tar.gz: 8a6fb5c6cde0a75377b95641cadacc243ca7ab0ddd03d641df37f055c574a33552bd045b13cfa6236f49d570188c490d83dedb5715bd2908a53746af721c060c
6
+ metadata.gz: 723f4b6b9e5341a7e0bef48c6de38528860985d46d9a139c2d3e133c59ab867c9a4507b0c98a431b5b654f332178f90038168bc0143d9d9dcb2916dfe1956e44
7
+ data.tar.gz: 84441877b034060e5876ae67d8afd1d01f15a91d1aab8a76065bd4549a85c7de1639b0557a814482edc8312bbc11cbcbdc0565fa87aedfb794493966064201b7
@@ -1,13 +1,60 @@
1
- name: Java CI
1
+ name: main
2
2
 
3
- on: [push, pull_request]
3
+ on:
4
+ push:
5
+ branches:
6
+ - 'master'
7
+ tags:
8
+ - '*'
9
+ pull_request:
10
+ branches:
11
+ - 'master'
12
+ types: [opened, synchronize]
4
13
 
5
14
  jobs:
6
- build:
15
+ main:
7
16
  runs-on: ubuntu-latest
8
17
  steps:
9
18
  - uses: actions/checkout@v2
10
- - uses: actions/setup-java@v1
19
+ - name: Set Up
20
+ uses: actions/setup-java@v1
11
21
  with:
12
22
  java-version: 1.8
13
- - run: ./gradlew build
23
+
24
+ - name: Test
25
+ run: ./gradlew test
26
+
27
+ - name: Build Gem
28
+ run: ./gradlew gem
29
+
30
+ - name: Set up JRuby
31
+ uses: ruby/setup-ruby@v1
32
+ with:
33
+ ruby-version: jruby
34
+
35
+ - name: Publish to GPR
36
+ if: startsWith( github.ref, 'refs/tags/' )
37
+ run: |
38
+ mkdir -p $HOME/.gem
39
+ touch $HOME/.gem/credentials
40
+ chmod 0600 $HOME/.gem/credentials
41
+ printf -- "---\n:github: ${GEM_HOST_API_KEY}\n" > $HOME/.gem/credentials
42
+ gem push --KEY github --host https://rubygems.pkg.github.com/${OWNER} ./pkg/*.gem
43
+ env:
44
+ GEM_HOST_API_KEY: "Bearer ${{secrets.GITHUB_TOKEN}}"
45
+ OWNER: ${{ github.repository_owner }}
46
+
47
+ - name: Publish to RubyGems
48
+ if: startsWith( github.ref, 'refs/tags/' )
49
+ run: |
50
+ mkdir -p $HOME/.gem
51
+ touch $HOME/.gem/credentials
52
+ chmod 0600 $HOME/.gem/credentials
53
+ printf -- "---\n:rubygems_api_key: ${GEM_HOST_API_KEY}\n" > $HOME/.gem/credentials
54
+ # TODO: If it is possible to accept input in the middle of a step, then the OTP Token should be inputted instead of generated.
55
+ gem install rotp -v 6.2.0
56
+ OTP_TOKEN=$(echo ${OTP_SECRET} | ruby -rtime -rrotp -e "puts ROTP::TOTP.new(STDIN.read.chomp, issuer: 'rubygems.org').at(Time.now)")
57
+ gem push --otp="${OTP_TOKEN}" ./pkg/*.gem
58
+ env:
59
+ GEM_HOST_API_KEY: "${{secrets.RUBYGEMS_API_KEY}}"
60
+ OTP_SECRET: "${{secrets.RUBYGEMS_OTP_SECRET}}"
data/README.md CHANGED
@@ -17,11 +17,11 @@ kintone output plugin for Embulk stores app records from kintone.
17
17
  - **basic_auth_password**: kintone basic auth password (string, optional)
18
18
  - **guest_space_id**: kintone app belongs to guest space, guest space id is required. (integer, optional)
19
19
  - **mode**: kintone mode (string, required)
20
+ - **update_key**: column name to set update key (string, required if mode is update or upsert)
20
21
  - **column_options** advanced: a key-value pairs where key is a column name and value is options for the column.
21
22
  - **field_code**: field code (string, required)
22
23
  - **type**: field type (string, required)
23
24
  - **timezone**: timezone to convert into `date` (string, default is `UTC`)
24
- - **update_key**: update key (boolean, default is `false`)
25
25
  - **val_sep**: Used to specify multiple checkbox values (string, default is `,`)
26
26
 
27
27
  ## Example
@@ -33,7 +33,8 @@ out:
33
33
  username: username
34
34
  password: password
35
35
  app_id: 1
36
- mode: insert
36
+ mode: upsert
37
+ update_key: id
37
38
  column_options:
38
39
  id: {field_code: "id", type: "NUMBER"}
39
40
  name: {field_code: "name", type: "SINGLE_LINE_TEXT"}
data/build.gradle CHANGED
@@ -14,7 +14,7 @@ configurations {
14
14
  provided
15
15
  }
16
16
 
17
- version = "0.2.2"
17
+ version = "0.3.0"
18
18
 
19
19
  sourceCompatibility = 1.8
20
20
  targetCompatibility = 1.8
@@ -19,10 +19,6 @@ public interface KintoneColumnOption
19
19
  @ConfigDefault("\"UTC\"")
20
20
  public Optional<String> getTimezone();
21
21
 
22
- @Config("update_key")
23
- @ConfigDefault("false")
24
- public boolean getUpdateKey();
25
-
26
22
  @Config("val_sep")
27
23
  @ConfigDefault("\",\"")
28
24
  public String getValueSeparator();
@@ -22,6 +22,7 @@ import java.time.Instant;
22
22
  import java.time.ZoneId;
23
23
  import java.time.ZonedDateTime;
24
24
  import java.util.Map;
25
+ import java.util.Objects;
25
26
 
26
27
  public class KintoneColumnVisitor
27
28
  implements ColumnVisitor
@@ -30,6 +31,7 @@ public class KintoneColumnVisitor
30
31
  private Record record;
31
32
  private UpdateKey updateKey;
32
33
  private Map<String, KintoneColumnOption> columnOptions;
34
+ private String updateKeyName;
33
35
 
34
36
  public KintoneColumnVisitor(PageReader pageReader,
35
37
  Map<String, KintoneColumnOption> columnOptions)
@@ -38,6 +40,15 @@ public class KintoneColumnVisitor
38
40
  this.columnOptions = columnOptions;
39
41
  }
40
42
 
43
+ public KintoneColumnVisitor(PageReader pageReader,
44
+ Map<String, KintoneColumnOption> columnOptions,
45
+ String updateKeyName)
46
+ {
47
+ this.pageReader = pageReader;
48
+ this.columnOptions = columnOptions;
49
+ this.updateKeyName = updateKeyName;
50
+ }
51
+
41
52
  public void setRecord(Record record)
42
53
  {
43
54
  this.record = record;
@@ -50,20 +61,17 @@ public class KintoneColumnVisitor
50
61
 
51
62
  private void setValue(String fieldCode, Object value, FieldType type, boolean isUpdateKey)
52
63
  {
53
- if (value == null) {
54
- return;
55
- }
56
-
57
64
  if (isUpdateKey && updateKey != null) {
58
65
  updateKey
59
66
  .setField(fieldCode)
60
- .setValue(String.valueOf(value));
67
+ .setValue(Objects.toString(value, ""));
61
68
  }
62
- String stringValue = String.valueOf(value);
63
- FieldValue fieldValue = null;
69
+ String stringValue = Objects.toString(value, "");
70
+ FieldValue fieldValue;
64
71
  switch (type) {
65
72
  case NUMBER:
66
- fieldValue = new NumberFieldValue(new BigDecimal(stringValue));
73
+ BigDecimal setValue = stringValue.equals("") ? null : new BigDecimal(stringValue);
74
+ fieldValue = new NumberFieldValue(setValue);
67
75
  break;
68
76
  case MULTI_LINE_TEXT:
69
77
  fieldValue = new MultiLineTextFieldValue(stringValue);
@@ -133,11 +141,11 @@ public class KintoneColumnVisitor
133
141
 
134
142
  private boolean isUpdateKey(Column column)
135
143
  {
136
- KintoneColumnOption option = columnOptions.get(column.getName());
137
- if (option == null) {
144
+ if (this.updateKeyName == null) {
138
145
  return false;
139
146
  }
140
- return option.getUpdateKey();
147
+
148
+ return this.updateKeyName.equals(column.getName());
141
149
  }
142
150
 
143
151
  private String getValueSeparator(Column column)
@@ -162,7 +170,11 @@ public class KintoneColumnVisitor
162
170
  {
163
171
  String fieldCode = getFieldCode(column);
164
172
  FieldType type = getType(column, FieldType.NUMBER);
165
- setValue(fieldCode, pageReader.getLong(column), type, isUpdateKey(column));
173
+ if (pageReader.isNull(column)) {
174
+ setValue(fieldCode, null, type, isUpdateKey(column));
175
+ } else {
176
+ setValue(fieldCode, pageReader.getLong(column), type, isUpdateKey(column));
177
+ }
166
178
  }
167
179
 
168
180
  @Override
@@ -1,6 +1,7 @@
1
1
  package org.embulk.output.kintone;
2
2
 
3
3
  import org.embulk.config.ConfigDiff;
4
+ import org.embulk.config.ConfigException;
4
5
  import org.embulk.config.ConfigSource;
5
6
  import org.embulk.config.TaskReport;
6
7
  import org.embulk.config.TaskSource;
@@ -50,32 +51,18 @@ public class KintoneOutputPlugin
50
51
  KintoneMode mode = KintoneMode.getKintoneModeByValue(task.getMode());
51
52
  switch (mode) {
52
53
  case INSERT:
53
- for (KintoneColumnOption option : options) {
54
- if (option.getUpdateKey()) {
55
- throw new IllegalArgumentException(
56
- "when mode is insert, require no update_key.");
57
- }
54
+ if (task.getUpdateKeyName().isPresent()) {
55
+ throw new ConfigException("when mode is insert, require no update_key.");
58
56
  }
59
57
  break;
60
58
  case UPDATE:
61
59
  case UPSERT:
62
- boolean hasUpdateKey = false;
63
- for (KintoneColumnOption option : options) {
64
- if (option.getUpdateKey()) {
65
- if (hasUpdateKey) {
66
- throw new IllegalArgumentException(
67
- "when mode is update and upsert, only one column can have an update_key.");
68
- }
69
- hasUpdateKey = true;
70
- }
71
- }
72
- if (!hasUpdateKey) {
73
- throw new IllegalArgumentException(
74
- "when mode is update and upsert, require update_key.");
60
+ if (!task.getUpdateKeyName().isPresent()) {
61
+ throw new ConfigException("when mode is update or upsert, require update_key.");
75
62
  }
76
63
  break;
77
64
  default:
78
- throw new IllegalArgumentException(String.format(
65
+ throw new ConfigException(String.format(
79
66
  "Unknown mode '%s'",
80
67
  task.getMode()));
81
68
  }
@@ -3,6 +3,7 @@ package org.embulk.output.kintone;
3
3
  import com.kintone.client.KintoneClient;
4
4
  import com.kintone.client.KintoneClientBuilder;
5
5
  import com.kintone.client.api.record.GetRecordsByCursorResponseBody;
6
+ import com.kintone.client.model.record.FieldType;
6
7
  import com.kintone.client.model.record.Record;
7
8
  import com.kintone.client.model.record.RecordForUpdate;
8
9
  import com.kintone.client.model.record.UpdateKey;
@@ -14,7 +15,6 @@ import org.embulk.spi.PageReader;
14
15
  import org.embulk.spi.Schema;
15
16
  import org.embulk.spi.TransactionalPageOutput;
16
17
 
17
- import java.math.BigDecimal;
18
18
  import java.util.ArrayList;
19
19
  import java.util.Arrays;
20
20
  import java.util.List;
@@ -23,6 +23,8 @@ import java.util.stream.Collectors;
23
23
  public class KintonePageOutput
24
24
  implements TransactionalPageOutput
25
25
  {
26
+ public static final int UPSERT_BATCH_SIZE = 10000;
27
+ public static final int CHUNK_SIZE = 100;
26
28
  private PageReader pageReader;
27
29
  private PluginTask task;
28
30
  private KintoneClient client;
@@ -136,7 +138,7 @@ public class KintonePageOutput
136
138
  }
137
139
 
138
140
  records.add(record);
139
- if (records.size() == 100) {
141
+ if (records.size() == CHUNK_SIZE) {
140
142
  client.record().addRecords(task.getAppId(), records);
141
143
  records.clear();
142
144
  }
@@ -155,10 +157,16 @@ public class KintonePageOutput
155
157
  {
156
158
  execute(client -> {
157
159
  try {
158
- ArrayList<RecordForUpdate> updateRecords = new ArrayList<RecordForUpdate>();
160
+ if (!task.getUpdateKeyName().isPresent()) {
161
+ // already validated in KintoneOutputPlugin.open()
162
+ throw new RuntimeException("unreachable error");
163
+ }
164
+ ArrayList<RecordForUpdate> updateRecords = new ArrayList<>();
159
165
  pageReader.setPage(page);
166
+
160
167
  KintoneColumnVisitor visitor = new KintoneColumnVisitor(pageReader,
161
- task.getColumnOptions());
168
+ task.getColumnOptions(),
169
+ task.getUpdateKeyName().get());
162
170
  while (pageReader.nextRecord()) {
163
171
  Record record = new Record();
164
172
  UpdateKey updateKey = new UpdateKey();
@@ -168,9 +176,13 @@ public class KintonePageOutput
168
176
  column.visit(visitor);
169
177
  }
170
178
 
179
+ if (updateKey.getValue() == "") {
180
+ continue;
181
+ }
182
+
171
183
  record.removeField(updateKey.getField());
172
184
  updateRecords.add(new RecordForUpdate(updateKey, record));
173
- if (updateRecords.size() == 100) {
185
+ if (updateRecords.size() == CHUNK_SIZE) {
174
186
  client.record().updateRecords(task.getAppId(), updateRecords);
175
187
  updateRecords.clear();
176
188
  }
@@ -185,183 +197,133 @@ public class KintonePageOutput
185
197
  });
186
198
  }
187
199
 
188
- private List<Record> getRecordsByUpdateKey(String fieldCode, List<String> queryValues)
200
+ private void upsertPage(final Page page)
189
201
  {
190
- List<Record> allRecords = new ArrayList<Record>();
191
- List<String> fields = Arrays.asList(fieldCode);
192
- String cursorId = client.record().createCursor(
193
- task.getAppId(),
194
- fields,
195
- fieldCode + " in (" + String.join(",", queryValues) + ")"
196
- );
197
- while (true) {
198
- GetRecordsByCursorResponseBody resp = client.record().getRecordsByCursor(cursorId);
199
- List<Record> records = resp.getRecords();
200
- allRecords.addAll(records);
202
+ execute(client -> {
203
+ try {
204
+ if (!task.getUpdateKeyName().isPresent()) {
205
+ // already validated in KintoneOutputPlugin.open()
206
+ throw new RuntimeException("unreachable error");
207
+ }
208
+ ArrayList<Record> records = new ArrayList<>();
209
+ ArrayList<UpdateKey> updateKeys = new ArrayList<>();
210
+ pageReader.setPage(page);
201
211
 
202
- if (!resp.hasNext()) {
203
- break;
212
+ KintoneColumnVisitor visitor = new KintoneColumnVisitor(pageReader,
213
+ task.getColumnOptions(),
214
+ task.getUpdateKeyName().get());
215
+ while (pageReader.nextRecord()) {
216
+ Record record = new Record();
217
+ UpdateKey updateKey = new UpdateKey();
218
+ visitor.setRecord(record);
219
+ visitor.setUpdateKey(updateKey);
220
+ for (Column column : pageReader.getSchema().getColumns()) {
221
+ column.visit(visitor);
222
+ }
223
+ records.add(record);
224
+ updateKeys.add(updateKey);
225
+
226
+ if (records.size() == UPSERT_BATCH_SIZE) {
227
+ upsert(records, updateKeys);
228
+ records.clear();
229
+ updateKeys.clear();
230
+ }
231
+ }
232
+ if (records.size() > 0) {
233
+ upsert(records, updateKeys);
234
+ }
204
235
  }
205
- }
206
- return allRecords;
236
+ catch (Exception e) {
237
+ throw new RuntimeException("kintone throw exception", e);
238
+ }
239
+ });
207
240
  }
208
241
 
209
- abstract class UpsertPage<T>
242
+ private void upsert(ArrayList<Record> records, ArrayList<UpdateKey> updateKeys)
210
243
  {
211
- public abstract List<T> getUpdateKeyValues(List<String> queryValues);
212
- public abstract boolean existsRecord(List<T> updateKeyValues, Record record);
213
-
214
- public void upsert(ArrayList<Record> records, ArrayList<UpdateKey> updateKeys)
215
- {
216
- if (records.size() != updateKeys.size()) {
217
- throw new RuntimeException("records.size() != updateKeys.size()");
218
- }
219
-
220
- List<String> queryValues = updateKeys
221
- .stream()
222
- .map(k -> "\"" + k.getValue().toString() + "\"")
223
- .collect(Collectors.toList());
224
- List<T> updateKeyValues = getUpdateKeyValues(queryValues);
244
+ if (records.size() != updateKeys.size()) {
245
+ throw new RuntimeException("records.size() != updateKeys.size()");
246
+ }
225
247
 
226
- ArrayList<Record> insertRecords = new ArrayList<>();
227
- ArrayList<RecordForUpdate> updateRecords = new ArrayList<RecordForUpdate>();
228
- for (int i = 0; i < records.size(); i++) {
229
- Record record = records.get(i);
230
- UpdateKey updateKey = updateKeys.get(i);
248
+ List<Record> existingRecords = getExistingRecordsByUpdateKey(updateKeys);
231
249
 
232
- if (existsRecord(updateKeyValues, record)) {
233
- record.removeField(updateKey.getField());
234
- updateRecords.add(new RecordForUpdate(updateKey, record));
235
- }
236
- else {
237
- insertRecords.add(record);
238
- }
250
+ ArrayList<Record> insertRecords = new ArrayList<>();
251
+ ArrayList<RecordForUpdate> updateRecords = new ArrayList<>();
252
+ for (int i = 0; i < records.size(); i++) {
253
+ Record record = records.get(i);
254
+ UpdateKey updateKey = updateKeys.get(i);
239
255
 
240
- if (insertRecords.size() == 100) {
241
- client.record().addRecords(task.getAppId(), insertRecords);
242
- insertRecords.clear();
243
- }
244
- else if (updateRecords.size() == 100) {
245
- client.record().updateRecords(task.getAppId(), updateRecords);
246
- updateRecords.clear();
247
- }
256
+ if (existsRecord(existingRecords, updateKey)) {
257
+ record.removeField(updateKey.getField());
258
+ updateRecords.add(new RecordForUpdate(updateKey, record));
259
+ }
260
+ else {
261
+ insertRecords.add(record);
248
262
  }
249
- if (insertRecords.size() > 0) {
263
+
264
+ if (insertRecords.size() == CHUNK_SIZE) {
250
265
  client.record().addRecords(task.getAppId(), insertRecords);
266
+ insertRecords.clear();
251
267
  }
252
- if (updateRecords.size() > 0) {
268
+ else if (updateRecords.size() == CHUNK_SIZE) {
253
269
  client.record().updateRecords(task.getAppId(), updateRecords);
270
+ updateRecords.clear();
254
271
  }
255
272
  }
256
-
257
- public void run(final Page page)
258
- {
259
- execute(client -> {
260
- try {
261
- ArrayList<Record> records = new ArrayList<>();
262
- ArrayList<UpdateKey> updateKeys = new ArrayList<>();
263
-
264
- pageReader.setPage(page);
265
- KintoneColumnVisitor visitor = new KintoneColumnVisitor(pageReader,
266
- task.getColumnOptions());
267
- while (pageReader.nextRecord()) {
268
- Record record = new Record();
269
- UpdateKey updateKey = new UpdateKey();
270
- visitor.setRecord(record);
271
- visitor.setUpdateKey(updateKey);
272
- for (Column column : pageReader.getSchema().getColumns()) {
273
- column.visit(visitor);
274
- }
275
- records.add(record);
276
- updateKeys.add(updateKey);
277
-
278
- if (records.size() == 10000) {
279
- upsert(records, updateKeys);
280
- records.clear();
281
- updateKeys.clear();
282
- }
283
- }
284
- if (records.size() > 0) {
285
- upsert(records, updateKeys);
286
- }
287
- }
288
- catch (Exception e) {
289
- throw new RuntimeException("kintone throw exception", e);
290
- }
291
- });
292
- }
293
- }
294
-
295
- class UpsertPageByStringKey extends UpsertPage<String>
296
- {
297
- private String fieldCode;
298
-
299
- public UpsertPageByStringKey(String fieldCode)
300
- {
301
- this.fieldCode = fieldCode;
302
- }
303
-
304
- public List<String> getUpdateKeyValues(List<String> queryValues)
305
- {
306
- return getRecordsByUpdateKey(fieldCode, queryValues)
307
- .stream()
308
- .map(r -> r.getSingleLineTextFieldValue(fieldCode))
309
- .collect(Collectors.toList());
273
+ if (insertRecords.size() > 0) {
274
+ client.record().addRecords(task.getAppId(), insertRecords);
310
275
  }
311
-
312
- public boolean existsRecord(List<String> updateKeyValues, Record record)
313
- {
314
- return updateKeyValues.contains(record.getSingleLineTextFieldValue(fieldCode));
276
+ if (updateRecords.size() > 0) {
277
+ client.record().updateRecords(task.getAppId(), updateRecords);
315
278
  }
316
279
  }
317
280
 
318
- class UpsertPageByNumberKey extends UpsertPage<BigDecimal>
319
- {
320
- private String fieldCode;
321
-
322
- public UpsertPageByNumberKey(String fieldCode)
323
- {
324
- this.fieldCode = fieldCode;
325
- }
326
281
 
327
- public List<BigDecimal> getUpdateKeyValues(List<String> queryValues)
328
- {
329
- return getRecordsByUpdateKey(fieldCode, queryValues)
282
+ private List<Record> getExistingRecordsByUpdateKey(ArrayList<UpdateKey> updateKeys)
283
+ {
284
+ String fieldCode = updateKeys.get(0).getField();
285
+ List<String> queryValues = updateKeys
330
286
  .stream()
331
- .map(r -> r.getNumberFieldValue(fieldCode))
287
+ .filter(k -> k.getValue() != "")
288
+ .map(k -> "\"" + k.getValue().toString() + "\"")
332
289
  .collect(Collectors.toList());
333
- }
334
290
 
335
- public boolean existsRecord(List<BigDecimal> updateKeyValues, Record record)
336
- {
337
- return updateKeyValues.contains(record.getNumberFieldValue(fieldCode));
291
+ List<Record> allRecords = new ArrayList<>();
292
+ if (queryValues.isEmpty()) {
293
+ return allRecords;
338
294
  }
339
- }
295
+ String cursorId = client.record().createCursor(
296
+ task.getAppId(),
297
+ Arrays.asList(fieldCode),
298
+ fieldCode + " in (" + String.join(",", queryValues) + ")"
299
+ );
300
+ while (true) {
301
+ GetRecordsByCursorResponseBody resp = client.record().getRecordsByCursor(cursorId);
302
+ List<Record> records = resp.getRecords();
303
+ allRecords.addAll(records);
340
304
 
341
- private void upsertPage(final Page page)
342
- {
343
- KintoneColumnOption updateKeyColumn = null;
344
- for (KintoneColumnOption v : task.getColumnOptions().values()) {
345
- if (v.getUpdateKey()) {
346
- updateKeyColumn = v;
305
+ if (!resp.hasNext()) {
347
306
  break;
348
307
  }
349
308
  }
350
- if (updateKeyColumn == null) {
351
- throw new RuntimeException("when mode is upsert, require update_key");
352
- }
309
+ return allRecords;
310
+ }
353
311
 
354
- UpsertPage runner;
355
- switch(updateKeyColumn.getType()) {
356
- case "SINGLE_LINE_TEXT":
357
- runner = new UpsertPageByStringKey(updateKeyColumn.getFieldCode());
358
- break;
359
- case "NUMBER":
360
- runner = new UpsertPageByNumberKey(updateKeyColumn.getFieldCode());
361
- break;
312
+ private boolean existsRecord(List<Record> distRecords, UpdateKey updateKey)
313
+ {
314
+ String fieldCode = updateKey.getField();
315
+ FieldType type = client.app().getFormFields(task.getAppId()).get(fieldCode).getType();
316
+ switch (type) {
317
+ case SINGLE_LINE_TEXT:
318
+ return distRecords
319
+ .stream()
320
+ .anyMatch(d -> d.getSingleLineTextFieldValue(fieldCode).equals(updateKey.getValue()));
321
+ case NUMBER:
322
+ return distRecords
323
+ .stream()
324
+ .anyMatch(d -> d.getNumberFieldValue(fieldCode).equals(updateKey.getValue()));
362
325
  default:
363
326
  throw new RuntimeException("The update_key must be 'SINGLE_LINE_TEXT' or 'NUMBER'.");
364
327
  }
365
- runner.run(page);
366
328
  }
367
329
  }
@@ -47,4 +47,8 @@ public interface PluginTask
47
47
  @Config("mode")
48
48
  @ConfigDefault("insert")
49
49
  public String getMode();
50
+
51
+ @Config("update_key")
52
+ @ConfigDefault("null")
53
+ Optional<String> getUpdateKeyName();
50
54
  }
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: embulk-output-kintone
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.2
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - takeshi fujita
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-11-18 00:00:00.000000000 Z
11
+ date: 2022-03-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  requirement: !ruby/object:Gem::Requirement
@@ -52,7 +52,7 @@ files:
52
52
  - README.md
53
53
  - Rakefile
54
54
  - build.gradle
55
- - classpath/embulk-output-kintone-0.2.2.jar
55
+ - classpath/embulk-output-kintone-0.3.0.jar
56
56
  - config/checkstyle/checkstyle.xml
57
57
  - config/checkstyle/default.xml
58
58
  - gradle/wrapper/gradle-wrapper.jar