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,
00247 NEQ);
00248
00249 pdata_s = (query_string_t) pd;
00250 PUT_MATCH2 ("qofquery:string-match", pdata_s->options,
00251 STRING_MATCH, NORMAL, CASEINSENSITIVE);
00252 PUT_BOOL ("qofquery:is-regex", pdata_s->is_regex);
00253 PUT_STR ("qofquery:string", pdata_s->matchstring);
00254 return topnode;
00255 }
00256 if (!safe_strcmp (pd->type_name, QOF_TYPE_NUMERIC))
00257 {
00258 topnode = xmlNewNode (NULL, "qofquery:pred-numeric");
00259 PUT_HOW ("qofquery:compare", pd->how, LT, LTE, EQUAL, GT, GTE,
00260 NEQ);
00261
00262 pdata_n = (query_numeric_t) pd;
00263 PUT_MATCH3 ("qofquery:numeric-match", pdata_n->options,
00264 NUMERIC_MATCH, DEBIT, CREDIT, ANY);
00265
00266 PUT_NUMERIC ("qofquery:numeric", pdata_n->amount);
00267 return topnode;
00268 }
00269 if (!safe_strcmp (pd->type_name, QOF_TYPE_KVP))
00270 {
00271 topnode = xmlNewNode (NULL, "qofquery:pred-kvp");
00272 PUT_HOW ("qofquery:compare", pd->how, LT, LTE, EQUAL, GT, GTE,
00273 NEQ);
00274
00275 pdata_k = (query_kvp_t) pd;
00276 for (ns = pdata_k->path; ns; ns = ns->next)
00277 {
00278 PUT_STR ("qofquery:kvp-path", ns->data);
00279 }
00280 qof_kvp_value_to_xml (pdata_k->value, topnode);
00281 return topnode;
00282 }
00283 if (!safe_strcmp (pd->type_name, QOF_TYPE_DATE))
00284 {
00285 topnode = xmlNewNode (NULL, "qofquery:pred-date");
00286 PUT_HOW ("qofquery:compare", pd->how, LT, LTE, EQUAL, GT, GTE,
00287 NEQ);
00288
00289 pdata_d = (query_date_t) pd;
00290
00291 PUT_MATCH2 ("qofquery:date-match", pdata_d->options,
00292 DATE_MATCH, NORMAL, DAY);
00293
00294 PUT_DATE ("qofquery:date", pdata_d->date);
00295 return topnode;
00296 }
00297 if (!safe_strcmp (pd->type_name, QOF_TYPE_INT64))
00298 {
00299 topnode = xmlNewNode (NULL, "qofquery:pred-int64");
00300 PUT_HOW ("qofquery:compare", pd->how, LT, LTE, EQUAL, GT, GTE,
00301 NEQ);
00302
00303 pdata_i64 = (query_int64_t) pd;
00304 PUT_INT64 ("qofquery:int64", pdata_i64->val);
00305 return topnode;
00306 }
00307 if (!safe_strcmp (pd->type_name, QOF_TYPE_INT32))
00308 {
00309 topnode = xmlNewNode (NULL, "qofquery:pred-int32");
00310 PUT_HOW ("qofquery:compare", pd->how, LT, LTE, EQUAL, GT, GTE,
00311 NEQ);
00312
00313 pdata_i32 = (query_int32_t) pd;
00314
00315 PUT_INT32 ("qofquery:int32", pdata_i32->val);
00316 return topnode;
00317 }
00318 if (!safe_strcmp (pd->type_name, QOF_TYPE_DOUBLE))
00319 {
00320 topnode = xmlNewNode (NULL, "qofquery:pred-double");
00321 PUT_HOW ("qofquery:compare", pd->how, LT, LTE, EQUAL, GT, GTE,
00322 NEQ);
00323
00324 pdata_db = (query_double_t) pd;
00325
00326 PUT_DBL ("qofquery:double", pdata_db->val);
00327 return topnode;
00328 }
00329 if (!safe_strcmp (pd->type_name, QOF_TYPE_BOOLEAN))
00330 {
00331 topnode = xmlNewNode (NULL, "qofquery:pred-boolean");
00332 PUT_HOW ("qofquery:compare", pd->how, LT, LTE, EQUAL, GT, GTE,
00333 NEQ);
00334
00335 pdata_bool = (query_boolean_t) pd;
00336
00337 PUT_BOOL ("qofquery:boolean", pdata_bool->val);
00338 return topnode;
00339 }
00340 if (!safe_strcmp (pd->type_name, QOF_TYPE_CHAR))
00341 {
00342 topnode = xmlNewNode (NULL, "qofquery:pred-char");
00343
00344 pdata_c = (query_char_t) pd;
00345
00346 PUT_MATCH2 ("qofquery:char-match", pdata_c->options,
00347 CHAR_MATCH, ANY, NONE);
00348
00349 PUT_STR ("qofquery:char-list", pdata_c->char_list);
00350 return topnode;
00351 }
00352 return NULL;
00353 }
00354
00355
00356
00357 static xmlNodePtr
00358 qof_query_param_path_to_xml (GSList * param_path)
00359 {
00360 xmlNodePtr topnode;
00361 GSList *n;
00362 QofIdTypeConst path;
00363
00364 n = param_path;
00365 topnode = xmlNewNode (NULL, "qofquery:param-path");
00366 for (; n; n = n->next)
00367 {
00368 path = n->data;
00369 if (!path)
00370 continue;
00371 PUT_STR ("qofquery:param", path);
00372 }
00373 return topnode;
00374 }
00375
00376
00377
00378 static xmlNodePtr
00379 qof_query_one_term_to_xml (QofQueryTerm * qt)
00380 {
00381 xmlNodePtr node;
00382 xmlNodePtr term;
00383 xmlNodePtr topnode;
00384 gboolean invert;
00385 GSList *path;
00386 QofQueryPredData *pd;
00387
00388 invert = qof_query_term_is_inverted (qt);
00389 term = xmlNewNode (NULL, "qofquery:term");
00390 topnode = term;
00391 path = qof_query_term_get_param_path (qt);
00392 pd = qof_query_term_get_pred_data (qt);
00393 if (invert)
00394 {
00395
00396 topnode = xmlNewNode (NULL, "qofquery:invert");
00397 xmlAddChild (term, topnode);
00398 }
00399
00400 node = qof_query_param_path_to_xml (path);
00401 if (node)
00402 xmlAddChild (topnode, node);
00403
00404 node = qof_query_pred_data_to_xml (pd);
00405 if (node)
00406 xmlAddChild (topnode, node);
00407
00408 return term;
00409 }
00410
00411
00412
00413 static xmlNodePtr
00414 qof_query_and_terms_to_xml (GList * and_terms)
00415 {
00416 xmlNodePtr terms;
00417 GList *n;
00418 QofQueryTerm *qt;
00419 xmlNodePtr t;
00420
00421 terms = xmlNewNode (NULL, "qofquery:and-terms");
00422 n = and_terms;
00423 for (; n; n = n->next)
00424 {
00425 qt = n->data;
00426 if (!qt)
00427 continue;
00428
00429 t = qof_query_one_term_to_xml (n->data);
00430 if (t)
00431 xmlAddChild (terms, t);
00432 }
00433 return terms;
00434 }
00435
00436
00437
00438 static xmlNodePtr
00439 qof_query_terms_to_xml (QofQuery * q)
00440 {
00441 xmlNodePtr terms;
00442 GList *n;
00443 xmlNodePtr andt;
00444
00445 terms = NULL;
00446 n = qof_query_get_terms (q);
00447 if (!n)
00448 return NULL;
00449 terms = xmlNewNode (NULL, "qofquery:or-terms");
00450
00451 for (; n; n = n->next)
00452 {
00453 andt = qof_query_and_terms_to_xml (n->data);
00454 if (andt)
00455 xmlAddChild (terms, andt);
00456 }
00457 return terms;
00458 }
00459
00460
00461
00462 static xmlNodePtr
00463 qof_query_sorts_to_xml (QofQuery * q)
00464 {
00465 QofQuerySort *s[3];
00466 xmlNodePtr sortlist;
00467 GSList *plist;
00468 xmlNodePtr sort;
00469 xmlNodePtr topnode;
00470 gboolean increasing;
00471 gint opt;
00472 xmlNodePtr pl;
00473 int i;
00474
00475 qof_query_get_sorts (q, &s[0], &s[1], &s[2]);
00476
00477 if (NULL == s[0])
00478 return NULL;
00479
00480 sortlist = xmlNewNode (NULL, "qofquery:sort-list");
00481 for (i = 0; i < 3; i++)
00482 {
00483 if (NULL == s[i])
00484 continue;
00485
00486 plist = qof_query_sort_get_param_path (s[i]);
00487 if (!plist)
00488 continue;
00489
00490 sort = xmlNewNode (NULL, "qofquery:sort");
00491 xmlAddChild (sortlist, sort);
00492
00493 topnode = sort;
00494
00495 increasing = qof_query_sort_get_increasing (s[i]);
00496 PUT_STR ("qofquery:order",
00497 increasing ? "DESCENDING" : "ASCENDING");
00498
00499 opt = qof_query_sort_get_sort_options (s[i]);
00500 PUT_INT32 ("qofquery:options", opt);
00501
00502 pl = qof_query_param_path_to_xml (plist);
00503 if (pl)
00504 xmlAddChild (sort, pl);
00505 }
00506
00507 return sortlist;
00508 }
00509
00510
00511
00512 static void
00513 do_qof_query_to_xml (QofQuery * q, xmlNodePtr topnode)
00514 {
00515 QofIdType search_for;
00516 xmlNodePtr terms;
00517 xmlNodePtr sorts;
00518 gint max_results;
00519
00520 search_for = qof_query_get_search_for (q);
00521 PUT_STR ("qofquery:search-for", search_for);
00522
00523 terms = qof_query_terms_to_xml (q);
00524 if (terms)
00525 xmlAddChild (topnode, terms);
00526
00527 sorts = qof_query_sorts_to_xml (q);
00528 if (sorts)
00529 xmlAddChild (topnode, sorts);
00530
00531 max_results = qof_query_get_max_results (q);
00532 PUT_INT32 ("qofquery:max-results", max_results);
00533 }
00534
00535
00536
00537 xmlNodePtr
00538 qof_query_to_xml (QofQuery * q)
00539 {
00540 xmlNodePtr topnode;
00541 xmlNodePtr node;
00542 xmlNsPtr ns;
00543
00544 topnode = xmlNewNode (NULL, "qof:qofquery");
00545 xmlSetProp (topnode, "version", "1.0.1");
00546
00547
00548
00549
00550 do_qof_query_to_xml (q, topnode);
00551
00552 return topnode;
00553 }
00554
00555
00556
00557 #ifdef UNIT_TEST
00558
00559 #include <stdio.h>
00560 #include <qof/qofsql.h>
00561
00562 int
00563 main (int argc, char *argv[])
00564 {
00565 QofQuery *q;
00566 QofSqlQuery *sq;
00567 xmlDocPtr doc;
00568 xmlNodePtr topnode;
00569 xmlChar *xbuf;
00570 int bufsz;
00571 xmlOutputBufferPtr xbuf;
00572
00573 qof_query_init ();
00574 qof_object_initialize ();
00575
00576 static QofParam params[] = {
00577 {"adate", QOF_TYPE_DATE, NULL, NULL},
00578 {"aint", QOF_TYPE_INT32, NULL, NULL},
00579 {"aint64", QOF_TYPE_INT64, NULL, NULL},
00580 {"astr", QOF_TYPE_STRING, NULL, NULL},
00581 {NULL},
00582 };
00583
00584 qof_class_register ("GncABC", NULL, params);
00585 sq = qof_sql_query_new ();
00586
00587 qof_sql_query_parse (sq,
00588 "SELECT * from GncABC WHERE aint = 123 "
00589 "or not astr=\'asdf\' " "and aint64 = 9876123456789;");
00590
00591 q = qof_sql_query_get_query (sq);
00592
00593 qof_query_print (q);
00594
00595 doc = doc = xmlNewDoc ("1.0");
00596 topnode = qof_query_to_xml (q);
00597 xmlDocSetRootElement (doc, topnode);
00598
00599 xmlDocDumpFormatMemory (doc, &xbuf, &bufsz, 1);
00600
00601 printf ("%s\n", xbuf);
00602 xmlFree (xbuf);
00603 xmlFreeDoc (doc);
00604
00605 #if 0
00606 printf ("duude\n");
00607
00608 xbuf = xmlOutputBufferCreateFile (stdout, NULL);
00609 printf ("duude\n");
00610
00611 xbuf = xmlOutputBufferCreateFd (1, NULL);
00612 printf ("duude\n");
00613 xmlNodeDumpOutput (xbuf, NULL, topnode, 99, 99, "iso-8859-1");
00614
00615 #endif
00616
00617 return 0;
00618 }
00619
00620 #endif
00621
00622