Skip to content

Commit 803d759

Browse files
committed
sqlite3 backend: support for immutable db when readonly fs
1 parent c140bd4 commit 803d759

File tree

2 files changed

+23
-9
lines changed

2 files changed

+23
-9
lines changed

opcua/common/sqlite3_backend.py

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11

2+
import os
23
import sys
34
import time
45
import sqlite3
@@ -69,22 +70,34 @@ def _wal_throttled(self):
6970

7071
def _db_connect(self):
7172
CID = SQLite3Backend._getCID()
72-
# PARSE_DECLTYPES is active so certain data types (such as datetime) will not be BLOBs
7373
assert CID not in self._conn
74-
self._conn[CID] = sqlite3.connect(
75-
self._sqlFile,
76-
detect_types = sqlite3.PARSE_DECLTYPES,
77-
check_same_thread = False
78-
)
7974
if SQLite3Backend.PY2:
80-
self._conn[CID].text_factory = bytes
75+
self._db_connect_py2(CID)
76+
else:
77+
self._conn[CID] = sqlite3.connect(
78+
'file:{:s}?immutable={:s}'.format(self._sqlFile, '1' if self.readonly else '0'),
79+
detect_types = sqlite3.PARSE_DECLTYPES, # so datetimes won't be BLOBs
80+
check_same_thread = False,
81+
uri = True,
82+
)
8183
c = self._get_conn().cursor()
8284
if self.readonly is True:
8385
c.execute('PRAGMA query_only=1')
8486
else:
8587
c.execute('PRAGMA journal_mode=WAL')
8688
c.execute('PRAGMA synchronous=NORMAL')
8789

90+
# Legacy support for Python<3.x.
91+
def _db_connect_py2(self, CID):
92+
if os.access(self._sqlFile, os.W_OK) is False:
93+
raise Exception('Python>=3.x is required for immutable sqlite3 database.')
94+
self._conn[CID] = sqlite3.connect(
95+
self._sqlFile,
96+
detect_types = sqlite3.PARSE_DECLTYPES,
97+
check_same_thread = False
98+
)
99+
self._conn[CID].text_factory = bytes
100+
88101
def _db_disconnect(self):
89102
# Commit, checkpoint.
90103
if self.readonly is False:

opcua/server/address_space_sqlite.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -96,8 +96,9 @@ def __init__(self, backend, cache=None):
9696

9797
def __enter__(self):
9898
super(AddressSpaceSQLite, self).__enter__()
99-
AddressSpaceSQLite._create_attr_table(self.backend)
100-
AddressSpaceSQLite._create_refs_table(self.backend)
99+
if self.readonly is False:
100+
AddressSpaceSQLite._create_attr_table(self.backend)
101+
AddressSpaceSQLite._create_refs_table(self.backend)
101102
return self
102103

103104
def __str__(self):

0 commit comments

Comments
 (0)