Skip to content

Commit fa77644

Browse files
committed
Add support for update by id
1 parent 738985d commit fa77644

File tree

125 files changed

+752
-117
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

125 files changed

+752
-117
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ kintone output plugin for Embulk stores app records from kintone.
2626
- **max_sort_memory**: Maximum memory usage for sorting input records (bytes in long, default is the estimated available memory, which is the approximate value of the JVM's current free memory)
2727
- **prefer_nulls**: Whether to set fields to null instead of default value of type when column is null (boolean, default is `false`)
2828
- **ignore_nulls**: Whether to completely ignore fields when column is null (boolean, default is `false`)
29+
- **skip_if_non_existing_id_or_update_key**: Skip policy if id or update key of record does not exist (string `auto`, `never` or `always`, default is `auto`)
2930
- **column_options** advanced: a key-value pairs where key is a column name and value is options for the column.
3031
- **field_code**: field code (string, required)
3132
- **type**: field type (string, required). See [this page](https://cybozu.dev/ja/kintone/docs/overview/field-types/#field-type-update) for list of available types. However, following types are not yet supported

src/main/java/org/embulk/output/kintone/KintoneClient.java

Lines changed: 30 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,12 @@
88
import java.util.Map;
99
import java.util.function.Supplier;
1010
import org.embulk.config.ConfigException;
11+
import org.embulk.output.kintone.record.Id;
1112
import org.embulk.output.kintone.util.Lazy;
1213
import org.embulk.spi.Column;
1314
import org.embulk.spi.Schema;
15+
import org.embulk.spi.type.Type;
16+
import org.embulk.spi.type.Types;
1417

1518
public class KintoneClient implements AutoCloseable {
1619
private final PluginTask task;
@@ -49,19 +52,13 @@ private KintoneClient(PluginTask task, Schema schema) {
4952
KintoneMode.of(task).validate(task, this);
5053
}
5154

52-
public void validateUpdateKey(String columnName) {
55+
public void validateIdOrUpdateKey(String columnName) {
5356
Column column = getColumn(columnName);
5457
if (column == null) {
5558
throw new ConfigException("The column '" + columnName + "' for update does not exist.");
5659
}
57-
String fieldCode = getFieldCode(column);
58-
FieldType fieldType = getFieldType(fieldCode);
59-
if (fieldType == null) {
60-
throw new ConfigException("The field '" + fieldCode + "' for update does not exist.");
61-
}
62-
if (fieldType != FieldType.SINGLE_LINE_TEXT && fieldType != FieldType.NUMBER) {
63-
throw new ConfigException("The update_key must be 'SINGLE_LINE_TEXT' or 'NUMBER'.");
64-
}
60+
validateId(column);
61+
validateUpdateKey(column);
6562
}
6663

6764
public Column getColumn(String columnName) {
@@ -89,6 +86,30 @@ public void close() {
8986
}
9087
}
9188

89+
private void validateId(Column column) {
90+
if (!column.getName().equals(Id.FIELD)) {
91+
return;
92+
}
93+
Type type = column.getType();
94+
if (!type.equals(Types.LONG)) {
95+
throw new ConfigException("The id column must be 'long'.");
96+
}
97+
}
98+
99+
private void validateUpdateKey(Column column) {
100+
if (column.getName().equals(Id.FIELD)) {
101+
return;
102+
}
103+
String fieldCode = getFieldCode(column);
104+
FieldType fieldType = getFieldType(fieldCode);
105+
if (fieldType == null) {
106+
throw new ConfigException("The field '" + fieldCode + "' for update does not exist.");
107+
}
108+
if (fieldType != FieldType.SINGLE_LINE_TEXT && fieldType != FieldType.NUMBER) {
109+
throw new ConfigException("The update_key must be 'SINGLE_LINE_TEXT' or 'NUMBER'.");
110+
}
111+
}
112+
92113
private String getFieldCode(Column column) {
93114
KintoneColumnOption option = task.getColumnOptions().get(column.getName());
94115
return option != null ? option.getFieldCode() : column.getName();

src/main/java/org/embulk/output/kintone/KintoneColumnVisitor.java

Lines changed: 54 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,12 @@
44
import com.kintone.client.model.record.Record;
55
import com.kintone.client.model.record.UpdateKey;
66
import java.time.Instant;
7+
import java.util.Arrays;
8+
import java.util.List;
79
import java.util.Map;
810
import java.util.Set;
11+
import org.embulk.output.kintone.record.Id;
12+
import org.embulk.output.kintone.record.IdOrUpdateKey;
913
import org.embulk.spi.Column;
1014
import org.embulk.spi.ColumnVisitor;
1115
import org.embulk.spi.PageReader;
@@ -14,6 +18,7 @@
1418
import org.msgpack.value.ValueFactory;
1519

1620
public class KintoneColumnVisitor implements ColumnVisitor {
21+
private static final List<String> BUILTIN_FIELD_CODES = Arrays.asList(Id.FIELD, "$revision");
1722
private final PageReader reader;
1823
private final Set<Column> derived;
1924
private final Map<String, KintoneColumnOption> options;
@@ -22,7 +27,7 @@ public class KintoneColumnVisitor implements ColumnVisitor {
2227
private final String reduceKeyName;
2328
private final String updateKeyName;
2429
private Record record;
25-
private UpdateKey updateKey;
30+
private IdOrUpdateKey idOrUpdateKey;
2631

2732
public KintoneColumnVisitor(
2833
PageReader reader,
@@ -55,8 +60,8 @@ public void setRecord(Record record) {
5560
this.record = record;
5661
}
5762

58-
public void setUpdateKey(UpdateKey updateKey) {
59-
this.updateKey = updateKey;
63+
public void setIdOrUpdateKey(IdOrUpdateKey idOrUpdateKey) {
64+
this.idOrUpdateKey = idOrUpdateKey;
6065
}
6166

6267
@Override
@@ -68,6 +73,9 @@ public void booleanColumn(Column column) {
6873
UpdateKey updateKey = getUpdateKey(column);
6974
KintoneColumnType type = KintoneColumnType.getType(option, KintoneColumnType.NUMBER);
7075
String fieldCode = getFieldCode(column);
76+
if (isBuiltin(fieldCode)) {
77+
return;
78+
}
7179
if (isPreferNull(column)) {
7280
setNull(type, fieldCode, updateKey);
7381
} else if (reader.isNull(column)) {
@@ -82,10 +90,18 @@ public void longColumn(Column column) {
8290
if (isReduced(column) || isIgnoreNull(column)) {
8391
return;
8492
}
93+
Id id = getId(column);
94+
if (id != null) {
95+
setIdValue(id, column);
96+
return;
97+
}
8598
KintoneColumnOption option = getOption(column);
8699
UpdateKey updateKey = getUpdateKey(column);
87100
KintoneColumnType type = KintoneColumnType.getType(option, KintoneColumnType.NUMBER);
88101
String fieldCode = getFieldCode(column);
102+
if (isBuiltin(fieldCode)) {
103+
return;
104+
}
89105
if (isPreferNull(column)) {
90106
setNull(type, fieldCode, updateKey);
91107
} else if (reader.isNull(column)) {
@@ -104,6 +120,9 @@ public void doubleColumn(Column column) {
104120
UpdateKey updateKey = getUpdateKey(column);
105121
KintoneColumnType type = KintoneColumnType.getType(option, KintoneColumnType.NUMBER);
106122
String fieldCode = getFieldCode(column);
123+
if (isBuiltin(fieldCode)) {
124+
return;
125+
}
107126
if (isPreferNull(column)) {
108127
setNull(type, fieldCode, updateKey);
109128
} else if (reader.isNull(column)) {
@@ -124,6 +143,9 @@ public void stringColumn(Column column) {
124143
updateKey != null ? KintoneColumnType.SINGLE_LINE_TEXT : KintoneColumnType.MULTI_LINE_TEXT;
125144
KintoneColumnType type = KintoneColumnType.getType(option, defaultType);
126145
String fieldCode = getFieldCode(column);
146+
if (isBuiltin(fieldCode)) {
147+
return;
148+
}
127149
if (isPreferNull(column)) {
128150
setNull(type, fieldCode, updateKey);
129151
} else if (reader.isNull(column)) {
@@ -142,6 +164,9 @@ public void timestampColumn(Column column) {
142164
UpdateKey updateKey = getUpdateKey(column);
143165
KintoneColumnType type = KintoneColumnType.getType(option, KintoneColumnType.DATETIME);
144166
String fieldCode = getFieldCode(column);
167+
if (isBuiltin(fieldCode)) {
168+
return;
169+
}
145170
if (isPreferNull(column)) {
146171
setNull(type, fieldCode, updateKey);
147172
} else if (reader.isNull(column)) {
@@ -162,6 +187,9 @@ public void jsonColumn(Column column) {
162187
isDerived(column) ? KintoneColumnType.SUBTABLE : KintoneColumnType.MULTI_LINE_TEXT;
163188
KintoneColumnType type = KintoneColumnType.getType(option, defaultType);
164189
String fieldCode = getFieldCode(column);
190+
if (isBuiltin(fieldCode)) {
191+
return;
192+
}
165193
if (isPreferNull(column)) {
166194
setNull(type, fieldCode, updateKey);
167195
} else if (reader.isNull(column)) {
@@ -171,6 +199,16 @@ public void jsonColumn(Column column) {
171199
}
172200
}
173201

202+
private void setIdValue(Id id, Column column) {
203+
if (isPreferNull(column)) {
204+
id.setValue(null);
205+
} else if (reader.isNull(column)) {
206+
id.setValue(0L);
207+
} else {
208+
id.setValue(reader.getLong(column));
209+
}
210+
}
211+
174212
private void setNull(KintoneColumnType type, String fieldCode, UpdateKey updateKey) {
175213
if (updateKey != null) {
176214
type.setUpdateKey(updateKey, fieldCode);
@@ -265,8 +303,16 @@ private KintoneColumnOption getOption(Column column) {
265303
return options.get(column.getName());
266304
}
267305

306+
private Id getId(Column column) {
307+
return column.getName().equals(updateKeyName) && updateKeyName.equals(Id.FIELD)
308+
? idOrUpdateKey.getId()
309+
: null;
310+
}
311+
268312
private UpdateKey getUpdateKey(Column column) {
269-
return updateKeyName != null && updateKeyName.equals(column.getName()) ? updateKey : null;
313+
return column.getName().equals(updateKeyName) && !updateKeyName.equals(Id.FIELD)
314+
? idOrUpdateKey.getUpdateKey()
315+
: null;
270316
}
271317

272318
private boolean isReduced(Column column) {
@@ -284,4 +330,8 @@ private boolean isIgnoreNull(Column column) {
284330
private boolean isPreferNull(Column column) {
285331
return preferNulls && reader.isNull(column);
286332
}
333+
334+
private static boolean isBuiltin(String fieldCode) {
335+
return BUILTIN_FIELD_CODES.contains(fieldCode);
336+
}
287337
}

src/main/java/org/embulk/output/kintone/KintoneMode.java

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
package org.embulk.output.kintone;
22

3+
import java.util.function.Consumer;
34
import org.embulk.config.ConfigException;
5+
import org.embulk.output.kintone.record.Id;
6+
import org.embulk.output.kintone.record.Skip;
47
import org.embulk.spi.Page;
58

69
public enum KintoneMode {
@@ -13,35 +16,36 @@ public void validate(PluginTask task, KintoneClient client) {
1316
}
1417

1518
@Override
16-
public void add(Page page, KintonePageOutput output) {
19+
public void add(Page page, Skip skip, KintonePageOutput output) {
1720
output.insertPage(page);
1821
}
1922
},
2023
UPDATE("update") {
2124
@Override
2225
public void validate(PluginTask task, KintoneClient client) {
23-
if (!task.getUpdateKeyName().isPresent()) {
24-
throw new ConfigException("When mode is update, require update_key.");
26+
if (!task.getUpdateKeyName().isPresent() && client.getColumn(Id.FIELD) == null) {
27+
throw new ConfigException("When mode is update, require update_key or id column.");
2528
}
26-
client.validateUpdateKey(task.getUpdateKeyName().orElse(null));
29+
client.validateIdOrUpdateKey(task.getUpdateKeyName().orElse(Id.FIELD));
2730
}
2831

2932
@Override
30-
public void add(Page page, KintonePageOutput output) {
31-
output.updatePage(page);
33+
public void add(Page page, Skip skip, KintonePageOutput output) {
34+
Consumer<Page> consumer = skip == Skip.ALWAYS ? output::upsertPage : output::updatePage;
35+
consumer.accept(page);
3236
}
3337
},
3438
UPSERT("upsert") {
3539
@Override
3640
public void validate(PluginTask task, KintoneClient client) {
37-
if (!task.getUpdateKeyName().isPresent()) {
38-
throw new ConfigException("When mode is upsert, require update_key.");
41+
if (!task.getUpdateKeyName().isPresent() && client.getColumn(Id.FIELD) == null) {
42+
throw new ConfigException("When mode is upsert, require update_key or id column.");
3943
}
40-
client.validateUpdateKey(task.getUpdateKeyName().orElse(null));
44+
client.validateIdOrUpdateKey(task.getUpdateKeyName().orElse(Id.FIELD));
4145
}
4246

4347
@Override
44-
public void add(Page page, KintonePageOutput output) {
48+
public void add(Page page, Skip skip, KintonePageOutput output) {
4549
output.upsertPage(page);
4650
}
4751
};
@@ -53,7 +57,7 @@ public void add(Page page, KintonePageOutput output) {
5357

5458
public abstract void validate(PluginTask task, KintoneClient client);
5559

56-
public abstract void add(Page page, KintonePageOutput output);
60+
public abstract void add(Page page, Skip skip, KintonePageOutput output);
5761

5862
@Override
5963
public String toString() {

0 commit comments

Comments
 (0)