libs-imp-mysql.lua /size: 6660 b    last modification: 2020-07-01 14:35
1
if
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
-- c:/data/develop/tex-context/tex/texmf-win64/bin/lib/luametatex/lua/copies/mysql/libmysql.dll
10 11
local
libname
=
"
mysql
"
12
local
libfile
=
"
libmysql
"
13 14
local
mysqllib
=
resolvers
.
libraries
.
validoptional
(
libname
)
15 16
if
not
mysqllib
then
return
end
17 18
local
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
(
)
25
end
26 27
local
lpegmatch
=
lpeg
.
match
28
local
setmetatable
=
setmetatable
29 30
local
sql
=
utilities
.
sql
or
require
(
"
util-sql
"
)
31
local
report
=
logs
.
reporter
(
libname
)
32 33
local
trace_sql
=
false
trackers
.
register
(
"
sql.trace
"
,
function
(
v
)
trace_sql
=
v
end
)
34
local
trace_queries
=
false
trackers
.
register
(
"
sql.queries
"
,
function
(
v
)
trace_queries
=
v
end
)
35 36
local
mysql_open
=
mysqllib
.
open
37
local
mysql_close
=
mysqllib
.
close
38
local
mysql_execute
=
mysqllib
.
execute
39
local
mysql_getmessage
=
mysqllib
.
getmessage
40 41
local
helpers
=
sql
.
helpers
42
local
methods
=
sql
.
methods
43
local
validspecification
=
helpers
.
validspecification
44
local
preparetemplate
=
helpers
.
preparetemplate
45
local
querysplitter
=
helpers
.
querysplitter
46
local
cache
=
{
}
47
local
timeout
-- = 3600 -- to be tested
48 49
local
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
61
end
62 63
local
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
-- or specification.presets and specification.presets.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
-- bonus
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
163
end
164 165
local
function
execute
(
specification
)
166
return
execute_once
(
specification
,
true
)
167
end
168 169
-- Here we build the dataset stepwise so we don't use the data hack that
170
-- is used in the client variant.
171 172
local
wraptemplate
=
[[
173local converters = utilities.sql.converters 174local deserialize = utilities.sql.deserialize 175 176local tostring = tostring 177local tonumber = tonumber 178local booleanstring = string.booleanstring 179 180%s 181 182return function(cells) 183 -- %s (not needed) 184 -- %s (not needed) 185 return { 186 %s 187 } 188end 189
]]
190 191
-- return function(result)
192
-- if not result then
193
-- return { }
194
-- end
195
-- local nofrows = #result
196
-- if nofrows == 0 then
197
-- return { }
198
-- end
199
-- local target = { } -- no %s needed here
200
-- for i=1,nofrows do
201
-- target[%s] = {
202
-- %s
203
-- }
204
-- end
205
-- return result
206
-- end
207 208
local
celltemplate
=
"
cells[%s]
"
209 210
methods
.
mysql
=
{
211
execute
=
execute
,
212
usesfiles
=
false
,
213
wraptemplate
=
wraptemplate
,
214
celltemplate
=
celltemplate
,
215
}
216 217
package
.
loaded
[
"
util-sql-imp-ffi
"
]
=
methods
.
mysql
218
package
.
loaded
[
"
util-sql-imp-mysql
"
]
=
methods
.
mysql
219
package
.
loaded
[
"
util-sql-imp-library
"
]
=
methods
.
mysql
220
package
.
loaded
[
libname
]
=
methods
.
mysql
221