Open Source Content Management System

mRFC 0016: MgdSchema API

  1. Functionality
  2. Data model
  3. Object creation
    1. gint midgard_object_create(MidgardObject *object)
  4. Object retrieval
    1. MidgardObject *midgard_object_find(GType type, guint id)
    2. MidgardObject **midgard_object_find_matching(GType type, MidgardQueryBuilder *builder, guint *nobjects)
  5. Query builder
  6. Object modification
    1. gint midgard_object_update(MidgardObject *object)
    2. gint midgard_object_update_matching(MidgardObject *object, MidgardQueryBuilder *builder)
  7. Object removal
    1. gint midgard_object_delete(GType type, guint id)
    2. gint midgard_object_delete_matching(GType type, MidgardQueryBuilder *builder)
  8. Parameters
  9. Attachments
  10. Metadata
  11. Sitegroups
  12. Localization
  13. Access control
  14. Data type inspection

This document specifies the client API of the MgdSchema layer. MgdSchema is an abstraction layer for the Midgard datase, and the client API allows Midgard applications and language bindings to access the database using standard interfaces and a standard object model.

The MgdSchema implementation and configuration is specified in the mRFC 0012 document.

The MgdSchema API depends on the GObject library to provide the standard object model.

Functionality

The MgdSchema client API covers the following functionality:

  • Object creation
  • Object retrieval
  • Object modification
  • Object removal
  • Access control
  • Data type inspection

All data inside the Midgard database is accessible using MgdSchema, and no other mechanism should be used to access the database under normal conditions. MgdSchema defines how to create new objects, how to query and retrieve existing objects, and how to modify and remove them. In addition to a generic query by example -mechanism, MgdSchema also provides generic tree and link abstractions for object retrieval.

The MgdSchema API makes the underlying data model visible by providing a type inspection mechanism that can be used to query the available data types and their properties. This makes it possible to write language bindings that can automatically adapt to new Midgard data types.

Data model

All data managed by MgdSchema is stored in the Midgard database and structured according to the MgdSchema configuration. MgdSchema provides a GObject-based object abstraction of this data to the clients. A central part of this abstraction is the MidgardObject base class that provides the common functionality of all MgdSchema objects.


During initialization MgdSchema will dynamically generate a MidgardObject subclass for each configured data type. These subclasses override the generic MidgardObject functionality to match the structure of the underlying database. Clients can then use these subclasses and subclass instances to access the various data types.

TODO parameters, attachments, metadata, sitegroups, localization, access control

Object creation

The configured MidgardObject subclasses can be instantiated using normal GObject conventions, as shown in the example below.

GType type = ...; /* MidgardObject subclass */
MidgardObject *object = MIDGARD_OBJECT(g_object_new(type, NULL));

Instantiated objects are not associated with any records in the database, and their properties are set to null values. Such instances are called template objects, because they can be used as templates for creating or modifying real records in the database. This is achieved by first setting the properties of the template object, and then calling the create() method, as shown below.

g_object_set(object,
"title", "Example title",
"content", "Example content",
NULL);
gint id = midgard_object_create(object);
if (id < 0) {
/* error handling */
}

The create() method uses the properties set in the template object to create a new record in the table identified by the type of the template object. See below a more detailed description of the method.

gint midgard_object_create(MidgardObject *object)

Creates a record in the Midgard database. The record table is determined from the type of the given template object, and the fields of the new record are set to the properties of the template object. Default values are used for fields whose properties have not been set. Metadata field values are filled in automatically, and the corresponding object properties are simply ignored.

Returns the id of the created record if it was successfully created. Otherwise returns -1, and sets the Midgard errno and errstr variables.

The given template object is not modified by this method.

Arguments:

  • object: the template object

Return value:

  • local id of the created object, or -1 on failure

Object retrieval

There are two mechanism in MgdSchema for retrieving data objects from the Midgard database. The first one allows a client to retrieve objects simply by type and id, while the second permits more complex queries.

Each Midgard object type contains a local id number that is unique for each record within that type. The find() class method can be used to retrieve an identified object of a selected type.

GType type = ...; /* MidgardObject subclass */
guint id = ...; /* ID of the selected object */
MidgardObject *object = midgard_object_find(type, id);
if (!object) {
/* error handling */
}

The other retrieval mechanism allows clients to retrieve more than one object at a time and to use more complex queries to identify the retrieved objects. The find_matching() class method uses a separate query builder object generated by the get_query_builder() class method to specify the query used to identify the retrieved objects.

GType type = ...; /* MidgardObject subclass */
GValue value = ...; /* Some date value for the query */
MidgardQueryBuilder *builder = midgard_object_get_query_builder(type);
midgard_query_builder_add_criteria(builder, "created", ">=", value);
guint nobjects = 0;
MidgardObject **objects =
midgard_object_find_matching(type, builder, &nobjects);
if (!objects) {
/* error handling */
}

See below for the detailed retrieval method signatures. The query builder functionality is described in the next section.

MidgardObject *midgard_object_find(GType type, guint id)

Retrieves the identified object from the Midgard database. The given type and local id number are used to select the database table and row to be returned.

If the identified record is found, it is wrapped into an instance of the given MidgardObject subclass and returned to the caller. If the record is not found or if a failure occurs, then a NULL pointer is returned to the caller. The caller can use the Midgard errno and errstr values to determine the cause of a NULL return value.

Arguments:

  • type: record type (MidgardObject subclass)
  • id: the local id of the record

Return value:

  • retrieved object, or NULL on failure or if the record was not found

MidgardObject **midgard_object_find_matching(GType type, MidgardQueryBuilder *builder, guint *nobjects)

Retrieves objects from the Midgard database. The retrieved objects are selected using the given record type and the query built by the given query builder.

The retrived objects are returned as an array of pointers and the number of objects is stored in the given location. A NULL pointer is returned on failures. The caller can then check the Midgard errno and errstr values to determine the cause of the failure.

Arguments:

  • type: record type (MidgardObject subclass)
  • builder: query builder
  • nobjects: location for the number of retrieved objects

Return value:

  • array of retrieved objects, or NULL on failure

Query builder

TODO

GType type = ...; /* MidgardObject subclass */
MidgardQueryBuilder *builder = midgard_object_get_query_builder(type);
midgard_query_builder_add_criteria(builder, "created", ">=", value);
...

Object modification

MgdSchema provides mechanisms to modify the contents of a single object that was earlier retrieved from the Midgard database or to do batch updates defined by a template object and a query builder.

A single object can be modified by setting some of its properties and invoking the update() method, as shown below.

MidgardObject *object = ...; /* Retrieved MidgardObject */
g_object_set(object,
"title", "Updated title",
NULL);
gint rv = midgard_object_update(object);
if (rv < 0) {
/* error handling */
}

A batch update can be performed by instantiating and filling in a template object, building a query, and invoking the update_matching() method on the template object.

GType type = ...; /* MidgardObject subclass */
MidgardObject *object = MIDGARD_OBJECT(g_object_new(type, NULL));
g_object_set(object,
"title", "Updated title",
NULL);
MidgardQueryBuilder *builder = ...; /* Query to select records to update */
gint rv = midgard_object_update_matching(object, builder);
if (rv < 0) {
/* error handling */
}

See below for the detailed update method signatures.

gint midgard_object_update(MidgardObject *object)

Updates a record in the Midgard database. The record is identified using the type and local id of the given object. The object properties that have changed since the object was retrieved are written to the corresponding fields of the database record. Possible metadata updates are generated automatically.

  • Returns 1 if the record was successfully updated.
  • Returns 0 if the record was not found in the database.
  • Returns -1 if a failure occurred. The caller can use the Midgard errno and errstr values to determine the cause of a failure.

Arguments:

  • object: the object to be updated

Return value:

  • 1 if successfull, 0 if record was not found, or -1 on failure

gint midgard_object_update_matching(MidgardObject *object, MidgardQueryBuilder *builder)

Updates records in the Midgard database. The updated records are selected using the type of the given template object and the query built by the given query builder. The properties that have been set in the template object are written to the corresponding fields of the selected database records. Possible metadata updates are generated automatically.

Returns the number of updated records, or -1 if a failure occurred. The caller can use the Midgard errno and errstr values to determine the cause of a failure.

Arguments:

  • object: templage object
  • builder: query builder

Return value:

  • number of updated records, or -1 on failure

Object removal

Just like for object retrieval and modification, MgdSchema provides two mechanisms for removing objects from the database. The class methods delete() and delete_matching() remove objects of the selected type either by the local id or a more general query.

A single object can be removed using the delete() class method.

GType type = ...; /* MidgardObject subtype */
guint id = ...; /* ID of the record to be removed */
gint rv = midgard_object_delete(type, id);
if (rv < 0) {
/* Error handling */
}

More than one object can be removed simultaneously by using the delete_matching() class method and a query builder.

GType type = ...; /* MidgardObject subtype */
MidgardQueryBuilder *builder = ...; /* Query to select records to remove */
gint rv = midgard_object_delete_matching(type, builder);
if (rv < 0) {
/* error handling */
}

See below for the detailed delete method signatures.

gint midgard_object_delete(GType type, guint id)

Removes the identified record from the Midgard database. The given type and local id number are used to select the database table and row to be removed.

  • Returns 1 if a record was successfully removed.
  • Returns 0 if the identified record does not exist.
  • Returns -1 if a failure occurred. The caller can use the Midgard errno and errstr values to determine the cause of a failure.

Arguments:

  • type: record type (MidgardObject subclass)
  • id: the local id of the record

Return value:

  • 1 if successful, 0 if record was not found, -1 on failure

gint midgard_object_delete_matching(GType type, MidgardQueryBuilder *builder)

Removes records from the Midgard database. The removed records are selected by the given type and the query built by the given query builder.

Returns the number of removed records. Returns -1 if a failure occurred. The caller can use the Midgard errno and errstr values to determine the cause of a failure.

Arguments:

  • type: record type (MidgardObject subclass)
  • builder: query builder

Return value:

  • number of removed records, -1 on failure

Parameters

TODO

Attachments

TODO

Metadata

TODO

Sitegroups

TODO

Localization

TODO

Access control

TODO

Data type inspection

MgdSchema uses the GObject API to provide a data inspection mechanism. This makes it possible to write general-purpose clients without hardcoding any information that is specific to a given data type. This feature is especially important to language bindings.

TODO

Clients can use the MidgardObject base class to find the available MgdSchema data types:

guint ntypes = 0;
GType *types = g_type_children(MIDGARD_TYPE_OBJECT, &ntypes);

The name of each data type:

GType type = ...;
const gchar *name = g_type_name(type);

The properties of a data type:

GType type = ...;
GObjectClass *klass = G_OBJECT_CLASS(g_type_class_ref(type));
guint nproperties = 0;
GParamSpec *properties = g_object_class_list_properties(klass, &nproperties);
g_type_class_unref(klass);

Link structure:

GType type = ...;
GParamSpec *property = ...;
if (property->flags & MIDGARD_PARAM_LINK) {
GType target = midgard_type_get_link_target(type, property->name);
}

Tree structure:

GType type = ...;
GParamSpec *parentfield = midgard_type_get_parent_field(type);
GParamSpec *namefield = midgard_type_get_name_field(type);

Back

Designed by Nemein, hosted by Anykey