Switch to newdb

Remove the use_newdb_tweak and various bits of code used to support
dual use.
This commit is contained in:
Kovid Goyal 2013-08-19 11:16:15 +05:30
parent 6690397d1a
commit 239407d73b
18 changed files with 55 additions and 146 deletions

View File

@ -122,17 +122,3 @@ def get_data_as_dict(self, prefix=None, authors_as_string=False, ids=None, conve
x['available_formats'] = [i.upper() for i in formats.split(',')]
return data
def get_db_loader():
from calibre.utils.config_base import tweaks
if tweaks.get('use_new_db', False):
from calibre.db.legacy import LibraryDatabase as cls
import apsw
errs = (apsw.Error,)
else:
from calibre.library.database2 import LibraryDatabase2 as cls
from calibre.library.sqlite import sqlite, DatabaseException
errs = (sqlite.Error, DatabaseException)
return cls, errs

View File

@ -21,7 +21,6 @@ CATEGORY_SORTS = ('name', 'popularity', 'rating') # This has to be a tuple not
class Tag(object):
if tweaks.get('use_new_db', False):
__slots__ = ('name', 'original_name', 'id', 'count', 'state', 'is_hierarchical',
'is_editable', 'is_searchable', 'id_set', 'avg_rating', 'sort',
'use_sort_as_name', 'tooltip', 'icon', 'category')

View File

@ -84,7 +84,7 @@ Everything after the -- is passed to the script.
return parser
def reinit_db_new(dbpath, callback=None, sql_dump=None):
def reinit_db(dbpath, callback=None, sql_dump=None):
from calibre.db.backend import Connection
import apsw
import shutil
@ -92,6 +92,8 @@ def reinit_db_new(dbpath, callback=None, sql_dump=None):
from contextlib import closing
if callback is None:
callback = lambda x, y: None
if not os.path.exists(dbpath):
raise ValueError(dbpath + ' does not exist')
with closing(Connection(dbpath)) as conn:
uv = int(conn.get('PRAGMA user_version;', all=False))
@ -117,56 +119,6 @@ def reinit_db_new(dbpath, callback=None, sql_dump=None):
os.remove(dest)
prints('Database successfully re-initialized')
def reinit_db(dbpath, callback=None, sql_dump=None):
if not os.path.exists(dbpath):
raise ValueError(dbpath + ' does not exist')
from calibre.utils.config_base import tweaks
if tweaks.get('use_new_db', False):
return reinit_db_new(dbpath, callback, sql_dump)
from calibre.library.sqlite import connect
from contextlib import closing
import shutil
conn = connect(dbpath, False)
uv = conn.get('PRAGMA user_version;', all=False)
conn.execute('PRAGMA writable_schema=ON')
conn.commit()
if sql_dump is None:
sql_lines = conn.dump()
else:
sql_lines = open(sql_dump, 'rb').read()
conn.close()
dest = dbpath + '.tmp'
try:
with closing(connect(dest, False)) as nconn:
nconn.execute('create temporary table temp_sequence(id INTEGER PRIMARY KEY AUTOINCREMENT)')
nconn.commit()
if sql_dump is None:
if callable(callback):
callback(len(sql_lines), True)
for i, line in enumerate(sql_lines):
try:
nconn.execute(line)
except:
import traceback
prints('SQL line %r failed with error:'%line)
prints(traceback.format_exc())
continue
finally:
if callable(callback):
callback(i, False)
else:
nconn.executescript(sql_lines)
nconn.execute('pragma user_version=%d'%int(uv))
nconn.commit()
os.remove(dbpath)
shutil.copyfile(dest, dbpath)
finally:
if os.path.exists(dest):
os.remove(dest)
prints('Database successfully re-initialized')
def debug_device_driver():
from calibre.devices import debug
debug(ioreg_to_tmp=True, buf=sys.stdout)

View File

@ -22,8 +22,8 @@ from calibre.gui2 import (gprefs, warning_dialog, Dispatcher, error_dialog,
from calibre.gui2.actions import InterfaceAction
def db_class():
from calibre.db import get_db_loader
return get_db_loader()[0]
from calibre.db.legacy import LibraryDatabase
return LibraryDatabase
class LibraryUsageStats(object): # {{{

View File

@ -55,8 +55,8 @@ class Worker(Thread): # {{{
notify=False, replace=replace)
def doit(self):
from calibre.db import get_db_loader
newdb = get_db_loader()[0](self.loc, is_second_db=True)
from calibre.db.legacy import LibraryDatabase
newdb = LibraryDatabase(self.loc, is_second_db=True)
with closing(newdb):
self._doit(newdb)
newdb.break_cycles()

View File

@ -13,7 +13,7 @@ from PyQt4.Qt import (QDialog, QVBoxLayout, QHBoxLayout, QTreeWidget, QLabel,
from calibre.gui2.dialogs.confirm_delete import confirm
from calibre.library.check_library import CheckLibrary, CHECKS
from calibre.library.database2 import delete_file, delete_tree
from calibre.utils.recycle_bin import delete_file, delete_tree
from calibre import prints, as_unicode
from calibre.ptempfile import PersistentTemporaryFile
from calibre.library.sqlite import DBThread, OperationalError

View File

@ -85,8 +85,7 @@ class ChooseLibrary(QDialog, Ui_Dialog):
show=True)
return False
if ac in ('new', 'move'):
from calibre.db import get_db_loader
LibraryDatabase = get_db_loader()[0]
from calibre.db.legacy import LibraryDatabase
if not empty:
error_dialog(self, _('Not empty'),
_('The folder %s is not empty. Please choose an empty'

View File

@ -12,7 +12,6 @@ from calibre.gui2 import (error_dialog, question_dialog, warning_dialog,
info_dialog)
from calibre import force_unicode
from calibre.constants import filesystem_encoding
from calibre.utils.config_base import tweaks
class DBRestore(QDialog):
@ -42,10 +41,7 @@ class DBRestore(QDialog):
self.library_path = library_path
self.update_signal.connect(self.do_update, type=Qt.QueuedConnection)
if tweaks.get('use_new_db', False):
from calibre.db.restore import Restore
else:
from calibre.library.restore import Restore
self.restorer = Restore(library_path, self)
self.restorer.daemon = True

View File

@ -10,7 +10,7 @@ import functools
from PyQt4.Qt import (Qt, QApplication, QStackedWidget, QMenu, QTimer,
QSize, QSizePolicy, QStatusBar, QLabel, QFont, QAction, QTabBar)
from calibre.utils.config import prefs, tweaks
from calibre.utils.config import prefs
from calibre.utils.icu import sort_key
from calibre.constants import (isosx, __appname__, preferred_encoding,
get_version)
@ -171,8 +171,6 @@ class StatusBar(QStatusBar): # {{{
QStatusBar.__init__(self, parent)
self.version = get_version()
self.base_msg = '%s %s' % (__appname__, self.version)
if tweaks.get('use_new_db', False):
self.base_msg += ' [newdb]'
self.device_string = ''
self.update_label = UpdateLabel('')
self.total = self.current = self.selected = self.library_total = 0
@ -249,7 +247,6 @@ class GridViewButton(LayoutButton): # {{{
def __init__(self, gui):
sc = _('Shift+Alt+G')
LayoutButton.__init__(self, I('grid.png'), _('Cover Grid'), parent=gui, shortcut=sc)
if tweaks.get('use_new_db', False):
self.set_state_to_show()
self.action_toggle = QAction(self.icon(), _('Toggle') + ' ' + self.label, self)
gui.addAction(self.action_toggle)
@ -257,10 +254,6 @@ class GridViewButton(LayoutButton): # {{{
default_keys=(sc,), action=self.action_toggle)
self.action_toggle.triggered.connect(self.toggle)
self.toggled.connect(self.update_state)
self.grid_enabled = True
else:
self.setVisible(False)
self.grid_enabled = False
def update_state(self, checked):
if checked:
@ -269,11 +262,10 @@ class GridViewButton(LayoutButton): # {{{
self.set_state_to_show()
def save_state(self):
if self.grid_enabled:
gprefs['grid view visible'] = bool(self.isChecked())
def restore_state(self):
if self.grid_enabled and gprefs.get('grid view visible', False):
if gprefs.get('grid view visible', False):
self.toggle()

View File

@ -4,12 +4,14 @@ __copyright__ = '2008, Kovid Goyal <kovid at kovidgoyal.net>'
import sys, os, time, socket, traceback
from functools import partial
import apsw
from PyQt4.Qt import (QCoreApplication, QIcon, QObject, QTimer,
QPixmap, QSplashScreen, QApplication)
from calibre import prints, plugins, force_unicode
from calibre.constants import (iswindows, __appname__, isosx, DEBUG, islinux,
filesystem_encoding, get_portable_base)
from calibre.db.legacy import LibraryDatabase
from calibre.utils.ipc import gui_socket_address, RC
from calibre.gui2 import (ORG_NAME, APP_UID, initialize_file_icon_provider,
Application, choose_dir, error_dialog, question_dialog, gprefs)
@ -222,7 +224,7 @@ class GuiRunner(QObject):
try:
self.library_path = candidate
db = self.db_class(candidate)
db = LibraryDatabase(candidate)
except:
error_dialog(self.splash_screen, _('Bad database location'),
_('Bad database location %r. calibre will now quit.'
@ -239,12 +241,10 @@ class GuiRunner(QObject):
det_msg=traceback.format_exc(), show=True)
def initialize_db(self):
from calibre.db import get_db_loader
db = None
self.db_class, errs = get_db_loader()
try:
db = self.db_class(self.library_path)
except errs:
db = LibraryDatabase(self.library_path)
except apsw.Error:
repair = question_dialog(self.splash_screen, _('Corrupted database'),
_('The library database at %s appears to be corrupted. Do '
'you want calibre to try and rebuild it automatically? '
@ -255,7 +255,7 @@ class GuiRunner(QObject):
)
if repair:
if repair_library(self.library_path):
db = self.db_class(self.library_path)
db = LibraryDatabase(self.library_path)
except:
error_dialog(self.splash_screen, _('Bad database location'),
_('Bad database location %r. Will start with '

View File

@ -17,7 +17,7 @@ from calibre.gui2.preferences.look_feel_ui import Ui_Form
from calibre.gui2 import config, gprefs, qt_app, NONE, open_local_file
from calibre.utils.localization import (available_translations,
get_language, get_lang)
from calibre.utils.config import prefs, tweaks
from calibre.utils.config import prefs
from calibre.utils.icu import sort_key
from calibre.gui2.book_details import get_field_list
from calibre.gui2.preferences.coloring import EditRules
@ -210,10 +210,6 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form):
self.fs_help_msg.setText(unicode(self.fs_help_msg.text())%(
_(' or ').join(keys)))
self.cover_grid_color_button.clicked.connect(self.change_cover_grid_color)
if not tweaks.get('use_new_db', False):
for i in range(self.tabWidget.count()):
if self.tabWidget.widget(i) is self.cover_grid_tab:
self.tabWidget.removeTab(i)
self.size_calculated.connect(self.update_cg_cache_size, type=Qt.QueuedConnection)
self.tabWidget.currentChanged.connect(self.tab_changed)
self.cover_grid_empty_cache.clicked.connect(self.empty_cache)

View File

@ -15,7 +15,7 @@ from PyQt4.Qt import (QAbstractItemModel, QIcon, QVariant, QFont, Qt,
from calibre.constants import config_dir
from calibre.gui2 import NONE, gprefs, config, error_dialog
from calibre.library.database2 import Tag
from calibre.db.categories import Tag
from calibre.utils.config import tweaks
from calibre.utils.icu import sort_key, lower, strcmp, collation_order
from calibre.library.field_metadata import TagsIcons, category_icon_map

View File

@ -14,6 +14,7 @@ from Queue import Queue, Empty
from threading import Thread
from collections import OrderedDict
import apsw
from PyQt4.Qt import (Qt, SIGNAL, QTimer, QHelpEvent, QAction,
QMenu, QIcon, pyqtSignal, QUrl, QFont,
QDialog, QSystemTrayIcon, QApplication)
@ -22,7 +23,7 @@ from calibre import prints, force_unicode
from calibre.constants import __appname__, isosx, filesystem_encoding, DEBUG
from calibre.utils.config import prefs, dynamic
from calibre.utils.ipc.server import Server
from calibre.db import get_db_loader
from calibre.db.legacy import LibraryDatabase
from calibre.customize.ui import interface_actions, available_store_plugins
from calibre.gui2 import (error_dialog, GetMetadata, open_url,
gprefs, max_available_height, config, info_dialog, Dispatcher,
@ -585,10 +586,9 @@ class Main(MainWindow, MainWindowMixin, DeviceMixin, EmailMixin, # {{{
unload_user_template_functions(olddb.library_id)
except:
olddb = None
db_class, errs = get_db_loader()
try:
db = db_class(newloc, default_prefs=default_prefs)
except errs:
db = LibraryDatabase(newloc, default_prefs=default_prefs)
except apsw.Error:
if not allow_rebuild:
raise
import traceback
@ -602,7 +602,7 @@ class Main(MainWindow, MainWindowMixin, DeviceMixin, EmailMixin, # {{{
if repair:
from calibre.gui2.dialogs.restore_library import repair_library_at
if repair_library_at(newloc, parent=self):
db = db_class(newloc, default_prefs=default_prefs)
db = LibraryDatabase(newloc, default_prefs=default_prefs)
else:
return
else:

View File

@ -14,6 +14,7 @@ from contextlib import closing
from PyQt4.Qt import (QWizard, QWizardPage, QPixmap, Qt, QAbstractListModel,
QVariant, QItemSelectionModel, SIGNAL, QObject, QTimer, pyqtSignal)
from calibre import __appname__, patheq
from calibre.db.legacy import LibraryDatabase
from calibre.library.move import MoveLibrary
from calibre.constants import (filesystem_encoding, iswindows, plugins,
isportable)
@ -33,10 +34,6 @@ from calibre.customize.ui import device_plugins
if iswindows:
winutil = plugins['winutil'][0]
def db_class():
from calibre.db import get_db_loader
return get_db_loader()[0]
# Devices {{{
class Device(object):
@ -626,7 +623,7 @@ def move_library(oldloc, newloc, parent, callback_on_complete):
if oldloc and os.access(os.path.join(oldloc, 'metadata.db'), os.R_OK):
# Move old library to new location
try:
db = db_class()(oldloc)
db = LibraryDatabase(oldloc)
except:
return move_library(None, newloc, parent,
callback)
@ -639,13 +636,13 @@ def move_library(oldloc, newloc, parent, callback_on_complete):
return
else:
# Create new library at new location
db = db_class()(newloc)
db = LibraryDatabase(newloc)
callback(newloc)
return
# Try to load existing library at new location
try:
db_class()(newloc)
LibraryDatabase(newloc)
except Exception as err:
det = traceback.format_exc()
error_dialog(parent, _('Invalid database'),
@ -732,7 +729,7 @@ class LibraryPage(QWizardPage, LibraryUI):
def is_library_dir_suitable(self, x):
try:
return db_class().exists_at(x) or not os.listdir(x)
return LibraryDatabase.exists_at(x) or not os.listdir(x)
except:
return False
@ -748,10 +745,10 @@ class LibraryPage(QWizardPage, LibraryUI):
_('Select location for books'))
if x:
if (iswindows and len(x) >
db_class().WINDOWS_LIBRARY_PATH_LIMIT):
LibraryDatabase.WINDOWS_LIBRARY_PATH_LIMIT):
return error_dialog(self, _('Too long'),
_('Path to library too long. Must be less than'
' %d characters.')%(db_class().WINDOWS_LIBRARY_PATH_LIMIT),
' %d characters.')%(LibraryDatabase.WINDOWS_LIBRARY_PATH_LIMIT),
show=True)
if not os.path.exists(x):
try:

View File

@ -3,9 +3,9 @@ __copyright__ = '2008, Kovid Goyal <kovid at kovidgoyal.net>'
''' Code to manage ebook library'''
def db(path=None, read_only=False):
from calibre.db import get_db_loader
from calibre.db.legacy import LibraryDatabase
from calibre.utils.config import prefs
return get_db_loader()[0](path if path else prefs['library_path'],
return LibraryDatabase(path if path else prefs['library_path'],
read_only=read_only)

View File

@ -13,21 +13,18 @@ from textwrap import TextWrapper
from calibre import preferred_encoding, prints, isbytestring, patheq
from calibre.constants import iswindows
from calibre.db.legacy import LibraryDatabase
from calibre.utils.config import OptionParser, prefs, tweaks
from calibre.ebooks.metadata.meta import get_metadata
from calibre.ebooks.metadata.book.base import field_from_string
from calibre.ebooks.metadata.opf2 import OPFCreator, OPF
from calibre.utils.date import isoformat
from calibre.db import get_db_loader
FIELDS = set(['title', 'authors', 'author_sort', 'publisher', 'rating',
'timestamp', 'size', 'tags', 'comments', 'series', 'series_index',
'formats', 'isbn', 'uuid', 'pubdate', 'cover', 'last_modified',
'identifiers'])
def db_class():
return get_db_loader()[0]
do_notify = True
def send_message(msg=''):
global do_notify
@ -66,7 +63,7 @@ def get_db(dbpath, options):
dbpath = os.path.abspath(dbpath)
if options.dont_notify_gui:
do_notify = False
return db_class()(dbpath)
return LibraryDatabase(dbpath)
def do_list(db, fields, afields, sort_by, ascending, search_text, line_width, separator,
prefix, limit, subtitle='Books in the calibre database'):
@ -1108,7 +1105,7 @@ def command_backup_metadata(args, dbpath):
dbpath = opts.library_path
if isbytestring(dbpath):
dbpath = dbpath.decode(preferred_encoding)
db = db_class()(dbpath)
db = LibraryDatabase(dbpath)
book_ids = None
if opts.all:
book_ids = db.all_ids()
@ -1190,7 +1187,7 @@ def command_check_library(args, dbpath):
for i in list:
print ' %-40.40s - %-40.40s'%(i[0], i[1])
db = db_class()(dbpath)
db = LibraryDatabase(dbpath)
checker = CheckLibrary(dbpath, db)
checker.scan_library(names, exts)
for check in checks:
@ -1245,10 +1242,7 @@ def command_restore_database(args, dbpath):
self.total = float(step)
else:
prints(msg, '...', '%d%%'%int(100*(step/self.total)))
if tweaks.get('use_new_db', False):
from calibre.db.restore import Restore
else:
from calibre.library.restore import Restore
r = Restore(dbpath, progress_callback=Progress())
r.start()
r.join()
@ -1306,7 +1300,7 @@ def command_list_categories(args, dbpath):
if isbytestring(dbpath):
dbpath = dbpath.decode(preferred_encoding)
db = db_class()(dbpath)
db = LibraryDatabase(dbpath)
category_data = db.get_categories()
data = []
report_on = [c.strip() for c in opts.report.split(',') if c.strip()]
@ -1425,8 +1419,6 @@ def command_clone(args, dbpath):
if not empty:
prints(_('%s is not empty. You must choose an empty directory for the new library.') % loc)
return 1
from calibre.db import get_db_loader
LibraryDatabase = get_db_loader()[0]
if iswindows and len(loc) > LibraryDatabase.WINDOWS_LIBRARY_PATH_LIMIT:
prints(_('Path to library too long. Must be less than'
' %d characters.')%LibraryDatabase.WINDOWS_LIBRARY_PATH_LIMIT)

View File

@ -15,9 +15,9 @@ from calibre.utils.ipc.job import ParallelJob
def move_library(from_, to, notification=lambda x:x):
from calibre.db import get_db_loader
from calibre.db.legacy import LibraryDatabase
time.sleep(1)
old = get_db_loader()[0](from_)
old = LibraryDatabase(from_)
old.move_library_to(to, notification)
return True

View File

@ -100,7 +100,7 @@ def daemonize(stdin='/dev/null', stdout='/dev/null', stderr='/dev/null'):
def main(args=sys.argv):
from calibre.db import get_db_loader
from calibre.db.legacy import LibraryDatabase
parser = option_parser()
opts, args = parser.parse_args(args)
if opts.daemonize and not iswindows:
@ -116,7 +116,7 @@ def main(args=sys.argv):
print('No saved library path. Use the --with-library option'
' to specify the path to the library you want to use.')
return 1
db = get_db_loader()[0](opts.with_library)
db = LibraryDatabase(opts.with_library)
server = LibraryServer(db, opts, show_tracebacks=opts.develop)
server.start()
return 0