7 """ |
7 """ |
8 __docformat__ = "restructuredtext en" |
8 __docformat__ = "restructuredtext en" |
9 |
9 |
10 from logilab.common.decorators import cached, clear_cache, copy_cache |
10 from logilab.common.decorators import cached, clear_cache, copy_cache |
11 |
11 |
12 from rql import nodes |
12 from rql import nodes, stmts |
13 |
13 |
14 from cubicweb import NotAnEntity |
14 from cubicweb import NotAnEntity |
15 |
15 |
16 |
16 |
17 class ResultSet(object): |
17 class ResultSet(object): |
238 result.append(rset) |
238 result.append(rset) |
239 else: |
239 else: |
240 rset = mapping[key] |
240 rset = mapping[key] |
241 rset.rows.append(self.rows[idx]) |
241 rset.rows.append(self.rows[idx]) |
242 rset.description.append(self.description[idx]) |
242 rset.description.append(self.description[idx]) |
243 |
|
244 |
|
245 for rset in result: |
243 for rset in result: |
246 rset.rowcount = len(rset.rows) |
244 rset.rowcount = len(rset.rows) |
247 if return_dict: |
245 if return_dict: |
248 return mapping |
246 return mapping |
249 else: |
247 else: |
250 return result |
248 return result |
|
249 |
|
250 def limited_rql(self): |
|
251 """return a printable rql for the result set associated to the object, |
|
252 with limit/offset correctly set according to maximum page size and |
|
253 currently displayed page when necessary |
|
254 """ |
|
255 # try to get page boundaries from the navigation component |
|
256 # XXX we should probably not have a ref to this component here (eg in |
|
257 # cubicweb.common) |
|
258 nav = self.vreg['components'].select_or_none('navigation', self.req, |
|
259 rset=self) |
|
260 if nav: |
|
261 start, stop = nav.page_boundaries() |
|
262 rql = self._limit_offset_rql(stop - start, start) |
|
263 # result set may have be limited manually in which case navigation won't |
|
264 # apply |
|
265 elif self.limited: |
|
266 rql = self._limit_offset_rql(*self.limited) |
|
267 # navigation component doesn't apply and rset has not been limited, no |
|
268 # need to limit query |
|
269 else: |
|
270 rql = self.printable_rql() |
|
271 return rql |
|
272 |
|
273 def _limit_offset_rql(self, limit, offset): |
|
274 rqlst = self.syntax_tree() |
|
275 if len(rqlst.children) == 1: |
|
276 select = rqlst.children[0] |
|
277 olimit, ooffset = select.limit, select.offset |
|
278 select.limit, select.offset = limit, offset |
|
279 rql = rqlst.as_string(kwargs=self.args) |
|
280 # restore original limit/offset |
|
281 select.limit, select.offset = olimit, ooffset |
|
282 else: |
|
283 newselect = stmts.Select() |
|
284 newselect.limit = limit |
|
285 newselect.offset = offset |
|
286 aliases = [nodes.VariableRef(newselect.get_variable(vref.name, i)) |
|
287 for i, vref in enumerate(rqlst.selection)] |
|
288 newselect.set_with([nodes.SubQuery(aliases, rqlst)], check=False) |
|
289 newunion = stmts.Union() |
|
290 newunion.append(newselect) |
|
291 rql = rqlst.as_string(kwargs=self.args) |
|
292 rqlst.parent = None |
|
293 return rql |
251 |
294 |
252 def limit(self, limit, offset=0, inplace=False): |
295 def limit(self, limit, offset=0, inplace=False): |
253 """limit the result set to the given number of rows optionaly starting |
296 """limit the result set to the given number of rows optionaly starting |
254 from an index different than 0 |
297 from an index different than 0 |
255 |
298 |
315 for i in xrange(len(self)): |
358 for i in xrange(len(self)): |
316 # may have None values in case of outer join (or aggregat on eid |
359 # may have None values in case of outer join (or aggregat on eid |
317 # hacks) |
360 # hacks) |
318 if self.rows[i][col] is not None: |
361 if self.rows[i][col] is not None: |
319 yield self.get_entity(i, col) |
362 yield self.get_entity(i, col) |
|
363 |
|
364 def complete_entity(self, row, col=0, skip_bytes=True): |
|
365 """short cut to get an completed entity instance for a particular |
|
366 row (all instance's attributes have been fetched) |
|
367 """ |
|
368 entity = self.get_entity(row, col) |
|
369 entity.complete(skip_bytes=skip_bytes) |
|
370 return entity |
320 |
371 |
321 @cached |
372 @cached |
322 def get_entity(self, row, col=None): |
373 def get_entity(self, row, col=None): |
323 """special method for query retreiving a single entity, returns a |
374 """special method for query retreiving a single entity, returns a |
324 partially initialized Entity instance. |
375 partially initialized Entity instance. |