drop usage of pysqlite Cursor
This commit is contained in:
parent
0b1d96fce0
commit
b5c6134d80
@ -4,9 +4,8 @@
|
|||||||
# fixme: lossy utf8 handling
|
# fixme: lossy utf8 handling
|
||||||
# fixme: progress
|
# fixme: progress
|
||||||
|
|
||||||
from sqlite3 import Cursor
|
|
||||||
from sqlite3 import dbapi2 as sqlite
|
from sqlite3 import dbapi2 as sqlite
|
||||||
from typing import Any, Iterable, List
|
from typing import Any, Iterable, List, Optional
|
||||||
|
|
||||||
|
|
||||||
class DBProxy:
|
class DBProxy:
|
||||||
@ -39,24 +38,51 @@ class DBProxy:
|
|||||||
# Querying
|
# Querying
|
||||||
################
|
################
|
||||||
|
|
||||||
def all(self, sql: str, *args) -> List:
|
def _query(self, sql: str, *args, first_row_only: bool = False) -> List[List]:
|
||||||
return self.execute(sql, *args).fetchall()
|
# mark modified?
|
||||||
|
s = sql.strip().lower()
|
||||||
|
for stmt in "insert", "update", "delete":
|
||||||
|
if s.startswith(stmt):
|
||||||
|
self.mod = True
|
||||||
|
# fetch rows
|
||||||
|
curs = self._db.execute(sql, args)
|
||||||
|
if first_row_only:
|
||||||
|
row = curs.fetchone()
|
||||||
|
curs.close()
|
||||||
|
if row is not None:
|
||||||
|
return [row]
|
||||||
|
else:
|
||||||
|
return []
|
||||||
|
else:
|
||||||
|
return curs.fetchall()
|
||||||
|
|
||||||
def first(self, sql: str, *args) -> Any:
|
# Query shortcuts
|
||||||
c = self.execute(sql, *args)
|
###################
|
||||||
res = c.fetchone()
|
|
||||||
c.close()
|
def all(self, sql: str, *args) -> List:
|
||||||
return res
|
return self._query(sql, *args)
|
||||||
|
|
||||||
def list(self, sql: str, *args) -> List:
|
def list(self, sql: str, *args) -> List:
|
||||||
return [x[0] for x in self.execute(sql, *args)]
|
return [x[0] for x in self._query(sql, *args)]
|
||||||
|
|
||||||
def scalar(self, sql: str, *args) -> Any:
|
def first(self, sql: str, *args) -> Optional[List]:
|
||||||
res = self.execute(sql, *args).fetchone()
|
rows = self._query(sql, *args, first_row_only=True)
|
||||||
if res:
|
if rows:
|
||||||
return res[0]
|
return rows[0]
|
||||||
|
else:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
def scalar(self, sql: str, *args) -> Optional[Any]:
|
||||||
|
rows = self._query(sql, *args, first_row_only=True)
|
||||||
|
if rows:
|
||||||
|
return rows[0][0]
|
||||||
|
else:
|
||||||
|
return None
|
||||||
|
|
||||||
|
# execute used to return a pysqlite cursor, but now is synonymous
|
||||||
|
# with .all()
|
||||||
|
execute = all
|
||||||
|
|
||||||
# Updates
|
# Updates
|
||||||
################
|
################
|
||||||
|
|
||||||
@ -67,15 +93,3 @@ class DBProxy:
|
|||||||
def executescript(self, sql: str) -> None:
|
def executescript(self, sql: str) -> None:
|
||||||
self.mod = True
|
self.mod = True
|
||||||
self._db.executescript(sql)
|
self._db.executescript(sql)
|
||||||
|
|
||||||
# Cursor API
|
|
||||||
###############
|
|
||||||
|
|
||||||
def execute(self, sql: str, *args) -> Cursor:
|
|
||||||
s = sql.strip().lower()
|
|
||||||
# mark modified?
|
|
||||||
for stmt in "insert", "update", "delete":
|
|
||||||
if s.startswith(stmt):
|
|
||||||
self.mod = True
|
|
||||||
res = self._db.execute(sql, args)
|
|
||||||
return res
|
|
||||||
|
@ -8,7 +8,6 @@ import io
|
|||||||
import json
|
import json
|
||||||
import os
|
import os
|
||||||
import random
|
import random
|
||||||
import sqlite3
|
|
||||||
from typing import Any, Dict, List, Optional, Tuple, Union
|
from typing import Any, Dict, List, Optional, Tuple, Union
|
||||||
|
|
||||||
import anki
|
import anki
|
||||||
@ -32,7 +31,7 @@ class UnexpectedSchemaChange(Exception):
|
|||||||
|
|
||||||
|
|
||||||
class Syncer:
|
class Syncer:
|
||||||
cursor: Optional[sqlite3.Cursor]
|
chunkRows: Optional[List[List]]
|
||||||
|
|
||||||
def __init__(self, col: anki.storage._Collection, server=None) -> None:
|
def __init__(self, col: anki.storage._Collection, server=None) -> None:
|
||||||
self.col = col.weakref()
|
self.col = col.weakref()
|
||||||
@ -247,11 +246,11 @@ class Syncer:
|
|||||||
|
|
||||||
def prepareToChunk(self) -> None:
|
def prepareToChunk(self) -> None:
|
||||||
self.tablesLeft = ["revlog", "cards", "notes"]
|
self.tablesLeft = ["revlog", "cards", "notes"]
|
||||||
self.cursor = None
|
self.chunkRows = None
|
||||||
|
|
||||||
def cursorForTable(self, table) -> sqlite3.Cursor:
|
def getChunkRows(self, table) -> List[List]:
|
||||||
lim = self.usnLim()
|
lim = self.usnLim()
|
||||||
x = self.col.db.execute
|
x = self.col.db.all
|
||||||
d = (self.maxUsn, lim)
|
d = (self.maxUsn, lim)
|
||||||
if table == "revlog":
|
if table == "revlog":
|
||||||
return x(
|
return x(
|
||||||
@ -280,14 +279,15 @@ from notes where %s"""
|
|||||||
lim = 250
|
lim = 250
|
||||||
while self.tablesLeft and lim:
|
while self.tablesLeft and lim:
|
||||||
curTable = self.tablesLeft[0]
|
curTable = self.tablesLeft[0]
|
||||||
if not self.cursor:
|
if not self.chunkRows:
|
||||||
self.cursor = self.cursorForTable(curTable)
|
self.chunkRows = self.getChunkRows(curTable)
|
||||||
rows = self.cursor.fetchmany(lim)
|
rows = self.chunkRows[:lim]
|
||||||
|
self.chunkRows = self.chunkRows[lim:]
|
||||||
fetched = len(rows)
|
fetched = len(rows)
|
||||||
if fetched != lim:
|
if fetched != lim:
|
||||||
# table is empty
|
# table is empty
|
||||||
self.tablesLeft.pop(0)
|
self.tablesLeft.pop(0)
|
||||||
self.cursor = None
|
self.chunkRows = None
|
||||||
# mark the objects as having been sent
|
# mark the objects as having been sent
|
||||||
self.col.db.execute(
|
self.col.db.execute(
|
||||||
"update %s set usn=? where usn=-1" % curTable, self.maxUsn
|
"update %s set usn=? where usn=-1" % curTable, self.maxUsn
|
||||||
|
Loading…
Reference in New Issue
Block a user