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:
mascarenhas 2005-02-28 19:48:10 +00:00
parent 81fd332056
commit 5619ae246b
5 changed files with 369 additions and 10 deletions

View File

@ -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&atilde;o</dt>
<dd>Programmer.</dd>

View File

@ -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>
@ -100,7 +100,8 @@ The MySQL driver has been tested on Linux and is compatible with versions 4.0
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 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&aacute;s Guisasola as part of the
The implementation is compatible with Lua 5.0 and was coded by
Tom&aacute;s Guisasola, Eduardo Quint&atilde;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>

View File

@ -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
View 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

View File

@ -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