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