接口
连接
连接用于访问数据库的大多数功能。当调用用户定义函数(UDF)时,数据库连接已作为预定义变量 con 建立。当使用脚本或控制台时,必须调用 connect() 函数来显式建立连接。connect() 函数的参数是一个具有指定键的表。根据其参数,此函数可以连接到本地数据库、远程 RSQL 数据库或分布式数据库。
示例
以下代码片段创建了一个本地内存(IM)数据库(在进程中)并连接到它。
db = create("luadb", devices, dbparams)
c = connect{db=db}
以下命令将创建一个名为 testdb
的 IM 数据库,其大小为 100Mb,页面大小为 512 字节。(参数 pagesize
可以省略,因为其默认值为 256 字节)。
c = connect{dbname=”testdb”, dbsize=100*1024*1024, pagesize=512}
以下命令将连接到位于同一台机器上端口 5000 的远程 xSQL 服务器。
c = connect{host=”localhost”, port=5000}
以下命令将创建一个连接到 2 个分片的分布式连接。
c = connect{nodes={"localhost:5000", "localhost:5001"}}
连接支持以下附加参数:
- nReplicas: HA副本个数
- maxConnectAttempts:尝试连接的次数
- connectTimeout:连接超时时间
- sql_login:安全登录名
- sql_password:安全密码
运行SQL查询
一旦建立了连接,我们就可以使用该连接执行语句和查询。语句不会从数据库返回数据,而查询会。以下是一个语句的示例:
con:statement("create table MyTable (pk int, value string)")
这可以从用户定义函数(UDF)中运行,也可以作为脚本运行。 为了能够从查询中检索数据,函数 con:query() 会返回一个游标对象。游标对象允许对其内容进行迭代,并返回以行形式表示的数据。这些行是 Lua 表,形式为键=值,其中键是列名,值是对应的行值。
以下是一个游标迭代的示例:
for row in con:query("select pk,value from MyTable"):tuples() do
return print row.pk, row.value
end
向 SQL 查询传递参数
在 SmartESQL 中,您可以通过查询或语句传递参数。SmartESQL 的 Lua 接口基于 C++ SQL API,使用 LuaJIT FFI 来绑定和传递参数。所有参数以“%”形式指定,并直接传递,不进行额外的检查或处理。
请注意以下几点:
- 参数值以 FFI 数据类型传递。
- 传递参数存在一定的风险,因为没有额外的安全检查。FFI 将参数转换为低级 C 兼容的数据结构,如果参数或类型指定错误,可能会导致未定义行为,如服务器崩溃、数据损坏或丢失。
我们建议您在传递参数时格外小心,确保参数格式正确,以避免潜在的问题。
以下是一个传递参数的示例:
for row in con:query("select k from t where i=%i", ffi.new("int", i)):tuples() do
return row.k
end
支持的格式说明符及其对应的 FFI 表达式列于下表:
格式符 | SmartEDB类型 | FFI 表达式 |
---|---|---|
%b | bool | ffi.new("bool", true) |
%i | int | ffi.new("int", 1) |
%i8 | int64_t | ffi.new("int64_t", 1000000000000) |
%u | unsigned | ffi.new("unsigned", 2) |
%l | int64_t | ffi.new("int64_t", 1000000000000) |
%L | integer value, passed as double | Native Lua type, a lua value can be passed. 123456 |
%I1 | Array of 1 byte integers. size_t,int8_t* | 2 values expected – size and an array. Array is passed as zero-based, while lua array is 1-based, so actual size of allocated array should be size+1 ffi.new('size_t', 3), ffi.new('int8_t[4]', {1,2,3}) |
%I2 | Array of 2-byte integers. size_t,int16_t* | Same as above. ffi.new('size_t', 3), ffi.new('int16_t[4]', {1,2,3}) |
%I4 | Array of 4-byte integers. size_t,int32_t* | Same as above. ffi.new('size_t', 3), ffi.new('int32_t[4]', {1,2,3}) |
%I8 | Array of 8-byte integers. size_t,int64_t* | Same as above. ffi.new('size_t', 3), ffi.new('int64_t[4]', {1,2,3}) |
%U1 | Array of 1-byte unsigned integers. size_t,uint8_t* | ffi.new('size_t', 3), ffi.new('uint8_t[4]', {1,2,3}) |
%U2 | Array of 2-byte unsigned integers. size_t,uint16_t* | Same as above. ffi.new('size_t', 3), ffi.new('uint16_t[4]', {1,2,3}) |
%U4 | Array of 4-byte unsigned integers. size_t,uint32_t* | Same as above. ffi.new('size_t', 3), ffi.new('uint32_t[4]', {1,2,3}) |
%U8 | Array of 8-byte unsigned integers. size_t,uint64_t* | Same as above. ffi.new('size_t', 3), ffi.new('uint64_t[4]', {1,2,3}) |
%F4 | Array of floats. size_t,float* | Same as above. ffi.new('size_t', 3), ffi.new('float[4]', {1,2,3}) |
%F8 | Array of doubles. size_t,double* | Same as above. ffi.new('size_t', 3), ffi.new('double[4]', {1,2,3}) |
%A | size_t nElems, size_t elemSize, char* body | |
%f | double | ffi.new("double", 10.1) or just Lua numeric value – 10.1 |
%t | mco_datetime . This is an internal representation of datetime , represented as uint64_t | ffi.new("uint64_t", ticks) |
%s | char* , but Lua string is properly converted | 'hello world' |
查询行
函数 query_row() 返回一个仅含一行的结果集表。
句法
row = con:query_row (sql_query, params1, param2, ... paramN, no_data_hdl, too_many_rows_hdl)
示例
假设我们有以下表格和数据:
create table Employee(
name char(25) primary key,
dept_no unsigned(2)
);
INSERT INTO Employee(name, dept_no) VALUES (['Luke Skywalker', 'Han Solo', 'Darth Vader'], [1,1,2])
我们可以编写以下的 Lua 代码:
local row = con:query_row("select name, dept_no from Employee order by name limit 1")
local name, dept_no = row.name, row.dept_no
print ("Values returned: ", name, dept_no)
这段代码将会输出:
Values returned: Darth Vader 2
注意:此函数专门用于需要获取恰好一行数据的情况。因此,如果查询返回多行或零行数据,query_row()
将分别尝试调用通过 too_many_rows_hdl
或 no_data_hdl
可选参数传递的处理程序。如果未提供相应的处理程序,则会调用 lua_error
(详情请参阅 pcall())。
local row = con:query_row(
"select name, dept_no from Employee order by name limit 1",
-- No data
function ( )
.....
end,
-- TOO_MANY_ROWS
function ()
.....
end
)