doc/book/devrepo/devcore/dbapi.rst
changeset 10491 c67bcee93248
equal deleted inserted replaced
10490:76ab3c71aff2 10491:c67bcee93248
       
     1 .. _dbapi:
       
     2 
       
     3 Python/RQL API
       
     4 ~~~~~~~~~~~~~~
       
     5 
       
     6 The Python API developped to interface with RQL is inspired from the standard db-api,
       
     7 with a Connection object having the methods cursor, rollback and commit essentially.
       
     8 The most important method is the `execute` method of a cursor.
       
     9 
       
    10 .. sourcecode:: python
       
    11 
       
    12    execute(rqlstring, args=None, build_descr=True)
       
    13 
       
    14 :rqlstring: the RQL query to execute (unicode)
       
    15 :args: if the query contains substitutions, a dictionary containing the values to use
       
    16 
       
    17 The `Connection` object owns the methods `commit` and `rollback`. You
       
    18 *should never need to use them* during the development of the web
       
    19 interface based on the *CubicWeb* framework as it determines the end
       
    20 of the transaction depending on the query execution success. They are
       
    21 however useful in other contexts such as tests or custom controllers.
       
    22 
       
    23 .. note::
       
    24 
       
    25   If a query generates an error related to security (:exc:`Unauthorized`) or to
       
    26   integrity (:exc:`ValidationError`), the transaction can still continue but you
       
    27   won't be able to commit it, a rollback will be necessary to start a new
       
    28   transaction.
       
    29 
       
    30   Also, a rollback is automatically done if an error occurs during commit.
       
    31 
       
    32 .. note::
       
    33 
       
    34    A :exc:`ValidationError` has a `entity` attribute. In CubicWeb,
       
    35    this atttribute is set to the entity's eid (not a reference to the
       
    36    entity itself).
       
    37 
       
    38 Executing RQL queries from a view or a hook
       
    39 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       
    40 
       
    41 When you're within code of the web interface, the db-api like connexion is
       
    42 handled by the request object. You should not have to access it directly, but
       
    43 use the `execute` method directly available on the request, eg:
       
    44 
       
    45 .. sourcecode:: python
       
    46 
       
    47    rset = self._cw.execute(rqlstring, kwargs)
       
    48 
       
    49 Similarly, on the server side (eg in hooks), there is no db-api connexion (since
       
    50 you're directly inside the data-server), so you'll have to use the execute method
       
    51 of the session object.
       
    52 
       
    53 
       
    54 Proper usage of `.execute`
       
    55 ~~~~~~~~~~~~~~~~~~~~~~~~~~
       
    56 
       
    57 Let's say you want to get T which is in configuration C, this translates to:
       
    58 
       
    59 .. sourcecode:: python
       
    60 
       
    61    self._cw.execute('Any T WHERE T in_conf C, C eid %s' % entity.eid)
       
    62 
       
    63 But it must be written in a syntax that will benefit from the use
       
    64 of a cache on the RQL server side:
       
    65 
       
    66 .. sourcecode:: python
       
    67 
       
    68    self._cw.execute('Any T WHERE T in_conf C, C eid %(x)s', {'x': entity.eid})
       
    69 
       
    70 The syntax tree is built once for the "generic" RQL and can be re-used
       
    71 with a number of different eids. There rql IN operator is an exception
       
    72 to this rule.
       
    73 
       
    74 .. sourcecode:: python
       
    75 
       
    76    self._cw.execute('Any T WHERE T in_conf C, C name IN (%s)'
       
    77                     % ','.join(['foo', 'bar']))
       
    78 
       
    79 Alternativelly, some of the common data related to an entity can be
       
    80 obtained from the `entity.related()` method (which is used under the
       
    81 hood by the orm when you use attribute access notation on an entity to
       
    82 get a relation. The initial request would then be translated to:
       
    83 
       
    84 .. sourcecode:: python
       
    85 
       
    86    entity.related('in_conf', 'object')
       
    87 
       
    88 Additionnaly this benefits from the fetch_attrs policy (see
       
    89 :ref:`FetchAttrs`) eventually defined on the class element, which says
       
    90 which attributes must be also loaded when the entity is loaded through
       
    91 the orm.
       
    92 
       
    93 
       
    94 .. _resultset:
       
    95 
       
    96 The `ResultSet` API
       
    97 ~~~~~~~~~~~~~~~~~~~
       
    98 
       
    99 ResultSet instances are a very commonly manipulated object. They have
       
   100 a rich API as seen below, but we would like to highlight a bunch of
       
   101 methods that are quite useful in day-to-day practice:
       
   102 
       
   103 * `__str__()` (applied by `print`) gives a very useful overview of both
       
   104   the underlying RQL expression and the data inside; unavoidable for
       
   105   debugging purposes
       
   106 
       
   107 * `printable_rql()` produces back a well formed RQL expression as a
       
   108   string; it is very useful to build views
       
   109 
       
   110 * `entities()` returns a generator on all entities of the result set
       
   111 
       
   112 * `get_entity(row, col)` gets the entity at row, col coordinates; one
       
   113   of the most used result set method
       
   114 
       
   115 .. autoclass:: cubicweb.rset.ResultSet
       
   116    :members:
       
   117 
       
   118 
       
   119 The `Cursor` and `Connection` API
       
   120 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       
   121 
       
   122 The whole cursor API is developped below.
       
   123 
       
   124 .. note::
       
   125 
       
   126   In practice you'll usually use the `.execute` method on the _cw object of
       
   127   appobjects. Usage of other methods is quite rare.
       
   128 
       
   129 .. autoclass:: cubicweb.dbapi.Cursor
       
   130    :members:
       
   131 
       
   132 .. autoclass:: cubicweb.dbapi.Connection
       
   133    :members: