[PATCH v5 04/12] box: introduce tuple_format_add_key_part

Kirill Shcherbatov kshcherbatov at tarantool.org
Mon Oct 29 09:56:36 MSK 2018


Introduced a new tuple_format_add_key_part that makes format
initialization for specified key_part and configuration.
This decrease tuple_format_create routine complexity and would
be used to initialize structures in format for JSON path.

Need for #1012
---
 src/box/tuple_format.c | 153 ++++++++++++++++++++++++++-----------------------
 1 file changed, 82 insertions(+), 71 deletions(-)

diff --git a/src/box/tuple_format.c b/src/box/tuple_format.c
index 6f76158..088579c 100644
--- a/src/box/tuple_format.c
+++ b/src/box/tuple_format.c
@@ -43,6 +43,84 @@ static const struct tuple_field tuple_field_default = {
 	ON_CONFLICT_ACTION_DEFAULT, NULL, COLL_NONE,
 };
 
+static int
+tuple_format_add_key_part(struct tuple_format *format,
+			  const struct field_def *fields, uint32_t field_count,
+			  const struct key_part *part, bool is_sequential,
+			  int *current_slot)
+{
+	assert(part->fieldno < format->field_count);
+	struct tuple_field *field = &format->fields[part->fieldno];
+	/*
+	 * Field and part nullable actions may differ only
+	 * if one of them is DEFAULT, in which case we use
+	 * the non-default action *except* the case when
+	 * the other one is NONE, in which case we assume
+	 * DEFAULT. The latter is needed so that in case
+	 * index definition and space format have different
+	 * is_nullable flag, we will use the strictest option,
+	 * i.e. DEFAULT.
+	 */
+	if (part->fieldno >= field_count) {
+		field->nullable_action = part->nullable_action;
+	} else if (field->nullable_action == ON_CONFLICT_ACTION_DEFAULT) {
+		if (part->nullable_action != ON_CONFLICT_ACTION_NONE)
+			field->nullable_action = part->nullable_action;
+	} else if (part->nullable_action == ON_CONFLICT_ACTION_DEFAULT) {
+		if (field->nullable_action == ON_CONFLICT_ACTION_NONE)
+			field->nullable_action = part->nullable_action;
+	} else if (field->nullable_action != part->nullable_action) {
+		diag_set(ClientError, ER_ACTION_MISMATCH,
+			 part->fieldno + TUPLE_INDEX_BASE,
+			 on_conflict_action_strs[field->nullable_action],
+			 on_conflict_action_strs[part->nullable_action]);
+		return -1;
+	}
+
+	/**
+	 * Check that there are no conflicts between index part
+	 * types and space fields. If a part type is compatible
+	 * with field's one, then the part type is more strict
+	 * and the part type must be used in tuple_format.
+	 */
+	if (field_type1_contains_type2(field->type,
+					part->type)) {
+		field->type = part->type;
+	} else if (!field_type1_contains_type2(part->type,
+					       field->type)) {
+		const char *name;
+		int fieldno = part->fieldno + TUPLE_INDEX_BASE;
+		if (part->fieldno >= field_count) {
+			name = tt_sprintf("%d", fieldno);
+		} else {
+			const struct field_def *def =
+				&fields[part->fieldno];
+			name = tt_sprintf("'%s'", def->name);
+		}
+		int errcode;
+		if (!field->is_key_part)
+			errcode = ER_FORMAT_MISMATCH_INDEX_PART;
+		else
+			errcode = ER_INDEX_PART_TYPE_MISMATCH;
+		diag_set(ClientError, errcode, name,
+			 field_type_strs[field->type],
+			 field_type_strs[part->type]);
+		return -1;
+	}
+	field->is_key_part = true;
+	/*
+	 * In the tuple, store only offsets necessary to access
+	 * fields of non-sequential keys. First field is always
+	 * simply accessible, so we don't store an offset for it.
+	 */
+	if (field->offset_slot == TUPLE_OFFSET_SLOT_NIL &&
+	    is_sequential == false && part->fieldno > 0) {
+		*current_slot = *current_slot - 1;
+		field->offset_slot = *current_slot;
+	}
+	return 0;
+}
+
 /**
  * Extract all available type info from keys and field
  * definitions.
@@ -93,78 +171,11 @@ tuple_format_create(struct tuple_format *format, struct key_def * const *keys,
 		const struct key_part *parts_end = part + key_def->part_count;
 
 		for (; part < parts_end; part++) {
-			assert(part->fieldno < format->field_count);
-			struct tuple_field *field = &format->fields[part->fieldno];
-			/*
-			 * Field and part nullable actions may differ only
-			 * if one of them is DEFAULT, in which case we use
-			 * the non-default action *except* the case when
-			 * the other one is NONE, in which case we assume
-			 * DEFAULT. The latter is needed so that in case
-			 * index definition and space format have different
-			 * is_nullable flag, we will use the strictest option,
-			 * i.e. DEFAULT.
-			 */
-			if (part->fieldno >= field_count) {
-				field->nullable_action = part->nullable_action;
-			} else if (field->nullable_action == ON_CONFLICT_ACTION_DEFAULT) {
-				if (part->nullable_action != ON_CONFLICT_ACTION_NONE)
-					field->nullable_action = part->nullable_action;
-			} else if (part->nullable_action == ON_CONFLICT_ACTION_DEFAULT) {
-				if (field->nullable_action == ON_CONFLICT_ACTION_NONE)
-					field->nullable_action = part->nullable_action;
-			} else if (field->nullable_action != part->nullable_action) {
-				diag_set(ClientError, ER_ACTION_MISMATCH,
-					 part->fieldno + TUPLE_INDEX_BASE,
-					 on_conflict_action_strs[field->nullable_action],
-					 on_conflict_action_strs[part->nullable_action]);
+			if (tuple_format_add_key_part(format, fields,
+						      field_count, part,
+						      is_sequential,
+						      &current_slot) != 0)
 				return -1;
-			}
-
-			/*
-			 * Check that there are no conflicts
-			 * between index part types and space
-			 * fields. If a part type is compatible
-			 * with field's one, then the part type is
-			 * more strict and the part type must be
-			 * used in tuple_format.
-			 */
-			if (field_type1_contains_type2(field->type,
-						       part->type)) {
-				field->type = part->type;
-			} else if (! field_type1_contains_type2(part->type,
-								field->type)) {
-				const char *name;
-				int fieldno = part->fieldno + TUPLE_INDEX_BASE;
-				if (part->fieldno >= field_count) {
-					name = tt_sprintf("%d", fieldno);
-				} else {
-					const struct field_def *def =
-						&fields[part->fieldno];
-					name = tt_sprintf("'%s'", def->name);
-				}
-				int errcode;
-				if (! field->is_key_part)
-					errcode = ER_FORMAT_MISMATCH_INDEX_PART;
-				else
-					errcode = ER_INDEX_PART_TYPE_MISMATCH;
-				diag_set(ClientError, errcode, name,
-					 field_type_strs[field->type],
-					 field_type_strs[part->type]);
-				return -1;
-			}
-			field->is_key_part = true;
-			/*
-			 * In the tuple, store only offsets necessary
-			 * to access fields of non-sequential keys.
-			 * First field is always simply accessible,
-			 * so we don't store an offset for it.
-			 */
-			if (field->offset_slot == TUPLE_OFFSET_SLOT_NIL &&
-			    is_sequential == false && part->fieldno > 0) {
-
-				field->offset_slot = --current_slot;
-			}
 		}
 	}
 
-- 
2.7.4




More information about the Tarantool-patches mailing list