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