Comparison

util/sql.lua @ 7278:1891854b25ac

Merge 0.10->trunk
author Kim Alvefur <zash@zash.se>
date Mon, 14 Mar 2016 14:20:37 +0100
parent 7276:30dfaf36ea6d
child 7306:98c4c3a2b536
comparison
equal deleted inserted replaced
7270:df22e314946c 7278:1891854b25ac
23 23
24 local function is_column(x) return getmetatable(x)==column_mt; end 24 local function is_column(x) return getmetatable(x)==column_mt; end
25 local function is_index(x) return getmetatable(x)==index_mt; end 25 local function is_index(x) return getmetatable(x)==index_mt; end
26 local function is_table(x) return getmetatable(x)==table_mt; end 26 local function is_table(x) return getmetatable(x)==table_mt; end
27 local function is_query(x) return getmetatable(x)==query_mt; end 27 local function is_query(x) return getmetatable(x)==query_mt; end
28 local function Integer(n) return "Integer()" end 28 local function Integer() return "Integer()" end
29 local function String(n) return "String()" end 29 local function String() return "String()" end
30 30
31 local function Column(definition) 31 local function Column(definition)
32 return setmetatable(definition, column_mt); 32 return setmetatable(definition, column_mt);
33 end 33 end
34 local function Table(definition) 34 local function Table(definition)
122 return true; 122 return true;
123 end 123 end
124 function engine:onconnect() 124 function engine:onconnect()
125 -- Override from create_engine() 125 -- Override from create_engine()
126 end 126 end
127
128 function engine:prepquery(sql)
129 if self.params.driver == "PostgreSQL" then
130 sql = sql:gsub("`", "\"");
131 end
132 return sql;
133 end
134
127 function engine:execute(sql, ...) 135 function engine:execute(sql, ...)
128 local success, err = self:connect(); 136 local success, err = self:connect();
129 if not success then return success, err; end 137 if not success then return success, err; end
130 local prepared = self.prepared; 138 local prepared = self.prepared;
131 139
151 local i = 0; local a = {...} 159 local i = 0; local a = {...}
152 log("debug", "[%s] %s", where, sql:gsub("%?", function () i = i + 1; local v = a[i]; if type(v) == "string" then v = ("%q"):format(v); end return tostring(v); end)); 160 log("debug", "[%s] %s", where, sql:gsub("%?", function () i = i + 1; local v = a[i]; if type(v) == "string" then v = ("%q"):format(v); end return tostring(v); end));
153 end 161 end
154 162
155 function engine:execute_query(sql, ...) 163 function engine:execute_query(sql, ...)
156 if self.params.driver == "PostgreSQL" then 164 sql = self:prepquery(sql);
157 sql = sql:gsub("`", "\"");
158 end
159 local stmt = assert(self.conn:prepare(sql)); 165 local stmt = assert(self.conn:prepare(sql));
160 assert(stmt:execute(...)); 166 assert(stmt:execute(...));
161 return stmt:rows(); 167 return stmt:rows();
162 end 168 end
163 function engine:execute_update(sql, ...) 169 function engine:execute_update(sql, ...)
164 if self.params.driver == "PostgreSQL" then 170 sql = self:prepquery(sql);
165 sql = sql:gsub("`", "\"");
166 end
167 local prepared = self.prepared; 171 local prepared = self.prepared;
168 local stmt = prepared[sql]; 172 local stmt = prepared[sql];
169 if not stmt then 173 if not stmt then
170 stmt = assert(self.conn:prepare(sql)); 174 stmt = assert(self.conn:prepare(sql));
171 prepared[sql] = stmt; 175 prepared[sql] = stmt;
293 end 297 end
294 function engine:set_encoding() -- to UTF-8 298 function engine:set_encoding() -- to UTF-8
295 local driver = self.params.driver; 299 local driver = self.params.driver;
296 if driver == "SQLite3" then 300 if driver == "SQLite3" then
297 return self:transaction(function() 301 return self:transaction(function()
298 if self:select"PRAGMA encoding;"()[1] == "UTF-8" then 302 for encoding in self:select"PRAGMA encoding;" do
299 self.charset = "utf8"; 303 if encoding[1] == "UTF-8" then
304 self.charset = "utf8";
305 end
300 end 306 end
301 end); 307 end);
302 end 308 end
303 local set_names_query = "SET NAMES '%s';" 309 local set_names_query = "SET NAMES '%s';"
304 local charset = "utf8"; 310 local charset = "utf8";
305 if driver == "MySQL" then 311 if driver == "MySQL" then
306 local ok, charsets = self:transaction(function() 312 self:transaction(function()
307 return self:select"SELECT `CHARACTER_SET_NAME` FROM `information_schema`.`CHARACTER_SETS` WHERE `CHARACTER_SET_NAME` LIKE 'utf8%' ORDER BY MAXLEN DESC LIMIT 1;"; 313 for row in self:select"SELECT `CHARACTER_SET_NAME` FROM `information_schema`.`CHARACTER_SETS` WHERE `CHARACTER_SET_NAME` LIKE 'utf8%' ORDER BY MAXLEN DESC LIMIT 1;" do
314 charset = row and row[1] or charset;
315 end
308 end); 316 end);
309 local row = ok and charsets();
310 charset = row and row[1] or charset;
311 set_names_query = set_names_query:gsub(";$", (" COLLATE '%s';"):format(charset.."_bin")); 317 set_names_query = set_names_query:gsub(";$", (" COLLATE '%s';"):format(charset.."_bin"));
312 end 318 end
313 self.charset = charset; 319 self.charset = charset;
314 log("debug", "Using encoding '%s' for database connection", charset); 320 log("debug", "Using encoding '%s' for database connection", charset);
315 local ok, err = self:transaction(function() return self:execute(set_names_query:format(charset)); end); 321 local ok, err = self:transaction(function() return self:execute(set_names_query:format(charset)); end);
319 325
320 if driver == "MySQL" then 326 if driver == "MySQL" then
321 local ok, actual_charset = self:transaction(function () 327 local ok, actual_charset = self:transaction(function ()
322 return self:select"SHOW SESSION VARIABLES LIKE 'character_set_client'"; 328 return self:select"SHOW SESSION VARIABLES LIKE 'character_set_client'";
323 end); 329 end);
330 local charset_ok;
324 for row in actual_charset do 331 for row in actual_charset do
325 if row[2] ~= charset then 332 if row[2] ~= charset then
326 log("error", "MySQL %s is actually %q (expected %q)", row[1], row[2], charset); 333 log("error", "MySQL %s is actually %q (expected %q)", row[1], row[2], charset);
327 return false, "Failed to set connection encoding"; 334 charset_ok = false;
328 end 335 end
336 end
337 if not charset_ok then
338 return false, "Failed to set connection encoding";
329 end 339 end
330 end 340 end
331 341
332 return true; 342 return true;
333 end 343 end