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