diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 689a0674061bdfa1e90b0b5e1522cd4bb3285b19..58f44d71bf75de4a48040021c563863109029d29 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -178,10 +178,11 @@ set(api_headers ${CMAKE_SOURCE_DIR}/src/lua/utils.h ${CMAKE_SOURCE_DIR}/src/box/txn.h ${CMAKE_SOURCE_DIR}/src/box/key_def.h + ${CMAKE_SOURCE_DIR}/src/box/field_def.h ${CMAKE_SOURCE_DIR}/src/box/tuple.h ${CMAKE_SOURCE_DIR}/src/box/tuple_format.h ${CMAKE_SOURCE_DIR}/src/box/tuple_compare.h - ${CMAKE_SOURCE_DIR}/src/box/schema.h + ${CMAKE_SOURCE_DIR}/src/box/schema_def.h ${CMAKE_SOURCE_DIR}/src/box/box.h ${CMAKE_SOURCE_DIR}/src/box/index.h ${CMAKE_SOURCE_DIR}/src/box/iterator_type.h diff --git a/src/box/CMakeLists.txt b/src/box/CMakeLists.txt index e0433994093c1d665552cce48095a8b23fad0fcc..60e3628a7208a002c969ece2cb22a59d5bd248ba 100644 --- a/src/box/CMakeLists.txt +++ b/src/box/CMakeLists.txt @@ -36,6 +36,8 @@ add_library(tuple STATIC tuple_compare.cc tuple_hash.cc key_def.cc + field_def.c + opt_def.c ) target_link_libraries(tuple box_error core ${MSGPUCK_LIBRARIES} misc) @@ -48,6 +50,7 @@ add_library(box STATIC xrow_io.cc tuple_convert.c index.cc + index_def.c iterator_type.c memtx_index.cc memtx_hash.cc @@ -77,9 +80,12 @@ add_library(box STATIC vy_log.c vy_upsert.c space.cc + space_def.c func.c + func_def.c alter.cc schema.cc + schema_def.c session.cc port.c txn.cc diff --git a/src/box/alter.cc b/src/box/alter.cc index 9a369db2a05cfee7e95f3478ff75fc2727d1c612..57b5ed606c2a565bbf3efa6bc98b6f20324adc41 100644 --- a/src/box/alter.cc +++ b/src/box/alter.cc @@ -390,7 +390,7 @@ index_def_new_from_tuple(struct tuple *tuple, struct space *old_space) if (index_def == NULL) diag_raise(); auto index_def_guard = make_scoped_guard([=] { index_def_delete(index_def); }); - index_def_check(index_def, space_name(old_space)); + index_def_check_xc(index_def, space_name(old_space)); old_space->handler->checkIndexDef(old_space, index_def); index_def_guard.is_active = false; return index_def; @@ -452,7 +452,7 @@ space_def_new_from_tuple(struct tuple *tuple, uint32_t errcode) auto def_guard = make_scoped_guard([=] { space_def_delete(def); }); memcpy(def->name, name, name_len); def->name[name_len] = 0; - identifier_check(def->name); + identifier_check_xc(def->name); def->id = tuple_field_u32_xc(tuple, BOX_SPACE_FIELD_ID); if (def->id > BOX_SPACE_MAX) { tnt_raise(ClientError, errcode, @@ -476,7 +476,7 @@ space_def_new_from_tuple(struct tuple *tuple, uint32_t errcode) } memcpy(def->engine_name, engine_name, name_len); def->engine_name[name_len] = 0; - identifier_check(def->engine_name); + identifier_check_xc(def->engine_name); space_opts_create(&def->opts, tuple); Engine *engine = engine_find(def->engine_name); engine->checkSpaceDef(def); @@ -550,7 +550,7 @@ alter_space_new(struct space *old_space) region_calloc_object_xc(&fiber()->gc, struct alter_space); rlist_create(&alter->ops); alter->old_space = old_space; - alter->space_def = space_def_dup(alter->old_space->def); + alter->space_def = space_def_dup_xc(alter->old_space->def); return alter; } @@ -1751,7 +1751,7 @@ user_def_new_from_tuple(struct tuple *tuple) tnt_raise(ClientError, ER_CREATE_USER, user->name, "unknown user type"); } - identifier_check(user->name); + identifier_check_xc(user->name); access_check_ddl(user->owner, SC_USER); /* * AUTH_DATA field in _user space should contain diff --git a/src/box/authentication.cc b/src/box/authentication.cc index 802d1a64cb637b43249870713ce4b12a57dae00d..d2c96c254d80aabc15078c658401ad421d2d6aa9 100644 --- a/src/box/authentication.cc +++ b/src/box/authentication.cc @@ -31,6 +31,7 @@ #include "authentication.h" #include "user.h" #include "session.h" +#include "msgpuck.h" static char zero_hash[SCRAMBLE_SIZE]; diff --git a/src/box/engine.cc b/src/box/engine.cc index 8ec6deb800a670fb52126e8eafcee1e7114ba44b..4375685a8a9da255dd0c35d1dcf824d3245e26c5 100644 --- a/src/box/engine.cc +++ b/src/box/engine.cc @@ -35,9 +35,7 @@ #include "port.h" #include "space.h" #include "exception.h" -#include "schema.h" #include "small/rlist.h" -#include "scoped_guard.h" #include "vclock.h" #include <stdlib.h> #include <string.h> diff --git a/src/box/field_def.c b/src/box/field_def.c new file mode 100644 index 0000000000000000000000000000000000000000..53c2b60beaa6de080f8800b296bc0ce32b6f6bd0 --- /dev/null +++ b/src/box/field_def.c @@ -0,0 +1,63 @@ +/* + * Copyright 2010-2016, Tarantool AUTHORS, please see AUTHORS file. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * 1. Redistributions of source code must retain the above + * copyright notice, this list of conditions and the + * following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY <COPYRIGHT HOLDER> ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * <COPYRIGHT HOLDER> OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF + * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "field_def.h" +#include "trivia/util.h" + +const char *field_type_strs[] = { + /* [FIELD_TYPE_ANY] = */ "any", + /* [FIELD_TYPE_UNSIGNED] = */ "unsigned", + /* [FIELD_TYPE_STRING] = */ "string", + /* [FIELD_TYPE_ARRAY] = */ "array", + /* [FIELD_TYPE_NUMBER] = */ "number", + /* [FIELD_TYPE_INTEGER] = */ "integer", + /* [FIELD_TYPE_SCALAR] = */ "scalar", + /* [FIELD_TYPE_MAP] = */ "map", +}; + +enum field_type +field_type_by_name(const char *name) +{ + enum field_type field_type = STR2ENUM(field_type, name); + /* + * FIELD_TYPE_ANY can't be used as type of indexed field, + * because it is internal type used only for filling + * struct tuple_format.fields array. + */ + if (field_type != field_type_MAX && field_type != FIELD_TYPE_ANY) + return field_type; + /* 'num' and 'str' in _index are deprecated since Tarantool 1.7 */ + if (strcasecmp(name, "num") == 0) + return FIELD_TYPE_UNSIGNED; + else if (strcasecmp(name, "str") == 0) + return FIELD_TYPE_STRING; + return field_type_MAX; +} diff --git a/src/box/field_def.h b/src/box/field_def.h new file mode 100644 index 0000000000000000000000000000000000000000..f2cd57e12584102d714beb6aa495741cfd8b2105 --- /dev/null +++ b/src/box/field_def.h @@ -0,0 +1,68 @@ +#ifndef TARANTOOL_BOX_FIELD_DEF_H_INCLUDED +#define TARANTOOL_BOX_FIELD_DEF_H_INCLUDED +/* + * Copyright 2010-2016, Tarantool AUTHORS, please see AUTHORS file. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * 1. Redistributions of source code must retain the above + * copyright notice, this list of conditions and the + * following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY <COPYRIGHT HOLDER> ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * <COPYRIGHT HOLDER> OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF + * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if defined(__cplusplus) +extern "C" { +#endif /* defined(__cplusplus) */ + +/** \cond public */ + +/* + * Possible field data types. Can't use STRS/ENUM macros for them, + * since there is a mismatch between enum name (STRING) and type + * name literal ("STR"). STR is already used as Objective C type. + */ +enum field_type { + FIELD_TYPE_ANY = 0, + FIELD_TYPE_UNSIGNED, + FIELD_TYPE_STRING, + FIELD_TYPE_ARRAY, + FIELD_TYPE_NUMBER, + FIELD_TYPE_INTEGER, + FIELD_TYPE_SCALAR, + FIELD_TYPE_MAP, + field_type_MAX +}; + +/** \endcond public */ + +extern const char *field_type_strs[]; + +enum field_type +field_type_by_name(const char *name); + +#if defined(__cplusplus) +} /* extern "C" */ +#endif /* defined(__cplusplus) */ + +#endif /* TARANTOOL_BOX_FIELD_DEF_H_INCLUDED */ diff --git a/src/box/func.c b/src/box/func.c index 1a4283802604e43995390aaa79b4a0e41a3c232a..e33783e4d92779b19ef653c820cd3ae1c9a90e90 100644 --- a/src/box/func.c +++ b/src/box/func.c @@ -29,14 +29,12 @@ * SUCH DAMAGE. */ #include "func.h" - #include "trivia/config.h" - -#include <dlfcn.h> - #include "assoc.h" - #include "lua/utils.h" +#include "error.h" +#include "diag.h" +#include <dlfcn.h> /** * Parsed symbol and package names. diff --git a/src/box/func.h b/src/box/func.h index b152a2285b15ef7b419de60ccc59b54a45ba2716..0957546c62e4d2639ca08542365d12a74d1bffbf 100644 --- a/src/box/func.h +++ b/src/box/func.h @@ -34,10 +34,9 @@ #include <stddef.h> #include <stdint.h> #include <stdbool.h> - -#include <small/rlist.h> - -#include "key_def.h" +#include "small/rlist.h" +#include "func_def.h" +#include "user_def.h" #if defined(__cplusplus) extern "C" { diff --git a/src/box/func_def.c b/src/box/func_def.c new file mode 100644 index 0000000000000000000000000000000000000000..76ed77b24b7c30ae5e1bdd0e48dde4de79194a57 --- /dev/null +++ b/src/box/func_def.c @@ -0,0 +1,3 @@ +#include "func_def.h" + +const char *func_language_strs[] = {"LUA", "C"}; diff --git a/src/box/func_def.h b/src/box/func_def.h new file mode 100644 index 0000000000000000000000000000000000000000..5b52ab498f7fb933a482b67219a9fe9935a154a9 --- /dev/null +++ b/src/box/func_def.h @@ -0,0 +1,89 @@ +#ifndef TARANTOOL_BOX_FUNC_DEF_H_INCLUDED +#define TARANTOOL_BOX_FUNC_DEF_H_INCLUDED +/* + * Copyright 2010-2016, Tarantool AUTHORS, please see AUTHORS file. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * 1. Redistributions of source code must retain the above + * copyright notice, this list of conditions and the + * following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY <COPYRIGHT HOLDER> ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * <COPYRIGHT HOLDER> OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF + * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "trivia/util.h" +#include <stdbool.h> + +/** + * The supported language of the stored function. + */ +enum func_language { + FUNC_LANGUAGE_LUA, + FUNC_LANGUAGE_C, + func_language_MAX, +}; + +extern const char *func_language_strs[]; + +/** + * Definition of a function. Function body is not stored + * or replicated (yet). + */ +struct func_def { + /** Function id. */ + uint32_t fid; + /** Owner of the function. */ + uint32_t uid; + /** + * True if the function requires change of user id before + * invocation. + */ + bool setuid; + /** + * The language of the stored function. + */ + enum func_language language; + /** Function name. */ + char name[0]; +}; + +/** + * @param name_len length of func_def->name + * @returns size in bytes needed to allocate for struct func_def + * for a function of length @a a name_len. + */ +static inline size_t +func_def_sizeof(uint32_t name_len) +{ + /* +1 for '\0' name terminating. */ + return sizeof(struct func_def) + name_len + 1; +} + +/** + * API of C stored function. + */ +typedef struct box_function_ctx box_function_ctx_t; +typedef int (*box_function_f)(box_function_ctx_t *ctx, + const char *args, const char *args_end); + +#endif /* TARANTOOL_BOX_FUNC_DEF_H_INCLUDED */ diff --git a/src/box/index.h b/src/box/index.h index 35af19ae79262d46709d6a5ceac3d02d9e5204fc..d41db48d01989e52f96d20b6b9d952aa4d96e312 100644 --- a/src/box/index.h +++ b/src/box/index.h @@ -212,7 +212,7 @@ box_index_info(uint32_t space_id, uint32_t index_id, #if defined(__cplusplus) } /* extern "C" */ -#include "key_def.h" +#include "index_def.h" struct iterator { struct tuple *(*next)(struct iterator *); diff --git a/src/box/index_def.c b/src/box/index_def.c new file mode 100644 index 0000000000000000000000000000000000000000..f4159e3041edde92da97cdd03716b50cc0e67404 --- /dev/null +++ b/src/box/index_def.c @@ -0,0 +1,252 @@ +/* + * Copyright 2010-2016, Tarantool AUTHORS, please see AUTHORS file. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * 1. Redistributions of source code must retain the above + * copyright notice, this list of conditions and the + * following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY <COPYRIGHT HOLDER> ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * <COPYRIGHT HOLDER> OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF + * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +#include "index_def.h" +#include "schema_def.h" + +const char *index_type_strs[] = { "HASH", "TREE", "BITSET", "RTREE" }; + +const char *rtree_index_distance_type_strs[] = { "EUCLID", "MANHATTAN" }; + +const struct index_opts index_opts_default = { + /* .unique = */ true, + /* .dimension = */ 2, + /* .distancebuf = */ { '\0' }, + /* .distance = */ RTREE_INDEX_DISTANCE_TYPE_EUCLID, + /* .range_size = */ 0, + /* .page_size = */ 0, + /* .run_count_per_level = */ 2, + /* .run_size_ratio = */ 3.5, + /* .bloom_fpr = */ 0.05, + /* .lsn = */ 0, +}; + +const struct opt_def index_opts_reg[] = { + OPT_DEF("unique", OPT_BOOL, struct index_opts, is_unique), + OPT_DEF("dimension", OPT_INT, struct index_opts, dimension), + OPT_DEF("distance", OPT_STR, struct index_opts, distancebuf), + OPT_DEF("range_size", OPT_INT, struct index_opts, range_size), + OPT_DEF("page_size", OPT_INT, struct index_opts, page_size), + OPT_DEF("run_count_per_level", OPT_INT, struct index_opts, run_count_per_level), + OPT_DEF("run_size_ratio", OPT_FLOAT, struct index_opts, run_size_ratio), + OPT_DEF("bloom_fpr", OPT_FLOAT, struct index_opts, bloom_fpr), + OPT_DEF("lsn", OPT_INT, struct index_opts, lsn), + { NULL, opt_type_MAX, 0, 0 }, +}; + +struct index_def * +index_def_new(uint32_t space_id, uint32_t iid, const char *name, + uint32_t name_len, enum index_type type, + const struct index_opts *opts, + struct key_def *key_def, struct key_def *pk_def) +{ + assert(name_len <= BOX_NAME_MAX); + /* Use calloc to make index_def_delete() safe at all times. */ + struct index_def *def = (struct index_def *) calloc(1, sizeof(*def)); + if (def == NULL) { + diag_set(OutOfMemory, sizeof(*def), "malloc", "struct index_def"); + return NULL; + } + def->name = strndup(name, name_len); + if (def->name == NULL) { + index_def_delete(def); + diag_set(OutOfMemory, name_len + 1, "malloc", "index_def name"); + return NULL; + } + if (!identifier_is_valid(def->name)) { + diag_set(ClientError, ER_IDENTIFIER, def->name); + index_def_delete(def); + return NULL; + } + def->key_def = key_def_dup(key_def); + if (pk_def) + def->cmp_def = key_def_merge(key_def, pk_def); + else + def->cmp_def = key_def_dup(key_def); + if (def->key_def == NULL || def->cmp_def == NULL) { + index_def_delete(def); + return NULL; + } + def->type = type; + def->space_id = space_id; + def->iid = iid; + def->opts = *opts; + return def; +} + +struct index_def * +index_def_dup(const struct index_def *def) +{ + struct index_def *dup = (struct index_def *) malloc(sizeof(*dup)); + if (dup == NULL) { + diag_set(OutOfMemory, sizeof(*dup), "malloc", + "struct index_def"); + return NULL; + } + *dup = *def; + dup->name = strdup(def->name); + if (dup->name == NULL) { + free(dup); + diag_set(OutOfMemory, strlen(def->name) + 1, "malloc", + "index_def name"); + return NULL; + } + dup->key_def = key_def_dup(def->key_def); + dup->cmp_def = key_def_dup(def->cmp_def); + if (dup->key_def == NULL || dup->cmp_def == NULL) { + index_def_delete(dup); + return NULL; + } + rlist_create(&dup->link); + return dup; +} + +void +index_def_swap(struct index_def *def1, struct index_def *def2) +{ + /* + * Swap const-size items and name. Keep the original key + * definitions, they are used in the engines. + */ + struct index_def tmp_def = *def1; + memcpy(def1, def2, offsetof(struct index_def, key_def)); + memcpy(def2, &tmp_def, offsetof(struct index_def, key_def)); + /* + * index_def_swap() is used only during alter to modify + * index metadata. + */ +} + +/** Free a key definition. */ +void +index_def_delete(struct index_def *index_def) +{ + free(index_def->name); + + if (index_def->key_def) { + TRASH(index_def->key_def); + free(index_def->key_def); + } + + if (index_def->cmp_def) { + TRASH(index_def->cmp_def); + free(index_def->cmp_def); + } + + TRASH(index_def); + free(index_def); +} + +bool +index_def_change_requires_rebuild(struct index_def *old_index_def, + struct index_def *new_index_def) +{ + if (old_index_def->iid != new_index_def->iid || + old_index_def->type != new_index_def->type || + old_index_def->opts.is_unique != new_index_def->opts.is_unique || + key_part_cmp(old_index_def->key_def->parts, + old_index_def->key_def->part_count, + new_index_def->key_def->parts, + new_index_def->key_def->part_count) != 0) { + return true; + } + if (old_index_def->type == RTREE) { + if (old_index_def->opts.dimension != new_index_def->opts.dimension + || old_index_def->opts.distance != new_index_def->opts.distance) + return true; + } + return false; +} + +int +index_def_cmp(const struct index_def *key1, const struct index_def *key2) +{ + assert(key1->space_id == key2->space_id); + if (key1->iid != key2->iid) + return key1->iid < key2->iid ? -1 : 1; + if (strcmp(key1->name, key2->name)) + return strcmp(key1->name, key2->name); + if (key1->type != key2->type) + return (int) key1->type < (int) key2->type ? -1 : 1; + if (index_opts_cmp(&key1->opts, &key2->opts)) + return index_opts_cmp(&key1->opts, &key2->opts); + + return key_part_cmp(key1->key_def->parts, key1->key_def->part_count, + key2->key_def->parts, key2->key_def->part_count); +} + +bool +index_def_is_valid(struct index_def *index_def, const char *space_name) + +{ + if (index_def->iid >= BOX_INDEX_MAX) { + diag_set(ClientError, ER_MODIFY_INDEX, index_def->name, + space_name, "index id too big"); + return false; + } + if (index_def->iid == 0 && index_def->opts.is_unique == false) { + diag_set(ClientError, ER_MODIFY_INDEX, index_def->name, + space_name, "primary key must be unique"); + return false; + } + if (index_def->key_def->part_count == 0) { + diag_set(ClientError, ER_MODIFY_INDEX, index_def->name, + space_name, "part count must be positive"); + return false; + } + if (index_def->key_def->part_count > BOX_INDEX_PART_MAX) { + diag_set(ClientError, ER_MODIFY_INDEX, index_def->name, + space_name, "too many key parts"); + return false; + } + for (uint32_t i = 0; i < index_def->key_def->part_count; i++) { + assert(index_def->key_def->parts[i].type > FIELD_TYPE_ANY && + index_def->key_def->parts[i].type < field_type_MAX); + if (index_def->key_def->parts[i].fieldno > BOX_INDEX_FIELD_MAX) { + diag_set(ClientError, ER_MODIFY_INDEX, index_def->name, + space_name, "field no is too big"); + return false; + } + for (uint32_t j = 0; j < i; j++) { + /* + * Courtesy to a user who could have made + * a typo. + */ + if (index_def->key_def->parts[i].fieldno == + index_def->key_def->parts[j].fieldno) { + diag_set(ClientError, ER_MODIFY_INDEX, + index_def->name, space_name, + "same key part is indexed twice"); + return false; + } + } + } + return true; +} diff --git a/src/box/index_def.h b/src/box/index_def.h new file mode 100644 index 0000000000000000000000000000000000000000..9d56c12ab87697a1a19e42565614c94d4fd04c85 --- /dev/null +++ b/src/box/index_def.h @@ -0,0 +1,253 @@ +#ifndef TARANTOOL_BOX_INDEX_DEF_H_INCLUDED +#define TARANTOOL_BOX_INDEX_DEF_H_INCLUDED +/* + * Copyright 2010-2016, Tarantool AUTHORS, please see AUTHORS file. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * 1. Redistributions of source code must retain the above + * copyright notice, this list of conditions and the + * following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY <COPYRIGHT HOLDER> ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * <COPYRIGHT HOLDER> OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF + * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "key_def.h" +#include "opt_def.h" +#include "small/rlist.h" + +#if defined(__cplusplus) +extern "C" { +#endif /* defined(__cplusplus) */ + +enum index_type { + HASH = 0, /* HASH Index */ + TREE, /* TREE Index */ + BITSET, /* BITSET Index */ + RTREE, /* R-Tree Index */ + index_type_MAX, +}; + +extern const char *index_type_strs[]; + +enum rtree_index_distance_type { + /* Euclid distance, sqrt(dx*dx + dy*dy) */ + RTREE_INDEX_DISTANCE_TYPE_EUCLID, + /* Manhattan distance, fabs(dx) + fabs(dy) */ + RTREE_INDEX_DISTANCE_TYPE_MANHATTAN, + rtree_index_distance_type_MAX +}; +extern const char *rtree_index_distance_type_strs[]; + +/** Index options */ +struct index_opts { + /** + * Is this index unique or not - relevant to HASH/TREE + * index + */ + bool is_unique; + /** + * RTREE index dimension. + */ + int64_t dimension; + /** + * RTREE distance type. + */ + char distancebuf[16]; + enum rtree_index_distance_type distance; + /** + * Vinyl index options. + */ + int64_t range_size; + int64_t page_size; + /** + * Maximal number of runs that can be created in a level + * of the LSM tree before triggering compaction. + */ + int64_t run_count_per_level; + /** + * The LSM tree multiplier. Each subsequent level of + * the LSM tree is run_size_ratio times larger than + * previous one. + */ + double run_size_ratio; + /* Bloom filter false positive rate. */ + double bloom_fpr; + /** + * LSN from the time of index creation. + */ + int64_t lsn; +}; + +extern const struct index_opts index_opts_default; +extern const struct opt_def index_opts_reg[]; + +static inline int +index_opts_cmp(const struct index_opts *o1, const struct index_opts *o2) +{ + if (o1->is_unique != o2->is_unique) + return o1->is_unique < o2->is_unique ? -1 : 1; + if (o1->dimension != o2->dimension) + return o1->dimension < o2->dimension ? -1 : 1; + if (o1->distance != o2->distance) + return o1->distance < o2->distance ? -1 : 1; + if (o1->range_size != o2->range_size) + return o1->range_size < o2->range_size ? -1 : 1; + if (o1->page_size != o2->page_size) + return o1->page_size < o2->page_size ? -1 : 1; + if (o1->run_count_per_level != o2->run_count_per_level) + return o1->run_count_per_level < o2->run_count_per_level ? + -1 : 1; + if (o1->run_size_ratio != o2->run_size_ratio) + return o1->run_size_ratio < o2->run_size_ratio ? -1 : 1; + if (o1->bloom_fpr != o2->bloom_fpr) + return o1->bloom_fpr < o2->bloom_fpr ? -1 : 1; + return 0; +} + +/* Definition of an index. */ +struct index_def { + /* A link in key list. */ + struct rlist link; + /** Ordinal index number in the index array. */ + uint32_t iid; + /* Space id. */ + uint32_t space_id; + /** Index name. */ + char *name; + /** Index type. */ + enum index_type type; + struct index_opts opts; + + /* Index key definition. */ + struct key_def *key_def; + /** + * User-defined key definition, merged with the primary + * key parts. Used by non-unique keys to uniquely identify + * iterator position. + */ + struct key_def *cmp_def; +}; + +struct index_def * +index_def_dup(const struct index_def *def); + +void +index_def_swap(struct index_def *def1, struct index_def *def2); + +/* Destroy and free an index_def. */ +void +index_def_delete(struct index_def *def); + +/** + * Add an index definition to a list, preserving the + * first position of the primary key. + * + * In non-unique indexes, secondary keys must contain key parts + * of the primary key. This is necessary to make ordered + * retrieval from a secondary key useful to SQL + * optimizer and make iterators over secondary keys stable + * in presence of concurrent updates. + * Thus we always create the primary key first, and put + * the primary key key_def first in the index_def list. + */ +static inline void +index_def_list_add(struct rlist *index_def_list, struct index_def *index_def) +{ + /** Preserve the position of the primary key */ + if (index_def->iid == 0) + rlist_add_entry(index_def_list, index_def, link); + else + rlist_add_tail_entry(index_def_list, index_def, link); +} + +/** + * True, if the index change by alter requires an index rebuild. + * + * Some changes, such as a new page size or bloom_fpr do not + * take effect immediately, so do not require a rebuild. + * + * Others, such as index name change, do not change the data, only + * metadata, so do not require a rebuild either. + * + * Finally, changing index type or number of parts always requires + * a rebuild. + */ +bool +index_def_change_requires_rebuild(struct index_def *old_index_def, + struct index_def *new_index_def); + +/** + * Create a new index definition definition. + * + * @param key_def key definition, must be fully built + * @param pk_def primary key definition, pass non-NULL + * for secondary keys to construct + * index_def::cmp_def + * @retval not NULL Success. + * @retval NULL Memory error. + */ +struct index_def * +index_def_new(uint32_t space_id, uint32_t iid, const char *name, + uint32_t name_len, enum index_type type, + const struct index_opts *opts, + struct key_def *key_def, struct key_def *pk_def); + +/** + * One key definition is greater than the other if it's id is + * greater, it's name is greater, it's index type is greater + * (HASH < TREE < BITSET) or its key part array is greater. + */ +int +index_def_cmp(const struct index_def *key1, const struct index_def *key2); + +/** + * Check a key definition for violation of various limits. + * + * @param index_def index definition + * @param old_space space definition + */ +bool +index_def_is_valid(struct index_def *index_def, const char *space_name); + +#if defined(__cplusplus) +} /* extern "C" */ + +static inline struct index_def * +index_def_dup_xc(const struct index_def *def) +{ + struct index_def *ret = index_def_dup(def); + if (ret == NULL) + diag_raise(); + return ret; +} + +static inline void +index_def_check_xc(struct index_def *index_def, const char *space_name) +{ + if (! index_def_is_valid(index_def, space_name)) + diag_raise(); +} + +#endif /* defined(__cplusplus) */ + +#endif /* TARANTOOL_BOX_INDEX_DEF_H_INCLUDED */ diff --git a/src/box/key_def.cc b/src/box/key_def.cc index c989bb4cc9b0ae9fb1affc74baa88cfedb12bf93..7db87ee228af5f4b925dbd2845daeab903923445 100644 --- a/src/box/key_def.cc +++ b/src/box/key_def.cc @@ -29,48 +29,10 @@ * SUCH DAMAGE. */ #include "key_def.h" - -#include <stdlib.h> -#include <stdio.h> - -#include <msgpuck/msgpuck.h> - -#include "trivia/util.h" -#include "scoped_guard.h" - #include "tuple_compare.h" #include "tuple_hash.h" #include "column_mask.h" - -const char *field_type_strs[] = { - /* [FIELD_TYPE_ANY] = */ "any", - /* [FIELD_TYPE_UNSIGNED] = */ "unsigned", - /* [FIELD_TYPE_STRING] = */ "string", - /* [FIELD_TYPE_ARRAY] = */ "array", - /* [FIELD_TYPE_NUMBER] = */ "number", - /* [FIELD_TYPE_INTEGER] = */ "integer", - /* [FIELD_TYPE_SCALAR] = */ "scalar", - /* [FIELD_TYPE_MAP] = */ "map", -}; - -enum field_type -field_type_by_name(const char *name) -{ - enum field_type field_type = STR2ENUM(field_type, name); - /* - * FIELD_TYPE_ANY can't be used as type of indexed field, - * because it is internal type used only for filling - * struct tuple_format.fields array. - */ - if (field_type != field_type_MAX && field_type != FIELD_TYPE_ANY) - return field_type; - /* 'num' and 'str' in _index are deprecated since Tarantool 1.7 */ - if (strcasecmp(name, "num") == 0) - return FIELD_TYPE_UNSIGNED; - else if (strcasecmp(name, "str") == 0) - return FIELD_TYPE_STRING; - return field_type_MAX; -} +#include "schema_def.h" const char *mp_type_strs[] = { /* .MP_NIL = */ "nil", @@ -86,12 +48,6 @@ const char *mp_type_strs[] = { /* .MP_EXT = */ "extension", }; -const char *index_type_strs[] = { "HASH", "TREE", "BITSET", "RTREE" }; - -const char *rtree_index_distance_type_strs[] = { "EUCLID", "MANHATTAN" }; - -const char *func_language_strs[] = {"LUA", "C"}; - const uint32_t key_mp_type[] = { /* [FIELD_TYPE_ANY] = */ UINT32_MAX, /* [FIELD_TYPE_UNSIGNED] = */ 1U << MP_UINT, @@ -105,61 +61,6 @@ const uint32_t key_mp_type[] = { (1U << MP_BIN) | (1U << MP_BOOL), }; -const char *opt_type_strs[] = { - /* [OPT_BOOL] = */ "boolean", - /* [OPT_INT] = */ "integer", - /* [OPT_FLOAT] = */ "float", - /* [OPT_STR] = */ "string", -}; - -const struct index_opts index_opts_default = { - /* .unique = */ true, - /* .dimension = */ 2, - /* .distancebuf = */ { '\0' }, - /* .distance = */ RTREE_INDEX_DISTANCE_TYPE_EUCLID, - /* .range_size = */ 0, - /* .page_size = */ 0, - /* .run_count_per_level = */ 2, - /* .run_size_ratio = */ 3.5, - /* .bloom_fpr = */ 0.05, - /* .lsn = */ 0, -}; - -const struct opt_def index_opts_reg[] = { - OPT_DEF("unique", OPT_BOOL, struct index_opts, is_unique), - OPT_DEF("dimension", OPT_INT, struct index_opts, dimension), - OPT_DEF("distance", OPT_STR, struct index_opts, distancebuf), - OPT_DEF("range_size", OPT_INT, struct index_opts, range_size), - OPT_DEF("page_size", OPT_INT, struct index_opts, page_size), - OPT_DEF("run_count_per_level", OPT_INT, struct index_opts, run_count_per_level), - OPT_DEF("run_size_ratio", OPT_FLOAT, struct index_opts, run_size_ratio), - OPT_DEF("bloom_fpr", OPT_FLOAT, struct index_opts, bloom_fpr), - OPT_DEF("lsn", OPT_INT, struct index_opts, lsn), - { NULL, opt_type_MAX, 0, 0 }, -}; - -static const char *object_type_strs[] = { - "unknown", "universe", "space", "function", "user", "role" }; - -enum schema_object_type -schema_object_type(const char *name) -{ - /** - * There may be other places in which we look object type by - * name, and they are case-sensitive, so be case-sensitive - * here too. - */ - int n_strs = sizeof(object_type_strs)/sizeof(*object_type_strs); - int index = strindex(object_type_strs, name, n_strs); - return (enum schema_object_type) (index == n_strs ? 0 : index); -} - -const char * -schema_object_name(enum schema_object_type type) -{ - return object_type_strs[type]; -} - struct key_def * key_def_dup(const struct key_def *src) { @@ -215,164 +116,6 @@ box_key_def_delete(box_key_def_t *key_def) free(key_def); } -struct space_def * -space_def_dup(const struct space_def *src) -{ - size_t size = space_def_sizeof(strlen(src->name)); - struct space_def *ret = (struct space_def *) malloc(size); - if (ret == NULL) - tnt_raise(OutOfMemory, size, "malloc", "ret"); - memcpy(ret, src, size); - return ret; -} - -struct space_def * -space_def_new(uint32_t id, uint32_t uid, uint32_t exact_field_count, - const char *name, uint32_t name_len, - const char *engine_name, uint32_t engine_len, - const struct space_opts *opts) -{ - size_t size = space_def_sizeof(name_len); - struct space_def *def = (struct space_def *) malloc(size); - if (def == NULL) - tnt_raise(OutOfMemory, size, "malloc", "def"); - assert(name_len <= BOX_NAME_MAX); - assert(engine_len <= ENGINE_NAME_MAX); - def->id = id; - def->uid = uid; - def->exact_field_count = exact_field_count; - memcpy(def->name, name, name_len); - def->name[name_len] = 0; - memcpy(def->engine_name, engine_name, engine_len); - def->engine_name[engine_len] = 0; - def->opts = *opts; - return def; -} - -struct index_def * -index_def_new(uint32_t space_id, uint32_t iid, const char *name, - uint32_t name_len, enum index_type type, - const struct index_opts *opts, - struct key_def *key_def, struct key_def *pk_def) -{ - assert(name_len <= BOX_NAME_MAX); - /* Use calloc to make index_def_delete() safe at all times. */ - struct index_def *def = (struct index_def *) calloc(1, sizeof(*def)); - if (def == NULL) { - diag_set(OutOfMemory, sizeof(*def), "malloc", "struct index_def"); - return NULL; - } - def->name = strndup(name, name_len); - if (def->name == NULL) { - index_def_delete(def); - diag_set(OutOfMemory, name_len + 1, "malloc", "index_def name"); - return NULL; - } - if (!identifier_is_valid(def->name)) { - diag_set(ClientError, ER_IDENTIFIER, def->name); - index_def_delete(def); - return NULL; - } - def->key_def = key_def_dup(key_def); - if (pk_def) - def->cmp_def = key_def_merge(key_def, pk_def); - else - def->cmp_def = key_def_dup(key_def); - if (def->key_def == NULL || def->cmp_def == NULL) { - index_def_delete(def); - return NULL; - } - def->type = type; - def->space_id = space_id; - def->iid = iid; - def->opts = *opts; - return def; -} - -struct index_def * -index_def_dup(const struct index_def *def) -{ - struct index_def *dup = (struct index_def *) malloc(sizeof(*dup)); - if (dup == NULL) { - diag_set(OutOfMemory, sizeof(*dup), "malloc", - "struct index_def"); - return NULL; - } - *dup = *def; - dup->name = strdup(def->name); - if (dup->name == NULL) { - free(dup); - diag_set(OutOfMemory, strlen(def->name) + 1, "malloc", - "index_def name"); - return NULL; - } - dup->key_def = key_def_dup(def->key_def); - dup->cmp_def = key_def_dup(def->cmp_def); - if (dup->key_def == NULL || dup->cmp_def == NULL) { - index_def_delete(dup); - return NULL; - } - rlist_create(&dup->link); - return dup; -} - -void -index_def_swap(struct index_def *def1, struct index_def *def2) -{ - /* - * Swap const-size items and name. Keep the original key - * definitions, they are used in the engines. - */ - struct index_def tmp_def = *def1; - memcpy(def1, def2, offsetof(struct index_def, key_def)); - memcpy(def2, &tmp_def, offsetof(struct index_def, key_def)); - /* - * index_def_swap() is used only during alter to modify - * index metadata. - */ -} - -/** Free a key definition. */ -void -index_def_delete(struct index_def *index_def) -{ - free(index_def->name); - - if (index_def->key_def) { - TRASH(index_def->key_def); - free(index_def->key_def); - } - - if (index_def->cmp_def) { - TRASH(index_def->cmp_def); - free(index_def->cmp_def); - } - - TRASH(index_def); - free(index_def); -} - -bool -index_def_change_requires_rebuild(struct index_def *old_index_def, - struct index_def *new_index_def) -{ - if (old_index_def->iid != new_index_def->iid || - old_index_def->type != new_index_def->type || - old_index_def->opts.is_unique != new_index_def->opts.is_unique || - key_part_cmp(old_index_def->key_def->parts, - old_index_def->key_def->part_count, - new_index_def->key_def->parts, - new_index_def->key_def->part_count) != 0) { - return true; - } - if (old_index_def->type == RTREE) { - if (old_index_def->opts.dimension != new_index_def->opts.dimension - || old_index_def->opts.distance != new_index_def->opts.distance) - return true; - } - return false; -} - int key_part_cmp(const struct key_part *parts1, uint32_t part_count1, const struct key_part *parts2, uint32_t part_count2) @@ -390,75 +133,6 @@ key_part_cmp(const struct key_part *parts1, uint32_t part_count1, return part_count1 < part_count2 ? -1 : part_count1 > part_count2; } -int -index_def_cmp(const struct index_def *key1, const struct index_def *key2) -{ - assert(key1->space_id == key2->space_id); - if (key1->iid != key2->iid) - return key1->iid < key2->iid ? -1 : 1; - if (strcmp(key1->name, key2->name)) - return strcmp(key1->name, key2->name); - if (key1->type != key2->type) - return (int) key1->type < (int) key2->type ? -1 : 1; - if (index_opts_cmp(&key1->opts, &key2->opts)) - return index_opts_cmp(&key1->opts, &key2->opts); - - return key_part_cmp(key1->key_def->parts, key1->key_def->part_count, - key2->key_def->parts, key2->key_def->part_count); -} - -void -index_def_check(struct index_def *index_def, const char *space_name) - -{ - if (index_def->iid >= BOX_INDEX_MAX) { - tnt_raise(ClientError, ER_MODIFY_INDEX, - index_def->name, space_name, - "index id too big"); - } - if (index_def->iid == 0 && index_def->opts.is_unique == false) { - tnt_raise(ClientError, ER_MODIFY_INDEX, - index_def->name, - space_name, - "primary key must be unique"); - } - if (index_def->key_def->part_count == 0) { - tnt_raise(ClientError, ER_MODIFY_INDEX, - index_def->name, - space_name, - "part count must be positive"); - } - if (index_def->key_def->part_count > BOX_INDEX_PART_MAX) { - tnt_raise(ClientError, ER_MODIFY_INDEX, - index_def->name, - space_name, - "too many key parts"); - } - for (uint32_t i = 0; i < index_def->key_def->part_count; i++) { - assert(index_def->key_def->parts[i].type > FIELD_TYPE_ANY && - index_def->key_def->parts[i].type < field_type_MAX); - if (index_def->key_def->parts[i].fieldno > BOX_INDEX_FIELD_MAX) { - tnt_raise(ClientError, ER_MODIFY_INDEX, - index_def->name, - space_name, - "field no is too big"); - } - for (uint32_t j = 0; j < i; j++) { - /* - * Courtesy to a user who could have made - * a typo. - */ - if (index_def->key_def->parts[i].fieldno == - index_def->key_def->parts[j].fieldno) { - tnt_raise(ClientError, ER_MODIFY_INDEX, - index_def->name, - space_name, - "same key part is indexed twice"); - } - } - } -} - void key_def_set_part(struct key_def *def, uint32_t part_no, uint32_t fieldno, enum field_type type) @@ -663,44 +337,3 @@ key_validate_parts(struct key_def *key_def, const char *key, } return 0; } - -const struct space_opts space_opts_default = { - /* .temporary = */ false, -}; - -const struct opt_def space_opts_reg[] = { - OPT_DEF("temporary", OPT_BOOL, struct space_opts, temporary), - { NULL, opt_type_MAX, 0, 0 } -}; - -bool -identifier_is_valid(const char *str) -{ - mbstate_t state; - memset(&state, 0, sizeof(state)); - wchar_t w; - ssize_t len = mbrtowc(&w, str, MB_CUR_MAX, &state); - if (len <= 0) - return false; /* invalid character or zero-length string */ - if (!iswalpha(w) && w != L'_') - return false; /* fail to match [a-zA-Z_] */ - - while ((len = mbrtowc(&w, str, MB_CUR_MAX, &state)) > 0) { - if (!iswalnum(w) && w != L'_') - return false; /* fail to match [a-zA-Z0-9_]* */ - str += len; - } - - if (len < 0) - return false; /* invalid character */ - - return true; -} - -void -identifier_check(const char *str) -{ - if (! identifier_is_valid(str)) - tnt_raise(ClientError, ER_IDENTIFIER, str); -} - diff --git a/src/box/key_def.h b/src/box/key_def.h index 478d9bf366bf8caf89954dbe33dc5ef5c0e72637..3147b6f9e03d25a4a3c22aba4c8d98a43c24d201 100644 --- a/src/box/key_def.h +++ b/src/box/key_def.h @@ -31,221 +31,25 @@ * SUCH DAMAGE. */ #include "trivia/util.h" -#include "small/rlist.h" #include "error.h" #include "diag.h" #include <msgpuck.h> -#define RB_COMPACT 1 -#include "small/rb.h" #include <limits.h> -#include <wchar.h> -#include <wctype.h> +#include "field_def.h" #if defined(__cplusplus) extern "C" { #endif /* defined(__cplusplus) */ -enum { - BOX_ENGINE_MAX = 3, /* + 1 to the actual number of engines */ - BOX_SPACE_MAX = INT32_MAX, - BOX_FUNCTION_MAX = 32000, - BOX_INDEX_MAX = 128, - BOX_NAME_MAX = 65000, - BOX_INVALID_NAME_MAX = 64, - ENGINE_NAME_MAX = 16, - FIELD_TYPE_NAME_MAX = 16, - GRANT_NAME_MAX = 16, - BOX_FIELD_MAX = INT32_MAX, - BOX_USER_MAX = 32, - /** - * A fairly arbitrary limit which is still necessary - * to keep tuple_format object small. - */ - BOX_INDEX_FIELD_MAX = INT16_MAX, - /** Yet another arbitrary limit which simply needs to - * exist. - */ - BOX_INDEX_PART_MAX = UINT8_MAX -}; -static_assert(BOX_INVALID_NAME_MAX <= BOX_NAME_MAX, - "invalid name max is less than name max"); - -/* - * Different objects which can be subject to access - * control. - * - * Use 0 for unknown to use the same index consistently - * even when there are more object types in the future. - */ -enum schema_object_type { - SC_UNKNOWN = 0, SC_UNIVERSE = 1, SC_SPACE = 2, SC_FUNCTION = 3, - SC_USER = 4, SC_ROLE = 5 -}; - -enum schema_object_type -schema_object_type(const char *name); - -const char * -schema_object_name(enum schema_object_type type); - -/** \cond public */ - -/* - * Possible field data types. Can't use STRS/ENUM macros for them, - * since there is a mismatch between enum name (STRING) and type - * name literal ("STR"). STR is already used as Objective C type. - */ -enum field_type { - FIELD_TYPE_ANY = 0, - FIELD_TYPE_UNSIGNED, - FIELD_TYPE_STRING, - FIELD_TYPE_ARRAY, - FIELD_TYPE_NUMBER, - FIELD_TYPE_INTEGER, - FIELD_TYPE_SCALAR, - FIELD_TYPE_MAP, - field_type_MAX -}; - -/** \endcond public */ - -extern const char *field_type_strs[]; - /* MsgPack type names */ extern const char *mp_type_strs[]; -/** - * The supported language of the stored function. - */ -enum func_language { - FUNC_LANGUAGE_LUA, - FUNC_LANGUAGE_C, - func_language_MAX, -}; -extern const char *func_language_strs[]; - -static inline uint32_t -field_type_maxlen(enum field_type type) -{ - static const uint32_t maxlen[] = - { UINT32_MAX, 8, UINT32_MAX, UINT32_MAX, UINT32_MAX }; - return maxlen[type]; -} - -enum field_type -field_type_by_name(const char *name); - -enum index_type { - HASH = 0, /* HASH Index */ - TREE, /* TREE Index */ - BITSET, /* BITSET Index */ - RTREE, /* R-Tree Index */ - index_type_MAX, -}; - -extern const char *index_type_strs[]; - -enum opt_type { - OPT_BOOL, /* bool */ - OPT_INT, /* int64_t */ - OPT_FLOAT, /* double */ - OPT_STR, /* char[] */ - opt_type_MAX, -}; - -extern const char *opt_type_strs[]; - -struct opt_def { - const char *name; - enum opt_type type; - ptrdiff_t offset; - uint32_t len; -}; - -#define OPT_DEF(key, type, opts, field) \ - { key, type, offsetof(opts, field), sizeof(((opts *)0)->field) } - -enum rtree_index_distance_type { - /* Euclid distance, sqrt(dx*dx + dy*dy) */ - RTREE_INDEX_DISTANCE_TYPE_EUCLID, - /* Manhattan distance, fabs(dx) + fabs(dy) */ - RTREE_INDEX_DISTANCE_TYPE_MANHATTAN, - rtree_index_distance_type_MAX -}; -extern const char *rtree_index_distance_type_strs[]; - /** Descriptor of a single part in a multipart key. */ struct key_part { uint32_t fieldno; enum field_type type; }; -/** Index options */ -struct index_opts { - /** - * Is this index unique or not - relevant to HASH/TREE - * index - */ - bool is_unique; - /** - * RTREE index dimension. - */ - int64_t dimension; - /** - * RTREE distance type. - */ - char distancebuf[16]; - enum rtree_index_distance_type distance; - /** - * Vinyl index options. - */ - int64_t range_size; - int64_t page_size; - /** - * Maximal number of runs that can be created in a level - * of the LSM tree before triggering compaction. - */ - int64_t run_count_per_level; - /** - * The LSM tree multiplier. Each subsequent level of - * the LSM tree is run_size_ratio times larger than - * previous one. - */ - double run_size_ratio; - /* Bloom filter false positive rate. */ - double bloom_fpr; - /** - * LSN from the time of index creation. - */ - int64_t lsn; -}; - -extern const struct index_opts index_opts_default; -extern const struct opt_def index_opts_reg[]; - -static inline int -index_opts_cmp(const struct index_opts *o1, const struct index_opts *o2) -{ - if (o1->is_unique != o2->is_unique) - return o1->is_unique < o2->is_unique ? -1 : 1; - if (o1->dimension != o2->dimension) - return o1->dimension < o2->dimension ? -1 : 1; - if (o1->distance != o2->distance) - return o1->distance < o2->distance ? -1 : 1; - if (o1->range_size != o2->range_size) - return o1->range_size < o2->range_size ? -1 : 1; - if (o1->page_size != o2->page_size) - return o1->page_size < o2->page_size ? -1 : 1; - if (o1->run_count_per_level != o2->run_count_per_level) - return o1->run_count_per_level < o2->run_count_per_level ? - -1 : 1; - if (o1->run_size_ratio != o2->run_size_ratio) - return o1->run_size_ratio < o2->run_size_ratio ? -1 : 1; - if (o1->bloom_fpr != o2->bloom_fpr) - return o1->bloom_fpr < o2->bloom_fpr ? -1 : 1; - return 0; -} - struct key_def; struct tuple; @@ -332,231 +136,6 @@ box_key_def_delete(box_key_def_t *key_def); /** \endcond public */ -/* Definition of an index. */ -struct index_def { - /* A link in key list. */ - struct rlist link; - /** Ordinal index number in the index array. */ - uint32_t iid; - /* Space id. */ - uint32_t space_id; - /** Index name. */ - char *name; - /** Index type. */ - enum index_type type; - struct index_opts opts; - - /* Index key definition. */ - struct key_def *key_def; - /** - * User-defined key definition, merged with the primary - * key parts. Used by non-unique keys to uniquely identify - * iterator position. - */ - struct key_def *cmp_def; -}; - -struct index_def * -index_def_dup(const struct index_def *def); - -void -index_def_swap(struct index_def *def1, struct index_def *def2); - -/* Destroy and free an index_def. */ -void -index_def_delete(struct index_def *def); - -/** - * Add an index definition to a list, preserving the - * first position of the primary key. - * - * In non-unique indexes, secondary keys must contain key parts - * of the primary key. This is necessary to make ordered - * retrieval from a secondary key useful to SQL - * optimizer and make iterators over secondary keys stable - * in presence of concurrent updates. - * Thus we always create the primary key first, and put - * the primary key key_def first in the index_def list. - */ -static inline void -index_def_list_add(struct rlist *index_def_list, struct index_def *index_def) -{ - /** Preserve the position of the primary key */ - if (index_def->iid == 0) - rlist_add_entry(index_def_list, index_def, link); - else - rlist_add_tail_entry(index_def_list, index_def, link); -} - -/** - * True, if the index change by alter requires an index rebuild. - * - * Some changes, such as a new page size or bloom_fpr do not - * take effect immediately, so do not require a rebuild. - * - * Others, such as index name change, do not change the data, only - * metadata, so do not require a rebuild either. - * - * Finally, changing index type or number of parts always requires - * a rebuild. - */ -bool -index_def_change_requires_rebuild(struct index_def *old_index_def, - struct index_def *new_index_def); - -/** - * Encapsulates privileges of a user on an object. - * I.e. "space" object has an instance of this - * structure for each user. - */ -struct access { - /** - * Granted access has been given to a user explicitly - * via some form of a grant. - */ - uint8_t granted; - /** - * Effective access is a sum of granted access and - * all privileges inherited by a user on this object - * via some role. Since roles may be granted to other - * roles, this may include indirect grants. - */ - uint8_t effective; -}; - -/** - * Effective session user. A cache of user data - * and access stored in session and fiber local storage. - * Differs from the authenticated user when executing - * setuid functions. - */ -struct credentials { - /** A look up key to quickly find session user. */ - uint8_t auth_token; - /** - * Cached global grants, to avoid an extra look up - * when checking global grants. - */ - uint8_t universal_access; - /** User id of the authenticated user. */ - uint32_t uid; -}; - -/** - * Definition of a function. Function body is not stored - * or replicated (yet). - */ -struct func_def { - /** Function id. */ - uint32_t fid; - /** Owner of the function. */ - uint32_t uid; - /** - * True if the function requires change of user id before - * invocation. - */ - bool setuid; - /** - * The language of the stored function. - */ - enum func_language language; - /** Function name. */ - char name[0]; -}; - -/** - * @param name_len length of func_def->name - * @returns size in bytes needed to allocate for struct func_def - * for a function of length @a a name_len. - */ -static inline size_t -func_def_sizeof(uint32_t name_len) -{ - /* +1 for '\0' name terminating. */ - return sizeof(struct func_def) + name_len + 1; -} - -/** - * Definition of a privilege - */ -struct priv_def { - /** Who grants the privilege. */ - uint32_t grantor_id; - /** Whom the privilege is granted. */ - uint32_t grantee_id; - /* Object id - is only defined for object type */ - uint32_t object_id; - /* Object type - function, space, universe */ - enum schema_object_type object_type; - /** - * What is being granted, has been granted, or is being - * revoked. - */ - uint8_t access; - /** To maintain a set of effective privileges. */ - rb_node(struct priv_def) link; -}; - -/** Space options */ -struct space_opts { - /** - * The space is a temporary: - * - it is empty at server start - * - changes are not written to WAL - * - changes are not part of a snapshot - */ - bool temporary; -}; - -extern const struct space_opts space_opts_default; -extern const struct opt_def space_opts_reg[]; - -/** Space metadata. */ -struct space_def { - /** Space id. */ - uint32_t id; - /** User id of the creator of the space */ - uint32_t uid; - /** - * If not set (is 0), any tuple in the - * space can have any number of fields. - * If set, each tuple - * must have exactly this many fields. - */ - uint32_t exact_field_count; - char engine_name[ENGINE_NAME_MAX + 1]; - struct space_opts opts; - char name[0]; -}; - -/** - * Size of the space_def, calculated using its name. - * @param name_len Length of the space name. - * @retval Size in bytes. - */ -static inline size_t -space_def_sizeof(uint32_t name_len) -{ - return sizeof(struct space_def) + name_len + 1; -} - -/** - * Delete the space_def object. - * @param def Def to delete. - */ -static inline void -space_def_delete(struct space_def *def) -{ - free(def); -} - -/** - * API of C stored function. - */ -typedef struct box_function_ctx box_function_ctx_t; -typedef int (*box_function_f)(box_function_ctx_t *ctx, - const char *args, const char *args_end); - static inline size_t key_def_sizeof(uint32_t part_count) { @@ -569,22 +148,6 @@ key_def_sizeof(uint32_t part_count) struct key_def * key_def_new(uint32_t part_count); -/** - * Create a new index definition definition. - * - * @param key_def key definition, must be fully built - * @param pk_def primary key definition, pass non-NULL - * for secondary keys to construct - * index_def::cmp_def - * @retval not NULL Success. - * @retval NULL Memory error. - */ -struct index_def * -index_def_new(uint32_t space_id, uint32_t iid, const char *name, - uint32_t name_len, enum index_type type, - const struct index_opts *opts, - struct key_def *key_def, struct key_def *pk_def); - /** * Set a single key part in a key def. * @pre part_no < part_count @@ -709,37 +272,6 @@ key_mp_type_validate(enum field_type key_type, enum mp_type mp_type, return 0; } -#if defined(__cplusplus) -} /* extern "C" */ - -/** - * Duplicate space_def object. - * @param src Def to duplicate. - * @retval Copy of the @src. - */ -struct space_def * -space_def_dup(const struct space_def *src); /* throws */ - -/** - * Create a new space definition. - * @param id Space identifier. - * @param uid Owner identifier. - * @param exact_field_count Space tuples field count. - * 0 for any count. - * @param name Space name. - * @param name_len Length of the @name. - * @param engine_name Engine name. - * @param engine_len Length of the @engine. - * @param opts Space options. - * - * @retval Space definition. - */ -struct space_def * -space_def_new(uint32_t id, uint32_t uid, uint32_t exact_field_count, - const char *name, uint32_t name_len, - const char *engine_name, uint32_t engine_len, - const struct space_opts *opts); /* throws */ - /** Compare two key part arrays. * * This function is used to find out whether alteration @@ -751,7 +283,6 @@ space_def_new(uint32_t id, uint32_t uid, uint32_t exact_field_count, * One key part is considered to be greater than the other if: * - its fieldno is greater * - given the same fieldno, NUM < STRING - * (coarsely speaking, based on field_type_maxlen()). * * A key part array is considered greater than the other if all * its key parts are greater, or, all common key parts are equal @@ -761,46 +292,8 @@ int key_part_cmp(const struct key_part *parts1, uint32_t part_count1, const struct key_part *parts2, uint32_t part_count2); -/** - * One key definition is greater than the other if it's id is - * greater, it's name is greater, it's index type is greater - * (HASH < TREE < BITSET) or its key part array is greater. - */ -int -index_def_cmp(const struct index_def *key1, const struct index_def *key2); - -/** - * Check a key definition for violation of various limits. - * - * @param index_def index definition - * @param old_space space definition - */ -void -index_def_check(struct index_def *index_def, const char *space_name); - -/** - * Check object identifier for invalid symbols. - * The function checks \a str for matching [a-zA-Z_][a-zA-Z0-9_]* expression. - * Result is locale-dependent. - */ -bool -identifier_is_valid(const char *str); - -/** - * Throw an error if identifier is not valid. - */ -void -identifier_check(const char *str); - -static inline struct index_def * -index_def_dup_xc(const struct index_def *def) -{ - struct index_def *ret = index_def_dup(def); - if (ret == NULL) - diag_raise(); - return ret; -} - +#if defined(__cplusplus) +} /* extern "C" */ #endif /* defined(__cplusplus) */ #endif /* TARANTOOL_BOX_KEY_DEF_H_INCLUDED */ diff --git a/src/box/opt_def.c b/src/box/opt_def.c new file mode 100644 index 0000000000000000000000000000000000000000..d15bc7017ae3e2ac1ae453c3672016e01fc61bf0 --- /dev/null +++ b/src/box/opt_def.c @@ -0,0 +1,39 @@ +/* + * Copyright 2010-2016, Tarantool AUTHORS, please see AUTHORS file. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * 1. Redistributions of source code must retain the above + * copyright notice, this list of conditions and the + * following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY <COPYRIGHT HOLDER> ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * <COPYRIGHT HOLDER> OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF + * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "opt_def.h" + +const char *opt_type_strs[] = { + /* [OPT_BOOL] = */ "boolean", + /* [OPT_INT] = */ "integer", + /* [OPT_FLOAT] = */ "float", + /* [OPT_STR] = */ "string", +}; diff --git a/src/box/opt_def.h b/src/box/opt_def.h new file mode 100644 index 0000000000000000000000000000000000000000..c519a1e43578b841aed4ca0156c88cf24b9564e5 --- /dev/null +++ b/src/box/opt_def.h @@ -0,0 +1,57 @@ +#ifndef TARANTOOL_BOX_OPT_DEF_H_INCLUDED +#define TARANTOOL_BOX_OPT_DEF_H_INCLUDED +/* + * Copyright 2010-2016, Tarantool AUTHORS, please see AUTHORS file. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * 1. Redistributions of source code must retain the above + * copyright notice, this list of conditions and the + * following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY <COPYRIGHT HOLDER> ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * <COPYRIGHT HOLDER> OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF + * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "trivia/util.h" +#include <stddef.h> + +enum opt_type { + OPT_BOOL, /* bool */ + OPT_INT, /* int64_t */ + OPT_FLOAT, /* double */ + OPT_STR, /* char[] */ + opt_type_MAX, +}; + +extern const char *opt_type_strs[]; + +struct opt_def { + const char *name; + enum opt_type type; + ptrdiff_t offset; + uint32_t len; +}; + +#define OPT_DEF(key, type, opts, field) \ + { key, type, offsetof(opts, field), sizeof(((opts *)0)->field) } + +#endif /* TARANTOOL_BOX_OPT_DEF_H_INCLUDED */ diff --git a/src/box/schema.cc b/src/box/schema.cc index ff881b74a483a7ad3741ac6e21c9ed04927eda2a..91e4a0678665ee74d52ef26aeaa11f2aa04a6d7d 100644 --- a/src/box/schema.cc +++ b/src/box/schema.cc @@ -37,7 +37,6 @@ #include "assoc.h" #include "lua/utils.h" #include "lua/space.h" -#include "key_def.h" #include "alter.h" #include "scoped_guard.h" #include <stdio.h> @@ -191,8 +190,8 @@ sc_space_new(uint32_t id, const char *name, struct key_def *key_def, auto index_def_guard = make_scoped_guard([=] { index_def_delete(index_def); }); struct space_def *def = - space_def_new(id, ADMIN, 0, name, strlen(name), "memtx", - strlen("memtx"), &space_opts_default); + space_def_new_xc(id, ADMIN, 0, name, strlen(name), "memtx", + strlen("memtx"), &space_opts_default); auto def_guard = make_scoped_guard([=] { space_def_delete(def); }); struct rlist key_list; rlist_create(&key_list); diff --git a/src/box/schema.h b/src/box/schema.h index d9fc81cd653223fefeff5c3839c548661a5e7aa9..091b8253302f15ec05baf298d875a46527b6f610 100644 --- a/src/box/schema.h +++ b/src/box/schema.h @@ -31,126 +31,20 @@ * SUCH DAMAGE. */ -/** \cond public */ -enum { - /** Start of the reserved range of system spaces. */ - BOX_SYSTEM_ID_MIN = 256, - /** Space id of _schema. */ - BOX_SCHEMA_ID = 272, - /** Space id of _space. */ - BOX_SPACE_ID = 280, - /** Space id of _vspace view. */ - BOX_VSPACE_ID = 281, - /** Space id of _index. */ - BOX_INDEX_ID = 288, - /** Space id of _vindex view. */ - BOX_VINDEX_ID = 289, - /** Space id of _func. */ - BOX_FUNC_ID = 296, - /** Space id of _vfunc view. */ - BOX_VFUNC_ID = 297, - /** Space id of _user. */ - BOX_USER_ID = 304, - /** Space id of _vuser view. */ - BOX_VUSER_ID = 305, - /** Space id of _priv. */ - BOX_PRIV_ID = 312, - /** Space id of _vpriv view. */ - BOX_VPRIV_ID = 313, - /** Space id of _cluster. */ - BOX_CLUSTER_ID = 320, - /** Space id of _truncate. */ - BOX_TRUNCATE_ID = 330, - /** End of the reserved range of system spaces. */ - BOX_SYSTEM_ID_MAX = 511, - BOX_ID_NIL = 2147483647 -}; -/** \endcond public */ - -/** _space fields. */ -enum { - BOX_SPACE_FIELD_ID = 0, - BOX_SPACE_FIELD_UID = 1, - BOX_SPACE_FIELD_NAME = 2, - BOX_SPACE_FIELD_ENGINE = 3, - BOX_SPACE_FIELD_FIELD_COUNT = 4, - BOX_SPACE_FIELD_OPTS = 5, -}; - -/** _index fields. */ -enum { - BOX_INDEX_FIELD_SPACE_ID = 0, - BOX_INDEX_FIELD_ID = 1, - BOX_INDEX_FIELD_NAME = 2, - BOX_INDEX_FIELD_TYPE = 3, - BOX_INDEX_FIELD_OPTS = 4, - BOX_INDEX_FIELD_IS_UNIQUE_165 = 4, - BOX_INDEX_FIELD_PARTS = 5, - BOX_INDEX_FIELD_PART_COUNT_165 = 5, - BOX_INDEX_FIELD_PARTS_165 = 6, -}; - -/** _user fields. */ -enum { - BOX_USER_FIELD_ID = 0, - BOX_USER_FIELD_UID = 1, - BOX_USER_FIELD_NAME = 2, - BOX_USER_FIELD_TYPE = 3, - BOX_USER_FIELD_AUTH_MECH_LIST = 4, -}; - -/** _priv fields. */ -enum { - BOX_PRIV_FIELD_ID = 0, - BOX_PRIV_FIELD_UID = 1, - BOX_PRIV_FIELD_OBJECT_TYPE = 2, - BOX_PRIV_FIELD_OBJECT_ID = 3, - BOX_PRIV_FIELD_ACCESS = 4, -}; - -/** _func fields. */ -enum { - BOX_FUNC_FIELD_ID = 0, - BOX_FUNC_FIELD_UID = 1, - BOX_FUNC_FIELD_NAME = 2, - BOX_FUNC_FIELD_SETUID = 3, - BOX_FUNC_FIELD_LANGUAGE = 4, -}; - -/** _schema fields. */ -enum { - BOX_SCHEMA_FIELD_KEY = 0, -}; - -/** _cluster fields. */ -enum { - BOX_CLUSTER_FIELD_ID = 0, - BOX_CLUSTER_FIELD_UUID = 1, -}; - -/** _truncate fields. */ -enum { - BOX_TRUNCATE_FIELD_SPACE_ID = 0, - BOX_TRUNCATE_FIELD_COUNT = 1, -}; - #include <stdint.h> - -extern uint32_t schema_version; - -#if defined(__cplusplus) - -#include "error.h" #include <stdio.h> /* snprintf */ +#include "error.h" #include "space.h" #include "latch.h" +extern uint32_t schema_version; + /** * Lock of schema modification */ extern struct latch schema_lock; -struct space; +#if defined(__cplusplus) /** Call a visitor function on every space in the space cache. */ void @@ -254,6 +148,7 @@ func_by_name(const char *name, uint32_t name_len); */ bool schema_find_grants(const char *type, uint32_t id); + #endif /* defined(__cplusplus) */ #endif /* INCLUDES_TARANTOOL_BOX_SCHEMA_H */ diff --git a/src/box/schema_def.c b/src/box/schema_def.c new file mode 100644 index 0000000000000000000000000000000000000000..0907292669dff49cf90ac949769f38b2e4bb19cf --- /dev/null +++ b/src/box/schema_def.c @@ -0,0 +1,79 @@ +/* + * Copyright 2010-2016, Tarantool AUTHORS, please see AUTHORS file. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * 1. Redistributions of source code must retain the above + * copyright notice, this list of conditions and the + * following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY <COPYRIGHT HOLDER> ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * <COPYRIGHT HOLDER> OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF + * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +#include "schema_def.h" +#include <wchar.h> +#include <wctype.h> + +static const char *object_type_strs[] = { + "unknown", "universe", "space", "function", "user", "role" }; + +enum schema_object_type +schema_object_type(const char *name) +{ + /** + * There may be other places in which we look object type by + * name, and they are case-sensitive, so be case-sensitive + * here too. + */ + int n_strs = sizeof(object_type_strs)/sizeof(*object_type_strs); + int index = strindex(object_type_strs, name, n_strs); + return (enum schema_object_type) (index == n_strs ? 0 : index); +} + +const char * +schema_object_name(enum schema_object_type type) +{ + return object_type_strs[type]; +} + +bool +identifier_is_valid(const char *str) +{ + mbstate_t state; + memset(&state, 0, sizeof(state)); + wchar_t w; + ssize_t len = mbrtowc(&w, str, MB_CUR_MAX, &state); + if (len <= 0) + return false; /* invalid character or zero-length string */ + if (!iswalpha(w) && w != L'_') + return false; /* fail to match [a-zA-Z_] */ + + while ((len = mbrtowc(&w, str, MB_CUR_MAX, &state)) > 0) { + if (!iswalnum(w) && w != L'_') + return false; /* fail to match [a-zA-Z0-9_]* */ + str += len; + } + + if (len < 0) + return false; /* invalid character */ + + return true; +} diff --git a/src/box/schema_def.h b/src/box/schema_def.h new file mode 100644 index 0000000000000000000000000000000000000000..61b4c63682b0ccb02fcd3953848cbbf79a4cd40f --- /dev/null +++ b/src/box/schema_def.h @@ -0,0 +1,211 @@ +#ifndef TARANTOOL_BOX_SCHEMA_DEF_H_INCLUDED +#define TARANTOOL_BOX_SCHEMA_DEF_H_INCLUDED +/* + * Copyright 2010-2016, Tarantool AUTHORS, please see AUTHORS file. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * 1. Redistributions of source code must retain the above + * copyright notice, this list of conditions and the + * following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY <COPYRIGHT HOLDER> ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * <COPYRIGHT HOLDER> OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF + * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +#include "trivia/util.h" +#include <stdbool.h> + +#if defined(__cplusplus) +extern "C" { +#endif /* defined(__cplusplus) */ + +enum { + BOX_ENGINE_MAX = 3, /* + 1 to the actual number of engines */ + BOX_SPACE_MAX = INT32_MAX, + BOX_FUNCTION_MAX = 32000, + BOX_INDEX_MAX = 128, + BOX_NAME_MAX = 65000, + BOX_INVALID_NAME_MAX = 64, + ENGINE_NAME_MAX = 16, + FIELD_TYPE_NAME_MAX = 16, + GRANT_NAME_MAX = 16, + BOX_FIELD_MAX = INT32_MAX, + BOX_USER_MAX = 32, + /** + * A fairly arbitrary limit which is still necessary + * to keep tuple_format object small. + */ + BOX_INDEX_FIELD_MAX = INT16_MAX, + /** Yet another arbitrary limit which simply needs to + * exist. + */ + BOX_INDEX_PART_MAX = UINT8_MAX +}; +static_assert(BOX_INVALID_NAME_MAX <= BOX_NAME_MAX, + "invalid name max is less than name max"); + +/** \cond public */ +enum { + /** Start of the reserved range of system spaces. */ + BOX_SYSTEM_ID_MIN = 256, + /** Space id of _schema. */ + BOX_SCHEMA_ID = 272, + /** Space id of _space. */ + BOX_SPACE_ID = 280, + /** Space id of _vspace view. */ + BOX_VSPACE_ID = 281, + /** Space id of _index. */ + BOX_INDEX_ID = 288, + /** Space id of _vindex view. */ + BOX_VINDEX_ID = 289, + /** Space id of _func. */ + BOX_FUNC_ID = 296, + /** Space id of _vfunc view. */ + BOX_VFUNC_ID = 297, + /** Space id of _user. */ + BOX_USER_ID = 304, + /** Space id of _vuser view. */ + BOX_VUSER_ID = 305, + /** Space id of _priv. */ + BOX_PRIV_ID = 312, + /** Space id of _vpriv view. */ + BOX_VPRIV_ID = 313, + /** Space id of _cluster. */ + BOX_CLUSTER_ID = 320, + /** Space id of _truncate. */ + BOX_TRUNCATE_ID = 330, + /** End of the reserved range of system spaces. */ + BOX_SYSTEM_ID_MAX = 511, + BOX_ID_NIL = 2147483647 +}; +/** \endcond public */ + +/** _space fields. */ +enum { + BOX_SPACE_FIELD_ID = 0, + BOX_SPACE_FIELD_UID = 1, + BOX_SPACE_FIELD_NAME = 2, + BOX_SPACE_FIELD_ENGINE = 3, + BOX_SPACE_FIELD_FIELD_COUNT = 4, + BOX_SPACE_FIELD_OPTS = 5, +}; + +/** _index fields. */ +enum { + BOX_INDEX_FIELD_SPACE_ID = 0, + BOX_INDEX_FIELD_ID = 1, + BOX_INDEX_FIELD_NAME = 2, + BOX_INDEX_FIELD_TYPE = 3, + BOX_INDEX_FIELD_OPTS = 4, + BOX_INDEX_FIELD_IS_UNIQUE_165 = 4, + BOX_INDEX_FIELD_PARTS = 5, + BOX_INDEX_FIELD_PART_COUNT_165 = 5, + BOX_INDEX_FIELD_PARTS_165 = 6, +}; + +/** _user fields. */ +enum { + BOX_USER_FIELD_ID = 0, + BOX_USER_FIELD_UID = 1, + BOX_USER_FIELD_NAME = 2, + BOX_USER_FIELD_TYPE = 3, + BOX_USER_FIELD_AUTH_MECH_LIST = 4, +}; + +/** _priv fields. */ +enum { + BOX_PRIV_FIELD_ID = 0, + BOX_PRIV_FIELD_UID = 1, + BOX_PRIV_FIELD_OBJECT_TYPE = 2, + BOX_PRIV_FIELD_OBJECT_ID = 3, + BOX_PRIV_FIELD_ACCESS = 4, +}; + +/** _func fields. */ +enum { + BOX_FUNC_FIELD_ID = 0, + BOX_FUNC_FIELD_UID = 1, + BOX_FUNC_FIELD_NAME = 2, + BOX_FUNC_FIELD_SETUID = 3, + BOX_FUNC_FIELD_LANGUAGE = 4, +}; + +/** _schema fields. */ +enum { + BOX_SCHEMA_FIELD_KEY = 0, +}; + +/** _cluster fields. */ +enum { + BOX_CLUSTER_FIELD_ID = 0, + BOX_CLUSTER_FIELD_UUID = 1, +}; + +/** _truncate fields. */ +enum { + BOX_TRUNCATE_FIELD_SPACE_ID = 0, + BOX_TRUNCATE_FIELD_COUNT = 1, +}; + +/* + * Different objects which can be subject to access + * control. + * + * Use 0 for unknown to use the same index consistently + * even when there are more object types in the future. + */ +enum schema_object_type { + SC_UNKNOWN = 0, SC_UNIVERSE = 1, SC_SPACE = 2, SC_FUNCTION = 3, + SC_USER = 4, SC_ROLE = 5 +}; + +enum schema_object_type +schema_object_type(const char *name); + +const char * +schema_object_name(enum schema_object_type type); + +/** + * Check object identifier for invalid symbols. + * The function checks \a str for matching [a-zA-Z_][a-zA-Z0-9_]* expression. + * Result is locale-dependent. + */ +bool +identifier_is_valid(const char *str); + +#if defined(__cplusplus) +} /* extern "C" */ + +#include "error.h" + +/** + * Throw an error if identifier is not valid. + */ +static inline void +identifier_check_xc(const char *str) +{ + if (! identifier_is_valid(str)) + tnt_raise(ClientError, ER_IDENTIFIER, str); +} + +#endif /* defined(__cplusplus) */ + +#endif /* TARANTOOL_BOX_SCHEMA_DEF_H_INCLUDED */ diff --git a/src/box/space.cc b/src/box/space.cc index e89afb32797d8e8418bc0890da12cabccae5025b..31fe296e9462d9d6c5b5ded3be32c965fa4b94da 100644 --- a/src/box/space.cc +++ b/src/box/space.cc @@ -85,7 +85,7 @@ space_new(struct space_def *def, struct rlist *key_list) struct index_def *index_def; MAYBE_UNUSED struct index_def *pk = rlist_empty(key_list) ? NULL : rlist_first_entry(key_list, struct index_def, link); - def = space_def_dup(def); + def = space_def_dup_xc(def); rlist_foreach_entry(index_def, key_list, link) { index_count++; index_id_max = MAX(index_id_max, index_def->iid); diff --git a/src/box/space.h b/src/box/space.h index b7b9fc63c8038d0762dd5bc0998159d8dfad9b8d..15e938d7a8dae744c72723fb85d658009b9521d1 100644 --- a/src/box/space.h +++ b/src/box/space.h @@ -30,8 +30,10 @@ * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -#include "key_def.h" +#include "user_def.h" +#include "space_def.h" #include "small/rlist.h" +#include "error.h" #if defined(__cplusplus) extern "C" { diff --git a/src/box/space_def.c b/src/box/space_def.c new file mode 100644 index 0000000000000000000000000000000000000000..56583f1d385bd929082b07c3561ba52a30d390e0 --- /dev/null +++ b/src/box/space_def.c @@ -0,0 +1,80 @@ +/* + * Copyright 2010-2016, Tarantool AUTHORS, please see AUTHORS file. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * 1. Redistributions of source code must retain the above + * copyright notice, this list of conditions and the + * following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY <COPYRIGHT HOLDER> ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * <COPYRIGHT HOLDER> OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF + * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "space_def.h" +#include "diag.h" + +const struct space_opts space_opts_default = { + /* .temporary = */ false, +}; + +const struct opt_def space_opts_reg[] = { + OPT_DEF("temporary", OPT_BOOL, struct space_opts, temporary), + { NULL, opt_type_MAX, 0, 0 } +}; + +struct space_def * +space_def_dup(const struct space_def *src) +{ + size_t size = space_def_sizeof(strlen(src->name)); + struct space_def *ret = (struct space_def *) malloc(size); + if (ret == NULL) { + diag_set(OutOfMemory, size, "malloc", "ret"); + return NULL; + } + memcpy(ret, src, size); + return ret; +} + +struct space_def * +space_def_new(uint32_t id, uint32_t uid, uint32_t exact_field_count, + const char *name, uint32_t name_len, + const char *engine_name, uint32_t engine_len, + const struct space_opts *opts) +{ + size_t size = space_def_sizeof(name_len); + struct space_def *def = (struct space_def *) malloc(size); + if (def == NULL) { + diag_set(OutOfMemory, size, "malloc", "def"); + return NULL; + } + assert(name_len <= BOX_NAME_MAX); + assert(engine_len <= ENGINE_NAME_MAX); + def->id = id; + def->uid = uid; + def->exact_field_count = exact_field_count; + memcpy(def->name, name, name_len); + def->name[name_len] = 0; + memcpy(def->engine_name, engine_name, engine_len); + def->engine_name[engine_len] = 0; + def->opts = *opts; + return def; +} diff --git a/src/box/space_def.h b/src/box/space_def.h new file mode 100644 index 0000000000000000000000000000000000000000..f0eea5ca9427d66dab67017f58e141360c75a263 --- /dev/null +++ b/src/box/space_def.h @@ -0,0 +1,153 @@ +#ifndef TARANTOOL_BOX_SPACE_DEF_H_INCLUDED +#define TARANTOOL_BOX_SPACE_DEF_H_INCLUDED +/* + * Copyright 2010-2016, Tarantool AUTHORS, please see AUTHORS file. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * 1. Redistributions of source code must retain the above + * copyright notice, this list of conditions and the + * following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY <COPYRIGHT HOLDER> ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * <COPYRIGHT HOLDER> OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF + * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +#include "trivia/util.h" +#include "opt_def.h" +#include "schema_def.h" +#include <stdbool.h> + +#if defined(__cplusplus) +extern "C" { +#endif /* defined(__cplusplus) */ + +/** Space options */ +struct space_opts { + /** + * The space is a temporary: + * - it is empty at server start + * - changes are not written to WAL + * - changes are not part of a snapshot + */ + bool temporary; +}; + +extern const struct space_opts space_opts_default; +extern const struct opt_def space_opts_reg[]; + +/** Space metadata. */ +struct space_def { + /** Space id. */ + uint32_t id; + /** User id of the creator of the space */ + uint32_t uid; + /** + * If not set (is 0), any tuple in the + * space can have any number of fields. + * If set, each tuple + * must have exactly this many fields. + */ + uint32_t exact_field_count; + char engine_name[ENGINE_NAME_MAX + 1]; + struct space_opts opts; + char name[0]; +}; + +/** + * Size of the space_def, calculated using its name. + * @param name_len Length of the space name. + * @retval Size in bytes. + */ +static inline size_t +space_def_sizeof(uint32_t name_len) +{ + return sizeof(struct space_def) + name_len + 1; +} + +/** + * Delete the space_def object. + * @param def Def to delete. + */ +static inline void +space_def_delete(struct space_def *def) +{ + free(def); +} + +/** + * Duplicate space_def object. + * @param src Def to duplicate. + * @retval Copy of the @src. + */ +struct space_def * +space_def_dup(const struct space_def *src); + +/** + * Create a new space definition. + * @param id Space identifier. + * @param uid Owner identifier. + * @param exact_field_count Space tuples field count. + * 0 for any count. + * @param name Space name. + * @param name_len Length of the @name. + * @param engine_name Engine name. + * @param engine_len Length of the @engine. + * @param opts Space options. + * + * @retval Space definition. + */ +struct space_def * +space_def_new(uint32_t id, uint32_t uid, uint32_t exact_field_count, + const char *name, uint32_t name_len, + const char *engine_name, uint32_t engine_len, + const struct space_opts *opts); + +#if defined(__cplusplus) +} /* extern "C" */ + +#include "diag.h" + +static inline struct space_def * +space_def_dup_xc(const struct space_def *src) +{ + struct space_def *ret = space_def_dup(src); + if (ret == NULL) + diag_raise(); + return ret; +} + +static inline struct space_def * +space_def_new_xc(uint32_t id, uint32_t uid, uint32_t exact_field_count, + const char *name, uint32_t name_len, + const char *engine_name, uint32_t engine_len, + const struct space_opts *opts) +{ + struct space_def *ret = space_def_new(id, uid, exact_field_count, name, + name_len, engine_name, engine_len, + opts); + if (ret == NULL) + diag_raise(); + return ret; +} + +#endif /* __cplusplus */ + +#endif /* TARANTOOL_BOX_SPACE_DEF_H_INCLUDED */ diff --git a/src/box/user_def.h b/src/box/user_def.h index 67f1d68e35c7ef863d73532ce73f3e5eb29e4582..602ac512faf8c330dbaf9f1ecce198393809ae95 100644 --- a/src/box/user_def.h +++ b/src/box/user_def.h @@ -30,13 +30,33 @@ * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -#include "key_def.h" /* for SCHEMA_OBJECT_TYPE */ +#include "schema_def.h" /* for SCHEMA_OBJECT_TYPE */ #include "scramble.h" /* for SCRAMBLE_SIZE */ +#define RB_COMPACT 1 +#include "small/rb.h" #if defined(__cplusplus) extern "C" { #endif /* defined(__cplusplus) */ +/** + * Effective session user. A cache of user data + * and access stored in session and fiber local storage. + * Differs from the authenticated user when executing + * setuid functions. + */ +struct credentials { + /** A look up key to quickly find session user. */ + uint8_t auth_token; + /** + * Cached global grants, to avoid an extra look up + * when checking global grants. + */ + uint8_t universal_access; + /** User id of the authenticated user. */ + uint32_t uid; +}; + enum { /* SELECT */ PRIV_R = 1, @@ -48,10 +68,51 @@ enum { PRIV_ALL = PRIV_R + PRIV_W + PRIV_X }; +/** + * Definition of a privilege + */ +struct priv_def { + /** Who grants the privilege. */ + uint32_t grantor_id; + /** Whom the privilege is granted. */ + uint32_t grantee_id; + /* Object id - is only defined for object type */ + uint32_t object_id; + /* Object type - function, space, universe */ + enum schema_object_type object_type; + /** + * What is being granted, has been granted, or is being + * revoked. + */ + uint8_t access; + /** To maintain a set of effective privileges. */ + rb_node(struct priv_def) link; +}; + /* Privilege name for error messages */ const char * priv_name(uint8_t access); +/** + * Encapsulates privileges of a user on an object. + * I.e. "space" object has an instance of this + * structure for each user. + */ +struct access { + /** + * Granted access has been given to a user explicitly + * via some form of a grant. + */ + uint8_t granted; + /** + * Effective access is a sum of granted access and + * all privileges inherited by a user on this object + * via some role. Since roles may be granted to other + * roles, this may include indirect grants. + */ + uint8_t effective; +}; + /** * A cache entry for an existing user. Entries for all existing * users are always present in the cache. The entry is maintained diff --git a/src/box/vy_cache.c b/src/box/vy_cache.c index b68e6b674350b53a9cb30a77e18014d7befdeeba..c1bba5fcd7d8ed01f4d27f6bb5a679f226599aa1 100644 --- a/src/box/vy_cache.c +++ b/src/box/vy_cache.c @@ -30,6 +30,7 @@ */ #include "vy_cache.h" #include "diag.h" +#include "schema_def.h" #ifndef CT_ASSERT_G #define CT_ASSERT_G(e) typedef char CONCAT(__ct_assert_, __LINE__)[(e) ? 1 :-1] diff --git a/src/box/vy_index.c b/src/box/vy_index.c index 9e8bd1ad3f91615ccc280a26d361183404d112da..b9472e520b62901a690914627d02c0243d736f1b 100644 --- a/src/box/vy_index.c +++ b/src/box/vy_index.c @@ -30,28 +30,20 @@ */ #include "vy_index.h" -#include <assert.h> +#include "trivia/util.h" #include <stdbool.h> #include <stddef.h> -#include <stdint.h> -#include <stdio.h> -#include <stdlib.h> - #include <sys/stat.h> #include <sys/types.h> -#include <small/rlist.h> - #include "assoc.h" #include "diag.h" #include "errcode.h" #include "histogram.h" -#include "key_def.h" +#include "index_def.h" #include "say.h" #include "schema.h" -#include "trivia/util.h" #include "tuple.h" -#include "tuple_format.h" #include "vy_log.h" #include "vy_mem.h" #include "vy_range.h" diff --git a/src/box/vy_index.h b/src/box/vy_index.h index 4a85393b70fb5a5d83efb5ff00d5319d3fd36548..f2b7c3f6c7a1a0ee301f4e4a69ba8b2aaca5e5c3 100644 --- a/src/box/vy_index.h +++ b/src/box/vy_index.h @@ -37,7 +37,7 @@ #include <small/rlist.h> -#include "key_def.h" +#include "index_def.h" #define HEAP_FORWARD_DECLARATION #include "salad/heap.h" #include "vy_cache.h" diff --git a/src/box/vy_run.h b/src/box/vy_run.h index 772b69ab2f885ddebd68ffb95355147c737dd588..dad1092189541d5ad78aa88c81c812fa78fc9264 100644 --- a/src/box/vy_run.h +++ b/src/box/vy_run.h @@ -39,6 +39,7 @@ #include "vy_stmt.h" /* for comparators */ #include "vy_stmt_iterator.h" /* struct vy_stmt_iterator */ #include "vy_stat.h" +#include "index_def.h" #include "small/mempool.h" #include "salad/bloom.h" diff --git a/test/unit/CMakeLists.txt b/test/unit/CMakeLists.txt index 8845258aab3979e808c4c7c52183c6ec0be86805..e30449ba47b9152241d4c2278fee635d4c22182b 100644 --- a/test/unit/CMakeLists.txt +++ b/test/unit/CMakeLists.txt @@ -157,6 +157,8 @@ add_executable(vy_point_iterator.test ${PROJECT_SOURCE_DIR}/src/box/vy_upsert.c ${PROJECT_SOURCE_DIR}/src/box/vy_index.c ${PROJECT_SOURCE_DIR}/src/box/vy_cache.c + ${PROJECT_SOURCE_DIR}/src/box/index_def.c + ${PROJECT_SOURCE_DIR}/src/box/schema_def.c ) target_link_libraries(vy_point_iterator.test core tuple xrow xlog unit)