Skip to content

Commit 69de22c

Browse files
ArtDuAlexey Kuzin
authored andcommitted
Parse metadata from crud response
Closes #272
1 parent 97f2a19 commit 69de22c

10 files changed

Lines changed: 215 additions & 58 deletions

File tree

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
## [Unreleased]
44

5+
- Parse metadata from crud response ([#272](https://github.com/tarantool/cartridge-java/pull/272))
56
- Use netty part dependencies instead of netty-all ([#295](https://github.com/tarantool/cartridge-java/issues/295))
67
- Refactor mappers and split `TarantoolResultConverter` ([#301](https://github.com/tarantool/cartridge-java/pull/301))
78
- **[breaking change]** `TarantoolResultConverter` was removed, use `DefaultArrayValueToTarantoolResultConverter` or `DefaultMapValueToTarantoolTupleResultConverter` instead ([#301](https://github.com/tarantool/cartridge-java/pull/301))
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
package io.tarantool.driver.core;
2+
3+
import io.tarantool.driver.api.metadata.TarantoolSpaceMetadata;
4+
import io.tarantool.driver.api.tuple.TarantoolTuple;
5+
import io.tarantool.driver.exceptions.TarantoolTupleConversionException;
6+
import io.tarantool.driver.mappers.converters.value.ArrayValueToTarantoolTupleConverter;
7+
import org.msgpack.core.MessageTypeCastException;
8+
import org.msgpack.value.ArrayValue;
9+
import org.msgpack.value.Value;
10+
11+
import java.util.stream.Collectors;
12+
13+
/**
14+
* Specific TarantoolResult implementation especially for TarantoolTuple input
15+
*
16+
* @author Artyom Dubinin
17+
*/
18+
public class TarantoolTupleResultImpl extends TarantoolResultImpl<TarantoolTuple> {
19+
20+
public TarantoolTupleResultImpl(ArrayValue rawTuples, TarantoolSpaceMetadata metadata,
21+
ArrayValueToTarantoolTupleConverter tupleConverter) {
22+
setItems(rawTuples, metadata, tupleConverter);
23+
}
24+
25+
public TarantoolTupleResultImpl(Value value, ArrayValueToTarantoolTupleConverter tupleConverter) {
26+
setItems(value.asArrayValue(), tupleConverter);
27+
}
28+
29+
private void setItems(ArrayValue tupleArray, TarantoolSpaceMetadata responseMetadata,
30+
ArrayValueToTarantoolTupleConverter tupleConverter) {
31+
this.tuples = tupleArray.list().stream()
32+
.map(v -> {
33+
try {
34+
return tupleConverter.fromValue(v.asArrayValue(), responseMetadata);
35+
} catch (MessageTypeCastException e) {
36+
throw new TarantoolTupleConversionException(v, e);
37+
}
38+
})
39+
.collect(Collectors.toList());
40+
}
41+
}
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
package io.tarantool.driver.core.metadata;
2+
3+
import io.tarantool.driver.api.TarantoolResult;
4+
import io.tarantool.driver.api.metadata.TarantoolFieldMetadata;
5+
import io.tarantool.driver.api.metadata.TarantoolSpaceMetadata;
6+
import io.tarantool.driver.api.tuple.TarantoolTuple;
7+
import io.tarantool.driver.core.TarantoolTupleResultImpl;
8+
import io.tarantool.driver.exceptions.TarantoolClientException;
9+
import io.tarantool.driver.mappers.converters.ValueConverter;
10+
import io.tarantool.driver.mappers.converters.value.ArrayValueToTarantoolTupleConverter;
11+
import org.msgpack.value.ArrayValue;
12+
import org.msgpack.value.MapValue;
13+
import org.msgpack.value.StringValue;
14+
import org.msgpack.value.Value;
15+
import org.msgpack.value.ValueFactory;
16+
17+
import java.util.LinkedHashMap;
18+
import java.util.List;
19+
import java.util.Map;
20+
21+
/**
22+
* @author Artyom Dubinin
23+
*/
24+
public class RowsMetadataToTarantoolTupleResultConverter
25+
implements ValueConverter<MapValue, TarantoolResult<TarantoolTuple>> {
26+
27+
private static final long serialVersionUID = -5228606294087295535L;
28+
29+
protected static final StringValue RESULT_META = ValueFactory.newString("metadata");
30+
protected static final StringValue RESULT_ROWS = ValueFactory.newString("rows");
31+
protected static final StringValue FORMAT_NAME_KEY = ValueFactory.newString("name");
32+
protected static final StringValue FORMAT_TYPE_KEY = ValueFactory.newString("type");
33+
34+
private final ArrayValueToTarantoolTupleConverter tupleConverter;
35+
36+
public RowsMetadataToTarantoolTupleResultConverter(ArrayValueToTarantoolTupleConverter tupleConverter) {
37+
super();
38+
this.tupleConverter = tupleConverter;
39+
}
40+
41+
@Override
42+
public TarantoolResult<TarantoolTuple> fromValue(MapValue value) {
43+
Map<Value, Value> tupleMap = value.asMapValue().map();
44+
ArrayValue rawTuples = tupleMap.get(RESULT_ROWS).asArrayValue();
45+
ArrayValue rawMetadata = tupleMap.get(RESULT_META).asArrayValue();
46+
TarantoolSpaceMetadata parsedMetadata = parseCRUDMetadata(rawMetadata);
47+
48+
return new TarantoolTupleResultImpl(rawTuples, parsedMetadata, tupleConverter);
49+
}
50+
51+
@Override
52+
public boolean canConvertValue(MapValue value) {
53+
// [{"metadata" : [...], "rows": [...]}]
54+
Map<Value, Value> tupleMap = value.asMapValue().map();
55+
if (!hasRowsAndMetadata(tupleMap)) {
56+
return false;
57+
}
58+
return tupleMap.get(RESULT_ROWS).isArrayValue() && tupleMap.get(RESULT_META).isArrayValue();
59+
}
60+
61+
static boolean hasRowsAndMetadata(Map<Value, Value> valueMap) {
62+
return valueMap.containsKey(RESULT_META) && valueMap.containsKey(RESULT_ROWS);
63+
}
64+
65+
private TarantoolSpaceMetadata parseCRUDMetadata(Value metadata) {
66+
if (metadata == null || !metadata.isArrayValue()) {
67+
throw new TarantoolClientException("Unsupported crud metadata format: expected array of maps");
68+
}
69+
70+
List<Value> responseFormat = metadata.asArrayValue().list();
71+
72+
Map<String, TarantoolFieldMetadata> spaceFormatMetadata = new LinkedHashMap<>();
73+
int fieldPosition = 0;
74+
for (Value value : responseFormat) {
75+
if (!value.isMapValue()) {
76+
throw new TarantoolClientException("Unsupported crud metadata format: expected array of maps");
77+
}
78+
Map<Value, Value> fieldMap = value.asMapValue().map();
79+
80+
Value fieldNameValue = fieldMap.get(FORMAT_NAME_KEY);
81+
if (fieldNameValue == null || !fieldNameValue.isStringValue()) {
82+
throw new TarantoolClientException(
83+
"Unsupported space metadata format: key '" + FORMAT_NAME_KEY + "' must have string value," +
84+
" get " + fieldNameValue);
85+
}
86+
String fieldName = fieldNameValue.asStringValue().asString();
87+
88+
Value fieldTypeValue = fieldMap.get(FORMAT_TYPE_KEY);
89+
if (fieldTypeValue == null || !fieldTypeValue.isStringValue()) {
90+
throw new TarantoolClientException(
91+
"Unsupported space metadata format: key '" + FORMAT_TYPE_KEY + "' must have string value," +
92+
" get " + fieldNameValue);
93+
}
94+
String fieldType = fieldTypeValue.asStringValue().asString();
95+
96+
spaceFormatMetadata.put(fieldName,
97+
new TarantoolFieldMetadataImpl(fieldName, fieldType, fieldPosition++));
98+
}
99+
100+
TarantoolSpaceMetadataImpl spaceMetadata = new TarantoolSpaceMetadataImpl();
101+
spaceMetadata.setSpaceFormatMetadata(spaceFormatMetadata);
102+
103+
return spaceMetadata;
104+
}
105+
}

src/main/java/io/tarantool/driver/mappers/converters/value/ArrayValueToTarantoolTupleConverter.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
* Default {@link ArrayValue} to {@link TarantoolTuple} converter
1212
*
1313
* @author Sergey Volgin
14+
* @author Artyom Dubinin
1415
*/
1516
public class ArrayValueToTarantoolTupleConverter implements ValueConverter<ArrayValue, TarantoolTuple> {
1617

@@ -28,4 +29,8 @@ public ArrayValueToTarantoolTupleConverter(MessagePackMapper mapper, TarantoolSp
2829
public TarantoolTuple fromValue(ArrayValue value) {
2930
return new TarantoolTupleImpl(value, mapper, spaceMetadata);
3031
}
32+
33+
public TarantoolTuple fromValue(ArrayValue value, TarantoolSpaceMetadata responseMetadata) {
34+
return new TarantoolTupleImpl(value, mapper, responseMetadata);
35+
}
3136
}

src/main/java/io/tarantool/driver/mappers/converters/value/ArrayValueToTarantoolTupleResultConverter.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import io.tarantool.driver.api.TarantoolResult;
44
import io.tarantool.driver.api.tuple.TarantoolTuple;
55
import io.tarantool.driver.core.TarantoolResultImpl;
6+
import io.tarantool.driver.core.TarantoolTupleResultImpl;
67
import io.tarantool.driver.mappers.converters.ValueConverter;
78
import org.msgpack.value.ArrayValue;
89

@@ -14,16 +15,16 @@ public class ArrayValueToTarantoolTupleResultConverter
1415

1516
private static final long serialVersionUID = -1348387430063097175L;
1617

17-
private final ValueConverter<ArrayValue, TarantoolTuple> tupleConverter;
18+
private final ArrayValueToTarantoolTupleConverter tupleConverter;
1819

1920
public ArrayValueToTarantoolTupleResultConverter(
20-
ValueConverter<ArrayValue, TarantoolTuple> tupleConverter) {
21+
ArrayValueToTarantoolTupleConverter tupleConverter) {
2122
super();
2223
this.tupleConverter = tupleConverter;
2324
}
2425

2526
@Override
2627
public TarantoolResult<TarantoolTuple> fromValue(ArrayValue value) {
27-
return new TarantoolResultImpl<>(value, tupleConverter);
28+
return new TarantoolTupleResultImpl(value, tupleConverter);
2829
}
2930
}

src/main/java/io/tarantool/driver/mappers/converters/value/RowsMetadataToTarantoolTupleResultConverter.java

Lines changed: 0 additions & 54 deletions
This file was deleted.

src/main/java/io/tarantool/driver/mappers/factories/RowsMetadataToTarantoolTupleResultMapperFactory.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
import io.tarantool.driver.mappers.MessagePackValueMapper;
77
import io.tarantool.driver.mappers.TarantoolResultMapper;
88
import io.tarantool.driver.mappers.converters.value.ArrayValueToTarantoolTupleConverter;
9-
import io.tarantool.driver.mappers.converters.value.RowsMetadataToTarantoolTupleResultConverter;
9+
import io.tarantool.driver.core.metadata.RowsMetadataToTarantoolTupleResultConverter;
1010
import org.msgpack.value.ValueType;
1111

1212
/**

src/test/java/io/tarantool/driver/integration/ProxyTarantoolClientIT.java

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -390,6 +390,42 @@ public void test_clusterUpdate_shouldReturnTuple_ifSearchByFieldName() throws Ex
390390
assertEquals(42, updateResult.get(0).getInteger(2));
391391
}
392392

393+
@Test
394+
public void test_crudMetadataResponse_shouldReturnTuple_withoutDDLMetadata()
395+
throws ExecutionException, InterruptedException {
396+
Integer id = 123000;
397+
String field1 = "Jane Doe";
398+
Integer field2 = 999;
399+
Boolean field3 = true;
400+
Double field4 = 123.456;
401+
402+
List<Object> values = Arrays.asList(id, null, field1, field2);
403+
TarantoolTuple tarantoolTuple = tupleFactory.create(values);
404+
client.space("test_space").insert(tarantoolTuple).get();
405+
406+
values = Arrays.asList(id, null, field3, field4);
407+
tarantoolTuple = tupleFactory.create(values);
408+
client.space("test_space_to_join").insert(tarantoolTuple).get();
409+
410+
CallResultMapper<TarantoolResult<TarantoolTuple>, SingleValueCallResult<TarantoolResult<TarantoolTuple>>>
411+
defaultResultMapper = mapperFactoryFactory.singleValueTupleResultMapperFactory()
412+
.withSingleValueRowsMetadataToTarantoolTupleResultMapper(defaultMapper, null);
413+
414+
TarantoolResult<TarantoolTuple> result =
415+
client.callForSingleResult(
416+
"get_composite_data_with_crud",
417+
Collections.singletonList(id),
418+
defaultResultMapper
419+
).get();
420+
assertEquals(1, result.size());
421+
TarantoolTuple tuple = result.get(0);
422+
assertEquals(id, tuple.getObject("id").orElse(null));
423+
assertEquals(field1, tuple.getObject("field1").orElse(null));
424+
assertEquals(field2, tuple.getObject("field2").orElse(null));
425+
assertEquals(field3, tuple.getObject("field3").orElse(null));
426+
assertEquals(field4, tuple.getObject("field4").orElse(null));
427+
}
428+
393429
@Test
394430
public void clusterUpsertTest() throws ExecutionException, InterruptedException {
395431
TarantoolSpaceOperations<TarantoolTuple, TarantoolResult<TarantoolTuple>> profileSpace =

src/test/resources/cartridge/app/roles/api_router.lua

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,7 @@ local function init()
214214
rawset(_G, 'init_router_status', init_router_status)
215215
rawset(_G, 'test_no_such_procedure', test_no_such_procedure)
216216
rawset(_G, 'get_other_storage_bucket_id', crud_utils.get_other_storage_bucket_id)
217+
rawset(_G, 'get_composite_data_with_crud', crud_utils.get_composite_data_with_crud)
217218
rawset(_G, 'vshard', vshard)
218219

219220
create_restricted_user()

src/test/resources/cartridge/utils/crud.lua

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,27 @@ local function get_other_storage_bucket_id(key)
3131
return res_bucket_id
3232
end
3333

34+
local function get_composite_data_with_crud(id)
35+
local test_space = crud.get("test_space", id)
36+
local test_space_to_join = crud.get("test_space_to_join", id)
37+
38+
table.move(
39+
test_space_to_join.metadata,
40+
1,
41+
#test_space_to_join.metadata,
42+
#test_space.metadata + 1,
43+
test_space.metadata)
44+
table.move(
45+
test_space_to_join.rows[1],
46+
1,
47+
#test_space_to_join.rows[1],
48+
#test_space.rows[1] + 1,
49+
test_space.rows[1]
50+
)
51+
return test_space
52+
end
53+
3454
return {
3555
get_other_storage_bucket_id = get_other_storage_bucket_id,
56+
get_composite_data_with_crud = get_composite_data_with_crud,
3657
}

0 commit comments

Comments
 (0)