diff --git a/.github/workflows/tests-ce.yml b/.github/workflows/tests-ce.yml index de0d9dc0..c05d3eea 100644 --- a/.github/workflows/tests-ce.yml +++ b/.github/workflows/tests-ce.yml @@ -14,7 +14,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - tarantool-version: [ "1.10", "2.8" ] + tarantool-version: [ "1.10", "2.8", "2.10.3" ] fail-fast: false steps: - uses: actions/checkout@v2 diff --git a/CHANGELOG.md b/CHANGELOG.md index 40f974dd..0cd0f06a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,8 @@ ## [Unreleased] - Adding default mapper for long arrays ([#290](https://github.com/tarantool/cartridge-java/pull/290)) +- Support Datetime type ([#293](https://github.com/tarantool/cartridge-java/pull/293)) + ## [0.9.1] - 2022-10-13 diff --git a/src/main/java/io/tarantool/driver/api/tuple/TarantoolTuple.java b/src/main/java/io/tarantool/driver/api/tuple/TarantoolTuple.java index ac1b3476..87d5878c 100644 --- a/src/main/java/io/tarantool/driver/api/tuple/TarantoolTuple.java +++ b/src/main/java/io/tarantool/driver/api/tuple/TarantoolTuple.java @@ -3,6 +3,7 @@ import io.tarantool.driver.protocol.Packable; import java.math.BigDecimal; +import java.time.Instant; import java.util.List; import java.util.Map; import java.util.Optional; @@ -16,7 +17,7 @@ public interface TarantoolTuple extends Iterable, Packable { /** * Get a tuple field by its position - * @param fieldPosition the field position from the the tuple start, starting from 0 + * @param fieldPosition the field position from the tuple start, starting from 0 * @return field or empty optional if the field position is out of tuple length */ Optional getField(int fieldPosition); @@ -38,7 +39,7 @@ public interface TarantoolTuple extends Iterable, Packable { /** * Get a tuple field value by its position specifying the target value type - * @param fieldPosition field position from the the tuple start, starting from 0 + * @param fieldPosition field position from the tuple start, starting from 0 * @param objectClass target value type class * @param target value type * @return nullable value of a field wrapped in Optional, possibly converted to a Java type @@ -47,7 +48,7 @@ public interface TarantoolTuple extends Iterable, Packable { /** * Check if a tuple field exists and can be converted to the target value type - * @param fieldPosition field position from the the tuple start, starting from 0 + * @param fieldPosition field position from the tuple start, starting from 0 * @param objectClass target value type class * @return true, if the field exists and can be converted to the given type, false otherwise */ @@ -72,7 +73,7 @@ public interface TarantoolTuple extends Iterable, Packable { /** * Get a tuple field value as a raw object - * @param fieldPosition field position from the the tuple start, starting from 0 + * @param fieldPosition field position from the tuple start, starting from 0 * @return nullable value of a field wrapped in Optional */ Optional getObject(int fieldPosition); @@ -94,7 +95,7 @@ public interface TarantoolTuple extends Iterable, Packable { /** * Set a tuple field by field position * - * @param fieldPosition the field position from the the tuple start, starting from 0 + * @param fieldPosition the field position from the tuple start, starting from 0 * @param field new field */ void setField(int fieldPosition, TarantoolField field); @@ -110,7 +111,7 @@ public interface TarantoolTuple extends Iterable, Packable { /** * Set a tuple field value from an object by field position * - * @param fieldPosition the field position from the the tuple start, starting from 0 + * @param fieldPosition the field position from the tuple start, starting from 0 * @param value new field value */ void putObject(int fieldPosition, Object value); @@ -126,7 +127,7 @@ public interface TarantoolTuple extends Iterable, Packable { /** * Get the field value converted to {@code byte[]} * - * @param fieldPosition the field position from the the tuple start, starting from 0 + * @param fieldPosition the field position from the tuple start, starting from 0 * @return value */ byte[] getByteArray(int fieldPosition); @@ -142,7 +143,7 @@ public interface TarantoolTuple extends Iterable, Packable { /** * Get the field value converted to {@code Boolean} * - * @param fieldPosition the field position from the the tuple start, starting from 0 + * @param fieldPosition the field position from the tuple start, starting from 0 * @return value */ Boolean getBoolean(int fieldPosition); @@ -158,7 +159,7 @@ public interface TarantoolTuple extends Iterable, Packable { /** * Get the field value converted to {@code Double} * - * @param fieldPosition the field position from the the tuple start, starting from 0 + * @param fieldPosition the field position from the tuple start, starting from 0 * @return value */ Double getDouble(int fieldPosition); @@ -174,7 +175,7 @@ public interface TarantoolTuple extends Iterable, Packable { /** * Get the field value converted to {@code Float} * - * @param fieldPosition the field position from the the tuple start, starting from 0 + * @param fieldPosition the field position from the tuple start, starting from 0 * @return value */ Float getFloat(int fieldPosition); @@ -190,7 +191,7 @@ public interface TarantoolTuple extends Iterable, Packable { /** * Get the field value converted to {@code Integer} * - * @param fieldPosition the field position from the the tuple start, starting from 0 + * @param fieldPosition the field position from the tuple start, starting from 0 * @return value */ Integer getInteger(int fieldPosition); @@ -206,7 +207,7 @@ public interface TarantoolTuple extends Iterable, Packable { /** * Get the field value converted to {@code Long} * - * @param fieldPosition the field position from the the tuple start, starting from 0 + * @param fieldPosition the field position from the tuple start, starting from 0 * @return value */ Long getLong(int fieldPosition); @@ -222,7 +223,7 @@ public interface TarantoolTuple extends Iterable, Packable { /** * Get the field value converted to {@code String} * - * @param fieldPosition the field position from the the tuple start, starting from 0 + * @param fieldPosition the field position from the tuple start, starting from 0 * @return value */ String getString(int fieldPosition); @@ -238,7 +239,7 @@ public interface TarantoolTuple extends Iterable, Packable { /** * Get the field value converted to {@code Character} * - * @param fieldPosition the field position from the the tuple start, starting from 0 + * @param fieldPosition the field position from the tuple start, starting from 0 * @return value */ Character getCharacter(int fieldPosition); @@ -254,7 +255,7 @@ public interface TarantoolTuple extends Iterable, Packable { /** * Get the field value converted to {@link UUID} * - * @param fieldPosition the field position from the the tuple start, starting from 0 + * @param fieldPosition the field position from the tuple start, starting from 0 * @return value */ UUID getUUID(int fieldPosition); @@ -267,10 +268,26 @@ public interface TarantoolTuple extends Iterable, Packable { */ UUID getUUID(String fieldName); + /** + * Get the field value converted to {@link Instant} + * + * @param fieldPosition the field position from the tuple start, starting from 0 + * @return value + */ + Instant getInstant(int fieldPosition); + + /** + * Get the field value converted to {@link Instant} + * + * @param fieldName the field name, must not be null + * @return value + */ + Instant getInstant(String fieldName); + /** * Get the field value converted to {@link BigDecimal} * - * @param fieldPosition the field position from the the tuple start, starting from 0 + * @param fieldPosition the field position from the tuple start, starting from 0 * @return value */ BigDecimal getDecimal(int fieldPosition); @@ -286,7 +303,7 @@ public interface TarantoolTuple extends Iterable, Packable { /** * Get the field value converted to {@link List} * - * @param fieldPosition the field position from the the tuple start, starting from 0 + * @param fieldPosition the field position from the tuple start, starting from 0 * @return value */ List getList(int fieldPosition); @@ -302,7 +319,7 @@ public interface TarantoolTuple extends Iterable, Packable { /** * Get the field value converted to {@link Map} * - * @param fieldPosition the field position from the the tuple start, starting from 0 + * @param fieldPosition the field position from the tuple start, starting from 0 * @return value */ Map getMap(int fieldPosition); diff --git a/src/main/java/io/tarantool/driver/core/tuple/TarantoolTupleImpl.java b/src/main/java/io/tarantool/driver/core/tuple/TarantoolTupleImpl.java index 681299f8..30108639 100644 --- a/src/main/java/io/tarantool/driver/core/tuple/TarantoolTupleImpl.java +++ b/src/main/java/io/tarantool/driver/core/tuple/TarantoolTupleImpl.java @@ -18,6 +18,7 @@ import java.io.IOException; import java.math.BigDecimal; +import java.time.Instant; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; @@ -361,6 +362,16 @@ public UUID getUUID(String fieldName) { return getObject(fieldName, UUID.class).orElse(null); } + @Override + public Instant getInstant(int fieldPosition) { + return getObject(fieldPosition, Instant.class).orElse(null); + } + + @Override + public Instant getInstant(String fieldName) { + return getObject(fieldName, Instant.class).orElse(null); + } + @Override public BigDecimal getDecimal(int fieldPosition) { return getObject(fieldPosition, BigDecimal.class).orElse(null); diff --git a/src/main/java/io/tarantool/driver/mappers/DefaultMessagePackMapperFactory.java b/src/main/java/io/tarantool/driver/mappers/DefaultMessagePackMapperFactory.java index 22f7cb75..bcfa2081 100644 --- a/src/main/java/io/tarantool/driver/mappers/DefaultMessagePackMapperFactory.java +++ b/src/main/java/io/tarantool/driver/mappers/DefaultMessagePackMapperFactory.java @@ -1,5 +1,6 @@ package io.tarantool.driver.mappers; +import io.tarantool.driver.mappers.converters.object.DefaultInstantToExtensionValueConverter; import io.tarantool.driver.mappers.converters.object.DefaultNilValueToNullConverter; import io.tarantool.driver.mappers.converters.object.DefaultBigDecimalToExtensionValueConverter; import io.tarantool.driver.mappers.converters.object.DefaultLongArrayToArrayValueConverter; @@ -18,6 +19,7 @@ import io.tarantool.driver.mappers.converters.value.DefaultBinaryValueToByteArrayConverter; import io.tarantool.driver.mappers.converters.value.DefaultBooleanValueToBooleanConverter; import io.tarantool.driver.mappers.converters.value.DefaultExtensionValueToBigDecimalConverter; +import io.tarantool.driver.mappers.converters.value.DefaultExtensionValueToInstantConverter; import io.tarantool.driver.mappers.converters.value.DefaultExtensionValueToUUIDConverter; import io.tarantool.driver.mappers.converters.value.DefaultFloatValueToDoubleConverter; import io.tarantool.driver.mappers.converters.value.DefaultFloatValueToFloatConverter; @@ -42,6 +44,7 @@ import org.msgpack.value.ValueType; import java.math.BigDecimal; +import java.time.Instant; import java.util.UUID; /** @@ -81,6 +84,7 @@ private DefaultMessagePackMapperFactory() { .withValueConverter(ValueType.EXTENSION, UUID.class, new DefaultExtensionValueToUUIDConverter()) .withValueConverter(ValueType.EXTENSION, BigDecimal.class, new DefaultExtensionValueToBigDecimalConverter()) + .withValueConverter(ValueType.EXTENSION, Instant.class, new DefaultExtensionValueToInstantConverter()) .withValueConverter(ValueType.NIL, Object.class, new DefaultNilValueToNullConverter()) //TODO: Potential issue https://github.com/tarantool/cartridge-java/issues/118 .withObjectConverter(Character.class, StringValue.class, new DefaultCharacterToStringValueConverter()) @@ -96,6 +100,7 @@ private DefaultMessagePackMapperFactory() { .withObjectConverter(UUID.class, ExtensionValue.class, new DefaultUUIDToExtensionValueConverter()) .withObjectConverter(BigDecimal.class, ExtensionValue.class, new DefaultBigDecimalToExtensionValueConverter()) + .withObjectConverter(Instant.class, ExtensionValue.class, new DefaultInstantToExtensionValueConverter()) .build(); } diff --git a/src/main/java/io/tarantool/driver/mappers/converters/object/DefaultInstantToExtensionValueConverter.java b/src/main/java/io/tarantool/driver/mappers/converters/object/DefaultInstantToExtensionValueConverter.java new file mode 100644 index 00000000..ce8e0dd7 --- /dev/null +++ b/src/main/java/io/tarantool/driver/mappers/converters/object/DefaultInstantToExtensionValueConverter.java @@ -0,0 +1,31 @@ +package io.tarantool.driver.mappers.converters.object; + +import io.tarantool.driver.mappers.converters.ObjectConverter; +import org.msgpack.value.ExtensionValue; +import org.msgpack.value.ValueFactory; + +import java.nio.ByteBuffer; +import java.time.Instant; + +/** + * Default {@link java.time.Instant} to {@link ExtensionValue} converter + * + * @author Anastasiia Romanova + */ +public class DefaultInstantToExtensionValueConverter implements ObjectConverter { + + private static final long serialVersionUID = 20221025L; + + private static final byte DATETIME_TYPE = 0x04; + + private byte[] toBytes(Instant value) { + ByteBuffer buffer = ByteBuffer.wrap(new byte[8]); + buffer.putLong(0, value.getEpochSecond()); + return buffer.array(); + } + + @Override + public ExtensionValue toValue(Instant object) { + return ValueFactory.newExtension(DATETIME_TYPE, toBytes(object)); + } +} diff --git a/src/main/java/io/tarantool/driver/mappers/converters/value/DefaultExtensionValueToInstantConverter.java b/src/main/java/io/tarantool/driver/mappers/converters/value/DefaultExtensionValueToInstantConverter.java new file mode 100644 index 00000000..ed37019c --- /dev/null +++ b/src/main/java/io/tarantool/driver/mappers/converters/value/DefaultExtensionValueToInstantConverter.java @@ -0,0 +1,33 @@ +package io.tarantool.driver.mappers.converters.value; + +import io.tarantool.driver.mappers.converters.ValueConverter; +import org.msgpack.value.ExtensionValue; + +import java.nio.ByteBuffer; +import java.time.Instant; + +/** + * Default {@link ExtensionValue} to {@link java.time.Instant} converter + * + * @author Anastasiia Romanova + */ +public class DefaultExtensionValueToInstantConverter implements ValueConverter { + + private static final long serialVersionUID = 20221025L; + private static final byte DATETIME_TYPE = 0x04; + + private Instant fromBytes(byte[] bytes) { + ByteBuffer buffer = ByteBuffer.wrap(bytes); + return Instant.ofEpochSecond(buffer.getLong()); + } + + @Override + public Instant fromValue(ExtensionValue value) { + return fromBytes(value.getData()); + } + + @Override + public boolean canConvertValue(ExtensionValue value) { + return value.getType() == DATETIME_TYPE; + } +} diff --git a/src/test/java/io/tarantool/driver/TarantoolUtils.java b/src/test/java/io/tarantool/driver/TarantoolUtils.java index 8e24d579..c5457eb6 100644 --- a/src/test/java/io/tarantool/driver/TarantoolUtils.java +++ b/src/test/java/io/tarantool/driver/TarantoolUtils.java @@ -31,6 +31,10 @@ public static boolean versionWithUUID() { return versionGreaterThen("2.4"); } + public static boolean versionWithInstant() { + return versionGreaterThen("2.10"); + } + public static boolean versionWithVarbinary() { return versionGreaterThen("2.2.1"); } diff --git a/src/test/java/io/tarantool/driver/integration/ConvertersWithClusterClientIT.java b/src/test/java/io/tarantool/driver/integration/ConvertersWithClusterClientIT.java index aeceb66e..c71ab28e 100644 --- a/src/test/java/io/tarantool/driver/integration/ConvertersWithClusterClientIT.java +++ b/src/test/java/io/tarantool/driver/integration/ConvertersWithClusterClientIT.java @@ -15,6 +15,7 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.api.condition.EnabledIf; +import java.time.Instant; import java.util.UUID; import org.testcontainers.shaded.org.apache.commons.lang.ArrayUtils; @@ -65,6 +66,23 @@ public void test_boxSelect_shouldReturnTupleWithUUID() throws Exception { Assertions.assertEquals(uuid, fields.getUUID("uuid_field")); } + @Test + @EnabledIf("io.tarantool.driver.TarantoolUtils#versionWithInstant") + public void test_boxSelect_shouldReturnTupleWithInstant() throws Exception { + //given + Instant instant = Instant.now(); + client.space("space_with_instant") + .insert(tupleFactory.create(1, instant)).get(); + + //when + TarantoolTuple fields = client + .space("space_with_instant") + .select(Conditions.equals("id", 1)).get().get(0); + + //then + Assertions.assertEquals(instant, fields.getInstant("instant_field")); + } + @Test @EnabledIf("io.tarantool.driver.TarantoolUtils#versionWithVarbinary") public void test_boxOperations_shouldWorkWithVarbinary() throws Exception { diff --git a/src/test/java/io/tarantool/driver/integration/ConvertersWithProxyClientIT.java b/src/test/java/io/tarantool/driver/integration/ConvertersWithProxyClientIT.java index 348de77f..0c0e84a7 100644 --- a/src/test/java/io/tarantool/driver/integration/ConvertersWithProxyClientIT.java +++ b/src/test/java/io/tarantool/driver/integration/ConvertersWithProxyClientIT.java @@ -13,6 +13,7 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.api.condition.EnabledIf; +import java.time.Instant; import java.util.UUID; import org.junit.jupiter.api.Disabled; import org.testcontainers.shaded.org.apache.commons.lang.ArrayUtils; @@ -65,6 +66,23 @@ public void test_crudSelect_shouldReturnTupleWithUUID() throws Exception { Assertions.assertEquals(uuid, fields.getUUID("uuid_field")); } + @Test + @EnabledIf("io.tarantool.driver.TarantoolUtils#versionWithInstant") + public void test_crudSelect_shouldReturnTupleWithInstant() throws Exception { + //given + Instant instant = Instant.now(); + client.space("space_with_instant") + .insert(tupleFactory.create(1, instant)).get(); + + //when + TarantoolTuple fields = client + .space("space_with_instant") + .select(Conditions.equals("id", 1)).get().get(0); + + //then + Assertions.assertEquals(instant, fields.getInstant("instant_field")); + } + @Test @Disabled("Until https://github.com/tarantool/tarantool/issues/1629 is fixed") @EnabledIf("io.tarantool.driver.TarantoolUtils#versionWithVarbinary") diff --git a/src/test/java/io/tarantool/driver/mappers/DefaultInstantConverterTest.java b/src/test/java/io/tarantool/driver/mappers/DefaultInstantConverterTest.java new file mode 100644 index 00000000..8a649c4d --- /dev/null +++ b/src/test/java/io/tarantool/driver/mappers/DefaultInstantConverterTest.java @@ -0,0 +1,56 @@ +package io.tarantool.driver.mappers; + +import io.tarantool.driver.mappers.converters.object.DefaultInstantToExtensionValueConverter; +import io.tarantool.driver.mappers.converters.object.DefaultUUIDToExtensionValueConverter; +import io.tarantool.driver.mappers.converters.value.DefaultExtensionValueToInstantConverter; +import io.tarantool.driver.mappers.converters.value.DefaultExtensionValueToUUIDConverter; +import org.junit.jupiter.api.Test; +import org.msgpack.core.MessageBufferPacker; +import org.msgpack.core.MessagePack; +import org.msgpack.core.MessagePacker; +import org.msgpack.value.ExtensionValue; +import org.msgpack.value.ImmutableExtensionValue; +import org.msgpack.value.ValueFactory; + +import java.io.IOException; +import java.time.Instant; +import java.time.LocalDateTime; +import java.time.ZoneId; +import java.time.ZoneOffset; +import java.util.Base64; +import java.util.UUID; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + +class DefaultInstantConverterTest { + @Test + void toValue() throws IOException { + DefaultInstantToExtensionValueConverter converter = new DefaultInstantToExtensionValueConverter(); + MessagePacker packer = MessagePack.newDefaultBufferPacker(); + Base64.Encoder encoder = Base64.getEncoder(); + Instant instant = LocalDateTime.parse("2022-10-25T12:03:58").toInstant(ZoneOffset.UTC); + byte[] result = ((MessageBufferPacker) packer.packValue(converter.toValue(instant))).toByteArray(); + assertEquals("1wQAAAAAY1fQrg==", encoder.encodeToString(result)); + } + + @Test + void fromValue() throws IOException { + DefaultExtensionValueToInstantConverter converter = new DefaultExtensionValueToInstantConverter(); + Base64.Decoder base64decoder = Base64.getDecoder(); + Instant instant = LocalDateTime.parse("2022-10-25T12:03:58").toInstant(ZoneOffset.UTC); + byte[] packed = base64decoder.decode("1wQAAAAAY1fQrg=="); + ExtensionValue value = MessagePack.newDefaultUnpacker(packed).unpackValue().asExtensionValue(); + assertEquals(instant, converter.fromValue(value)); + } + + @Test + void canConvertValue() { + DefaultExtensionValueToInstantConverter converter = new DefaultExtensionValueToInstantConverter(); + assertFalse(converter.canConvertValue(ValueFactory.newExtension((byte) 100, new byte[]{0}))); + assertFalse(converter.canConvertValue(ValueFactory.newExtension((byte) 0x01, new byte[]{0}))); + ImmutableExtensionValue value = ValueFactory.newExtension((byte) 0x04, new byte[]{0}); + assertTrue(converter.canConvertValue(value)); + } +} diff --git a/src/test/java/io/tarantool/driver/mappers/DefaultMessagePackMapperTest.java b/src/test/java/io/tarantool/driver/mappers/DefaultMessagePackMapperTest.java index be790559..b9c5563e 100644 --- a/src/test/java/io/tarantool/driver/mappers/DefaultMessagePackMapperTest.java +++ b/src/test/java/io/tarantool/driver/mappers/DefaultMessagePackMapperTest.java @@ -2,8 +2,8 @@ import io.tarantool.driver.CustomTuple; import io.tarantool.driver.api.tuple.DefaultTarantoolTupleFactory; -import io.tarantool.driver.api.tuple.TarantoolTupleFactory; import io.tarantool.driver.api.tuple.TarantoolTuple; +import io.tarantool.driver.api.tuple.TarantoolTupleFactory; import io.tarantool.driver.mappers.converters.ValueConverter; import org.junit.jupiter.api.Test; import org.msgpack.core.MessageTypeCastException; @@ -16,6 +16,9 @@ import org.msgpack.value.impl.ImmutableStringValueImpl; import java.math.BigDecimal; +import java.time.Instant; +import java.time.LocalDateTime; +import java.time.ZoneOffset; import java.util.Arrays; import java.util.HashMap; import java.util.List; @@ -76,6 +79,10 @@ void getDefaultConverter() throws MessagePackValueMapperException { UUID uuid = UUID.fromString("84b56906-aeed-11ea-b3de-0242ac130004"); assertEquals(uuid, mapper.fromValue(mapper.toValue(uuid))); + //instant + Instant instant = LocalDateTime.parse("2022-10-25T12:03:58").toInstant(ZoneOffset.UTC); + assertEquals(instant, mapper.fromValue(mapper.toValue(instant))); + // null assertEquals(ValueFactory.newNil(), mapper.toValue(null)); } diff --git a/src/test/resources/cartridge/app/roles/api_storage.lua b/src/test/resources/cartridge/app/roles/api_storage.lua index e9cdcb0d..9a04e93c 100644 --- a/src/test/resources/cartridge/app/roles/api_storage.lua +++ b/src/test/resources/cartridge/app/roles/api_storage.lua @@ -145,6 +145,23 @@ local function init_space() space_with_varbinary:create_index('bucket_id', { parts = { 'bucket_id' }, unique = false, if_not_exists = true, }) end + if major >= 2 and minor >= 10 and patch > 1 then + -- test space for check instant + local space_with_instant = box.schema.space.create( + 'space_with_instant', + { + format = { + { 'id', 'unsigned' }, + { 'instant_field', 'datetime',}, + { 'bucket_id', 'unsigned' }, + }, + if_not_exists = true, + } + ) + space_with_instant:create_index('id', { parts = { 'id' }, if_not_exists = true, }) + space_with_instant:create_index('bucket_id', { parts = { 'bucket_id' }, unique = false, if_not_exists = true, }) + end + local space_with_string = box.schema.space.create( 'space_with_string', { diff --git a/src/test/resources/org/testcontainers/containers/server.lua b/src/test/resources/org/testcontainers/containers/server.lua index 3743828b..96f7dbc8 100755 --- a/src/test/resources/org/testcontainers/containers/server.lua +++ b/src/test/resources/org/testcontainers/containers/server.lua @@ -107,6 +107,20 @@ if major >= 2 and minor >= 2 and patch > 1 then ) space_with_varbinary:create_index('id', { parts = { 'id' }, if_not_exists = true, }) end +if major >= 2 and minor >= 10 and patch > 1 then + -- test space for check instant + local space_with_instant = box.schema.space.create( + 'space_with_instant', + { + format = { + { 'id', 'unsigned' }, + { 'instant_field', 'datetime',}, + }, + if_not_exists = true, + } + ) + space_with_instant:create_index('id', { parts = { 'id' }, if_not_exists = true, }) +end --functions