summaryrefslogtreecommitdiff
path: root/doc/source/user/usage.rst
diff options
context:
space:
mode:
Diffstat (limited to 'doc/source/user/usage.rst')
-rw-r--r--doc/source/user/usage.rst184
1 files changed, 184 insertions, 0 deletions
diff --git a/doc/source/user/usage.rst b/doc/source/user/usage.rst
new file mode 100644
index 0000000..1b2d996
--- /dev/null
+++ b/doc/source/user/usage.rst
@@ -0,0 +1,184 @@
+=======
+ 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 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)
+
+
+``connection`` modifier can be used when a :class:`.Session` object is not
+needed, e.g. when `SQLAlchemy Core <http://docs.sqlalchemy.org/en/latest/core/>`_
+is preferred:
+
+.. code:: python
+
+ @enginefacade.reader.connection
+ def _refresh_from_db(context, cache):
+ sel = sa.select([table.c.id, table.c.name])
+ res = context.connection.execute(sel).fetchall()
+ cache.id_cache = {r[1]: r[0] for r in res}
+ cache.str_cache = {r[0]: r[1] for r in res}
+
+
+.. 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 decorator form can also be used with class and instance methods which
+implicitly receive the first positional argument:
+
+.. code:: python
+
+ class DatabaseAccessLayer(object):
+
+ @classmethod
+ @enginefacade.reader
+ def some_reader_api_function(cls, context):
+ return context.session.query(SomeClass).all()
+
+ @enginefacade.writer
+ def some_writer_api_function(self, context, x, y):
+ context.session.add(SomeClass(x, y))
+
+.. note:: Note that enginefacade decorators must be applied **before**
+ `classmethod`, otherwise you will get a ``TypeError`` at import time
+ (as enginefacade will try to use ``inspect.getargspec()`` on a descriptor,
+ not on a bound method, please refer to the `Data Model
+ <https://docs.python.org/3/reference/datamodel.html#data-model>`_ section
+ of the Python Language Reference for details).
+
+
+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.sqlalchemy 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)
+
+DB migration extensions
+=======================
+
+Available extensions for `oslo_db.migration`.
+
+.. list-plugins:: oslo_db.sqlalchemy.migration
+ :detailed: