00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00029 #include "config.h"
00030
00031 #include <stdlib.h>
00032 #include <errno.h>
00033 #include "glib.h"
00034 #ifdef HAVE_GDA
00035 #include <sql/sql_parser.h>
00036 #else
00037 #include "sql_parser.h"
00038 #endif
00039 #include <time.h>
00040
00041 #include "qof.h"
00042
00043 static QofLogModule log_module = QOF_MOD_QUERY;
00044
00045
00046
00047 struct _QofSqlQuery
00048 {
00049 sql_statement *parse_result;
00050 QofQuery *qof_query;
00051 QofBook *book;
00052 char * single_global_tablename;
00053 KvpFrame *kvp_join;
00054 GList *param_list;
00055 QofInstance *inserted_entity;
00056 };
00057
00058
00059
00060 QofSqlQuery *
00061 qof_sql_query_new(void)
00062 {
00063 QofSqlQuery * sqn = (QofSqlQuery *) g_new0 (QofSqlQuery, 1);
00064
00065 sqn->qof_query = NULL;
00066 sqn->parse_result = NULL;
00067 sqn->book = NULL;
00068 sqn->single_global_tablename = NULL;
00069 sqn->kvp_join = NULL;
00070
00071 return sqn;
00072 }
00073
00074
00075
00076 void
00077 qof_sql_query_destroy (QofSqlQuery *q)
00078 {
00079 if (!q) return;
00080 qof_query_destroy (q->qof_query);
00081 sql_destroy (q->parse_result);
00082 g_free (q);
00083 }
00084
00085
00086
00087 QofQuery *
00088 qof_sql_query_get_query (QofSqlQuery *q)
00089 {
00090 if (!q) return NULL;
00091 return q->qof_query;
00092 }
00093
00094
00095
00096 void
00097 qof_sql_query_set_book (QofSqlQuery *q, QofBook *book)
00098 {
00099 if (!q) return;
00100 q->book = book;
00101 }
00102
00103
00104
00105 void
00106 qof_sql_query_set_kvp (QofSqlQuery *q, KvpFrame *kvp)
00107 {
00108 if (!q) return;
00109 q->kvp_join = kvp;
00110 }
00111
00112
00113
00114 static inline void
00115 get_table_and_param (char * str, char **tab, char **param)
00116 {
00117 char * end = strchr (str, '.');
00118 if (!end)
00119 {
00120 *tab = 0;
00121 *param = str;
00122 return;
00123 }
00124 *end = 0;
00125 *tab = str;
00126 *param = end + 1;
00127 }
00128
00129 static inline char *
00130 dequote_string (char *str)
00131 {
00132 size_t len;
00133
00134 if (('\'' == str[0]) ||
00135 ('\"' == str[0]))
00136 {
00137 str ++;
00138 len = strlen(str);
00139 str[len-1] = 0;
00140 }
00141 return str;
00142 }
00143
00144 static QofQuery *
00145 handle_single_condition (QofSqlQuery *query, sql_condition * cond)
00146 {
00147 char tmpbuff[128];
00148 GSList *param_list;
00149 GList *guid_list;
00150 QofQueryPredData *pred_data;
00151 sql_field_item *sparam, *svalue;
00152 char * qparam_name, *qvalue_name, *table_name, *param_name;
00153 char *sep, *path, *str, *p;
00154 QofQuery *qq;
00155 KvpValue *kv, *kval;
00156 KvpValueType kvt;
00157 QofQueryCompare qop;
00158 time_t exact;
00159 int rc, len;
00160 Timespec ts;
00161 QofType param_type;
00162 QofGuidMatch gm;
00163
00164 pred_data = NULL;
00165 if (NULL == cond)
00166 {
00167 PWARN("missing condition");
00168 return NULL;
00169 }
00170
00171
00172
00173 if (NULL == cond->d.pair.left)
00174 {
00175 PWARN("missing left parameter");
00176 return NULL;
00177 }
00178 sparam = cond->d.pair.left->item;
00179 if (SQL_name != sparam->type)
00180 {
00181 PWARN("we support only parameter names at this time (parsed %d)",
00182 sparam->type);
00183 return NULL;
00184 }
00185 qparam_name = sparam->d.name->data;
00186 if (NULL == qparam_name)
00187 {
00188 PWARN ("missing parameter name");
00189 return NULL;
00190 }
00191
00192
00193
00194
00195 if (NULL == cond->d.pair.right)
00196 {
00197 PWARN ("missing right parameter");
00198 return NULL;
00199 }
00200 svalue = cond->d.pair.right->item;
00201 if (SQL_name != svalue->type)
00202 {
00203 PWARN("we support only simple values (parsed as %d)", svalue->type);
00204 return NULL;
00205 }
00206 qvalue_name = svalue->d.name->data;
00207 if (NULL == qvalue_name)
00208 {
00209 PWARN("missing value");
00210 return NULL;
00211 }
00212 qvalue_name = dequote_string (qvalue_name);
00213 qvalue_name = (char *) qof_util_whitespace_filter (qvalue_name);
00214
00215
00216
00217 if (0 == g_ascii_strncasecmp (qvalue_name, "kvp://", 6))
00218 {
00219 if (NULL == query->kvp_join)
00220 {
00221 PWARN ("missing kvp frame");
00222 return NULL;
00223 }
00224 kv = kvp_frame_get_value (query->kvp_join, qvalue_name + 5);
00225
00226
00227 if (!kv) return NULL;
00228 kvt = kvp_value_get_type (kv);
00229
00230 tmpbuff[0] = 0x0;
00231 qvalue_name = tmpbuff;
00232 switch (kvt)
00233 {
00234 case KVP_TYPE_GINT64:
00235 {
00236 gint64 ival = kvp_value_get_gint64(kv);
00237 sprintf (tmpbuff, "%" G_GINT64_FORMAT "\n", ival);
00238 break;
00239 }
00240 case KVP_TYPE_DOUBLE:
00241 {
00242 double ival = kvp_value_get_double(kv);
00243 sprintf (tmpbuff, "%26.18g\n", ival);
00244 break;
00245 }
00246 case KVP_TYPE_STRING:
00247
00248
00249 qvalue_name = kvp_value_get_string (kv);
00250 if (!qvalue_name) return NULL;
00251 break;
00252 case KVP_TYPE_GUID:
00253 case KVP_TYPE_TIMESPEC:
00254 case KVP_TYPE_BINARY:
00255 case KVP_TYPE_GLIST:
00256 case KVP_TYPE_NUMERIC:
00257 case KVP_TYPE_FRAME:
00258 PWARN ("unhandled kvp type=%d", kvt);
00259 return NULL;
00260 }
00261 }
00262
00263
00264
00265 param_list = qof_query_build_param_list (qparam_name, NULL);
00266
00267
00268 switch (cond->op)
00269 {
00270 case SQL_eq:
00271 qop = QOF_COMPARE_EQUAL;
00272 break;
00273 case SQL_gt:
00274 qop = QOF_COMPARE_GT;
00275 break;
00276 case SQL_lt:
00277 qop = QOF_COMPARE_LT;
00278 break;
00279 case SQL_geq:
00280 qop = QOF_COMPARE_GTE;
00281 break;
00282 case SQL_leq:
00283 qop = QOF_COMPARE_LTE;
00284 break;
00285 case SQL_diff:
00286 qop = QOF_COMPARE_NEQ;
00287 break;
00288 default:
00289
00290
00291 PWARN ("Unsupported compare op (parsed as %u)", cond->op);
00292 return NULL;
00293 }
00294
00295
00296
00297
00298 get_table_and_param (qparam_name, &table_name, ¶m_name);
00299 if (NULL == table_name)
00300 {
00301 table_name = query->single_global_tablename;
00302 }
00303 if (NULL == table_name)
00304 {
00305 PWARN ("Need to specify an object class to query");
00306 return NULL;
00307 }
00308
00309 if (FALSE == qof_class_is_registered (table_name))
00310 {
00311 PWARN ("The query object \'%s\' is not known", table_name);
00312 return NULL;
00313 }
00314
00315 param_type = qof_class_get_parameter_type (table_name, param_name);
00316 if (!param_type)
00317 {
00318 PWARN ("The parameter \'%s\' on object \'%s\' is not known",
00319 param_name, table_name);
00320 return NULL;
00321 }
00322
00323 if (!strcmp (param_type, QOF_TYPE_STRING))
00324 {
00325 pred_data =
00326 qof_query_string_predicate (qop,
00327 qvalue_name,
00328 QOF_STRING_MATCH_CASEINSENSITIVE,
00329 FALSE);
00330 }
00331 else if (!strcmp (param_type, QOF_TYPE_CHAR))
00332 {
00333 QofCharMatch cm = QOF_CHAR_MATCH_ANY;
00334 if (QOF_COMPARE_NEQ == qop) cm = QOF_CHAR_MATCH_NONE;
00335 pred_data = qof_query_char_predicate (cm, qvalue_name);
00336 }
00337 else if (!strcmp (param_type, QOF_TYPE_INT32))
00338 {
00339 gint32 ival = atoi (qvalue_name);
00340 pred_data = qof_query_int32_predicate (qop, ival);
00341 }
00342 else if (!strcmp (param_type, QOF_TYPE_INT64))
00343 {
00344 gint64 ival = atoll (qvalue_name);
00345 pred_data = qof_query_int64_predicate (qop, ival);
00346 }
00347 else if (!strcmp (param_type, QOF_TYPE_DOUBLE))
00348 {
00349 double ival = atof (qvalue_name);
00350 pred_data = qof_query_double_predicate (qop, ival);
00351 }
00352 else if (!strcmp (param_type, QOF_TYPE_BOOLEAN))
00353 {
00354 gboolean ival = qof_util_bool_to_int (qvalue_name);
00355 pred_data = qof_query_boolean_predicate (qop, ival);
00356 }
00357 else if (!strcmp (param_type, QOF_TYPE_DATE))
00358 {
00359
00360 qof_date_format_set(QOF_DATE_FORMAT_UTC);
00361 rc = 0;
00362 if (FALSE == qof_scan_date_secs (qvalue_name, &exact))
00363 {
00364 char *tail;
00365 exact = strtoll(qvalue_name, &tail, 0);
00366
00367
00368 }
00369 ts.tv_sec = exact;
00370 ts.tv_nsec = 0;
00371 pred_data = qof_query_date_predicate (qop, QOF_DATE_MATCH_NORMAL, ts);
00372 }
00373 else if (!strcmp (param_type, QOF_TYPE_NUMERIC))
00374 {
00375 gnc_numeric ival;
00376 string_to_gnc_numeric (qvalue_name, &ival);
00377 pred_data = qof_query_numeric_predicate (qop, QOF_NUMERIC_MATCH_ANY, ival);
00378 }
00379 else if (!strcmp (param_type, QOF_TYPE_DEBCRED))
00380 {
00381
00382 gnc_numeric ival;
00383 string_to_gnc_numeric (qvalue_name, &ival);
00384 pred_data = qof_query_numeric_predicate (qop, QOF_NUMERIC_MATCH_ANY, ival);
00385 }
00386 else if (!strcmp (param_type, QOF_TYPE_GUID))
00387 {
00388 GncGUID guid;
00389 gboolean rc = string_to_guid (qvalue_name, &guid);
00390 if (0 == rc)
00391 {
00392 PWARN ("unable to parse guid: %s", qvalue_name);
00393 return NULL;
00394 }
00395
00396
00397
00398
00399 gm = QOF_GUID_MATCH_ANY;
00400 if (QOF_COMPARE_NEQ == qop) gm = QOF_GUID_MATCH_NONE;
00401 guid_list = g_list_append (NULL, &guid);
00402 pred_data = qof_query_guid_predicate (gm, guid_list);
00403
00404 g_list_free (guid_list);
00405 }
00406 else if (!strcmp (param_type, QOF_TYPE_KVP))
00407 {
00408
00409
00410
00411 sep = strchr (qvalue_name, ':');
00412 if (!sep) return NULL;
00413 *sep = 0;
00414 path = qvalue_name;
00415 str = sep + 1;
00416
00417
00418
00419
00420
00421
00422
00423 kval = NULL;
00424 len = strlen (str);
00425 if ((32 == len) && (32 == strspn (str, "0123456789abcdef")))
00426 {
00427 GncGUID guid;
00428 string_to_guid (str, &guid);
00429 kval = kvp_value_new_guid (&guid);
00430 }
00431 else if (len == strspn (str, "0123456789"))
00432 {
00433 kval = kvp_value_new_gint64 (atoll(str));
00434 }
00435 else if ((p = strchr (str, '.')) &&
00436 ((len - 1) == (strspn (str, "0123456789") +
00437 strspn (p + 1, "0123456789"))))
00438 {
00439 kval = kvp_value_new_double (atof(str));
00440 }
00441
00442 else if ((p = strchr (str, '/')) &&
00443 ((len - 1) == (strspn (str, "0123456789") +
00444 strspn (p + 1, "0123456789"))))
00445 {
00446 gnc_numeric num;
00447 string_to_gnc_numeric (str, &num);
00448 kval = kvp_value_new_gnc_numeric (num);
00449 }
00450 else if ((p = strchr (str, '-')) &&
00451 (p = strchr (p + 1, '-')) &&
00452 (p = strchr (p + 1, ' ')) &&
00453 (p = strchr (p + 1, ':')) &&
00454 (p = strchr (p + 1, ':')))
00455 {
00456 kval = kvp_value_new_timespec (gnc_iso8601_to_timespec_gmt(str));
00457 }
00458
00459
00460 if (NULL == kval)
00461 {
00462 kval = kvp_value_new_string (str);
00463 }
00464 pred_data = qof_query_kvp_predicate_path (qop, path, kval);
00465 }
00466 else
00467 {
00468 PWARN ("The predicate type \"%s\" is unsupported for now", param_type);
00469 return NULL;
00470 }
00471
00472 qq = qof_query_create();
00473 qof_query_add_term (qq, param_list, pred_data, QOF_QUERY_FIRST_TERM);
00474 return qq;
00475 }
00476
00477
00478
00479 static QofQuery *
00480 handle_where (QofSqlQuery *query, sql_where *swear)
00481 {
00482 QofQueryOp qop;
00483 QofQuery * qq;
00484
00485 switch (swear->type)
00486 {
00487 case SQL_pair:
00488 {
00489 QofQuery *qleft = handle_where (query, swear->d.pair.left);
00490 QofQuery *qright = handle_where (query, swear->d.pair.right);
00491 if (NULL == qleft) return qright;
00492 if (NULL == qright) return qleft;
00493 switch (swear->d.pair.op)
00494 {
00495 case SQL_and:
00496 qop = QOF_QUERY_AND;
00497 break;
00498 case SQL_or:
00499 qop = QOF_QUERY_OR;
00500 break;
00501
00502 default:
00503 qof_query_destroy (qleft);
00504 qof_query_destroy (qright);
00505 return NULL;
00506 }
00507 qq = qof_query_merge (qleft, qright, qop);
00508 qof_query_destroy (qleft);
00509 qof_query_destroy (qright);
00510 return qq;
00511 }
00512 case SQL_negated:
00513 {
00514 QofQuery *qq = handle_where (query, swear->d.negated);
00515 QofQuery *qneg = qof_query_invert (qq);
00516 qof_query_destroy (qq);
00517 return qneg;
00518 }
00519
00520 case SQL_single:
00521 {
00522 sql_condition * cond = swear->d.single;
00523 return handle_single_condition (query, cond);
00524 }
00525 }
00526 return NULL;
00527 }
00528
00529
00530
00531 static void
00532 handle_sort_order (QofSqlQuery *query, GList *sorder_list)
00533 {
00534 GSList *qsp[3];
00535 GList *n;
00536 gboolean direction[3];
00537 int i;
00538 sql_order_field *sorder;
00539 char * qparam_name;
00540
00541 if (!sorder_list) return;
00542
00543 for (i = 0; i < 3; i++)
00544 {
00545 qsp[i] = NULL;
00546 direction[i] = 0;
00547
00548 if (sorder_list)
00549 {
00550 sorder = sorder_list->data;
00551
00552
00553 if (SQL_asc == sorder->order_type) direction[i] = TRUE;
00554
00555
00556 qparam_name = NULL;
00557 n = sorder->name;
00558 if (n)
00559 {
00560 qparam_name = n->data;
00561 if (qparam_name)
00562 {
00563 qsp[i] = qof_query_build_param_list (qparam_name, NULL);
00564 }
00565 n = n->next;
00566 }
00567 else
00568 {
00569
00570 sorder_list = sorder_list->next;
00571 }
00572 }
00573 }
00574
00575 qof_query_set_sort_order (query->qof_query, qsp[0], qsp[1], qsp[2]);
00576 qof_query_set_sort_increasing (query->qof_query, direction[0],
00577 direction[1], direction[2]);
00578 }
00579
00580
00581
00582 static void
00583 qof_sql_insertCB(const QofParam *param, const gchar *insert_string, QofSqlQuery *query)
00584 {
00585 QofIdTypeConst type;
00586 sql_insert_statement *sis;
00587 gboolean registered_type;
00588 QofInstance *ent;
00589 struct tm query_time;
00590 time_t query_time_t;
00591
00592 gnc_numeric cm_numeric;
00593 double cm_double;
00594 gboolean cm_boolean;
00595 gint32 cm_i32;
00596 gint64 cm_i64;
00597 Timespec cm_date;
00598 char cm_char, *tail;
00599 GncGUID *cm_guid;
00600
00601
00602
00603 void (*string_setter) (QofInstance*, const char*);
00604 void (*date_setter) (QofInstance*, Timespec);
00605 void (*numeric_setter) (QofInstance*, gnc_numeric);
00606 void (*double_setter) (QofInstance*, double);
00607 void (*boolean_setter) (QofInstance*, gboolean);
00608 void (*i32_setter) (QofInstance*, gint32);
00609 void (*i64_setter) (QofInstance*, gint64);
00610 void (*char_setter) (QofInstance*, char);
00611
00612
00613 g_return_if_fail(param || insert_string || query);
00614 ent = query->inserted_entity;
00615 sis = query->parse_result->statement;
00616 type = g_strdup_printf("%s", sis->table->d.simple);
00617
00618 ENTER (" param=%s param_type=%s type=%s content=%s",
00619 param->param_name, param->param_type, type, insert_string);
00620 if (safe_strcmp(param->param_type, QOF_TYPE_STRING) == 0)
00621 {
00622 string_setter = (void(*)(QofInstance*, const char*))param->param_setfcn;
00623 if (string_setter != NULL)
00624 {
00625 string_setter(ent, insert_string);
00626 }
00627 registered_type = TRUE;
00628 }
00629 if (safe_strcmp(param->param_type, QOF_TYPE_DATE) == 0)
00630 {
00631 date_setter = (void(*)(QofInstance*, Timespec))param->param_setfcn;
00632 strptime(insert_string, QOF_UTC_DATE_FORMAT, &query_time);
00633 query_time_t = mktime(&query_time);
00634 timespecFromTime_t(&cm_date, query_time_t);
00635 if (date_setter != NULL)
00636 {
00637 date_setter(ent, cm_date);
00638 }
00639 }
00640 if ((safe_strcmp(param->param_type, QOF_TYPE_NUMERIC) == 0) ||
00641 (safe_strcmp(param->param_type, QOF_TYPE_DEBCRED) == 0))
00642 {
00643 numeric_setter = (void(*)(QofInstance*, gnc_numeric))param->param_setfcn;
00644 string_to_gnc_numeric(insert_string, &cm_numeric);
00645 if (numeric_setter != NULL)
00646 {
00647 numeric_setter(ent, cm_numeric);
00648 }
00649 }
00650 if (safe_strcmp(param->param_type, QOF_TYPE_GUID) == 0)
00651 {
00652 cm_guid = g_new(GncGUID, 1);
00653 if (TRUE != string_to_guid(insert_string, cm_guid))
00654 {
00655 LEAVE (" string to guid failed for %s", insert_string);
00656 return;
00657 }
00658 }
00659 if (safe_strcmp(param->param_type, QOF_TYPE_INT32) == 0)
00660 {
00661 errno = 0;
00662 cm_i32 = (gint32)strtol (insert_string, &tail, 0);
00663 if (errno == 0)
00664 {
00665 i32_setter = (void(*)(QofInstance*, gint32))param->param_setfcn;
00666 if (i32_setter != NULL)
00667 {
00668 i32_setter(ent, cm_i32);
00669 }
00670 }
00671 else
00672 {
00673 QofBackend *backend;
00674 QofBook *book;
00675
00676 book = qof_instance_get_book((QofInstance*)ent);
00677 backend = qof_book_get_backend(book);
00678 qof_backend_set_error(backend, ERR_QOF_OVERFLOW);
00679 }
00680 }
00681 if (safe_strcmp(param->param_type, QOF_TYPE_INT64) == 0)
00682 {
00683 errno = 0;
00684 cm_i64 = strtoll(insert_string, &tail, 0);
00685 if (errno == 0)
00686 {
00687 i64_setter = (void(*)(QofInstance*, gint64))param->param_setfcn;
00688 if (i64_setter != NULL)
00689 {
00690 i64_setter(ent, cm_i64);
00691 }
00692 }
00693 else
00694 {
00695 QofBackend *backend;
00696 QofBook *book;
00697
00698 book = qof_instance_get_book((QofInstance*)ent);
00699 backend = qof_book_get_backend(book);
00700 qof_backend_set_error(backend, ERR_QOF_OVERFLOW);
00701 }
00702 }
00703 if (safe_strcmp(param->param_type, QOF_TYPE_DOUBLE) == 0)
00704 {
00705 errno = 0;
00706 cm_double = strtod(insert_string, &tail);
00707 if (errno == 0)
00708 {
00709 double_setter = (void(*)(QofInstance*, double))param->param_setfcn;
00710 if (double_setter != NULL)
00711 {
00712 double_setter(ent, cm_double);
00713 }
00714 }
00715 }
00716 if (safe_strcmp(param->param_type, QOF_TYPE_BOOLEAN) == 0)
00717 {
00718 gint b;
00719 b = qof_util_bool_to_int(insert_string);
00720 if (b == 1)
00721 {
00722 cm_boolean = TRUE;
00723 }
00724 else
00725 {
00726 cm_boolean = FALSE;
00727 }
00728 boolean_setter = (void(*)(QofInstance*, gboolean))param->param_setfcn;
00729 if (boolean_setter != NULL)
00730 {
00731 boolean_setter(ent, cm_boolean);
00732 }
00733 }
00734 if (safe_strcmp(param->param_type, QOF_TYPE_KVP) == 0)
00735 {
00736
00737 }
00738 if (safe_strcmp(param->param_type, QOF_TYPE_CHAR) == 0)
00739 {
00740 cm_char = *insert_string;
00741 char_setter = (void(*)(QofInstance*, char))param->param_setfcn;
00742 if (char_setter != NULL)
00743 {
00744 char_setter(ent, cm_char);
00745 }
00746 }
00747 LEAVE (" ");
00748 }
00749
00750 static void
00751 qof_query_set_insert_table(QofSqlQuery *query)
00752 {
00753 sql_insert_statement *sis;
00754 sql_table *sis_t;
00755 sis = query->parse_result->statement;
00756 switch (sis->table->type)
00757 {
00758 case SQL_simple:
00759 {
00760 sis_t = sis->table;
00761 query->single_global_tablename = g_strdup_printf("%s", sis_t->d.simple);
00762 qof_query_search_for (query->qof_query, query->single_global_tablename);
00763 PINFO (" insert set to table: %s", sis_t->d.simple);
00764 break;
00765 }
00766 default:
00767 {
00768 PWARN ("SQL insert only handles simple statements");
00769 }
00770 }
00771 }
00772
00773 static QofInstance*
00774 qof_query_insert(QofSqlQuery *query)
00775 {
00776 GList *field_list, *value_list, *cur;
00777 const gchar *param_name;
00778 gchar *value;
00779 QofIdType type;
00780 const QofParam *param;
00781 QofInstance *inst;
00782 sql_insert_statement *sis;
00783 sql_field *field;
00784 sql_field_item *item;
00785
00786 ENTER (" ");
00787 query->param_list = NULL;
00788 type = NULL;
00789 param = NULL;
00790 value = NULL;
00791 field_list = NULL;
00792 value_list = NULL;
00793 param_name = NULL;
00794 sis = query->parse_result->statement;
00795 if (!sis->fields || !sis->values)
00796 {
00797 LEAVE (" NULL insert statement");
00798 return NULL;
00799 }
00800 type = g_strdup(query->single_global_tablename);
00801 inst = (QofInstance*)qof_object_new_instance(type, query->book);
00802 if (inst == NULL)
00803 {
00804 LEAVE (" unable to create instance of type %s", type);
00805 return NULL;
00806 }
00807 query->inserted_entity = inst;
00808 value_list = sis->values;
00809 for (field_list = sis->fields; field_list != NULL; field_list = field_list->next)
00810 {
00811 field = value_list->data;
00812 item = field->item;
00813 for (cur = item->d.name; cur != NULL; cur = cur->next)
00814 {
00815 value = g_strdup_printf("%s", dequote_string((char*)cur->data));
00816 }
00817 field = field_list->data;
00818 item = field->item;
00819 for (cur = item->d.name; cur != NULL; cur = cur->next)
00820 {
00821 param_name = g_strdup_printf("%s", (char*)cur->data);
00822 param = qof_class_get_parameter(type, param_name);
00823 }
00824 if (param && value)
00825 {
00826 qof_sql_insertCB(param, value, query);
00827 }
00828 value_list = g_list_next(value_list);
00829 }
00830 LEAVE (" ");
00831 return query->inserted_entity;
00832 }
00833
00834 static const char*
00835 sql_type_as_string(sql_statement_type type)
00836 {
00837 switch (type)
00838 {
00839 case SQL_select :
00840 {
00841 return "SELECT";
00842 }
00843 case SQL_insert :
00844 {
00845 return "INSERT";
00846 }
00847 case SQL_delete :
00848 {
00849 return "DELETE";
00850 }
00851 case SQL_update :
00852 {
00853 return "UPDATE";
00854 }
00855 default :
00856 {
00857 return "unknown";
00858 }
00859 }
00860 }
00861
00862 void
00863 qof_sql_query_parse (QofSqlQuery *query, const char *str)
00864 {
00865 GList *tables;
00866 char *buf;
00867 sql_select_statement *sss;
00868 sql_where *swear;
00869
00870 if (!query) return;
00871 ENTER (" ");
00872
00873 if (query->qof_query)
00874 {
00875 qof_query_destroy (query->qof_query);
00876 sql_destroy(query->parse_result);
00877 query->qof_query = NULL;
00878 }
00879
00880
00881 buf = g_strdup(str);
00882 query->parse_result = sql_parse (buf);
00883 g_free(buf);
00884
00885 if (!query->parse_result)
00886 {
00887 LEAVE ("parse error");
00888 return;
00889 }
00890
00891 if ((SQL_select != query->parse_result->type) && (SQL_insert != query->parse_result->type))
00892 {
00893 LEAVE ("currently, only SELECT or INSERT statements are supported, "
00894 "got type=%s", sql_type_as_string(query->parse_result->type));
00895 return;
00896 }
00897
00898
00899
00900
00901
00902
00903 tables = sql_statement_get_tables (query->parse_result);
00904 if (1 == g_list_length (tables))
00905 {
00906 query->single_global_tablename = tables->data;
00907 }
00908
00909 if (SQL_insert == query->parse_result->type)
00910 {
00911 query->qof_query = qof_query_create();
00912 qof_query_set_insert_table(query);
00913 LEAVE (" insert statement parsed OK");
00914 return;
00915 }
00916 sss = query->parse_result->statement;
00917 swear = sss->where;
00918 if (swear)
00919 {
00920
00921 query->qof_query = handle_where (query, swear);
00922 if (NULL == query->qof_query)
00923 {
00924 LEAVE (" no query found");
00925 return;
00926 }
00927 }
00928 else
00929 {
00930 query->qof_query = qof_query_create();
00931 }
00932
00933 handle_sort_order (query, sss->order);
00934
00935
00936
00937
00938
00939 qof_query_search_for (query->qof_query, query->single_global_tablename);
00940 LEAVE (" success");
00941 }
00942
00943
00944
00945 GList *
00946 qof_sql_query_run (QofSqlQuery *query, const char *str)
00947 {
00948 GList *results;
00949
00950 if (!query) return NULL;
00951
00952 qof_sql_query_parse (query, str);
00953 if (NULL == query->qof_query)
00954 {
00955 PINFO (" Null query");
00956 return NULL;
00957 }
00958
00959 qof_query_set_book (query->qof_query, query->book);
00960
00961 if (qof_should_log (log_module, QOF_LOG_DEBUG))
00962 {
00963 qof_query_print (query->qof_query);
00964 }
00965 if (SQL_insert == query->parse_result->type)
00966 {
00967 results = NULL;
00968 results = g_list_append(results, qof_query_insert(query));
00969 return results;
00970 }
00971
00972 results = qof_query_run (query->qof_query);
00973
00974 return results;
00975 }
00976
00977 GList *
00978 qof_sql_query_rerun (QofSqlQuery *query)
00979 {
00980 GList *results;
00981
00982 if (!query) return NULL;
00983
00984 if (NULL == query->qof_query) return NULL;
00985
00986 qof_query_set_book (query->qof_query, query->book);
00987
00988
00989 if (qof_should_log (log_module, QOF_LOG_DEBUG))
00990 {
00991 qof_query_print (query->qof_query);
00992 }
00993
00994 results = qof_query_run (query->qof_query);
00995
00996 return results;
00997 }
00998
00999