From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from smtp45.i.mail.ru (smtp45.i.mail.ru [94.100.177.105]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by dev.tarantool.org (Postfix) with ESMTPS id C60674696C3 for ; Thu, 2 Apr 2020 13:41:40 +0300 (MSK) From: imeevma@tarantool.org Date: Thu, 2 Apr 2020 13:41:39 +0300 Message-Id: <91166652f0b9cd151ca485538e6e895639c62acd.1585823952.git.imeevma@gmail.com> Subject: [Tarantool-patches] [PATCH v1 1/1] sql: specify field types in ephemeral space format List-Id: Tarantool development patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: v.shpilevoy@tarantool.org, tsafin@tarantool.org, tarantool-patches@dev.tarantool.org This patch allows to specify field types in ephemeral space format. Prior to this patch, all fields had a SCALAR field type. Closes #3841 --- https://github.com/tarantool/tarantool/issues/3841 https://github.com/tarantool/tarantool/tree/imeevma/gh-3841-format-for-ephemeral-space @ChangeLog - Format of ephemeral spaces can have field with types other that SCALAR now (gh-3841). src/box/space_def.c | 5 ++- src/box/space_def.h | 2 +- src/box/sql.c | 83 +++++++++++++++++++++++++++++++------------------- src/box/tuple_format.c | 22 ++++++------- 4 files changed, 64 insertions(+), 48 deletions(-) diff --git a/src/box/space_def.c b/src/box/space_def.c index 6611312..5af0f38 100644 --- a/src/box/space_def.c +++ b/src/box/space_def.c @@ -233,7 +233,7 @@ space_def_new(uint32_t id, uint32_t uid, uint32_t exact_field_count, } struct space_def* -space_def_new_ephemeral(uint32_t field_count) +space_def_new_ephemeral(uint32_t field_count, struct field_def *fields) { struct space_opts opts = space_opts_default; opts.is_temporary = true; @@ -242,8 +242,7 @@ space_def_new_ephemeral(uint32_t field_count) "ephemeral", strlen("ephemeral"), "memtx", strlen("memtx"), - &opts, &field_def_default, - 0); + &opts, fields, field_count); return space_def; } diff --git a/src/box/space_def.h b/src/box/space_def.h index ac6d226..e7b0c28 100644 --- a/src/box/space_def.h +++ b/src/box/space_def.h @@ -177,7 +177,7 @@ space_def_new(uint32_t id, uint32_t uid, uint32_t exact_field_count, * @retval Space definition. */ struct space_def * -space_def_new_ephemeral(uint32_t field_count); +space_def_new_ephemeral(uint32_t field_count, struct field_def *fields); /** * Size of the space_def. diff --git a/src/box/sql.c b/src/box/sql.c index 1256df8..27089bd 100644 --- a/src/box/sql.c +++ b/src/box/sql.c @@ -330,58 +330,77 @@ sql_ephemeral_space_create(uint32_t field_count, struct sql_key_info *key_info) return NULL; } - struct key_part_def *ephemer_key_parts = region_alloc(&fiber()->gc, - sizeof(*ephemer_key_parts) * field_count); - if (ephemer_key_parts == NULL) { - diag_set(OutOfMemory, sizeof(*ephemer_key_parts) * field_count, - "region", "key parts"); - return NULL; + struct region *region = &fiber()->gc; + /* + * Name of the fields will be "_COLUMN_1", "_COLUMN_2" + * and so on. Since number of columns no more than 2000, + * length of each name is no more than strlen("_COLUMN_") + * + 5. + */ + assert(SQL_MAX_COLUMN < 9999); + uint32_t name_len = sizeof("_COLUMN_") + 5; + uint32_t size = field_count * (sizeof(struct field_def) + name_len + + sizeof(struct key_part_def)); + struct field_def *fields = region_alloc(region, size); + struct key_part_def *parts = (void *)fields + + field_count * sizeof(struct field_def); + char *names = (char *)parts + field_count * sizeof(struct key_part_def); + for (uint32_t i = 0; i < field_count; ++i) { + struct field_def *field = &fields[i]; + field->name = names; + names += name_len; + sprintf(field->name, "_COLUMN_%d", i); + field->is_nullable = true; + field->nullable_action = ON_CONFLICT_ACTION_NONE; + field->default_value = NULL; + field->default_value_expr = NULL; + if (def != NULL && i < def->part_count) { + assert(def->parts[i].type < field_type_MAX); + field->type = def->parts[i].type; + field->coll_id = def->parts[i].coll_id; + } else { + field->coll_id = COLL_NONE; + field->type = FIELD_TYPE_SCALAR; + } } + for (uint32_t i = 0; i < field_count; ++i) { - struct key_part_def *part = &ephemer_key_parts[i]; + struct key_part_def *part = &parts[i]; part->fieldno = i; part->nullable_action = ON_CONFLICT_ACTION_NONE; part->is_nullable = true; part->sort_order = SORT_ORDER_ASC; part->path = NULL; - if (def != NULL && i < def->part_count) { - assert(def->parts[i].type < field_type_MAX); - part->type = def->parts[i].type; - part->coll_id = def->parts[i].coll_id; - } else { - part->coll_id = COLL_NONE; - part->type = FIELD_TYPE_SCALAR; - } + part->type = fields[i].type; + part->coll_id = fields[i].coll_id; } - struct key_def *ephemer_key_def = key_def_new(ephemer_key_parts, - field_count, false); - if (ephemer_key_def == NULL) + struct key_def *key_def = key_def_new(parts, field_count, false); + if (key_def == NULL) return NULL; - struct index_def *ephemer_index_def = + struct index_def *index_def = index_def_new(0, 0, "ephemer_idx", strlen("ephemer_idx"), TREE, - &index_opts_default, ephemer_key_def, NULL); - key_def_delete(ephemer_key_def); - if (ephemer_index_def == NULL) + &index_opts_default, key_def, NULL); + key_def_delete(key_def); + if (index_def == NULL) return NULL; struct rlist key_list; rlist_create(&key_list); - rlist_add_entry(&key_list, ephemer_index_def, link); + rlist_add_entry(&key_list, index_def, link); - struct space_def *ephemer_space_def = - space_def_new_ephemeral(field_count); - if (ephemer_space_def == NULL) { - index_def_delete(ephemer_index_def); + struct space_def *space_def = space_def_new_ephemeral(field_count, + fields); + if (space_def == NULL) { + index_def_delete(index_def); return NULL; } - struct space *ephemer_new_space = space_new_ephemeral(ephemer_space_def, - &key_list); - index_def_delete(ephemer_index_def); - space_def_delete(ephemer_space_def); + struct space *space = space_new_ephemeral(space_def, &key_list); + index_def_delete(index_def); + space_def_delete(space_def); - return ephemer_new_space; + return space; } int tarantoolsqlEphemeralInsert(struct space *space, const char *tuple, diff --git a/src/box/tuple_format.c b/src/box/tuple_format.c index 312c966..beaeb0f 100644 --- a/src/box/tuple_format.c +++ b/src/box/tuple_format.c @@ -698,6 +698,12 @@ tuple_format_destroy(struct tuple_format *format) * dictionary will never be altered. If it can, then alter can * affect another space, which shares a format with one which is * altered. + * + * The only way to change the format of the space is to recreate + * space with the new format inside of BOX. Since there is no + * mechanism for recreating the ephemeral space, we need not worry + * about changing the format of the ephemeral space. + * * @param p_format Double pointer to format. It is updated with * hashed value, if corresponding format was found * in hash table @@ -709,13 +715,7 @@ static bool tuple_format_reuse(struct tuple_format **p_format) { struct tuple_format *format = *p_format; - if (!format->is_ephemeral) - return false; - /* - * These fields do not participate in hashing. - * Make sure they're unset. - */ - assert(format->dict->name_count == 0); + assert(format->is_ephemeral); assert(format->is_temporary); mh_int_t key = mh_tuple_format_find(tuple_formats_hash, format, NULL); @@ -739,9 +739,7 @@ tuple_format_reuse(struct tuple_format **p_format) static int tuple_format_add_to_hash(struct tuple_format *format) { - if(!format->is_ephemeral) - return 0; - assert(format->dict->name_count == 0); + assert(format->is_ephemeral); assert(format->is_temporary); mh_int_t key = mh_tuple_format_put(tuple_formats_hash, (const struct tuple_format **)&format, @@ -795,11 +793,11 @@ tuple_format_new(struct tuple_format_vtab *vtab, void *engine, if (tuple_format_create(format, keys, key_count, space_fields, space_field_count) < 0) goto err; - if (tuple_format_reuse(&format)) + if (is_ephemeral && tuple_format_reuse(&format)) return format; if (tuple_format_register(format) < 0) goto err; - if (tuple_format_add_to_hash(format) < 0) { + if (is_ephemeral && tuple_format_add_to_hash(format) < 0) { tuple_format_deregister(format); goto err; } -- 2.7.4