[Tarantool-patches] [PATCH 1/2] box: introduce internal sequence error

olegrok at tarantool.org olegrok at tarantool.org
Fri Mar 6 14:46:42 MSK 2020


From: Oleg Babin <babinoleg at mail.ru>

This patch introduces SequenceError. It is thrown
in case when we try to get current value of sequence
before it was initialized ("next" was called at least once)

Need for #4752
---
Issue: https://github.com/tarantool/tarantool/issues/4752
Branch: https://github.com/tarantool/tarantool/tree/olegrok/4752-sequence-current
 src/box/sequence.c        | 12 ++++++++----
 src/box/sequence.h        |  7 ++++---
 src/box/sql/vdbe.c        |  5 ++++-
 src/lib/core/diag.h       |  2 ++
 src/lib/core/exception.cc | 25 +++++++++++++++++++++++++
 src/lib/core/exception.h  |  6 ++++++
 6 files changed, 49 insertions(+), 8 deletions(-)

diff --git a/src/box/sequence.c b/src/box/sequence.c
index 5ebfa2747..617b7ca38 100644
--- a/src/box/sequence.c
+++ b/src/box/sequence.c
@@ -367,14 +367,18 @@ sequence_data_iterator_create(void)
 	return &iter->base;
 }
 
-int64_t
-sequence_get_value(struct sequence *seq)
+int
+sequence_get_value(struct sequence *seq, int64_t *result)
 {
 	uint32_t key = seq->def->id;
 	uint32_t hash = sequence_hash(key);
 	uint32_t pos = light_sequence_find_key(&sequence_data_index, hash, key);
-	assert(pos != light_sequence_end);
+	if (pos == light_sequence_end) {
+		diag_set(SequenceError, "Sequence is not initialized yet");
+		return -1;
+	}
 	struct sequence_data data = light_sequence_get(&sequence_data_index,
 						       pos);
-	return data.value;
+	*result = data.value;
+	return 0;
 }
diff --git a/src/box/sequence.h b/src/box/sequence.h
index a164da9af..8c442872a 100644
--- a/src/box/sequence.h
+++ b/src/box/sequence.h
@@ -171,10 +171,11 @@ sequence_data_iterator_create(void);
  * Get last element of given sequence.
  *
  * @param seq sequence to get value from.
- * @retval last element of sequence.
+ * @result value of sequence.
+ * Return 0 on success, -1 if sequence is not initialized.
  */
-int64_t
-sequence_get_value(struct sequence *seq);
+int
+sequence_get_value(struct sequence *seq, int64_t *result);
 
 #if defined(__cplusplus)
 } /* extern "C" */
diff --git a/src/box/sql/vdbe.c b/src/box/sql/vdbe.c
index 912a10153..0de07ca1d 100644
--- a/src/box/sql/vdbe.c
+++ b/src/box/sql/vdbe.c
@@ -4328,7 +4328,10 @@ case OP_IdxInsert: {
 		p->nChange++;
 	if (pOp->p3 > 0 && ((aMem[pOp->p3].flags) & MEM_Null) != 0) {
 		assert(space->sequence != NULL);
-		int64_t value = sequence_get_value(space->sequence);
+		int64_t value;
+		if (sequence_get_value(space->sequence, &value) != 0) {
+			goto abort_due_to_error;
+		}
 		if (vdbe_add_new_autoinc_id(p, value) != 0)
 			goto abort_due_to_error;
 	}
diff --git a/src/lib/core/diag.h b/src/lib/core/diag.h
index f763957c2..e19b6b824 100644
--- a/src/lib/core/diag.h
+++ b/src/lib/core/diag.h
@@ -259,6 +259,8 @@ struct error *
 BuildSwimError(const char *file, unsigned line, const char *format, ...);
 struct error *
 BuildCryptoError(const char *file, unsigned line, const char *format, ...);
+struct error *
+BuildSequenceError(const char *file, unsigned line, const char *format, ...);
 
 struct index_def;
 
diff --git a/src/lib/core/exception.cc b/src/lib/core/exception.cc
index 76dcea553..53b86291f 100644
--- a/src/lib/core/exception.cc
+++ b/src/lib/core/exception.cc
@@ -287,6 +287,19 @@ CryptoError::CryptoError(const char *file, unsigned line,
 	va_end(ap);
 }
 
+const struct type_info type_SequenceError =
+		make_type("SequenceError", &type_Exception);
+
+SequenceError::SequenceError(const char *file, unsigned line,
+						 const char *format, ...)
+		: Exception(&type_SequenceError, 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));			\
 	if (p == NULL)					\
@@ -390,6 +403,18 @@ BuildCryptoError(const char *file, unsigned line, const char *format, ...)
 	return e;
 }
 
+struct error *
+BuildSequenceError(const char *file, unsigned line, const char *format, ...)
+{
+	BuildAlloc(CryptoError);
+	SequenceError *e =  new (p) SequenceError(file, line, "");
+	va_list ap;
+	va_start(ap, format);
+	error_vformat_msg(e, format, ap);
+	va_end(ap);
+	return e;
+}
+
 struct error *
 BuildSocketError(const char *file, unsigned line, const char *socketname,
 		 const char *format, ...)
diff --git a/src/lib/core/exception.h b/src/lib/core/exception.h
index d6154eb32..d9c4542da 100644
--- a/src/lib/core/exception.h
+++ b/src/lib/core/exception.h
@@ -168,6 +168,12 @@ public:
 	virtual void raise() { throw this; }
 };
 
+class SequenceError: public Exception {
+public:
+	SequenceError(const char *file, unsigned line, const char *format, ...);
+	virtual void raise() { throw this; }
+};
+
 /**
  * Initialize the exception subsystem.
  */
-- 
2.23.0



More information about the Tarantool-patches mailing list