Mercurial > prosody-modules
comparison mod_storage_xmlarchive/mod_storage_xmlarchive.lua @ 2398:7e922b968b44
mod_storage_xmlarchive: Find item indices for 'before' or 'after' queries and behave as if they were excluded if the items don't exist (thanks MattJ)
| author | Kim Alvefur <zash@zash.se> |
|---|---|
| date | Fri, 25 Nov 2016 23:17:13 +0100 |
| parents | 7f9bf161f640 |
| children | 913bd81a4d3c |
comparison
equal
deleted
inserted
replaced
| 2397:7f9bf161f640 | 2398:7e922b968b44 |
|---|---|
| 50 end | 50 end |
| 51 if not ok then | 51 if not ok then |
| 52 return nil, err; | 52 return nil, err; |
| 53 end | 53 end |
| 54 return id; | 54 return id; |
| 55 end | |
| 56 | |
| 57 function archive:_get_idx(username, id, dates) | |
| 58 dates = dates or self:dates(username) or empty; | |
| 59 local date = id:sub(1, 10); | |
| 60 for d = 1, #dates do | |
| 61 if date == dates[d] then | |
| 62 module:log("debug", "Loading items from %s", dates[d]); | |
| 63 local items = dm.list_load(username .. "@" .. dates[d], module.host, self.store) or empty; | |
| 64 for i = 1, #items do | |
| 65 if items[i].id == id then | |
| 66 return d, i, items; | |
| 67 end | |
| 68 end | |
| 69 return; -- Assuming no duplicates | |
| 70 elseif date > dates[d] then | |
| 71 return; -- List is assumed to be sorted | |
| 72 end | |
| 73 end | |
| 55 end | 74 end |
| 56 | 75 |
| 57 function archive:find(username, query) | 76 function archive:find(username, query) |
| 58 username = username or "@"; | 77 username = username or "@"; |
| 59 query = query or empty; | 78 query = query or empty; |
| 79 | 98 |
| 80 local limit = query.limit; | 99 local limit = query.limit; |
| 81 local start_day, step, last_day = 1, 1, #dates; | 100 local start_day, step, last_day = 1, 1, #dates; |
| 82 local count = 0; | 101 local count = 0; |
| 83 local rev = query.reverse; | 102 local rev = query.reverse; |
| 84 local in_range = not (query.after or query.before); | 103 if query.start then |
| 85 if query.after or query.start then | 104 local d = dt.date(query.start); |
| 86 local d = query.after and query.after:sub(1, 10) or dt.date(query.start); | |
| 87 for i = 1, #dates do | 105 for i = 1, #dates do |
| 88 if dates[i] == d then | 106 if dates[i] == d then |
| 89 start_day = i; break; | 107 start_day = i; break; |
| 90 end | 108 end |
| 91 end | 109 end |
| 92 end | 110 end |
| 93 if query.before or query["end"] then | 111 if query["end"] then |
| 94 local d = query.before and query.before:sub(1, 10) or dt.date(query["end"]); | 112 local d = dt.date(query["end"]); |
| 95 for i = #dates, 1, -1 do | 113 for i = #dates, 1, -1 do |
| 96 if dates[i] == d then | 114 if dates[i] == d then |
| 97 last_day = i; break; | 115 last_day = i; break; |
| 98 end | 116 end |
| 99 end | 117 end |
| 100 end | 118 end |
| 119 local items, xmlfile; | |
| 120 local first_item, last_item; | |
| 101 if rev then | 121 if rev then |
| 102 start_day, step, last_day = last_day, -step, start_day; | 122 start_day, step, last_day = last_day, -step, start_day; |
| 103 end | 123 if query.before then |
| 104 local items, xmlfile; | 124 local before_day, before_item, items_ = self:_get_idx(username, query.before, dates); |
| 105 local first_item, last_item; | 125 if before_day and before_day <= start_day then |
| 126 if before_item then | |
| 127 first_item = before_item - 1; | |
| 128 else | |
| 129 first_item = #items_; | |
| 130 end | |
| 131 last_item = 1; | |
| 132 start_day = before_day; | |
| 133 items = items_; | |
| 134 end | |
| 135 end | |
| 136 elseif query.after then | |
| 137 local after_day, after_item, items_ = self:_get_idx(username, query.after, dates); | |
| 138 if after_day and after_day >= start_day then | |
| 139 if after_item then | |
| 140 first_item = after_item + 1; | |
| 141 else | |
| 142 first_item = 1; | |
| 143 end | |
| 144 last_item = #items_; | |
| 145 start_day = after_day; | |
| 146 items = items_; | |
| 147 end | |
| 148 end | |
| 106 | 149 |
| 107 return function () | 150 return function () |
| 108 if limit and count >= limit then if xmlfile then xmlfile:close() end return; end | 151 if limit and count >= limit then if xmlfile then xmlfile:close() end return; end |
| 109 local filename; | 152 local filename; |
| 110 | 153 |
| 111 for d = start_day, last_day, step do | 154 for d = start_day, last_day, step do |
| 112 if d ~= start_day or not items then | 155 if not items then |
| 113 module:log("debug", "Loading items from %s", dates[d]); | 156 module:log("debug", "Loading items from %s", dates[d]); |
| 114 start_day = d; | 157 start_day = d; |
| 115 items = dm.list_load(username .. "@" .. dates[d], module.host, self.store) or empty; | 158 items = dm.list_load(username .. "@" .. dates[d], module.host, self.store) or empty; |
| 116 if not rev then | 159 if not rev then |
| 117 first_item, last_item = 1, #items; | 160 first_item, last_item = 1, #items; |
| 142 if not xmlfile then | 185 if not xmlfile then |
| 143 module:log("error", "Error: %s", ferr); | 186 module:log("error", "Error: %s", ferr); |
| 144 return; | 187 return; |
| 145 end | 188 end |
| 146 end | 189 end |
| 147 if in_range | 190 if (not q_with or i_with == q_with) |
| 148 and (not q_with or i_with == q_with) | |
| 149 and (not q_start or i_when >= q_start) | 191 and (not q_start or i_when >= q_start) |
| 150 and (not q_end or i_when <= q_end) then | 192 and (not q_end or i_when <= q_end) then |
| 151 count = count + 1; | 193 count = count + 1; |
| 152 first_item = i + step; | 194 first_item = i + step; |
| 153 | 195 |
| 162 local stanza = result; | 204 local stanza = result; |
| 163 result = nil; | 205 result = nil; |
| 164 return item.id, stanza, i_when, i_with; | 206 return item.id, stanza, i_when, i_with; |
| 165 end | 207 end |
| 166 end | 208 end |
| 167 if (rev and item.id == query.after) or | 209 end |
| 168 (not rev and item.id == query.before) then | 210 items = nil; |
| 169 in_range = false; | |
| 170 limit = count; | |
| 171 end | |
| 172 if (rev and item.id == query.before) or | |
| 173 (not rev and item.id == query.after) then | |
| 174 in_range = true; | |
| 175 end | |
| 176 end | |
| 177 if xmlfile then | 211 if xmlfile then |
| 178 xmlfile:close(); | 212 xmlfile:close(); |
| 179 xmlfile = nil; | 213 xmlfile = nil; |
| 180 end | 214 end |
| 181 end | 215 end |
