如何返回带有SELECT元组的表?

问题描述

tarantool-cartridge。 呼叫者功能

local function http_redirections(req)
    log.info("-- redirections started")

    local b_id = tostring(req)
    local bucket_id = vshard.router.bucket_id_mpcrc32(b_id)
    log.info("-- bucket_id: %s",bucket_id)
    local answer,error = err_vshard_router:pcall(
        vshard.router.call,bucket_id,'read','redirections'
    )

    for k,v in pairs(answer) do log.info(" http: key: %s value: %s",k,v) end
end

处理程序:

local function redirections(req)
    log.info("-- redirections handler started")
    local response = {}
    local answer = {}
    response = Box.space.space_name:select()
    for k,v in pairs(response) do answer[k] = v end
    for k,v in pairs(answer) do log.info("key: %s value: %s",v) end
    log.info("-- response size: %d",#answer)
    return answer
end

产生调用函数http: key: 1 value: table: 0x418e3d10 http: key: 2 value 处理程序OK中的结果:key = select()中的值。为什么表中的表返回到调用函数

解决方法

简而言之,您没有任何合法方法可以通过netbox / vshard调用返回元组。

它如何工作:

-- You have a tuple
tuple = box.tuple.new({1,2,3})
tarantool> box.tuple.is(tuple) -- It's tuple,cdata object
---
- true
...
-- In order to transfer your tuple via network you need convert
-- them to binary form
msgpack = require('msgpack')
tarantool> msgpack.encode(tuple)
---
- !!binary kwECAw==
...
-- But you don't know after that it was a tuple or simple lua table
tarantool> msgpack.encode({1,3}) -- The same,but input is a lua table
---
- !!binary kwECAw==
...
-- After receive you need to decode you tuple/table back to lua object
tarantool> msgpack.decode(msgpack.encode({1,3}))
---
- [1,3]
- 5
...

tarantool> msgpack.decode(msgpack.encode(tuple))
---
- [1,3]
- 5
...
tarantool> box.tuple.is(msgpack.decode(msgpack.encode(tuple)))
---
- false
...

但是,如果您使用连接,则可以直接调用“选择/插入/ ...”功能。 从Tarantool 2.2开始,这样的元组甚至具有格式。有关详细信息,请参见issue

box.cfg{listen = 3302}
box.schema.user.grant('guest','read,write,execute','space')
box.schema.user.grant('guest','create','space')

box.schema.create_space("named",{format = {{name = "id"}}})
box.space.named:create_index('id',{parts = {{1,'unsigned'}}})
box.space.named:insert({1})
require('net.box').connect('localhost',3302).space.named:get(1).id

Result:

tarantool> require('net.box').connect('localhost',3302).space.named:get(1).id
---
- 1
...

如果需要将lua表转换为元组,可以使用box.tuple.new()函数。但这将是没有格式的元组。

tarantool> tbl = {1,3}
---
...

tarantool> box.tuple.is(tbl)
---
- false
...

tarantool> tuple = box.tuple.new(tbl)
---
...

tarantool> box.tuple.is(tuple)
---
- true
...

在这里,我应该结束我的回答。但是您有从网箱调用中返回格式化元组的非法方法。

netbox = require('net.box')
netboxlib = require('net.box.lib')
buffer = require('buffer')
msgpackffi = require('msgpackffi')
msgpack = require('msgpack')
ffi = require('ffi')

box.cfg{listen = 3301}
box.schema.user.passwd('admin','test')

s = box.schema.space.create('test')
s:format({{name = 'id',type = 'string'},{name = 'value',type = 'string'}})
s:create_index('pk')
s:replace({'key','value'})
c = netbox.connect('admin:test@localhost:3301')
function get()
    return s:select()
end

call_buffer = buffer.ibuf()
c:call('get',{},{buffer = call_buffer,skip_header = true})
len,call_buffer.rpos = msgpack.decode_array_header(call_buffer.rpos,call_buffer:size())
buf = buffer.ibuf()
encode_fix = msgpackffi.internal.encode_fix
encode_r = msgpackffi.internal.encode_r
encode_fix(buf,0x80,1)
encode_r(buf,0x30,1)
wpos = buf:alloc(call_buffer:size())
ffi.copy(wpos,call_buffer.rpos,call_buffer:size())

tarantool> netboxlib.decode_select(buf.rpos,nil,c.space.test._format_cdata)
---
- - ['key','value']
- 'cdata<char *>: 0x010586803e'
...
tarantool> tuples = netboxlib.decode_select(buf.rpos,c.space.test._format_cdata)
---
...

tarantool> tuples 
---
- - ['key','value']
...

tarantool> tuples[1]
---
- ['key','value']
...

tarantool> tuples[1]:tomap()
---
- 1: key
  2: value
  value: value
  id: key
...

此代码自Tarantool 2.2起可用,由于使用了一些内部Tarantool函数,将来很容易被破坏。我不建议您使用它们。 希望在this问题解决后,将其更改。