webmcp

annotate libraries/mondelefant/mondelefant_atom_connector.lua @ 106:bbfbbddf13ad

Support for intervals
author jbe
date Sun Nov 04 04:55:22 2012 +0100 (2012-11-04)
parents 3d43a5cf17c1
children 6b435d3c0b14
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 --]]

Impressum / About Us