1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
3 * Copyright (C) 2008 Novell, Inc. (www.novell.com)
5 * Author: Srinivasa Ragavan <sragavan@novell.com>
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of version 2 of the GNU Lesser General Public
9 * License as published by the Free Software Foundation.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this program; if not, write to the
18 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 * Boston, MA 02110-1301, USA.
22 /* This is a helper class for folders to implement the search function.
23 * It implements enough to do basic searches on folders that can provide
24 * an in-memory summary and a body index. */
33 #include "camel-search-sql-sexp.h"
34 #define d(x) /* x;printf("\n"); */
39 CAMEL_SEARCH_MATCH_EXACT,
40 CAMEL_SEARCH_MATCH_CONTAINS,
41 CAMEL_SEARCH_MATCH_STARTS,
42 CAMEL_SEARCH_MATCH_ENDS,
43 CAMEL_SEARCH_MATCH_SOUNDEX
44 } camel_search_match_t;
45 gchar * camel_db_get_column_name (const gchar *raw_name);
48 camel_db_sqlize_string (const gchar *string)
50 return sqlite3_mprintf ("%Q", string);
54 camel_db_free_sqlized_string (gchar *string)
56 sqlite3_free (string);
62 #include "camel-folder-search.h"
63 #include "camel-search-private.h"
67 get_db_safe_string (const gchar *str)
69 gchar *tmp = camel_db_sqlize_string (str);
73 camel_db_free_sqlized_string (tmp);
78 /* Configuration of your sexp expression */
80 static CamelSExpResult *
81 func_and (CamelSExp *f,
83 struct _CamelSExpTerm **argv,
86 CamelSExpResult *r, *r1;
90 d (printf ("executing and: %d", argc));
92 string = g_string_new ("( ");
93 for (i = 0; i < argc; i++) {
94 r1 = camel_sexp_term_eval (f, argv[i]);
96 if (r1->type != CAMEL_SEXP_RES_STRING) {
97 camel_sexp_result_free (f, r1);
100 if (r1->value.string && *r1->value.string)
101 g_string_append_printf (string, "%s%s", r1->value.string, ((argc > 1) && (i != argc - 1)) ? " AND ":"");
102 camel_sexp_result_free (f, r1);
104 g_string_append (string, " )");
105 r = camel_sexp_result_new (f, CAMEL_SEXP_RES_STRING);
107 if (strlen (string->str) == 4)
108 r->value.string = g_strdup ("");
110 r->value.string = string->str;
111 g_string_free (string, FALSE);
116 static CamelSExpResult *
117 func_or (CamelSExp *f,
119 struct _CamelSExpTerm **argv,
122 CamelSExpResult *r, *r1;
126 d (printf ("executing or: %d", argc));
128 string = g_string_new ("( ");
129 for (i = 0; i < argc; i++) {
130 r1 = camel_sexp_term_eval (f, argv[i]);
132 if (r1->type != CAMEL_SEXP_RES_STRING) {
133 camel_sexp_result_free (f, r1);
136 g_string_append_printf (string, "%s%s", r1->value.string, ((argc > 1) && (i != argc - 1)) ? " OR ":"");
137 camel_sexp_result_free (f, r1);
139 g_string_append (string, " )");
141 r = camel_sexp_result_new (f, CAMEL_SEXP_RES_STRING);
142 r->value.string = string->str;
143 g_string_free (string, FALSE);
147 static CamelSExpResult *
148 func_not (CamelSExp *f,
150 struct _CamelSExpTerm **argv,
153 CamelSExpResult *r = NULL, *r1;
155 d (printf ("executing not: %d", argc));
156 r1 = camel_sexp_term_eval (f, argv[0]);
158 if (r1->type == CAMEL_SEXP_RES_STRING) {
159 r = camel_sexp_result_new (f, CAMEL_SEXP_RES_STRING);
160 /* HACK: Fix and handle completed-on better. */
161 if (g_strcmp0 (r1->value.string, "( (usertags LIKE '%completed-on 0%' AND usertags LIKE '%completed-on%') )") == 0)
162 r->value.string = g_strdup ("( (not (usertags LIKE '%completed-on 0%')) AND usertags LIKE '%completed-on%' )");
164 r->value.string = g_strdup_printf (
165 "(NOT (%s))", r1->value.string);
167 camel_sexp_result_free (f, r1);
172 /* this should support all arguments ...? */
173 static CamelSExpResult *
174 eval_eq (struct _CamelSExp *f,
176 struct _CamelSExpTerm **argv,
179 struct _CamelSExpResult *r, *r1, *r2;
181 r = camel_sexp_result_new (f, CAMEL_SEXP_RES_STRING);
184 GString *str = g_string_new ("( ");
185 r1 = camel_sexp_term_eval (f, argv[0]);
186 r2 = camel_sexp_term_eval (f, argv[1]);
188 if (r1->type == CAMEL_SEXP_RES_INT)
189 g_string_append_printf (str, "%d", r1->value.number);
190 else if (r1->type == CAMEL_SEXP_RES_TIME)
191 g_string_append_printf (str, "%ld", r1->value.time);
192 else if (r1->type == CAMEL_SEXP_RES_STRING)
193 g_string_append_printf (str, "%s", r1->value.string);
195 if (!strstr (str->str, "completed-on") && !strstr (str->str, "follow-up")) {
198 if (strstr (str->str, "usertags"))
201 g_string_append_printf (str, " LIKE ");
203 g_string_append_printf (str, " = ");
204 if (r2->type == CAMEL_SEXP_RES_INT)
205 g_string_append_printf (str, "%d", r2->value.number);
206 if (r2->type == CAMEL_SEXP_RES_BOOL)
207 g_string_append_printf (str, "%d", r2->value.boolean);
208 else if (r2->type == CAMEL_SEXP_RES_TIME)
209 g_string_append_printf (str, "%ld", r2->value.time);
210 else if (r2->type == CAMEL_SEXP_RES_STRING) {
211 gchar *tmp = g_strdup_printf ("%c%s%c", ut ? '%':' ', r2->value.string, ut ? '%':' ');
212 gchar *safe = get_db_safe_string (tmp);
213 g_string_append_printf (str, "%s", safe);
218 camel_sexp_result_free (f, r1);
219 camel_sexp_result_free (f, r2);
220 g_string_append (str, " )");
221 r->value.string = str->str;
222 g_string_free (str, FALSE);
224 r->value.string = g_strdup ("(0)");
229 static CamelSExpResult *
230 eval_lt (struct _CamelSExp *f,
232 struct _CamelSExpTerm **argv,
235 struct _CamelSExpResult *r, *r1, *r2;
237 r = camel_sexp_result_new (f, CAMEL_SEXP_RES_STRING);
240 GString *str = g_string_new ("( ");
241 r1 = camel_sexp_term_eval (f, argv[0]);
242 r2 = camel_sexp_term_eval (f, argv[1]);
244 if (r1->type == CAMEL_SEXP_RES_INT)
245 g_string_append_printf (str, "%d", r1->value.number);
246 else if (r1->type == CAMEL_SEXP_RES_TIME)
247 g_string_append_printf (str, "%ld", r1->value.time);
248 else if (r1->type == CAMEL_SEXP_RES_STRING)
249 g_string_append_printf (str, "%s", r1->value.string);
251 g_string_append_printf (str, " < ");
252 if (r2->type == CAMEL_SEXP_RES_INT)
253 g_string_append_printf (str, "%d", r2->value.number);
254 if (r2->type == CAMEL_SEXP_RES_BOOL)
255 g_string_append_printf (str, "%d", r2->value.boolean);
256 else if (r2->type == CAMEL_SEXP_RES_TIME)
257 g_string_append_printf (str, "%ld", r2->value.time);
258 else if (r2->type == CAMEL_SEXP_RES_STRING)
259 g_string_append_printf (str, "%s", r2->value.string);
260 camel_sexp_result_free (f, r1);
261 camel_sexp_result_free (f, r2);
262 g_string_append (str, " )");
264 r->value.string = str->str;
265 g_string_free (str, FALSE);
270 /* this should support all arguments ...? */
271 static CamelSExpResult *
272 eval_gt (struct _CamelSExp *f,
274 struct _CamelSExpTerm **argv,
277 struct _CamelSExpResult *r, *r1, *r2;
279 r = camel_sexp_result_new (f, CAMEL_SEXP_RES_STRING);
282 GString *str = g_string_new ("( ");
283 r1 = camel_sexp_term_eval (f, argv[0]);
284 r2 = camel_sexp_term_eval (f, argv[1]);
286 if (r1->type == CAMEL_SEXP_RES_INT)
287 g_string_append_printf (str, "%d", r1->value.number);
288 else if (r1->type == CAMEL_SEXP_RES_TIME)
289 g_string_append_printf (str, "%ld", r1->value.time);
290 else if (r1->type == CAMEL_SEXP_RES_STRING)
291 g_string_append_printf (str, "%s", r1->value.string);
293 g_string_append_printf (str, " > ");
294 if (r2->type == CAMEL_SEXP_RES_INT)
295 g_string_append_printf (str, "%d", r2->value.number);
296 if (r2->type == CAMEL_SEXP_RES_BOOL)
297 g_string_append_printf (str, "%d", r2->value.boolean);
298 else if (r2->type == CAMEL_SEXP_RES_TIME)
299 g_string_append_printf (str, "%ld", r2->value.time);
300 else if (r2->type == CAMEL_SEXP_RES_STRING)
301 g_string_append_printf (str, "%s", r2->value.string);
302 camel_sexp_result_free (f, r1);
303 camel_sexp_result_free (f, r2);
304 g_string_append (str, " )");
306 r->value.string = str->str;
307 g_string_free (str, FALSE);
312 static CamelSExpResult *
313 match_all (struct _CamelSExp *f,
315 struct _CamelSExpTerm **argv,
320 d (printf ("executing match-all: %d", argc));
322 r = camel_sexp_result_new (f, CAMEL_SEXP_RES_STRING);
323 r->value.string = g_strdup ("1");
324 } else if (argv[0]->type != CAMEL_SEXP_TERM_BOOL)
325 r = camel_sexp_term_eval (f, argv[0]);
327 r = camel_sexp_result_new (f, CAMEL_SEXP_RES_STRING);
328 r->value.string = g_strdup (argv[0]->value.boolean ? "1" : "0");
335 static CamelSExpResult *
336 match_threads (struct _CamelSExp *f,
338 struct _CamelSExpTerm **argv,
343 GString *str = g_string_new ("( ");
345 d (printf ("executing match-threads: %d", argc));
347 for (i = 1; i < argc; i++) {
348 r = camel_sexp_term_eval (f, argv[i]);
349 g_string_append_printf (str, "%s%s", r->value.string, ((argc > 1) && (i != argc - 1)) ? " AND ":"");
350 camel_sexp_result_free (f, r);
353 g_string_append (str, " )");
354 r = camel_sexp_result_new (f, CAMEL_SEXP_RES_STRING);
355 r->value.string = str->str;
356 g_string_free (str, FALSE);
361 static CamelSExpResult *
362 check_header (struct _CamelSExp *f,
364 struct _CamelSExpResult **argv,
366 camel_search_match_t how)
371 d (printf ("executing check-header %d\n", how));
373 /* are we inside a match-all? */
374 if (argc > 1 && argv[0]->type == CAMEL_SEXP_RES_STRING) {
378 /* only a subset of headers are supported .. */
379 headername = camel_db_get_column_name (argv[0]->value.string);
381 /* performs an OR of all words */
382 for (i = 1; i < argc; i++) {
383 if (argv[i]->type == CAMEL_SEXP_RES_STRING) {
384 gchar *value = NULL, *tstr = NULL;
385 if (argv[i]->value.string[0] == 0)
387 if (how == CAMEL_SEARCH_MATCH_CONTAINS || how == CAMEL_SEARCH_MATCH_WORD) {
388 tstr = g_strdup_printf ("%c%s%c", '%', argv[i]->value.string, '%');
389 value = get_db_safe_string (tstr);
391 } else if (how == CAMEL_SEARCH_MATCH_ENDS) {
392 tstr = g_strdup_printf ("%c%s", '%', argv[i]->value.string);
393 value = get_db_safe_string (tstr);
395 } else if (how == CAMEL_SEARCH_MATCH_STARTS) {
396 tstr = g_strdup_printf ("%s%c", argv[i]->value.string, '%');
397 value = get_db_safe_string (tstr);
399 } else if (how == CAMEL_SEARCH_MATCH_EXACT) {
400 tstr = g_strdup_printf ("%c%s%c", '%', argv[i]->value.string, '%');
401 value = get_db_safe_string (tstr);
404 str = g_strdup_printf ("(%s IS NOT NULL AND %s LIKE %s)", headername, headername, value);
410 /* TODO: else, find all matches */
412 r = camel_sexp_result_new (f, CAMEL_SEXP_RES_STRING);
413 r->value.string = str;
418 static CamelSExpResult *
419 header_contains (struct _CamelSExp *f,
421 struct _CamelSExpResult **argv,
424 d (printf ("executing header-contains: %d", argc));
426 return check_header (f, argc, argv, data, CAMEL_SEARCH_MATCH_CONTAINS);
429 static CamelSExpResult *
430 header_has_words (struct _CamelSExp *f,
432 struct _CamelSExpResult **argv,
435 d (printf ("executing header-has-word: %d", argc));
437 return check_header (f, argc, argv, data, CAMEL_SEARCH_MATCH_WORD);
440 static CamelSExpResult *
441 header_matches (struct _CamelSExp *f,
443 struct _CamelSExpResult **argv,
446 d (printf ("executing header-matches: %d", argc));
448 return check_header (f, argc, argv, data, CAMEL_SEARCH_MATCH_EXACT);
451 static CamelSExpResult *
452 header_starts_with (struct _CamelSExp *f,
454 struct _CamelSExpResult **argv,
457 d (printf ("executing header-starts-with: %d", argc));
459 return check_header (f, argc, argv, data, CAMEL_SEARCH_MATCH_STARTS);
462 static CamelSExpResult *
463 header_ends_with (struct _CamelSExp *f,
465 struct _CamelSExpResult **argv,
468 d (printf ("executing header-ends-with: %d", argc));
470 return check_header (f, argc, argv, data, CAMEL_SEARCH_MATCH_ENDS);
473 static CamelSExpResult *
474 header_exists (struct _CamelSExp *f,
476 struct _CamelSExpResult **argv,
482 d (printf ("executing header-exists: %d", argc));
484 headername = camel_db_get_column_name (argv[0]->value.string);
485 r = camel_sexp_result_new (f, CAMEL_SEXP_RES_STRING);
486 r->value.string = g_strdup_printf ("(%s NOTNULL)", headername);
491 static CamelSExpResult *
492 user_tag (struct _CamelSExp *f,
494 struct _CamelSExpResult **argv,
499 d (printf ("executing user-tag: %d", argc));
501 r = camel_sexp_result_new (f, CAMEL_SEXP_RES_STRING);
502 /* Hacks no otherway to fix these really :( */
503 if (g_strcmp0 (argv[0]->value.string, "completed-on") == 0)
504 r->value.string = g_strdup_printf ("(usertags LIKE '%ccompleted-on 0%c' AND usertags LIKE '%ccompleted-on%c')", '%', '%', '%', '%');
505 else if (g_strcmp0 (argv[0]->value.string, "follow-up") == 0)
506 r->value.string = g_strdup_printf ("usertags NOT LIKE '%cfollow-up%c'", '%', '%');
508 r->value.string = g_strdup ("usertags");
513 static CamelSExpResult *
514 user_flag (struct _CamelSExp *f,
516 struct _CamelSExpResult **argv,
522 d (printf ("executing user-flag: %d", argc));
524 r = camel_sexp_result_new (f, CAMEL_SEXP_RES_STRING);
527 r->value.string = g_strdup ("(0)");
529 tstr = g_strdup_printf ("%s", argv[0]->value.string);
530 qstr = get_db_safe_string (tstr);
532 r->value.string = g_strdup_printf ("(labels MATCH %s)", qstr);
539 static CamelSExpResult *
540 system_flag (struct _CamelSExp *f,
542 struct _CamelSExpResult **argv,
548 d (printf ("executing system-flag: %d", argc));
550 r = camel_sexp_result_new (f, CAMEL_SEXP_RES_STRING);
553 r->value.string = g_strdup ("(0)");
555 tstr = camel_db_get_column_name (argv[0]->value.string);
556 r->value.string = g_strdup_printf ("(%s = 1)", tstr);
563 static CamelSExpResult *
564 get_sent_date (struct _CamelSExp *f,
566 struct _CamelSExpResult **argv,
571 d (printf ("executing get-sent-date\n"));
573 r = camel_sexp_result_new (f, CAMEL_SEXP_RES_STRING);
574 r->value.string = g_strdup ("dsent");
579 static CamelSExpResult *
580 get_received_date (struct _CamelSExp *f,
582 struct _CamelSExpResult **argv,
587 d (printf ("executing get-received-date\n"));
589 r = camel_sexp_result_new (f, CAMEL_SEXP_RES_STRING);
590 r->value.string = g_strdup ("dreceived");
595 static CamelSExpResult *
596 get_current_date (struct _CamelSExp *f,
598 struct _CamelSExpResult **argv,
603 d (printf ("executing get-current-date\n"));
605 r = camel_sexp_result_new (f, CAMEL_SEXP_RES_INT);
606 r->value.number = time (NULL);
610 static CamelSExpResult *
611 get_relative_months (struct _CamelSExp *f,
613 struct _CamelSExpResult **argv,
618 d (printf ("executing get-relative-months\n"));
620 if (argc != 1 || argv[0]->type != CAMEL_SEXP_RES_INT) {
621 r = camel_sexp_result_new (f, CAMEL_SEXP_RES_BOOL);
622 r->value.boolean = FALSE;
624 g_debug ("%s: Expecting 1 argument, an integer, but got %d arguments", G_STRFUNC, argc);
626 r = camel_sexp_result_new (f, CAMEL_SEXP_RES_INT);
627 r->value.number = camel_folder_search_util_add_months (time (NULL), argv[0]->value.number);
633 static CamelSExpResult *
634 get_size (struct _CamelSExp *f,
636 struct _CamelSExpResult **argv,
641 d (printf ("executing get-size\n"));
643 r = camel_sexp_result_new (f, CAMEL_SEXP_RES_STRING);
644 r->value.string = g_strdup ("size/1024");
649 static CamelSExpResult *
650 sql_exp (struct _CamelSExp *f,
652 struct _CamelSExpResult **argv,
657 GString *str = g_string_new (NULL);
659 d (printf ("executing sql-exp\n"));
661 r = camel_sexp_result_new (f, CAMEL_SEXP_RES_STRING);
662 for (i = 0; i < argc; i++) {
663 if (argv[i]->type == CAMEL_SEXP_RES_STRING && argv[i]->value.string)
664 g_string_append (str, argv[i]->value.string);
666 r->value.string = str->str;
667 g_string_free (str, FALSE);
672 /* 'builtin' functions */
678 { "and", (CamelSExpFunc) func_and, 1 },
679 { "or", (CamelSExpFunc) func_or, 1},
680 { "not", (CamelSExpFunc) func_not, 1},
681 { "=", (CamelSExpFunc) eval_eq, 1},
682 { ">", (CamelSExpFunc) eval_gt, 1},
683 { "<", (CamelSExpFunc) eval_lt, 1},
685 { "match-all", (CamelSExpFunc) match_all, 1 },
686 { "match-threads", (CamelSExpFunc) match_threads, 1 },
687 /* { "body-contains", body_contains}, */ /* We don't store body on the db. */
688 { "header-contains", header_contains, 0},
689 { "header-has-words", header_has_words, 0},
690 { "header-matches", header_matches, 0},
691 { "header-starts-with", header_starts_with, 0},
692 { "header-ends-with", header_ends_with, 0},
693 { "header-exists", header_exists, 0},
694 { "user-tag", user_tag, 0},
695 { "user-flag", user_flag, 0},
696 { "system-flag", system_flag, 0},
697 { "get-sent-date", get_sent_date, 0},
698 { "get-received-date", get_received_date, 0},
699 { "get-current-date", get_current_date, 0},
700 { "get-relative-months", get_relative_months, 0},
701 { "get-size", get_size, 0},
702 { "sql-exp", sql_exp, 0},
704 /* { "uid", CAMEL_STRUCT_OFFSET(CamelFolderSearchClass, uid), 1 }, */
708 * camel_sexp_to_sql_sexp:
713 camel_sexp_to_sql_sexp (const gchar *sql)
720 sexp = camel_sexp_new ();
722 for (i = 0; i < G_N_ELEMENTS (symbols); i++) {
723 if (symbols[i].immediate)
724 camel_sexp_add_ifunction (sexp, 0, symbols[i].name,
725 (CamelSExpIFunc) symbols[i].func, NULL);
727 camel_sexp_add_function (
728 sexp, 0, symbols[i].name,
729 symbols[i].func, NULL);
732 camel_sexp_input_text (sexp, sql, strlen (sql));
733 if (camel_sexp_parse (sexp)) {
734 g_object_unref (sexp);
738 r = camel_sexp_eval (sexp);
740 g_object_unref (sexp);
744 if (r->type == CAMEL_SEXP_RES_STRING) {
745 res = g_strdup (r->value.string);
749 camel_sexp_result_free (sexp, r);
750 g_object_unref (sexp);
758 * (and (match-all (and (not (system-flag "deleted")) (not (system-flag "junk"))))
761 * (match-all (not (system-flag "Attachments")))
767 * replied INTEGER , (match-all (system-flag "Answered"))
768 * size INTEGER , (match-all (< (get-size) 100))
769 * dsent NUMERIC , (match-all (< (get-sent-date) (- (get-current-date) 10)))
770 * dreceived NUMERIC , (match-all (< (get-received-date) (- (get-current-date) 10)))
771 * //mlist TEXT , x-camel-mlist (match-all (header-matches "x-camel-mlist" "gnome.org"))
772 * //attachment, system-flag "Attachments" (match-all (system-flag "Attachments"))
773 * //followup_flag TEXT , (match-all (not (= (user-tag "follow-up") "")))
774 * //followup_completed_on TEXT , (match-all (not (= (user-tag "completed-on") "")))
775 * //followup_due_by TEXT ," //NOTREQD
778 gchar * camel_db_get_column_name (const gchar *raw_name)
780 /* d(g_print ("\n\aRAW name is : [%s] \n\a", raw_name)); */
781 if (!g_ascii_strcasecmp (raw_name, "Subject"))
782 return g_strdup ("subject");
783 else if (!g_ascii_strcasecmp (raw_name, "from"))
784 return g_strdup ("mail_from");
785 else if (!g_ascii_strcasecmp (raw_name, "Cc"))
786 return g_strdup ("mail_cc");
787 else if (!g_ascii_strcasecmp (raw_name, "To"))
788 return g_strdup ("mail_to");
789 else if (!g_ascii_strcasecmp (raw_name, "Flagged"))
790 return g_strdup ("important");
791 else if (!g_ascii_strcasecmp (raw_name, "deleted"))
792 return g_strdup ("deleted");
793 else if (!g_ascii_strcasecmp (raw_name, "junk"))
794 return g_strdup ("junk");
795 else if (!g_ascii_strcasecmp (raw_name, "Answered"))
796 return g_strdup ("replied");
797 else if (!g_ascii_strcasecmp (raw_name, "Seen"))
798 return g_strdup ("read");
799 else if (!g_ascii_strcasecmp (raw_name, "user-tag"))
800 return g_strdup ("usertags");
801 else if (!g_ascii_strcasecmp (raw_name, "user-flag"))
802 return g_strdup ("labels");
803 else if (!g_ascii_strcasecmp (raw_name, "Attachments"))
804 return g_strdup ("attachment");
805 else if (!g_ascii_strcasecmp (raw_name, "x-camel-mlist"))
806 return g_strdup ("mlist");
808 /* Let it crash for all unknown columns for now.
809 * We need to load the messages into memory and search etc.
810 * We should extend this for camel-folder-search system flags search as well
811 * otherwise, search-for-signed-messages will not work etc.*/
813 return g_strdup (raw_name);
824 "(match-all (header-contains \"From\" \"org\"))",
825 "(and (match-all (and (not (system-flag \"deleted\")) (not (system-flag \"junk\")))) (and (or (match-all (or (header-ends-with \"To\" \"novell.com\") (header-ends-with \"Cc\" \"novell.com\"))) (match-all (or (= (user-tag \"label\") \"work\") (user-flag \"work\"))) )))",
827 "(and (and (match-all (header-contains \"From\" \"org\")) ) (match-all (not (system-flag \"junk\"))))",
829 "(and (and (match-all (header-contains \"From\" \"org\"))) (and (match-all (not (system-flag \"junk\"))) (and (or (match-all (header-contains \"Subject\" \"test\")) (match-all (header-contains \"From\" \"test\"))))))",
830 "(and (and (match-all (header-exists \"From\")) ) (match-all (not (system-flag \"junk\"))))",
831 "(and (match-all (and (not (system-flag \"deleted\")) (not (system-flag \"junk\")))) (and (or (match-all (header-contains \"Subject\" \"org\")) (match-all (header-contains \"From\" \"org\")) (match-all (system-flag \"Flagged\")) (match-all (system-flag \"Seen\")) )))",
832 "(and (match-all (and (not (system-flag \"deleted\")) (not (system-flag \"junk\")))) (and (or (match-all (or (header-ends-with \"To\" \"novell.com\") (header-ends-with \"Cc\" \"novell.com\"))) (= (user-tag \"label\") \"work\") )))",
833 "(and (match-all (and (not (system-flag \"deleted\")) (not (system-flag \"junk\")))) (and (or (match-all (or (header-ends-with \"To\" \"novell.com\") (header-ends-with \"Cc\" \"novell.com\"))) (user-flag \"work\") )))",
834 "(and (match-all (and (not (system-flag \"deleted\")) (not (system-flag \"junk\")))) (and (or (match-all (or (header-ends-with \"To\" \"novell.com\") (header-ends-with \"Cc\" \"novell.com\"))) (user-flag (+ \"$Label\" \"work\")) )))"
835 "(and (match-all (and (not (system-flag \"deleted\")) (not (system-flag \"junk\")))) (and (or (match-all (not (= (user-tag \"follow-up\") \"\"))) )))",
836 "(and (match-all (and (not (system-flag \"deleted\")) (not (system-flag \"junk\")))) (and (or (match-all (= (user-tag \"follow-up\") \"\")) )))",
837 "(and (match-all (and (not (system-flag \"deleted\")) (not (system-flag \"junk\")))) (and (or (match-all (not (= (user-tag \"completed-on\") \"\"))) )))",
838 "(match-all (and (match-all #t) (system-flag \"deleted\")))",
839 "(and (match-all (and (not (system-flag \"deleted\")) (not (system-flag \"junk\")))) (and (or (match-all (or (= (user-tag \"label\") \"important\") (user-flag (+ \"$Label\" \"important\")) (user-flag \"important\"))) )))",
840 "(or (match-all (and (not (system-flag \"deleted\")) (not (system-flag \"junk\")) (not (system-flag \"Attachments\")) (not (system-flag \"Answered\")))) (and (or (match-all (= (user-tag \"completed-on\") \"\")) )))",
841 "(and (match-all (and (not (system-flag \"deleted\")) (not (system-flag \"junk\")))) (and (or (match-all (= (user-tag \"completed-on\") \"\")) (match-all (= (user-tag \"follow-up\") \"\")) )))",
842 "(and (match-all (and (not (system-flag \"deleted\")) (not (system-flag \"junk\")))) (and (or (match-all (> (get-sent-date) (- (get-current-date) 100))) )))",
843 "(and (match-all (and (not (system-flag \"deleted\")) (not (system-flag \"junk\")))) (and (or (match-all (< (get-sent-date) (+ (get-current-date) 100))) )))",
844 "(and (match-all (and (not (system-flag \"deleted\")) (not (system-flag \"junk\")))) (and (or (match-all (not (= (get-sent-date) 1216146600))) )))",
845 "(and (match-all (and (not (system-flag \"deleted\")) (not (system-flag \"junk\")))) (and (or (match-all (= (get-sent-date) 1216146600)) )))" ,
846 "(match-threads \"all\" (or (match-all (header-contains \"From\" \"@edesvcs.com\")) (match-all (or (header-contains \"To\" \"@edesvcs.com\") (header-contains \"Cc\" \"@edesvcs.com\"))) ))",
847 "(match-all (not (system-flag \"deleted\")))",
848 "(match-all (system-flag \"seen\"))",
849 "(match-all (and (match-all #t) (system-flag \"deleted\")))",
850 "(match-all (and (not (system-flag \"deleted\")) (not (system-flag \"junk\"))))",
852 "(and (or (match-all (header-contains \"Subject\" \"lin\")) ) (and (match-all (and (not (system-flag \"deleted\")) (not (system-flag \"junk\")))) (and (or (match-all (header-contains \"Subject\" \"case\")) (match-all (header-contains \"From\" \"case\"))))))",
853 "(and ( match-all(or (match-all (header-contains \"Subject\" \"lin\")) (match-all (header-contains \"From\" \"in\")))) (and (match-all (and (not (system-flag \"deleted\")) (not (system-flag \"junk\")))) (and (or (match-all (header-contains \"Subject\" \"proc\")) (match-all (header-contains \"From\" \"proc\"))))))",
854 "(and (or (match-all (header-contains \"Subject\" \"[LDTP-NOSIP]\")) ) (and (match-all (and (not (system-flag \"deleted\")) (not (system-flag \"junk\")))) (and (or (match-all (header-contains \"Subject\" \"vamsi\")) (match-all (header-contains \"From\" \"vamsi\"))))))",
855 /* Last one doesn't work so well and fails on one case. But I doubt, you can create a query like that in Evo. */
856 "(and (match-all (and (not (system-flag \"deleted\")) (not (system-flag \"junk\")))) (match-all (or (= (user-tag \"label\") \"_office\") (user-flag \"$Label_office\") (user-flag \"_office\"))))",
857 "(and (and (match-all #t))(and(match-all #t)))",
858 "(and (match-all (and (not (system-flag \"deleted\")) (not (system-flag \"junk\")))) (and (and (match-all (header-contains \"Subject\" \"mysubject\")) (match-all (not (header-matches \"From\" \"mysender\"))) (match-all (= (get-sent-date) (+ (get-current-date) 1))) (match-all (= (get-received-date) (- (get-current-date) 604800))) (match-all (or (= (user-tag \"label\") \"important\") (user-flag (+ \"$Label\" \"important\")) (match-all (< (get-size) 7000)) (match-all (not (= (get-sent-date) 1216146600))) (match-all (> (cast-int (user-tag \"score\")) 3)) (user-flag \"important\"))) (match-all (system-flag \"Deleted\")) (match-all (not (= (user-tag \"follow-up\") \"\"))) (match-all (= (user-tag \"completed-on\") \"\")) (match-all (system-flag \"Attachments\")) (match-all (header-contains \"x-camel-mlist\" \"evo-hackers\")) )))",
859 "(and (or (match-all (or (= (user-tag \"label\") \"important\") (user-flag (+ \"$Label\" \"important\")) (user-flag \"important\"))) (match-all (or (= (user-tag \"label\") \"work\") (user-flag (+ \"$Label\" \"work\")) (user-flag \"work\"))) (match-all (or (= (user-tag \"label\") \"personal\") (user-flag (+ \"$Label\" \"personal\")) (user-flag \"personal\"))) (match-all (or (= (user-tag \"label\") \"todo\") (user-flag (+ \"$Label\" \"todo\")) (user-flag \"todo\"))) (match-all (or (= (user-tag \"label\") \"later\") (user-flag (+ \"$Label\" \"later\")) (user-flag \"later\"))) ) (match-all (and (not (system-flag \"deleted\")) (not (system-flag \"junk\")))))",
860 "(or (header-matches \"to\" \"maw@ximian.com\") (header-matches \"to\" \"mw@ximian.com\") (header-matches \"to\" \"maw@novell.com\") (header-matches \"to\" \"maw.AMERICAS3.AMERICAS@novell.com\") (header-matches \"cc\" \"maw@ximian.com\") (header-matches \"cc\" \"mw@ximian.com\") (header-matches \"cc\" \"maw@novell.com\") (header-matches \"cc\" \"maw.AMERICAS3.AMERICAS@novell.com\"))",
861 "(not (or (header-matches \"from\" \"bugzilla-daemon@bugzilla.ximian.com\") (header-matches \"from\" \"bugzilla-daemon@bugzilla.gnome.org\") (header-matches \"from\" \"bugzilla_noreply@novell.com\") (header-matches \"from\" \"bugzilla-daemon@mozilla.org\") (header-matches \"from\" \"root@dist.suse.de\") (header-matches \"from\" \"root@hilbert3.suse.de\") (header-matches \"from\" \"root@hilbert4.suse.de\") (header-matches \"from\" \"root@hilbert5.suse.de\") (header-matches \"from\" \"root@hilbert6.suse.de\") (header-matches \"from\" \"root@suse.de\") (header-matches \"from\" \"swamp_noreply@suse.de\") (and (header-matches \"from\" \"hermes@opensuse.org\") (header-starts-with \"subject\" \"submit-Request\"))))",
862 "(and (match-threads \"replies_parents\" (and (match-all (or (header-matches \"to\" \"maw@ximian.com\") (header-matches \"to\" \"mw@ximian.com\") (header-matches \"to\" \"maw@novell.com\") (header-matches \"to\" \"maw.AMERICAS3.AMERICAS@novell.com\") (header-matches \"cc\" \"maw@ximian.com\") (header-matches \"cc\" \"mw@ximian.com\") (header-matches \"cc\" \"maw@novell.com\") (header-matches \"cc\" \"maw.AMERICAS3.AMERICAS@novell.com\"))) (match-all (not (or (header-matches \"from\" \"bugzilla-daemon@bugzilla.ximian.com\") (header-matches \"from\" \"bugzilla-daemon@bugzilla.gnome.org\") (header-matches \"from\" \"bugzilla_noreply@novell.com\") (header-matches \"from\" \"bugzilla-daemon@mozilla.org\") (header-matches \"from\" \"root@dist.suse.de\") (header-matches \"from\" \"root@hilbert3.suse.de\") (header-matches \"from\" \"root@hilbert4.suse.de\") (header-matches \"from\" \"root@hilbert5.suse.de\") (header-matches \"from\" \"root@hilbert6.suse.de\") (header-matches \"from\" \"root@suse.de\") (header-matches \"from\" \"swamp_noreply@suse.de\") (and (header-matches \"from\" \"hermes@opensuse.org\") (header-starts-with \"subject\" \"submit-Request\"))))) (match-all (> (get-sent-date) (- (get-current-date) 1209600))) )) (match-all (and (not (system-flag \"deleted\")) (not (system-flag \"junk\")))))",
863 "and ((match-all (system-flag \"Deleted\")) (match-all (system-flag \"junk\")))",
864 "(and (match-threads \"replies_parents\" (and (match-all (or (header-matches \"to\" \"maw@ximian.com\")))))))",
865 "(and (sql-exp \"folder_key = 'ASDGASd' AND folder_key = 'DSFWEA'\") (match-threads \"replies_parents\" (and (match-all (or (header-matches \"to\" \"maw@ximian.com\")))))))"
867 "(and (match-all (and (not (system-flag \"deleted\")) (not (system-flag \"junk\")))) (and (or (match-all list-post.*zypp-devel) ) ))"
870 for (i = 0; i < G_N_ELEMENTS (txt); i++) {
872 printf ("Q: %s\n\"%c\"\n", txt[i], 40);
873 sql = camel_sexp_to_sql_sexp (txt[i]);
874 printf ("A: %s\n\n\n", sql);