# HG changeset patch # User Aurelien Campeas # Date 1270748220 -7200 # Node ID e9dd56699097cf32f36f6ecf77d7a13b2c48c844 # Parent 6d182c7d4392467138608f747b25b4e2cb3f18a7# Parent 5f9a2b32c9e1523c52b7204d1a226fea2add869d [merge] diff -r 5f9a2b32c9e1 -r e9dd56699097 doc/book/en/.static/sphinx-default.css --- a/doc/book/en/.static/sphinx-default.css Thu Apr 08 14:40:18 2010 +0200 +++ b/doc/book/en/.static/sphinx-default.css Thu Apr 08 19:37:00 2010 +0200 @@ -3,7 +3,7 @@ */ html, body { - background: white; + background: white; } body { @@ -115,7 +115,7 @@ } div.sphinxsidebar h3 { - font-family: 'Verdanda', sans-serif; + font-family: Verdana, sans-serif; color: black; font-size: 1.2em; font-weight: normal; @@ -126,7 +126,7 @@ } div.sphinxsidebar h4 { - font-family: 'Verdana', sans-serif; + font-family: Verdana, sans-serif; color: black; font-size: 1.1em; font-weight: normal; diff -r 5f9a2b32c9e1 -r e9dd56699097 doc/book/en/annexes/rql/intro.rst --- a/doc/book/en/annexes/rql/intro.rst Thu Apr 08 14:40:18 2010 +0200 +++ b/doc/book/en/annexes/rql/intro.rst Thu Apr 08 19:37:00 2010 +0200 @@ -5,10 +5,10 @@ Goals of RQL ~~~~~~~~~~~~ -The goal is to have a language emphasizing the way of browsing relations. As -such, attributes will be regarded as cases of special relations (in terms of -implementation, the user should see no difference between an attribute and a -relation). +The goal is to have a language making relations browsing easy. As +such, attributes will be regarded as cases of special relations (in +terms of usage, the user should see no syntactic difference between an +attribute and a relation). Comparison with existing languages ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -32,10 +32,10 @@ We should look in more detail, but here are already some ideas for the moment ... Versa_ is the language most similar to what we wanted to do, but the model -underlying data being RDF, there is some number of things such as namespaces or +underlying data being RDF, there are some things such as namespaces or handling of the RDF types which does not interest us. On the functionality level, Versa_ is very comprehensive including through many functions of -conversion and basic types manipulation, which may need to be guided at one time +conversion and basic types manipulation, which we may want to look at one time or another. Finally, the syntax is a little esoteric. diff -r 5f9a2b32c9e1 -r e9dd56699097 doc/book/en/development/devcore/dbapi.rst --- a/doc/book/en/development/devcore/dbapi.rst Thu Apr 08 14:40:18 2010 +0200 +++ b/doc/book/en/development/devcore/dbapi.rst Thu Apr 08 19:37:00 2010 +0200 @@ -5,9 +5,10 @@ The Python API developped to interface with RQL is inspired from the standard db-api, with a Connection object having the methods cursor, rollback and commit essentially. -The most important method is the `execute` method of a cursor : +The most important method is the `execute` method of a cursor. -`execute(rqlstring, args=None, cachekey=None, build_descr=True)` +.. sourcecode:: python + execute(rqlstring, args=None, cachekey=None, build_descr=True) :rqlstring: the RQL query to execute (unicode) :args: if the query contains substitutions, a dictionary containing the values to use @@ -18,10 +19,11 @@ through this argument -The `Connection` object owns the methods `commit` and `rollback`. You *should -never need to use them* during the development of the web interface based on -the *CubicWeb* framework as it determines the end of the transaction depending -on the query execution success. +The `Connection` object owns the methods `commit` and `rollback`. You +*should never need to use them* during the development of the web +interface based on the *CubicWeb* framework as it determines the end +of the transaction depending on the query execution success. They are +however useful in other contexts such as tests. .. note:: While executing update queries (SET, INSERT, DELETE), if a query generates @@ -30,6 +32,7 @@ Executing RQL queries from a view or a hook ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + When you're within code of the web interface, the db-api like connexion is handled by the request object. You should not have to access it directly, but use the `execute` method directly available on the request, eg: @@ -50,33 +53,30 @@ self._cw.execute('Any T WHERE T in_conf C, C eid %s' % entity.eid) -But it can also be written in a syntax that will benefit from the use +But it must be written in a syntax that will benefit from the use of a cache on the RQL server side: .. sourcecode:: python - self._cw.execute('Any T WHERE T in_conf C, C eid %(x)s', {'x': entity.eid}, 'x') + self._cw.execute('Any T WHERE T in_conf C, C eid %(x)s', {'x': entity.eid}) -Beside proper usage of the `args` argument, notice the latest argument: this is what's called -the cache key. The cache key should be either a string or a tuple containing the names of keys -in args which are referencing eids. *YOU MUST SET THIS PROPERLY* if you don't want weird result -on queries which have ambigous solutions deambiguified by specifing an eid. So the good habit is: -*always put in the cache key all eid keys*. +The syntax tree is built once for the "generic" RQL and can be re-used +with a number of different eids. There rql IN operator is an exception +to this rule. -The syntax tree is build once for the "generic" RQL and can be re-used -with a number of different eid. +.. sourcecode:: python + + self._cw.execute('Any T WHERE T in_conf C, C name IN (%s)' % ','.join(['foo', 'bar'])) -Alternativelly, some of the common data related to an entity can be obtained from -the top-level `entity.related()` method (which is used under the hood by the orm -when you use attribute access notation on an entity to get a relation. The above -would then be translated to: +Alternativelly, some of the common data related to an entity can be +obtained from the `entity.related()` method (which is used under the +hood by the orm when you use attribute access notation on an entity to +get a relation. The initial request would then be translated to: .. sourcecode:: python entity.related('in_conf', 'object') -The `related()` method, as more generally others orm methods, makes extensive use -of the cache mechanisms so you don't have to worry about them. Additionnaly this -use will get you commonly used attributes that you will be able to use in your -view generation without having to ask the data backend. - +Additionnaly this benefits from the fetch_attrs policy eventually +defined on the class element, which says which attributes must be also +loaded when the entity is loaded through the orm. diff -r 5f9a2b32c9e1 -r e9dd56699097 doc/book/en/development/devrepo/hooks.rst --- a/doc/book/en/development/devrepo/hooks.rst Thu Apr 08 14:40:18 2010 +0200 +++ b/doc/book/en/development/devrepo/hooks.rst Thu Apr 08 19:37:00 2010 +0200 @@ -2,31 +2,103 @@ .. _hooks: -Hooks -===== +Hooks and Operations +==================== + +Principles +---------- -XXX FILLME +Paraphrasing the `emacs`_ documentation, let us say that hooks are an +important mechanism for customizing an application. A hook is +basically a list of functions to be called on some well-defined +occasion (This is called `running the hook`). + +.. _`emacs`: http://www.gnu.org/software/emacs/manual/html_node/emacs/Hooks.html + +In CubicWeb, hooks are classes subclassing the Hook class in +`server/hook.py`, implementing their own `call` method, and defined +over pre-defined `events`. + +There are two families of events: data events and server events. In a +typical application, most of the Hooks are defined over data +events. There can be a lot of them. -*Hooks* are executed before or after updating an entity or a relation in the -repository. +The purpose of data hooks is to complement the data model as defined +in the schema.py, which is static by nature, with dynamic or value +driven behaviours. It is functionally equivalent to a `database +trigger`_, except that database triggers definitions languages are not +standardized, hence not portable (for instance, PL/SQL works with +Oracle and PostgreSQL but not SqlServer nor Sqlite). + +.. _`database trigger`: http://en.wikipedia.org/wiki/Database_trigger + +Data hooks can serve the following purposes: + +* enforcing constraints that the static schema cannot express + (spanning several entities/relations, exotic cardinalities, etc.) -Their prototypes are as follows: +* implement computed attributes (an example could be the maintenance + of a relation representing the transitive closure of another relation) + +Operations are Hook-like objects that are created by Hooks and +scheduled to happen just before (or after) the `commit` event. Hooks +being fired immediately on data operations, it is sometime necessary +to delay the actual work down to a time where all other Hooks have run +and the application state converges towards consistency. Also while +the order of execution of Hooks is data dependant (and thus hard to +predict), it is possible to force an order on Operations. + +Events +------ - * after_add_entity (session, entity) - * after_update_entity (session, entity) - * after_delete_entity (session, eid) - * before_add_entity (session, entity) - * before_update_entity (session, entity) - * before_delete_entity (session, eid) +Hooks are mostly defined and used to handle `dataflow`_ operations. It +means as data gets in (mostly), specific events are issued and the +Hooks matching these events are called. + +.. _`dataflow`: http://en.wikipedia.org/wiki/Dataflow + +Below comes a list of the dataflow events related to entities operations: + +* before_add_entity + +* before_update_entity + +* before_delete_entity + +* after_add_entity + +* after_update_entity + +* after_delete_entity + +These define ENTTIES HOOKS. RELATIONS HOOKS are defined +over the following events: + +* after_add_relation - * after_add_relation (session, fromeid, rtype, toeid) - * after_delete_relation (session, fromeid, rtype, toeid) - * before_add_relation (session, fromeid, rtype, toeid) - * before_delete_relation (session, fromeid, rtype, toeid) +* after_delete_relation + +* before_add_relation + +* before_delete_relation + +This is an occasion to remind us that relations support the add/delete +operation, but no delete. + +Non data events also exist. These are called SYSTEM HOOKS. + +* server_startup - * server_startup - * server_shutdown +* server_shutdown + +* server_maintenance + +* server_backup - * session_open - * session_close +* server_restore + +* session_open +* session_close + + diff -r 5f9a2b32c9e1 -r e9dd56699097 doc/book/en/intro/concepts.rst --- a/doc/book/en/intro/concepts.rst Thu Apr 08 14:40:18 2010 +0200 +++ b/doc/book/en/intro/concepts.rst Thu Apr 08 19:37:00 2010 +0200 @@ -339,5 +339,5 @@ .. Note: RQL queries executed in hooks and operations are *unsafe* by default, e.g. the read and write security is deactivated unless explicitly asked. - + .. |cubicweb| replace:: *CubicWeb* diff -r 5f9a2b32c9e1 -r e9dd56699097 server/hook.py --- a/server/hook.py Thu Apr 08 14:40:18 2010 +0200 +++ b/server/hook.py Thu Apr 08 19:37:00 2010 +0200 @@ -30,7 +30,6 @@ Session hooks (eg session_open, session_close) have no special attribute. - :organization: Logilab :copyright: 2001-2010 LOGILAB S.A. (Paris, FRANCE), license is LGPL v2. :contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr