1if not modules then modules = { } end modules ['libs-imp-mysql'] = {
2 version = 1.001,
3 comment = "companion to util-sql.lua",
4 author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
5 copyright = "PRAGMA ADE / ConTeXt Development Team",
6 license = "see context related readme files"
7}
8
9
10
11local libname = "mysql"
12local libfile = "libmysql"
13
14local mysqllib = resolvers.libraries.validoptional(libname)
15
16if not mysqllib then return end
17
18local function okay()
19 if resolvers.libraries.optionalloaded(libname,libfile) then
20 okay = function() return true end
21 else
22 okay = function() return false end
23 end
24 return okay()
25end
26
27local lpegmatch = lpeg.match
28local setmetatable = setmetatable
29
30local sql = utilities.sql or require("util-sql")
31local report = logs.reporter(libname)
32
33local trace_sql = false trackers.register("sql.trace", function(v) trace_sql = v end)
34local trace_queries = false trackers.register("sql.queries",function(v) trace_queries = v end)
35
36local mysql_open = mysqllib.open
37local mysql_close = mysqllib.close
38local mysql_execute = mysqllib.execute
39local mysql_getmessage = mysqllib.getmessage
40
41local helpers = sql.helpers
42local methods = sql.methods
43local validspecification = helpers.validspecification
44local preparetemplate = helpers.preparetemplate
45local querysplitter = helpers.querysplitter
46local cache = { }
47local timeout
48
49local function connect(specification)
50 local db = mysql_open(
51 specification.database or "",
52 specification.username or "",
53 specification.password or "",
54 specification.host or "",
55 specification.port
56 )
57 if db and timeout then
58 mysql_execute(db,formatters["SET SESSION connect_timeout=%s ;"](timeout))
59 end
60 return db
61end
62
63local function execute_once(specification,retry)
64 if okay() then
65 if trace_sql then
66 report("executing mysql")
67 end
68 if not validspecification(specification) then
69 report("error in specification")
70 end
71 local query = preparetemplate(specification)
72 if not query then
73 report("error in preparation")
74 return
75 else
76 query = lpegmatch(querysplitter,query)
77 end
78 local base = specification.database
79 if not base then
80 report("no database specified")
81 return
82 end
83 local result = { }
84 local keys = { }
85 local id = specification.id
86 local db = nil
87 if id then
88 local session = cache[id]
89 if session then
90 db = session.db
91 else
92 db = connect(specification)
93 if not db then
94 report("no session database specified")
95 else
96 cache[id] = {
97 specification = specification,
98 db = db,
99 }
100 end
101 end
102 else
103 db = connect(specification)
104 end
105 if not db then
106 report("no database opened")
107 else
108 local converter = specification.converter
109 local nofrows = 0
110 local callback = nil
111 if converter then
112 local convert = converter.mysql
113 callback = function(nofcolumns,values,fields)
114 nofrows = nofrows + 1
115 result[nofrows] = convert(values)
116 end
117 else
118 callback = function(nofcolumns,values,fields)
119 local column = { }
120 for i=1,nofcolumns do
121 local field
122 if fields then
123 field = fields[i]
124 keys[i] = field
125 else
126 field = keys[i]
127 end
128 if field then
129 column[field] = values[i]
130 end
131 end
132 nofrows = nofrows + 1
133 result[nofrows] = column
134 end
135 end
136 for i=1,#query do
137 local okay = mysql_execute(db,query[i],callback)
138 if not okay then
139 if id and retry and i == 1 then
140 report("error: %s, retrying to connect",mysql_getmessage(db))
141 mysql_close(db)
142 cache[id] = nil
143 return execute_once(specification,false)
144 else
145 report("error: %s",mysql_getmessage(db))
146 end
147 end
148 end
149 end
150 if db and not id then
151 mysql_close(db)
152 end
153
154 local one = result[1]
155 if one then
156 setmetatable(result,{ __index = one } )
157 end
158
159 return result, keys
160 else
161 report("error: ","no library loaded")
162 end
163end
164
165local function execute(specification)
166 return execute_once(specification,true)
167end
168
169
170
171
172local wraptemplate = [[
173local converters = utilities.sql.converters
174local deserialize = utilities.sql.deserialize
175local fromjson = utilities.sql.fromjson
176
177local tostring = tostring
178local tonumber = tonumber
179local booleanstring = string.booleanstring
180
181%s
182
183return function(cells)
184 -- %s (not needed)
185 -- %s (not needed)
186 return {
187 %s
188 }
189end
190]]
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209local celltemplate = "cells[%s]"
210
211methods.mysql = {
212 execute = execute,
213 usesfiles = false,
214 wraptemplate = wraptemplate,
215 celltemplate = celltemplate,
216}
217
218package.loaded["util-sql-imp-ffi"] = methods.mysql
219package.loaded["util-sql-imp-mysql"] = methods.mysql
220package.loaded["util-sql-imp-library"] = methods.mysql
221package.loaded[libname] = methods.mysql
222 |