![]() |
![]() |
![]() |
GNOME Data Access manual | ![]() |
---|
Every DML (Data Manipulation Language) query is described as a single GdaQuery object. The object is then specialized to represent all the possible DML queries:
selection queries: of type GDA_QUERY_TYPE_SELECT
modification queries: of type GDA_QUERY_TYPE_INSERT, GDA_QUERY_TYPE_UPDATE and GDA_QUERY_TYPE_DELETE
aggregation queries: of type GDA_QUERY_TYPE_UNION, GDA_QUERY_TYPE_INTERSECT and GDA_QUERY_TYPE_EXCEPT
direct SQL queries: when they can be interpreted, their type is set to one of the above types, and when parsing is not possible (either because the SQL statement is wrong or because the SQL statement uses some specific extensions), the type is set to GDA_QUERY_TYPE_NON_PARSED_SQL
The general structure of a query is the following one:
A list of targets (as GdaQueryTarget objects). Each GdaQueryTarget object represents an entity (= an object which implements the GdaEntity interface, for example a database table or another query); A single entity can be represented several times through different GdaQueryTarget objects. In the example above there are two GdaQueryTarget objects representing the "person" and "title" entities.
If a target that represents a GdaQuery object is added to a query, then the represented query MUST BE a sub query of the query the target is added to. In the following query: “"SELECT firstname, lastname FROM (SELECT * FROM person WHERE type=1)"”, there is one GdaQueryTarget object which represents the “"SELECT * FROM person WHERE type=1"” sub query and that sub query must be declared as a sub query of the complete query.
A list of joins (as GdaQueryJoin objects) between the targets. This is usefull only for selection queries where a join represents a SQL join between entities to avoid cross products. In the example above there is one GdaQueryJoin object to represent the "INNER JOIN" between the two GdaQueryTarget objects representing the "person" and "title" entities.
A list of fields (as GdaQueryField objects). Query fields can be of several different types to represent all the possibilities of data manipulation. In the example query, there are three query fields, all representing an entity's field: "firstname", "lastname" and "title".
Query fields can be visible or invisible (in which case they are only there to be used by other query fields, but they do not participate directly in the query).
Depending on their type, some query fields have a "value_provider" property which can point to another query field. In this case, when the query is executed, the query field which is pointed at is used to provide a value. This is particularly the case of modification queries: a query such as “"INSERT INTO persons (firstname, lastname) VALUES ('name1', 'name2')"”, the query fields "firstname" and "lastname" have their "value_provider" property pointing respectively to the GdaQueryFieldValue query fields with the values "name1" and "name2".
A list of sub queries (also as GdaQuery objects).
A condition on the application of the query (as a GdaQueryCondition object). A condition object can contain several sub conditions.
Some other attributes describing the grouping and ordering.
The requirements in terms of query structuration for each type of query is explained in the following sections. Note that these requirements are only really tested when the query is rendered into an executable statement, where errors may be returned.
The GdaGraphviz object can produce .dot files out of a GdaQuery object, which can the processed using the GraphViz tool. This tool has been used to produce the internal represantations of queries in this documentation.
As an example, the following query “SELECT t1.id, t1.name, t2.name, t3.country, t3.city FROM customers AS t1 INNER JOIN salesrep AS t2 ON (t1.default_served_by=t2.id) LEFT JOIN locations AS t3 ON (t1.country=t3.country AND t1.city=t3.city) WHERE t1.id=12” has the internal structure as represented in the following figure.
Internal structure of the "SELECT t1.id, t1.name, t2.name, t3.country, t3.city FROM customers AS t1 INNER JOIN salesrep AS t2 ON (t1.default_served_by=t2.id) LEFT JOIN locations AS t3 ON (t1.country=t3.country AND t1.city=t3.city) WHERE t1.id=12" query.
Here is how to read the diagram:
Each GdaQueryTarget object is represented by an orange box (here "customers", "salesrep" and "locations").
Each GdaQueryJoin object is represented by an arc between the GdaQueryTarget objects it links. Here there is one join between "customers" and "salesrep" (INNER join), and one between "customers" and "locations" (LEFT join, note the empty circle on the side of the target where NULL values can be part of the join).
Each GdaQueryField object is represented by a blue box devided into two rows: the top one is the name of the field, and the bottom one is devided into 4 boxes which in order from the left display the real type of field ("Field" fo a GdaQueryFieldField, "Value" for a GdaQueryFieldValue, etc), if the field is visible (a "V" appears), if the field is internal (marked with a "I") and if the field is a query parameter (a "P").
Also, each blue box representing a GdaQueryFieldField object has an arc to the GdaQueryTarget in which it belongs.
The GdaQueryCondition object, if present, is represented by a yellow box labeled after the SQL representation of the condition, and with arcs to all the GdaQueryField objects it uses.
Any query can require some parameters to be given values before they can be executed. That is the case for example for a query like “SELECT name FROM person WHERE age = <value>” where "<value>" is a parameter which value must be provided before the query can be executed. A parameter can only be represented as such in a query by a GdaQueryFieldValue query field, and providing a value for a parameter to a query is done using a GdaParameter object.
A query QU1 can specify that a given parameter QU1:QF1 have its value restrained by the values of another "SELECT" query (QU2:QF2). In this case the GdaQueryFieldValue which is a parameter (QU1:QF1) has its "value_prov" property set to point to the QU2:QF1 field In this case, the QU2 query can be managed by the QU1 query (use the gda_query_add_param_source() and similar methods).
The list of parameters required to run a query is obtained using the gda_entity_get_parameters() method. This function returns a raw list of parameters. Usually however, it is better to use a GdaParameterList object which stores the parameters, and organises the parameters in a convenient. The function to be used to obtain a GdaParameterList object is gda_entity_get_exec_context(). them
A selection query can have all the possible structural elements, with the following restrictions:
All the sub queries must also be selection queries
Modification queries have the following structural restrictions:
There must be one and only one target object which represents the entity to be modified. Also the represented entity mus be modifiable (ie it cannot be another query or a database view for example)
There cannot be any join
All the visible query fields must be GdaQueryFieldField fields
If the query is an insertion query, there must be at most one sub query, and in this case the sub query must be a selection query (and the insertion query will be interpreted as "INSERT INTO table SELECT ..."). As a consequence the sub query must render the same number of fields as the query itself.
Also, if there is no sub query, then all the fields which are value providers MUST be GdaQueryFieldValue fields.
Insertion queries can't have any associated condition.
If the query is a deletion query, then there can't be any visible field at all (some hidden ones can exist to take part in a condition.
If the query is an update query, then all the fields which are value providers MUST NOT be GdaQueryFieldAll fields.
As it is sometimes easier to define a query usong an SQL statement, a #GdaQuery object can be defined from any SQL 1992 statement, using the gda_query_set_sql_text() method. The SQL passed as argument must be a single SQL statement (that is not several statements separated by a colon).
Some extensions are provided to be able to define variables from within SQL. The way of doing this is to use the following syntax right after a constant value in the SQL statement: [:attribute="value", ...]. For example the following SQL:
SELECT 10[:type="int2" :descr="this is a good' description" :isparam="TRUE" :nullok="TRUE"], id FROM customers
creates a query structure similar to "SELECT 10, t1.id FROM customers AS t1", but also specifies that the "10" value is in fact to be interpreted as of type "int2", with a description, that it is a variable for which the NULL value is acceptable.
So, when the query will be executed, the real executed SQL statement will be "SELECT 10, t1.id FROM customers AS t1" if the "10" value has not been replaced by another value. The replacement of that value will be possible through the usage of a #GdaParameter object (obtained through a GdaParameterList object).
The available extension "tags" are:
":name" fixes the name of the value's name
":descr" fixes the name of the value's description
":type" fixes the Gda type or the GdaDictType type of the value
":isparam" tells if value is a variable (a parameter) or not (the default is that it is a parameter)
":nullok" tells if value can have a NULL value
Each query can contain some fields which make the query's contents. There are different types of query fields, and each type corresponds to a class and inherits the GdaQueryField class.
Any query field can be visible or hidden. A visible field will appear in the entity corresponding to the query (in case of SELECTion queries anyway), and invisible fields are used by other query fields.
Also, any query field can be internal or not. An internal field is one used by the library itself, and should never be known to the user of the library (so it is just mentionned here for completeness).
Some fields can represent more than one value (usefull for IN operators for example).
The different types of query fields are:
GdaQueryFieldAll: represents all the fields of an entity which itself is represented through a GdaQueryTarget (the SQL notation is "entity.*")
GdaQueryFieldField: represents one field of an entity which itself is represented through a GdaQueryTarget (the SQL notation is "entity.field")
GdaQueryFieldValue: represents a value, which can also be a parameter (in this case the parameter may or may not have a default value)
GdaQueryFieldFunc: represents the result of a function (a GdaDictFunction object) applied to one or more query field object(s) of the same query
GdaQueryFieldAgg: represents the result of an aggregate (a GdaDictAggregate object) applied to a query field object of the same query
GnomeDbQfSelect: represents the result of the execution of a whole SELECTion query. It represents a list but may return a single value as well
GnomeDbQfLink: represents one field of an entity, that entity not being represented through a GdaQueryTarget object. This kind of query field is used to link sub-queries to their parent query in complex queries
GdaQueryFieldValue: represent a list of values, which cannot be parameters
<< GdaDictConstraint | GdaQuery >> |