embulk-output-kintone 0.2.0 → 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: 12c249d873d4feb22cad46c5d7bd8858f21c6138
4
- data.tar.gz: fe0ff0d7a8433caa4afe30a90c2acd7bdffb73ac
3
+ metadata.gz: 2004bfc2e202eeb6c57f3149bc7311f90343a67e
4
+ data.tar.gz: 86e036bc863ac7d8ca632488d0eb84c645658c43
5
5
  SHA512:
6
- metadata.gz: 6f6a9c530c8c9ea1b3324aace5dbac3a9cbb6eaf9a800a064942f1229565a86cfb0ad51bd95ce53cadfc014320981c4e126addf699a32e16b90e7667a2745004
7
- data.tar.gz: 96f86db9027769370cf6af39f2ff157d7ca6b691d1712fa2ec112e04a464dc87e6db5b3d664ef45d69db73f213ce5e7007f0321c86809a5d5d17c11b1bb0479f
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.0"
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,36 +61,31 @@ 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
- else {
63
- String stringValue = String.valueOf(value);
64
- FieldValue fieldValue = null;
65
- switch (type) {
66
- case NUMBER:
67
- fieldValue = new NumberFieldValue(new BigDecimal(stringValue));
68
- break;
69
- case MULTI_LINE_TEXT:
70
- fieldValue = new MultiLineTextFieldValue(stringValue);
71
- break;
72
- case DROP_DOWN:
73
- fieldValue = new DropDownFieldValue(stringValue);
74
- break;
75
- case LINK:
76
- fieldValue = new LinkFieldValue(stringValue);
77
- break;
78
- default:
79
- fieldValue = new SingleLineTextFieldValue(stringValue);
80
- }
81
- record.putField(fieldCode, fieldValue);
69
+ String stringValue = Objects.toString(value, "");
70
+ FieldValue fieldValue;
71
+ switch (type) {
72
+ case NUMBER:
73
+ BigDecimal setValue = stringValue.equals("") ? null : new BigDecimal(stringValue);
74
+ fieldValue = new NumberFieldValue(setValue);
75
+ break;
76
+ case MULTI_LINE_TEXT:
77
+ fieldValue = new MultiLineTextFieldValue(stringValue);
78
+ break;
79
+ case DROP_DOWN:
80
+ fieldValue = new DropDownFieldValue(stringValue);
81
+ break;
82
+ case LINK:
83
+ fieldValue = new LinkFieldValue(stringValue);
84
+ break;
85
+ default:
86
+ fieldValue = new SingleLineTextFieldValue(stringValue);
82
87
  }
88
+ record.putField(fieldCode, fieldValue);
83
89
  }
84
90
 
85
91
  private void setTimestampValue(String fieldCode, Instant instant, ZoneId zoneId, FieldType type)
@@ -135,11 +141,11 @@ public class KintoneColumnVisitor
135
141
 
136
142
  private boolean isUpdateKey(Column column)
137
143
  {
138
- KintoneColumnOption option = columnOptions.get(column.getName());
139
- if (option == null) {
144
+ if (this.updateKeyName == null) {
140
145
  return false;
141
146
  }
142
- return option.getUpdateKey();
147
+
148
+ return this.updateKeyName.equals(column.getName());
143
149
  }
144
150
 
145
151
  private String getValueSeparator(Column column)
@@ -164,7 +170,11 @@ public class KintoneColumnVisitor
164
170
  {
165
171
  String fieldCode = getFieldCode(column);
166
172
  FieldType type = getType(column, FieldType.NUMBER);
167
- 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
+ }
168
178
  }
169
179
 
170
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,17 +15,16 @@ 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
- import java.util.HashMap;
21
20
  import java.util.List;
22
- import java.util.Map;
23
21
  import java.util.stream.Collectors;
24
22
 
25
23
  public class KintonePageOutput
26
24
  implements TransactionalPageOutput
27
25
  {
26
+ public static final int UPSERT_BATCH_SIZE = 10000;
27
+ public static final int CHUNK_SIZE = 100;
28
28
  private PageReader pageReader;
29
29
  private PluginTask task;
30
30
  private KintoneClient client;
@@ -138,7 +138,7 @@ public class KintonePageOutput
138
138
  }
139
139
 
140
140
  records.add(record);
141
- if (records.size() == 100) {
141
+ if (records.size() == CHUNK_SIZE) {
142
142
  client.record().addRecords(task.getAppId(), records);
143
143
  records.clear();
144
144
  }
@@ -157,10 +157,16 @@ public class KintonePageOutput
157
157
  {
158
158
  execute(client -> {
159
159
  try {
160
- 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<>();
161
165
  pageReader.setPage(page);
166
+
162
167
  KintoneColumnVisitor visitor = new KintoneColumnVisitor(pageReader,
163
- task.getColumnOptions());
168
+ task.getColumnOptions(),
169
+ task.getUpdateKeyName().get());
164
170
  while (pageReader.nextRecord()) {
165
171
  Record record = new Record();
166
172
  UpdateKey updateKey = new UpdateKey();
@@ -170,9 +176,13 @@ public class KintonePageOutput
170
176
  column.visit(visitor);
171
177
  }
172
178
 
179
+ if (updateKey.getValue() == "") {
180
+ continue;
181
+ }
182
+
173
183
  record.removeField(updateKey.getField());
174
184
  updateRecords.add(new RecordForUpdate(updateKey, record));
175
- if (updateRecords.size() == 100) {
185
+ if (updateRecords.size() == CHUNK_SIZE) {
176
186
  client.record().updateRecords(task.getAppId(), updateRecords);
177
187
  updateRecords.clear();
178
188
  }
@@ -187,150 +197,133 @@ public class KintonePageOutput
187
197
  });
188
198
  }
189
199
 
190
- private List<Record> getAllRecords(String fieldCode)
200
+ private void upsertPage(final Page page)
191
201
  {
192
- List<Record> allRecords = new ArrayList<Record>();
193
- List<String> fields = Arrays.asList(fieldCode);
194
- String cursorId = client.record().createCursor(task.getAppId(), fields, null);
195
- while (true) {
196
- GetRecordsByCursorResponseBody resp = client.record().getRecordsByCursor(cursorId);
197
- List<Record> records = resp.getRecords();
198
- allRecords.addAll(records);
199
-
200
- if (!resp.hasNext()) {
201
- break;
202
- }
203
- }
204
- return allRecords;
205
- }
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);
206
211
 
207
- abstract class UpsertPage<T>
208
- {
209
- public abstract List<T> getUpdateKeyValues();
210
- public abstract boolean existsRecord(List<T> updateKeyValues, Record record);
211
-
212
- public void run(final Page page)
213
- {
214
- execute(client -> {
215
- try {
216
- List<T> updateKeyValues = getUpdateKeyValues();
217
-
218
- ArrayList<Record> insertRecords = new ArrayList<>();
219
- ArrayList<RecordForUpdate> updateRecords = new ArrayList<RecordForUpdate>();
220
- pageReader.setPage(page);
221
- KintoneColumnVisitor visitor = new KintoneColumnVisitor(pageReader,
222
- task.getColumnOptions());
223
- while (pageReader.nextRecord()) {
224
- Record record = new Record();
225
- UpdateKey updateKey = new UpdateKey();
226
- visitor.setRecord(record);
227
- visitor.setUpdateKey(updateKey);
228
- for (Column column : pageReader.getSchema().getColumns()) {
229
- column.visit(visitor);
230
- }
231
-
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
- }
239
-
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
- }
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);
248
222
  }
223
+ records.add(record);
224
+ updateKeys.add(updateKey);
249
225
 
250
- if (insertRecords.size() > 0) {
251
- client.record().addRecords(task.getAppId(), insertRecords);
252
- }
253
- if (updateRecords.size() > 0) {
254
- client.record().updateRecords(task.getAppId(), updateRecords);
226
+ if (records.size() == UPSERT_BATCH_SIZE) {
227
+ upsert(records, updateKeys);
228
+ records.clear();
229
+ updateKeys.clear();
255
230
  }
256
231
  }
257
- catch (Exception e) {
258
- throw new RuntimeException("kintone throw exception", e);
232
+ if (records.size() > 0) {
233
+ upsert(records, updateKeys);
259
234
  }
260
- });
261
- }
235
+ }
236
+ catch (Exception e) {
237
+ throw new RuntimeException("kintone throw exception", e);
238
+ }
239
+ });
262
240
  }
263
241
 
264
- class UpsertPageByStringKey extends UpsertPage<String>
242
+ private void upsert(ArrayList<Record> records, ArrayList<UpdateKey> updateKeys)
265
243
  {
266
- private String fieldCode;
267
-
268
- public UpsertPageByStringKey(String fieldCode)
269
- {
270
- this.fieldCode = fieldCode;
244
+ if (records.size() != updateKeys.size()) {
245
+ throw new RuntimeException("records.size() != updateKeys.size()");
271
246
  }
272
247
 
273
- public List<String> getUpdateKeyValues()
274
- {
275
- return getAllRecords(fieldCode)
276
- .stream()
277
- .map(r -> r.getSingleLineTextFieldValue(fieldCode))
278
- .collect(Collectors.toList());
279
- }
248
+ List<Record> existingRecords = getExistingRecordsByUpdateKey(updateKeys);
280
249
 
281
- public boolean existsRecord(List<String> updateKeyValues, Record record)
282
- {
283
- return updateKeyValues.contains(record.getSingleLineTextFieldValue(fieldCode));
284
- }
285
- }
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);
286
255
 
287
- class UpsertPageByNumberKey extends UpsertPage<BigDecimal>
288
- {
289
- private String fieldCode;
256
+ if (existsRecord(existingRecords, updateKey)) {
257
+ record.removeField(updateKey.getField());
258
+ updateRecords.add(new RecordForUpdate(updateKey, record));
259
+ }
260
+ else {
261
+ insertRecords.add(record);
262
+ }
290
263
 
291
- public UpsertPageByNumberKey(String fieldCode)
292
- {
293
- this.fieldCode = fieldCode;
264
+ if (insertRecords.size() == CHUNK_SIZE) {
265
+ client.record().addRecords(task.getAppId(), insertRecords);
266
+ insertRecords.clear();
267
+ }
268
+ else if (updateRecords.size() == CHUNK_SIZE) {
269
+ client.record().updateRecords(task.getAppId(), updateRecords);
270
+ updateRecords.clear();
271
+ }
272
+ }
273
+ if (insertRecords.size() > 0) {
274
+ client.record().addRecords(task.getAppId(), insertRecords);
275
+ }
276
+ if (updateRecords.size() > 0) {
277
+ client.record().updateRecords(task.getAppId(), updateRecords);
294
278
  }
279
+ }
280
+
295
281
 
296
- public List<BigDecimal> getUpdateKeyValues()
297
- {
298
- return getAllRecords(fieldCode)
282
+ private List<Record> getExistingRecordsByUpdateKey(ArrayList<UpdateKey> updateKeys)
283
+ {
284
+ String fieldCode = updateKeys.get(0).getField();
285
+ List<String> queryValues = updateKeys
299
286
  .stream()
300
- .map(r -> r.getNumberFieldValue(fieldCode))
287
+ .filter(k -> k.getValue() != "")
288
+ .map(k -> "\"" + k.getValue().toString() + "\"")
301
289
  .collect(Collectors.toList());
302
- }
303
290
 
304
- public boolean existsRecord(List<BigDecimal> updateKeyValues, Record record)
305
- {
306
- return updateKeyValues.contains(record.getNumberFieldValue(fieldCode));
291
+ List<Record> allRecords = new ArrayList<>();
292
+ if (queryValues.isEmpty()) {
293
+ return allRecords;
307
294
  }
308
- }
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);
309
304
 
310
- private void upsertPage(final Page page)
311
- {
312
- KintoneColumnOption updateKeyColumn = null;
313
- for (KintoneColumnOption v : task.getColumnOptions().values()) {
314
- if (v.getUpdateKey()) {
315
- updateKeyColumn = v;
305
+ if (!resp.hasNext()) {
316
306
  break;
317
307
  }
318
308
  }
319
- if (updateKeyColumn == null) {
320
- throw new RuntimeException("when mode is upsert, require update_key");
321
- }
309
+ return allRecords;
310
+ }
322
311
 
323
- UpsertPage runner;
324
- switch(updateKeyColumn.getType()) {
325
- case "SINGLE_LINE_TEXT":
326
- runner = new UpsertPageByStringKey(updateKeyColumn.getFieldCode());
327
- break;
328
- case "NUMBER":
329
- runner = new UpsertPageByNumberKey(updateKeyColumn.getFieldCode());
330
- 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()));
331
325
  default:
332
326
  throw new RuntimeException("The update_key must be 'SINGLE_LINE_TEXT' or 'NUMBER'.");
333
327
  }
334
- runner.run(page);
335
328
  }
336
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.0
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-09-25 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.0.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