Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

C stored function works different when called locally and remotely #4799

Closed
Gerold103 opened this issue Mar 8, 2020 · 4 comments
Closed
Assignees
Labels
3.0 Target is 3.0 and all newer release/master branches app breaking change bug Something isn't working

Comments

@Gerold103
Copy link
Collaborator

Example. Run this from tarantool sources root folder:

box.cfg{listen = 3313}
box.schema.user.grant('guest', 'super')
build_path = '/Users/gerold/Work/Repositories/tarantool'
package.cpath = build_path..'/test/box/?.so;'..build_path..'/test/box/?.dylib;'..package.cpath

box.schema.func.create('function1.multireturn', {language = "C", exports = {'LUA'}})

c = require('net.box').connect(box.cfg.listen)
c:call('function1.multireturn')
---
- [[1], [1]]
...
box.func['function1.multireturn']:call()
---
- [1]
- [1]
...

Result of the function depends on from where it was called. When I call a Lua function, it returns the same result regardless of how I call it.
I don't know what a behaviour is correct - return an array in both cases, or multireturn. Seems like C functions always returned an array, because there was no other way to call them except via netbox, until box.func was introduced. I don't know. But behaviour should be at least the same.

@Gerold103 Gerold103 added bug Something isn't working app labels Mar 8, 2020
@MariaHajdic MariaHajdic self-assigned this Jun 2, 2020
MariaHajdic added a commit that referenced this issue Jun 15, 2020
C stored function always returns an array. Local call introduced
with box.func used to convert resulting array to multireturn in
contrast to netbox call that serializes it to a tuple.
This patch makes resulting behavior consistent by making the local
call always return a tuple as well.

Closes #4799
@kyukhin kyukhin added this to the wishlist milestone Sep 16, 2020
@Korablev77 Korablev77 self-assigned this Mar 11, 2021
@Korablev77
Copy link
Contributor

It does not concern only C stored functions - Lua ones show the same bevaiour. Setup:

box.cfg{listen = 3301}
nb = require('net.box')
cn = nb:connect(3301)
box.execute('create table t(id int primary key)')
box.space.T:insert({1})
box.space.T:insert({2})
box.space.T:insert({3})
function foo() return 1, 2, 3 end
function select() return box.space.T:select() end
function replace() return box.space.T:replace({3}) end
box.schema.user.grant('guest', 'super')

Local calls:

tarantool> foo()
---
- 1
- 2
- 3
...

tarantool> select()
---
- - [1]
  - [2]
  - [3]
...

tarantool> replace()
---
- [3]
...

Remote calls:

tarantool> cn:call('select')
---
- [[1], [2], [3]]
...

tarantool> cn:call('replace')
---
- [3]
...

tarantool> cn:call('foo')
---
- 1
- 2
- 3
...
tarantool> cn.space.T:select()
---
- - [1]
  - [2]
  - [3]
...

As one can see, result for select() different for local and remote calls. However, there's special (legacy) call16, which emulates local behaviour:

tarantool> cn:call_16('select')
---
- - [1]
  - [2]
  - [3]
...

I have no idea why current call replaced call_16, but it looks like we shouldn't touch it...

@Korablev77 Korablev77 removed their assignment Mar 17, 2021
@Gerold103
Copy link
Collaborator Author

No, I am not talking about calling Lua functions as variables. I am talking about working with registered functions using box API: box.func. If you will call your examples using box.func.foo/box.func.select/..., you will see it works like netbox call. But if the function is defined in C, it works different. This is inconsistency, because it should not depend on the language.

@NeraverinTarantool
Copy link

We will check this issue after #7000

@kyukhin kyukhin removed this from the wishlist milestone Jun 17, 2022
@Mons Mons added the 3.0 Target is 3.0 and all newer release/master branches label Feb 7, 2023
@TarantoolBot TarantoolBot removed the teamP label Jun 7, 2023
@gmoshkin
Copy link
Contributor

I had to investigate this behavior twice now, so I'll just keep a record of what I found here:

Implementation details

struct port

When the stored procedure is called if it has any return values those are stored
in a struct port helper struct which has different implementation for
different types of stored procedures.

LUA stored procedures have struct port_lua which stores a reference to a lua
state where the return values are stored on the stack.

FFI stored procedures have struct port_c which contains a linked list of
entries each of which stores a msgpack value.

And to extract values from that port a table of virtual methods is used with
different methods for different contexts.

box.schema.func.call

In case when the proc is called via box.schema.func.call (see lbox_func_call
in box/lua/call.c), the port.port_vtab->dump_lua is called, which pushes the
return values onto the lua stack of the caller. So in case of port_lua the
values are simply copied from one stack to another (see port_lua_dump_lua) and
in case of port_c the msgpack values from the linked list are decoded and
pushed to the stack one after another (see port_c_dump_lua).

IPROTO_CALL

When the proc is called via IPROTO_CALL (see tx_process_call), the result is
encoded as a IPROTO_RESPONSE, which consists of an IPROTO_HEADER (see
iproto_header_encode) and a body which is just a msgpack map with key
IRPOTO_DATA (0x30) and value -- a msgpack array. This msgpack array is
generated by calling port.port_vtab->dump_msgpack which encodes the elements
of the array and returns count the length of the array.

So in case of a LUA stored proc (see port_lua_dump -> encode_lua_call) the
return values are encoded to msgpack one after another and the resulting
count is the number of lua values returned.

But in case of an FFI stored proc (see port_c_dump_msgpack) the entries of
port_c are encoded into a msgpack array and the resulting count is
explicitly 1.

This effectively means that when calling an FFI stored proc the
result values are always explicitly wrapped into a msgpack array of length 1.

Buristan added a commit to Buristan/tarantool that referenced this issue Sep 14, 2023
With this option enabled (new), the multiresults returned by a stored C
function via iproto aren't wrapped in the additional msgpack array (old).

The reason is the usage of `port_dump_msgpack()` for SQL processing in
`tx_process_sql()` and inside `iproto_session_push()`. So, global changes
in `port_c_dump_msgpack()` (or on port creation) require some syncing
with the aforementioned routines too. Hence, the new
`port_c_unwrap_multireturn()` routine is introduced to check when we
don't need to wrap the results in the additional msgpack array.

Needed for tarantool#4799

@TarantoolBot document
Title: Document `c_func_iproto_multireturn` compat option

Please create a documentation page for the new compat option:
https://tarantool.io/compat/c_func_iproto_multireturn

In the new behaviour, the multiresults returned by a stored C function
via iproto aren't wrapped in the additional msgpack array (old).

```hl
tarantool> compat.c_func_iproto_multireturn = 'old'
---
...

tarantool> net_box.connect(box.cfg.listen):call('myclib.cfunc')
---
- [true, -1]
...

tarantool> compat.c_func_iproto_multireturn = 'new'
---
...

tarantool> net_box.connect(box.cfg.listen):call('myclib.cfunc')
---
- true
- -1
...

```

The new behaviour is consistent with the local call of the function
via `box.func`:

```hl
tarantool> box.func['myclib.cfunc']:call()
---
- true
- -1
...

```

Assume you have a stored C function that returns values like the
following:

```c
char *position = mp_encode_bool(buffer, true);
box_return_mp(ctx, buffer, position);
/* ... */
position = mp_encode_int(buffer, -1);
box_return_mp(ctx, buffer, position);
```

If you want to preserve the format of the returned array for your C
functions, when the `c_func_iproto_multireturn` option is set to "new",
you should add the additional wrapping, like the following:

```c
char *position = mp_encode_array(buffer_with_results, n_results);
position = mp_encode_bool(position, true);
/* ... */
position = mp_encode_int(position, -1);
box_return_mp(ctx, buffer_with_results, position);
```

Also, you should update its usage via `box.func` if there is any.
Buristan added a commit to Buristan/tarantool that referenced this issue Sep 14, 2023
This patch sets the aforementioned option to new. This is a breaking
change that makes the behaviour of the stored C functions called locally
and remotely via iproto consistent.

Closes tarantool#4799
Relates to tarantool#8576

NO_DOC=see previous commit
Buristan added a commit to Buristan/tarantool that referenced this issue Sep 14, 2023
With this option enabled (new), the multiresults returned by a stored C
function via iproto aren't wrapped in the additional msgpack array (old).

The reason is the usage of `port_dump_msgpack()` for SQL processing in
`tx_process_sql()` and inside `iproto_session_push()`. So, global changes
in `port_c_dump_msgpack()` (or on port creation) require some syncing
with the aforementioned routines too. Hence, the new
`port_c_unwrap_multireturn()` routine is introduced to check when we
don't need to wrap the results in the additional msgpack array.

Needed for tarantool#4799

@TarantoolBot document
Title: Document `c_func_iproto_multireturn` compat option

Please create a documentation page for the new compat option:
https://tarantool.io/compat/c_func_iproto_multireturn

In the new behaviour, the multiresults returned by a stored C function
via iproto aren't wrapped in the additional msgpack array (old).

```hl
tarantool> compat.c_func_iproto_multireturn = 'old'
---
...

tarantool> net_box.connect(box.cfg.listen):call('myclib.cfunc')
---
- [true, -1]
...

tarantool> compat.c_func_iproto_multireturn = 'new'
---
...

tarantool> net_box.connect(box.cfg.listen):call('myclib.cfunc')
---
- true
- -1
...

```

The new behaviour is consistent with the local call of the function
via `box.func`:

```hl
tarantool> box.func['myclib.cfunc']:call()
---
- true
- -1
...

```

Assume you have a stored C function that returns values like the
following:

```c
char *position = mp_encode_bool(buffer, true);
box_return_mp(ctx, buffer, position);
/* ... */
position = mp_encode_int(buffer, -1);
box_return_mp(ctx, buffer, position);
```

If you want to preserve the format of the returned array for your C
functions, when the `c_func_iproto_multireturn` option is set to "new",
you should add the additional wrapping, like the following:

```c
char *position = mp_encode_array(buffer_with_results, n_results);
position = mp_encode_bool(position, true);
/* ... */
position = mp_encode_int(position, -1);
box_return_mp(ctx, buffer_with_results, position);
```

Also, you should update its usage via `box.func` if there is any.

(cherry picked from commit df59e65)
Buristan added a commit to Buristan/tarantool that referenced this issue Sep 14, 2023
With this option enabled (new), the multiresults returned by a stored C
function via iproto aren't wrapped in the additional msgpack array (old).

The reason is the usage of `port_dump_msgpack()` for SQL processing in
`tx_process_sql()` and inside `iproto_session_push()`. So, global changes
in `port_c_dump_msgpack()` (or on port creation) require some syncing
with the aforementioned routines too. Hence, the new
`port_c_unwrap_multireturn()` routine is introduced to check when we
don't need to wrap the results in the additional msgpack array.

Needed for tarantool#4799

@TarantoolBot document
Title: Document `c_func_iproto_multireturn` compat option

Please create a documentation page for the new compat option:
https://tarantool.io/compat/c_func_iproto_multireturn

In the new behaviour, the multiresults returned by a stored C function
via iproto aren't wrapped in the additional msgpack array (old).

```
tarantool> compat.c_func_iproto_multireturn = 'old'
---
...

tarantool> net_box.connect(box.cfg.listen):call('myclib.cfunc')
---
- [true, -1]
...

tarantool> compat.c_func_iproto_multireturn = 'new'
---
...

tarantool> net_box.connect(box.cfg.listen):call('myclib.cfunc')
---
- true
- -1
...

```

The new behaviour is consistent with the local call of the function
via `box.func`:

```
tarantool> box.func['myclib.cfunc']:call()
---
- true
- -1
...

```

Assume you have a stored C function that returns values like the
following:

```c
char *position = mp_encode_bool(buffer, true);
box_return_mp(ctx, buffer, position);
/* ... */
position = mp_encode_int(buffer, -1);
box_return_mp(ctx, buffer, position);
```

If you want to preserve the format of the returned array for your C
functions, when the `c_func_iproto_multireturn` option is set to "new",
you should add the additional wrapping, like the following:

```c
char *position = mp_encode_array(buffer_with_results, n_results);
position = mp_encode_bool(position, true);
/* ... */
position = mp_encode_int(position, -1);
box_return_mp(ctx, buffer_with_results, position);
```

Also, you should update its usage via `box.func` if there is any.
Buristan added a commit to Buristan/tarantool that referenced this issue Sep 14, 2023
This patch sets the aforementioned option to new. This is a breaking
change that makes the behaviour of the stored C functions called locally
and remotely via iproto consistent.

Closes tarantool#4799
Relates to tarantool#8576

NO_DOC=see previous commit
Buristan added a commit to Buristan/tarantool that referenced this issue Sep 14, 2023
With this option enabled (new), the multiresults returned by a stored C
function via iproto aren't wrapped in the additional msgpack array (old).

The reason is the usage of `port_dump_msgpack()` for SQL processing in
`tx_process_sql()` and inside `iproto_session_push()`. So, global changes
in `port_c_dump_msgpack()` (or on port creation) require some syncing
with the aforementioned routines too. Hence, the new
`port_c_unwrap_multireturn()` routine is introduced to check when we
don't need to wrap the results in the additional msgpack array.

Needed for tarantool#4799

@TarantoolBot document
Title: Document `c_func_iproto_multireturn` compat option

Please create a documentation page for the new compat option:
https://tarantool.io/compat/c_func_iproto_multireturn

In the new behaviour, the multiresults returned by a stored C function
via iproto aren't wrapped in the additional msgpack array (old).

```
tarantool> compat.c_func_iproto_multireturn = 'old'
---
...

tarantool> net_box.connect(box.cfg.listen):call('myclib.cfunc')
---
- [true, -1]
...

tarantool> compat.c_func_iproto_multireturn = 'new'
---
...

tarantool> net_box.connect(box.cfg.listen):call('myclib.cfunc')
---
- true
- -1
...

```

The new behaviour is consistent with the local call of the function
via `box.func`:

```
tarantool> box.func['myclib.cfunc']:call()
---
- true
- -1
...

```

Assume you have a stored C function that returns values like the
following:

```c
char *position = mp_encode_bool(buffer, true);
box_return_mp(ctx, buffer, position);
/* ... */
position = mp_encode_int(buffer, -1);
box_return_mp(ctx, buffer, position);
```

If you want to preserve the format of the returned array for your C
functions, when the `c_func_iproto_multireturn` option is set to "new",
you should add the additional wrapping, like the following:

```c
char *position = mp_encode_array(buffer_with_results, n_results);
position = mp_encode_bool(position, true);
/* ... */
position = mp_encode_int(position, -1);
box_return_mp(ctx, buffer_with_results, position);
```

Also, you should update its usage via `box.func` if there is any.

(cherry picked from commit df59e65)
Buristan added a commit to Buristan/tarantool that referenced this issue Sep 14, 2023
With this option enabled (new), the multiresults returned by a stored C
function via iproto aren't wrapped in the additional msgpack array (old).

The reason is the usage of `port_dump_msgpack()` for SQL processing in
`tx_process_sql()` and inside `iproto_session_push()`. So, global changes
in `port_c_dump_msgpack()` (or on port creation) require some syncing
with the aforementioned routines too. Hence, the new
`port_c_unwrap_multireturn()` routine is introduced to check when we
don't need to wrap the results in the additional msgpack array.

Needed for tarantool#4799

@TarantoolBot document
Title: Document `c_func_iproto_multireturn` compat option

Please create a documentation page for the new compat option:
https://tarantool.io/compat/c_func_iproto_multireturn

In the new behaviour, the multiresults returned by a stored C function
via iproto aren't wrapped in the additional msgpack array (old).

```
tarantool> compat.c_func_iproto_multireturn = 'old'
---
...

tarantool> net_box.connect(box.cfg.listen):call('myclib.cfunc')
---
- [true, -1]
...

tarantool> compat.c_func_iproto_multireturn = 'new'
---
...

tarantool> net_box.connect(box.cfg.listen):call('myclib.cfunc')
---
- true
- -1
...

```

The new behaviour is consistent with the local call of the function
via `box.func`:

```
tarantool> box.func['myclib.cfunc']:call()
---
- true
- -1
...

```

Assume you have a stored C function that returns values like the
following:

```c
char *position = mp_encode_bool(buffer, true);
box_return_mp(ctx, buffer, position);
/* ... */
position = mp_encode_int(buffer, -1);
box_return_mp(ctx, buffer, position);
```

If you want to preserve the format of the returned array for your C
functions, when the `c_func_iproto_multireturn` option is set to "new",
you should add the additional wrapping, like the following:

```c
char *position = mp_encode_array(buffer_with_results, n_results);
position = mp_encode_bool(position, true);
/* ... */
position = mp_encode_int(position, -1);
box_return_mp(ctx, buffer_with_results, position);
```

Also, you should update its usage via `box.func` if there is any.

(cherry picked from commit 4a27779)
Buristan added a commit to Buristan/tarantool that referenced this issue Sep 14, 2023
With this option enabled (new), the multiresults returned by a stored C
function via iproto aren't wrapped in the additional msgpack array (old).

The reason is the usage of `port_dump_msgpack()` for SQL processing in
`tx_process_sql()` and inside `iproto_session_push()`. So, global changes
in `port_c_dump_msgpack()` (or on port creation) require some syncing
with the aforementioned routines too. Hence, the new
`port_c_unwrap_multireturn()` routine is introduced to check when we
don't need to wrap the results in the additional msgpack array.

Needed for tarantool#4799

@TarantoolBot document
Title: Document `c_func_iproto_multireturn` compat option

Please create a documentation page for the new compat option:
https://tarantool.io/compat/c_func_iproto_multireturn

In the new behaviour, the multiresults returned by a stored C function
via iproto aren't wrapped in the additional msgpack array (old).

```
tarantool> compat.c_func_iproto_multireturn = 'old'
---
...

tarantool> net_box.connect(box.cfg.listen):call('myclib.cfunc')
---
- [true, -1]
...

tarantool> compat.c_func_iproto_multireturn = 'new'
---
...

tarantool> net_box.connect(box.cfg.listen):call('myclib.cfunc')
---
- true
- -1
...

```

The new behaviour is consistent with the local call of the function
via `box.func`:

```
tarantool> box.func['myclib.cfunc']:call()
---
- true
- -1
...

```

Assume you have a stored C function that returns values like the
following:

```c
char *position = mp_encode_bool(buffer, true);
box_return_mp(ctx, buffer, position);
/* ... */
position = mp_encode_int(buffer, -1);
box_return_mp(ctx, buffer, position);
```

If you want to preserve the format of the returned array for your C
functions, when the `c_func_iproto_multireturn` option is set to "new",
you should add the additional wrapping, like the following:

```c
char *position = mp_encode_array(buffer_with_results, n_results);
position = mp_encode_bool(position, true);
/* ... */
position = mp_encode_int(position, -1);
box_return_mp(ctx, buffer_with_results, position);
```

Also, you should update its usage via `box.func` if there is any.
Buristan added a commit to Buristan/tarantool that referenced this issue Sep 14, 2023
This patch sets the aforementioned option to new. This is a breaking
change that makes the behaviour of the stored C functions called locally
and remotely via iproto consistent.

Closes tarantool#4799
Relates to tarantool#8576

NO_DOC=see previous commit
Buristan added a commit to Buristan/tarantool that referenced this issue Sep 14, 2023
With this option enabled (new), the multiresults returned by a stored C
function via iproto aren't wrapped in the additional msgpack array (old).

The reason is the usage of `port_dump_msgpack()` for SQL processing in
`tx_process_sql()` and inside `iproto_session_push()`. So, global changes
in `port_c_dump_msgpack()` (or on port creation) require some syncing
with the aforementioned routines too. Hence, the new
`port_c_unwrap_multireturn()` routine is introduced to check when we
don't need to wrap the results in the additional msgpack array.

Needed for tarantool#4799

@TarantoolBot document
Title: Document `c_func_iproto_multireturn` compat option

Please create a documentation page for the new compat option:
https://tarantool.io/compat/c_func_iproto_multireturn

In the new behaviour, the multiresults returned by a stored C function
via iproto aren't wrapped in the additional msgpack array (old).

```
tarantool> compat.c_func_iproto_multireturn = 'old'
---
...

tarantool> net_box.connect(box.cfg.listen):call('myclib.cfunc')
---
- [true, -1]
...

tarantool> compat.c_func_iproto_multireturn = 'new'
---
...

tarantool> net_box.connect(box.cfg.listen):call('myclib.cfunc')
---
- true
- -1
...

```

The new behaviour is consistent with the local call of the function
via `box.func`:

```
tarantool> box.func['myclib.cfunc']:call()
---
- true
- -1
...

```

Assume you have a stored C function that returns values like the
following:

```c
char *position = mp_encode_bool(buffer, true);
box_return_mp(ctx, buffer, position);
/* ... */
position = mp_encode_int(buffer, -1);
box_return_mp(ctx, buffer, position);
```

If you want to preserve the format of the returned array for your C
functions, when the `c_func_iproto_multireturn` option is set to "new",
you should add the additional wrapping, like the following:

```c
char *position = mp_encode_array(buffer_with_results, n_results);
position = mp_encode_bool(position, true);
/* ... */
position = mp_encode_int(position, -1);
box_return_mp(ctx, buffer_with_results, position);
```

Also, you should update its usage via `box.func` if there is any.
Buristan added a commit to Buristan/tarantool that referenced this issue Sep 14, 2023
This patch sets the aforementioned option to new. This is a breaking
change that makes the behaviour of the stored C functions called locally
and remotely via iproto consistent.

Closes tarantool#4799
Relates to tarantool#8576

NO_DOC=see previous commit
Buristan added a commit to Buristan/tarantool that referenced this issue Sep 14, 2023
With this option enabled (new), the multiresults returned by a stored C
function via iproto aren't wrapped in the additional msgpack array (old).

The reason is the usage of `port_dump_msgpack()` for SQL processing in
`tx_process_sql()` and inside `iproto_session_push()`. So, global changes
in `port_c_dump_msgpack()` (or on port creation) require some syncing
with the aforementioned routines too. Hence, the new
`port_c_unwrap_multireturn()` routine is introduced to check when we
don't need to wrap the results in the additional msgpack array.

Needed for tarantool#4799

@TarantoolBot document
Title: Document `c_func_iproto_multireturn` compat option

Please create a documentation page for the new compat option:
https://tarantool.io/compat/c_func_iproto_multireturn

In the new behaviour, the multiresults returned by a stored C function
via iproto aren't wrapped in the additional msgpack array (old).

```
tarantool> compat.c_func_iproto_multireturn = 'old'
---
...

tarantool> net_box.connect(box.cfg.listen):call('myclib.cfunc')
---
- [true, -1]
...

tarantool> compat.c_func_iproto_multireturn = 'new'
---
...

tarantool> net_box.connect(box.cfg.listen):call('myclib.cfunc')
---
- true
- -1
...

```

The new behaviour is consistent with the local call of the function
via `box.func`:

```
tarantool> box.func['myclib.cfunc']:call()
---
- true
- -1
...

```

Assume you have a stored C function that returns values like the
following:

```c
char *position = mp_encode_bool(buffer, true);
box_return_mp(ctx, buffer, position);
/* ... */
position = mp_encode_int(buffer, -1);
box_return_mp(ctx, buffer, position);
```

If you want to preserve the format of the returned array for your C
functions, when the `c_func_iproto_multireturn` option is set to "new",
you should add the additional wrapping, like the following:

```c
char *position = mp_encode_array(buffer_with_results, n_results);
position = mp_encode_bool(position, true);
/* ... */
position = mp_encode_int(position, -1);
box_return_mp(ctx, buffer_with_results, position);
```

Also, you should update its usage via `box.func` if there is any.

(cherry picked from commit 1e15260)
Buristan added a commit to Buristan/tarantool that referenced this issue Sep 14, 2023
With this option enabled (new), the multiresults returned by a stored C
function via iproto aren't wrapped in the additional msgpack array (old).

The reason is the usage of `port_dump_msgpack()` for SQL processing in
`tx_process_sql()` and inside `iproto_session_push()`. So, global changes
in `port_c_dump_msgpack()` (or on port creation) require some syncing
with the aforementioned routines too. Hence, the new
`port_c_unwrap_multireturn()` routine is introduced to check when we
don't need to wrap the results in the additional msgpack array.

Needed for tarantool#4799

@TarantoolBot document
Title: Document `c_func_iproto_multireturn` compat option

Please create a documentation page for the new compat option:
https://tarantool.io/compat/c_func_iproto_multireturn

In the new behaviour, the multiresults returned by a stored C function
via iproto aren't wrapped in the additional msgpack array (old).

```
tarantool> compat.c_func_iproto_multireturn = 'old'
---
...

tarantool> net_box.connect(box.cfg.listen):call('myclib.cfunc')
---
- [true, -1]
...

tarantool> compat.c_func_iproto_multireturn = 'new'
---
...

tarantool> net_box.connect(box.cfg.listen):call('myclib.cfunc')
---
- true
- -1
...

```

The new behaviour is consistent with the local call of the function
via `box.func`:

```
tarantool> box.func['myclib.cfunc']:call()
---
- true
- -1
...

```

Assume you have a stored C function that returns values like the
following:

```c
char *position = mp_encode_bool(buffer, true);
box_return_mp(ctx, buffer, position);
/* ... */
position = mp_encode_int(buffer, -1);
box_return_mp(ctx, buffer, position);
```

If you want to preserve the format of the returned array for your C
functions, when the `c_func_iproto_multireturn` option is set to "new",
you should add the additional wrapping, like the following:

```c
char *position = mp_encode_array(buffer_with_results, n_results);
position = mp_encode_bool(position, true);
/* ... */
position = mp_encode_int(position, -1);
box_return_mp(ctx, buffer_with_results, position);
```

Also, you should update its usage via `box.func` if there is any.
@kyukhin kyukhin assigned Buristan and unassigned unera Sep 15, 2023
Buristan added a commit to Buristan/tarantool that referenced this issue Sep 19, 2023
With this option enabled (new), the multiresults returned by a stored C
function via iproto aren't wrapped in the additional msgpack array (old).

Due to new behaviour some renames are performed:
* `port_c_dump_msgpack()` -> `port_c_dump_msgpack_sql()`, since this is
  dump format used in the SQL ports, see `port_sql_dump_msgpack()` in
  the  <src/box/sql/port.c>
* `port_c_dump_msgpack16()` -> `port_c_dump_msgpack()`, since this
  format is now the default new format of a msgpack dump.

The behaviour of the C port msgpack dumping depends on the
`c_func_iproto_multireturn` option:
* uses `port_c_dump_msgpack()` if set to true (new),
* uses `port_c_dump_msgpack_sql()` otherwise (old).

Needed for tarantool#4799

@TarantoolBot document
Title: Document `c_func_iproto_multireturn` compat option

Please create a documentation page for the new compat option:
https://tarantool.io/compat/c_func_iproto_multireturn

In the new behaviour, the multiresults returned by a stored C function
via iproto aren't wrapped in the additional msgpack array (old).

```
tarantool> compat.c_func_iproto_multireturn = 'old'
---
...

tarantool> net_box.connect(box.cfg.listen):call('myclib.cfunc')
---
- [true, -1]
...

tarantool> compat.c_func_iproto_multireturn = 'new'
---
...

tarantool> net_box.connect(box.cfg.listen):call('myclib.cfunc')
---
- true
- -1
...

```

The new behaviour is consistent with the local call of the function
via `box.func`:

```
tarantool> box.func['myclib.cfunc']:call()
---
- true
- -1
...

```

Assume you have a stored C function that returns values like the
following:

```c
char *position = mp_encode_bool(buffer, true);
box_return_mp(ctx, buffer, position);
/* ... */
position = mp_encode_int(buffer, -1);
box_return_mp(ctx, buffer, position);
```

If you want to preserve the format of the returned array for your C
functions, when the `c_func_iproto_multireturn` option is set to "new",
you should add the additional wrapping, like the following:

```c
char *position = mp_encode_array(buffer_with_results, n_results);
position = mp_encode_bool(position, true);
/* ... */
position = mp_encode_int(position, -1);
box_return_mp(ctx, buffer_with_results, position);
```

The amount of `box_return_mp()` calls indicates the number of values to
be returned.

Also, you should update its usage via `box.func` if there is any.
Buristan added a commit to Buristan/tarantool that referenced this issue Sep 19, 2023
This patch sets the aforementioned option to new. This is a breaking
change that makes the behaviour of the stored C functions called locally
and remotely via iproto consistent.

Closes tarantool#4799
Relates to tarantool#8576

NO_DOC=see previous commit
Buristan added a commit to Buristan/tarantool that referenced this issue Sep 19, 2023
With this option enabled (new), the multiresults returned by a stored C
function via iproto aren't wrapped in the additional msgpack array (old).

Due to new behaviour some renames are performed:
* `port_c_dump_msgpack()` -> `port_c_dump_msgpack_sql()`, since this is
  dump format used in the SQL ports, see `port_sql_dump_msgpack()` in
  the  <src/box/sql/port.c>
* `port_c_dump_msgpack16()` -> `port_c_dump_msgpack()`, since this
  format is now the default new format of a msgpack dump.

The behaviour of the C port msgpack dumping depends on the
`c_func_iproto_multireturn` option:
* uses `port_c_dump_msgpack()` if set to true (new),
* uses `port_c_dump_msgpack_sql()` otherwise (old).

Needed for tarantool#4799

@TarantoolBot document
Title: Document `c_func_iproto_multireturn` compat option

Please create a documentation page for the new compat option:
https://tarantool.io/compat/c_func_iproto_multireturn

In the new behaviour, the multiresults returned by a stored C function
via iproto aren't wrapped in the additional msgpack array (old).

```
tarantool> compat.c_func_iproto_multireturn = 'old'
---
...

tarantool> net_box.connect(box.cfg.listen):call('myclib.cfunc')
---
- [true, -1]
...

tarantool> compat.c_func_iproto_multireturn = 'new'
---
...

tarantool> net_box.connect(box.cfg.listen):call('myclib.cfunc')
---
- true
- -1
...

```

The new behaviour is consistent with the local call of the function
via `box.func`:

```
tarantool> box.func['myclib.cfunc']:call()
---
- true
- -1
...

```

Assume you have a stored C function that returns values like the
following:

```c
char *position = mp_encode_bool(buffer, true);
box_return_mp(ctx, buffer, position);
/* ... */
position = mp_encode_int(buffer, -1);
box_return_mp(ctx, buffer, position);
```

If you want to preserve the format of the returned array for your C
functions, when the `c_func_iproto_multireturn` option is set to "new",
you should add the additional wrapping, like the following:

```c
char *position = mp_encode_array(buffer_with_results, n_results);
position = mp_encode_bool(position, true);
/* ... */
position = mp_encode_int(position, -1);
box_return_mp(ctx, buffer_with_results, position);
```

The amount of `box_return_mp()` calls indicates the number of values to
be returned.

Also, you should update its usage via `box.func` if there is any.
Buristan added a commit to Buristan/tarantool that referenced this issue Sep 19, 2023
With this option enabled (new), the multiresults returned by a stored C
function via iproto aren't wrapped in the additional msgpack array (old).

Due to new behaviour some renames are performed:
* `port_c_dump_msgpack()` -> `port_c_dump_msgpack_sql()`, since this is
  dump format used in the SQL ports, see `port_sql_dump_msgpack()` in
  the  <src/box/sql/port.c>
* `port_c_dump_msgpack16()` -> `port_c_dump_msgpack()`, since this
  format is now the default new format of a msgpack dump.

The behaviour of the C port msgpack dumping depends on the
`c_func_iproto_multireturn` option:
* uses `port_c_dump_msgpack()` if set to true (new),
* uses `port_c_dump_msgpack_sql()` otherwise (old).

Needed for tarantool#4799

@TarantoolBot document
Title: Document `c_func_iproto_multireturn` compat option

Please create a documentation page for the new compat option:
https://tarantool.io/compat/c_func_iproto_multireturn

In the new behaviour, the multiresults returned by a stored C function
via iproto aren't wrapped in the additional msgpack array (old).

```
tarantool> compat.c_func_iproto_multireturn = 'old'
---
...

tarantool> net_box.connect(box.cfg.listen):call('myclib.cfunc')
---
- [true, -1]
...

tarantool> compat.c_func_iproto_multireturn = 'new'
---
...

tarantool> net_box.connect(box.cfg.listen):call('myclib.cfunc')
---
- true
- -1
...

```

The new behaviour is consistent with the local call of the function
via `box.func`:

```
tarantool> box.func['myclib.cfunc']:call()
---
- true
- -1
...

```

Assume you have a stored C function that returns values like the
following:

```c
char *position = mp_encode_bool(buffer, true);
box_return_mp(ctx, buffer, position);
/* ... */
position = mp_encode_int(buffer, -1);
box_return_mp(ctx, buffer, position);
```

If you want to preserve the format of the returned array for your C
functions, when the `c_func_iproto_multireturn` option is set to "new",
you should add the additional wrapping, like the following:

```c
char *position = mp_encode_array(buffer_with_results, n_results);
position = mp_encode_bool(position, true);
/* ... */
position = mp_encode_int(position, -1);
box_return_mp(ctx, buffer_with_results, position);
```

The amount of `box_return_mp()` calls indicates the number of values to
be returned.

Also, you should update its usage via `box.func` if there is any.
Buristan added a commit to Buristan/tarantool that referenced this issue Sep 19, 2023
This patch sets the aforementioned option to new. This is a breaking
change that makes the behaviour of the stored C functions called locally
and remotely via iproto consistent.

Closes tarantool#4799
Relates to tarantool#8576

NO_DOC=see previous commit
Buristan added a commit to Buristan/tarantool that referenced this issue Sep 19, 2023
With this option enabled (new), the multiresults returned by a stored C
function via iproto aren't wrapped in the additional msgpack array (old).

Due to new behaviour some renames are performed:
* `port_c_dump_msgpack()` -> `port_c_dump_msgpack_sql()`, since this is
  dump format used in the SQL ports, see `port_sql_dump_msgpack()` in
  the  <src/box/sql/port.c>
* `port_c_dump_msgpack16()` -> `port_c_dump_msgpack()`, since this
  format is now the default new format of a msgpack dump.

The behaviour of the C port msgpack dumping depends on the
`c_func_iproto_multireturn` option:
* uses `port_c_dump_msgpack()` if set to true (new),
* uses `port_c_dump_msgpack_sql()` otherwise (old).

Needed for tarantool#4799

@TarantoolBot document
Title: Document `c_func_iproto_multireturn` compat option

Please create a documentation page for the new compat option:
https://tarantool.io/compat/c_func_iproto_multireturn

In the new behaviour, the multiresults returned by a stored C function
via iproto aren't wrapped in the additional msgpack array (old).

```
tarantool> compat.c_func_iproto_multireturn = 'old'
---
...

tarantool> net_box.connect(box.cfg.listen):call('myclib.cfunc')
---
- [true, -1]
...

tarantool> compat.c_func_iproto_multireturn = 'new'
---
...

tarantool> net_box.connect(box.cfg.listen):call('myclib.cfunc')
---
- true
- -1
...

```

The new behaviour is consistent with the local call of the function
via `box.func`:

```
tarantool> box.func['myclib.cfunc']:call()
---
- true
- -1
...

```

Assume you have a stored C function that returns values like the
following:

```c
char *position = mp_encode_bool(buffer, true);
box_return_mp(ctx, buffer, position);
/* ... */
position = mp_encode_int(buffer, -1);
box_return_mp(ctx, buffer, position);
```

If you want to preserve the format of the returned array for your C
functions, when the `c_func_iproto_multireturn` option is set to "new",
you should add the additional wrapping, like the following:

```c
char *position = mp_encode_array(buffer_with_results, n_results);
position = mp_encode_bool(position, true);
/* ... */
position = mp_encode_int(position, -1);
box_return_mp(ctx, buffer_with_results, position);
```

The amount of `box_return_mp()` calls indicates the number of values to
be returned.

Also, you should update its usage via `box.func` if there is any.
Buristan added a commit to Buristan/tarantool that referenced this issue Sep 20, 2023
With this option enabled (new), the multiresults returned by a stored C
function via iproto aren't wrapped in the additional msgpack array (old).

Due to new behaviour some renames are performed:
* `port_c_dump_msgpack()` -> `port_c_dump_msgpack_wrapped()`, since this
  is dump format with additional msgpack array encoded.
* `port_c_dump_msgpack16()` -> `port_c_dump_msgpack()`, since this
  format is now the default new format of a msgpack dump.

The behaviour of the C port msgpack dumping depends on the
`c_func_iproto_multireturn` option:
* uses `port_c_dump_msgpack()` if set to true (new),
* uses `port_c_dump_msgpack_wrapped()` otherwise (old).

Needed for tarantool#4799

@TarantoolBot document
Title: Document `c_func_iproto_multireturn` compat option

Please create a documentation page for the new compat option:
https://tarantool.io/compat/c_func_iproto_multireturn

In the new behaviour, the multiresults returned by a stored C function
via iproto aren't wrapped in the additional msgpack array (old).

```
tarantool> compat.c_func_iproto_multireturn = 'old'
---
...

tarantool> net_box.connect(box.cfg.listen):call('myclib.cfunc')
---
- [true, -1]
...

tarantool> compat.c_func_iproto_multireturn = 'new'
---
...

tarantool> net_box.connect(box.cfg.listen):call('myclib.cfunc')
---
- true
- -1
...

```

The new behaviour is consistent with the local call of the function
via `box.func`:

```
tarantool> box.func['myclib.cfunc']:call()
---
- true
- -1
...

```

Assume you have a stored C function that returns values like the
following:

```c
char *position = mp_encode_bool(buffer, true);
box_return_mp(ctx, buffer, position);
/* ... */
position = mp_encode_int(buffer, -1);
box_return_mp(ctx, buffer, position);
```

If you want to preserve the format of the returned array for your C
functions, when the `c_func_iproto_multireturn` option is set to "new",
you should add the additional wrapping, like the following:

```c
char *position = mp_encode_array(buffer_with_results, n_results);
position = mp_encode_bool(position, true);
/* ... */
position = mp_encode_int(position, -1);
box_return_mp(ctx, buffer_with_results, position);
```

The amount of `box_return_mp()` calls indicates the number of values to
be returned.

Also, you should update its usage via `box.func` if there is any.
Buristan added a commit to Buristan/tarantool that referenced this issue Sep 20, 2023
This patch sets the aforementioned option to new. This is a breaking
change that makes the behaviour of the stored C functions called locally
and remotely via iproto consistent.

Closes tarantool#4799
Relates to tarantool#8576

NO_DOC=see previous commit
Buristan added a commit to Buristan/tarantool that referenced this issue Sep 20, 2023
With this option enabled (new), the multiresults returned by a stored C
function via iproto aren't wrapped in the additional msgpack array (old).

Due to new behaviour some renames are performed:
* `port_c_dump_msgpack()` -> `port_c_dump_msgpack_wrapped()`, since this
  is dump format with additional msgpack array encoded.
* `port_c_dump_msgpack16()` -> `port_c_dump_msgpack()`, since this
  format is now the default new format of a msgpack dump.

The behaviour of the C port msgpack dumping depends on the
`c_func_iproto_multireturn` option:
* uses `port_c_dump_msgpack()` if set to true (new),
* uses `port_c_dump_msgpack_wrapped()` otherwise (old).

Needed for tarantool#4799

@TarantoolBot document
Title: Document `c_func_iproto_multireturn` compat option

Please create a documentation page for the new compat option:
https://tarantool.io/compat/c_func_iproto_multireturn

In the new behaviour, the multiresults returned by a stored C function
via iproto aren't wrapped in the additional msgpack array (old).

```
tarantool> compat.c_func_iproto_multireturn = 'old'
---
...

tarantool> net_box.connect(box.cfg.listen):call('myclib.cfunc')
---
- [true, -1]
...

tarantool> compat.c_func_iproto_multireturn = 'new'
---
...

tarantool> net_box.connect(box.cfg.listen):call('myclib.cfunc')
---
- true
- -1
...

```

The new behaviour is consistent with the local call of the function
via `box.func`:

```
tarantool> box.func['myclib.cfunc']:call()
---
- true
- -1
...

```

Assume you have a stored C function that returns values like the
following:

```c
char *position = mp_encode_bool(buffer, true);
box_return_mp(ctx, buffer, position);
/* ... */
position = mp_encode_int(buffer, -1);
box_return_mp(ctx, buffer, position);
```

If you want to preserve the format of the returned array for your C
functions, when the `c_func_iproto_multireturn` option is set to "new",
you should add the additional wrapping, like the following:

```c
char *position = mp_encode_array(buffer_with_results, n_results);
position = mp_encode_bool(position, true);
/* ... */
position = mp_encode_int(position, -1);
box_return_mp(ctx, buffer_with_results, position);
```

The amount of `box_return_mp()` calls indicates the number of values to
be returned.

Also, you should update its usage via `box.func` if there is any.
igormunkin pushed a commit that referenced this issue Sep 28, 2023
With this option enabled (new), the multiresults returned by a stored C
function via iproto aren't wrapped in the additional msgpack array (old).

Due to new behaviour some renames are performed:
* `port_c_dump_msgpack()` -> `port_c_dump_msgpack_wrapped()`, since this
  is dump format with additional msgpack array encoded.
* `port_c_dump_msgpack16()` -> `port_c_dump_msgpack()`, since this
  format is now the default new format of a msgpack dump.

The behaviour of the C port msgpack dumping depends on the
`c_func_iproto_multireturn` option:
* uses `port_c_dump_msgpack()` if set to true (new),
* uses `port_c_dump_msgpack_wrapped()` otherwise (old).

Needed for #4799

@TarantoolBot document
Title: Document `c_func_iproto_multireturn` compat option

Please create a documentation page for the new compat option:
https://tarantool.io/compat/c_func_iproto_multireturn

In the new behaviour, the multiresults returned by a stored C function
via iproto aren't wrapped in the additional msgpack array (old).

```
tarantool> compat.c_func_iproto_multireturn = 'old'
---
...

tarantool> net_box.connect(box.cfg.listen):call('myclib.cfunc')
---
- [true, -1]
...

tarantool> compat.c_func_iproto_multireturn = 'new'
---
...

tarantool> net_box.connect(box.cfg.listen):call('myclib.cfunc')
---
- true
- -1
...

```

The new behaviour is consistent with the local call of the function
via `box.func`:

```
tarantool> box.func['myclib.cfunc']:call()
---
- true
- -1
...

```

Assume you have a stored C function that returns values like the
following:

```c
char *position = mp_encode_bool(buffer, true);
box_return_mp(ctx, buffer, position);
/* ... */
position = mp_encode_int(buffer, -1);
box_return_mp(ctx, buffer, position);
```

If you want to preserve the format of the returned array for your C
functions, when the `c_func_iproto_multireturn` option is set to "new",
you should add the additional wrapping, like the following:

```c
char *position = mp_encode_array(buffer_with_results, n_results);
position = mp_encode_bool(position, true);
/* ... */
position = mp_encode_int(position, -1);
box_return_mp(ctx, buffer_with_results, position);
```

The amount of `box_return_mp()` calls indicates the number of values to
be returned.

Also, you should update its usage via `box.func` if there is any.
igormunkin pushed a commit to Buristan/tarantool that referenced this issue Sep 28, 2023
With this option enabled (new), the multiresults returned by a stored C
function via iproto aren't wrapped in the additional msgpack array (old).

Due to new behaviour some renames are performed:
* `port_c_dump_msgpack()` -> `port_c_dump_msgpack_wrapped()`, since this
  is dump format with additional msgpack array encoded.
* `port_c_dump_msgpack16()` -> `port_c_dump_msgpack()`, since this
  format is now the default new format of a msgpack dump.

The behaviour of the C port msgpack dumping depends on the
`c_func_iproto_multireturn` option:
* uses `port_c_dump_msgpack()` if set to true (new),
* uses `port_c_dump_msgpack_wrapped()` otherwise (old).

Needed for tarantool#4799

@TarantoolBot document
Title: Document `c_func_iproto_multireturn` compat option

Please create a documentation page for the new compat option:
https://tarantool.io/compat/c_func_iproto_multireturn

In the new behaviour, the multiresults returned by a stored C function
via iproto aren't wrapped in the additional msgpack array (old).

```
tarantool> compat.c_func_iproto_multireturn = 'old'
---
...

tarantool> net_box.connect(box.cfg.listen):call('myclib.cfunc')
---
- [true, -1]
...

tarantool> compat.c_func_iproto_multireturn = 'new'
---
...

tarantool> net_box.connect(box.cfg.listen):call('myclib.cfunc')
---
- true
- -1
...

```

The new behaviour is consistent with the local call of the function
via `box.func`:

```
tarantool> box.func['myclib.cfunc']:call()
---
- true
- -1
...

```

Assume you have a stored C function that returns values like the
following:

```c
char *position = mp_encode_bool(buffer, true);
box_return_mp(ctx, buffer, position);
/* ... */
position = mp_encode_int(buffer, -1);
box_return_mp(ctx, buffer, position);
```

If you want to preserve the format of the returned array for your C
functions, when the `c_func_iproto_multireturn` option is set to "new",
you should add the additional wrapping, like the following:

```c
char *position = mp_encode_array(buffer_with_results, n_results);
position = mp_encode_bool(position, true);
/* ... */
position = mp_encode_int(position, -1);
box_return_mp(ctx, buffer_with_results, position);
```

The amount of `box_return_mp()` calls indicates the number of values to
be returned.

Also, you should update its usage via `box.func` if there is any.

(cherry picked from commit 96ee6d9)
igormunkin pushed a commit that referenced this issue Sep 28, 2023
With this option enabled (new), the multiresults returned by a stored C
function via iproto aren't wrapped in the additional msgpack array (old).

Due to new behaviour some renames are performed:
* `port_c_dump_msgpack()` -> `port_c_dump_msgpack_wrapped()`, since this
  is dump format with additional msgpack array encoded.
* `port_c_dump_msgpack16()` -> `port_c_dump_msgpack()`, since this
  format is now the default new format of a msgpack dump.

The behaviour of the C port msgpack dumping depends on the
`c_func_iproto_multireturn` option:
* uses `port_c_dump_msgpack()` if set to true (new),
* uses `port_c_dump_msgpack_wrapped()` otherwise (old).

Needed for #4799

@TarantoolBot document
Title: Document `c_func_iproto_multireturn` compat option

Please create a documentation page for the new compat option:
https://tarantool.io/compat/c_func_iproto_multireturn

In the new behaviour, the multiresults returned by a stored C function
via iproto aren't wrapped in the additional msgpack array (old).

```
tarantool> compat.c_func_iproto_multireturn = 'old'
---
...

tarantool> net_box.connect(box.cfg.listen):call('myclib.cfunc')
---
- [true, -1]
...

tarantool> compat.c_func_iproto_multireturn = 'new'
---
...

tarantool> net_box.connect(box.cfg.listen):call('myclib.cfunc')
---
- true
- -1
...

```

The new behaviour is consistent with the local call of the function
via `box.func`:

```
tarantool> box.func['myclib.cfunc']:call()
---
- true
- -1
...

```

Assume you have a stored C function that returns values like the
following:

```c
char *position = mp_encode_bool(buffer, true);
box_return_mp(ctx, buffer, position);
/* ... */
position = mp_encode_int(buffer, -1);
box_return_mp(ctx, buffer, position);
```

If you want to preserve the format of the returned array for your C
functions, when the `c_func_iproto_multireturn` option is set to "new",
you should add the additional wrapping, like the following:

```c
char *position = mp_encode_array(buffer_with_results, n_results);
position = mp_encode_bool(position, true);
/* ... */
position = mp_encode_int(position, -1);
box_return_mp(ctx, buffer_with_results, position);
```

The amount of `box_return_mp()` calls indicates the number of values to
be returned.

Also, you should update its usage via `box.func` if there is any.

(cherry picked from commit 96ee6d9)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
3.0 Target is 3.0 and all newer release/master branches app breaking change bug Something isn't working
Projects
None yet
Development

No branches or pull requests