doc/book/en/devrepo/devcore/dbapi.rst
branchstable
changeset 5394 105011657405
parent 5312 d2dbba898a96
child 5400 b7ab099b128a
equal deleted inserted replaced
5393:875bdc0fe8ce 5394:105011657405
       
     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   While executing update queries (SET, INSERT, DELETE), if a query generates
       
    26   an error related to security, a rollback is automatically done on the current
       
    27   transaction.
       
    28 
       
    29 Executing RQL queries from a view or a hook
       
    30 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       
    31 
       
    32 When you're within code of the web interface, the db-api like connexion is
       
    33 handled by the request object. You should not have to access it directly, but
       
    34 use the `execute` method directly available on the request, eg:
       
    35 
       
    36    rset = self._cw.execute(rqlstring, kwargs)
       
    37 
       
    38 Similarly, on the server side (eg in hooks), there is no db-api connexion (since
       
    39 you're directly inside the data-server), so you'll have to use the execute method
       
    40 of the session object.
       
    41 
       
    42 
       
    43 Important note about proper usage of .execute
       
    44 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       
    45 
       
    46 Let's say you want to get T which is in configuration C, this translates to:
       
    47 
       
    48 .. sourcecode:: python
       
    49 
       
    50    self._cw.execute('Any T WHERE T in_conf C, C eid %s' % entity.eid)
       
    51 
       
    52 But it must be written in a syntax that will benefit from the use
       
    53 of a cache on the RQL server side:
       
    54 
       
    55 .. sourcecode:: python
       
    56 
       
    57    self._cw.execute('Any T WHERE T in_conf C, C eid %(x)s', {'x': entity.eid})
       
    58 
       
    59 The syntax tree is built once for the "generic" RQL and can be re-used
       
    60 with a number of different eids. There rql IN operator is an exception
       
    61 to this rule.
       
    62 
       
    63 .. sourcecode:: python
       
    64 
       
    65    self._cw.execute('Any T WHERE T in_conf C, C name IN (%s)'
       
    66                     % ','.join(['foo', 'bar']))
       
    67 
       
    68 Alternativelly, some of the common data related to an entity can be
       
    69 obtained from the `entity.related()` method (which is used under the
       
    70 hood by the orm when you use attribute access notation on an entity to
       
    71 get a relation. The initial request would then be translated to:
       
    72 
       
    73 .. sourcecode:: python
       
    74 
       
    75    entity.related('in_conf', 'object')
       
    76 
       
    77 Additionnaly this benefits from the fetch_attrs policy (see
       
    78 :ref:`FetchAttrs`) eventually defined on the class element, which says
       
    79 which attributes must be also loaded when the entity is loaded through
       
    80 the orm.
       
    81 
       
    82 
       
    83 .. _resultset:
       
    84 
       
    85 The `ResultSet` API
       
    86 ~~~~~~~~~~~~~~~~~~~
       
    87 
       
    88 ResultSet instances are a very commonly manipulated object. They have
       
    89 a rich API as seen below, but we would like to highlight a bunch of
       
    90 methods that are quite useful in day-to-day practice:
       
    91 
       
    92 * `__str__()` (applied by `print`) gives a very useful overview of both
       
    93   the underlying RQL expression and the data inside; unavoidable for
       
    94   debugging purposes
       
    95 
       
    96 * `printable_rql()` produces back a well formed RQL expression as a
       
    97   string; it is very useful to build views
       
    98 
       
    99 * `entities()` returns a generator on all entities of the result set
       
   100 
       
   101 * `get_entity(row, col)` gets the entity at row, col coordinates; one
       
   102   of the most used result set method
       
   103 
       
   104 .. autoclass:: cubicweb.rset.ResultSet
       
   105    :members:
       
   106 
       
   107 
       
   108 The `Cursor` API
       
   109 ~~~~~~~~~~~~~~~~
       
   110 
       
   111 The whole cursor API is developped below.
       
   112 
       
   113 .. note:
       
   114 
       
   115   In practice we use the `.execute` method on the _cw object of
       
   116   appobjects. Usage of other methods is quite rare.
       
   117 
       
   118 .. autoclass:: cubicweb.dbapi.Cursor
       
   119    :members: