Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

moteus/lua-odbc

Open more actions menu

Repository files navigation

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

odbc = require "odbc"
dbassert = odbc.assert

cnn = odbc.connect('EmptyDB')
cnn:setautocommit(false)
stmt = cnn:prepare("insert into test_table(f1, f2) values(?, ?)")
f1 = stmt:vbind_param_ulong(1)
for i = 1, 5 do
  f1:set(i)          -- just set data
  stmt:bindnum(2, i) -- each time call SQLBindParameter
  dbassert(stmt:execute())
end
dbassert( cnn:commit() )

Select resultset

odbc = require "odbc"
dbassert = odbc.assert

cnn = odbc.connect('EmptyDB')

stmt = cnn:execute('select f1, f2 from test_table order by 1')
stmt:foreach(function(f1, f2)
  if f1 == 2 then return true end
end)
assert(stmt:closed()) -- foreach close cursor 
assert(not stmt:destroyed()) -- statement valid

stmt:execute('select f1, f2 from test_table order by 1')
f1, f2 = stmt:fetch()

Input/Output parameters

odbc = require "odbc"
dbassert = odbc.assert
cnn = odbc.connect('EmptyDB')

stmt = dbassert(cnn:prepare("{?= call dba.fn_test(?)}"))
ret  = stmt:vbind_param_ulong(1, ret, odbc.PARAM_OUTPUT)
val  = stmt:vbind_param_char(2, "hello") -- default odbc.PARAM_INPUT
dbassert(stmt:execute())
print(ret:get())

stmt:reset()
stmt:vbind_col(1, ret)
dbassert(stmt:execute('select 321'))
stmt:vfetch()
print(ret:get())

Use async mode

local odbc = require "odbc"
local dbassert = odbc.assert

cnn = odbc.connect('EmptyDB')

stmt = cnn:prepare('select f1, f2 from test_table order by 1')
local f1 = stmt:vbind_col_ulong(1)
local f2 = stmt:vbind_col_ulong(2)

stmt:setasyncmode(true)

local COUNTER = 0

function async(stmt, f, ...)
  while true do
    local ok, err = f(stmt, ...)
    if ok ~= 'timeout' then return ok, err end
    COUNTER = COUNTER + 1
  end
end

dbassert(async(stmt, stmt.execute))
while(async(stmt, stmt.vfetch))do
  print(f1:get(),f2:get())
end

print("execute counter:", COUNTER)

Use C API

static void luaX_call_method(lua_State *L, const char *name, int nargs, int nresults){
  int obj_index = -nargs - 1;
  lua_getfield(L, obj_index, name);
  lua_insert(L, obj_index - 1);
  return lua_call(L, nargs + 1, nresults);
}

static int odbc_first_row_impl(lua_State *L){
  SQLHSTMT *pstmt = (SQLHSTMT *)lua_touserdata(L, lua_upvalueindex(1));

  lua_settop(L, 1); // sql

  // wrap existed handle to lua object
  lodbc_statement(L, *pstmt, 0);      // sql, stmt
  lua_insert(L, 1); lua_insert(L, 1); // stmt, sql

  luaX_call_method(L, "execute", 1, 2); // [nil/stmt], [err/nil]

  // here we should check error and ether execute return recordset

  lua_pop(L, 1); //stmt
  luaX_call_method(L, "fetch", 0, LUA_MULTRET);

  return lua_gettop(L);
}

static int odbc_first_row(lua_State *L){
  int res;
  { // this is may be cpp scope (we can use RAII)
    // get existed handle from somewhere(e.g. prepared pool)
    SQLHSTMT hstmt = ... 

    lua_pushlightuserdata(L, &hstmt);
    lua_pushcclosure(L, odbc_first_row_impl, 1);
    lua_insert(L, 1);

    res = lua_pcall(L, lua_gettop(L)-1, LUA_MULTRET, 0);

    // cleanup
  }
  if(res) return lua_error(L);
  return lua_gettop(L);
}

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

odbc.dba module

Implementaion of dba API

Bitdeli Badge

About

ODBC Library for lua

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Contributors 2

  •  
  •  
Morty Proxy This is a proxified and sanitized view of the page, visit original site.