Tarantool development patches archive
 help / color / mirror / Atom feed
* [Tarantool-patches] [PATCH 0/2] Introcude sequence.current
@ 2020-03-06 11:46 olegrok
  2020-03-06 11:46 ` [Tarantool-patches] [PATCH 1/2] box: introduce internal sequence error olegrok
  2020-03-06 11:46 ` [Tarantool-patches] [PATCH 2/2] box: introduce "current" for sequence olegrok
  0 siblings, 2 replies; 6+ messages in thread
From: olegrok @ 2020-03-06 11:46 UTC (permalink / raw)
  To: tarantool-patches, v.shpilevoy, korablev; +Cc: Oleg Babin

From: Oleg Babin <babinoleg@mail.ru>

This patchset exposes function for getting
current value of sequence to lua.
The first patch adds a new type of internal error -
sequence error.
The second one introduces "current" function
for sequence object.

Issue: https://github.com/tarantool/tarantool/issues/4752
Branch: https://github.com/tarantool/tarantool/tree/olegrok/4752-sequence-current

@ChangeLog
 - Introduce "current" function for sequence object.
  It allows to get current value of a sequence.

Oleg Babin (2):
  box: introduce internal sequence error
  box: introduce "current" for sequence

 src/box/box.cc             | 14 ++++++++++++++
 src/box/box.h              | 12 ++++++++++++
 src/box/lua/schema.lua     |  4 ++++
 src/box/lua/sequence.c     | 12 ++++++++++++
 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 ++++++
 test/box/sequence.result   | 32 ++++++++++++++++++++++++++++++++
 test/box/sequence.test.lua | 12 ++++++++++++
 12 files changed, 135 insertions(+), 8 deletions(-)

-- 
2.23.0

^ permalink raw reply	[flat|nested] 6+ messages in thread

* [Tarantool-patches] [PATCH 1/2] box: introduce internal sequence error
  2020-03-06 11:46 [Tarantool-patches] [PATCH 0/2] Introcude sequence.current olegrok
@ 2020-03-06 11:46 ` olegrok
  2020-03-06 12:55   ` Nikita Pettik
  2020-03-06 11:46 ` [Tarantool-patches] [PATCH 2/2] box: introduce "current" for sequence olegrok
  1 sibling, 1 reply; 6+ messages in thread
From: olegrok @ 2020-03-06 11:46 UTC (permalink / raw)
  To: tarantool-patches, v.shpilevoy, korablev; +Cc: Oleg Babin

From: Oleg Babin <babinoleg@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

^ permalink raw reply	[flat|nested] 6+ messages in thread

* [Tarantool-patches] [PATCH 2/2] box: introduce "current" for sequence
  2020-03-06 11:46 [Tarantool-patches] [PATCH 0/2] Introcude sequence.current olegrok
  2020-03-06 11:46 ` [Tarantool-patches] [PATCH 1/2] box: introduce internal sequence error olegrok
@ 2020-03-06 11:46 ` olegrok
  2020-03-06 13:00   ` Nikita Pettik
  1 sibling, 1 reply; 6+ messages in thread
From: olegrok @ 2020-03-06 11:46 UTC (permalink / raw)
  To: tarantool-patches, v.shpilevoy, korablev; +Cc: Oleg Babin

From: Oleg Babin <babinoleg@mail.ru>

This patch introduces "current" function for
sequences. It returns current value of
specified sequence or throws an error
if sequence is not initialized ("next" called
at least once).

Closes #4752

@TarantoolBot document
Title: sequence:current()

New function returns current value of sequence
of throws an error if used before sequence
initialization.

Example

```lua
sq = box.schema.sequence.create('test')
---
...
sq:current()
---
- error: Sequence is not initialized yet
...
sq:next()
---
- 1
...
sq:current()
---
- 1
...
sq:set(42)
---
...
sq:current()
---
- 42
...
```
---
Issue: https://github.com/tarantool/tarantool/issues/4752
Branch: https://github.com/tarantool/tarantool/tree/olegrok/4752-sequence-current
 src/box/box.cc             | 14 ++++++++++++++
 src/box/box.h              | 12 ++++++++++++
 src/box/lua/schema.lua     |  4 ++++
 src/box/lua/sequence.c     | 12 ++++++++++++
 test/box/sequence.result   | 32 ++++++++++++++++++++++++++++++++
 test/box/sequence.test.lua | 12 ++++++++++++
 6 files changed, 86 insertions(+)

diff --git a/src/box/box.cc b/src/box/box.cc
index 09dd67ab4..a5052dba4 100644
--- a/src/box/box.cc
+++ b/src/box/box.cc
@@ -1414,6 +1414,20 @@ box_sequence_next(uint32_t seq_id, int64_t *result)
 	*result = value;
 	return 0;
 }
+
+int
+box_sequence_current(uint32_t seq_id, int64_t *result)
+{
+	struct sequence *seq = sequence_cache_find(seq_id);
+	if (seq == NULL)
+		return -1;
+	if (access_check_sequence(seq) != 0)
+		return -1;
+	if (sequence_get_value(seq, result) != 0)
+		return -1;
+	return 0;
+}
+
 int
 box_sequence_set(uint32_t seq_id, int64_t value)
 {
diff --git a/src/box/box.h b/src/box/box.h
index f37a945eb..8fb723630 100644
--- a/src/box/box.h
+++ b/src/box/box.h
@@ -423,6 +423,18 @@ box_truncate(uint32_t space_id);
 API_EXPORT int
 box_sequence_next(uint32_t seq_id, int64_t *result);
 
+/**
+ * Returns current value of sequence.
+ *
+ * \param seq_id sequence identifier
+ * \param[out] result pointer to a variable where the current sequence
+ * value will be stored on success
+ * \retval -1 on error (check box_error_last())
+ * \retval 0 on success
+ */
+API_EXPORT int
+box_sequence_current(uint32_t seq_id, int64_t *result);
+
 /**
  * Set a sequence value.
  *
diff --git a/src/box/lua/schema.lua b/src/box/lua/schema.lua
index f537c3cec..0cd747350 100644
--- a/src/box/lua/schema.lua
+++ b/src/box/lua/schema.lua
@@ -1812,6 +1812,10 @@ sequence_mt.next = function(self)
     return internal.sequence.next(self.id)
 end
 
+sequence_mt.current = function(self)
+    return internal.sequence.current(self.id)
+end
+
 sequence_mt.set = function(self, value)
     return internal.sequence.set(self.id, value)
 end
diff --git a/src/box/lua/sequence.c b/src/box/lua/sequence.c
index bf0714c1a..ae4b5d3ce 100644
--- a/src/box/lua/sequence.c
+++ b/src/box/lua/sequence.c
@@ -49,6 +49,17 @@ lbox_sequence_next(struct lua_State *L)
 	return 1;
 }
 
+static int
+lbox_sequence_current(struct lua_State *L)
+{
+	uint32_t seq_id = luaL_checkinteger(L, 1);
+	int64_t result;
+	if (box_sequence_current(seq_id, &result) != 0)
+		luaT_error(L);
+	luaL_pushint64(L, result);
+	return 1;
+}
+
 static int
 lbox_sequence_set(struct lua_State *L)
 {
@@ -174,6 +185,7 @@ box_lua_sequence_init(struct lua_State *L)
 {
 	static const struct luaL_Reg sequence_internal_lib[] = {
 		{"next", lbox_sequence_next},
+		{"current", lbox_sequence_current},
 		{"set", lbox_sequence_set},
 		{"reset", lbox_sequence_reset},
 		{NULL, NULL}
diff --git a/test/box/sequence.result b/test/box/sequence.result
index 0a6cfee2c..5a4cc8153 100644
--- a/test/box/sequence.result
+++ b/test/box/sequence.result
@@ -2289,3 +2289,35 @@ box.space._space_sequence:update({s.id}, {{'=', 2, t[2]}})
 s:drop()
 ---
 ...
+--
+-- gh-4752 current value of sequence
+--
+sq = box.schema.sequence.create('test')
+---
+...
+sq:current()
+---
+- error: Sequence is not initialized yet
+...
+sq:next()
+---
+- 1
+...
+sq:current()
+---
+- 1
+...
+sq:set(42)
+---
+...
+sq:current()
+---
+- 42
+...
+sq:current()
+---
+- 42
+...
+sq:drop()
+---
+...
diff --git a/test/box/sequence.test.lua b/test/box/sequence.test.lua
index 8e00571e5..54011225e 100644
--- a/test/box/sequence.test.lua
+++ b/test/box/sequence.test.lua
@@ -780,3 +780,15 @@ pk = s:create_index('pk', {sequence = true})
 t = box.space._space_sequence:get({s.id})
 box.space._space_sequence:update({s.id}, {{'=', 2, t[2]}})
 s:drop()
+
+--
+-- gh-4752 current value of sequence
+--
+sq = box.schema.sequence.create('test')
+sq:current()
+sq:next()
+sq:current()
+sq:set(42)
+sq:current()
+sq:current()
+sq:drop()
-- 
2.23.0

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [Tarantool-patches] [PATCH 1/2] box: introduce internal sequence error
  2020-03-06 11:46 ` [Tarantool-patches] [PATCH 1/2] box: introduce internal sequence error olegrok
@ 2020-03-06 12:55   ` Nikita Pettik
  2020-03-06 16:37     ` Oleg Babin
  0 siblings, 1 reply; 6+ messages in thread
From: Nikita Pettik @ 2020-03-06 12:55 UTC (permalink / raw)
  To: olegrok; +Cc: Oleg Babin, tarantool-patches, v.shpilevoy

On 06 Mar 14:46, olegrok@tarantool.org wrote:
> From: Oleg Babin <babinoleg@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)

Why do you need separate type class for this error?
All sequence errors are of ClientError class, so why
don't you simply use it? Otherwise, it would be nice
to make all sequence related errors be of SequenceError class.
 
> 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
> 

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [Tarantool-patches] [PATCH 2/2] box: introduce "current" for sequence
  2020-03-06 11:46 ` [Tarantool-patches] [PATCH 2/2] box: introduce "current" for sequence olegrok
@ 2020-03-06 13:00   ` Nikita Pettik
  0 siblings, 0 replies; 6+ messages in thread
From: Nikita Pettik @ 2020-03-06 13:00 UTC (permalink / raw)
  To: olegrok; +Cc: Oleg Babin, tarantool-patches, v.shpilevoy

On 06 Mar 14:46, olegrok@tarantool.org wrote:
> From: Oleg Babin <babinoleg@mail.ru>
> 
> diff --git a/test/box/sequence.test.lua b/test/box/sequence.test.lua
> index 8e00571e5..54011225e 100644
> --- a/test/box/sequence.test.lua
> +++ b/test/box/sequence.test.lua
> @@ -780,3 +780,15 @@ pk = s:create_index('pk', {sequence = true})
>  t = box.space._space_sequence:get({s.id})
>  box.space._space_sequence:update({s.id}, {{'=', 2, t[2]}})
>  s:drop()
> +
> +--
> +-- gh-4752 current value of sequence
> +--

Nit: please, write a bit more informative comments. For instance:

--
-- gh-4752: introduce sequence:current() method which
-- fetches current sequence value but doesn't modify
-- sequence itself.
--

> +sq = box.schema.sequence.create('test')
> +sq:current()
> +sq:next()
> +sq:current()
> +sq:set(42)
> +sq:current()
> +sq:current()
> +sq:drop()
> -- 
> 2.23.0
> 

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [Tarantool-patches] [PATCH 1/2] box: introduce internal sequence error
  2020-03-06 12:55   ` Nikita Pettik
@ 2020-03-06 16:37     ` Oleg Babin
  0 siblings, 0 replies; 6+ messages in thread
From: Oleg Babin @ 2020-03-06 16:37 UTC (permalink / raw)
  To: Nikita Pettik; +Cc: Oleg Babin, tarantool-patches, v.shpilevoy

Thanks for your review!
I've sent the second version of this patch. Seems similar function 
existed untill 
https://github.com/tarantool/tarantool/commit/3ff1f1e36e14381c0ebb5862943d4da281254767

I've change an error type to ClientError and modified tests a bit.

On 06/03/2020 15:55, Nikita Pettik wrote:
> On 06 Mar 14:46, olegrok@tarantool.org wrote:
>> From: Oleg Babin <babinoleg@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)
> 
> Why do you need separate type class for this error?
> All sequence errors are of ClientError class, so why
> don't you simply use it? Otherwise, it would be nice
> to make all sequence related errors be of SequenceError class.
>   
>> 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
>>

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2020-03-06 16:37 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-03-06 11:46 [Tarantool-patches] [PATCH 0/2] Introcude sequence.current olegrok
2020-03-06 11:46 ` [Tarantool-patches] [PATCH 1/2] box: introduce internal sequence error olegrok
2020-03-06 12:55   ` Nikita Pettik
2020-03-06 16:37     ` Oleg Babin
2020-03-06 11:46 ` [Tarantool-patches] [PATCH 2/2] box: introduce "current" for sequence olegrok
2020-03-06 13:00   ` Nikita Pettik

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox