Module refinery.units.formats.archive.xtsql
Expand source code Browse git
from __future__ import annotations
import functools
import sqlite3
import sys
from refinery.lib import json
from refinery.units.formats import PathExtractorUnit, UnpackResult
class xtsql(PathExtractorUnit):
"""
Extract files from SQLite3 databases.
"""
def unpack(self, data: bytearray):
def _json(object):
return json.dumps(object, tojson=json.bytes_as_string)
if sys.version_info[:2] < (3, 11):
raise NotImplementedError(F'python 3.11 is required to use {self.__class__.__name__}.')
database = sqlite3.connect(':memory:')
database.text_factory = bytes
database.deserialize(data)
database.setlimit(sqlite3.SQLITE_LIMIT_LENGTH, len(data))
cursor = database.cursor()
result: dict[str, list[dict[str, int | float | str | bytes]]] = {}
listing: list[tuple[bytes]] = cursor.execute(
'SELECT name FROM sqlite_master WHERE type = ?', ('table',)).fetchall()
for (name,) in listing:
table = name.decode('utf8')
quoted = table.replace('"', '""')
select = F'SELECT * FROM "{quoted}"'
try:
if any(step[1] == B'VOpen' for step in cursor.execute(F'EXPLAIN {select}')):
self.log_info(F'skipping {table}, which does not store its own rows')
continue
rows = cursor.execute(select).fetchall()
except sqlite3.Error as error:
self.log_warn(F'failed to read table {table}: {error!s}')
continue
names = [column[0] for column in cursor.description]
result[table] = [dict(zip(names, row)) for row in rows]
yield UnpackResult('db', functools.partial(_json, result))
for table, rows in result.items():
yield UnpackResult(F'db/{table}', functools.partial(_json, rows))
for k, row in enumerate(rows):
root = F'db/{table}/{k}'
yield UnpackResult(root, functools.partial(_json, row))
for name, value in row.items():
path = F'{root}/{name}'
if value is None:
continue
if isinstance(value, (int, float)):
value = str(value)
if isinstance(value, str):
value = value.encode(self.codec)
if isinstance(value, bytes):
yield UnpackResult(path, value)
@classmethod
def handles(cls, data):
return memoryview(data)[:15] == B'SQLite format 3'
Classes
class xtsql (*paths, exclude=None, list=False, join_path=False, drop_path=False, fuzzy=0, exact=False, regex=False, path=b'path')-
Extract files from SQLite3 databases.
Expand source code Browse git
class xtsql(PathExtractorUnit): """ Extract files from SQLite3 databases. """ def unpack(self, data: bytearray): def _json(object): return json.dumps(object, tojson=json.bytes_as_string) if sys.version_info[:2] < (3, 11): raise NotImplementedError(F'python 3.11 is required to use {self.__class__.__name__}.') database = sqlite3.connect(':memory:') database.text_factory = bytes database.deserialize(data) database.setlimit(sqlite3.SQLITE_LIMIT_LENGTH, len(data)) cursor = database.cursor() result: dict[str, list[dict[str, int | float | str | bytes]]] = {} listing: list[tuple[bytes]] = cursor.execute( 'SELECT name FROM sqlite_master WHERE type = ?', ('table',)).fetchall() for (name,) in listing: table = name.decode('utf8') quoted = table.replace('"', '""') select = F'SELECT * FROM "{quoted}"' try: if any(step[1] == B'VOpen' for step in cursor.execute(F'EXPLAIN {select}')): self.log_info(F'skipping {table}, which does not store its own rows') continue rows = cursor.execute(select).fetchall() except sqlite3.Error as error: self.log_warn(F'failed to read table {table}: {error!s}') continue names = [column[0] for column in cursor.description] result[table] = [dict(zip(names, row)) for row in rows] yield UnpackResult('db', functools.partial(_json, result)) for table, rows in result.items(): yield UnpackResult(F'db/{table}', functools.partial(_json, rows)) for k, row in enumerate(rows): root = F'db/{table}/{k}' yield UnpackResult(root, functools.partial(_json, row)) for name, value in row.items(): path = F'{root}/{name}' if value is None: continue if isinstance(value, (int, float)): value = str(value) if isinstance(value, str): value = value.encode(self.codec) if isinstance(value, bytes): yield UnpackResult(path, value) @classmethod def handles(cls, data): return memoryview(data)[:15] == B'SQLite format 3'Ancestors
Subclasses
Class variables
var reverse-
The type of the None singleton.
Methods
def unpack(self, data)-
Expand source code Browse git
def unpack(self, data: bytearray): def _json(object): return json.dumps(object, tojson=json.bytes_as_string) if sys.version_info[:2] < (3, 11): raise NotImplementedError(F'python 3.11 is required to use {self.__class__.__name__}.') database = sqlite3.connect(':memory:') database.text_factory = bytes database.deserialize(data) database.setlimit(sqlite3.SQLITE_LIMIT_LENGTH, len(data)) cursor = database.cursor() result: dict[str, list[dict[str, int | float | str | bytes]]] = {} listing: list[tuple[bytes]] = cursor.execute( 'SELECT name FROM sqlite_master WHERE type = ?', ('table',)).fetchall() for (name,) in listing: table = name.decode('utf8') quoted = table.replace('"', '""') select = F'SELECT * FROM "{quoted}"' try: if any(step[1] == B'VOpen' for step in cursor.execute(F'EXPLAIN {select}')): self.log_info(F'skipping {table}, which does not store its own rows') continue rows = cursor.execute(select).fetchall() except sqlite3.Error as error: self.log_warn(F'failed to read table {table}: {error!s}') continue names = [column[0] for column in cursor.description] result[table] = [dict(zip(names, row)) for row in rows] yield UnpackResult('db', functools.partial(_json, result)) for table, rows in result.items(): yield UnpackResult(F'db/{table}', functools.partial(_json, rows)) for k, row in enumerate(rows): root = F'db/{table}/{k}' yield UnpackResult(root, functools.partial(_json, row)) for name, value in row.items(): path = F'{root}/{name}' if value is None: continue if isinstance(value, (int, float)): value = str(value) if isinstance(value, str): value = value.encode(self.codec) if isinstance(value, bytes): yield UnpackResult(path, value)
Inherited members
PathExtractorUnit:CustomJoinBehaviourCustomPathSeparatorFilterEverythingRequiresactassemblecarvedclosecodecconsolefilterfinishhandlesis_quietis_reversibleisattylabelledleniencylog_alwayslog_debuglog_detachlog_faillog_infolog_levellog_warnloggernamenozzleoptional_dependenciesreadread1required_dependenciesresetrunsourcesuperinit
UnitBase: