Groonga 3.0.9 Source Code Document
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
test-expr.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 *expr;
31 static grn_obj text_buf, int_buf, ptr_buf;
32 
33 void test_accessor(void);
34 void test_expr(void);
35 void test_persistent_expr(void);
36 void test_expr_query(void);
37 
38 void
40 {
41  tmp_directory = g_build_filename(grn_test_get_tmp_dir(),
42  "test-expr",
43  NULL);
44 }
45 
46 void
48 {
49  g_free(tmp_directory);
50 }
51 
52 void
53 cut_setup(void)
54 {
55  cut_remove_path(tmp_directory, NULL);
56  g_mkdir_with_parents(tmp_directory, 0700);
57  path = g_build_filename(tmp_directory, "text-expr", NULL);
58  context = g_new0(grn_ctx, 1);
59  grn_ctx_init(context, 0);
60  database = grn_db_create(context, path, NULL);
61 
62  expr = NULL;
63 
64  GRN_TEXT_INIT(&text_buf, 0);
65  GRN_UINT32_INIT(&int_buf, 0);
66  GRN_PTR_INIT(&ptr_buf, 0, GRN_ID_NIL);
67 }
68 
69 void
71 {
72  grn_obj_close(context, &text_buf);
73  grn_obj_close(context, &int_buf);
74  grn_obj_close(context, &ptr_buf);
75 
76  if (expr)
77  grn_obj_close(context, expr);
78 
79  grn_db_close(context, database);
80  grn_ctx_fin(context);
81  g_free(context);
82 
83  cut_remove_path(tmp_directory, NULL);
84  g_free(path);
85 }
86 
87 #define NRECORDS 1000000
88 
89 void
91 {
92  int i;
93  grn_obj *t1, *t2, *c1, *c2, r1, r2;
94  t1 = grn_table_create(context, "t1", 2, NULL,
96  cut_assert_not_null(t1);
97  t2 = grn_table_create(context, "t2", 2, NULL,
99  cut_assert_not_null(t2);
100  c1 = grn_column_create(context, t1, "c1", 2, NULL,
101  GRN_OBJ_PERSISTENT, t2);
102  cut_assert_not_null(c1);
103  c2 = grn_column_create(context, t2, "c2", 2, NULL,
104  GRN_OBJ_PERSISTENT, t1);
105  cut_assert_not_null(c2);
106  GRN_RECORD_INIT(&r1, 0, grn_obj_id(context, t1));
107  GRN_RECORD_INIT(&r2, 0, grn_obj_id(context, t2));
108  for (i = 0; i < NRECORDS; i++) {
109  grn_id i1, i2;
110  i1 = grn_table_add(context, t1, NULL, 0, NULL);
111  i2 = grn_table_add(context, t2, NULL, 0, NULL);
112  GRN_RECORD_SET(context, &r1, i1);
113  GRN_RECORD_SET(context, &r2, i2);
114  grn_obj_set_value(context, c1, i1, &r2, GRN_OBJ_SET);
115  grn_obj_set_value(context, c2, i2, &r1, GRN_OBJ_SET);
116  }
117  {
118  grn_id id;
119  uint64_t et;
120  int nerr = 0;
121  struct timeval tvb, tve;
122  grn_obj *a = grn_obj_column(context, t1, "c1.c2.c1", 8);
123  grn_table_cursor *tc = grn_table_cursor_open(context, t1, NULL, 0, NULL, 0, 0, -1, 0);
124  cut_assert_not_null(a);
125  cut_assert_not_null(tc);
126  gettimeofday(&tvb, NULL);
127  while ((id = grn_table_cursor_next(context, tc))) {
128  GRN_BULK_REWIND(&r2);
129  grn_obj_get_value(context, a, id, &r2);
130  if (GRN_RECORD_VALUE(&r2) != id) { nerr++; }
131  }
132  gettimeofday(&tve, NULL);
133  et = (tve.tv_sec - tvb.tv_sec) * 1000000 + (tve.tv_usec - tvb.tv_usec);
134  // printf("et=%zu\n", et);
135  cut_assert_equal_uint(0, nerr);
137  grn_test_assert(grn_obj_close(context, a));
138  }
139  grn_test_assert(grn_obj_close(context, &r1));
140  grn_test_assert(grn_obj_close(context, &r2));
141 }
142 
143 void
145 {
146  int i;
147  grn_obj *t1, *t2, *c1, *c2, r1, r2, buf;
148  t1 = grn_table_create(context, "t1", 2, NULL,
150  cut_assert_not_null(t1);
151  t2 = grn_table_create(context, "t2", 2, NULL,
153  cut_assert_not_null(t2);
154  c1 = grn_column_create(context, t1, "c1", 2, NULL,
155  GRN_OBJ_PERSISTENT, t2);
156  cut_assert_not_null(c1);
157  c2 = grn_column_create(context, t2, "c2", 2, NULL,
158  GRN_OBJ_PERSISTENT, t1);
159  cut_assert_not_null(c2);
160  GRN_TEXT_INIT(&buf, 0);
161  GRN_RECORD_INIT(&r1, 0, grn_obj_id(context, t1));
162  GRN_RECORD_INIT(&r2, 0, grn_obj_id(context, t2));
163  for (i = 0; i < NRECORDS; i++) {
164  grn_id i1, i2;
165  i1 = grn_table_add(context, t1, NULL, 0, NULL);
166  i2 = grn_table_add(context, t2, NULL, 0, NULL);
167  GRN_RECORD_SET(context, &r1, i1);
168  GRN_RECORD_SET(context, &r2, i2);
169  grn_obj_set_value(context, c1, i1, &r2, GRN_OBJ_SET);
170  grn_obj_set_value(context, c2, i2, &r1, GRN_OBJ_SET);
171  }
172  {
173  grn_obj *r, *v;
174 
175  expr = grn_expr_create(context, NULL, 0);
176  cut_assert_not_null(expr);
177  v = grn_expr_add_var(context, expr, NULL, 0);
178  GRN_RECORD_INIT(v, 0, grn_obj_id(context, t1));
179  grn_expr_append_obj(context, expr, v, GRN_OP_PUSH, 1);
180 
181  GRN_TEXT_SETS(context, &buf, "c1");
182  grn_expr_append_const(context, expr, &buf, GRN_OP_PUSH, 1);
183  grn_expr_append_op(context, expr, GRN_OP_GET_VALUE, 2);
184  GRN_TEXT_SETS(context, &buf, "c2");
185  grn_expr_append_const(context, expr, &buf, GRN_OP_PUSH, 1);
186  grn_expr_append_op(context, expr, GRN_OP_GET_VALUE, 2);
187  GRN_TEXT_SETS(context, &buf, "c1");
188  grn_expr_append_const(context, expr, &buf, GRN_OP_PUSH, 1);
189 
190 
191 // GRN_TEXT_SETS(context, &buf, "c1.c2.c1");
192 // grn_expr_append_const(context, expr, &buf);
193 
194  grn_expr_append_op(context, expr, GRN_OP_GET_VALUE, 2);
195  grn_expr_compile(context, expr);
196  {
197  grn_id id;
198  uint64_t et;
199  int nerr = 0;
200  grn_table_cursor *tc;
201  struct timeval tvb, tve;
202  tc = grn_table_cursor_open(context, t1, NULL, 0, NULL, 0, 0, -1, 0);
203  cut_assert_not_null(tc);
204  gettimeofday(&tvb, NULL);
205  while ((id = grn_table_cursor_next(context, tc))) {
206  GRN_RECORD_SET(context, v, id);
207  r = grn_expr_exec(context, expr, 0);
208  if (GRN_RECORD_VALUE(r) != id) { nerr++; }
209  }
210  gettimeofday(&tve, NULL);
211  et = (tve.tv_sec - tvb.tv_sec) * 1000000 + (tve.tv_usec - tvb.tv_usec);
212  // printf("et=%zu\n", et);
213  cut_assert_equal_uint(0, nerr);
215  }
216  }
217  grn_test_assert(grn_obj_close(context, &r1));
218  grn_test_assert(grn_obj_close(context, &r2));
219  grn_test_assert(grn_obj_close(context, &buf));
220 }
221 
222 #ifdef ENABLE_PERSISTENT_EXPR
223 void
225 {
226  int i;
227  grn_obj *t1, *t2, *c1, *c2, r1, r2, buf;
228  t1 = grn_table_create(context, "t1", 2, NULL,
230  cut_assert_not_null(t1);
231  t2 = grn_table_create(context, "t2", 2, NULL,
233  cut_assert_not_null(t2);
234  c1 = grn_column_create(context, t1, "c1", 2, NULL,
235  GRN_OBJ_PERSISTENT, t2);
236  cut_assert_not_null(c1);
237  c2 = grn_column_create(context, t2, "c2", 2, NULL,
238  GRN_OBJ_PERSISTENT, t1);
239  cut_assert_not_null(c2);
240  GRN_TEXT_INIT(&buf, 0);
241  GRN_RECORD_INIT(&r1, 0, grn_obj_id(context, t1));
242  GRN_RECORD_INIT(&r2, 0, grn_obj_id(context, t2));
243  for (i = 0; i < NRECORDS; i++) {
244  grn_id i1, i2;
245  i1 = grn_table_add(context, t1, NULL, 0, NULL);
246  i2 = grn_table_add(context, t2, NULL, 0, NULL);
247  GRN_RECORD_SET(context, &r1, i1);
248  GRN_RECORD_SET(context, &r2, i2);
249  grn_obj_set_value(context, c1, i1, &r2, GRN_OBJ_SET);
250  grn_obj_set_value(context, c2, i2, &r1, GRN_OBJ_SET);
251  }
252  {
253  grn_obj *v;
254  expr = grn_expr_create(context, "test", 4);
255  cut_assert_not_null(expr);
256  v = grn_expr_add_var(context, expr, "foo", 3);
257  GRN_RECORD_INIT(v, 0, grn_obj_id(context, t1));
258  grn_expr_append_obj(context, expr, v, GRN_OP_PUSH, 1);
259 
260  GRN_TEXT_SETS(context, &buf, "c1");
261  grn_expr_append_const(context, expr, &buf, GRN_OP_PUSH, 1);
262  grn_expr_append_op(context, expr, GRN_OP_GET_VALUE, 2);
263  GRN_TEXT_SETS(context, &buf, "c2");
264  grn_expr_append_const(context, expr, &buf, GRN_OP_PUSH, 1);
265  grn_expr_append_op(context, expr, GRN_OP_GET_VALUE, 2);
266  GRN_TEXT_SETS(context, &buf, "c1");
267  grn_expr_append_const(context, expr, &buf, GRN_OP_PUSH, 1);
268 
269  /*
270  GRN_TEXT_SETS(context, &buf, "c1.c2.c1");
271  grn_expr_append_const(context, expr, &buf);
272  */
273 
274  grn_expr_append_op(context, expr, GRN_OP_GET_VALUE, 2);
275  grn_expr_compile(context, expr);
276  grn_test_assert(grn_obj_close(context, expr));
277  expr = NULL;
278  }
279  grn_test_assert(grn_obj_close(context, &buf));
280 
281  grn_db_close(context, database);
282  database = grn_db_open(context, path);
283 
284  {
285  grn_id id;
286  uint64_t et;
287  int nerr = 0;
288  grn_obj *r, *v;
289  grn_table_cursor *tc;
290  struct timeval tvb, tve;
291  expr = get_object("test");
292  v = grn_expr_get_var(context, expr, "foo", 3);
293  t1 = get_object("t1");
294  tc = grn_table_cursor_open(context, t1, NULL, 0, NULL, 0, 0, -1, 0);
295  cut_assert_not_null(tc);
296  gettimeofday(&tvb, NULL);
297  while ((id = grn_table_cursor_next(context, tc))) {
298  GRN_RECORD_SET(context, v, id);
299  r = grn_expr_exec(context, expr, 0);
300  if (GRN_RECORD_VALUE(r) != id) { nerr++; }
301  }
302  gettimeofday(&tve, NULL);
303  et = (tve.tv_sec - tvb.tv_sec) * 1000000 + (tve.tv_usec - tvb.tv_usec);
304  // printf("et=%zu\n", et);
305  cut_assert_equal_uint(0, nerr);
307  }
308  grn_test_assert(grn_obj_close(context, &r1));
309  grn_test_assert(grn_obj_close(context, &r2));
310 }
311 #endif /* ENABLE_PERSISTENT_EXPR */
312 
313 void
315 {
316  grn_obj *t1, *c1, *lc, *ft, *v;
317  grn_id r1, r2, r3, r4;
318 
319  /* actual table */
320  t1 = grn_table_create(context, "t1", 2, NULL,
322  cut_assert_not_null(t1);
323 
324  /* lexicon table */
325  lc = grn_table_create(context, "lc", 2, NULL,
327  grn_ctx_at(context, GRN_DB_SHORT_TEXT), NULL);
328  cut_assert_not_null(lc);
330  grn_ctx_at(context, GRN_DB_BIGRAM)));
331 
332  /* actual column */
333  c1 = grn_column_create(context, t1, "c1", 2, NULL,
335  grn_ctx_at(context, GRN_DB_TEXT));
336  cut_assert_not_null(c1);
337 
338  /* fulltext index */
339  ft = grn_column_create(context, lc, "ft", 2, NULL,
341  cut_assert_not_null(ft);
342 
343  /* link between actual column and fulltext index */
344  GRN_UINT32_SET(context, &int_buf, grn_obj_id(context, c1));
345  grn_obj_set_info(context, ft, GRN_INFO_SOURCE, &int_buf); /* need to use grn_id */
346 
347  /* insert row */
348  r1 = grn_table_add(context, t1, NULL, 0, NULL);
349  cut_assert_equal_int(1, r1);
350  GRN_TEXT_SETS(context, &text_buf, "abhij");
351  grn_test_assert(grn_obj_set_value(context, c1, r1, &text_buf, GRN_OBJ_SET));
352 
353  r2 = grn_table_add(context, t1, NULL, 0, NULL);
354  cut_assert_equal_int(2, r2);
355  GRN_TEXT_SETS(context, &text_buf, "fghij");
356  grn_test_assert(grn_obj_set_value(context, c1, r2, &text_buf, GRN_OBJ_SET));
357 
358  r3 = grn_table_add(context, t1, NULL, 0, NULL);
359  cut_assert_equal_int(3, r3);
360  GRN_TEXT_SETS(context, &text_buf, "11 22 33");
361  grn_test_assert(grn_obj_set_value(context, c1, r3, &text_buf, GRN_OBJ_SET));
362 
363  r4 = grn_table_add(context, t1, NULL, 0, NULL);
364  cut_assert_equal_int(4, r4);
365  GRN_TEXT_SETS(context, &text_buf, "44 22 55");
366  grn_test_assert(grn_obj_set_value(context, c1, r4, &text_buf, GRN_OBJ_SET));
367 
368  /* confirm record are inserted in both column and index */
369  cut_assert_equal_int(4, grn_table_size(context, t1));
370  cut_assert_equal_int(20, grn_table_size(context, lc));
371 
372  cut_assert_not_null((expr = grn_expr_create(context, NULL, 0)));
373 
374  v = grn_expr_add_var(context, expr, NULL, 0);
375 
376  grn_expr_append_obj(context, expr, v, GRN_OP_PUSH, 1);
377 
378  GRN_BULK_REWIND(&text_buf);
379  grn_expr_append_const(context, expr, &text_buf, GRN_OP_PUSH, 1);
381  grn_expr_append_const(context, expr, &int_buf, GRN_OP_PUSH, 1);
382  grn_expr_append_obj(context, expr, t1, GRN_OP_PUSH, 1);
383  GRN_PTR_SET(context, &ptr_buf, NULL);
384  grn_expr_append_obj(context, expr, &ptr_buf, GRN_OP_PUSH, 1);
385  grn_expr_append_op(context, expr, GRN_OP_TABLE_CREATE, 4);
386 
387  grn_expr_append_op(context, expr, GRN_OP_ASSIGN, 2);
388 
389  grn_expr_append_obj(context, expr, ft, GRN_OP_PUSH, 1);
390  GRN_TEXT_SETS(context, &text_buf, "hij");
391  grn_expr_append_const(context, expr, &text_buf, GRN_OP_PUSH, 1);
392  grn_expr_append_obj(context, expr, v, GRN_OP_PUSH, 1);
393  GRN_UINT32_SET(context, &int_buf, GRN_OP_OR);
394  grn_expr_append_const(context, expr, &int_buf, GRN_OP_PUSH, 1);
395  grn_expr_append_op(context, expr, GRN_OP_OBJ_SEARCH, 4);
396 
397  grn_expr_append_obj(context, expr, v, GRN_OP_PUSH, 1);
398  GRN_TEXT_SETS(context, &text_buf, ".c1 ._score");
399  grn_expr_append_const(context, expr, &text_buf, GRN_OP_PUSH, 1);
400  GRN_BULK_REWIND(&text_buf);
401  grn_expr_append_obj(context, expr, &text_buf, GRN_OP_PUSH, 1);
402  grn_expr_append_op(context, expr, GRN_OP_JSON_PUT, 3);
403 
404  grn_expr_compile(context, expr);
405 
406  grn_expr_exec(context, expr, 0);
407 
408  cut_assert_equal_substring("[[2],[\"abhij\",1],[\"fghij\",1]]",
409  GRN_TEXT_VALUE(&text_buf), GRN_TEXT_LEN(&text_buf));
410 
411  grn_obj_close(context, ft);
412  grn_obj_close(context, c1);
413  grn_obj_close(context, lc);
414  grn_obj_close(context, t1);
415 }