For SELECT, the returned list is a list of all of the instances of 'SomeObj' that match the query. The 'SORT' term is optional. The 'WHERE' term is optional; but if you don't include 'WHERE', you will get a list of all of the object instances. The Boolean operations 'AND' and 'OR' together with parenthesis can be used to construct arbitrarily nested predicates.
For INSERT, the returned list is a list containing the newly created instance of 'SomeObj'.
Joins are not supported directly. SELECT * FROM ObjA,ObjB WHERE (ObjA.param_id = ObjB.param_other_id); The problem with the above is that the search requires a nested search loop, aka a 'join', which is not currently supported in the underlying QofQuery code.
However, by repeating queries and adding the entities to a new session using qof_entity_copy_list, a series of queries can be added to a single book. e.g. You can insert multiple entities and save out as a QSF XML file or use multiple SELECT queries to build a precise list - this can be used to replicate most of the functionality of a SQL join.
SELECT * from ObjA where param_id = value; SELECT * from ObjB where param_other_id = value;
Equivalent to: SELECT * from ObjA,ObjB where param_id = param_other_id and param_id = value;
When combined with a foreach callback on the value of param_id for each entity in the QofBook, you can produce the effect of a join from running the two SELECT queries for each value of param_id held in 'value'.
See QofEntityForeachCB and qof_object_foreach.
Date queries handle full date and time strings, using the format exported by the QSF backend. To query dates and times, convert user input into UTC time using the QOF_UTC_DATE_FORMAT string. e.g. set the UTC date format and call qof_print_time_buff with a time_t obtained via timespecToTime_t.
If the param is a KVP frame, then we use a special markup to indicate frame values. The markup should look like /some/kvp/path:value. Thus, for example, SELECT * FROM SomeObj WHERE (param_a < '/some/kvp:10.0') will search for the object where param_a is a KVP frame, and this KVP frame contains a path '/some/kvp' and the value stored at that path is floating-point and that float value is less than 10.0.
The following are types of queries are NOT supported: SELECT a,b,c FROM ... I am thinking of implementing the above as a list of KVP's whose keys would be a,b,c and values would be the results of the search. (Linas)
XXX (Neil W). Alternatively, I need to use something like this when converting QOF objects between applications by using the returned parameter values to create a second object. One application using QOF could register objects from two applications and convert data from one to the other by using SELECT a,b,c FROM ObjA; SELECT d,f,k FROM ObjB; qof_object_new_instance(); ObjC_set_a(value_c); ObjC_set_b(value_k) etc. What's needed is for the SELECT to return a complete object that only contains the parameters selected.
Also unsupported: UPDATE.
Certain SQL commands can have no QOF equivalent and will generate a runtime parser error:
Typedefs | |
| typedef _QofSqlQuery | QofSqlQuery |
Functions | |
| QofSqlQuery * | qof_sql_query_new (void) |
| void | qof_sql_query_destroy (QofSqlQuery *) |
| void | qof_sql_query_set_book (QofSqlQuery *q, QofBook *book) |
| GList * | qof_sql_query_run (QofSqlQuery *query, const char *str) |
| Perform the query, return the results. | |
| void | qof_sql_query_parse (QofSqlQuery *query, const char *str) |
| QofQuery * | qof_sql_query_get_query (QofSqlQuery *) |
| GList * | qof_sql_query_rerun (QofSqlQuery *query) |
| void | qof_sql_query_set_kvp (QofSqlQuery *, KvpFrame *) |
|
|
Return the QofQuery form of the previously parsed query. Definition at line 99 of file qofsql.c.
|
|
|
Create a new SQL-syntax query machine. Definition at line 72 of file qofsql.c. 00073 { 00074 QofSqlQuery * sqn = (QofSqlQuery *) g_new0 (QofSqlQuery, 1); 00075 00076 sqn->qof_query = NULL; 00077 sqn->parse_result = NULL; 00078 sqn->book = NULL; 00079 sqn->single_global_tablename = NULL; 00080 sqn->kvp_join = NULL; 00081 00082 return sqn; 00083 }
|
|
||||||||||||
|
Same qof_sql_query_run, but just parse/pre-process the query; do not actually run it over the dataset. The QofBook does not need to be set before calling this function. Definition at line 814 of file qofsql.c. 00815 { 00816 GList *tables; 00817 char *buf; 00818 sql_select_statement *sss; 00819 sql_where *swear; 00820 00821 if (!query) return; 00822 00823 /* Delete old query, if any */ 00824 if (query->qof_query) 00825 { 00826 qof_query_destroy (query->qof_query); 00827 sql_destroy(query->parse_result); 00828 query->qof_query = NULL; 00829 } 00830 00831 /* Parse the SQL string */ 00832 buf = g_strdup(str); 00833 query->parse_result = sql_parse (buf); 00834 g_free(buf); 00835 00836 if (!query->parse_result) 00837 { 00838 PWARN ("parse error"); 00839 return; 00840 } 00841 00842 if ((SQL_select != query->parse_result->type)&&(SQL_insert != query->parse_result->type)) 00843 { 00844 PWARN("currently, only SELECT or INSERT statements are supported, " 00845 "got type=%s", sql_type_as_string(query->parse_result->type)); 00846 return; 00847 } 00848 00849 /* If the user wrote "SELECT * FROM tablename WHERE ..." 00850 * then we have a single global tablename. But if the 00851 * user wrote "SELECT * FROM tableA, tableB WHERE ..." 00852 * then we don't have a single unique table-name. 00853 */ 00854 tables = sql_statement_get_tables (query->parse_result); 00855 if (1 == g_list_length (tables)) 00856 { 00857 query->single_global_tablename = tables->data; 00858 } 00859 /* if this is an insert, we're done with the parse. */ 00860 if(SQL_insert == query->parse_result->type) { 00861 query->qof_query = qof_query_create(); 00862 return; 00863 } 00864 sss = query->parse_result->statement; 00865 swear = sss->where; 00866 if (swear) 00867 { 00868 /* Walk over the where terms, turn them into QOF predicates */ 00869 query->qof_query = handle_where (query, swear); 00870 if (NULL == query->qof_query) return; 00871 } 00872 else 00873 { 00874 query->qof_query = qof_query_create(); 00875 } 00876 /* Provide support for different sort orders */ 00877 handle_sort_order (query, sss->order); 00878 00879 /* We also want to set the type of thing to search for. 00880 * If the user said SELECT * FROM ... then we should return 00881 * a list of QofEntity. Otherwise, we return ... ? 00882 * XXX all this needs fixing. 00883 */ 00884 qof_query_search_for (query->qof_query, query->single_global_tablename); 00885 }
|
|
|
Run the previously parsed query. The QofBook must be set before this function can be called. Note, teh QofBook can be changed between each successive call to this routine. This routine can be called after either qof_sql_query_parse() or qof_sql_query_run() because both will set up the parse. Definition at line 912 of file qofsql.c. 00913 { 00914 GList *results; 00915 00916 if (!query) return NULL; 00917 00918 if (NULL == query->qof_query) return NULL; 00919 00920 qof_query_set_book (query->qof_query, query->book); 00921 00922 // qof_query_print (query->qof_query); 00923 results = qof_query_run (query->qof_query); 00924 00925 return results; 00926 }
|
|
||||||||||||
|
Perform the query, return the results. The book must be set in order to be able to perform a query. The returned list will have been sorted using the indicated sort order, (by default ascending order) and trimmed to the max_results length. Do NOT free the resulting list. This list is managed internally by QofSqlQuery. Definition at line 890 of file qofsql.c. 00891 { 00892 GList *results; 00893 00894 if (!query) return NULL; 00895 00896 qof_sql_query_parse (query, str); 00897 if (NULL == query->qof_query) return NULL; 00898 00899 qof_query_set_book (query->qof_query, query->book); 00900 if(SQL_insert == query->parse_result->type){ 00901 results = NULL; 00902 results = g_list_append(results, qof_query_insert(query)); 00903 return results; 00904 } 00905 qof_query_print (query->qof_query); 00906 results = qof_query_run (query->qof_query); 00907 00908 return results; 00909 }
|
|
||||||||||||
|
Set the book to be searched (you can search multiple books) If no books are set, no results will be returned (since there is nothing to search over). Definition at line 108 of file qofsql.c. 00109 { 00110 if (!q) return; 00111 q->book = book; 00112 }
|
|
||||||||||||
|
Set the kvp frame to be used for formulating 'indirect' predicates. Although joins are not supported (see above), there is one special hack that one can use to pass data indirectly into the predicates. This is by using a KVP key name to reference the value to be used for a predicate. Thus, for example, SELECT * FROM SomeObj WHERE (param_a = KVP:/some/key/path); will look up the value stored at '/some/key/path', and use that value to form the actual predicate. So, for example, if the value stored at '/some/key/path' was 2, then the actual query run will be SELECT * FROM SomeObj WHERE (param_a = 2); The lookup occurs at the time that the query is formulated. The query does *not* take over ownership of the kvp frame, nor does it copy it. Thus, the kvp frame must exist when the query is formulated, and it is the responsibility of the caller to free it when no longer needed. Note that because this feature is a kind of a hack put in place due to the lack of support for joins, it will probably go away (be deprecated) if/when joins are implemented. Definition at line 117 of file qofsql.c.
|
1.4.5