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 guint 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 QofNumeric ival;
00402 qof_numeric_from_string (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 QofNumeric ival;
00410 qof_numeric_from_string (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 QofNumeric num;
00477 qof_numeric_from_string (str, &num);
00478 kval = kvp_value_new_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 if (NULL == kval)
00497 {
00498 kval = kvp_value_new_string (str);
00499 }
00500 pred_data = qof_query_kvp_predicate_path (qop, path, kval);
00501 }
00502 else
00503 {
00504 PWARN ("The predicate type \"%s\" is unsupported for now",
00505 param_type);
00506 return NULL;
00507 }
00508
00509 qq = qof_query_create ();
00510 qof_query_add_term (qq, param_list, pred_data, QOF_QUERY_FIRST_TERM);
00511 return qq;
00512 }
00513
00514
00515
00516 static QofQuery *
00517 handle_where (QofSqlQuery * query, sql_where * swear)
00518 {
00519 QofQueryOp qop;
00520 QofQuery *qq;
00521
00522 switch (swear->type)
00523 {
00524 case SQL_pair:
00525 {
00526 QofQuery *qleft = handle_where (query, swear->d.pair.left);
00527 QofQuery *qright = handle_where (query, swear->d.pair.right);
00528 if (NULL == qleft)
00529 return qright;
00530 if (NULL == qright)
00531 return qleft;
00532 switch (swear->d.pair.op)
00533 {
00534 case SQL_and:
00535 qop = QOF_QUERY_AND;
00536 break;
00537 case SQL_or:
00538 qop = QOF_QUERY_OR;
00539 break;
00540
00541 default:
00542 qof_query_destroy (qleft);
00543 qof_query_destroy (qright);
00544 return NULL;
00545 }
00546 qq = qof_query_merge (qleft, qright, qop);
00547 qof_query_destroy (qleft);
00548 qof_query_destroy (qright);
00549 return qq;
00550 }
00551 case SQL_negated:
00552 {
00553 QofQuery *qq = handle_where (query, swear->d.negated);
00554 QofQuery *qneg = qof_query_invert (qq);
00555 qof_query_destroy (qq);
00556 return qneg;
00557 }
00558
00559 case SQL_single:
00560 {
00561 sql_condition *cond = swear->d.single;
00562 return handle_single_condition (query, cond);
00563 }
00564 }
00565 return NULL;
00566 }
00567
00568
00569
00570 static void
00571 handle_sort_order (QofSqlQuery * query, GList * sorder_list)
00572 {
00573 GSList *qsp[3];
00574 GList *n;
00575 gboolean direction[3];
00576 int i;
00577 sql_order_field *sorder;
00578 char *qparam_name;
00579
00580 if (!sorder_list)
00581 return;
00582
00583 for (i = 0; i < 3; i++)
00584 {
00585 qsp[i] = NULL;
00586 direction[i] = 0;
00587
00588 if (sorder_list)
00589 {
00590 sorder = sorder_list->data;
00591
00592
00593 if (SQL_asc == sorder->order_type)
00594 direction[i] = TRUE;
00595
00596
00597 qparam_name = NULL;
00598 n = sorder->name;
00599 if (n)
00600 {
00601 qparam_name = n->data;
00602 if (qparam_name)
00603 {
00604 qsp[i] =
00605 qof_query_build_param_list (qparam_name, NULL);
00606 }
00607 n = n->next;
00608 }
00609 else
00610 {
00611
00612 sorder_list = sorder_list->next;
00613 }
00614 }
00615 }
00616
00617 qof_query_set_sort_order (query->qof_query, qsp[0], qsp[1], qsp[2]);
00618 qof_query_set_sort_increasing (query->qof_query, direction[0],
00619 direction[1], direction[2]);
00620 }
00621
00622
00623
00624 static void
00625 qof_sql_insertCB (const QofParam * param, const gchar * insert_string,
00626 QofSqlQuery * query)
00627 {
00628 QofIdTypeConst type;
00629 sql_insert_statement *sis;
00630 gboolean registered_type;
00631 QofEntity *ent;
00632
00633 QofNumeric cm_numeric;
00634 gdouble cm_double;
00635 gboolean cm_boolean;
00636 gint32 cm_i32;
00637 gint64 cm_i64;
00638 gchar cm_char, *tail;
00639 GUID *cm_guid;
00640
00641
00642
00643 void (*string_setter) (QofEntity *, const gchar *);
00644 void (*time_setter) (QofEntity *, QofTime *);
00645 void (*numeric_setter) (QofEntity *, QofNumeric);
00646 void (*double_setter) (QofEntity *, gdouble);
00647 void (*boolean_setter) (QofEntity *, gboolean);
00648 void (*i32_setter) (QofEntity *, gint32);
00649 void (*i64_setter) (QofEntity *, gint64);
00650 void (*char_setter) (QofEntity *, gchar);
00651
00652
00653 g_return_if_fail (param || insert_string || query);
00654 ent = query->inserted_entity;
00655 sis = query->parse_result->statement;
00656 type = g_strdup_printf ("%s", sis->table->d.simple);
00657
00658 ENTER (" param=%s param_type=%s type=%s content=%s",
00659 param->param_name, param->param_type, type, insert_string);
00660 if (safe_strcmp (param->param_type, QOF_TYPE_STRING) == 0)
00661 {
00662 string_setter =
00663 (void (*)(QofEntity *, const char *)) param->param_setfcn;
00664 if (string_setter != NULL)
00665 {
00666 string_setter (ent, insert_string);
00667 }
00668 registered_type = TRUE;
00669 }
00670 if (safe_strcmp (param->param_type, QOF_TYPE_TIME) == 0)
00671 {
00672 QofDate *qd;
00673 QofTime *qt;
00674 time_setter =
00675 (void (*)(QofEntity *, QofTime *)) param->param_setfcn;
00676 qd = qof_date_parse (insert_string, QOF_DATE_FORMAT_UTC);
00677 qt = qof_date_to_qtime (qd);
00678 if((time_setter != NULL) && (qof_time_is_valid(qt)))
00679 {
00680 time_setter (ent, qt);
00681 }
00682 }
00683 #ifndef QOF_DISABLE_DEPRECATED
00684 if (safe_strcmp (param->param_type, QOF_TYPE_DATE) == 0)
00685 {
00686 void (*date_setter) (QofEntity *, Timespec);
00687 Timespec cm_date;
00688 struct tm query_time;
00689 time_t query_time_t;
00690
00691 date_setter =
00692 (void (*)(QofEntity *, Timespec)) 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)
00697 {
00698 date_setter (ent, cm_date);
00699 }
00700 }
00701 #endif
00702 if ((safe_strcmp (param->param_type, QOF_TYPE_NUMERIC) == 0) ||
00703 (safe_strcmp (param->param_type, QOF_TYPE_DEBCRED) == 0))
00704 {
00705 numeric_setter =
00706 (void (*)(QofEntity *, QofNumeric)) param->param_setfcn;
00707 qof_numeric_from_string (insert_string, &cm_numeric);
00708 if (numeric_setter != NULL)
00709 {
00710 numeric_setter (ent, cm_numeric);
00711 }
00712 }
00713 if (safe_strcmp (param->param_type, QOF_TYPE_GUID) == 0)
00714 {
00715 cm_guid = g_new (GUID, 1);
00716 if (TRUE != string_to_guid (insert_string, cm_guid))
00717 {
00718 LEAVE (" string to guid failed for %s", insert_string);
00719 return;
00720 }
00721
00722
00723
00724
00725
00726
00727
00728
00729
00730
00731
00732 }
00733 if (safe_strcmp (param->param_type, QOF_TYPE_INT32) == 0)
00734 {
00735 errno = 0;
00736 cm_i32 = (gint32) strtol (insert_string, &tail, 0);
00737 if (errno == 0)
00738 {
00739 i32_setter =
00740 (void (*)(QofEntity *, gint32)) param->param_setfcn;
00741 if (i32_setter != NULL)
00742 {
00743 i32_setter (ent, cm_i32);
00744 }
00745 }
00746 else
00747 {
00748 QofBackend *backend;
00749 QofBook *book;
00750
00751 book = qof_instance_get_book ((QofInstance *) ent);
00752 backend = qof_book_get_backend (book);
00753 qof_backend_set_error (backend, ERR_QSF_OVERFLOW);
00754 }
00755 }
00756 if (safe_strcmp (param->param_type, QOF_TYPE_INT64) == 0)
00757 {
00758 errno = 0;
00759 cm_i64 = strtoll (insert_string, &tail, 0);
00760 if (errno == 0)
00761 {
00762 i64_setter =
00763 (void (*)(QofEntity *, gint64)) param->param_setfcn;
00764 if (i64_setter != NULL)
00765 {
00766 i64_setter (ent, cm_i64);
00767 }
00768 }
00769 else
00770 {
00771 QofBackend *backend;
00772 QofBook *book;
00773
00774 book = qof_instance_get_book ((QofInstance *) ent);
00775 backend = qof_book_get_backend (book);
00776 qof_backend_set_error (backend, ERR_QSF_OVERFLOW);
00777 }
00778 }
00779 if (safe_strcmp (param->param_type, QOF_TYPE_DOUBLE) == 0)
00780 {
00781 errno = 0;
00782 cm_double = strtod (insert_string, &tail);
00783 if (errno == 0)
00784 {
00785 double_setter =
00786 (void (*)(QofEntity *, double)) param->param_setfcn;
00787 if (double_setter != NULL)
00788 {
00789 double_setter (ent, cm_double);
00790 }
00791 }
00792 }
00793 if (safe_strcmp (param->param_type, QOF_TYPE_BOOLEAN) == 0)
00794 {
00795 gint b;
00796 b = qof_util_bool_to_int (insert_string);
00797 if (b == 1)
00798 {
00799 cm_boolean = TRUE;
00800 }
00801 else
00802 {
00803 cm_boolean = FALSE;
00804 }
00805 boolean_setter =
00806 (void (*)(QofEntity *, gboolean)) param->param_setfcn;
00807 if (boolean_setter != NULL)
00808 {
00809 boolean_setter (ent, cm_boolean);
00810 }
00811 }
00812 if (safe_strcmp (param->param_type, QOF_TYPE_KVP) == 0)
00813 {
00814
00815 }
00816 if (safe_strcmp (param->param_type, QOF_TYPE_CHAR) == 0)
00817 {
00818 cm_char = *insert_string;
00819 char_setter = (void (*)(QofEntity *, char)) param->param_setfcn;
00820 if (char_setter != NULL)
00821 {
00822 char_setter (ent, cm_char);
00823 }
00824 }
00825 LEAVE (" ");
00826 }
00827
00828 static void
00829 qof_query_set_insert_table (QofSqlQuery * query)
00830 {
00831 sql_insert_statement *sis;
00832 sql_table *sis_t;
00833 sis = query->parse_result->statement;
00834 switch (sis->table->type)
00835 {
00836 case SQL_simple:
00837 {
00838 sis_t = sis->table;
00839 query->single_global_tablename =
00840 g_strdup_printf ("%s", sis_t->d.simple);
00841 qof_query_search_for (query->qof_query,
00842 query->single_global_tablename);
00843 PINFO (" insert set to table: %s", sis_t->d.simple);
00844 break;
00845 }
00846 default:
00847 {
00848 PWARN ("SQL insert only handles simple statements");
00849 }
00850 }
00851 }
00852
00853 static QofEntity *
00854 qof_query_insert (QofSqlQuery * query)
00855 {
00856 GList *field_list, *value_list, *cur;
00857 const gchar *param_name;
00858 gchar *value;
00859 QofIdType type;
00860 const QofParam *param;
00861 QofInstance *inst;
00862 sql_insert_statement *sis;
00863 sql_field *field;
00864 sql_field_item *item;
00865
00866 ENTER (" ");
00867 query->param_list = NULL;
00868 type = NULL;
00869 param = NULL;
00870 value = NULL;
00871 field_list = NULL;
00872 value_list = NULL;
00873 param_name = NULL;
00874 sis = query->parse_result->statement;
00875 if (!sis->fields || !sis->values)
00876 {
00877 LEAVE (" NULL insert statement");
00878 return NULL;
00879 }
00880 type = g_strdup (query->single_global_tablename);
00881 inst = (QofInstance *) qof_object_new_instance (type, query->book);
00882 if (inst == NULL)
00883 {
00884 LEAVE (" unable to create instance of type %s", type);
00885 return NULL;
00886 }
00887 query->inserted_entity = &inst->entity;
00888 value_list = sis->values;
00889 for (field_list = sis->fields; field_list != NULL;
00890 field_list = field_list->next)
00891 {
00892 field = value_list->data;
00893 item = field->item;
00894 for (cur = item->d.name; cur != NULL; cur = cur->next)
00895 {
00896 value =
00897 g_strdup_printf ("%s",
00898 dequote_string ((char *) cur->data));
00899 }
00900 field = field_list->data;
00901 item = field->item;
00902 for (cur = item->d.name; cur != NULL; cur = cur->next)
00903 {
00904 param_name = g_strdup_printf ("%s", (char *) cur->data);
00905 param = qof_class_get_parameter (type, param_name);
00906 }
00907 if (param && value)
00908 {
00909 qof_sql_insertCB (param, value, query);
00910 }
00911 value_list = g_list_next (value_list);
00912 }
00913 LEAVE (" ");
00914 return query->inserted_entity;
00915 }
00916
00917 static const char *
00918 sql_type_as_string (sql_statement_type type)
00919 {
00920 switch (type)
00921 {
00922 case SQL_select:
00923 {
00924 return "SELECT";
00925 }
00926 case SQL_insert:
00927 {
00928 return "INSERT";
00929 }
00930 case SQL_delete:
00931 {
00932 return "DELETE";
00933 }
00934 case SQL_update:
00935 {
00936 return "UPDATE";
00937 }
00938 default:
00939 {
00940 return "unknown";
00941 }
00942 }
00943 }
00944
00945 void
00946 qof_sql_query_parse (QofSqlQuery * query, const char *str)
00947 {
00948 GList *tables;
00949 char *buf;
00950 sql_select_statement *sss;
00951 sql_where *swear;
00952
00953 if (!query)
00954 return;
00955 ENTER (" ");
00956
00957 if (query->qof_query)
00958 {
00959 qof_query_destroy (query->qof_query);
00960 sql_destroy (query->parse_result);
00961 query->qof_query = NULL;
00962 }
00963
00964
00965 buf = g_strdup (str);
00966 query->parse_result = sql_parse (buf);
00967 g_free (buf);
00968
00969 if (!query->parse_result)
00970 {
00971 LEAVE ("parse error");
00972 return;
00973 }
00974
00975 if ((SQL_select != query->parse_result->type)
00976 && (SQL_insert != query->parse_result->type))
00977 {
00978 LEAVE
00979 ("currently, only SELECT or INSERT statements are supported, "
00980 "got type=%s", sql_type_as_string (query->parse_result->type));
00981 return;
00982 }
00983
00984
00985
00986
00987
00988
00989 tables = sql_statement_get_tables (query->parse_result);
00990 if (1 == g_list_length (tables))
00991 {
00992 query->single_global_tablename = tables->data;
00993 }
00994
00995 if (SQL_insert == query->parse_result->type)
00996 {
00997 query->qof_query = qof_query_create ();
00998 qof_query_set_insert_table (query);
00999 LEAVE (" insert statement parsed OK");
01000 return;
01001 }
01002 sss = query->parse_result->statement;
01003 swear = sss->where;
01004 if (swear)
01005 {
01006
01007 query->qof_query = handle_where (query, swear);
01008 if (NULL == query->qof_query)
01009 {
01010 LEAVE (" no query found");
01011 return;
01012 }
01013 }
01014 else
01015 {
01016 query->qof_query = qof_query_create ();
01017 }
01018
01019 handle_sort_order (query, sss->order);
01020
01021
01022
01023
01024
01025 qof_query_search_for (query->qof_query,
01026 query->single_global_tablename);
01027 LEAVE (" success");
01028 }
01029
01030
01031
01032 GList *
01033 qof_sql_query_run (QofSqlQuery * query, const char *str)
01034 {
01035 GList *results;
01036
01037 if (!query)
01038 return NULL;
01039
01040 qof_sql_query_parse (query, str);
01041 if (NULL == query->qof_query)
01042 {
01043 PINFO (" Null query");
01044 return NULL;
01045 }
01046
01047 qof_query_set_book (query->qof_query, query->book);
01048
01049 if (qof_log_check (log_module, QOF_LOG_DETAIL))
01050 {
01051 qof_query_print (query->qof_query);
01052 }
01053 if (SQL_insert == query->parse_result->type)
01054 {
01055 results = NULL;
01056 results = g_list_append (results, qof_query_insert (query));
01057 return results;
01058 }
01059
01060 results = qof_query_run (query->qof_query);
01061
01062 return results;
01063 }
01064
01065 GList *
01066 qof_sql_query_rerun (QofSqlQuery * query)
01067 {
01068 GList *results;
01069
01070 if (!query)
01071 return NULL;
01072
01073 if (NULL == query->qof_query)
01074 return NULL;
01075
01076 qof_query_set_book (query->qof_query, query->book);
01077
01078
01079 if (qof_log_check (log_module, QOF_LOG_DETAIL))
01080 {
01081 qof_query_print (query->qof_query);
01082 }
01083
01084 results = qof_query_run (query->qof_query);
01085
01086 return results;
01087 }
01088
01089