
Check explicitly for the cases where no "sql_connection" attribute was set when running _start(), so that the lack of this parameter is documented by the exception rather than failing into create_engine() with an unclear failure mode. If _start() fails as it will here, make sure _started stays False so that repeated calls to _start() continue to raise the same exception, rather than raising attribute errors. When accessing the "session" or "connection" attributes of the context when these attributes were not requested by the decorator or context manager, raise explicit exceptions for each, rather than returning None which leads to hard-to-debug NoneType errors. Change-Id: Iadfbf4707daed4140285a3a472009f6863b18275 Closes-bug: 1477080
139 lines
3.5 KiB
ReStructuredText
139 lines
3.5 KiB
ReStructuredText
=======
|
|
Usage
|
|
=======
|
|
|
|
To use oslo.db in a project:
|
|
|
|
Session Handling
|
|
================
|
|
|
|
Session handling is achieved using the :mod:`oslo_db.sqlalchemy.enginefacade`
|
|
system. This module presents a function decorator as well as a
|
|
context manager approach to delivering :class:`.Session` as well as
|
|
:class:`.Connection` objects to a function or block.
|
|
|
|
Both calling styles require the use of a context object. This object may
|
|
be of any class, though when used with the decorator form, requires
|
|
special instrumentation.
|
|
|
|
The context manager form is as follows:
|
|
|
|
.. code:: python
|
|
|
|
|
|
from oslo_db.sqlalchemy import enginefacade
|
|
|
|
|
|
class MyContext(object):
|
|
"User-defined context class."
|
|
|
|
|
|
def some_reader_api_function(context):
|
|
with enginefacade.reader.using(context) as session:
|
|
return session.query(SomeClass).all()
|
|
|
|
|
|
def some_writer_api_function(context, x, y):
|
|
with enginefacade.writer.using(context) as session:
|
|
session.add(SomeClass(x, y))
|
|
|
|
|
|
def run_some_database_calls():
|
|
context = MyContext()
|
|
|
|
results = some_reader_api_function(context)
|
|
some_writer_api_function(context, 5, 10)
|
|
|
|
|
|
The decorator form accesses attributes off the user-defined context
|
|
directly; the context must be decorated with the
|
|
:func:`oslo_db.sqlalchemy.enginefacade.transaction_context_provider`
|
|
decorator. Each function must receive the context as the first
|
|
positional argument:
|
|
|
|
.. code:: python
|
|
|
|
|
|
from oslo_db.sqlalchemy import enginefacade
|
|
|
|
@enginefacade.transaction_context_provider
|
|
class MyContext(object):
|
|
"User-defined context class."
|
|
|
|
@enginefacade.reader
|
|
def some_reader_api_function(context):
|
|
return context.session.query(SomeClass).all()
|
|
|
|
|
|
@enginefacade.writer
|
|
def some_writer_api_function(context, x, y):
|
|
context.session.add(SomeClass(x, y))
|
|
|
|
|
|
def run_some_database_calls():
|
|
context = MyContext()
|
|
|
|
results = some_reader_api_function(context)
|
|
some_writer_api_function(context, 5, 10)
|
|
|
|
.. note:: The ``context.session`` and ``context.connection`` attributes
|
|
must be accessed within the scope of an appropriate writer/reader block
|
|
(either the decorator or contextmanager approach). An AttributeError is
|
|
raised otherwise.
|
|
|
|
|
|
The scope of transaction and connectivity for both approaches is managed
|
|
transparently. The configuration for the connection comes from the standard
|
|
:obj:`oslo_config.cfg.CONF` collection. Additional configurations can be
|
|
established for the enginefacade using the
|
|
:func:`oslo_db.sqlalchemy.enginefacade.configure` function, before any use of
|
|
the database begins:
|
|
|
|
.. code:: python
|
|
|
|
from oslo_db.sqlalchemy import enginefacade
|
|
|
|
enginefacade.configure(
|
|
sqlite_fk=True,
|
|
max_retries=5,
|
|
mysql_sql_mode='ANSI'
|
|
)
|
|
|
|
|
|
Base class for models usage
|
|
===========================
|
|
|
|
.. code:: python
|
|
|
|
from oslo.db import models
|
|
|
|
|
|
class ProjectSomething(models.TimestampMixin,
|
|
models.ModelBase):
|
|
id = Column(Integer, primary_key=True)
|
|
...
|
|
|
|
|
|
DB API backend support
|
|
======================
|
|
|
|
.. code:: python
|
|
|
|
from oslo.config import cfg
|
|
from oslo.db import api as db_api
|
|
|
|
|
|
_BACKEND_MAPPING = {'sqlalchemy': 'project.db.sqlalchemy.api'}
|
|
|
|
IMPL = db_api.DBAPI.from_config(cfg.CONF, backend_mapping=_BACKEND_MAPPING)
|
|
|
|
def get_engine():
|
|
return IMPL.get_engine()
|
|
|
|
def get_session():
|
|
return IMPL.get_session()
|
|
|
|
# DB-API method
|
|
def do_something(somethind_id):
|
|
return IMPL.do_something(somethind_id)
|