From bf086dc984d4ee87e6a7857b0f44b6c1ed033df8 Mon Sep 17 00:00:00 2001
From: Georgiy Lebedev <g.lebedev@tarantool.org>
Date: Thu, 20 Apr 2023 09:59:31 +0300
Subject: [PATCH] box: add `space_by_name` and `space_index_by_name` for
 arbitrary strings

Change original `space_by_name` to `space_by_name0` and
`space_index_by_name` to `space_index_by_name0`, since they accept
NULL-terminated names, and add `space_by_name` and `space_index_by_name`
for arbitrary strings.

Needed for #8146

NO_CHANGELOG=refactoring
NO_DOC=refactoring
NO_TEST=refactoring
---
 src/box/alter.cc       |  2 +-
 src/box/space.h        | 17 +++++++++++++++--
 src/box/space_cache.c  |  6 ++----
 src/box/space_cache.h  | 11 ++++++++++-
 src/box/sql/alter.c    |  4 ++--
 src/box/sql/build.c    | 20 ++++++++++----------
 src/box/sql/delete.c   |  4 ++--
 src/box/sql/insert.c   |  2 +-
 src/box/sql/pragma.c   |  8 ++++----
 src/box/sql/tokenize.c |  2 +-
 10 files changed, 48 insertions(+), 28 deletions(-)

diff --git a/src/box/alter.cc b/src/box/alter.cc
index 6caa02a458..29199285ec 100644
--- a/src/box/alter.cc
+++ b/src/box/alter.cc
@@ -1854,7 +1854,7 @@ update_view_references(struct Select *select, int update_value,
 		 */
 		if (sql_select_constains_cte(select, space_name))
 			continue;
-		struct space *space = space_by_name(space_name);
+		struct space *space = space_by_name0(space_name);
 		if (space == NULL) {
 			if (! suppress_error) {
 				assert(not_found_space != NULL);
diff --git a/src/box/space.h b/src/box/space.h
index afcddebc5f..e8a10b52b0 100644
--- a/src/box/space.h
+++ b/src/box/space.h
@@ -364,20 +364,33 @@ space_index(struct space *space, uint32_t id)
  *
  * @param space Space index belongs to.
  * @param index_name Name of index to be found.
+ * @param index_name_len Length of index name.
  *
  * @retval NULL if the index is not found.
  */
 static inline struct index *
-space_index_by_name(struct space *space, const char *index_name)
+space_index_by_name(struct space *space, const char *index_name,
+		    uint32_t index_name_len)
 {
 	for(uint32_t i = 0; i < space->index_count; i++) {
 		struct index *index = space->index[i];
-		if (strcmp(index_name, index->def->name) == 0)
+		if (strlen(index->def->name) != index_name_len)
+			continue;
+		if (strncmp(index_name, index->def->name, index_name_len) == 0)
 			return index;
 	}
 	return NULL;
 }
 
+/**
+ * `space_index_by_name` for NULL-terminated index names.
+ */
+static inline struct index *
+space_index_by_name0(struct space *space, const char *index_name)
+{
+	return space_index_by_name(space, index_name, strlen(index_name));
+}
+
 /**
  * Return true if the unique constraint must be checked for
  * the index with the given id before inserting a tuple into
diff --git a/src/box/space_cache.c b/src/box/space_cache.c
index 05e162ba96..e5a41478d3 100644
--- a/src/box/space_cache.c
+++ b/src/box/space_cache.c
@@ -58,12 +58,10 @@ space_by_id(uint32_t id)
 	return (struct space *)mh_i32ptr_node(spaces, space)->val;
 }
 
-/** Return space by its name */
 struct space *
-space_by_name(const char *name)
+space_by_name(const char *name, uint32_t len)
 {
-	mh_int_t space = mh_strnptr_find_str(spaces_by_name, name,
-					     strlen(name));
+	mh_int_t space = mh_strnptr_find_str(spaces_by_name, name, len);
 	if (space == mh_end(spaces_by_name))
 		return NULL;
 	return (struct space *)mh_strnptr_node(spaces_by_name, space)->val;
diff --git a/src/box/space_cache.h b/src/box/space_cache.h
index 56d8d2e737..344f8359ec 100644
--- a/src/box/space_cache.h
+++ b/src/box/space_cache.h
@@ -95,7 +95,16 @@ space_by_id(uint32_t id);
  * @return NULL if space not found, otherwise space object.
  */
 struct space *
-space_by_name(const char *name);
+space_by_name(const char *name, uint32_t len);
+
+/**
+ * `space_by_name` for NULL-terminated names.
+ */
+static inline struct space *
+space_by_name0(const char *name)
+{
+	return space_by_name(name, strlen(name));
+}
 
 /**
  * Find minimal unused id, which is greater than cur_id.
diff --git a/src/box/sql/alter.c b/src/box/sql/alter.c
index f793553228..f2f76bf715 100644
--- a/src/box/sql/alter.c
+++ b/src/box/sql/alter.c
@@ -47,12 +47,12 @@ sql_alter_table_rename(struct Parse *parse)
 	assert(src_tab->nSrc == 1);
 	char *new_name = sql_name_from_token(&rename_def->new_name);
 	/* Check that new name isn't occupied by another table. */
-	if (space_by_name(new_name) != NULL) {
+	if (space_by_name0(new_name) != NULL) {
 		diag_set(ClientError, ER_SPACE_EXISTS, new_name);
 		goto tnt_error;
 	}
 	const char *tbl_name = src_tab->a[0].zName;
-	struct space *space = space_by_name(tbl_name);
+	struct space *space = space_by_name0(tbl_name);
 	if (space == NULL) {
 		diag_set(ClientError, ER_NO_SUCH_SPACE, tbl_name);
 		goto tnt_error;
diff --git a/src/box/sql/build.c b/src/box/sql/build.c
index f0e7041a8d..945aa38d60 100644
--- a/src/box/sql/build.c
+++ b/src/box/sql/build.c
@@ -338,7 +338,7 @@ sql_create_column_start(struct Parse *parse)
 	if (is_alter) {
 		const char *space_name =
 			alter_entity_def->entity_name->a[0].zName;
-		space = space_by_name(space_name);
+		space = space_by_name0(space_name);
 		if (space == NULL) {
 			diag_set(ClientError, ER_NO_SUCH_SPACE, space_name);
 			goto tnt_error;
@@ -760,7 +760,7 @@ sql_create_check_contraint(struct Parse *parser, bool is_field_ck)
 	ck_def->name[name_len] = '\0';
 	if (is_alter_add_constr) {
 		const char *space_name = alter_def->entity_name->a[0].zName;
-		struct space *space = space_by_name(space_name);
+		struct space *space = space_by_name0(space_name);
 		if (space == NULL) {
 			diag_set(ClientError, ER_NO_SUCH_SPACE, space_name);
 			parser->is_aborted = true;
@@ -1254,7 +1254,7 @@ vdbe_emit_create_constraints(struct Parse *parse, int reg_space_id)
 	 */
 	if (is_alter) {
 		space = parse->create_column_def.space;
-		i = space_by_name(space->def->name)->index_count;
+		i = space_by_name0(space->def->name)->index_count;
 	}
 	assert(space != NULL);
 	for (; i < space->index_count; ++i) {
@@ -1758,7 +1758,7 @@ sql_drop_table(struct Parse *parse_context)
 	assert(!parse_context->is_aborted);
 	assert(table_name_list->nSrc == 1);
 	const char *space_name = table_name_list->a[0].zName;
-	struct space *space = space_by_name(space_name);
+	struct space *space = space_by_name0(space_name);
 	if (space == NULL) {
 		if (!drop_def.if_exist) {
 			diag_set(ClientError, ER_NO_SUCH_SPACE, space_name);
@@ -1919,7 +1919,7 @@ sql_create_foreign_key(struct Parse *parse_context)
 	assert(constraint_name != NULL);
 	if (is_alter_add_constr) {
 		const char *child_name = alter_def->entity_name->a[0].zName;
-		child_space = space_by_name(child_name);
+		child_space = space_by_name0(child_name);
 		if (child_space == NULL) {
 			diag_set(ClientError, ER_NO_SUCH_SPACE, child_name);
 			goto tnt_error;
@@ -1955,7 +1955,7 @@ sql_create_foreign_key(struct Parse *parse_context)
 	 */
 	is_self_referenced = !is_alter_add_constr &&
 			     strcmp(parent_name, space->def->name) == 0;
-	struct space *parent_space = space_by_name(parent_name);
+	struct space *parent_space = space_by_name0(parent_name);
 	if (parent_space == NULL && !is_self_referenced) {
 		diag_set(ClientError, ER_NO_SUCH_SPACE, parent_name);
 		goto tnt_error;
@@ -2103,7 +2103,7 @@ sql_drop_constraint(struct Parse *parse_context)
 	assert(drop_def->base.alter_action == ALTER_ACTION_DROP);
 	const char *table_name = drop_def->base.entity_name->a[0].zName;
 	assert(table_name != NULL);
-	struct space *space = space_by_name(table_name);
+	struct space *space = space_by_name0(table_name);
 	if (space == NULL) {
 		diag_set(ClientError, ER_NO_SUCH_SPACE, table_name);
 		parse_context->is_aborted = true;
@@ -2426,7 +2426,7 @@ sql_create_index(struct Parse *parse) {
 	if (tbl_name != NULL) {
 		assert(token.n > 0 && token.z != NULL);
 		const char *name = tbl_name->a[0].zName;
-		space = space_by_name(name);
+		space = space_by_name0(name);
 		if (space == NULL) {
 			if (! create_entity_def->if_not_exist) {
 				diag_set(ClientError, ER_NO_SUCH_SPACE, name);
@@ -2474,7 +2474,7 @@ sql_create_index(struct Parse *parse) {
 	if (!is_create_table_or_add_col) {
 		assert(token.z != NULL);
 		name = sql_name_from_token(&token);
-		if (space_index_by_name(space, name) != NULL) {
+		if (space_index_by_name0(space, name) != NULL) {
 			if (! create_entity_def->if_not_exist) {
 				diag_set(ClientError, ER_INDEX_EXISTS_IN_SPACE,
 					 name, def->name);
@@ -2739,7 +2739,7 @@ sql_drop_index(struct Parse *parse_context)
 	char *table_name = table_list->a[0].zName;
 	char *index_name = NULL;
 	sqlVdbeCountChanges(v);
-	struct space *space = space_by_name(table_name);
+	struct space *space = space_by_name0(table_name);
 	bool if_exists = drop_def->if_exist;
 	if (space == NULL) {
 		if (!if_exists) {
diff --git a/src/box/sql/delete.c b/src/box/sql/delete.c
index 1015616f9a..9ac7ec20db 100644
--- a/src/box/sql/delete.c
+++ b/src/box/sql/delete.c
@@ -39,7 +39,7 @@ sql_lookup_space(struct Parse *parse, struct SrcList_item *space_name)
 {
 	assert(space_name != NULL);
 	assert(space_name->space == NULL);
-	struct space *space = space_by_name(space_name->zName);
+	struct space *space = space_by_name0(space_name->zName);
 	if (space == NULL) {
 		diag_set(ClientError, ER_NO_SUCH_SPACE, space_name->zName);
 		parse->is_aborted = true;
@@ -87,7 +87,7 @@ sql_table_truncate(struct Parse *parse, struct SrcList *tab_list)
 
 	struct Vdbe *v = sqlGetVdbe(parse);
 	const char *tab_name = tab_list->a->zName;
-	struct space *space = space_by_name(tab_name);
+	struct space *space = space_by_name0(tab_name);
 	if (space == NULL) {
 		diag_set(ClientError, ER_NO_SUCH_SPACE, tab_name);
 		goto tarantool_error;
diff --git a/src/box/sql/insert.c b/src/box/sql/insert.c
index 52ee831f7c..e94b2d8a63 100644
--- a/src/box/sql/insert.c
+++ b/src/box/sql/insert.c
@@ -1071,7 +1071,7 @@ xferOptimization(Parse * pParse,	/* Parser context */
 	 * we have to check the semantics.
 	 */
 	pItem = pSelect->pSrc->a;
-	struct space *src = space_by_name(pItem->zName);
+	struct space *src = space_by_name0(pItem->zName);
 	/* FROM clause does not contain a real table. */
 	if (src == NULL)
 		return 0;
diff --git a/src/box/sql/pragma.c b/src/box/sql/pragma.c
index 47662d0f32..c00cdc3080 100644
--- a/src/box/sql/pragma.c
+++ b/src/box/sql/pragma.c
@@ -100,7 +100,7 @@ sql_pragma_table_info(struct Parse *parse, const char *tbl_name)
 {
 	if (tbl_name == NULL)
 		return;
-	struct space *space = space_by_name(tbl_name);
+	struct space *space = space_by_name0(tbl_name);
 	if (space == NULL)
 		return;
 	struct index *pk = space_index(space, 0);
@@ -187,10 +187,10 @@ sql_pragma_index_info(struct Parse *parse,
 {
 	if (idx_name == NULL || tbl_name == NULL)
 		return;
-	struct space *space = space_by_name(tbl_name);
+	struct space *space = space_by_name0(tbl_name);
 	if (space == NULL)
 		return;
-	struct index *idx = space_index_by_name(space, idx_name);
+	struct index *idx = space_index_by_name0(space, idx_name);
 	if (idx == NULL)
 		return;
 	parse->nMem = 6;
@@ -267,7 +267,7 @@ sql_pragma_index_list(struct Parse *parse, const char *tbl_name)
 {
 	if (tbl_name == NULL)
 		return;
-	struct space *space = space_by_name(tbl_name);
+	struct space *space = space_by_name0(tbl_name);
 	if (space == NULL)
 		return;
 	parse->nMem = 3;
diff --git a/src/box/sql/tokenize.c b/src/box/sql/tokenize.c
index 415d3e6a4c..101dc87764 100644
--- a/src/box/sql/tokenize.c
+++ b/src/box/sql/tokenize.c
@@ -456,7 +456,7 @@ parser_space_delete(struct space *space)
 	if (space == NULL)
 		return;
 	assert(space->def->opts.is_ephemeral);
-	struct space *altered_space = space_by_name(space->def->name);
+	struct space *altered_space = space_by_name0(space->def->name);
 	uint32_t i = 0;
 	/*
 	 * Don't delete already existing defs and start from new
-- 
GitLab