def exec(self, sql: SqlText, inputs: tuple[Any, ...] = tuple()
) -> DbCursor:
- """Wrapper around sqlite3.Connection.execute."""
- return self._conn.execute(sql, inputs)
-
- def exec_on_values(self, sql: SqlText, inputs: tuple[Any, ...]
- ) -> DbCursor:
- """Wraps .exec on inputs, affixes to sql proper ' VALUES (?, …)'."""
- q_marks = '(' + ','.join(['?'] * len(inputs)) + ')'
- return self._conn.execute(f'{sql} VALUES {q_marks}', inputs)
+ """Wrapper around sqlite3.Connection.execute, building '?' if inputs"""
+ if len(inputs) > 0:
+ q_marks = ('?' if len(inputs) == 1
+ else '(' + ','.join(['?'] * len(inputs)) + ')')
+ return self._conn.execute(SqlText(f'{sql} {q_marks}'), inputs)
+ return self._conn.execute(sql)
def exec_script(self, sql: SqlText) -> DbCursor:
"""Wrapper around sqlite3.Connection.executescript."""
@classmethod
def get_one(cls, conn: DbConn, id_: str | Hash) -> Self:
"""Return single entry of id_ from DB."""
- sql = SqlText(f'SELECT * FROM {cls._table_name} '
- f'WHERE {cls.id_name} = ?')
+ sql = SqlText(f'SELECT * FROM {cls._table_name} WHERE {cls.id_name} =')
id__ = id_.bytes if isinstance(id_, Hash) else id_
row = conn.exec(sql, (id__,)).fetchone()
if not row:
elif isinstance(val, Hash):
val = val.bytes
vals += [val]
- return conn.exec_on_values(SqlText(f'REPLACE INTO {self._table_name}'),
- tuple(vals))
+ return conn.exec(SqlText(f'REPLACE INTO {self._table_name} VALUES'),
+ tuple(vals))
rows = conn.exec(SqlText('SELECT * FROM files')).fetchall()
for row in [list(r) for r in rows]:
row[-1] = cb(row[0])
- conn.exec_on_values(SqlText('REPLACE INTO files'), tuple(row))
+ conn.exec(SqlText('REPLACE INTO files VALUES'), tuple(row))
def _mig_2_calc_digests(conn: DbConn) -> None:
if _LEGIT_YES != reply:
raise HandledException('Migration aborted!')
for path in missing:
- conn.exec(SqlText('DELETE FROM files WHERE rel_path = ?'), (path,))
+ conn.exec(SqlText('DELETE FROM files WHERE rel_path ='), (path,))
def hexdigest_file(path):
print(f'Calculating digest for: {path}')
) -> list[Self]:
"""Return YoutubeQueries containing YoutubeVideo's ID in results."""
sql = SqlText('SELECT query_id FROM '
- 'yt_query_results WHERE video_id = ?')
+ 'yt_query_results WHERE video_id =')
query_ids = conn.exec(sql, (video_id,)).fetchall()
return [cls.get_one(conn, query_id_tup[0])
for query_id_tup in query_ids]
def get_all_for_query(cls, conn: DbConn, query_id: QueryId) -> list[Self]:
"""Return all videos for query of query_id."""
sql = SqlText('SELECT video_id '
- 'FROM yt_query_results WHERE query_id = ?')
+ 'FROM yt_query_results WHERE query_id =')
video_ids = conn.exec(sql, (query_id,)).fetchall()
return [cls.get_one(conn, video_id_tup[0])
for video_id_tup in video_ids]
def save_to_query(self, conn: DbConn, query_id: QueryId) -> None:
"""Save inclusion of self in results to query of query_id."""
- conn.exec_on_values(SqlText('REPLACE INTO yt_query_results'),
- (query_id, self.id_))
+ conn.exec(SqlText('REPLACE INTO yt_query_results VALUES'),
+ (query_id, self.id_))
class VideoFile(DbData):
@classmethod
def get_by_yt_id(cls, conn: DbConn, yt_id: YoutubeId) -> Self:
"""Return VideoFile of .yt_id."""
- sql = SqlText(f'SELECT * FROM {cls._table_name} WHERE yt_id = ?')
+ sql = SqlText(f'SELECT * FROM {cls._table_name} WHERE yt_id =')
row = conn.exec(sql, (yt_id,)).fetchone()
if not row:
raise NotFoundException(f'no entry for file to Youtube ID {yt_id}')
file.unlink_locally()
print(f'SYNC: purging off DB: {file.digest.b64} ({file.rel_path})')
conn.exec(
- SqlText(f'DELETE FROM {cls._table_name} WHERE digest = ?'),
+ SqlText(f'DELETE FROM {cls._table_name} WHERE digest ='),
(file.digest.bytes,))