| 267 | |
| 268 | |
| 269 | class QueryResult: |
| 270 | |
| 271 | def __init__(self, sql, connection): |
| 272 | |
| 273 | self.sql = sql |
| 274 | self.connection = connection |
| 275 | |
| 276 | cursor, duration = self.execute_query() |
| 277 | |
| 278 | self._description = cursor.description or [] |
| 279 | self._data = [list(r) for r in cursor.fetchall()] |
| 280 | self.duration = duration |
| 281 | |
| 282 | cursor.close() |
| 283 | |
| 284 | self._headers = self._get_headers() |
| 285 | self._summary = {} |
| 286 | |
| 287 | @property |
| 288 | def data(self): |
| 289 | return self._data or [] |
| 290 | |
| 291 | @property |
| 292 | def headers(self): |
| 293 | return self._headers or [] |
| 294 | |
| 295 | @property |
| 296 | def header_strings(self): |
| 297 | return [str(h) for h in self.headers] |
| 298 | |
| 299 | def _get_headers(self): |
| 300 | return [ |
| 301 | ColumnHeader(d[0]) for d in self._description |
| 302 | ] if self._description else [ColumnHeader("--")] |
| 303 | |
| 304 | def _get_numerics(self): |
| 305 | if hasattr(self.connection.Database, "NUMBER"): |
| 306 | return [ |
| 307 | ix for ix, c in enumerate(self._description) |
| 308 | if hasattr(c, "type_code") and c.type_code in self.connection.Database.NUMBER.values |
| 309 | ] |
| 310 | elif self.data: |
| 311 | d = self.data[0] |
| 312 | return [ |
| 313 | ix for ix, _ in enumerate(self._description) |
| 314 | if not isinstance(d[ix], str) and str(d[ix]).isnumeric() |
| 315 | ] |
| 316 | return [] |
| 317 | |
| 318 | def _get_transforms(self): |
| 319 | transforms = dict(app_settings.EXPLORER_TRANSFORMS) |
| 320 | return [ |
| 321 | (ix, transforms[str(h)]) |
| 322 | for ix, h in enumerate(self.headers) if str(h) in transforms.keys() |
| 323 | ] |
| 324 | |
| 325 | def column(self, ix): |
| 326 | return [r[ix] for r in self.data] |
no outgoing calls