[tarantool-patches] Re: [PATCH v3 2/4] collation: split collation into core and box objects
Vladislav Shpilevoy
v.shpilevoy at tarantool.org
Thu May 17 22:23:27 MSK 2018
Hello. Below the new patch is presented. Here box_coll is
renamed to coll_id, and stack buffers are removed from coll.c.
---
collation: split collation into coll and id objects
In the issue #3290 the important problem appeared - Tarantool can
not create completely internal collations with no ID, name,
owner. Just for internal usage.
Original struct coll can not be used for this since
* it has fields that are not needed in internals;
* collation name is public thing, and the collation cache uses
it, so it would be necessary to forbid to a user usage of some
system names;
* when multiple collations has the same comparator and only their
names/owners/IDs are different, the separate UCollator objects
are created, but it would be good to be able to reference a
single one.
This patch renames coll to coll_id, coll_def to call_id_def and
introduces coll - pure collation object with no any user defined
things.
Needed for #3290.
---
src/CMakeLists.txt | 2 +
src/box/CMakeLists.txt | 6 +-
src/box/alter.cc | 105 ++++++++++----------
src/box/coll_id.c | 65 +++++++++++++
src/box/coll_id.h | 77 +++++++++++++++
src/box/{coll_cache.c => coll_id_cache.c} | 62 +++++-------
src/box/{coll_cache.h => coll_id_cache.h} | 27 +++---
src/box/{coll_def.c => coll_id_def.c} | 34 +------
src/box/coll_id_def.h | 54 +++++++++++
src/box/error.cc | 2 +
src/box/key_def.cc | 23 +++--
src/box/key_def.h | 7 +-
src/box/lua/space.cc | 8 +-
src/box/schema.cc | 8 +-
src/box/tuple.c | 6 +-
src/box/tuple_compare.cc | 5 +-
src/box/tuple_hash.cc | 1 -
src/{box => }/coll.c | 153 +++++++++++-------------------
src/{box => }/coll.h | 37 +++-----
src/coll_def.c | 63 ++++++++++++
src/{box => }/coll_def.h | 35 ++-----
src/diag.h | 2 +
src/exception.cc | 24 +++++
src/exception.h | 9 ++
test/unit/coll.cpp | 8 +-
25 files changed, 505 insertions(+), 318 deletions(-)
create mode 100644 src/box/coll_id.c
create mode 100644 src/box/coll_id.h
rename src/box/{coll_cache.c => coll_id_cache.c} (56%)
rename src/box/{coll_cache.h => coll_id_cache.h} (78%)
rename src/box/{coll_def.c => coll_id_def.c} (86%)
create mode 100644 src/box/coll_id_def.h
rename src/{box => }/coll.c (63%)
rename src/{box => }/coll.h (74%)
create mode 100644 src/coll_def.c
rename src/{box => }/coll_def.h (82%)
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 8ab09e968..5bf17614b 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -94,6 +94,8 @@ set (core_sources
random.c
trigger.cc
http_parser.c
+ coll.c
+ coll_def.c
)
if (TARGET_OS_NETBSD)
diff --git a/src/box/CMakeLists.txt b/src/box/CMakeLists.txt
index 866b7b75c..e84e791df 100644
--- a/src/box/CMakeLists.txt
+++ b/src/box/CMakeLists.txt
@@ -41,9 +41,9 @@ add_library(tuple STATIC
tuple_bloom.c
tuple_dictionary.c
key_def.cc
- coll_def.c
- coll.c
- coll_cache.c
+ coll_id_def.c
+ coll_id.c
+ coll_id_cache.c
field_def.c
opt_def.c
)
diff --git a/src/box/alter.cc b/src/box/alter.cc
index 8766c8171..7858af989 100644
--- a/src/box/alter.cc
+++ b/src/box/alter.cc
@@ -34,7 +34,8 @@
#include "space.h"
#include "index.h"
#include "func.h"
-#include "coll_cache.h"
+#include "coll_id_cache.h"
+#include "coll_id_def.h"
#include "txn.h"
#include "tuple.h"
#include "fiber.h" /* for gc_pool */
@@ -2284,9 +2285,9 @@ on_replace_dd_func(struct trigger * /* trigger */, void *event)
}
}
-/** Create a collation definition from tuple. */
+/** Create a collation identifier definition from tuple. */
void
-coll_def_new_from_tuple(const struct tuple *tuple, struct coll_def *def)
+coll_id_def_new_from_tuple(const struct tuple *tuple, struct coll_id_def *def)
{
memset(def, 0, sizeof(*def));
uint32_t name_len, locale_len, type_len;
@@ -2294,15 +2295,16 @@ coll_def_new_from_tuple(const struct tuple *tuple, struct coll_def *def)
def->name = tuple_field_str_xc(tuple, BOX_COLLATION_FIELD_NAME, &name_len);
def->name_len = name_len;
def->owner_id = tuple_field_u32_xc(tuple, BOX_COLLATION_FIELD_UID);
+ struct coll_def *base = &def->base;
const char *type = tuple_field_str_xc(tuple, BOX_COLLATION_FIELD_TYPE,
&type_len);
- def->type = STRN2ENUM(coll_type, type, type_len);
- if (def->type == coll_type_MAX)
+ base->type = STRN2ENUM(coll_type, type, type_len);
+ if (base->type == coll_type_MAX)
tnt_raise(ClientError, ER_CANT_CREATE_COLLATION,
"unknown collation type");
- def->locale = tuple_field_str_xc(tuple, BOX_COLLATION_FIELD_LOCALE,
- &locale_len);
- def->locale_len = locale_len;
+ base->locale = tuple_field_str_xc(tuple, BOX_COLLATION_FIELD_LOCALE,
+ &locale_len);
+ base->locale_len = locale_len;
const char *options =
tuple_field_with_type_xc(tuple, BOX_COLLATION_FIELD_OPTIONS,
MP_MAP);
@@ -2315,53 +2317,53 @@ coll_def_new_from_tuple(const struct tuple *tuple, struct coll_def *def)
"collation locale is too long");
/* Locale is an optional argument and can be NULL. */
if (locale_len > 0)
- identifier_check_xc(def->locale, locale_len);
+ identifier_check_xc(base->locale, locale_len);
identifier_check_xc(def->name, name_len);
- assert(def->type == COLL_TYPE_ICU); /* no more defined now */
- if (opts_decode(&def->icu, coll_icu_opts_reg, &options,
+ assert(base->type == COLL_TYPE_ICU);
+ if (opts_decode(&base->icu, coll_icu_opts_reg, &options,
ER_WRONG_COLLATION_OPTIONS,
BOX_COLLATION_FIELD_OPTIONS, NULL) != 0)
diag_raise();
- if (def->icu.french_collation == coll_icu_on_off_MAX) {
+ if (base->icu.french_collation == coll_icu_on_off_MAX) {
tnt_raise(ClientError, ER_CANT_CREATE_COLLATION,
"ICU wrong french_collation option setting, "
"expected ON | OFF");
}
- if (def->icu.alternate_handling == coll_icu_alternate_handling_MAX) {
+ if (base->icu.alternate_handling == coll_icu_alternate_handling_MAX) {
tnt_raise(ClientError, ER_CANT_CREATE_COLLATION,
"ICU wrong alternate_handling option setting, "
"expected NON_IGNORABLE | SHIFTED");
}
- if (def->icu.case_first == coll_icu_case_first_MAX) {
+ if (base->icu.case_first == coll_icu_case_first_MAX) {
tnt_raise(ClientError, ER_CANT_CREATE_COLLATION,
"ICU wrong case_first option setting, "
"expected OFF | UPPER_FIRST | LOWER_FIRST");
}
- if (def->icu.case_level == coll_icu_on_off_MAX) {
+ if (base->icu.case_level == coll_icu_on_off_MAX) {
tnt_raise(ClientError, ER_CANT_CREATE_COLLATION,
"ICU wrong case_level option setting, "
"expected ON | OFF");
}
- if (def->icu.normalization_mode == coll_icu_on_off_MAX) {
+ if (base->icu.normalization_mode == coll_icu_on_off_MAX) {
tnt_raise(ClientError, ER_CANT_CREATE_COLLATION,
"ICU wrong normalization_mode option setting, "
"expected ON | OFF");
}
- if (def->icu.strength == coll_icu_strength_MAX) {
+ if (base->icu.strength == coll_icu_strength_MAX) {
tnt_raise(ClientError, ER_CANT_CREATE_COLLATION,
"ICU wrong strength option setting, "
"expected PRIMARY | SECONDARY | "
"TERTIARY | QUATERNARY | IDENTICAL");
}
- if (def->icu.numeric_collation == coll_icu_on_off_MAX) {
+ if (base->icu.numeric_collation == coll_icu_on_off_MAX) {
tnt_raise(ClientError, ER_CANT_CREATE_COLLATION,
"ICU wrong numeric_collation option setting, "
"expected ON | OFF");
@@ -2373,36 +2375,36 @@ coll_def_new_from_tuple(const struct tuple *tuple, struct coll_def *def)
* A change is only INSERT or DELETE, UPDATE is not supported.
*/
static void
-coll_cache_rollback(struct trigger *trigger, void *event)
+coll_id_cache_rollback(struct trigger *trigger, void *event)
{
- struct coll *coll = (struct coll *) trigger->data;
+ struct coll_id *coll_id = (struct coll_id *) trigger->data;
struct txn_stmt *stmt = txn_last_stmt((struct txn*) event);
if (stmt->new_tuple == NULL) {
- /* Rollback DELETE: put the collation back. */
+ /* DELETE: put the collation identifier back. */
assert(stmt->old_tuple != NULL);
- struct coll *replaced;
- if (coll_cache_replace(coll, &replaced) != 0) {
+ struct coll_id *replaced_id;
+ if (coll_id_cache_replace(coll_id, &replaced_id) != 0) {
panic("Out of memory on insertion into collation "\
"cache");
}
- assert(replaced == NULL);
+ assert(replaced_id == NULL);
} else {
- /* INSERT: remove and free the new collation */
+ /* INSERT: delete the new collation identifier. */
assert(stmt->old_tuple == NULL);
- coll_cache_delete(coll);
- coll_unref(coll);
+ coll_id_cache_delete(coll_id);
+ coll_id_delete(coll_id);
}
}
-/** Dereference a deleted collation on commit. */
+/** Free a deleted collation identifier on commit. */
static void
-coll_cache_commit(struct trigger *trigger, void *event)
+coll_id_cache_commit(struct trigger *trigger, void *event)
{
(void) event;
- struct coll *coll = (struct coll *) trigger->data;
- coll_unref(coll);
+ struct coll_id *coll_id = (struct coll_id *) trigger->data;
+ coll_id_delete(coll_id);
}
/**
@@ -2418,44 +2420,47 @@ on_replace_dd_collation(struct trigger * /* trigger */, void *event)
struct tuple *new_tuple = stmt->new_tuple;
txn_check_singlestatement_xc(txn, "Space _collation");
struct trigger *on_rollback =
- txn_alter_trigger_new(coll_cache_rollback, NULL);
+ txn_alter_trigger_new(coll_id_cache_rollback, NULL);
struct trigger *on_commit =
- txn_alter_trigger_new(coll_cache_commit, NULL);
+ txn_alter_trigger_new(coll_id_cache_commit, NULL);
if (new_tuple == NULL && old_tuple != NULL) {
/* DELETE */
- /* TODO: Check that no index uses the collation */
+ /*
+ * TODO: Check that no index uses the collation
+ * identifier.
+ */
int32_t old_id = tuple_field_u32_xc(old_tuple,
BOX_COLLATION_FIELD_ID);
- struct coll *old_coll = coll_by_id(old_id);
- assert(old_coll != NULL);
- access_check_ddl(old_coll->name, old_coll->owner_id,
+ struct coll_id *old_coll_id = coll_by_id(old_id);
+ assert(old_coll_id != NULL);
+ access_check_ddl(old_coll_id->name, old_coll_id->owner_id,
SC_COLLATION, PRIV_D, false);
/*
* Set on_commit/on_rollback triggers after
* deletion from the cache to make trigger logic
- * simple..
+ * simple.
*/
- coll_cache_delete(old_coll);
- on_rollback->data = old_coll;
- on_commit->data = old_coll;
+ coll_id_cache_delete(old_coll_id);
+ on_rollback->data = old_coll_id;
+ on_commit->data = old_coll_id;
txn_on_rollback(txn, on_rollback);
txn_on_commit(txn, on_commit);
} else if (new_tuple != NULL && old_tuple == NULL) {
/* INSERT */
- struct coll_def new_def;
- coll_def_new_from_tuple(new_tuple, &new_def);
+ struct coll_id_def new_def;
+ coll_id_def_new_from_tuple(new_tuple, &new_def);
access_check_ddl(new_def.name, new_def.owner_id, SC_COLLATION,
PRIV_C, false);
- struct coll *new_coll = coll_new(&new_def);
- if (new_coll == NULL)
+ struct coll_id *new_coll_id = coll_id_new(&new_def);
+ if (new_coll_id == NULL)
diag_raise();
- struct coll *replaced;
- if (coll_cache_replace(new_coll, &replaced) != 0) {
- coll_unref(new_coll);
+ struct coll_id *replaced_id;
+ if (coll_id_cache_replace(new_coll_id, &replaced_id) != 0) {
+ coll_id_delete(new_coll_id);
diag_raise();
}
- assert(replaced == NULL);
- on_rollback->data = new_coll;
+ assert(replaced_id == NULL);
+ on_rollback->data = new_coll_id;
txn_on_rollback(txn, on_rollback);
} else {
/* UPDATE */
diff --git a/src/box/coll_id.c b/src/box/coll_id.c
new file mode 100644
index 000000000..2d5f8a09a
--- /dev/null
+++ b/src/box/coll_id.c
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2010-2017, 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 AUTHORS ``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
+ * AUTHORS 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 "coll_id.h"
+#include "coll_id_def.h"
+#include "coll.h"
+#include "error.h"
+#include "diag.h"
+
+struct coll_id *
+coll_id_new(const struct coll_id_def *def)
+{
+ assert(def->base.type == COLL_TYPE_ICU);
+ size_t total_len = sizeof(struct coll_id) + def->name_len + 1;
+ struct coll_id *coll_id = (struct coll_id *) malloc(total_len);
+ if (coll_id == NULL) {
+ diag_set(OutOfMemory, total_len, "malloc", "coll_id");
+ return NULL;
+ }
+ coll_id->coll = coll_new(&def->base);
+ if (coll_id->coll == NULL) {
+ free(coll_id);
+ return NULL;
+ }
+ coll_id->id = def->id;
+ coll_id->owner_id = def->owner_id;
+ coll_id->name_len = def->name_len;
+ memcpy(coll_id->name, def->name, def->name_len);
+ coll_id->name[coll_id->name_len] = 0;
+ return coll_id;
+}
+
+void
+coll_id_delete(struct coll_id *coll_id)
+{
+ coll_unref(coll_id->coll);
+ free(coll_id);
+}
diff --git a/src/box/coll_id.h b/src/box/coll_id.h
new file mode 100644
index 000000000..1b67a3f86
--- /dev/null
+++ b/src/box/coll_id.h
@@ -0,0 +1,77 @@
+#ifndef TARANTOOL_BOX_COLL_ID_H_INCLUDED
+#define TARANTOOL_BOX_COLL_ID_H_INCLUDED
+/*
+ * Copyright 2010-2017, 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 AUTHORS ``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
+ * AUTHORS 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 <stddef.h>
+#include <stdint.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif /* defined(__cplusplus) */
+
+struct coll_id_def;
+struct coll;
+
+/**
+ * A collation identifier. It gives a name, owner and unique
+ * identifier to a base collation. Multiple coll_id can reference
+ * the same collation if their functional parts match.
+ */
+struct coll_id {
+ /** Personal ID */
+ uint32_t id;
+ /** Owner ID */
+ uint32_t owner_id;
+ /** Collation object. */
+ struct coll *coll;
+ /** Collation name. */
+ size_t name_len;
+ char name[0];
+};
+
+/**
+ * Create a collation identifier by definition.
+ * @param def Collation definition.
+ * @retval NULL Illegal parameters or memory error.
+ * @retval not NULL Collation.
+ */
+struct coll_id *
+coll_id_new(const struct coll_id_def *def);
+
+/** Delete collation identifier, unref the basic collation. */
+void
+coll_id_delete(struct coll_id *coll);
+
+#if defined(__cplusplus)
+} /* extern "C" */
+#endif /* defined(__cplusplus) */
+
+#endif /* TARANTOOL_BOX_COLL_ID_H_INCLUDED */
diff --git a/src/box/coll_cache.c b/src/box/coll_id_cache.c
similarity index 56%
rename from src/box/coll_cache.c
rename to src/box/coll_id_cache.c
index b7eb3edb9..122863937 100644
--- a/src/box/coll_cache.c
+++ b/src/box/coll_id_cache.c
@@ -28,75 +28,63 @@
* THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
-#include "coll_cache.h"
+#include "coll_id_cache.h"
+#include "coll_id.h"
#include "diag.h"
#include "assoc.h"
/** mhash table (id -> collation) */
-static struct mh_i32ptr_t *coll_cache_id = NULL;
+static struct mh_i32ptr_t *coll_id_cache = NULL;
-/** Create global hash tables if necessary. */
int
-coll_cache_init()
+coll_id_cache_init()
{
- coll_cache_id = mh_i32ptr_new();
- if (coll_cache_id == NULL) {
- diag_set(OutOfMemory, sizeof(*coll_cache_id), "malloc",
- "coll_cache_id");
+ coll_id_cache = mh_i32ptr_new();
+ if (coll_id_cache == NULL) {
+ diag_set(OutOfMemory, sizeof(*coll_id_cache), "malloc",
+ "coll_id_cache");
return -1;
}
return 0;
}
-/** Delete global hash tables. */
void
-coll_cache_destroy()
+coll_id_cache_destroy()
{
- mh_i32ptr_delete(coll_cache_id);
+ mh_i32ptr_delete(coll_id_cache);
}
-/**
- * Insert or replace a collation into collation cache.
- * @param coll - collation to insert/replace.
- * @return - NULL if inserted, replaced collation if replaced.
- */
int
-coll_cache_replace(struct coll *coll, struct coll **replaced)
+coll_id_cache_replace(struct coll_id *coll_id, struct coll_id **replaced_id)
{
- const struct mh_i32ptr_node_t id_node = {coll->id, coll};
+ const struct mh_i32ptr_node_t id_node = {coll_id->id, coll_id};
struct mh_i32ptr_node_t repl_id_node = {0, NULL};
struct mh_i32ptr_node_t *prepl_id_node = &repl_id_node;
- if (mh_i32ptr_put(coll_cache_id, &id_node, &prepl_id_node, NULL) ==
- mh_end(coll_cache_id)) {
- diag_set(OutOfMemory, sizeof(id_node), "malloc", "coll_cache_id");
+ if (mh_i32ptr_put(coll_id_cache, &id_node, &prepl_id_node, NULL) ==
+ mh_end(coll_id_cache)) {
+ diag_set(OutOfMemory, sizeof(id_node), "malloc",
+ "coll_id_cache");
return -1;
}
assert(repl_id_node.val == NULL);
- *replaced = repl_id_node.val;
+ *replaced_id = repl_id_node.val;
return 0;
}
-/**
- * Delete a collation from collation cache.
- * @param coll - collation to delete.
- */
void
-coll_cache_delete(const struct coll *coll)
+coll_id_cache_delete(const struct coll_id *coll_id)
{
- mh_int_t i = mh_i32ptr_find(coll_cache_id, coll->id, NULL);
- if (i == mh_end(coll_cache_id))
+ mh_int_t i = mh_i32ptr_find(coll_id_cache, coll_id->id, NULL);
+ if (i == mh_end(coll_id_cache))
return;
- mh_i32ptr_del(coll_cache_id, i, NULL);
+ mh_i32ptr_del(coll_id_cache, i, NULL);
}
-/**
- * Find a collation object by its id.
- */
-struct coll *
+struct coll_id *
coll_by_id(uint32_t id)
{
- mh_int_t pos = mh_i32ptr_find(coll_cache_id, id, NULL);
- if (pos == mh_end(coll_cache_id))
+ mh_int_t pos = mh_i32ptr_find(coll_id_cache, id, NULL);
+ if (pos == mh_end(coll_id_cache))
return NULL;
- return mh_i32ptr_node(coll_cache_id, pos)->val;
+ return mh_i32ptr_node(coll_id_cache, pos)->val;
}
diff --git a/src/box/coll_cache.h b/src/box/coll_id_cache.h
similarity index 78%
rename from src/box/coll_cache.h
rename to src/box/coll_id_cache.h
index 418de4e35..4bbbc85de 100644
--- a/src/box/coll_cache.h
+++ b/src/box/coll_id_cache.h
@@ -1,5 +1,5 @@
-#ifndef TARANTOOL_BOX_COLL_CACHE_H_INCLUDED
-#define TARANTOOL_BOX_COLL_CACHE_H_INCLUDED
+#ifndef TARANTOOL_BOX_COLL_ID_CACHE_H_INCLUDED
+#define TARANTOOL_BOX_COLL_ID_CACHE_H_INCLUDED
/*
* Copyright 2010-2016, Tarantool AUTHORS, please see AUTHORS file.
*
@@ -30,48 +30,49 @@
* THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
-
-#include "coll.h"
+#include <stdint.h>
#if defined(__cplusplus)
extern "C" {
#endif /* defined(__cplusplus) */
+struct coll_id;
+
/**
* Create global hash tables.
* @return - 0 on success, -1 on memory error.
*/
int
-coll_cache_init();
+coll_id_cache_init();
/** Delete global hash tables. */
void
-coll_cache_destroy();
+coll_id_cache_destroy();
/**
* Insert or replace a collation into collation cache.
- * @param coll - collation to insert/replace.
- * @param replaced - collation that was replaced.
+ * @param coll_id Collation to insert/replace.
+ * @param Replaced_id Collation that was replaced.
* @return - 0 on success, -1 on memory error.
*/
int
-coll_cache_replace(struct coll *coll, struct coll **replaced);
+coll_id_cache_replace(struct coll_id *coll_id, struct coll_id **replaced_id);
/**
* Delete a collation from collation cache.
- * @param coll - collation to delete.
+ * @param coll_id Collation to delete.
*/
void
-coll_cache_delete(const struct coll *coll);
+coll_id_cache_delete(const struct coll_id *coll_id);
/**
* Find a collation object by its id.
*/
-struct coll *
+struct coll_id *
coll_by_id(uint32_t id);
#if defined(__cplusplus)
} /* extern "C" */
#endif /* defined(__cplusplus) */
-#endif /* TARANTOOL_BOX_COLL_CACHE_H_INCLUDED */
+#endif /* TARANTOOL_BOX_COLL_ID_CACHE_H_INCLUDED */
diff --git a/src/box/coll_def.c b/src/box/coll_id_def.c
similarity index 86%
rename from src/box/coll_def.c
rename to src/box/coll_id_def.c
index f849845b3..9fe0cda8c 100644
--- a/src/box/coll_def.c
+++ b/src/box/coll_id_def.c
@@ -29,39 +29,7 @@
* SUCH DAMAGE.
*/
-#include "coll_def.h"
-
-const char *coll_type_strs[] = {
- "ICU"
-};
-
-const char *coll_icu_on_off_strs[] = {
- "DEFAULT",
- "ON",
- "OFF"
-};
-
-const char *coll_icu_alternate_handling_strs[] = {
- "DEFAULT",
- "NON_IGNORABLE",
- "SHIFTED"
-};
-
-const char *coll_icu_case_first_strs[] = {
- "DEFAULT",
- "OFF",
- "UPPER_FIRST",
- "LOWER_FIRST"
-};
-
-const char *coll_icu_strength_strs[] = {
- "DEFAULT",
- "PRIMARY",
- "SECONDARY",
- "TERTIARY",
- "QUATERNARY",
- "IDENTICAL"
-};
+#include "coll_id_def.h"
static int64_t
icu_on_off_from_str(const char *str, uint32_t len)
diff --git a/src/box/coll_id_def.h b/src/box/coll_id_def.h
new file mode 100644
index 000000000..489280c00
--- /dev/null
+++ b/src/box/coll_id_def.h
@@ -0,0 +1,54 @@
+#ifndef TARANTOOL_BOX_COLL_ID_DEF_H_INCLUDED
+#define TARANTOOL_BOX_COLL_ID_DEF_H_INCLUDED
+/*
+ * Copyright 2010-2017, 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 AUTHORS ``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
+ * AUTHORS 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 <stddef.h>
+#include <stdint.h>
+#include <coll_def.h>
+#include "opt_def.h"
+
+/** Collation identifier definition. */
+struct coll_id_def {
+ /** Perconal ID */
+ uint32_t id;
+ /** Owner ID */
+ uint32_t owner_id;
+ /** Collation name. */
+ size_t name_len;
+ const char *name;
+ /** Core collation definition. */
+ struct coll_def base;
+};
+
+extern const struct opt_def coll_icu_opts_reg[];
+
+#endif /* TARANTOOL_BOX_COLL_ID_DEF_H_INCLUDED */
diff --git a/src/box/error.cc b/src/box/error.cc
index 99f519537..6b14dff05 100644
--- a/src/box/error.cc
+++ b/src/box/error.cc
@@ -155,6 +155,8 @@ ClientError::get_errcode(const struct error *e)
return ER_MEMORY_ISSUE;
if (type_cast(SystemError, e))
return ER_SYSTEM;
+ if (type_cast(CollationError, e))
+ return ER_CANT_CREATE_COLLATION;
return ER_PROC_LUA;
}
diff --git a/src/box/key_def.cc b/src/box/key_def.cc
index 45997ae83..ee09dc99d 100644
--- a/src/box/key_def.cc
+++ b/src/box/key_def.cc
@@ -34,7 +34,7 @@
#include "tuple_hash.h"
#include "column_mask.h"
#include "schema_def.h"
-#include "coll_cache.h"
+#include "coll_id_cache.h"
static const struct key_part_def key_part_def_default = {
0,
@@ -156,16 +156,17 @@ key_def_new_with_parts(struct key_part_def *parts, uint32_t part_count)
struct key_part_def *part = &parts[i];
struct coll *coll = NULL;
if (part->coll_id != COLL_NONE) {
- coll = coll_by_id(part->coll_id);
- if (coll == NULL) {
+ struct coll_id *coll_id = coll_by_id(part->coll_id);
+ if (coll_id == NULL) {
diag_set(ClientError, ER_WRONG_INDEX_OPTIONS,
i + 1, "collation was not found by ID");
key_def_delete(def);
return NULL;
}
+ coll = coll_id->coll;
}
key_def_set_part(def, i, part->fieldno, part->type,
- part->is_nullable, coll);
+ part->is_nullable, coll, part->coll_id);
}
return def;
}
@@ -179,8 +180,7 @@ key_def_dump_parts(const struct key_def *def, struct key_part_def *parts)
part_def->fieldno = part->fieldno;
part_def->type = part->type;
part_def->is_nullable = part->is_nullable;
- part_def->coll_id = (part->coll != NULL ?
- part->coll->id : COLL_NONE);
+ part_def->coll_id = part->coll_id;
}
}
@@ -194,7 +194,8 @@ box_key_def_new(uint32_t *fields, uint32_t *types, uint32_t part_count)
for (uint32_t item = 0; item < part_count; ++item) {
key_def_set_part(key_def, item, fields[item],
(enum field_type)types[item],
- key_part_def_default.is_nullable, NULL);
+ key_part_def_default.is_nullable, NULL,
+ COLL_NONE);
}
return key_def;
}
@@ -246,7 +247,8 @@ key_part_cmp(const struct key_part *parts1, uint32_t part_count1,
void
key_def_set_part(struct key_def *def, uint32_t part_no, uint32_t fieldno,
- enum field_type type, bool is_nullable, struct coll *coll)
+ enum field_type type, bool is_nullable, struct coll *coll,
+ uint32_t coll_id)
{
assert(part_no < def->part_count);
assert(type < field_type_MAX);
@@ -255,6 +257,7 @@ key_def_set_part(struct key_def *def, uint32_t part_no, uint32_t fieldno,
def->parts[part_no].fieldno = fieldno;
def->parts[part_no].type = type;
def->parts[part_no].coll = coll;
+ def->parts[part_no].coll_id = coll_id;
column_mask_set_fieldno(&def->column_mask, fieldno);
/**
* When all parts are set, initialize the tuple
@@ -554,7 +557,7 @@ key_def_merge(const struct key_def *first, const struct key_def *second)
end = part + first->part_count;
for (; part != end; part++) {
key_def_set_part(new_def, pos++, part->fieldno, part->type,
- part->is_nullable, part->coll);
+ part->is_nullable, part->coll, part->coll_id);
}
/* Set-append second key def's part to the new key def. */
@@ -564,7 +567,7 @@ key_def_merge(const struct key_def *first, const struct key_def *second)
if (key_def_find(first, part->fieldno))
continue;
key_def_set_part(new_def, pos++, part->fieldno, part->type,
- part->is_nullable, part->coll);
+ part->is_nullable, part->coll, part->coll_id);
}
return new_def;
}
diff --git a/src/box/key_def.h b/src/box/key_def.h
index 12016a51a..aecbe0345 100644
--- a/src/box/key_def.h
+++ b/src/box/key_def.h
@@ -36,7 +36,7 @@
#include <msgpuck.h>
#include <limits.h>
#include "field_def.h"
-#include "coll.h"
+#include "coll_id.h"
#if defined(__cplusplus)
extern "C" {
@@ -68,6 +68,8 @@ struct key_part {
uint32_t fieldno;
/** Type of the tuple field */
enum field_type type;
+ /** Collation ID for string comparison. */
+ uint32_t coll_id;
/** Collation definition for string comparison */
struct coll *coll;
/** True if a part can store NULLs. */
@@ -249,7 +251,8 @@ key_def_dump_parts(const struct key_def *def, struct key_part_def *parts);
*/
void
key_def_set_part(struct key_def *def, uint32_t part_no, uint32_t fieldno,
- enum field_type type, bool is_nullable, struct coll *coll);
+ enum field_type type, bool is_nullable, struct coll *coll,
+ uint32_t coll_id);
/**
* Update 'has_optional_parts' of @a key_def with correspondence
diff --git a/src/box/lua/space.cc b/src/box/lua/space.cc
index 333b6370f..524382750 100644
--- a/src/box/lua/space.cc
+++ b/src/box/lua/space.cc
@@ -46,6 +46,7 @@ extern "C" {
#include "box/txn.h"
#include "box/vclock.h" /* VCLOCK_MAX */
#include "box/sequence.h"
+#include "box/coll_id_cache.h"
/**
* Trigger function for all spaces
@@ -291,8 +292,11 @@ lbox_fillspace(struct lua_State *L, struct space *space, int i)
lua_pushboolean(L, part->is_nullable);
lua_setfield(L, -2, "is_nullable");
- if (part->coll != NULL) {
- lua_pushstring(L, part->coll->name);
+ if (part->coll_id != COLL_NONE) {
+ struct coll_id *coll_id =
+ coll_by_id(part->coll_id);
+ assert(coll_id != NULL);
+ lua_pushstring(L, coll_id->name);
lua_setfield(L, -2, "collation");
}
diff --git a/src/box/schema.cc b/src/box/schema.cc
index 1b96f978c..8df4aa73b 100644
--- a/src/box/schema.cc
+++ b/src/box/schema.cc
@@ -281,13 +281,13 @@ schema_init()
auto key_def_guard = make_scoped_guard([&] { key_def_delete(key_def); });
key_def_set_part(key_def, 0 /* part no */, 0 /* field no */,
- FIELD_TYPE_STRING, false, NULL);
+ FIELD_TYPE_STRING, false, NULL, COLL_NONE);
sc_space_new(BOX_SCHEMA_ID, "_schema", key_def, &on_replace_schema,
NULL);
/* _space - home for all spaces. */
key_def_set_part(key_def, 0 /* part no */, 0 /* field no */,
- FIELD_TYPE_UNSIGNED, false, NULL);
+ FIELD_TYPE_UNSIGNED, false, NULL, COLL_NONE);
/* _collation - collation description. */
sc_space_new(BOX_COLLATION_ID, "_collation", key_def,
@@ -335,10 +335,10 @@ schema_init()
diag_raise();
/* space no */
key_def_set_part(key_def, 0 /* part no */, 0 /* field no */,
- FIELD_TYPE_UNSIGNED, false, NULL);
+ FIELD_TYPE_UNSIGNED, false, NULL, COLL_NONE);
/* index no */
key_def_set_part(key_def, 1 /* part no */, 1 /* field no */,
- FIELD_TYPE_UNSIGNED, false, NULL);
+ FIELD_TYPE_UNSIGNED, false, NULL, COLL_NONE);
sc_space_new(BOX_INDEX_ID, "_index", key_def,
&alter_space_on_replace_index, &on_stmt_begin_index);
}
diff --git a/src/box/tuple.c b/src/box/tuple.c
index d4760f3b1..cf3929734 100644
--- a/src/box/tuple.c
+++ b/src/box/tuple.c
@@ -38,7 +38,7 @@
#include "small/small.h"
#include "tuple_update.h"
-#include "coll_cache.h"
+#include "coll_id_cache.h"
static struct mempool tuple_iterator_pool;
static struct small_alloc runtime_alloc;
@@ -207,7 +207,7 @@ tuple_init(field_name_hash_f hash)
box_tuple_last = NULL;
- if (coll_cache_init() != 0)
+ if (coll_id_cache_init() != 0)
return -1;
return 0;
@@ -260,7 +260,7 @@ tuple_free(void)
tuple_format_free();
- coll_cache_destroy();
+ coll_id_cache_destroy();
}
box_tuple_format_t *
diff --git a/src/box/tuple_compare.cc b/src/box/tuple_compare.cc
index cfee00496..e53afba42 100644
--- a/src/box/tuple_compare.cc
+++ b/src/box/tuple_compare.cc
@@ -30,9 +30,9 @@
*/
#include "tuple_compare.h"
#include "tuple.h"
+#include "coll.h"
#include "trivia/util.h" /* NOINLINE */
#include <math.h>
-#include "coll_def.h"
/* {{{ tuple_compare */
@@ -295,8 +295,7 @@ mp_compare_str(const char *field_a, const char *field_b)
}
static inline int
-mp_compare_str_coll(const char *field_a, const char *field_b,
- struct coll *coll)
+mp_compare_str_coll(const char *field_a, const char *field_b, struct coll *coll)
{
uint32_t size_a = mp_decode_strl(&field_a);
uint32_t size_b = mp_decode_strl(&field_b);
diff --git a/src/box/tuple_hash.cc b/src/box/tuple_hash.cc
index 0fa8ea561..dee9be328 100644
--- a/src/box/tuple_hash.cc
+++ b/src/box/tuple_hash.cc
@@ -30,7 +30,6 @@
*/
#include "tuple_hash.h"
-
#include "third_party/PMurHash.h"
#include "coll.h"
diff --git a/src/box/coll.c b/src/coll.c
similarity index 63%
rename from src/box/coll.c
rename to src/coll.c
index 436d8d127..66afa6c4f 100644
--- a/src/box/coll.c
+++ b/src/coll.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2010-2017, Tarantool AUTHORS, please see AUTHORS file.
+ * Copyright 2010-2018, Tarantool AUTHORS, please see AUTHORS file.
*
* Redistribution and use in source and binary forms, with or
* without modification, are permitted provided that the following
@@ -31,19 +31,18 @@
#include "coll.h"
#include "third_party/PMurHash.h"
-#include "error.h"
#include "diag.h"
#include <unicode/ucol.h>
#include <trivia/config.h>
enum {
- MAX_HASH_BUFFER = 1024,
MAX_LOCALE = 1024,
};
-/**
- * Compare two string using ICU collation.
- */
+static_assert(MAX_LOCALE <= TT_STATIC_BUF_LEN,
+ "static buf is used to 0-terminate locale name");
+
+/** Compare two string using ICU collation. */
static int
coll_icu_cmp(const char *s, size_t slen, const char *t, size_t tlen,
const struct coll *coll)
@@ -66,9 +65,7 @@ coll_icu_cmp(const char *s, size_t slen, const char *t, size_t tlen,
return (int)result;
}
-/**
- * Get a hash of a string using ICU collation.
- */
+/** Get a hash of a string using ICU collation. */
static uint32_t
coll_icu_hash(const char *s, size_t s_len, uint32_t *ph, uint32_t *pcarry,
struct coll *coll)
@@ -76,115 +73,103 @@ coll_icu_hash(const char *s, size_t s_len, uint32_t *ph, uint32_t *pcarry,
uint32_t total_size = 0;
UCharIterator itr;
uiter_setUTF8(&itr, s, s_len);
- uint8_t buf[MAX_HASH_BUFFER];
+ uint8_t *buf = (uint8_t *) tt_static_buf();
uint32_t state[2] = {0, 0};
UErrorCode status = U_ZERO_ERROR;
- while (true) {
- int32_t got = ucol_nextSortKeyPart(coll->icu.collator,
- &itr, state, buf,
- MAX_HASH_BUFFER, &status);
+ int32_t got;
+ do {
+ got = ucol_nextSortKeyPart(coll->icu.collator, &itr, state, buf,
+ TT_STATIC_BUF_LEN, &status);
PMurHash32_Process(ph, pcarry, buf, got);
total_size += got;
- if (got < MAX_HASH_BUFFER)
- break;
- }
+ } while (got == TT_STATIC_BUF_LEN);
return total_size;
}
/**
* Set up ICU collator and init cmp and hash members of collation.
- * @param coll - collation to set up.
- * @param def - collation definition.
- * @return 0 on success, -1 on error.
+ * @param coll Collation to set up.
+ * @param def Collation definition.
+ * @retval 0 Success.
+ * @retval -1 Collation error.
*/
static int
coll_icu_init_cmp(struct coll *coll, const struct coll_def *def)
{
- if (coll->icu.collator != NULL) {
- ucol_close(coll->icu.collator);
- coll->icu.collator = NULL;
- }
-
if (def->locale_len >= MAX_LOCALE) {
- diag_set(ClientError, ER_CANT_CREATE_COLLATION,
- "too long locale");
+ diag_set(CollationError, "too long locale");
return -1;
}
- char locale[MAX_LOCALE];
+ char *locale = tt_static_buf();
memcpy(locale, def->locale, def->locale_len);
locale[def->locale_len] = '\0';
UErrorCode status = U_ZERO_ERROR;
struct UCollator *collator = ucol_open(locale, &status);
if (U_FAILURE(status)) {
- diag_set(ClientError, ER_CANT_CREATE_COLLATION,
- u_errorName(status));
+ diag_set(CollationError, u_errorName(status));
return -1;
}
coll->icu.collator = collator;
if (def->icu.french_collation != COLL_ICU_DEFAULT) {
enum coll_icu_on_off w = def->icu.french_collation;
- UColAttributeValue v =
- w == COLL_ICU_ON ? UCOL_ON :
- w == COLL_ICU_OFF ? UCOL_OFF :
- UCOL_DEFAULT;
+ UColAttributeValue v = w == COLL_ICU_ON ? UCOL_ON :
+ w == COLL_ICU_OFF ? UCOL_OFF :
+ UCOL_DEFAULT;
ucol_setAttribute(collator, UCOL_FRENCH_COLLATION, v, &status);
if (U_FAILURE(status)) {
- diag_set(ClientError, ER_CANT_CREATE_COLLATION,
- "failed to set french_collation");
+ diag_set(CollationError, "failed to set "\
+ "french_collation: %s", u_errorName(status));
return -1;
}
}
if (def->icu.alternate_handling != COLL_ICU_AH_DEFAULT) {
- enum coll_icu_alternate_handling w = def->icu.alternate_handling;
+ enum coll_icu_alternate_handling w =
+ def->icu.alternate_handling;
UColAttributeValue v =
w == COLL_ICU_AH_NON_IGNORABLE ? UCOL_NON_IGNORABLE :
- w == COLL_ICU_AH_SHIFTED ? UCOL_SHIFTED :
- UCOL_DEFAULT;
- ucol_setAttribute(collator, UCOL_ALTERNATE_HANDLING, v, &status);
+ w == COLL_ICU_AH_SHIFTED ? UCOL_SHIFTED : UCOL_DEFAULT;
+ ucol_setAttribute(collator, UCOL_ALTERNATE_HANDLING, v,
+ &status);
if (U_FAILURE(status)) {
- diag_set(ClientError, ER_CANT_CREATE_COLLATION,
- "failed to set alternate_handling");
+ diag_set(CollationError, "failed to set "\
+ "alternate_handling: %s", u_errorName(status));
return -1;
}
}
if (def->icu.case_first != COLL_ICU_CF_DEFAULT) {
enum coll_icu_case_first w = def->icu.case_first;
- UColAttributeValue v =
- w == COLL_ICU_CF_OFF ? UCOL_OFF :
+ UColAttributeValue v = w == COLL_ICU_CF_OFF ? UCOL_OFF :
w == COLL_ICU_CF_UPPER_FIRST ? UCOL_UPPER_FIRST :
w == COLL_ICU_CF_LOWER_FIRST ? UCOL_LOWER_FIRST :
UCOL_DEFAULT;
ucol_setAttribute(collator, UCOL_CASE_FIRST, v, &status);
if (U_FAILURE(status)) {
- diag_set(ClientError, ER_CANT_CREATE_COLLATION,
- "failed to set case_first");
+ diag_set(CollationError, "failed to set case_first: "\
+ "%s", u_errorName(status));
return -1;
}
}
if (def->icu.case_level != COLL_ICU_DEFAULT) {
enum coll_icu_on_off w = def->icu.case_level;
- UColAttributeValue v =
- w == COLL_ICU_ON ? UCOL_ON :
- w == COLL_ICU_OFF ? UCOL_OFF :
- UCOL_DEFAULT;
+ UColAttributeValue v = w == COLL_ICU_ON ? UCOL_ON :
+ w == COLL_ICU_OFF ? UCOL_OFF : UCOL_DEFAULT;
ucol_setAttribute(collator, UCOL_CASE_LEVEL , v, &status);
if (U_FAILURE(status)) {
- diag_set(ClientError, ER_CANT_CREATE_COLLATION,
- "failed to set case_level");
+ diag_set(CollationError, "failed to set case_level: "\
+ "%s", u_errorName(status));
return -1;
}
}
if (def->icu.normalization_mode != COLL_ICU_DEFAULT) {
enum coll_icu_on_off w = def->icu.normalization_mode;
- UColAttributeValue v =
- w == COLL_ICU_ON ? UCOL_ON :
- w == COLL_ICU_OFF ? UCOL_OFF :
- UCOL_DEFAULT;
- ucol_setAttribute(collator, UCOL_NORMALIZATION_MODE, v, &status);
+ UColAttributeValue v = w == COLL_ICU_ON ? UCOL_ON :
+ w == COLL_ICU_OFF ? UCOL_OFF : UCOL_DEFAULT;
+ ucol_setAttribute(collator, UCOL_NORMALIZATION_MODE, v,
+ &status);
if (U_FAILURE(status)) {
- diag_set(ClientError, ER_CANT_CREATE_COLLATION,
- "failed to set normalization_mode");
+ diag_set(CollationError, "failed to set "\
+ "normalization_mode: %s", u_errorName(status));
return -1;
}
}
@@ -199,81 +184,51 @@ coll_icu_init_cmp(struct coll *coll, const struct coll_def *def)
UCOL_DEFAULT;
ucol_setAttribute(collator, UCOL_STRENGTH, v, &status);
if (U_FAILURE(status)) {
- diag_set(ClientError, ER_CANT_CREATE_COLLATION,
- "failed to set strength");
+ diag_set(CollationError, "failed to set strength: %s",
+ u_errorName(status));
return -1;
}
}
if (def->icu.numeric_collation != COLL_ICU_DEFAULT) {
enum coll_icu_on_off w = def->icu.numeric_collation;
- UColAttributeValue v =
- w == COLL_ICU_ON ? UCOL_ON :
- w == COLL_ICU_OFF ? UCOL_OFF :
- UCOL_DEFAULT;
+ UColAttributeValue v = w == COLL_ICU_ON ? UCOL_ON :
+ w == COLL_ICU_OFF ? UCOL_OFF : UCOL_DEFAULT;
ucol_setAttribute(collator, UCOL_NUMERIC_COLLATION, v, &status);
if (U_FAILURE(status)) {
- diag_set(ClientError, ER_CANT_CREATE_COLLATION,
- "failed to set numeric_collation");
+ diag_set(CollationError, "failed to set "\
+ "numeric_collation: %s", u_errorName(status));
return -1;
}
}
-
coll->cmp = coll_icu_cmp;
coll->hash = coll_icu_hash;
return 0;
}
-/**
- * Destroy ICU collation.
- */
-static void
-coll_icu_destroy(struct coll *coll)
-{
- if (coll->icu.collator != NULL)
- ucol_close(coll->icu.collator);
-}
-
-/**
- * Create a collation by definition.
- * @param def - collation definition.
- * @return - the collation OR NULL on memory error (diag is set).
- */
struct coll *
coll_new(const struct coll_def *def)
{
- assert(def->type == COLL_TYPE_ICU); /* no more types are implemented yet */
-
- size_t total_len = sizeof(struct coll) + def->name_len + 1;
- struct coll *coll = (struct coll *)calloc(1, total_len);
+ assert(def->type == COLL_TYPE_ICU);
+ struct coll *coll = (struct coll *) malloc(sizeof(*coll));
if (coll == NULL) {
- diag_set(OutOfMemory, total_len, "malloc", "struct coll");
+ diag_set(OutOfMemory, sizeof(*coll), "malloc", "coll");
return NULL;
}
-
coll->refs = 1;
- coll->id = def->id;
- coll->owner_id = def->owner_id;
coll->type = def->type;
- coll->name_len = def->name_len;
- memcpy(coll->name, def->name, def->name_len);
- coll->name[coll->name_len] = 0;
-
if (coll_icu_init_cmp(coll, def) != 0) {
free(coll);
return NULL;
}
-
return coll;
}
void
coll_unref(struct coll *coll)
{
- /* No more types are implemented yet. */
- assert(coll->type == COLL_TYPE_ICU);
assert(coll->refs > 0);
if (--coll->refs == 0) {
- coll_icu_destroy(coll);
+ ucol_close(coll->icu.collator);
free(coll);
}
}
diff --git a/src/box/coll.h b/src/coll.h
similarity index 74%
rename from src/box/coll.h
rename to src/coll.h
index 248500ab4..cc834f446 100644
--- a/src/box/coll.h
+++ b/src/coll.h
@@ -1,7 +1,7 @@
-#ifndef TARANTOOL_BOX_COLL_H_INCLUDED
-#define TARANTOOL_BOX_COLL_H_INCLUDED
+#ifndef TARANTOOL_COLL_H_INCLUDED
+#define TARANTOOL_COLL_H_INCLUDED
/*
- * Copyright 2010-2017, Tarantool AUTHORS, please see AUTHORS file.
+ * Copyright 2010-2018, Tarantool AUTHORS, please see AUTHORS file.
*
* Redistribution and use in source and binary forms, with or
* without modification, are permitted provided that the following
@@ -41,17 +41,13 @@ extern "C" {
struct coll;
-typedef int (*coll_cmp_f)(const char *s, size_t s_len,
- const char *t, size_t t_len,
- const struct coll *coll);
+typedef int (*coll_cmp_f)(const char *s, size_t s_len, const char *t,
+ size_t t_len, const struct coll *coll);
-typedef uint32_t (*coll_hash_f)(const char *s, size_t s_len,
- uint32_t *ph, uint32_t *pcarry,
- struct coll *coll);
+typedef uint32_t (*coll_hash_f)(const char *s, size_t s_len, uint32_t *ph,
+ uint32_t *pcarry, struct coll *coll);
-/**
- * ICU collation specific data.
- */
+/** ICU collation specific data. */
struct UCollator;
struct coll_icu {
@@ -59,13 +55,10 @@ struct coll_icu {
};
/**
- * A collation.
+ * Collation. It has no unique features like name, id or owner.
+ * Only functional part - comparator, locale, ICU settings.
*/
struct coll {
- /** Personal ID */
- uint32_t id;
- /** Owner ID */
- uint32_t owner_id;
/** Collation type. */
enum coll_type type;
/** Type specific data. */
@@ -75,15 +68,13 @@ struct coll {
coll_hash_f hash;
/** Reference counter. */
int refs;
- /** Collation name. */
- size_t name_len;
- char name[0];
};
/**
* Create a collation by definition.
- * @param def - collation definition.
- * @return - the collation OR NULL on memory error (diag is set).
+ * @param def Collation definition.
+ * @retval NULL Collation or memory error.
+ * @retval not NULL Collation.
*/
struct coll *
coll_new(const struct coll_def *def);
@@ -103,4 +94,4 @@ coll_unref(struct coll *coll);
} /* extern "C" */
#endif /* defined(__cplusplus) */
-#endif /* TARANTOOL_BOX_COLL_H_INCLUDED */
+#endif /* TARANTOOL_COLL_H_INCLUDED */
diff --git a/src/coll_def.c b/src/coll_def.c
new file mode 100644
index 000000000..df58caca8
--- /dev/null
+++ b/src/coll_def.c
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2010-2018, 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 AUTHORS ``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
+ * AUTHORS 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 "coll_def.h"
+
+const char *coll_type_strs[] = {
+ "ICU"
+};
+
+const char *coll_icu_on_off_strs[] = {
+ "DEFAULT",
+ "ON",
+ "OFF"
+};
+
+const char *coll_icu_alternate_handling_strs[] = {
+ "DEFAULT",
+ "NON_IGNORABLE",
+ "SHIFTED"
+};
+
+const char *coll_icu_case_first_strs[] = {
+ "DEFAULT",
+ "OFF",
+ "UPPER_FIRST",
+ "LOWER_FIRST"
+};
+
+const char *coll_icu_strength_strs[] = {
+ "DEFAULT",
+ "PRIMARY",
+ "SECONDARY",
+ "TERTIARY",
+ "QUATERNARY",
+ "IDENTICAL"
+};
diff --git a/src/box/coll_def.h b/src/coll_def.h
similarity index 82%
rename from src/box/coll_def.h
rename to src/coll_def.h
index 7a1027a1e..10dbc860e 100644
--- a/src/box/coll_def.h
+++ b/src/coll_def.h
@@ -1,7 +1,7 @@
-#ifndef TARANTOOL_BOX_COLL_DEF_H_INCLUDED
-#define TARANTOOL_BOX_COLL_DEF_H_INCLUDED
+#ifndef TARANTOOL_COLL_DEF_H_INCLUDED
+#define TARANTOOL_COLL_DEF_H_INCLUDED
/*
- * Copyright 2010-2017, Tarantool AUTHORS, please see AUTHORS file.
+ * Copyright 2010-2018, Tarantool AUTHORS, please see AUTHORS file.
*
* Redistribution and use in source and binary forms, with or
* without modification, are permitted provided that the following
@@ -30,18 +30,10 @@
* THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
-
#include <stddef.h>
#include <stdint.h>
-#include "opt_def.h"
-
-#if defined(__cplusplus)
-extern "C" {
-#endif /* defined(__cplusplus) */
-/**
- * The supported collation types
- */
+/** The supported collation types */
enum coll_type {
COLL_TYPE_ICU = 0,
coll_type_MAX,
@@ -109,17 +101,8 @@ struct coll_icu_def {
enum coll_icu_on_off numeric_collation;
};
-/**
- * Definition of a collation.
- */
+/** Collation definition. */
struct coll_def {
- /** Perconal ID */
- uint32_t id;
- /** Owner ID */
- uint32_t owner_id;
- /** Collation name. */
- size_t name_len;
- const char *name;
/** Locale. */
size_t locale_len;
const char *locale;
@@ -129,10 +112,4 @@ struct coll_def {
struct coll_icu_def icu;
};
-extern const struct opt_def coll_icu_opts_reg[];
-
-#if defined(__cplusplus)
-} /* extern "C" */
-#endif /* defined(__cplusplus) */
-
-#endif /* TARANTOOL_BOX_COLL_DEF_H_INCLUDED */
+#endif /* TARANTOOL_COLL_DEF_H_INCLUDED */
diff --git a/src/diag.h b/src/diag.h
index dc6c132d5..bd5a539b0 100644
--- a/src/diag.h
+++ b/src/diag.h
@@ -249,6 +249,8 @@ struct error *
BuildSystemError(const char *file, unsigned line, const char *format, ...);
struct error *
BuildXlogError(const char *file, unsigned line, const char *format, ...);
+struct error *
+BuildCollationError(const char *file, unsigned line, const char *format, ...);
struct index_def;
diff --git a/src/exception.cc b/src/exception.cc
index 56077f76d..1cbf8852f 100644
--- a/src/exception.cc
+++ b/src/exception.cc
@@ -235,6 +235,18 @@ IllegalParams::IllegalParams(const char *file, unsigned line,
va_end(ap);
}
+const struct type_info type_CollationError =
+ make_type("CollationError", &type_Exception);
+
+CollationError::CollationError(const char *file, unsigned line,
+ const char *format, ...)
+ : Exception(&type_CollationError, file, line)
+{
+ va_list ap;
+ va_start(ap, format);
+ error_vformat_msg(this, format, ap);
+ va_end(ap);
+}
#define BuildAlloc(type) \
void *p = malloc(sizeof(type)); \
@@ -303,6 +315,18 @@ BuildSystemError(const char *file, unsigned line, const char *format, ...)
return e;
}
+struct error *
+BuildCollationError(const char *file, unsigned line, const char *format, ...)
+{
+ BuildAlloc(CollationError);
+ CollationError *e = new (p) CollationError(file, line, "");
+ va_list ap;
+ va_start(ap, format);
+ error_vformat_msg(e, format, ap);
+ va_end(ap);
+ return e;
+}
+
void
exception_init()
{
diff --git a/src/exception.h b/src/exception.h
index fe7ab84f0..f56616b68 100644
--- a/src/exception.h
+++ b/src/exception.h
@@ -49,6 +49,7 @@ extern const struct type_info type_ChannelIsClosed;
extern const struct type_info type_LuajitError;
extern const struct type_info type_IllegalParams;
extern const struct type_info type_SystemError;
+extern const struct type_info type_CollationError;
const char *
exception_get_string(struct error *e, const struct method_info *method);
@@ -139,6 +140,14 @@ public:
IllegalParams(const char *file, unsigned line, const char *format, ...);
virtual void raise() { throw this; }
};
+
+class CollationError: public Exception {
+public:
+ CollationError(const char *file, unsigned line, const char *format,
+ ...);
+ virtual void raise() { throw this; }
+};
+
/**
* Initialize the exception subsystem.
*/
diff --git a/test/unit/coll.cpp b/test/unit/coll.cpp
index d77959606..53e06f2ce 100644
--- a/test/unit/coll.cpp
+++ b/test/unit/coll.cpp
@@ -1,14 +1,14 @@
-#include "box/coll.h"
#include <iostream>
#include <vector>
#include <algorithm>
#include <string.h>
-#include <box/coll_def.h>
#include <assert.h>
#include <msgpuck.h>
#include <diag.h>
#include <fiber.h>
#include <memory.h>
+#include "coll_def.h"
+#include "coll.h"
#include "third_party/PMurHash.h"
using namespace std;
@@ -51,8 +51,6 @@ manual_test()
def.locale = "ru_RU";
def.locale_len = strlen(def.locale);
def.type = COLL_TYPE_ICU;
- def.name = "test";
- def.name_len = strlen(def.name);
struct coll *coll;
cout << " -- default ru_RU -- " << endl;
@@ -136,8 +134,6 @@ hash_test()
def.locale = "ru_RU";
def.locale_len = strlen(def.locale);
def.type = COLL_TYPE_ICU;
- def.name = "test";
- def.name_len = strlen(def.name);
struct coll *coll;
/* Case sensitive */
--
2.15.1 (Apple Git-101)
More information about the Tarantool-patches
mailing list