Software /
code /
prosody
Comparison
plugins/mod_storage_sql.lua @ 13143:3ec48555b773
mod_storage_sql: Add UPSERT support
Currently limited to SQLite3 for lack of testing on other databases.
Adds a migration to replace the non-UNIQUE prosody_index, renaming it
prosody_unique_index since ALTER INDEX does not seem to be portable.
author | Kim Alvefur <zash@zash.se> |
---|---|
date | Sat, 10 Jun 2023 15:44:09 +0200 |
parent | 12977:74b9e05af71e |
child | 13144:033ea8b46d6a |
comparison
equal
deleted
inserted
replaced
13142:879a6a33c21b | 13143:3ec48555b773 |
---|---|
201 local insert_sql = [[ | 201 local insert_sql = [[ |
202 INSERT INTO "prosody" | 202 INSERT INTO "prosody" |
203 ("host","user","store","key","type","value") | 203 ("host","user","store","key","type","value") |
204 VALUES (?,?,?,?,?,?); | 204 VALUES (?,?,?,?,?,?); |
205 ]]; | 205 ]]; |
206 local upsert_sql = [[ | |
207 INSERT INTO "prosody" | |
208 ("host","user","store","key","type","value") | |
209 VALUES (?,?,?,?,?,?) | |
210 ON CONFLICT ("host", "user","store", "key") | |
211 DO UPDATE SET "type"=?, "value"=?; | |
212 ]]; | |
206 local select_extradata_sql = [[ | 213 local select_extradata_sql = [[ |
207 SELECT "type", "value" | 214 SELECT "type", "value" |
208 FROM "prosody" | 215 FROM "prosody" |
209 WHERE "host"=? AND "user"=? AND "store"=? AND "key"=? | 216 WHERE "host"=? AND "user"=? AND "store"=? AND "key"=? |
210 LIMIT 1; | 217 LIMIT 1; |
211 ]]; | 218 ]]; |
212 for key, data in pairs(keydatas) do | 219 for key, data in pairs(keydatas) do |
213 if type(key) == "string" and key ~= "" then | 220 if type(key) == "string" and key ~= "" and engine.params.driver == "SQLite3" and data ~= self.remove then |
221 local t, value = assert(serialize(data)); | |
222 engine:insert(upsert_sql, host, username or "", self.store, key, t, value, t, value); | |
223 elseif type(key) == "string" and key ~= "" then | |
214 engine:delete(delete_sql, | 224 engine:delete(delete_sql, |
215 host, username or "", self.store, key); | 225 host, username or "", self.store, key); |
216 if data ~= self.remove then | 226 if data ~= self.remove then |
217 local t, value = assert(serialize(data)); | 227 local t, value = assert(serialize(data)); |
218 engine:insert(insert_sql, host, username or "", self.store, key, t, value); | 228 engine:insert(insert_sql, host, username or "", self.store, key, t, value); |
703 Column { name="user", type="TEXT", nullable=false }; | 713 Column { name="user", type="TEXT", nullable=false }; |
704 Column { name="store", type="TEXT", nullable=false }; | 714 Column { name="store", type="TEXT", nullable=false }; |
705 Column { name="key", type="TEXT", nullable=false }; | 715 Column { name="key", type="TEXT", nullable=false }; |
706 Column { name="type", type="TEXT", nullable=false }; | 716 Column { name="type", type="TEXT", nullable=false }; |
707 Column { name="value", type="MEDIUMTEXT", nullable=false }; | 717 Column { name="value", type="MEDIUMTEXT", nullable=false }; |
708 Index { name="prosody_index", "host", "user", "store", "key" }; | 718 Index { name = "prosody_unique_index"; unique = engine.params.driver ~= "MySQL"; "host"; "user"; "store"; "key" }; |
709 }; | 719 }; |
710 engine:transaction(function() | 720 engine:transaction(function() |
711 ProsodyTable:create(engine); | 721 ProsodyTable:create(engine); |
712 end); | 722 end); |
713 | 723 |
801 end | 811 end |
802 end); | 812 end); |
803 success,err = engine:transaction(function() | 813 success,err = engine:transaction(function() |
804 return engine:execute(check_encoding_query, params.database, | 814 return engine:execute(check_encoding_query, params.database, |
805 engine.charset, engine.charset.."_bin"); | 815 engine.charset, engine.charset.."_bin"); |
806 end); | 816 end); |
807 if not success then | 817 if not success then |
808 module:log("error", "Failed to check/upgrade database encoding: %s", err or "unknown error"); | 818 module:log("error", "Failed to check/upgrade database encoding: %s", err or "unknown error"); |
809 return false; | 819 return false; |
810 end | 820 end |
811 end | 821 else |
822 local indices = {}; | |
823 engine:transaction(function () | |
824 if params.driver == "SQLite3" then | |
825 for row in engine:select [[SELECT "name" from "sqlite_schema" WHERE "name"='prosody_index';]] do | |
826 indices[row[1]] = true; | |
827 end | |
828 elseif params.driver == "PostgreSQL" then | |
829 for row in engine:select [[SELECT "relname" FROM "pg_class" WHERE "relname"='prosody_index';]] do | |
830 indices[row[1]] = true; | |
831 end | |
832 end | |
833 end) | |
834 if apply_changes then | |
835 local success = engine:transaction(function () | |
836 return assert(engine:execute([[DROP INDEX "prosody_index";]])); | |
837 end); | |
838 if not success then | |
839 module:log("error", "Failed to delete obsolete index \"prosody_index\""); | |
840 return false; | |
841 end | |
842 else | |
843 changes = changes or indices["prosody_index"]; | |
844 end | |
845 end | |
812 return changes; | 846 return changes; |
813 end | 847 end |
814 | 848 |
815 local function normalize_database(driver, database) -- luacheck: ignore 431/driver | 849 local function normalize_database(driver, database) -- luacheck: ignore 431/driver |
816 if driver == "SQLite3" and database ~= ":memory:" then | 850 if driver == "SQLite3" and database ~= ":memory:" then |