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