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