doc/book/en/B0012-schema-definition.en.txt
author sylvain.thenault@logilab.fr
Mon, 04 May 2009 13:18:38 +0200
branchtls-sprint
changeset 1642 12a98b17fb05
parent 1641 2c80b09d8d86
permissions -rw-r--r--
fix tests

.. -*- coding: utf-8 -*-

Entity type definition
----------------------

An entity type is defined by a Python class which inherits from `EntityType`.
The class definition contains the description of attributes and relations
for the defined entity type.
The class name corresponds to the entity type name. It is exepected to be
defined in the module ``mycube.schema``.


For example ::

  class Person(EntityType):
    """A person with the properties and the relations necessary for my
    application"""

    last_name = String(required=True, fulltextindexed=True)
    first_name = String(required=True, fulltextindexed=True)
    title = String(vocabulary=('Mr', 'Mrs', 'Miss'))
    date_of_birth = Date()
    works_for = SubjectRelation('Company', cardinality='?*')


The entity described above defines three attributes of type String,
last_name, first_name and title, an attribute of type Date for the date of
birth and a relation that connects a `Person` to another entity of type
`Company` through the semantic `works_for`.

The name of the Python attribute corresponds to the name of the attribute
or the relation in `CubicWeb` application.

Built-in types for attributes
`````````````````````````````

All `CubicWeb` built-in types are available : `String`, `Int`, `Float`,
`Decimal`, `Boolean`, `Date`, `Datetime`, `Time`, `Interval`, `Byte`
and `Password`.
They are implicitely imported (as well as the special the function "_"
for translation :ref:`internationalization`).

An attribute is defined in the schema as follows::

    attr_name = attr_type(properties*)

where `attr_type` is one of the type listed above and `properties` is
a list of  the attribute needs to statisfy (see :ref:`properties`
for more details).


Meta-data
`````````

Each entity type has at least the following meta-relations :

  - `eid` (`Int`)

  - `creation_date` (`Datetime`)

  - `modification_date` (`Datetime`)

  - `created_by` (`CWUser`) (which user created the entity)

  - `owned_by` (`CWUser`) (to whom the entity belongs; by default the
     creator but not necessary, and it could have multiple owners)

  - `is` (`CWEType`) (of which type the entity is)


* relations can be defined by using `ObjectRelation` or `SubjectRelation`.
  The first argument of `SubjectRelation` or `ObjectRelation` gives respectively
  the object/subject entity type of the relation. This could be :

  * a string corresponding to an entity type

  * a tuple of string corresponding to multiple entity types

  * special string such as follows :

    - "**" : all types of entities
    - "*" : all types of non-meta entities
    - "@" : all types of meta entities but not system entities (e.g. used for
      the basic schema description)

* it is possible to use the attribute `meta` to flag an entity type as a `meta`
  (e.g. used to describe/categorize other entities)

Optionnal properties
````````````````````
.. _properties:


* optional properties for attributes and relations :

  - `description` : a string describing an attribute or a relation. By default
    this string will be used in the editing form of the entity, which means
    that it is supposed to help the end-user and should be flagged by the
    function `_` to be properly internationalized.

  - `constraints` : a list of conditions/constraints that the relation has to
    satisfy (c.f. `Contraints`_)

  - `cardinality` : a two character string which specify the cardinality of the
    relation. The first character defines the cardinality of the relation on
    the subject, and the second on the object. When a relation can have
    multiple subjects or objects, the cardinality applies to all,
    not on a one-to-one basis (so it must be consistent...). The possible
    values are inspired from regular expression syntax :

    * `1`: 1..1
    * `?`: 0..1
    * `+`: 1..n
    * `*`: 0..n

  - `meta` : boolean indicating that the relation is a meta-relation (false by
    default)

* optional properties for attributes :

  - `required` : boolean indicating if the attribute is required (false by default)

  - `unique` : boolean indicating if the value of the attribute has to be unique
    or not within all entities of the same type (false by default)

  - `indexed` : boolean indicating if an index needs to be created for this
    attribute in the database (false by default). This is useful only if
    you know that you will have to run numerous searches on the value of this
    attribute.

  - `default` : default value of the attribute. In case of date types, the values
    which could be used correspond to the RQL keywords `TODAY` and `NOW`.

  - `vocabulary` : specify static possible values of an attribute

* optional properties of type `String` :

  - `fulltextindexed` : boolean indicating if the attribute is part of
    the full text index (false by default) (*applicable on the type `Byte`
    as well*)

  - `internationalizable` : boolean indicating if the value of the attribute
    is internationalizable (false by default)

  - `maxsize` : integer providing the maximum size of the string (no limit by default)

* optional properties for relations :

  - `composite` : string indicating that the subject (composite == 'subject')
    is composed of the objects of the relations. For the opposite case (when
    the object is composed of the subjects of the relation), we just set
    'object' as value. The composition implies that when the relation
    is deleted (so when the composite is deleted), the composed are also deleted.

Contraints
``````````
By default, the available constraint types are :

* `SizeConstraint` : allows to specify a minimum and/or maximum size on
  string (generic case of `maxsize`)

* `BoundConstraint` : allows to specify a minimum and/or maximum value on
  numeric types

* `UniqueConstraint` : identical to "unique=True"

* `StaticVocabularyConstraint` : identical to "vocabulary=(...)"

* `RQLConstraint` : allows to specify a RQL query that has to be satisfied
  by the subject and/or the object of the relation. In this query the variables
  `S` and `O` are reserved for the entities subject and object of the
  relation.

* `RQLVocabularyConstraint` : similar to the previous type of constraint except
  that it does not express a "strong" constraint, which means it is only used to
  restrict the values listed in the drop-down menu of editing form, but it does
  not prevent another entity to be selected.


Definition of relations
-----------------------

XXX add note about defining relation type / definition

A relation is defined by a Python class heriting `RelationType`. The name
of the class corresponds to the name of the type. The class then contains
a description of the properties of this type of relation, and could as well
contain a string for the subject and a string for the object. This allows to create
new definition of associated relations, (so that the class can have the
definition properties from the relation) for example ::

  class locked_by(RelationType):
    """relation on all entities indicating that they are locked"""
    inlined = True
    cardinality = '?*'
    subject = '*'
    object = 'CWUser'

In addition to the permissions, the properties of the relation types
(shared also by all definition of relation of this type) are :


* `inlined` : boolean handling the physical optimization for archiving
  the relation in the subject entity table, instead of creating a specific
  table for the relation. This applies to the relation when the cardinality
  of subject->relation->object is 0..1 (`?`) or 1..1 (`1`)

* `symmetric` : boolean indicating that the relation is symmetrical, which
  means `X relation Y` implies `Y relation X`

In the case of simultaneous relations definitions, `subject` and `object`
can both be equal to the value of the first argument of `SubjectRelation`
and `ObjectRelation`.

When a relation is not inlined and not symmetrical, and it does not require
specific permissions, its definition (by using `SubjectRelation` and
`ObjectRelation`) is all we need.


Updating your application with your new schema
----------------------------------------------

If you modified your schema, the update is not automatic; indeed, this is
in general not a good idea.
Instead, you call a shell on your application, which is a
an interactive python shell, with an appropriate
cubicweb environment ::

   cubicweb-ctl shell myinstance

and type ::

   add_entity_type('Person')

And restart your application!