项目作者: moteus

项目描述 :
ODBC Library for lua
高级语言: C
项目地址: git://github.com/moteus/lua-odbc.git
创建时间: 2012-10-23T08:10:59Z
项目社区:https://github.com/moteus/lua-odbc

开源协议:MIT License

下载


ODBC library for Lua 5.1/5.2

Licence
Build Status
Coverage Status

Supports

  • prepared query
  • bind parameters (input/output)
  • bind column
  • async mode for statements
  • catalog functions
  • luasql compatable module
  • C API to create Lua object based on existed ODBC handle

Known issues

  • assert method rise error as object.
    This works fine on Lua > 5.1 and on LuaJIT but on Lua 5.1 it results message as
    lua.exe: (error object is not a string). But it allows wrap code
    in pcall function and handle errors as object(with access to SQLCODE and SQLSTATE).
    To change this behavior set -DLODBC_ASSERT_TOSTRING flag in compile time.

Usage

Insert multiple rows

  1. odbc = require "odbc"
  2. dbassert = odbc.assert
  3. cnn = odbc.connect('EmptyDB')
  4. cnn:setautocommit(false)
  5. stmt = cnn:prepare("insert into test_table(f1, f2) values(?, ?)")
  6. f1 = stmt:vbind_param_ulong(1)
  7. for i = 1, 5 do
  8. f1:set(i) -- just set data
  9. stmt:bindnum(2, i) -- each time call SQLBindParameter
  10. dbassert(stmt:execute())
  11. end
  12. dbassert( cnn:commit() )

Select resultset

  1. odbc = require "odbc"
  2. dbassert = odbc.assert
  3. cnn = odbc.connect('EmptyDB')
  4. stmt = cnn:execute('select f1, f2 from test_table order by 1')
  5. stmt:foreach(function(f1, f2)
  6. if f1 == 2 then return true end
  7. end)
  8. assert(stmt:closed()) -- foreach close cursor
  9. assert(not stmt:destroyed()) -- statement valid
  10. stmt:execute('select f1, f2 from test_table order by 1')
  11. f1, f2 = stmt:fetch()

Input/Output parameters

  1. odbc = require "odbc"
  2. dbassert = odbc.assert
  3. cnn = odbc.connect('EmptyDB')
  4. stmt = dbassert(cnn:prepare("{?= call dba.fn_test(?)}"))
  5. ret = stmt:vbind_param_ulong(1, ret, odbc.PARAM_OUTPUT)
  6. val = stmt:vbind_param_char(2, "hello") -- default odbc.PARAM_INPUT
  7. dbassert(stmt:execute())
  8. print(ret:get())
  9. stmt:reset()
  10. stmt:vbind_col(1, ret)
  11. dbassert(stmt:execute('select 321'))
  12. stmt:vfetch()
  13. print(ret:get())

Use async mode

  1. local odbc = require "odbc"
  2. local dbassert = odbc.assert
  3. cnn = odbc.connect('EmptyDB')
  4. stmt = cnn:prepare('select f1, f2 from test_table order by 1')
  5. local f1 = stmt:vbind_col_ulong(1)
  6. local f2 = stmt:vbind_col_ulong(2)
  7. stmt:setasyncmode(true)
  8. local COUNTER = 0
  9. function async(stmt, f, ...)
  10. while true do
  11. local ok, err = f(stmt, ...)
  12. if ok ~= 'timeout' then return ok, err end
  13. COUNTER = COUNTER + 1
  14. end
  15. end
  16. dbassert(async(stmt, stmt.execute))
  17. while(async(stmt, stmt.vfetch))do
  18. print(f1:get(),f2:get())
  19. end
  20. print("execute counter:", COUNTER)

Use C API

  1. static void luaX_call_method(lua_State *L, const char *name, int nargs, int nresults){
  2. int obj_index = -nargs - 1;
  3. lua_getfield(L, obj_index, name);
  4. lua_insert(L, obj_index - 1);
  5. return lua_call(L, nargs + 1, nresults);
  6. }
  7. static int odbc_first_row_impl(lua_State *L){
  8. SQLHSTMT *pstmt = (SQLHSTMT *)lua_touserdata(L, lua_upvalueindex(1));
  9. lua_settop(L, 1); // sql
  10. // wrap existed handle to lua object
  11. lodbc_statement(L, *pstmt, 0); // sql, stmt
  12. lua_insert(L, 1); lua_insert(L, 1); // stmt, sql
  13. luaX_call_method(L, "execute", 1, 2); // [nil/stmt], [err/nil]
  14. // here we should check error and ether execute return recordset
  15. lua_pop(L, 1); //stmt
  16. luaX_call_method(L, "fetch", 0, LUA_MULTRET);
  17. return lua_gettop(L);
  18. }
  19. static int odbc_first_row(lua_State *L){
  20. int res;
  21. { // this is may be cpp scope (we can use RAII)
  22. // get existed handle from somewhere(e.g. prepared pool)
  23. SQLHSTMT hstmt = ...
  24. lua_pushlightuserdata(L, &hstmt);
  25. lua_pushcclosure(L, odbc_first_row_impl, 1);
  26. lua_insert(L, 1);
  27. res = lua_pcall(L, lua_gettop(L)-1, LUA_MULTRET, 0);
  28. // cleanup
  29. }
  30. if(res) return lua_error(L);
  31. return lua_gettop(L);
  32. }

And from Lua we can call this function just like ... = odbc.first_row("select ...")

odbc.dba module

Implementaion of dba API

Bitdeli Badge