# HG changeset patch # User jbe # Date 1571680513 -7200 # Node ID a006593b747c5f998d14304430294f0fcc079141 # Parent 75fd8869bc4eab36c16fc3eee94eeedf08a2a16b Basic support for database array types (integers and strings) diff -r 75fd8869bc4e -r a006593b747c libraries/mondelefant/mondelefant_atom_connector.lua --- a/libraries/mondelefant/mondelefant_atom_connector.lua Sat Oct 19 20:45:35 2019 +0200 +++ b/libraries/mondelefant/mondelefant_atom_connector.lua Mon Oct 21 19:55:13 2019 +0200 @@ -93,6 +93,19 @@ return conn:quote_string(tostring(value)) .. "::time" end +input_converters["table"] = function(conn, value) -- integer and text arrays + -- TODO: support more types + local parts = { "{" } + for i, v in ipairs(value) do + if i > 1 then parts[#parts+1] = "," end + parts[#parts+1] = '"' + parts[#parts+1] = string.gsub(tostring(v), '[\\"]', '\\%0') + parts[#parts+1] = '"' + end + parts[#parts+1] = "}" + return conn:quote_string(table.concat(parts)) +end + output_converters = setmetatable({}, { __mode = "k" }) @@ -108,7 +121,7 @@ output_converters.date = function(str) return atom.date:load(str) end -local timestamp_loader_func = function(str) +local function timestamp_loader_func(str) local year, month, day, hour, minute, second = string.match( str, "^([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])" @@ -129,7 +142,7 @@ output_converters.timestamp = timestamp_loader_func output_converters.timestamptz = timestamp_loader_func -local time_loader_func = function(str) +local function time_loader_func(str) local hour, minute, second = string.match( str, "^([0-9]?[0-9]):([0-9][0-9]):([0-9][0-9])" @@ -147,7 +160,7 @@ output_converters.time = time_loader_func output_converters.timetz = time_loader_func -local json_loader_func = function(str) +local function json_loader_func(str) return assert(json.import(str)) end output_converters.json = json_loader_func @@ -187,11 +200,51 @@ if value == nil then return nil else - local converter = output_converters[info.type] - if converter then - return converter(value) + local array_type = string.match(info.type, "^(.*)_array$") + if array_type then + local result = {} + local count = 0 + local inner_converter = output_converters[array_type] + if not inner_converter then + inner_converter = function(x) return x end + end + value = string.match(value, "^{(.*)}$") + if not value then + error("Could not parse database array") + end + local pos = 1 + while pos <= #value do + count = count + 1 + if string.find(value, '^""$', pos) then + result[count] = inner_converter("") + pos = pos + 2 + elseif string.find(value, '^"",', pos) then + result[count] = inner_converter("") + pos = pos + 3 + elseif string.find(value, '^"', pos) then + local p1, p2, entry = string.find(value, '^"(.-[^\\])",', pos) + if not p1 then + p1, p2, entry = string.find(value, '^"(.*[^\\])"$', pos) + end + if not entry then error("Could not parse database array") end + entry = string.gsub(entry, "\\(.)", "%1") + result[count] = inner_converter(entry) + pos = p2 + 1 + else + local p1, p2, entry = string.find(value, '^(.-),', pos) + if not p1 then p1, p2, entry = string.find(value, '^(.*)$', pos) end + result[count] = inner_converter(entry) + pos = p2 + 1 + end + end + return result else - return value + local converter = output_converters[info.type] + if converter then + return converter(value) + else + return value + end end end end diff -r 75fd8869bc4e -r a006593b747c libraries/mondelefant/mondelefant_native.c --- a/libraries/mondelefant/mondelefant_native.c Sat Oct 19 20:45:35 2019 +0200 +++ b/libraries/mondelefant/mondelefant_native.c Mon Oct 21 19:55:13 2019 +0200 @@ -73,6 +73,7 @@ case 28: return "xid"; case 29: return "cid"; case 114: return "json"; + case 199: return "json_array"; case 600: return "point"; case 601: return "lseg"; case 602: return "path"; @@ -87,18 +88,38 @@ case 829: return "macaddr"; case 869: return "inet"; case 650: return "cidr"; + case 1000: return "bool_array"; + case 1001: return "bytea_array"; + case 1002: return "char_array"; + case 1005: return "int2_array"; + case 1007: return "int4_array"; + case 1009: return "text_array"; + case 1015: return "varchar_array"; + case 1016: return "int8_array"; + case 1021: return "float4_array"; + case 1022: return "float8_array"; case 1042: return "bpchar"; case 1043: return "varchar"; case 1082: return "date"; case 1083: return "time"; case 1114: return "timestamp"; + case 1115: return "timestamp_array"; + case 1182: return "date_array"; + case 1183: return "time_array"; case 1184: return "timestamptz"; + case 1185: return "timestamptz_array"; case 1186: return "interval"; + case 1187: return "interval_array"; + case 1231: return "numeric_array"; case 1266: return "timetz"; + case 1270: return "timetz_array"; case 1560: return "bit"; + case 1561: return "bit_array"; case 1562: return "varbit"; + case 1563: return "varbit_array"; case 1700: return "numeric"; case 3802: return "jsonb"; + case 3807: return "jsonb_array"; default: return NULL; } }