Groonga 3.0.9 Source Code Document
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
test-expr-parse.c
Go to the documentation of this file.
1 /* -*- c-basic-offset: 2; coding: utf-8 -*- */
2 /* Copyright(C) 2009 Brazil
3 
4  This library is free software; you can redistribute it and/or
5  modify it under the terms of the GNU Lesser General Public
6  License as published by the Free Software Foundation; either
7  version 2.1 of the License, or (at your option) any later version.
8 
9  This library is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12  Lesser General Public License for more details.
13 
14  You should have received a copy of the GNU Lesser General Public
15  License along with this library; if not, write to the Free Software
16  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17 */
18 
19 #include "db.h"
20 #include <stdio.h>
21 
22 #include <gcutter.h>
23 
24 #include "../lib/grn-assertions.h"
25 
26 static gchar *tmp_directory;
27 static gchar *path;
28 static grn_ctx context;
29 static grn_obj *database;
30 static grn_obj *cond, *res, *expr;
31 static grn_obj textbuf, intbuf;
32 
33 void data_parse(void);
34 void test_parse(gconstpointer data);
35 void test_set_value(void);
37 void test_set_value_with_query(void);
38 void test_proc_call(void);
39 void test_score_set(void);
40 void test_key_equal(void);
41 void test_value_access(void);
42 void test_snip(void);
43 void test_snip_without_tags(void);
44 void test_float_literal(void);
45 void test_uint32_literal(void);
47 void test_int64_literal(void);
48 void test_long_integer_literal(void);
50 
51 void
53 {
54  tmp_directory = g_build_filename(grn_test_get_tmp_dir(),
55  "test-expr-parse",
56  NULL);
57 }
58 
59 void
61 {
62  g_free(tmp_directory);
63 }
64 
65 void
66 cut_setup(void)
67 {
68  cut_remove_path(tmp_directory, NULL);
69  g_mkdir_with_parents(tmp_directory, 0700);
70  path = g_build_filename(tmp_directory, "text-expr-parse", NULL);
71  grn_ctx_init(&context, 0);
72  database = grn_db_create(&context, path, NULL);
73 
74  cond = NULL;
75  expr = NULL;
76  res = NULL;
77 
78  GRN_TEXT_INIT(&textbuf, 0);
79  GRN_UINT32_INIT(&intbuf, 0);
80 }
81 
82 void
84 {
85  grn_obj_close(&context, &textbuf);
86  grn_obj_close(&context, &intbuf);
87 
88  if (res)
89  grn_obj_close(&context, res);
90  if (expr)
91  grn_obj_close(&context, expr);
92  if (cond)
93  grn_obj_close(&context, cond);
94 
95  grn_db_close(&context, database);
96  grn_ctx_fin(&context);
97  cut_remove_path(tmp_directory, NULL);
98  g_free(path);
99 }
100 
101 static grn_obj *properties, *docs, *terms, *size, *body, *author, *index_body;
102 
103 static void
104 insert_document(const gchar *author_content, const gchar *body_content)
105 {
106  uint32_t s = (uint32_t)strlen(body_content);
107  grn_id docid = grn_table_add(&context, docs, NULL, 0, NULL);
108 
109  if (author_content) {
110  GRN_TEXT_SET(&context, &textbuf, author_content, strlen(author_content));
111  grn_test_assert(grn_obj_set_value(&context, author, docid, &textbuf,
112  GRN_OBJ_SET));
113  }
114 
115  GRN_TEXT_SET(&context, &textbuf, body_content, s);
116  grn_test_assert(grn_obj_set_value(&context, body, docid, &textbuf,
117  GRN_OBJ_SET));
118 
119  GRN_UINT32_SET(&context, &intbuf, s);
120  grn_test_assert(grn_obj_set_value(&context, size, docid, &intbuf,
121  GRN_OBJ_SET));
122 }
123 
124 #define INSERT_DOCUMENT(author, body) \
125  cut_trace(insert_document(author, body))
126 
127 static void grn_test_assert_select_all(grn_obj *result);
128 static void grn_test_assert_select_none(grn_obj *result);
129 
130 static void
131 grn_test_assert_select_all(grn_obj *result)
132 {
133  grn_test_assert_select(&context,
134  gcut_take_new_list_string("hoge",
135  "fuga fuga",
136  "moge moge moge",
137  "hoge hoge",
138  "hoge fuga fuga",
139  "hoge moge moge moge",
140  "moge hoge hoge",
141  "moge hoge fuga fuga",
142  "moge hoge moge moge moge",
143  "poyo moge hoge "
144  "moge moge moge",
145  NULL),
146  result,
147  "body");
148 }
149 
150 static void
151 grn_test_assert_select_none(grn_obj *result)
152 {
153  cut_assert_equal_uint(0, grn_table_size(&context, result));
154 }
155 
156 static void
157 create_properties_table(void)
158 {
159  const gchar *table_name = "properties";
160  properties = grn_table_create(&context, table_name, strlen(table_name), NULL,
162  grn_ctx_at(&context, GRN_DB_SHORT_TEXT), NULL);
163  cut_assert_not_null(properties);
164 }
165 
166 static void
167 create_documents_table(void)
168 {
169  docs = grn_table_create(&context, "docs", 4, NULL,
171  cut_assert_not_null(docs);
172 
173  size = grn_column_create(&context, docs, "size", 4, NULL,
175  grn_ctx_at(&context, GRN_DB_UINT32));
176  cut_assert_not_null(size);
177 
178  body = grn_column_create(&context, docs, "body", 4, NULL,
180  grn_ctx_at(&context, GRN_DB_TEXT));
181  cut_assert_not_null(body);
182 
183  author = grn_column_create(&context, docs, "author", 6, NULL,
185  properties);
186  cut_assert_not_null(author);
187 }
188 
189 static void
190 create_terms_table(void)
191 {
192  terms = grn_table_create(&context, "terms", 5, NULL,
194  grn_ctx_at(&context, GRN_DB_SHORT_TEXT), NULL);
195  cut_assert_not_null(terms);
197  grn_ctx_at(&context, GRN_DB_BIGRAM)));
198 
199  index_body = grn_column_create(&context, terms, "docs_body", 4, NULL,
201  docs);
202  cut_assert_not_null(index_body);
203 
204  GRN_UINT32_SET(&context, &intbuf, grn_obj_id(&context, body));
205  grn_obj_set_info(&context, index_body, GRN_INFO_SOURCE, &intbuf);
206 }
207 
208 static void
209 insert_data(void)
210 {
211  INSERT_DOCUMENT("morita", "hoge");
212  INSERT_DOCUMENT("morita", "fuga fuga");
213  INSERT_DOCUMENT("gunyara-kun", "moge moge moge");
214  INSERT_DOCUMENT(NULL, "hoge hoge");
215  INSERT_DOCUMENT(NULL, "hoge fuga fuga");
216  INSERT_DOCUMENT("gunyara-kun", "hoge moge moge moge");
217  INSERT_DOCUMENT("yu", "moge hoge hoge");
218  INSERT_DOCUMENT(NULL, "moge hoge fuga fuga");
219  INSERT_DOCUMENT(NULL, "moge hoge moge moge moge");
220  INSERT_DOCUMENT("morita", "poyo moge hoge moge moge moge");
221 }
222 
223 static void
224 prepare_data(void)
225 {
226  create_properties_table();
227  create_documents_table();
228  create_terms_table();
229  insert_data();
230 }
231 
232 #define PARSE(expr,str,flags) \
233  grn_test_assert(grn_expr_parse(&context, (expr), (str), strlen(str), \
234  body, GRN_OP_MATCH, GRN_OP_AND, flags))
235 
236 void
238 {
239 #define ADD_DATUM(label, \
240  query_hoge_moge, query_hoge_moge_parse_level, \
241  query_poyo, query_poyo_parse_level, \
242  query_size, query_size_parse_level) \
243  gcut_add_datum(label, \
244  "query_hoge_moge", G_TYPE_STRING, query_hoge_moge, \
245  "query_hoge_moge_parse_level", \
246  G_TYPE_INT, query_hoge_moge_parse_level, \
247  "query_poyo", G_TYPE_STRING, query_poyo, \
248  "query_poyo_parse_level", \
249  G_TYPE_INT, query_poyo_parse_level, \
250  "query_size", G_TYPE_STRING, query_size, \
251  "query_size_parse_level", \
252  G_TYPE_INT, query_size_parse_level, \
253  NULL)
254 
255  ADD_DATUM("column query parse level",
256  "hoge + moge",
258  "poyo", GRN_EXPR_SYNTAX_QUERY,
260  ADD_DATUM("table query parse level",
261  "body:@hoge + body:@moge",
265  ADD_DATUM("expression parse level",
266  "body@\"hoge\" && body@\"moge\"",
268  "body@\"poyo\"", GRN_EXPR_SYNTAX_SCRIPT,
269  "size == 14", GRN_EXPR_SYNTAX_SCRIPT);
270 #undef ADD_DATUM
271 }
272 
273 void
274 test_parse(gconstpointer data)
275 {
276  grn_obj *v;
277 
278  prepare_data();
279 
280  cond = grn_expr_create(&context, NULL, 0);
281  cut_assert_not_null(cond);
282  v = grn_expr_add_var(&context, cond, NULL, 0);
283  cut_assert_not_null(v);
284  GRN_RECORD_INIT(v, 0, grn_obj_id(&context, docs));
285  PARSE(cond, gcut_data_get_string(data, "query_hoge_moge"),
286  gcut_data_get_int(data, "query_hoge_moge_parse_level"));
287  PARSE(cond, gcut_data_get_string(data, "query_poyo"),
288  gcut_data_get_int(data, "query_poyo_parse_level"));
289  grn_expr_append_op(&context, cond, GRN_OP_AND, 2);
290  grn_test_assert_expr(&context,
291  "noname($1:0){2body GET_VALUE,0\"hoge\",4MATCH,"
292  "2body GET_VALUE,0\"moge\",0MATCH,4AND,"
293  "2body GET_VALUE,0\"poyo\",0MATCH,0AND}",
294  cond);
295  res = grn_table_create(&context, NULL, 0, NULL,
297  cut_assert_not_null(res);
298  cut_assert_not_null(grn_table_select(&context, docs, cond, res, GRN_OP_OR));
299 
300  grn_test_assert_select(&context,
301  gcut_take_new_list_string("poyo moge hoge "
302  "moge moge moge",
303  NULL),
304  res,
305  "body");
306  grn_test_assert(grn_obj_close(&context, res));
307  res = NULL;
308  grn_test_assert(grn_obj_close(&context, cond));
309  cond = NULL;
310 
311  cond = grn_expr_create(&context, NULL, 0);
312  cut_assert_not_null(cond);
313  v = grn_expr_add_var(&context, cond, NULL, 0);
314  cut_assert_not_null(v);
315  GRN_RECORD_INIT(v, 0, grn_obj_id(&context, docs));
316  PARSE(cond, gcut_data_get_string(data, "query_size"),
317  gcut_data_get_int(data, "query_size_parse_level"));
318  grn_test_assert_expr(&context,
319  "noname($1:0){2size GET_VALUE,014,0EQUAL}",
320  cond);
321  res = grn_table_create(&context, NULL, 0, NULL,
323  cut_assert_not_null(res);
324  cut_assert_not_null(grn_table_select(&context, docs, cond, res, GRN_OP_OR));
325 
326  grn_test_assert_select(&context,
327  gcut_take_new_list_string("moge moge moge",
328  "hoge fuga fuga",
329  "moge hoge hoge",
330  NULL),
331  res,
332  "body");
333 }
334 
335 void
337 {
338  grn_obj *v;
339 
340  prepare_data();
341 
342  GRN_EXPR_CREATE_FOR_QUERY(&context, docs, cond, v);
343  cut_assert_not_null(cond);
344  cut_assert_not_null(v);
345  PARSE(cond, "size:14",
347  res = grn_table_select(&context, docs, cond, NULL, GRN_OP_OR);
348  cut_assert_not_null(res);
349  grn_test_assert_select(&context,
350  gcut_take_new_list_string("moge moge moge",
351  "hoge fuga fuga",
352  "moge hoge hoge",
353  NULL),
354  res,
355  "body");
356  grn_test_assert(grn_obj_close(&context, res));
357  res = NULL;
358 
359  GRN_EXPR_CREATE_FOR_QUERY(&context, docs, expr, v);
360 
361  grn_expr_append_obj(&context, expr, v, GRN_OP_PUSH, 1);
362  GRN_TEXT_SETS(&context, &textbuf, "size");
363  grn_expr_append_const(&context, expr, &textbuf, GRN_OP_PUSH, 1);
364  grn_expr_append_op(&context, expr, GRN_OP_GET_VALUE, 2);
365  GRN_UINT32_SET(&context, &intbuf, 14);
366  grn_expr_append_const(&context, expr, &intbuf, GRN_OP_PUSH, 1);
367  grn_expr_append_op(&context, expr, GRN_OP_ASSIGN, 2);
368  {
369  grn_id id;
370  grn_table_cursor *tc;
371  tc = grn_table_cursor_open(&context, docs, NULL, 0, NULL, 0, 0, -1, 0);
372  cut_assert_not_null(tc);
373  while ((id = grn_table_cursor_next(&context, tc))) {
374  GRN_RECORD_SET(&context, v, id);
375  grn_expr_exec(&context, expr, 0);
376  }
378  }
379 
380  res = grn_table_select(&context, docs, cond, NULL, GRN_OP_OR);
381  cut_assert_not_null(res);
382  grn_test_assert_select_all(res);
383 }
384 
385 void
387 {
388  grn_obj *v;
389 
390  prepare_data();
391 
392  GRN_EXPR_CREATE_FOR_QUERY(&context, docs, cond, v);
393  cut_assert_not_null(cond);
394  cut_assert_not_null(v);
395  PARSE(cond, "size:14",
397  res = grn_table_select(&context, docs, cond, NULL, GRN_OP_OR);
398  cut_assert_not_null(res);
399  grn_test_assert_select(&context,
400  gcut_take_new_list_string("moge moge moge",
401  "hoge fuga fuga",
402  "moge hoge hoge",
403  NULL),
404  res,
405  "body");
406  grn_test_assert(grn_obj_close(&context, res));
407  res = NULL;
408 
409  GRN_EXPR_CREATE_FOR_QUERY(&context, docs, expr, v);
410 
411  GRN_TEXT_SETS(&context, &textbuf, "size");
412  grn_expr_append_const(&context, expr, &textbuf, GRN_OP_GET_VALUE, 1);
413  GRN_UINT32_SET(&context, &intbuf, 14);
414  grn_expr_append_const(&context, expr, &intbuf, GRN_OP_ASSIGN, 2);
415  {
416  grn_id id;
417  grn_table_cursor *tc;
418  tc = grn_table_cursor_open(&context, docs, NULL, 0, NULL, 0, 0, -1, 0);
419  cut_assert_not_null(tc);
420  while ((id = grn_table_cursor_next(&context, tc))) {
421  GRN_RECORD_SET(&context, v, id);
422  grn_expr_exec(&context, expr, 0);
423  }
425  }
426 
427  res = grn_table_select(&context, docs, cond, NULL, GRN_OP_OR);
428  cut_assert_not_null(res);
429  grn_test_assert_select_all(res);
430 }
431 
432 void
434 {
435  grn_obj *v;
436 
437  prepare_data();
438 
439  GRN_EXPR_CREATE_FOR_QUERY(&context, docs, cond, v);
440  cut_assert_not_null(cond);
441  cut_assert_not_null(v);
442  PARSE(cond, "size:14",
444  res = grn_table_select(&context, docs, cond, NULL, GRN_OP_OR);
445  cut_assert_not_null(res);
446  grn_test_assert_select(&context,
447  gcut_take_new_list_string("moge moge moge",
448  "hoge fuga fuga",
449  "moge hoge hoge",
450  NULL),
451  res,
452  "body");
453  grn_test_assert(grn_obj_close(&context, res));
454  res = NULL;
455 
456  GRN_EXPR_CREATE_FOR_QUERY(&context, docs, expr, v);
458  {
459  grn_id id;
460  grn_table_cursor *tc;
461  tc = grn_table_cursor_open(&context, docs, NULL, 0, NULL, 0, 0, -1, 0);
462  cut_assert_not_null(tc);
463  while ((id = grn_table_cursor_next(&context, tc))) {
464  GRN_RECORD_SET(&context, v, id);
465  grn_expr_exec(&context, expr, 0);
466  }
468  }
469 
470  res = grn_table_select(&context, docs, cond, NULL, GRN_OP_OR);
471  cut_assert_not_null(res);
472  grn_test_assert_select_all(res);
473 }
474 
475 void
477 {
478  grn_obj *v;
479 
480  prepare_data();
481 
482  GRN_EXPR_CREATE_FOR_QUERY(&context, docs, cond, v);
483  cut_assert_not_null(cond);
484  cut_assert_not_null(v);
485  PARSE(cond, "size:>14",
487  res = grn_table_select(&context, docs, cond, NULL, GRN_OP_OR);
488  cut_assert_not_null(res);
489  grn_test_assert_select(&context,
490  gcut_take_new_list_string("hoge moge moge moge",
491  "moge hoge fuga fuga",
492  "moge hoge moge moge moge",
493  "poyo moge hoge "
494  "moge moge moge",
495  NULL),
496  res,
497  "body");
498  grn_test_assert(grn_obj_close(&context, res));
499  res = NULL;
500 
501  GRN_EXPR_CREATE_FOR_QUERY(&context, docs, expr, v);
502  PARSE(expr, "size = rand(14)", GRN_EXPR_SYNTAX_SCRIPT|GRN_EXPR_ALLOW_UPDATE);
503  {
504  grn_id id;
505  grn_table_cursor *tc;
506  tc = grn_table_cursor_open(&context, docs, NULL, 0, NULL, 0, 0, -1, 0);
507  cut_assert_not_null(tc);
508  while ((id = grn_table_cursor_next(&context, tc))) {
509  GRN_RECORD_SET(&context, v, id);
510  grn_expr_exec(&context, expr, 0);
511  }
513  }
514 
515  res = grn_table_select(&context, docs, cond, NULL, GRN_OP_OR);
516  cut_assert_not_null(res);
517  grn_test_assert_select_none(res);
518 }
519 
520 void
522 {
523  grn_obj *v, *res2;
524 
525  prepare_data();
526 
527  GRN_EXPR_CREATE_FOR_QUERY(&context, docs, cond, v);
528  cut_assert_not_null(cond);
529  cut_assert_not_null(v);
530  PARSE(cond, "size:>0",
532  res = grn_table_select(&context, docs, cond, NULL, GRN_OP_OR);
533  cut_assert_not_null(res);
534  grn_test_assert_select_all(res);
535  grn_test_assert(grn_obj_close(&context, cond));
536  cond = NULL;
537 
538  GRN_EXPR_CREATE_FOR_QUERY(&context, res, expr, v);
539  PARSE(expr, "_score = size",
541  GRN_TABLE_EACH(&context, res, 0, 0, id, NULL, 0, NULL, {
542  GRN_RECORD_SET(&context, v, id);
543  grn_expr_exec(&context, expr, 0);
544  });
545 
546  GRN_EXPR_CREATE_FOR_QUERY(&context, res, cond, v);
547  cut_assert_not_null(cond);
548  cut_assert_not_null(v);
549  PARSE(cond, "_score:>9",
551  res2 = grn_table_select(&context, res, cond, NULL, GRN_OP_OR);
552  cut_assert_not_null(res2);
553  grn_test_assert_select(&context,
554  gcut_take_new_list_string("moge moge moge",
555  "hoge fuga fuga",
556  "hoge moge moge moge",
557  "moge hoge hoge",
558  "moge hoge fuga fuga",
559  "moge hoge moge moge moge",
560  "poyo moge hoge "
561  "moge moge moge",
562  NULL),
563  res2,
564  "body");
565  grn_test_assert(grn_obj_close(&context, res2));
566 }
567 
568 void
570 {
571  grn_obj *v;
572 
573  docs = grn_table_create(&context, "docs", 4, NULL,
575  grn_ctx_at(&context, GRN_DB_SHORT_TEXT), NULL);
576 
577  grn_table_add(&context, docs, "hoge", 4, NULL);
578  grn_table_add(&context, docs, "moge", 4, NULL);
579 
580  GRN_EXPR_CREATE_FOR_QUERY(&context, docs, cond, v);
581  cut_assert_not_null(cond);
582  cut_assert_not_null(v);
583  PARSE(cond, "_key:moge",
585  res = grn_table_select(&context, docs, cond, NULL, GRN_OP_OR);
586  cut_assert_not_null(res);
587  cut_assert_equal_uint(1, grn_table_size(&context, res));
588  grn_test_assert(grn_obj_close(&context, res));
589  res = NULL;
590  grn_test_assert(grn_obj_close(&context, cond));
591  cond = NULL;
592 
593  GRN_EXPR_CREATE_FOR_QUERY(&context, docs, cond, v);
594  cut_assert_not_null(cond);
595  cut_assert_not_null(v);
596  PARSE(cond, "_key:poge",
598  res = grn_table_select(&context, docs, cond, NULL, GRN_OP_OR);
599  cut_assert_not_null(res);
600  cut_assert_equal_uint(0, grn_table_size(&context, res));
601 }
602 
603 void
605 {
606  grn_id id;
607  grn_obj *v;
608 
609  docs = grn_table_create(&context, "docs", 4, NULL,
611  grn_ctx_at(&context, GRN_DB_SHORT_TEXT),
612  grn_ctx_at(&context, GRN_DB_INT32));
613 
614  id = grn_table_add(&context, docs, "one", 3, NULL);
615  GRN_UINT32_SET(&context, &intbuf, 1);
616  grn_test_assert(grn_obj_set_value(&context, docs, id, &intbuf, GRN_OBJ_SET));
617  id = grn_table_add(&context, docs, "two", 3, NULL);
618  GRN_UINT32_SET(&context, &intbuf, 2);
619  grn_test_assert(grn_obj_set_value(&context, docs, id, &intbuf, GRN_OBJ_SET));
620 
621  GRN_EXPR_CREATE_FOR_QUERY(&context, docs, cond, v);
622  cut_assert_not_null(cond);
623  cut_assert_not_null(v);
624  PARSE(cond, "_value:1",
626  res = grn_table_select(&context, docs, cond, NULL, GRN_OP_OR);
627  cut_assert_not_null(res);
628  cut_assert_equal_uint(1, grn_table_size(&context, res));
629  grn_test_assert(grn_obj_close(&context, res));
630  res = NULL;
631  grn_test_assert(grn_obj_close(&context, cond));
632  cond = NULL;
633 
634  GRN_EXPR_CREATE_FOR_QUERY(&context, docs, expr, v);
636  GRN_TABLE_EACH(&context, docs, 0, 0, id, NULL, 0, NULL, {
637  GRN_RECORD_SET(&context, v, id);
638  grn_expr_exec(&context, expr, 0);
639  });
640 
641  GRN_EXPR_CREATE_FOR_QUERY(&context, docs, cond, v);
642  cut_assert_not_null(cond);
643  cut_assert_not_null(v);
644  PARSE(cond, "_value:5",
646  res = grn_table_select(&context, docs, cond, NULL, GRN_OP_OR);
647  cut_assert_not_null(res);
648  cut_assert_equal_uint(2, grn_table_size(&context, res));
649 }
650 
651 void
653 {
654  grn_obj *v;
655 
656  prepare_data();
657 
658  GRN_EXPR_CREATE_FOR_QUERY(&context, docs, expr, v);
659  cut_assert_not_null(expr);
660 
661  PARSE(expr, "search engine column",
663 
664  {
665  grn_snip *snip;
666  int flags = 0;
667  unsigned int width, max_results;
668  const char *open_tags[] = {"[[", "<"};
669  const char *close_tags[] = {"]]", ">"};
670  unsigned int open_tag_lens[] = {2, 1};
671  unsigned int close_tag_lens[] = {2, 1};
672  unsigned int n_results;
673  unsigned int max_tagged_len;
674  gchar *result;
675  unsigned int result_len;
676  gchar text[] =
677  "groonga is an open-source fulltext search engine and column store.\n"
678  "It lets you write high-performance applications that requires "
679  "fulltext search.";
680 
681  width = 100;
682  max_results = 10;
683  snip = grn_expr_snip(&context, expr, flags,
684  width, max_results,
685  sizeof(open_tags) / sizeof(open_tags[0]),
686  open_tags, open_tag_lens,
687  close_tags, close_tag_lens,
688  NULL);
689  cut_assert_not_null(snip);
690 
691  grn_test_assert(grn_snip_exec(&context, snip, text, strlen(text),
692  &n_results, &max_tagged_len));
693 
694  cut_assert_equal_uint(2, n_results);
695  cut_assert_equal_uint(111, max_tagged_len);
696  result = g_new(gchar, max_tagged_len);
697  cut_take_memory(result);
698 
699  grn_test_assert(grn_snip_get_result(&context, snip, 0, result, &result_len));
700  cut_assert_equal_string("groonga is an open-source fulltext "
701  "[[search]] <engine> and [[column]] store.\n"
702  "It lets you write high-performanc",
703  result);
704  cut_assert_equal_uint(110, result_len);
705 
706  grn_test_assert(grn_snip_get_result(&context, snip, 1, result, &result_len));
707  cut_assert_equal_string("e applications that requires "
708  "fulltext [[search]].",
709  result);
710  cut_assert_equal_uint(49, result_len);
711 
712  grn_test_assert(grn_snip_close(&context, snip));
713  }
714 }
715 
716 void
718 {
719  grn_obj *v;
720 
721  prepare_data();
722 
723  GRN_EXPR_CREATE_FOR_QUERY(&context, docs, expr, v);
724  cut_assert_not_null(expr);
725 
726  PARSE(expr, "search engine column",
728 
729  {
730  grn_snip *snip;
731  int flags = 0;
732  unsigned int width, max_results;
733  unsigned int n_results;
734  unsigned int max_tagged_len;
735  gchar *result;
736  unsigned int result_len;
737  gchar text[] =
738  "groonga is an open-source fulltext search engine and column store.\n"
739  "It lets you write high-performance applications that requires "
740  "fulltext search.";
741 
742  width = 100;
743  max_results = 10;
744  snip = grn_expr_snip(&context, expr, flags,
745  width, max_results,
746  0,
747  NULL, NULL,
748  NULL, NULL,
749  NULL);
750  cut_assert_not_null(snip);
751 
752  grn_test_assert(grn_snip_exec(&context, snip, text, strlen(text),
753  &n_results, &max_tagged_len));
754 
755  cut_assert_equal_uint(2, n_results);
756  cut_assert_equal_uint(101, max_tagged_len);
757  result = g_new(gchar, max_tagged_len);
758  cut_take_memory(result);
759 
760  grn_test_assert(grn_snip_get_result(&context, snip, 0, result, &result_len));
761  cut_assert_equal_string("groonga is an open-source fulltext "
762  "search engine and column store.\n"
763  "It lets you write high-performanc",
764  result);
765  cut_assert_equal_uint(100, result_len);
766 
767  grn_test_assert(grn_snip_get_result(&context, snip, 1, result, &result_len));
768  cut_assert_equal_string("e applications that requires "
769  "fulltext search.",
770  result);
771  cut_assert_equal_uint(45, result_len);
772 
773  grn_test_assert(grn_snip_close(&context, snip));
774  }
775 }
776 
777 static grn_obj *
778 parse_numeric_literal(const char *str_expr)
779 {
780  grn_obj *expr;
781  grn_obj *var;
782 
783  expr = grn_expr_create(&context, NULL, 0);
784  cut_assert_not_null(expr);
785  var = grn_expr_add_var(&context, expr, "var", strlen("var"));
786  cut_assert_not_null(var);
787 
788  GRN_FLOAT_INIT(var, 0);
789  grn_test_assert(grn_expr_parse(&context, expr, str_expr, strlen(str_expr),
790  NULL, GRN_OP_NOP, GRN_OP_NOP,
793 
794  grn_test_assert(grn_expr_compile(&context, expr));
795  grn_expr_exec(&context, expr, 0);
796  grn_test_assert(context.rc);
797 
798  return var;
799 }
800 
801 void
803 {
804  grn_obj *var;
805  const char *str_expr = "var = 3.14159265";
806 
807  var = parse_numeric_literal(str_expr);
808  cut_assert_equal_int(GRN_DB_FLOAT, GRN_OBJ_GET_DOMAIN(var));
809  cut_assert_equal_double(3.14159265, 0.00000001, GRN_FLOAT_VALUE(var));
810 }
811 
812 void
814 {
815  grn_obj *var;
816  const char *str_expr = "var = 123456";
817 
818  var = parse_numeric_literal(str_expr);
819  cut_assert_equal_int(GRN_DB_UINT32, GRN_OBJ_GET_DOMAIN(var));
820  cut_assert_equal_int(123456, GRN_UINT32_VALUE(var));
821 }
822 
823 void
825 {
826  grn_obj *var;
827  const char *str_expr = "var = 3456789012";
828 
829  var = parse_numeric_literal(str_expr);
830  cut_assert_equal_int(GRN_DB_UINT32, GRN_OBJ_GET_DOMAIN(var));
831  cut_assert_equal_int(3456789012U, GRN_UINT32_VALUE(var));
832 }
833 
834 void
836 {
837  grn_obj *var;
838  const char *str_expr = "var = 123456789012";
839 
840  var = parse_numeric_literal(str_expr);
841  cut_assert_equal_int(GRN_DB_INT64, GRN_OBJ_GET_DOMAIN(var));
842  cut_assert_equal_int_least64(G_GINT64_CONSTANT(123456789012),
843  GRN_INT64_VALUE(var));
844 }
845 
846 void
848 {
849  grn_obj *var;
850  const char *str_expr = "var = 12345678901234567890";
851 
852  var = parse_numeric_literal(str_expr);
853  cut_assert_equal_int(GRN_DB_FLOAT, GRN_OBJ_GET_DOMAIN(var));
854  /* IEEE 754 says "double" can presisely hold about 16 digits.
855  To be safe, assume only 15 digits are preserved. */
856  cut_assert_equal_double(12345678901234567890., 100000., GRN_FLOAT_VALUE(var));
857 }
858 
859 void
861 {
862  grn_obj *v;
863 
864  prepare_data();
865 
866  GRN_EXPR_CREATE_FOR_QUERY(&context, docs, cond, v);
867  cut_assert_not_null(cond);
868  cut_assert_not_null(v);
869  PARSE(cond, "author == \"morita\"", GRN_EXPR_SYNTAX_SCRIPT);
870  grn_test_assert_expr(&context,
871  "noname($1:0){2author GET_VALUE,0\"morita\",0EQUAL}",
872  cond);
873 }