Coverage for .tox/coverage/lib/python3.11/site-packages/wuttjamaican/db/handler.py: 100%
19 statements
« prev ^ index » next coverage.py v7.3.2, created at 2024-12-15 00:47 -0600
« prev ^ index » next coverage.py v7.3.2, created at 2024-12-15 00:47 -0600
1# -*- coding: utf-8; -*-
2################################################################################
3#
4# WuttJamaican -- Base package for Wutta Framework
5# Copyright © 2024 Lance Edgar
6#
7# This file is part of Wutta Framework.
8#
9# Wutta Framework is free software: you can redistribute it and/or modify it
10# under the terms of the GNU General Public License as published by the Free
11# Software Foundation, either version 3 of the License, or (at your option) any
12# later version.
13#
14# Wutta Framework is distributed in the hope that it will be useful, but
15# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
17# more details.
18#
19# You should have received a copy of the GNU General Public License along with
20# Wutta Framework. If not, see <http://www.gnu.org/licenses/>.
21#
22################################################################################
23"""
24Database Handler
25"""
27import sqlalchemy as sa
29from wuttjamaican.app import GenericHandler
32class DatabaseHandler(GenericHandler):
33 """
34 Base class and default implementation for the :term:`db handler`.
35 """
37 def next_counter_value(self, session, key):
38 """
39 Return the next counter value for the given key.
41 If the DB backend is PostgreSQL, then a proper "sequence" is
42 used for the counter.
44 All other backends use a "fake" sequence by creating a
45 dedicated table with auto-increment primary key, to provide
46 the counter.
48 :param session: Current :term:`db session`.
50 :param key: Unique key indicating the counter for which the
51 next value should be fetched.
53 :returns: Next value as integer.
54 """
55 dialect = session.bind.url.get_dialect().name
57 # postgres uses "true" native sequence
58 if dialect == 'postgresql':
59 sql = f"create sequence if not exists {key}_seq"
60 session.execute(sa.text(sql))
61 sql = f"select nextval('{key}_seq')"
62 value = session.execute(sa.text(sql)).scalar()
63 return value
65 # otherwise use "magic" workaround
66 engine = session.bind
67 metadata = sa.MetaData()
68 table = sa.Table(f'_counter_{key}', metadata,
69 sa.Column('value', sa.Integer(), primary_key=True))
70 table.create(engine, checkfirst=True)
71 with engine.begin() as cxn:
72 result = cxn.execute(table.insert())
73 return result.lastrowid