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