From a585109adb5b3c7c2cffcc85a36c2fc953998d4d Mon Sep 17 00:00:00 2001 From: Leonid Vasiliev Date: Mon, 29 Jun 2020 21:52:39 +0300 Subject: [PATCH 1/9] compilation: set use C99 mode by default Before the patch, the default compiler compilation mode is used (including C89, version dependent). But support the C89 dialect in 2020 is strange. Accordingly, set C99 as preffered. --- config.m4 | 2 ++ 1 file changed, 2 insertions(+) diff --git a/config.m4 b/config.m4 index c8b5097..8df5eaf 100644 --- a/config.m4 +++ b/config.m4 @@ -1,4 +1,6 @@ dnl config.m4 for extension tarantool +dnl set C compiler to C99 mode +AC_PROG_CC_C99 PHP_ARG_ENABLE(tarantool, for tarantool support, [ --enable-tarantool Enable tarantool support]) From 115529bcb07dee7dbe0ba82e7f083eefe0dfbe7f Mon Sep 17 00:00:00 2001 From: Leonid Vasiliev Date: Tue, 30 Jun 2020 11:27:55 +0300 Subject: [PATCH 2/9] cleanup: clean code from excessive use of "inline" There is serious "inline disease" in the code. It seems that "inline" is set to all static function. The patch clears the tarantool_schema.c file. --- src/tarantool_schema.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/tarantool_schema.c b/src/tarantool_schema.c index 70d434c..c75d744 100644 --- a/src/tarantool_schema.c +++ b/src/tarantool_schema.c @@ -69,7 +69,7 @@ schema_index_value_free(const struct schema_index_value *val) { } } -static inline void +static void schema_index_free(struct mh_schema_index_t *schema) { int pos = 0; mh_int_t index_slot = 0; @@ -146,7 +146,7 @@ mh_spacecmp_key_eq( #define MH_DEBUG 1 #include "third_party/mhash.h" -static inline void +static void schema_space_value_free(const struct schema_space_value *val) { if (val) { pefree(val->space_name, 1); @@ -161,7 +161,7 @@ schema_space_value_free(const struct schema_space_value *val) { } } -static inline void +static void schema_space_free(struct mh_schema_space_t *schema) { int pos = 0; mh_int_t space_slot = 0; @@ -212,7 +212,7 @@ int parse_field_type(const char *sfield, size_t sfield_len) { return FT_OTHER; } -static inline int +static int parse_schema_space_value_value(struct schema_field_value *fld, const char **tuple) { uint32_t sfield_len = 0; @@ -240,7 +240,7 @@ parse_schema_space_value_value(struct schema_field_value *fld, return -1; } -static inline int +static int parse_schema_space_value(struct schema_space_value *space_string, const char **tuple) { uint32_t fmp_tmp_len = 0; @@ -269,7 +269,7 @@ parse_schema_space_value(struct schema_space_value *space_string, return -1; } -static inline int +static int parse_schema_index_value(struct schema_index_value *index_string, const char **tuple) { if (mp_typeof(**tuple) != MP_ARRAY) @@ -304,7 +304,7 @@ parse_schema_index_value(struct schema_index_value *index_string, return -1; } -static inline int +static int schema_add_space( struct mh_schema_space_t *schema, const char **data @@ -421,7 +421,7 @@ tarantool_schema_add_spaces( return -1; } -static inline int schema_add_index( +static int schema_add_index( struct mh_schema_space_t *schema, const char **data ) { From 846b01560906adb2ba0fb2ae1525107a8d159725 Mon Sep 17 00:00:00 2001 From: Leonid Vasiliev Date: Mon, 29 Jun 2020 18:32:56 +0300 Subject: [PATCH 3/9] cleanup: remove 4-byte hole in struct schema_field_value Alignment of structure members to "natural" address boundaries will cause to a 4-byte gap between field_name and field_name_len on 64-bit platform. If the members will be swapped, the gap is gone. --- src/tarantool_schema.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tarantool_schema.h b/src/tarantool_schema.h index 219775a..2a970cd 100644 --- a/src/tarantool_schema.h +++ b/src/tarantool_schema.h @@ -15,8 +15,8 @@ enum field_type { struct schema_field_value { uint32_t field_number; - char *field_name; uint32_t field_name_len; + char *field_name; enum field_type field_type; }; From 471e0619700e4fbf0eb5823020bace63c1155029 Mon Sep 17 00:00:00 2001 From: Leonid Vasiliev Date: Tue, 30 Jun 2020 11:31:40 +0300 Subject: [PATCH 4/9] refactoring: move decoding index parts to a separate function To simplify adding further changes, move decoding index parts to a separate function and update it in accordance with the decoding function from tarantool. Part of #151 --- src/tarantool_schema.c | 53 +++++++++++++++++++++++++++++------------- 1 file changed, 37 insertions(+), 16 deletions(-) diff --git a/src/tarantool_schema.c b/src/tarantool_schema.c index c75d744..fab5b41 100644 --- a/src/tarantool_schema.c +++ b/src/tarantool_schema.c @@ -269,6 +269,38 @@ parse_schema_space_value(struct schema_space_value *space_string, return -1; } +/** + * 1.6.6-1.7.5 + * Decode parts array from tuple field. + */ +static int +decode_index_parts_166(struct schema_field_value *parts, uint32_t part_count, + const char **data) +{ + for (uint32_t i = 0; i < part_count; ++i) { + struct schema_field_value *part = &parts[i]; + if (mp_typeof(**data) != MP_ARRAY) + return -1; + uint32_t item_count = mp_decode_array(data); + if (item_count < 2) + return -1; + + if (mp_typeof(**data) != MP_UINT) + return -1; + part->field_number = mp_decode_uint(data); + + if (mp_typeof(**data) != MP_STR) + return -1; + uint32_t len; + const char *str = mp_decode_str(data, &len); + part->field_type = parse_field_type(str, len); + + for (uint32_t j = 2; j < item_count; ++j) + mp_next(data); + } + return 0; +} + static int parse_schema_index_value(struct schema_index_value *index_string, const char **tuple) { @@ -283,23 +315,12 @@ parse_schema_index_value(struct schema_index_value *index_string, goto error; memset(index_string->index_parts, 0, part_count * sizeof(struct schema_field_value)); - int i = 0; - for (i = 0; i < part_count; ++i) { - if (mp_typeof(**tuple) != MP_ARRAY) - goto error; - if (mp_decode_array(tuple) != 2) - goto error; - struct schema_field_value *val = &(index_string->index_parts[i]); - if (mp_typeof(**tuple) != MP_UINT) - goto error; - val->field_number = mp_decode_uint(tuple); - uint32_t sfield_len = 0; - if (mp_typeof(**tuple) != MP_STR) - goto error; - const char *sfield = mp_decode_str(tuple, &sfield_len); - val->field_type = parse_field_type(sfield, sfield_len); + + if (mp_typeof(**tuple) == MP_ARRAY) { + return decode_index_parts_166(index_string->index_parts, + part_count, tuple); } - return 0; + error: return -1; } From 4d4e4d9b0f9fabe139f107d03b996efb984c8bb8 Mon Sep 17 00:00:00 2001 From: Leonid Vasiliev Date: Fri, 3 Jul 2020 02:33:21 +0300 Subject: [PATCH 5/9] schema: add collation and is_nullable opts Add collation and is_nullable opts to schema_field_value. Part of #151 --- src/tarantool_schema.c | 3 +++ src/tarantool_schema.h | 8 ++++++++ 2 files changed, 11 insertions(+) diff --git a/src/tarantool_schema.c b/src/tarantool_schema.c index fab5b41..256dba3 100644 --- a/src/tarantool_schema.c +++ b/src/tarantool_schema.c @@ -297,6 +297,9 @@ decode_index_parts_166(struct schema_field_value *parts, uint32_t part_count, for (uint32_t j = 2; j < item_count; ++j) mp_next(data); + /* Set default values. */ + part->is_nullable = false; + part->coll_id = COLL_NONE; } return 0; } diff --git a/src/tarantool_schema.h b/src/tarantool_schema.h index 2a970cd..1bdd5c7 100644 --- a/src/tarantool_schema.h +++ b/src/tarantool_schema.h @@ -1,6 +1,8 @@ #ifndef PHP_TNT_SCHEMA_H #define PHP_TNT_SCHEMA_H +#include + struct schema_key { const char *id; uint32_t id_len; @@ -13,11 +15,17 @@ enum field_type { FT_OTHER = 2 }; +#define COLL_NONE UINT32_MAX + struct schema_field_value { uint32_t field_number; uint32_t field_name_len; char *field_name; enum field_type field_type; + /* Collation ID for string comparison. */ + uint32_t coll_id; + /* True if a key part can store NULLs. */ + bool is_nullable; }; struct schema_index_value { From c2a464edb48cf7ece2a01e8223443b604278c962 Mon Sep 17 00:00:00 2001 From: Leonid Vasiliev Date: Tue, 30 Jun 2020 12:42:34 +0300 Subject: [PATCH 6/9] schema: update processing the field type Update processing the field type in accordance with the same in tarantool. Part of #151 --- src/tarantool_schema.c | 61 +++++++++++++++++++++++++++++++++--------- src/tarantool_schema.h | 21 ++++++++++++--- 2 files changed, 66 insertions(+), 16 deletions(-) diff --git a/src/tarantool_schema.c b/src/tarantool_schema.c index 256dba3..656bfa0 100644 --- a/src/tarantool_schema.c +++ b/src/tarantool_schema.c @@ -198,18 +198,53 @@ schema_space_free(struct mh_schema_space_t *schema) { } } -int parse_field_type(const char *sfield, size_t sfield_len) { - if (sfield_len == 3) { - if (tolower(sfield[0]) == 's' && - tolower(sfield[1]) == 't' && - tolower(sfield[2]) == 'r') - return FT_STR; - if (tolower(sfield[0]) == 'n' && - tolower(sfield[1]) == 'u' && - tolower(sfield[2]) == 'm') - return FT_NUM; +static const char *field_type_strs[] = { + /* [FIELD_TYPE_ANY] = */ "any", + /* [FIELD_TYPE_UNSIGNED] = */ "unsigned", + /* [FIELD_TYPE_STRING] = */ "string", + /* [FIELD_TYPE_NUMBER] = */ "number", + /* [FIELD_TYPE_DOUBLE] = */ "double", + /* [FIELD_TYPE_INTEGER] = */ "integer", + /* [FIELD_TYPE_BOOLEAN] = */ "boolean", + /* [FIELD_TYPE_VARBINARY] = */"varbinary", + /* [FIELD_TYPE_SCALAR] = */ "scalar", + /* [FIELD_TYPE_DECIMAL] = */ "decimal", + /* [FIELD_TYPE_UUID] = */ "uuid", + /* [FIELD_TYPE_ARRAY] = */ "array", + /* [FIELD_TYPE_MAP] = */ "map", +}; + +/** + * Find a string in an array of strings. + */ +static uint32_t +strnindex(const char **haystack, const char *needle, uint32_t len, uint32_t hmax) +{ + if (len == 0) + return hmax; + for (unsigned index = 0; index != hmax && haystack[index]; ++index) { + if (strncasecmp(haystack[index], needle, len) == 0 && + strlen(haystack[index]) == len) + return index; } - return FT_OTHER; + return hmax; +} + +static enum field_type +field_type_by_name(const char *name, size_t len) +{ + enum field_type field_type = strnindex(field_type_strs, name, len, + field_type_MAX); + if (field_type != field_type_MAX) + return field_type; + /* 'num' and 'str' in _index are deprecated since Tarantool 1.7 */ + if (strncasecmp(name, "num", len) == 0) + return FIELD_TYPE_UNSIGNED; + else if (strncasecmp(name, "str", len) == 0) + return FIELD_TYPE_STRING; + else if (len == 1 && name[0] == '*') + return FIELD_TYPE_ANY; + return field_type_MAX; } static int @@ -231,7 +266,7 @@ parse_schema_space_value_value(struct schema_field_value *fld, if (mp_typeof(**tuple) != MP_STR) goto error; sfield = mp_decode_str(tuple, &sfield_len); - fld->field_type = parse_field_type(sfield, sfield_len); + fld->field_type = field_type_by_name(sfield, sfield_len); } else { mp_next(tuple); } @@ -293,7 +328,7 @@ decode_index_parts_166(struct schema_field_value *parts, uint32_t part_count, return -1; uint32_t len; const char *str = mp_decode_str(data, &len); - part->field_type = parse_field_type(str, len); + part->field_type = field_type_by_name(str, len); for (uint32_t j = 2; j < item_count; ++j) mp_next(data); diff --git a/src/tarantool_schema.h b/src/tarantool_schema.h index 1bdd5c7..e3e5e57 100644 --- a/src/tarantool_schema.h +++ b/src/tarantool_schema.h @@ -9,10 +9,25 @@ struct schema_key { uint32_t number; }; +/** + * Possible field data types. + */ enum field_type { - FT_STR = 0, - FT_NUM = 1, - FT_OTHER = 2 + FIELD_TYPE_ANY = 0, + FIELD_TYPE_UNSIGNED, + FIELD_TYPE_STRING, + FIELD_TYPE_NUMBER, + FIELD_TYPE_DOUBLE, + FIELD_TYPE_INTEGER, + FIELD_TYPE_BOOLEAN, + FIELD_TYPE_VARBINARY, + FIELD_TYPE_SCALAR, + FIELD_TYPE_DECIMAL, + FIELD_TYPE_UUID, + FIELD_TYPE_ARRAY, + FIELD_TYPE_MAP, + /* Used for unknown type. */ + field_type_MAX }; #define COLL_NONE UINT32_MAX From 746e42d6426d4d953b96de1dd33aece8690f60ae Mon Sep 17 00:00:00 2001 From: Leonid Vasiliev Date: Wed, 1 Jul 2020 17:50:11 +0300 Subject: [PATCH 7/9] schema: add support new _index system space format After tarantool-1.7.5-153-g1651fc9be the new _index format was introduced. We should support it to fetch a schema from a tarantool-1.7.5.153+ instance. When an index parts do not use parameters except name and type the index info is stored in the old format in _index system space. When an index part uses is_nullable or collation parameter, then the new format will be used. Close #151 --- src/tarantool_schema.c | 95 ++++++++++++++++++++++++++++++++++++++++-- test/shared/box.lua | 26 ++++++++++++ 2 files changed, 118 insertions(+), 3 deletions(-) diff --git a/src/tarantool_schema.c b/src/tarantool_schema.c index 656bfa0..ba385f4 100644 --- a/src/tarantool_schema.c +++ b/src/tarantool_schema.c @@ -230,6 +230,17 @@ strnindex(const char **haystack, const char *needle, uint32_t len, uint32_t hmax return hmax; } +/** + * Strict compare a null-terminated string with a length specified + * string. + */ +static inline bool +strncmp_strict(const char *str, size_t str_len, const char *str_null_term) +{ + return (strncmp(str, str_null_term, str_len) == 0 && + strlen(str_null_term) == str_len); +} + static enum field_type field_type_by_name(const char *name, size_t len) { @@ -275,6 +286,18 @@ parse_schema_space_value_value(struct schema_field_value *fld, return -1; } +/** + * Initialization value. + */ +static const struct schema_field_value field_val_def = { + .field_number = 0, + .field_name_len = 0, + .field_name = NULL, + .field_type = field_type_MAX, + .coll_id = COLL_NONE, + .is_nullable = false +}; + static int parse_schema_space_value(struct schema_space_value *space_string, const char **tuple) { @@ -314,6 +337,7 @@ decode_index_parts_166(struct schema_field_value *parts, uint32_t part_count, { for (uint32_t i = 0; i < part_count; ++i) { struct schema_field_value *part = &parts[i]; + *part = field_val_def; if (mp_typeof(**data) != MP_ARRAY) return -1; uint32_t item_count = mp_decode_array(data); @@ -332,9 +356,69 @@ decode_index_parts_166(struct schema_field_value *parts, uint32_t part_count, for (uint32_t j = 2; j < item_count; ++j) mp_next(data); - /* Set default values. */ - part->is_nullable = false; - part->coll_id = COLL_NONE; + } + return 0; +} + +static int +decode_index_part(struct schema_field_value *part, uint32_t map_size, + const char **data) +{ + *part = field_val_def; + for (uint32_t i = 0; i < map_size; ++i) { + if (mp_typeof(**data) != MP_STR) + return -1; + + uint32_t k_len; + const char *key = mp_decode_str(data, &k_len); + if (strncmp_strict(key, k_len, "type")) { + if (mp_typeof(**data) != MP_STR) + return -1; + uint32_t v_len; + const char *val = mp_decode_str(data, &v_len); + part->field_type = field_type_by_name(val, v_len); + } else if (strncmp_strict(key, k_len, "field")) { + if (mp_typeof(**data) != MP_UINT) + return -1; + part->field_number = mp_decode_uint(data); + } else if (strncmp_strict(key, k_len, "collation")) { + if (mp_typeof(**data) != MP_UINT) + return -1; + part->coll_id = mp_decode_uint(data); + } else if (strncmp_strict(key, k_len, "is_nullable")) { + if (mp_typeof(**data) != MP_BOOL) + return -1; + part->is_nullable = mp_decode_bool(data); + } else { + mp_next(data); + } + } + + /* Collation is reasonable only for string and scalar parts. */ + if (part->coll_id != COLL_NONE && + part->field_type != FIELD_TYPE_STRING && + part->field_type != FIELD_TYPE_SCALAR) { + return -1; + } + + return 0; +} + +/** + * Decode parts array from tuple field. + */ +static int +decode_index_parts(struct schema_field_value *parts, uint32_t part_count, + const char **data) +{ + for (uint32_t i = 0; i < part_count; ++i) { + struct schema_field_value *part = &parts[i]; + if (mp_typeof(**data) != MP_MAP) + return -1; + + uint32_t map_size = mp_decode_map(data); + if (decode_index_part(part, map_size, data) != 0) + return -1; } return 0; } @@ -355,8 +439,13 @@ parse_schema_index_value(struct schema_index_value *index_string, sizeof(struct schema_field_value)); if (mp_typeof(**tuple) == MP_ARRAY) { + /* Base coding format is used. */ return decode_index_parts_166(index_string->index_parts, part_count, tuple); + } else { + /* Extended coding format is used. */ + return decode_index_parts(index_string->index_parts, + part_count, tuple); } error: diff --git a/test/shared/box.lua b/test/shared/box.lua index 33838c8..f9e2f42 100755 --- a/test/shared/box.lua +++ b/test/shared/box.lua @@ -134,6 +134,32 @@ box.once('initialization', function() local tuple = yaml.decode(yml)[1] tuple[1] = "12345" box.space._schema:insert(tuple) + + -- gh-151: Support new _index system space format + -- After tarantool-1.7.5-153-g1651fc9be the new _index format + -- was introduced. When an index part uses is_nullable or + -- collation parameter, then the new format will be used. + if tarantool_version_at_least(1, 7, 6, 0) then + local test_index_part_176 = box.schema.space.create( + 'test_index_part_176', + { + format = { + {type = compat.unsigned, name = 'f1'}, + {type = compat.unsigned, name = 'f2', is_nullable = true}, + {type = compat.string, name = 'f3'}, + } + }) + + test_index_part_176:create_index('primary', { + parts = {{1, compat.unsigned}} + }) + test_index_part_176:create_index('secondary', { + parts = { + {2, compat.unsigned, is_nullable = true}, + {3, compat.string, collation = 'unicode_ci'} + } + }) + end end) function test_1() From df11b961e617430681e4774e01e8d934d12cc660 Mon Sep 17 00:00:00 2001 From: Leonid Vasiliev Date: Fri, 3 Jul 2020 00:19:54 +0300 Subject: [PATCH 8/9] schema: update parsing _space system space Doesn't change user visible behaviour. * Add support is_nullable to parsing _space system space. * Replace string comparation. It's no always correct and safe to use memcmp to compare a null-terminated string with a length specified string, because it doesn't check the end of null-terminated string (like strncmp) which may be less. --- src/tarantool_schema.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/tarantool_schema.c b/src/tarantool_schema.c index ba385f4..84cc89d 100644 --- a/src/tarantool_schema.c +++ b/src/tarantool_schema.c @@ -265,7 +265,7 @@ parse_schema_space_value_value(struct schema_field_value *fld, if (mp_typeof(**tuple) != MP_STR) goto error; const char *sfield = mp_decode_str(tuple, &sfield_len); - if (memcmp(sfield, "name", sfield_len) == 0) { + if (strncmp_strict(sfield, sfield_len, "name")) { if (mp_typeof(**tuple) != MP_STR) goto error; sfield = mp_decode_str(tuple, &fld->field_name_len); @@ -273,11 +273,15 @@ parse_schema_space_value_value(struct schema_field_value *fld, if (!fld->field_name) goto error; memcpy(fld->field_name, sfield, fld->field_name_len); - } else if (memcmp(sfield, "type", sfield_len) == 0) { + } else if (strncmp_strict(sfield, sfield_len, "type")) { if (mp_typeof(**tuple) != MP_STR) goto error; sfield = mp_decode_str(tuple, &sfield_len); fld->field_type = field_type_by_name(sfield, sfield_len); + } else if (strncmp_strict(sfield, sfield_len, "is_nullable")) { + if (mp_typeof(**tuple) != MP_BOOL) + goto error; + fld->is_nullable = mp_decode_bool(tuple); } else { mp_next(tuple); } @@ -313,6 +317,7 @@ parse_schema_space_value(struct schema_space_value *space_string, int i = 0; for (i = 0; i < fmt_len; ++i) { struct schema_field_value *val = &(space_string->schema_list[i]); + *val = field_val_def; if (mp_typeof(**tuple) != MP_MAP) goto error; uint32_t arrsz = mp_decode_map(tuple); From 7f8bc6008793e52127b2f43a70455380d3e8b230 Mon Sep 17 00:00:00 2001 From: Leonid Vasiliev Date: Tue, 21 Jul 2020 20:32:47 +0300 Subject: [PATCH 9/9] travis-ci: enable tests for tarantool-2.2 Added support for the new _index format. The time is come to enable tests for tarantool-2.2. --- .travis.yml | 17 +++++++---------- test.all.sh | 8 -------- 2 files changed, 7 insertions(+), 18 deletions(-) diff --git a/.travis.yml b/.travis.yml index 94339ea..5059e1e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,9 +3,6 @@ dist: xenial language: php -# gh-151: disable tarantoo-2.2 due to lack of support the new -# _index format. -# # Disable tarantool-1.6 and 1.7 on php 7.1-7.4, because # php-7.[1-4]-cli docker images are based on Debian Buster, but we # have no tarantool-1.[6-7] packages for this distribution. @@ -23,8 +20,8 @@ jobs: env: TARANTOOL_VERSION=1.10 - php: 7.0 env: TARANTOOL_VERSION=2.1 - # - php: 7.0 - # env: TARANTOOL_VERSION=2.2 + - php: 7.0 + env: TARANTOOL_VERSION=2.2 - php: 7.0 env: TARANTOOL_VERSION=2.3 - php: 7.0 @@ -40,8 +37,8 @@ jobs: env: TARANTOOL_VERSION=1.10 - php: 7.1 env: TARANTOOL_VERSION=2.1 - # - php: 7.1 - # env: TARANTOOL_VERSION=2.2 + - php: 7.1 + env: TARANTOOL_VERSION=2.2 - php: 7.1 env: TARANTOOL_VERSION=2.3 - php: 7.1 @@ -58,7 +55,7 @@ jobs: - php: 7.2 env: TARANTOOL_VERSION=2.1 # - php: 7.2 - # env: TARANTOOL_VERSION=2.2 + env: TARANTOOL_VERSION=2.2 - php: 7.2 env: TARANTOOL_VERSION=2.3 - php: 7.2 @@ -75,7 +72,7 @@ jobs: - php: 7.3 env: TARANTOOL_VERSION=2.1 # - php: 7.3 - # env: TARANTOOL_VERSION=2.2 + env: TARANTOOL_VERSION=2.2 - php: 7.3 env: TARANTOOL_VERSION=2.3 - php: 7.3 @@ -92,7 +89,7 @@ jobs: - php: 7.4 env: TARANTOOL_VERSION=2.1 # - php: 7.4 - # env: TARANTOOL_VERSION=2.2 + env: TARANTOOL_VERSION=2.2 - php: 7.4 env: TARANTOOL_VERSION=2.3 - php: 7.4 diff --git a/test.all.sh b/test.all.sh index 2beb05b..d1c4568 100755 --- a/test.all.sh +++ b/test.all.sh @@ -5,26 +5,18 @@ set -exu # Strict shell (w/o -o pipefail) php_version_list="7.0 7.1 7.2 7.3 7.4" tarantool_version_list="1.6 1.7 1.9 1.10 2.1 2.2 2.3 2.4 2.5" -# gh-151: disable tarantool-2.2 due to lack of support the new -# _index format. -# # Disable tarantool-1.6 and 1.7 on php 7.1-7.4, because # php-7.[1-4]-cli docker images are based on Debian Buster, but we # have no tarantool-1.[6-7] packages for this distribution. exceptions=" - php-7.0-tarantool-2.2 php-7.1-tarantool-1.6 php-7.1-tarantool-1.7 - php-7.1-tarantool-2.2 php-7.2-tarantool-1.6 php-7.2-tarantool-1.7 - php-7.2-tarantool-2.2 php-7.3-tarantool-1.6 php-7.3-tarantool-1.7 - php-7.3-tarantool-2.2 php-7.4-tarantool-1.6 php-7.4-tarantool-1.7 - php-7.4-tarantool-2.2 " for php_version in $php_version_list; do