Driver ADO, mudanas na documentao e nos testes para novo driver.
Modified Files: authors.html index.html manual.html test.lua Added Files: ado/ado.lua
This commit is contained in:
parent
81fd332056
commit
5619ae246b
@ -39,6 +39,13 @@ href="http://www.puc-rio.br/">PUC-Rio</a>. Consultant at <a href=
|
||||
|
||||
<dd>Programmer.</dd>
|
||||
|
||||
<dt>Fabio Mascarenhas</dt>
|
||||
|
||||
<dd>M.Sc. in Computer Science, <a href=
|
||||
"http://www.inf.puc-rio.br/">PUC-Rio</a>, 2004.</dd>
|
||||
|
||||
<dd>Programmer.</dd>
|
||||
|
||||
<dt>Eduardo Quintão</dt>
|
||||
|
||||
<dd>Programmer.</dd>
|
||||
|
10
index.html
10
index.html
@ -79,7 +79,7 @@
|
||||
<p>
|
||||
LuaSQL is a simple interface from Lua to a DBMS. It enables a Lua program to:
|
||||
<ul>
|
||||
<li> Connect to ODBC, Oracle, MySQL, SQLite, JDBC and PostgreSQL databases;</li>
|
||||
<li> Connect to ODBC, ADO, Oracle, MySQL, SQLite, JDBC, and PostgreSQL databases;</li>
|
||||
<li> Execute arbitrary SQL statements;</li>
|
||||
<li> Retrieve results in a row-by-row cursor fashion.</li>
|
||||
</ul>
|
||||
@ -101,6 +101,7 @@ and 4.1.
|
||||
The Oracle driver has been tested on Windows and is compatible with OCI 8 API.
|
||||
The SQLite driver had been tested on Linux and are compatible with versions 2.x.
|
||||
The JDBC driver has been tested with LuaJava Beta 3 and JDK 1.4 (MySQL driver).
|
||||
The ADO driver has been tested on Windows, with LuaCOM 1.3 (Microsoft Access driver).
|
||||
</p>
|
||||
|
||||
<a name=download></a>
|
||||
@ -170,6 +171,9 @@ In order to use LuaSQL over JDBC, make sure that:
|
||||
<li> JDBC driver of the desired database is also in the virtual machine classpath
|
||||
</ul>
|
||||
|
||||
<p>In order to use LuaSQL over ADO, make sure that Lua is running with
|
||||
<a href="http://www.tecgraf.puc-rio.br/~rcerq/luacom">LuaCOM 1.3</a></p>
|
||||
|
||||
|
||||
<a name="credits"></a>
|
||||
|
||||
@ -183,7 +187,7 @@ and Tomás Guisasola as part of the
|
||||
The implementation is compatible with Lua 5.0 and was coded by
|
||||
Tomás Guisasola, Eduardo Quintão and Thiago Ponte,
|
||||
with many invaluable contributions by Michael Roth, Tiago Dionisio,
|
||||
Leonardo Godinho and Danilo Tuler.
|
||||
Leonardo Godinho, Danilo Tuler, and Fabio Mascarenhas.
|
||||
|
||||
<h4>LuaSQL 1.0</h4>
|
||||
<p>
|
||||
@ -223,7 +227,7 @@ Comments are welcome!
|
||||
|
||||
<hr>
|
||||
<small>
|
||||
$Id: index.html,v 1.36 2004/12/22 15:27:56 tomas Exp $
|
||||
$Id: index.html,v 1.37 2005/02/28 19:48:10 mascarenhas Exp $
|
||||
</small>
|
||||
|
||||
</body>
|
||||
|
@ -52,8 +52,8 @@
|
||||
<p>
|
||||
LuaSQL is a simple interface from Lua to a DBMS.
|
||||
It has a collection of drivers to some popular databases
|
||||
(actually PostgreSQL, ODBC, JDBC, MySQL, SQLite and Oracle;
|
||||
ADO, Interbase and Sybase are on our plans).
|
||||
(actually PostgreSQL, ODBC, JDBC, MySQL, SQLite, Oracle, and ADO;
|
||||
Interbase and Sybase are on our plans).
|
||||
LuaSQL defines a simple object-oriented API.
|
||||
All drivers should implement this common API,
|
||||
but each one is free to offer extensions.
|
||||
@ -468,7 +468,7 @@ end
|
||||
|
||||
<hr>
|
||||
<small>
|
||||
$Id: manual.html,v 1.31 2005/02/17 14:37:19 carregal Exp $
|
||||
$Id: manual.html,v 1.32 2005/02/28 19:48:10 mascarenhas Exp $
|
||||
</small>
|
||||
|
||||
</body>
|
||||
|
345
src/ado/ado.lua
Normal file
345
src/ado/ado.lua
Normal file
@ -0,0 +1,345 @@
|
||||
---------------------------------------------------------------------
|
||||
-- ADO driver implemented using LuaCOM
|
||||
---------------------------------------------------------------------
|
||||
|
||||
require"luacom"
|
||||
|
||||
---------------------------------------------------------------------
|
||||
-- luasql table name
|
||||
---------------------------------------------------------------------
|
||||
local libName = "luasql"
|
||||
|
||||
local Private = {}
|
||||
|
||||
luasql = (_G[libName] and type(_G[libName]) == "table") or {}
|
||||
|
||||
local ADOTypes = {}
|
||||
|
||||
do
|
||||
local conn = luacom.CreateObject("ADODB.Connection")
|
||||
local typeinfo = luacom.GetTypeInfo(conn)
|
||||
local typelib = typeinfo:GetTypeLib()
|
||||
local enums = typelib:ExportEnumerations()
|
||||
for k, v in pairs(enums.DataTypeEnum) do
|
||||
ADOTypes[k] = v
|
||||
ADOTypes[v] = k
|
||||
end
|
||||
end
|
||||
|
||||
local metatable = {
|
||||
__metatable = "LuaSQL: you're not allowed to get this metatable"
|
||||
}
|
||||
|
||||
---------------------------------------------------------------------
|
||||
-- function that returns an ADO environment
|
||||
---------------------------------------------------------------------
|
||||
function luasql.ado()
|
||||
local isClosed = false
|
||||
local openConns = {}
|
||||
openConns.n = 0
|
||||
|
||||
local env = {}
|
||||
|
||||
setmetatable(env, metatable)
|
||||
|
||||
env.ADOTypes = ADOTypes
|
||||
|
||||
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()
|
||||
if not self then error("You must provide a self parameter") end
|
||||
|
||||
if isClosed or openConns.n ~= 0 then
|
||||
return false
|
||||
end
|
||||
|
||||
isClosed = true
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
function env:connect(sourcestr, user, pass, opts)
|
||||
if not self then error("You must provide a self parameter") end
|
||||
|
||||
if isClosed then
|
||||
return false, "Environment closed."
|
||||
end
|
||||
|
||||
if sourcestr == nil then
|
||||
return false, "Invalid sourcename."
|
||||
end
|
||||
|
||||
local conn = luacom.CreateObject("ADODB.Connection")
|
||||
local ok, errmsg = pcall(conn.Open, conn, sourcestr, user, pass, opts)
|
||||
|
||||
if not ok then
|
||||
return false, errmsg
|
||||
end
|
||||
|
||||
if conn.State == 0 then
|
||||
return nil
|
||||
end
|
||||
|
||||
openConns[conn] = true
|
||||
openConns.n = openConns.n + 1
|
||||
|
||||
local ok, errmsg = pcall(conn.BeginTrans, conn)
|
||||
|
||||
return Private.createConnection(conn, closeConn)
|
||||
end
|
||||
|
||||
return env
|
||||
end
|
||||
|
||||
|
||||
---------------------------------------------------------------------
|
||||
-- creates an ADO connection
|
||||
---------------------------------------------------------------------
|
||||
function Private.createConnection(conObj, closeFunc)
|
||||
|
||||
local openCursors = {}
|
||||
openCursors.n = 0
|
||||
local isClosed = false
|
||||
|
||||
local con = {}
|
||||
|
||||
setmetatable(con, metatable)
|
||||
|
||||
local autocommit = true
|
||||
|
||||
local function closeCursor(cursor)
|
||||
|
||||
if not openCursors[cursor] then
|
||||
return false
|
||||
end
|
||||
|
||||
openCursors[cursor] = nil
|
||||
openCursors.n = openCursors.n - 1
|
||||
end
|
||||
|
||||
function con:close()
|
||||
if not self then error("You must provide a self parameter") end
|
||||
|
||||
if isClosed or openCursors.n ~= 0 then
|
||||
return false
|
||||
end
|
||||
|
||||
isClosed = true
|
||||
conObj:Close()
|
||||
closeFunc(conObj)
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
function con:commit()
|
||||
if not self then error("You must provide a self parameter") end
|
||||
|
||||
if isClosed then
|
||||
return false, "Connection closed."
|
||||
end
|
||||
|
||||
local cond, err = pcall(conObj.CommitTrans, conObj)
|
||||
if not cond then
|
||||
return false, err
|
||||
end
|
||||
|
||||
local cond, err = pcall(conObj.BeginTrans, conObj)
|
||||
if not cond then
|
||||
return false, err
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
function con:execute(sql)
|
||||
if not self then error("You must provide a self parameter") end
|
||||
|
||||
if isClosed then
|
||||
return false, "Connection closed."
|
||||
end
|
||||
|
||||
local cond, res, upcount = pcall(conObj.Execute, conObj, sql)
|
||||
if not cond then
|
||||
return false, res
|
||||
end
|
||||
|
||||
if not upcount then upcount = 0 end
|
||||
|
||||
if autocommit then
|
||||
local cond, err = con:commit()
|
||||
if not cond then
|
||||
return false, err
|
||||
end
|
||||
end
|
||||
|
||||
if res and res.State ~= 0 then
|
||||
res = Private.createCursor(res, con, closeCursor)
|
||||
openCursors[res] = true
|
||||
openCursors.n = openCursors.n + 1
|
||||
else
|
||||
res = upcount
|
||||
end
|
||||
|
||||
return res
|
||||
end
|
||||
|
||||
function con:rollback()
|
||||
if not self then error("You must provide a self parameter") end
|
||||
|
||||
if isClosed then
|
||||
return false, "Connection closed."
|
||||
end
|
||||
|
||||
local cond, err = pcall(conObj.RollbackTrans, conObj)
|
||||
if not cond then
|
||||
return false, err
|
||||
end
|
||||
|
||||
local cond, err = pcall(conObj.BeginTrans, conObj)
|
||||
if not cond then
|
||||
return false, err
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
function con:setautocommit(bool)
|
||||
if not self then error("You must provide a self parameter") end
|
||||
|
||||
local cond, err = pcall(conObj.CommitTrans, conObj)
|
||||
if not cond then
|
||||
return false, err
|
||||
end
|
||||
|
||||
autocommit = bool
|
||||
|
||||
local cond, err = pcall(conObj.BeginTrans, conObj)
|
||||
if not cond then
|
||||
return false, err
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
return con
|
||||
end
|
||||
|
||||
---------------------------------------------------------------------
|
||||
-- creates an ADO cursor (recordset)
|
||||
---------------------------------------------------------------------
|
||||
function Private.createCursor(rs, con, closeFunc)
|
||||
|
||||
local isClosed = false
|
||||
local cursor = rs
|
||||
local res = {}
|
||||
local col_names = nil
|
||||
local col_types = nil
|
||||
|
||||
setmetatable(res, metatable)
|
||||
|
||||
function res:close()
|
||||
if not self then error("You must provide a self parameter") end
|
||||
|
||||
if isClosed then
|
||||
return false
|
||||
end
|
||||
|
||||
rs:Close()
|
||||
closeFunc(res, con)
|
||||
|
||||
isClosed = true
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
function res:fetch(tb, modestring)
|
||||
if not self then error("You must provide a self parameter") end
|
||||
|
||||
local arg_tb = tb
|
||||
|
||||
if cursor.EOF then
|
||||
return nil
|
||||
end
|
||||
|
||||
if tb == nil or type(tb) ~= "table" then
|
||||
tb = {}
|
||||
end
|
||||
|
||||
if modestring == nil or type(modestring) ~= "string" then
|
||||
modestring = "n"
|
||||
end
|
||||
|
||||
for i = 0, cursor.Fields.Count-1 do
|
||||
local cond, field = pcall(cursor.Fields.Item, cursor.Fields, i)
|
||||
if not cond then
|
||||
return field
|
||||
end
|
||||
if modestring == "n" or modestring == "an" or modestring == "na" then
|
||||
tb[i+1] = field.Value
|
||||
end
|
||||
if modestring == "a" or modestring == "an" or modestring == "na" then
|
||||
tb[field.Name] = field.Value
|
||||
end
|
||||
end
|
||||
local cond, err = pcall(cursor.MoveNext, cursor)
|
||||
if not cond then
|
||||
return false, err
|
||||
end
|
||||
|
||||
if modestring == "n" and not arg_tb then
|
||||
return unpack(tb)
|
||||
else
|
||||
return tb
|
||||
end
|
||||
end
|
||||
|
||||
function res:getcolnames()
|
||||
if not self then error("You must provide a self parameter") end
|
||||
|
||||
if col_names then return col_names end
|
||||
|
||||
col_names = {}
|
||||
local tb = col_names
|
||||
|
||||
for i = 0, cursor.Fields.Count-1 do
|
||||
local cond, field = pcall(cursor.Fields.Item, cursor.Fields, i)
|
||||
if not cond then
|
||||
return field
|
||||
end
|
||||
tb[i+1] = field.Name
|
||||
end
|
||||
|
||||
return tb
|
||||
end
|
||||
|
||||
function res:getcoltypes()
|
||||
if not self then error("You must provide a self parameter") end
|
||||
|
||||
if col_types then return col_types end
|
||||
|
||||
col_types = {}
|
||||
local tb = col_types
|
||||
|
||||
for i = 0, cursor.Fields.Count-1 do
|
||||
local cond, field = pcall(cursor.Fields.Item, cursor.Fields, i)
|
||||
if not cond then
|
||||
return field
|
||||
end
|
||||
tb[i+1] = ADOTypes[field.Type]
|
||||
end
|
||||
|
||||
return tb
|
||||
end
|
||||
|
||||
return res
|
||||
end
|
@ -1,7 +1,7 @@
|
||||
#!/usr/local/bin/lua
|
||||
-- See Copyright Notice in license.html
|
||||
|
||||
TOTAL_FIELDS = 800
|
||||
TOTAL_FIELDS = 40
|
||||
TOTAL_ROWS = 40 --unused
|
||||
|
||||
---------------------------------------------------------------------
|
||||
@ -23,7 +23,7 @@ end
|
||||
---------------------------------------------------------------------
|
||||
function test_object (obj, objmethods)
|
||||
-- checking object type.
|
||||
assert2 ("userdata", type(obj), "incorrect object type")
|
||||
assert2 (true, type(obj) == "userdata" or type(obj) == "table", "incorrect object type")
|
||||
-- trying to get metatable.
|
||||
assert2 ("LuaSQL: you're not allowed to get this metatable",
|
||||
getmetatable(obj), "error permitting access to object's metatable")
|
||||
@ -427,7 +427,7 @@ function column_info ()
|
||||
for i = 1, table.getn(names) do
|
||||
assert2 ("f"..i, names[i], "incorrect column names table")
|
||||
local type_i = string.gsub(types[i], "%s+", "")
|
||||
assert (type_i == "varchar(30)" or type_i == "string" or type_i == "string(30)", "incorrect column types table")
|
||||
assert (type_i == "adWVarChar" or type_i == "varchar(30)" or type_i == "string" or type_i == "string(30)", "incorrect column types table")
|
||||
end
|
||||
-- check if the tables are being reused.
|
||||
local n2, t2 = cur:getcolnames(), cur:getcoltypes()
|
||||
@ -459,6 +459,8 @@ function check_close()
|
||||
collectgarbage ()
|
||||
CONN_OK (a.CONN)
|
||||
a.cur = cur
|
||||
a.cur:close()
|
||||
a.CONN:close()
|
||||
cur = nil
|
||||
collectgarbage ()
|
||||
assert2(nil, a.cur, "cursor not collected")
|
||||
@ -470,6 +472,7 @@ end
|
||||
---------------------------------------------------------------------
|
||||
function drop_table ()
|
||||
-- Postgres retorna 0, enquanto ODBC retorna -1.
|
||||
CONN:setautocommit(true)
|
||||
assert (CONN:execute ("drop table t"))
|
||||
end
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user