36 #include <libsql/sql_parser.h>
38 #include "sql_parser.h"
42 #include "qofquery-p.h"
44 #define _(String) dgettext (GETTEXT_PACKAGE, String)
52 sql_statement *parse_result;
55 gchar *single_global_tablename;
66 QofSqlQuery *sqn = (QofSqlQuery *) g_new0 (QofSqlQuery, 1);
68 sqn->qof_query = NULL;
69 sqn->parse_result = NULL;
71 sqn->single_global_tablename = NULL;
80 qof_sql_query_destroy (QofSqlQuery * q)
85 sql_destroy (q->parse_result);
122 get_table_and_param (
char *str,
char **tab,
char **param)
124 char *end = strchr (str,
'.');
137 dequote_string (
char *str)
141 if ((
'\'' == str[0]) || (
'\"' == str[0]))
151 handle_single_condition (QofSqlQuery * query, sql_condition * cond)
157 sql_field_item *sparam, *svalue;
158 gchar *qparam_name, *qvalue_name, *table_name, *param_name;
159 gchar *sep, *path, *str, *p;
171 PWARN (
"missing condition");
177 if (NULL == cond->d.pair.left)
179 PWARN (
"missing left parameter");
182 sparam = cond->d.pair.left->item;
183 if (SQL_name != sparam->type)
185 PWARN (
"we support only parameter names at this time (parsed %d)",
189 qparam_name = sparam->d.name->data;
190 if (NULL == qparam_name)
192 PWARN (
"missing parameter name");
199 if (NULL == cond->d.pair.right)
201 PWARN (
"missing right parameter");
204 svalue = cond->d.pair.right->item;
205 if (SQL_name != svalue->type)
207 PWARN (
"we support only simple values (parsed as %d)",
211 qvalue_name = svalue->d.name->data;
212 if (NULL == qvalue_name)
214 PWARN (
"missing value");
217 qvalue_name = dequote_string (qvalue_name);
222 if (0 == strncasecmp (qvalue_name,
"kvp://", 6))
224 if (NULL == query->kvp_join)
226 PWARN (
"missing kvp frame");
229 kv = kvp_frame_get_value (query->kvp_join, qvalue_name + 5);
234 kvt = kvp_value_get_type (kv);
237 qvalue_name = tmpbuff;
243 sprintf (tmpbuff,
"%" G_GINT64_FORMAT
"\n", ival);
248 double ival = kvp_value_get_double (kv);
249 sprintf (tmpbuff,
"%26.18g\n", ival);
261 #ifndef QOF_DISABLE_DEPRECATED
269 PWARN (
"unhandled kvp type=%d", kvt);
276 param_list = qof_query_build_param_list (qparam_name, NULL);
282 qop = QOF_COMPARE_EQUAL;
285 qop = QOF_COMPARE_GT;
288 qop = QOF_COMPARE_LT;
291 qop = QOF_COMPARE_GTE;
294 qop = QOF_COMPARE_LTE;
297 qop = QOF_COMPARE_NEQ;
302 PWARN (
"Unsupported compare op (parsed as %u)", cond->op);
309 get_table_and_param (qparam_name, &table_name, ¶m_name);
310 if (NULL == table_name)
312 table_name = query->single_global_tablename;
314 if (NULL == table_name)
316 PWARN (
"Need to specify an object class to query");
322 PWARN (
"The query object \'%s\' is not known", table_name);
329 PWARN (
"The parameter \'%s\' on object \'%s\' is not known",
330 param_name, table_name);
334 if (!strcmp (param_type, QOF_TYPE_STRING))
336 pred_data = qof_query_string_predicate (qop,
338 QOF_STRING_MATCH_CASEINSENSITIVE,
341 else if (!strcmp (param_type, QOF_TYPE_CHAR))
344 if (QOF_COMPARE_NEQ == qop)
345 cm = QOF_CHAR_MATCH_NONE;
346 pred_data = qof_query_char_predicate (cm, qvalue_name);
348 else if (!strcmp (param_type, QOF_TYPE_INT32))
350 gint32 ival = atoi (qvalue_name);
351 pred_data = qof_query_int32_predicate (qop, ival);
353 else if (!strcmp (param_type, QOF_TYPE_INT64))
355 gint64 ival = atoll (qvalue_name);
356 pred_data = qof_query_int64_predicate (qop, ival);
358 else if (!strcmp (param_type, QOF_TYPE_DOUBLE))
360 double ival = atof (qvalue_name);
361 pred_data = qof_query_double_predicate (qop, ival);
363 else if (!strcmp (param_type, QOF_TYPE_BOOLEAN))
366 pred_data = qof_query_boolean_predicate (qop, ival);
377 qof_query_time_predicate (qop, QOF_DATE_MATCH_NORMAL,
380 #ifndef QOF_DISABLE_DEPRECATED
393 exact = strtoll (qvalue_name, &tail, 0);
403 else if (!strcmp (param_type, QOF_TYPE_NUMERIC))
408 qof_query_numeric_predicate (qop, QOF_NUMERIC_MATCH_ANY, ival);
410 else if (!strcmp (param_type, QOF_TYPE_DEBCRED))
416 qof_query_numeric_predicate (qop, QOF_NUMERIC_MATCH_ANY, ival);
418 else if (!strcmp (param_type, QOF_TYPE_GUID))
424 PWARN (
"unable to parse guid: %s", qvalue_name);
432 if (QOF_COMPARE_NEQ == qop)
433 gm = QOF_GUID_MATCH_NONE;
434 guid_list = g_list_append (NULL, &guid);
435 pred_data = qof_query_guid_predicate (gm, guid_list);
437 g_list_free (guid_list);
439 else if (!strcmp (param_type, QOF_TYPE_KVP))
444 sep = strchr (qvalue_name,
':');
459 if ((32 == len) && (32 == strspn (str,
"0123456789abcdef")))
463 kval = kvp_value_new_guid (&guid);
465 else if (len == strspn (str,
"0123456789"))
467 kval = kvp_value_new_gint64 (atoll (str));
469 else if ((p = strchr (str,
'.')) &&
470 ((len - 1) == (strspn (str,
"0123456789") +
471 strspn (p + 1,
"0123456789"))))
473 kval = kvp_value_new_double (atof (str));
476 else if ((p = strchr (str,
'/')) &&
477 ((len - 1) == (strspn (str,
"0123456789") +
478 strspn (p + 1,
"0123456789"))))
482 kval = kvp_value_new_numeric (num);
484 else if ((p = strchr (str,
'-')) &&
485 (p = strchr (p + 1,
'-')) &&
486 (p = strchr (p + 1,
' ')) &&
487 (p = strchr (p + 1,
':')) && (p = strchr (p + 1,
':')))
495 kvp_value_new_time (qt);
502 kval = kvp_value_new_string (str);
508 PWARN (
"The predicate type \"%s\" is unsupported for now",
521 handle_where (QofSqlQuery * query, sql_where * swear)
530 QofQuery *qleft = handle_where (query, swear->d.pair.left);
531 QofQuery *qright = handle_where (query, swear->d.pair.right);
536 switch (swear->d.pair.op)
557 QofQuery *qq = handle_where (query, swear->d.negated);
565 sql_condition *cond = swear->d.single;
566 return handle_single_condition (query, cond);
575 handle_sort_order (QofSqlQuery * query, GList * sorder_list)
579 gboolean direction[3];
581 sql_order_field *sorder;
587 for (i = 0; i < 3; i++)
594 sorder = sorder_list->data;
597 if (SQL_asc == sorder->order_type)
605 qparam_name = n->data;
609 qof_query_build_param_list (qparam_name, NULL);
616 sorder_list = sorder_list->next;
623 direction[1], direction[2]);
629 qof_sql_insertCB (
const QofParam * param,
const gchar * insert_string,
633 sql_insert_statement *sis;
634 gboolean registered_type;
642 gchar cm_char, *tail;
647 void (*string_setter) (
QofEntity *,
const gchar *);
650 void (*double_setter) (
QofEntity *, gdouble);
651 void (*boolean_setter) (
QofEntity *, gboolean);
652 void (*i32_setter) (
QofEntity *, gint32);
653 void (*i64_setter) (
QofEntity *, gint64);
654 void (*char_setter) (
QofEntity *, gchar);
657 g_return_if_fail (param || insert_string || query);
658 ent = query->inserted_entity;
659 sis = query->parse_result->statement;
660 type = g_strdup_printf (
"%s", sis->table->d.simple);
662 ENTER (
" param=%s param_type=%s type=%s content=%s",
663 param->param_name, param->param_type, type, insert_string);
664 if (
safe_strcmp (param->param_type, QOF_TYPE_STRING) == 0)
667 (void (*)(
QofEntity *,
const char *)) param->param_setfcn;
668 if (string_setter != NULL)
670 string_setter (ent, insert_string);
672 registered_type = TRUE;
674 if (
safe_strcmp (param->param_type, QOF_TYPE_TIME) == 0)
682 if((time_setter != NULL) && (qof_time_is_valid(qt)))
684 time_setter (ent, qt);
687 #ifndef QOF_DISABLE_DEPRECATED
692 struct tm query_time;
698 query_time_t = mktime (&query_time);
699 timespecFromTime_t (&cm_date, query_time_t);
700 if (date_setter != NULL)
702 date_setter (ent, cm_date);
706 if ((
safe_strcmp (param->param_type, QOF_TYPE_NUMERIC) == 0) ||
707 (
safe_strcmp (param->param_type, QOF_TYPE_DEBCRED) == 0))
712 if (numeric_setter != NULL)
714 numeric_setter (ent, cm_numeric);
717 if (
safe_strcmp (param->param_type, QOF_TYPE_GUID) == 0)
719 cm_guid = g_new (
GUID, 1);
722 LEAVE (
" string to guid failed for %s", insert_string);
737 if (
safe_strcmp (param->param_type, QOF_TYPE_INT32) == 0)
740 cm_i32 = (gint32) strtol (insert_string, &tail, 0);
744 (void (*)(
QofEntity *, gint32)) param->param_setfcn;
745 if (i32_setter != NULL)
747 i32_setter (ent, cm_i32);
758 (_(
"When converting SQLite strings into numbers, an "
759 "overflow has been detected. The SQLite database "
760 "'%s' contains invalid data in a field that is meant "
761 "to hold a number."), TRUE));
764 if (
safe_strcmp (param->param_type, QOF_TYPE_INT64) == 0)
767 cm_i64 = strtoll (insert_string, &tail, 0);
771 (void (*)(
QofEntity *, gint64)) param->param_setfcn;
772 if (i64_setter != NULL)
774 i64_setter (ent, cm_i64);
785 (_(
"When converting SQLite strings into numbers, an "
786 "overflow has been detected. The SQLite database "
787 "'%s' contains invalid data in a field that is meant "
788 "to hold a number."), TRUE));
791 if (
safe_strcmp (param->param_type, QOF_TYPE_DOUBLE) == 0)
794 cm_double = strtod (insert_string, &tail);
798 (void (*)(
QofEntity *, double)) param->param_setfcn;
799 if (double_setter != NULL)
801 double_setter (ent, cm_double);
805 if (
safe_strcmp (param->param_type, QOF_TYPE_BOOLEAN) == 0)
818 (void (*)(
QofEntity *, gboolean)) param->param_setfcn;
819 if (boolean_setter != NULL)
821 boolean_setter (ent, cm_boolean);
824 if (
safe_strcmp (param->param_type, QOF_TYPE_KVP) == 0)
828 if (
safe_strcmp (param->param_type, QOF_TYPE_CHAR) == 0)
830 cm_char = *insert_string;
831 char_setter = (void (*)(
QofEntity *, char)) param->param_setfcn;
832 if (char_setter != NULL)
834 char_setter (ent, cm_char);
841 qof_query_set_insert_table (QofSqlQuery * query)
843 sql_insert_statement *sis;
845 sis = query->parse_result->statement;
846 switch (sis->table->type)
851 query->single_global_tablename =
852 g_strdup_printf (
"%s", sis_t->d.simple);
854 query->single_global_tablename);
855 PINFO (
" insert set to table: %s", sis_t->d.simple);
860 PWARN (
"SQL insert only handles simple statements");
866 qof_query_insert (QofSqlQuery * query)
868 GList *field_list, *value_list, *cur;
869 const gchar *param_name;
874 sql_insert_statement *sis;
876 sql_field_item *item;
879 query->param_list = NULL;
886 sis = query->parse_result->statement;
887 if (!sis->fields || !sis->values)
889 LEAVE (
" NULL insert statement");
892 type = g_strdup (query->single_global_tablename);
896 LEAVE (
" unable to create instance of type %s", type);
899 query->inserted_entity = &inst->
entity;
900 value_list = sis->values;
901 for (field_list = sis->fields; field_list != NULL;
902 field_list = field_list->next)
904 field = value_list->data;
906 for (cur = item->d.name; cur != NULL; cur = cur->next)
909 g_strdup_printf (
"%s",
910 dequote_string ((
char *) cur->data));
912 field = field_list->data;
914 for (cur = item->d.name; cur != NULL; cur = cur->next)
916 param_name = g_strdup_printf (
"%s", (
char *) cur->data);
921 qof_sql_insertCB (param, value, query);
923 value_list = g_list_next (value_list);
926 return query->inserted_entity;
930 sql_type_as_string (sql_statement_type type)
962 sql_select_statement *sss;
969 if (query->qof_query)
972 sql_destroy (query->parse_result);
973 query->qof_query = NULL;
977 buf = g_strdup (str);
978 query->parse_result = sql_parse (buf);
981 if (!query->parse_result)
983 LEAVE (
"parse error");
987 if ((SQL_select != query->parse_result->type)
988 && (SQL_insert != query->parse_result->type))
991 (
"currently, only SELECT or INSERT statements are supported, "
992 "got type=%s", sql_type_as_string (query->parse_result->type));
1001 tables = sql_statement_get_tables (query->parse_result);
1002 if (1 == g_list_length (tables))
1004 query->single_global_tablename = tables->data;
1007 if (SQL_insert == query->parse_result->type)
1010 qof_query_set_insert_table (query);
1011 LEAVE (
" insert statement parsed OK");
1014 sss = query->parse_result->statement;
1019 query->qof_query = handle_where (query, swear);
1020 if (NULL == query->qof_query)
1022 LEAVE (
" no query found");
1031 handle_sort_order (query, sss->order);
1038 query->single_global_tablename);
1053 if (NULL == query->qof_query)
1055 PINFO (
" Null query");
1065 if (SQL_insert == query->parse_result->type)
1068 results = g_list_append (results, qof_query_insert (query));
1085 if (NULL == query->qof_query)