rev |
line source |
jbe/bsw@0
|
1 #!/usr/bin/env lua
|
jbe/bsw@0
|
2
|
jbe/bsw@0
|
3 local _G = _G
|
jbe/bsw@0
|
4 local _VERSION = _VERSION
|
jbe/bsw@0
|
5 local assert = assert
|
jbe/bsw@0
|
6 local error = error
|
jbe/bsw@0
|
7 local getmetatable = getmetatable
|
jbe/bsw@0
|
8 local ipairs = ipairs
|
jbe/bsw@0
|
9 local next = next
|
jbe/bsw@0
|
10 local pairs = pairs
|
jbe/bsw@0
|
11 local print = print
|
jbe/bsw@0
|
12 local rawequal = rawequal
|
jbe/bsw@0
|
13 local rawget = rawget
|
jbe@64
|
14 local rawlen = rawlen
|
jbe/bsw@0
|
15 local rawset = rawset
|
jbe/bsw@0
|
16 local select = select
|
jbe/bsw@0
|
17 local setmetatable = setmetatable
|
jbe/bsw@0
|
18 local tonumber = tonumber
|
jbe/bsw@0
|
19 local tostring = tostring
|
jbe/bsw@0
|
20 local type = type
|
jbe/bsw@0
|
21
|
jbe/bsw@0
|
22 local math = math
|
jbe/bsw@0
|
23 local string = string
|
jbe@64
|
24 local table = table
|
jbe/bsw@0
|
25
|
jbe/bsw@0
|
26 local mondelefant = require("mondelefant")
|
jbe/bsw@0
|
27 local atom = require("atom")
|
jbe/bsw@0
|
28
|
jbe@64
|
29 local _M = {}
|
jbe@64
|
30 if _ENV then
|
jbe@64
|
31 _ENV = _M
|
jbe@64
|
32 else
|
jbe@64
|
33 _G[...] = _M
|
jbe@64
|
34 setfenv(1, _M)
|
jbe@64
|
35 end
|
jbe/bsw@0
|
36
|
jbe/bsw@0
|
37
|
jbe/bsw@0
|
38 input_converters = setmetatable({}, { __mode = "k" })
|
jbe/bsw@0
|
39
|
jbe/bsw@0
|
40 input_converters["boolean"] = function(conn, value)
|
jbe/bsw@0
|
41 if value then return "TRUE" else return "FALSE" end
|
jbe/bsw@0
|
42 end
|
jbe/bsw@0
|
43
|
jbe/bsw@0
|
44 input_converters["number"] = function(conn, value)
|
jbe/bsw@0
|
45 local str = tostring(value)
|
jbe/bsw@0
|
46 if string.find(str, "^[0-9%.e%-]+$") then
|
jbe/bsw@0
|
47 return str
|
jbe/bsw@0
|
48 else
|
jbe/bsw@0
|
49 return "'NaN'"
|
jbe/bsw@0
|
50 end
|
jbe/bsw@0
|
51 end
|
jbe/bsw@0
|
52
|
jbe/bsw@0
|
53 input_converters[atom.fraction] = function(conn, value)
|
jbe/bsw@0
|
54 if value.invalid then
|
jbe/bsw@0
|
55 return "'NaN'"
|
jbe/bsw@0
|
56 else
|
jbe/bsw@0
|
57 local n, d = tostring(value.numerator), tostring(value.denominator)
|
jbe/bsw@0
|
58 if string.find(n, "^%-?[0-9]+$") and string.find(d, "^%-?[0-9]+$") then
|
jbe/bsw@0
|
59 return "(" .. n .. "::numeric / " .. d .. "::numeric)"
|
jbe/bsw@0
|
60 else
|
jbe/bsw@0
|
61 return "'NaN'"
|
jbe/bsw@0
|
62 end
|
jbe/bsw@0
|
63 end
|
jbe/bsw@0
|
64 end
|
jbe/bsw@0
|
65
|
jbe/bsw@0
|
66 input_converters[atom.date] = function(conn, value)
|
jbe/bsw@0
|
67 return conn:quote_string(tostring(value)) .. "::date"
|
jbe/bsw@0
|
68 end
|
jbe/bsw@0
|
69
|
jbe/bsw@0
|
70 input_converters[atom.timestamp] = function(conn, value)
|
jbe/bsw@0
|
71 return conn:quote_string(tostring(value)) -- don't define type
|
jbe/bsw@0
|
72 end
|
jbe/bsw@0
|
73
|
jbe/bsw@0
|
74 input_converters[atom.time] = function(conn, value)
|
jbe/bsw@0
|
75 return conn:quote_string(tostring(value)) .. "::time"
|
jbe/bsw@0
|
76 end
|
jbe/bsw@0
|
77
|
jbe@106
|
78 input_converters[atom.interval] = function(conn, value)
|
jbe@106
|
79 return (
|
jbe@106
|
80 conn:quote_string(
|
jbe@106
|
81 table.concat(
|
jbe@106
|
82 {
|
jbe@106
|
83 tostring(value.years), "years",
|
jbe@106
|
84 tostring(value.months), "months",
|
jbe@106
|
85 tostring(value.days), "days",
|
jbe@106
|
86 tostring(value.hours), "hours",
|
jbe@106
|
87 tostring(value.minutes), "minutes",
|
jbe@106
|
88 tostring(value.seconds), "seconds"
|
jbe@106
|
89 },
|
jbe@106
|
90 " "
|
jbe@106
|
91 )
|
jbe@106
|
92 ) .. "::interval"
|
jbe@106
|
93 )
|
jbe@106
|
94 end
|
jbe@106
|
95
|
jbe/bsw@0
|
96
|
jbe/bsw@0
|
97 output_converters = setmetatable({}, { __mode = "k" })
|
jbe/bsw@0
|
98
|
jbe/bsw@0
|
99 output_converters.int8 = function(str) return atom.integer:load(str) end
|
jbe/bsw@0
|
100 output_converters.int4 = function(str) return atom.integer:load(str) end
|
jbe/bsw@0
|
101 output_converters.int2 = function(str) return atom.integer:load(str) end
|
jbe/bsw@0
|
102
|
jbe/bsw@0
|
103 output_converters.numeric = function(str) return atom.number:load(str) end
|
jbe/bsw@0
|
104 output_converters.float4 = function(str) return atom.number:load(str) end
|
jbe/bsw@0
|
105 output_converters.float8 = function(str) return atom.number:load(str) end
|
jbe/bsw@0
|
106
|
jbe/bsw@0
|
107 output_converters.bool = function(str) return atom.boolean:load(str) end
|
jbe/bsw@0
|
108
|
jbe/bsw@0
|
109 output_converters.date = function(str) return atom.date:load(str) end
|
jbe/bsw@0
|
110
|
jbe/bsw@0
|
111 local timestamp_loader_func = function(str)
|
jbe@1
|
112 local year, month, day, hour, minute, second = string.match(
|
jbe/bsw@0
|
113 str,
|
jbe@1
|
114 "^([0-9][0-9][0-9][0-9])%-([0-9][0-9])%-([0-9][0-9]) ([0-9]?[0-9]):([0-9][0-9]):([0-9][0-9])"
|
jbe/bsw@0
|
115 )
|
jbe@1
|
116 if year then
|
jbe/bsw@0
|
117 return atom.timestamp{
|
jbe@1
|
118 year = tonumber(year),
|
jbe@1
|
119 month = tonumber(month),
|
jbe@1
|
120 day = tonumber(day),
|
jbe/bsw@0
|
121 hour = tonumber(hour),
|
jbe/bsw@0
|
122 minute = tonumber(minute),
|
jbe/bsw@0
|
123 second = tonumber(second)
|
jbe/bsw@0
|
124 }
|
jbe/bsw@0
|
125 else
|
jbe/bsw@0
|
126 return atom.timestamp.invalid
|
jbe/bsw@0
|
127 end
|
jbe/bsw@0
|
128 end
|
jbe/bsw@0
|
129 output_converters.timestamp = timestamp_loader_func
|
jbe/bsw@0
|
130 output_converters.timestamptz = timestamp_loader_func
|
jbe/bsw@0
|
131
|
jbe/bsw@0
|
132 local time_loader_func = function(str)
|
jbe@1
|
133 local hour, minute, second = string.match(
|
jbe/bsw@0
|
134 str,
|
jbe@1
|
135 "^([0-9]?[0-9]):([0-9][0-9]):([0-9][0-9])"
|
jbe/bsw@0
|
136 )
|
jbe@1
|
137 if hour then
|
jbe/bsw@0
|
138 return atom.time{
|
jbe/bsw@0
|
139 hour = tonumber(hour),
|
jbe/bsw@0
|
140 minute = tonumber(minute),
|
jbe/bsw@0
|
141 second = tonumber(second)
|
jbe/bsw@0
|
142 }
|
jbe/bsw@0
|
143 else
|
jbe/bsw@0
|
144 return atom.time.invalid
|
jbe/bsw@0
|
145 end
|
jbe/bsw@0
|
146 end
|
jbe/bsw@0
|
147 output_converters.time = time_loader_func
|
jbe/bsw@0
|
148 output_converters.timetz = time_loader_func
|
jbe/bsw@0
|
149
|
jbe@106
|
150 output_converters.interval = function(str)
|
jbe@106
|
151 local years, months, days, hours, minutes, seconds = 0, 0, 0, 0, 0, 0
|
jbe@106
|
152 local any_match = false
|
jbe@106
|
153 for amount, unit in string.gmatch(str, "(%-?[0-9]+)%s*([A-Za-z]+)") do
|
jbe@106
|
154 local unit = string.lower(unit)
|
jbe@106
|
155 if string.match(unit, "^y") then
|
jbe@106
|
156 years = years + tonumber(amount)
|
jbe@106
|
157 any_match = true
|
jbe@106
|
158 elseif string.match(unit, "^mo") then
|
jbe@106
|
159 months = months + tonumber(amount)
|
jbe@106
|
160 any_match = true
|
jbe@106
|
161 elseif string.match(unit, "^d") then
|
jbe@106
|
162 days = days + tonumber(amount)
|
jbe@106
|
163 any_match = true
|
jbe@106
|
164 elseif string.match(unit, "^h") then
|
jbe@106
|
165 hours = hours + tonumber(amount)
|
jbe@106
|
166 any_match = true
|
jbe@106
|
167 elseif string.match(unit, "^mi") then
|
jbe@106
|
168 minutes = minutes + tonumber(amount)
|
jbe@106
|
169 any_match = true
|
jbe@106
|
170 elseif string.match(unit, "^s") then
|
jbe@106
|
171 seconds = seconds + tonumber(amount)
|
jbe@106
|
172 any_match = true
|
jbe@106
|
173 else
|
jbe@106
|
174 return atom.interval.invalid
|
jbe@106
|
175 end
|
jbe@106
|
176 end
|
jbe@106
|
177 local sign, h, m, s = string.match(str, "(%-?)([0-9]+):([0-9]+):([0-9]+)")
|
jbe@106
|
178 if h then
|
jbe@106
|
179 if sign == "-" then
|
jbe@106
|
180 hours = hours - tonumber(h)
|
jbe@106
|
181 minutes = minutes - tonumber(m)
|
jbe@106
|
182 seconds = seconds - tonumber(s)
|
jbe@106
|
183 else
|
jbe@106
|
184 hours = hours + tonumber(h)
|
jbe@106
|
185 minutes = minutes + tonumber(m)
|
jbe@106
|
186 seconds = seconds + tonumber(s)
|
jbe@106
|
187 end
|
jbe@106
|
188 any_match = true
|
jbe@106
|
189 end
|
jbe@106
|
190 if not any_match then
|
jbe@106
|
191 return atom.interval.invalid
|
jbe@106
|
192 end
|
jbe@106
|
193 if string.match(str, "%sago%s*$") then
|
jbe@106
|
194 years, months, days = -years, -months, -days
|
jbe@106
|
195 hours, minutes, seconds = -hours, -minutes, -seconds
|
jbe@106
|
196 end
|
jbe@106
|
197 return atom.interval:new{
|
jbe@106
|
198 years = years, months = months, days = days,
|
jbe@106
|
199 hours = hours, minutes = minutes, seconds = seconds
|
jbe@106
|
200 }
|
jbe@106
|
201 end
|
jbe@106
|
202
|
jbe/bsw@0
|
203 mondelefant.postgresql_connection_prototype.type_mappings = {
|
jbe/bsw@0
|
204 int8 = atom.integer,
|
jbe/bsw@0
|
205 int4 = atom.integer,
|
jbe/bsw@0
|
206 int2 = atom.integer,
|
jbe/bsw@0
|
207 bool = atom.boolean,
|
jbe/bsw@0
|
208 date = atom.date,
|
jbe/bsw@0
|
209 timestamp = atom.timestamp,
|
jbe/bsw@0
|
210 time = atom.time,
|
jbe/bsw@0
|
211 text = atom.string,
|
jbe/bsw@0
|
212 varchar = atom.string,
|
jbe/bsw@0
|
213 }
|
jbe/bsw@0
|
214
|
jbe/bsw@0
|
215
|
jbe/bsw@0
|
216 function mondelefant.postgresql_connection_prototype.input_converter(conn, value, info)
|
jbe/bsw@0
|
217 if value == nil then
|
jbe/bsw@0
|
218 return "NULL"
|
jbe/bsw@0
|
219 else
|
jbe/bsw@0
|
220 local converter =
|
jbe/bsw@0
|
221 input_converters[getmetatable(value)] or
|
jbe/bsw@0
|
222 input_converters[type(value)]
|
jbe/bsw@0
|
223 if converter then
|
jbe/bsw@0
|
224 return converter(conn, value)
|
jbe/bsw@0
|
225 else
|
jbe/bsw@0
|
226 return conn:quote_string(tostring(value))
|
jbe/bsw@0
|
227 end
|
jbe/bsw@0
|
228 end
|
jbe/bsw@0
|
229 end
|
jbe/bsw@0
|
230
|
jbe/bsw@0
|
231 function mondelefant.postgresql_connection_prototype.output_converter(conn, value, info)
|
jbe/bsw@0
|
232 if value == nil then
|
jbe/bsw@0
|
233 return nil
|
jbe/bsw@0
|
234 else
|
jbe/bsw@0
|
235 local converter = output_converters[info.type]
|
jbe/bsw@0
|
236 if converter then
|
jbe/bsw@0
|
237 return converter(value)
|
jbe/bsw@0
|
238 else
|
jbe/bsw@0
|
239 return value
|
jbe/bsw@0
|
240 end
|
jbe/bsw@0
|
241 end
|
jbe/bsw@0
|
242 end
|
jbe/bsw@0
|
243
|
jbe@64
|
244 return _M
|
jbe@64
|
245
|
jbe/bsw@0
|
246
|
jbe/bsw@0
|
247 --[[
|
jbe/bsw@0
|
248
|
jbe/bsw@0
|
249 db = assert(mondelefant.connect{engine='postgresql', dbname='test'})
|
jbe/bsw@0
|
250 result = db:query{'SELECT ? + 1', atom.date{ year=1999, month=12, day=31}}
|
jbe/bsw@0
|
251 print(result[1][1].year)
|
jbe/bsw@0
|
252
|
jbe/bsw@0
|
253 --]]
|