# -*- coding: utf-8 -*-
##############################################################################
#
# Copyright (c) 2019 Zope Foundation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
"""sqlite3 adapter for RelStorage."""
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
import os.path
from zope.interface import implementer
from ..adapter import AbstractAdapter
from ..dbiter import HistoryFreeDatabaseIterator
from ..dbiter import HistoryPreservingDatabaseIterator
from ..interfaces import IRelStorageAdapter
from ..packundo import HistoryFreePackUndo
from ..packundo import HistoryPreservingPackUndo
from . import drivers
from .batch import Sqlite3RowBatcher
from .connmanager import Sqlite3ConnectionManager
from .locker import Sqlite3Locker
from .mover import Sqlite3ObjectMover
from .oidallocator import Sqlite3OIDAllocator
from .schema import Sqlite3SchemaInstaller
from .stats import Sqlite3Stats
from .txncontrol import Sqlite3TransactionControl
from .poller import Sqlite3Poller
from .scriptrunner import Sqlite3ScriptRunner
[docs]
@implementer(IRelStorageAdapter)
class Sqlite3Adapter(AbstractAdapter): # pylint:disable=too-many-instance-attributes
"""
Adapter for sqlite.
"""
driver_options = drivers
WRITING_REQUIRES_EXCLUSIVE_LOCK = True
def __init__(self, data_dir, pragmas,
options=None, oidallocator=None,
locker=None,
mover=None,
connmanager=None):
self.data_dir = os.path.abspath(data_dir)
self.pragmas = pragmas
self.oidallocator = oidallocator
self.locker = locker
self.mover = mover
self.connmanager = connmanager
super().__init__(options)
def _create(self):
driver = self.driver
options = self.options
if self.connmanager is None:
self.connmanager = Sqlite3ConnectionManager(
driver,
path=os.path.join(self.data_dir, 'main.sqlite3'),
pragmas=self.pragmas,
options=options
)
if self.mover is None:
self.mover = Sqlite3ObjectMover(
driver,
options=options,
)
if self.locker is None:
self.locker = Sqlite3Locker(
options,
driver,
batcher_factory=Sqlite3RowBatcher)
if not self.oidallocator:
self.oidallocator = Sqlite3OIDAllocator(
os.path.join(self.data_dir, 'oids.sqlite3'),
# No switching during OID allocation. It holds an exclusive
# lock anyway.
driver=drivers.Sqlite3Driver()
)
self.runner = Sqlite3ScriptRunner()
self.poller = Sqlite3Poller(
self.driver,
keep_history=self.keep_history,
runner=self.runner,
revert_when_stale=options.revert_when_stale,
transactions_may_go_backwards=False
)
self.txncontrol = Sqlite3TransactionControl(
connmanager=self.connmanager,
poller=self.poller,
keep_history=self.keep_history,
Binary=driver.Binary,
)
self.schema = Sqlite3SchemaInstaller(
driver=driver,
oid_allocator=self.oidallocator,
connmanager=self.connmanager,
runner=self.runner,
keep_history=self.keep_history
)
self.stats = Sqlite3Stats(
self.connmanager,
self.keep_history
)
if self.keep_history:
self.packundo = HistoryPreservingPackUndo(
driver,
connmanager=self.connmanager,
runner=self.runner,
locker=self.locker,
options=options,
)
self.dbiter = HistoryPreservingDatabaseIterator(
driver,
)
else:
self.packundo = HistoryFreePackUndo(
driver,
connmanager=self.connmanager,
runner=self.runner,
locker=self.locker,
options=options,
)
self.dbiter = HistoryFreeDatabaseIterator(
driver,
)
def new_instance(self):
inst = type(self)(
self.data_dir,
self.pragmas,
options=self.options,
oidallocator=self.oidallocator.new_instance(),
locker=self.locker,
mover=self.mover,
connmanager=self.connmanager,
)
return inst