summaryrefslogtreecommitdiff
path: root/tex/context/base/util-sql-imp-library.lua
diff options
context:
space:
mode:
Diffstat (limited to 'tex/context/base/util-sql-imp-library.lua')
-rw-r--r--tex/context/base/util-sql-imp-library.lua234
1 files changed, 180 insertions, 54 deletions
diff --git a/tex/context/base/util-sql-imp-library.lua b/tex/context/base/util-sql-imp-library.lua
index a32a9d09b..90b6be5fb 100644
--- a/tex/context/base/util-sql-imp-library.lua
+++ b/tex/context/base/util-sql-imp-library.lua
@@ -91,10 +91,137 @@ local function connect(session,specification)
)
end
-local function datafetched(specification,query,converter)
+-- local function datafetched(specification,query,converter)
+-- if not query or query == "" then
+-- report_state("no valid query")
+-- return { }, { }
+-- end
+-- local id = specification.id
+-- local session, connection
+-- if id then
+-- local c = cache[id]
+-- if c then
+-- session = c.session
+-- connection = c.connection
+-- end
+-- if not connection then
+-- session = initialize()
+-- connection = connect(session,specification)
+-- cache[id] = { session = session, connection = connection }
+-- end
+-- else
+-- session = initialize()
+-- connection = connect(session,specification)
+-- end
+-- if not connection then
+-- report_state("error in connection: %s@%s to %s:%s",
+-- specification.database or "no database",
+-- specification.username or "no username",
+-- specification.host or "no host",
+-- specification.port or "no port"
+-- )
+-- return { }, { }
+-- end
+-- query = lpegmatch(querysplitter,query)
+-- local result, message, okay
+-- -- todo: check if open !
+-- for i=1,#query do
+-- local q = query[i]
+-- local r, m = connection:execute(q)
+-- if m then
+-- report_state("error in query, stage 1: %s",string.collapsespaces(q))
+-- message = message and format("%s\n%s",message,m) or m
+-- end
+-- local t = type(r)
+-- if t == "userdata" then
+-- result = r
+-- okay = true
+-- elseif t == "number" then
+-- okay = true
+-- end
+-- end
+-- if not okay and id then -- can go
+-- if session then
+-- session:close()
+-- end
+-- if connection then
+-- connection:close()
+-- end
+-- session = initialize() -- maybe not needed
+-- connection = connect(session,specification)
+-- if connection then
+-- cache[id] = { session = session, connection = connection }
+-- for i=1,#query do
+-- local q = query[i]
+-- local r, m = connection:execute(q)
+-- if m then
+-- report_state("error in query, stage 2: %s",string.collapsespaces(q))
+-- message = message and format("%s\n%s",message,m) or m
+-- end
+-- local t = type(r)
+-- if t == "userdata" then
+-- result = r
+-- okay = true
+-- elseif t == "number" then
+-- okay = true
+-- end
+-- end
+-- else
+-- message = "unable to connect"
+-- report_state(message)
+-- end
+-- end
+-- local data, keys
+-- if result then
+-- if converter then
+-- data = converter.library(result)
+-- -- data = converter(result)
+-- else
+-- keys = result:getcolnames()
+-- if keys then
+-- local n = result:numrows() or 0
+-- if n == 0 then
+-- data = { }
+-- -- elseif n == 1 then
+-- -- -- data = { result:fetch({},"a") }
+-- else
+-- data = { }
+-- -- for i=1,n do
+-- -- data[i] = result:fetch({},"a")
+-- -- end
+-- local k = #keys
+-- for i=1,n do
+-- local v = { result:fetch() }
+-- local d = { }
+-- for i=1,k do
+-- d[keys[i]] = v[i]
+-- end
+-- data[#data+1] = d
+-- end
+-- end
+-- end
+-- end
+-- result:close()
+-- elseif message then
+-- report_state("message %s",message)
+-- end
+-- if not keys then
+-- keys = { }
+-- end
+-- if not data then
+-- data = { }
+-- end
+-- if not id then
+-- connection:close()
+-- session:close()
+-- end
+-- return data, keys
+-- end
+
+local function fetched(specification,query,converter)
if not query or query == "" then
report_state("no valid query")
- return { }, { }
+ return false
end
local id = specification.id
local session, connection
@@ -106,31 +233,44 @@ local function datafetched(specification,query,converter)
end
if not connection then
session = initialize()
+ if not session then
+ return format("no session for %q",id)
+ end
connection = connect(session,specification)
+ if not connection then
+ return format("no connection for %q",id)
+ end
cache[id] = { session = session, connection = connection }
end
else
session = initialize()
+ if not session then
+ return "no session"
+ end
connection = connect(session,specification)
+ if not connection then
+ return "no connection"
+ end
end
if not connection then
report_state("error in connection: %s@%s to %s:%s",
- specification.database or "no database",
- specification.username or "no username",
- specification.host or "no host",
- specification.port or "no port"
- )
- return { }, { }
+ specification.database or "no database",
+ specification.username or "no username",
+ specification.host or "no host",
+ specification.port or "no port"
+ )
+ return "no connection"
end
query = lpegmatch(querysplitter,query)
- local result, message, okay
- -- todo: check if open !
+ local result, okay
for i=1,#query do
local q = query[i]
local r, m = connection:execute(q)
if m then
report_state("error in query, stage 1: %s",string.collapsespaces(q))
- message = message and format("%s\n%s",message,m) or m
+ if m then
+ report_state("message: %s",m)
+ end
end
local t = type(r)
if t == "userdata" then
@@ -140,55 +280,28 @@ local function datafetched(specification,query,converter)
okay = true
end
end
- if not okay and id then -- can go
+ if not okay then -- can go
if session then
session:close()
end
if connection then
connection:close()
end
- session = initialize() -- maybe not needed
- connection = connect(session,specification)
- if connection then
- cache[id] = { session = session, connection = connection }
- for i=1,#query do
- local q = query[i]
- local r, m = connection:execute(q)
- if m then
- report_state("error in query, stage 2: %s",string.collapsespaces(q))
- message = message and format("%s\n%s",message,m) or m
- end
- local t = type(r)
- if t == "userdata" then
- result = r
- okay = true
- elseif t == "number" then
- okay = true
- end
- end
- else
- message = "unable to connect"
- report_state(message)
+ if id then
+ cache[id] = nil
end
+ return "execution error"
end
local data, keys
if result then
if converter then
data = converter.library(result)
- -- data = converter(result)
else
keys = result:getcolnames()
if keys then
+ data = { }
local n = result:numrows() or 0
- if n == 0 then
- data = { }
- -- elseif n == 1 then
- -- -- data = { result:fetch({},"a") }
- else
- data = { }
- -- for i=1,n do
- -- data[i] = result:fetch({},"a")
- -- end
+ if n > 0 then
local k = #keys
for i=1,n do
local v = { result:fetch() }
@@ -202,20 +315,33 @@ local function datafetched(specification,query,converter)
end
end
result:close()
- elseif message then
- report_state("message %s",message)
end
- if not keys then
- keys = { }
+ if not id then
+ if connection then
+ connection:close()
+ end
+ if session then
+ session:close()
+ end
end
- if not data then
- data = { }
+ return false, data, keys
+end
+
+local function datafetched(specification,query,converter)
+ local callokay, connectionerror, data, keys = pcall(fetched,specification,query,converter)
+ if not callokay then
+ report_state("call error, retrying")
+ callerror, connectionerror, data, keys = pcall(fetched,specification,query,converter)
+ elseif connectionerror then
+ report_state("error: %q, retrying",connectionerror)
+ callerror, connectionerror, data, keys = pcall(fetched,specification,query,converter)
end
- if not id then
- connection:close()
- session:close()
+ if not callokay then
+ report_state("persistent call error")
+ elseif connectionerror then
+ report_state("persistent error: %q",connectionerror)
end
- return data, keys
+ return data or { }, keys or { }
end
local function execute(specification)