--------------------------------------------------------------------- -- LuaSQL JDBC driver implementation -- @author Thiago Ponte --------------------------------------------------------------------- --------------------------------------------------------------------- -- luasql table name --------------------------------------------------------------------- local libName = "luasql" local LUASQL_PREFIX = "LuaSQL: " local Private = {} luasql = type(_G[libName]) == "table" and _G[libName] or {} Private.createJavaCursor = luajava.loadLib("org.keplerproject.luasql.jdbc.LuaSQLCursor", "open") luasql._COPYRIGHT = "Copyright (C) 2003-2006 Kepler Project" luasql._DESCRIPTION = "LuaSQL is a simple interface from Lua to a DBMS" luasql._VERSION = "LuaSQL 2.0.2" --------------------------------------------------------------------- -- function that returns a jdbc environment --------------------------------------------------------------------- function luasql.jdbc(driver) if driver == nil then return nil, "Error. Argument #1 must be the jdbc driver class." end local cond, err = pcall(luajava.bindClass, driver) if not cond then return nil, err end return Private.createEnv() end --------------------------------------------------------------------- -- creates a jdbc environment --------------------------------------------------------------------- function Private.createEnv() local isClosed = false local openConns = {} openConns.n = 0 local env = {} local function closeConn(con) if not openConns[con] then return false end openConns[con] = nil openConns.n = openConns.n - 1 return true end function env:close() -- For compatibility with other drivers if type(self) ~= "table" then error(LUASQL_PREFIX.."environment expected") end if isClosed or openConns.n ~= 0 then return false end isClosed = true return true end function env:connect(sourcename, username, password) -- For compatibility with other drivers if type(self) ~= "table" then error(LUASQL_PREFIX.."environment expected") end if isClosed then error(LUASQL_PREFIX.."environment is closed") --return nil, "Environment closed." end if sourcename == nil then return nil, "Invalid sourcename." end local driverManager = luajava.bindClass("java.sql.DriverManager") local cond, con if username == nil and password == nil then cond, con = pcall(driverManager.getConnection, driverManager, sourcename) else cond, con = pcall(driverManager.getConnection, driverManager, sourcename, username or '', password or '') end if not cond then return nil, con end openConns[con] = true openConns.n = openConns.n + 1 return Private.createConnection(con, closeConn) end -- For compatibility with other drivers setmetatable(env, {__metatable = LUASQL_PREFIX.."you're not allowed to get this metatable"}) return env end --------------------------------------------------------------------- -- creates a jdbc connection --------------------------------------------------------------------- function Private.createConnection(conObj, closeFunc) local openCursors = {} openCursors.n = 0 local con = {} local function closeCursor(cursor) if not openCursors[cursor] then return false end openCursors[cursor] = nil openCursors.n = openCursors.n - 1 end function con:close() -- For compatibility with other drivers if type(self) ~= "table" then error(LUASQL_PREFIX.."connection expected") end if conObj:isClosed() or openCursors.n ~= 0 then return false end conObj:close() closeFunc(conObj) return true end function con:commit() -- For compatibility with other drivers if type(self) ~= "table" then error(LUASQL_PREFIX.."connection expected") end local cond, err = pcall(conObj.commit, conObj) if not cond then return nil, err end end function con:execute(sql) if conObj:isClosed() then error(LUASQL_PREFIX.."connection is closed") end -- For compatibility with other drivers if type(self) ~= "table" then error(LUASQL_PREFIX.."connection expected") end local st = conObj:createStatement() local cond, isRS = pcall(st.execute, st, sql) if not cond then return nil, isRS end local res; if isRS then res = Private.createCursor(st:getResultSet(), st, closeCursor, con) openCursors[res] = true openCursors.n = openCursors.n + 1 else res = st:getUpdateCount() st:close(); end return res end function con:rollback() -- For compatibility with other drivers if type(self) ~= "table" then error(LUASQL_PREFIX.."connection expected") end local cond, err = pcall(conObj.rollback, conObj) if not cond then return nil, err end end function con:setautocommit(bool) -- For compatibility with other drivers if type(self) ~= "table" then error(LUASQL_PREFIX.."connection expected") end local cond, err = pcall(conObj.setAutoCommit, conObj, bool) if not cond then return nil, err end end -- For compatibility with other drivers setmetatable(con, {__metatable = LUASQL_PREFIX.."you're not allowed to get this metatable"}) return con end --------------------------------------------------------------------- -- creates a jdbc cursor --------------------------------------------------------------------- function Private.createCursor(rs, st, closeFunc, con) local isClosed = false local cursor = Private.createJavaCursor(rs) local res = {} local names local types res._con = con function res:close() -- For compatibility with other drivers if type(self) ~= "table" then error(LUASQL_PREFIX.."cursor expected") end if isClosed then return false end rs:close() st:close() closeFunc(res) isClosed = true return true end function res:fetch(tb, modestring) -- For compatibility with other drivers if type(self) ~= "table" then error(LUASQL_PREFIX.."cursor expected") end if tb == nil or type(tb) ~= "table" then tb = {} local cond, tb = pcall(cursor.fetch, cursor, tb, "n") if not cond then error(LUASQ_PREFIX.."error fetching result") end if tb then return unpack(tb) else return nil end end if modestring == nil or type(modestring) ~= "string" then modestring = "n" end local cond, tb = pcall(cursor.fetch, cursor, tb, modestring) if not cond then return nil, tb end return tb end function res:getcolnames() -- For compatibility with other drivers if type(self) ~= "table" then error(LUASQL_PREFIX.."cursor expected") end if names then return names end local cond, tb = pcall (cursor.getcolnames, cursor) if not cond then return cond, tb end names = tb return tb end function res:getcoltypes() -- For compatibility with other drivers if type(self) ~= "table" then error(LUASQL_PREFIX.."cursor expected") end if types then return types end local cond, tb = pcall(cursor.getcoltypes, cursor) if not cond then return nil, tb end types = tb return tb end -- For compatibility with other drivers setmetatable(res, {__metatable = LUASQL_PREFIX.."you're not allowed to get this metatable"}) return res end