00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "config.h"
00025
00026 #include "qofquery-serialize.h"
00027 #include "qofquery-p.h"
00028 #include "qofquerycore-p.h"
00029 #include "kvp_frame.h"
00030
00031
00032
00033
00034
00035
00036 #define PUT_STR(TOK,VAL) { \
00037 xmlNodePtr node; \
00038 const char * str = (VAL); \
00039 if (str && 0 != str[0]) \
00040 { \
00041 node = xmlNewNode (NULL, TOK); \
00042 xmlNodeAddContent(node, str); \
00043 xmlAddChild (topnode, node); \
00044 } \
00045 }
00046
00047 #define PUT_INT32(TOK,VAL) { \
00048 xmlNodePtr node; \
00049 char buff[80]; \
00050 g_snprintf (buff, sizeof(buff), "%d", (VAL)); \
00051 node = xmlNewNode (NULL, TOK); \
00052 xmlNodeAddContent(node, buff); \
00053 xmlAddChild (topnode, node); \
00054 }
00055
00056 #define PUT_INT64(TOK,VAL) { \
00057 xmlNodePtr node; \
00058 char buff[80]; \
00059 g_snprintf (buff, sizeof(buff), "%" G_GINT64_FORMAT, (VAL)); \
00060 node = xmlNewNode (NULL, TOK); \
00061 xmlNodeAddContent(node, buff); \
00062 xmlAddChild (topnode, node); \
00063 }
00064
00065 #define PUT_DBL(TOK,VAL) { \
00066 xmlNodePtr node; \
00067 char buff[80]; \
00068 g_snprintf (buff, sizeof(buff), "%.18g", (VAL)); \
00069 node = xmlNewNode (NULL, TOK); \
00070 xmlNodeAddContent(node, buff); \
00071 xmlAddChild (topnode, node); \
00072 }
00073
00074 #define PUT_GUID(TOK,VAL) { \
00075 xmlNodePtr node; \
00076 char buff[80]; \
00077 guid_to_string_buff ((VAL), buff); \
00078 node = xmlNewNode (NULL, TOK); \
00079 xmlNodeAddContent(node, buff); \
00080 xmlAddChild (topnode, node); \
00081 }
00082
00083 #define PUT_DATE(TOK,VAL) { \
00084 xmlNodePtr node; \
00085 char buff[80]; \
00086 gnc_timespec_to_iso8601_buff ((VAL), buff); \
00087 node = xmlNewNode (NULL, TOK); \
00088 xmlNodeAddContent(node, buff); \
00089 xmlAddChild (topnode, node); \
00090 }
00091
00092 #define PUT_NUMERIC(TOK,VAL) { \
00093 xmlNodePtr node; \
00094 char *str; \
00095 str = gnc_numeric_to_string (VAL); \
00096 node = xmlNewNode (NULL, TOK); \
00097 xmlNodeAddContent(node, str); \
00098 g_free (str); \
00099 xmlAddChild (topnode, node); \
00100 }
00101
00102 #define PUT_BOOL(TOK,VAL) { \
00103 xmlNodePtr node; \
00104 gboolean boll = (VAL); \
00105 node = xmlNewNode (NULL, TOK); \
00106 if (boll) { \
00107 xmlNodeAddContent(node, "T"); \
00108 } else { \
00109 xmlNodeAddContent(node, "F"); \
00110 } \
00111 xmlAddChild (topnode, node); \
00112 }
00113
00114 #define PUT_HOW(TOK,VAL,A,B,C,D,E,F) { \
00115 xmlNodePtr node; \
00116 const char * str = "EQUAL"; \
00117 switch (VAL) \
00118 { \
00119 case QOF_COMPARE_##A: str = #A; break; \
00120 case QOF_COMPARE_##B: str = #B; break; \
00121 case QOF_COMPARE_##C: str = #C; break; \
00122 case QOF_COMPARE_##D: str = #D; break; \
00123 case QOF_COMPARE_##E: str = #E; break; \
00124 case QOF_COMPARE_##F: str = #F; break; \
00125 } \
00126 node = xmlNewNode (NULL, TOK); \
00127 xmlNodeAddContent(node, str); \
00128 xmlAddChild (topnode, node); \
00129 }
00130
00131 #define PUT_MATCH2(TOK,VAL,PFX,A,B) { \
00132 xmlNodePtr node; \
00133 const char * str = #A; \
00134 switch (VAL) \
00135 { \
00136 case QOF_##PFX##_##A: str = #A; break; \
00137 case QOF_##PFX##_##B: str = #B; break; \
00138 } \
00139 node = xmlNewNode (NULL, TOK); \
00140 xmlNodeAddContent(node, str); \
00141 xmlAddChild (topnode, node); \
00142 }
00143
00144 #define PUT_MATCH3(TOK,VAL,PFX,A,B,C) { \
00145 xmlNodePtr node; \
00146 const char * str = #A; \
00147 switch (VAL) \
00148 { \
00149 case QOF_##PFX##_##A: str = #A; break; \
00150 case QOF_##PFX##_##B: str = #B; break; \
00151 case QOF_##PFX##_##C: str = #C; break; \
00152 } \
00153 node = xmlNewNode (NULL, TOK); \
00154 xmlNodeAddContent(node, str); \
00155 xmlAddChild (topnode, node); \
00156 }
00157
00158 #define PUT_MATCH5(TOK,VAL,PFX,A,B,C,D,E) { \
00159 xmlNodePtr node; \
00160 const char * str = #A; \
00161 switch (VAL) \
00162 { \
00163 case QOF_##PFX##_##A: str = #A; break; \
00164 case QOF_##PFX##_##B: str = #B; break; \
00165 case QOF_##PFX##_##C: str = #C; break; \
00166 case QOF_##PFX##_##D: str = #D; break; \
00167 case QOF_##PFX##_##E: str = #E; break; \
00168 } \
00169 node = xmlNewNode (NULL, TOK); \
00170 xmlNodeAddContent(node, str); \
00171 xmlAddChild (topnode, node); \
00172 }
00173
00174
00175
00176 static void
00177 qof_kvp_value_to_xml (KvpValue *kval, xmlNodePtr topnode)
00178 {
00179 KvpValueType kvt = kvp_value_get_type (kval);
00180
00181 switch (kvt)
00182 {
00183 case KVP_TYPE_GINT64:
00184 PUT_INT64 ("qofquery:int64", kvp_value_get_gint64(kval));
00185 break;
00186 case KVP_TYPE_DOUBLE:
00187 PUT_DBL ("qofquery:double", kvp_value_get_double(kval));
00188 break;
00189 case KVP_TYPE_NUMERIC:
00190 PUT_NUMERIC ("qofquery:numeric", kvp_value_get_numeric(kval));
00191 break;
00192 case KVP_TYPE_GUID:
00193 PUT_GUID ("qofquery:guid", kvp_value_get_guid(kval));
00194 break;
00195 case KVP_TYPE_STRING:
00196 PUT_STR ("qofquery:string", kvp_value_get_string(kval));
00197 break;
00198 case KVP_TYPE_TIMESPEC:
00199 PUT_DATE ("qofquery:date", kvp_value_get_timespec(kval));
00200 break;
00201 case KVP_TYPE_BINARY:
00202 case KVP_TYPE_GLIST:
00203 case KVP_TYPE_FRAME:
00204
00205 break;
00206 }
00207 }
00208
00209
00210
00211 static xmlNodePtr
00212 qof_query_pred_data_to_xml (QofQueryPredData *pd)
00213 {
00214 GList *n;
00215 GSList *ns;
00216 xmlNodePtr topnode;
00217 query_guid_t pdata_g;
00218 query_string_t pdata_s;
00219 query_numeric_t pdata_n;
00220 query_kvp_t pdata_k;
00221 query_date_t pdata_d;
00222 query_int64_t pdata_i64;
00223 query_int32_t pdata_i32;
00224 query_double_t pdata_db;
00225 query_boolean_t pdata_bool;
00226 query_char_t pdata_c;
00227
00228 if (!safe_strcmp (pd->type_name, QOF_TYPE_GUID))
00229 {
00230 topnode = xmlNewNode (NULL, "qofquery:pred-guid");
00231
00232
00233 pdata_g = (query_guid_t) pd;
00234 PUT_MATCH5("qofquery:guid-match", pdata_g->options,
00235 GUID_MATCH, ANY, ALL, NONE, NULL, LIST_ANY);
00236
00237 for (n = pdata_g->guids; n; n = n->next)
00238 {
00239 PUT_GUID ("qofquery:guid", n->data);
00240 }
00241 return topnode;
00242 }
00243 if (!safe_strcmp (pd->type_name, QOF_TYPE_STRING))
00244 {
00245 topnode = xmlNewNode (NULL, "qofquery:pred-string");
00246 PUT_HOW ("qofquery:compare", pd->how, LT, LTE, EQUAL, GT, GTE, NEQ);
00247
00248 pdata_s = (query_string_t) pd;
00249 PUT_MATCH2("qofquery:string-match", pdata_s->options,
00250 STRING_MATCH, NORMAL, CASEINSENSITIVE);
00251 PUT_BOOL ("qofquery:is-regex", pdata_s->is_regex);
00252 PUT_STR ("qofquery:string", pdata_s->matchstring);
00253 return topnode;
00254 }
00255 if (!safe_strcmp (pd->type_name, QOF_TYPE_NUMERIC))
00256 {
00257 topnode = xmlNewNode (NULL, "qofquery:pred-numeric");
00258 PUT_HOW ("qofquery:compare", pd->how, LT, LTE, EQUAL, GT, GTE, NEQ);
00259
00260 pdata_n = (query_numeric_t) pd;
00261 PUT_MATCH3("qofquery:numeric-match", pdata_n->options,
00262 NUMERIC_MATCH, DEBIT, CREDIT, ANY);
00263
00264 PUT_NUMERIC ("qofquery:numeric", pdata_n->amount);
00265 return topnode;
00266 }
00267 if (!safe_strcmp (pd->type_name, QOF_TYPE_KVP))
00268 {
00269 topnode = xmlNewNode (NULL, "qofquery:pred-kvp");
00270 PUT_HOW ("qofquery:compare", pd->how, LT, LTE, EQUAL, GT, GTE, NEQ);
00271
00272 pdata_k = (query_kvp_t) pd;
00273 for (ns=pdata_k->path; ns; ns=ns->next)
00274 {
00275 PUT_STR ("qofquery:kvp-path", ns->data);
00276 }
00277 qof_kvp_value_to_xml (pdata_k->value, topnode);
00278 return topnode;
00279 }
00280 if (!safe_strcmp (pd->type_name, QOF_TYPE_DATE))
00281 {
00282 topnode = xmlNewNode (NULL, "qofquery:pred-date");
00283 PUT_HOW ("qofquery:compare", pd->how, LT, LTE, EQUAL, GT, GTE, NEQ);
00284
00285 pdata_d = (query_date_t) pd;
00286
00287 PUT_MATCH2("qofquery:date-match", pdata_d->options,
00288 DATE_MATCH, NORMAL, DAY);
00289
00290 PUT_DATE ("qofquery:date", pdata_d->date);
00291 return topnode;
00292 }
00293 if (!safe_strcmp (pd->type_name, QOF_TYPE_INT64))
00294 {
00295 topnode = xmlNewNode (NULL, "qofquery:pred-int64");
00296 PUT_HOW ("qofquery:compare", pd->how, LT, LTE, EQUAL, GT, GTE, NEQ);
00297
00298 pdata_i64 = (query_int64_t) pd;
00299 PUT_INT64 ("qofquery:int64", pdata_i64->val);
00300 return topnode;
00301 }
00302 if (!safe_strcmp (pd->type_name, QOF_TYPE_INT32))
00303 {
00304 topnode = xmlNewNode (NULL, "qofquery:pred-int32");
00305 PUT_HOW ("qofquery:compare", pd->how, LT, LTE, EQUAL, GT, GTE, NEQ);
00306
00307 pdata_i32 = (query_int32_t) pd;
00308
00309 PUT_INT32 ("qofquery:int32", pdata_i32->val);
00310 return topnode;
00311 }
00312 if (!safe_strcmp (pd->type_name, QOF_TYPE_DOUBLE))
00313 {
00314 topnode = xmlNewNode (NULL, "qofquery:pred-double");
00315 PUT_HOW ("qofquery:compare", pd->how, LT, LTE, EQUAL, GT, GTE, NEQ);
00316
00317 pdata_db = (query_double_t) pd;
00318
00319 PUT_DBL ("qofquery:double", pdata_db->val);
00320 return topnode;
00321 }
00322 if (!safe_strcmp (pd->type_name, QOF_TYPE_BOOLEAN))
00323 {
00324 topnode = xmlNewNode (NULL, "qofquery:pred-boolean");
00325 PUT_HOW ("qofquery:compare", pd->how, LT, LTE, EQUAL, GT, GTE, NEQ);
00326
00327 pdata_bool = (query_boolean_t) pd;
00328
00329 PUT_BOOL ("qofquery:boolean", pdata_bool->val);
00330 return topnode;
00331 }
00332 if (!safe_strcmp (pd->type_name, QOF_TYPE_CHAR))
00333 {
00334 topnode = xmlNewNode (NULL, "qofquery:pred-char");
00335
00336 pdata_c = (query_char_t) pd;
00337
00338 PUT_MATCH2("qofquery:char-match", pdata_c->options,
00339 CHAR_MATCH, ANY, NONE);
00340
00341 PUT_STR ("qofquery:char-list", pdata_c->char_list);
00342 return topnode;
00343 }
00344 return NULL;
00345 }
00346
00347
00348
00349 static xmlNodePtr
00350 qof_query_param_path_to_xml (GSList *param_path)
00351 {
00352 xmlNodePtr topnode;
00353 GSList *n;
00354 QofIdTypeConst path;
00355
00356 n = param_path;
00357 topnode = xmlNewNode (NULL, "qofquery:param-path");
00358 for ( ; n; n=n->next)
00359 {
00360 path = n->data;
00361 if (!path) continue;
00362 PUT_STR ("qofquery:param", path);
00363 }
00364 return topnode;
00365 }
00366
00367
00368
00369 static xmlNodePtr
00370 qof_query_one_term_to_xml (QofQueryTerm *qt)
00371 {
00372 xmlNodePtr node;
00373 xmlNodePtr term;
00374 xmlNodePtr topnode;
00375 gboolean invert;
00376 GSList *path;
00377 QofQueryPredData *pd;
00378
00379 invert = qof_query_term_is_inverted (qt);
00380 term = xmlNewNode (NULL, "qofquery:term");
00381 topnode = term;
00382 path = qof_query_term_get_param_path (qt);
00383 pd = qof_query_term_get_pred_data (qt);
00384 if (invert)
00385 {
00386
00387 topnode = xmlNewNode (NULL, "qofquery:invert");
00388 xmlAddChild (term, topnode);
00389 }
00390
00391 node = qof_query_param_path_to_xml (path);
00392 if (node) xmlAddChild (topnode, node);
00393
00394 node = qof_query_pred_data_to_xml (pd);
00395 if (node) xmlAddChild (topnode, node);
00396
00397 return term;
00398 }
00399
00400
00401
00402 static xmlNodePtr
00403 qof_query_and_terms_to_xml (GList *and_terms)
00404 {
00405 xmlNodePtr terms;
00406 GList *n;
00407 QofQueryTerm *qt;
00408 xmlNodePtr t;
00409
00410 terms = xmlNewNode (NULL, "qofquery:and-terms");
00411 n = and_terms;
00412 for ( ; n; n=n->next)
00413 {
00414 qt = n->data;
00415 if (!qt) continue;
00416
00417 t = qof_query_one_term_to_xml (n->data);
00418 if (t) xmlAddChild (terms, t);
00419 }
00420 return terms;
00421 }
00422
00423
00424
00425 static xmlNodePtr
00426 qof_query_terms_to_xml (QofQuery *q)
00427 {
00428 xmlNodePtr terms;
00429 GList *n;
00430 xmlNodePtr andt;
00431
00432 terms = NULL;
00433 n = qof_query_get_terms (q);
00434 if (!n) return NULL;
00435 terms = xmlNewNode (NULL, "qofquery:or-terms");
00436
00437 for ( ; n; n=n->next)
00438 {
00439 andt = qof_query_and_terms_to_xml (n->data);
00440 if (andt) xmlAddChild (terms, andt);
00441 }
00442 return terms;
00443 }
00444
00445
00446
00447 static xmlNodePtr
00448 qof_query_sorts_to_xml (QofQuery *q)
00449 {
00450 QofQuerySort *s[3];
00451 xmlNodePtr sortlist;
00452 GSList *plist;
00453 xmlNodePtr sort;
00454 xmlNodePtr topnode;
00455 gboolean increasing;
00456 gint opt;
00457 xmlNodePtr pl;
00458 int i;
00459
00460 qof_query_get_sorts (q, &s[0], &s[1], &s[2]);
00461
00462 if (NULL == s[0]) return NULL;
00463
00464 sortlist = xmlNewNode (NULL, "qofquery:sort-list");
00465 for (i=0; i<3; i++)
00466 {
00467 if (NULL == s[i]) continue;
00468
00469 plist = qof_query_sort_get_param_path (s[i]);
00470 if (!plist) continue;
00471
00472 sort = xmlNewNode (NULL, "qofquery:sort");
00473 xmlAddChild (sortlist, sort);
00474
00475 topnode = sort;
00476
00477 increasing = qof_query_sort_get_increasing (s[i]);
00478 PUT_STR ("qofquery:order", increasing ? "DESCENDING" : "ASCENDING");
00479
00480 opt = qof_query_sort_get_sort_options (s[i]);
00481 PUT_INT32 ("qofquery:options", opt);
00482
00483 pl = qof_query_param_path_to_xml (plist);
00484 if (pl) xmlAddChild (sort, pl);
00485 }
00486
00487 return sortlist;
00488 }
00489
00490
00491
00492 static void
00493 do_qof_query_to_xml (QofQuery *q, xmlNodePtr topnode)
00494 {
00495 QofIdType search_for;
00496 xmlNodePtr terms;
00497 xmlNodePtr sorts;
00498 gint max_results;
00499
00500 search_for = qof_query_get_search_for (q);
00501 PUT_STR ("qofquery:search-for", search_for);
00502
00503 terms = qof_query_terms_to_xml(q);
00504 if (terms) xmlAddChild (topnode, terms);
00505
00506 sorts = qof_query_sorts_to_xml (q);
00507 if (sorts) xmlAddChild (topnode, sorts);
00508
00509 max_results = qof_query_get_max_results (q);
00510 PUT_INT32 ("qofquery:max-results", max_results);
00511 }
00512
00513
00514
00515 xmlNodePtr
00516 qof_query_to_xml (QofQuery *q)
00517 {
00518 xmlNodePtr topnode;
00519 xmlNodePtr node;
00520 xmlNsPtr ns;
00521
00522 topnode = xmlNewNode(NULL, "qof:qofquery");
00523 xmlSetProp(topnode, "version", "1.0.1");
00524
00525
00526
00527
00528 do_qof_query_to_xml (q, topnode);
00529
00530 return topnode;
00531 }
00532
00533
00534
00535 #ifdef UNIT_TEST
00536
00537 #include <stdio.h>
00538 #include <qof/qofsql.h>
00539
00540 int main (int argc, char * argv[])
00541 {
00542 QofQuery *q;
00543 QofSqlQuery *sq;
00544 xmlDocPtr doc;
00545 xmlNodePtr topnode;
00546 xmlChar *xbuf;
00547 int bufsz;
00548 xmlOutputBufferPtr xbuf;
00549
00550 qof_query_init();
00551 qof_object_initialize ();
00552
00553 static QofParam params[] = {
00554 { "adate", QOF_TYPE_DATE, NULL, NULL},
00555 { "aint", QOF_TYPE_INT32, NULL, NULL},
00556 { "aint64", QOF_TYPE_INT64, NULL, NULL},
00557 { "astr", QOF_TYPE_STRING, NULL, NULL},
00558 { NULL },
00559 };
00560
00561 qof_class_register ("GncABC", NULL, params);
00562 sq = qof_sql_query_new();
00563
00564 qof_sql_query_parse (sq,
00565 "SELECT * from GncABC WHERE aint = 123 "
00566 "or not astr=\'asdf\' "
00567 "and aint64 = 9876123456789;");
00568
00569 q = qof_sql_query_get_query (sq);
00570
00571 qof_query_print (q);
00572
00573 doc = doc = xmlNewDoc("1.0");
00574 topnode = qof_query_to_xml (q);
00575 xmlDocSetRootElement(doc,topnode);
00576
00577 xmlDocDumpFormatMemory (doc, &xbuf, &bufsz, 1);
00578
00579 printf ("%s\n", xbuf);
00580 xmlFree (xbuf);
00581 xmlFreeDoc(doc);
00582
00583 #if 0
00584 printf ("duude\n");
00585
00586 xbuf = xmlOutputBufferCreateFile (stdout, NULL);
00587 printf ("duude\n");
00588
00589 xbuf = xmlOutputBufferCreateFd (1, NULL);
00590 printf ("duude\n");
00591 xmlNodeDumpOutput (xbuf, NULL, topnode, 99, 99, "iso-8859-1");
00592
00593 #endif
00594
00595 return 0;
00596 }
00597
00598 #endif
00599
00600