Groonga 3.0.9 Source Code Document
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
test-table.c
Go to the documentation of this file.
1 /* -*- c-basic-offset: 2; coding: utf-8 -*- */
2 /*
3  Copyright (C) 2009-2012 Kouhei Sutou <kou@clear-code.com>
4 
5  This library is free software; you can redistribute it and/or
6  modify it under the terms of the GNU Lesser General Public
7  License version 2.1 as published by the Free Software Foundation.
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 <groonga.h>
20 
21 #include <gcutter.h>
22 #include <glib/gstdio.h>
23 
24 #include "../lib/grn-assertions.h"
25 
26 void test_array_set_data(void);
28 void test_temporary_table_no_path(gpointer data);
30 void test_temporary_table_default_tokenizer(gpointer data);
31 void data_temporary_table_add(void);
32 void test_temporary_table_add(gpointer data);
33 void data_array_sort(void);
34 void test_array_sort(gpointer data);
35 void test_nonexistent_column(void);
37 void test_create_with_valid_name(gpointer data);
39 void test_create_with_invalid_name(gpointer data);
40 void data_truncate_anonymous(void);
41 void test_truncate_anonymous(gconstpointer data);
42 void data_truncate_named(void);
43 void test_truncate_named(gconstpointer data);
44 
45 static gchar *tmp_directory;
46 
47 static grn_logger_info *logger;
48 static grn_ctx *context;
49 static grn_obj *database, *table, *column, buffer;
50 
51 void
53 {
54  tmp_directory = g_build_filename(grn_test_get_tmp_dir(),
55  "test-database",
56  NULL);
57 }
58 
59 void
61 {
62  g_free(tmp_directory);
63 }
64 
65 static void
66 remove_tmp_directory(void)
67 {
68  cut_remove_path(tmp_directory, NULL);
69 }
70 
71 void
72 cut_setup(void)
73 {
74  remove_tmp_directory();
75  g_mkdir_with_parents(tmp_directory, 0700);
76 
77  context = NULL;
78  logger = setup_grn_logger();
79 
80  context = g_new0(grn_ctx, 1);
81  grn_ctx_init(context, 0);
82 
83  database = grn_db_create(context,
84  cut_build_path(tmp_directory, "table.db", NULL),
85  NULL);
86 
87  table = NULL;
88  column = NULL;
89  GRN_VOID_INIT(&buffer);
90 }
91 
92 void
94 {
95  grn_obj_unlink(context, &buffer);
96  if (column) {
97  grn_obj_unlink(context, column);
98  }
99  if (table) {
100  grn_obj_unlink(context, table);
101  }
102 
103  grn_obj_close(context, database);
104  grn_ctx_fin(context);
105  g_free(context);
106 
107  teardown_grn_logger(logger);
108  cut_remove_path(tmp_directory, NULL);
109 }
110 
111 void
113 {
114  grn_obj *table;
115  grn_id record_id;
116  gchar value[] = "sample value";
117  grn_obj *record_value;
118  grn_obj *retrieved_record_value;
119  const gchar *dupped_retrieved_record_value;
120  const gchar *value_type_name = "value_type";
121  grn_obj *value_type;
122 
123  value_type = grn_type_create(context,
124  value_type_name, strlen(value_type_name),
125  0, sizeof(value));
126  table = grn_table_create(context, NULL, 0, NULL,
128  NULL, value_type);
129  record_id = grn_table_add(context, table, NULL, 0, NULL);
130 
131  record_value = grn_obj_open(context, GRN_BULK, 0, GRN_DB_TEXT);
132  grn_bulk_write(context, record_value, value, sizeof(value));
133  grn_test_assert(grn_obj_set_value(context, table, record_id,
134  record_value, GRN_OBJ_SET));
135  grn_obj_unlink(context, record_value);
136 
137  retrieved_record_value = grn_obj_get_value(context, table, record_id, NULL);
138  dupped_retrieved_record_value =
139  cut_take_strdup(GRN_BULK_HEAD(retrieved_record_value));
140  grn_obj_unlink(context, retrieved_record_value);
141  cut_assert_equal_string(value, dupped_retrieved_record_value);
142 }
143 
144 void
146 {
147 #define ADD_DATA(label, flags) \
148  cut_add_data(label, GINT_TO_POINTER(flags), NULL, NULL)
149 
150  ADD_DATA("no-key", GRN_OBJ_TABLE_NO_KEY);
152  ADD_DATA("patricia trie", GRN_OBJ_TABLE_PAT_KEY);
153 
154 #undef ADD_DATA
155 }
156 
157 void
159 {
160  grn_obj *table;
161  grn_obj_flags flags = GPOINTER_TO_INT(data);
162 
163  table = grn_table_create(context, NULL, 0, NULL,
164  flags,
165  NULL, NULL);
166  cut_assert_equal_string(NULL, grn_obj_path(context, table));
167 }
168 
169 void
171 {
172 #define ADD_DATA(label, flags) \
173  cut_add_data(label, GINT_TO_POINTER(flags), NULL, NULL)
174 
176  ADD_DATA("patricia trie", GRN_OBJ_TABLE_PAT_KEY);
177 
178 #undef ADD_DATA
179 }
180 
181 void
183 {
184  grn_obj *table;
185  grn_obj_flags flags = GPOINTER_TO_INT(data);
186  grn_obj *tokenizer = NULL;
187  char name[1024];
188  int name_size;
189 
190  table = grn_table_create(context, NULL, 0, NULL,
191  flags,
192  NULL, NULL);
194  get_object("TokenTrigram"));
195  tokenizer = grn_obj_get_info(context, table, GRN_INFO_DEFAULT_TOKENIZER, NULL);
196  name_size = grn_obj_name(context, tokenizer, name, sizeof(name));
197  name[name_size] = '\0';
198  cut_assert_equal_string("TokenTrigram", name);
199 }
200 
201 void
203 {
204 #define ADD_DATA(label, flags) \
205  cut_add_data(label, GINT_TO_POINTER(flags), NULL, NULL)
206 
207  ADD_DATA("no-key", GRN_OBJ_TABLE_NO_KEY);
209  ADD_DATA("patricia trie", GRN_OBJ_TABLE_PAT_KEY);
210 
211 #undef ADD_DATA
212 }
213 
214 void
216 {
217  grn_obj *table;
218  grn_obj_flags flags = GPOINTER_TO_INT(data);
219  gchar key[] = "key";
220 
222  table = grn_table_create(context, NULL, 0, NULL,
223  flags,
224  NULL,
225  NULL);
226  grn_table_add(context, table, NULL, 0, NULL);
227  } else {
228  table = grn_table_create(context, NULL, 0, NULL,
229  flags,
230  get_object("ShortText"),
231  NULL);
232  grn_table_add(context, table, key, strlen(key), NULL);
233  }
234 
235  cut_assert_equal_int(1, grn_table_size(context, table));
236 }
237 
238 static GList *make_glist_from_array(const gint *value, guint length)
239 {
240  GList *list = NULL;
241  guint i;
242  for (i = 0; i < length; ++i)
243  list = g_list_prepend(list, GINT_TO_POINTER(value[i]));
244 
245  return g_list_reverse(list);
246 }
247 
248 void
250 {
251 #define ADD_DATUM(label, offset, limit, expected_values, n_expected_values) \
252  gcut_add_datum(label, \
253  "offset", G_TYPE_INT, offset, \
254  "limit", G_TYPE_INT, limit, \
255  "expected_values", G_TYPE_POINTER, \
256  make_glist_from_array(expected_values, n_expected_values),\
257  g_list_free, \
258  NULL)
259 
260  const gint32 sorted_values[] = {
261  0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19
262  };
263 
264  ADD_DATUM("no offset, no limit", 0, -1, &sorted_values[0], 20);
265  ADD_DATUM("offset", 10, -1, &sorted_values[10], 10);
266  ADD_DATUM("limit", 0, 10, &sorted_values[0], 10);
267  ADD_DATUM("offset, limit", 5, 10, &sorted_values[5], 10);
268 
269 #undef ADD_DATUM
270 }
271 
272 void
273 test_array_sort(gpointer data)
274 {
275  const gint32 values[] = {
276  5, 6, 18, 9, 0, 4, 13, 12, 8, 14, 19, 11, 7, 3, 1, 10, 15, 2, 17, 16
277  };
278  const int n_values = sizeof(values) / sizeof(values[0]);
279  const gchar table_name[] = "Store";
280  const gchar column_name[] = "sample_column";
281  const int n_keys = 1;
282  grn_table_sort_key keys[n_keys];
283 
284  grn_obj *table, *column, *result;
285  grn_table_cursor *cursor;
286  int n_results;
287  guint i;
288 
289  guint n_expected_values;
290  GList *expected_values, *sorted_values = NULL;
291 
292  table = grn_table_create(context, table_name, strlen(table_name),
293  NULL,
295  NULL,
296  NULL);
297  column = grn_column_create(context,
298  table,
299  column_name,
300  strlen(column_name),
301  NULL, 0,
302  get_object("Int32"));
303 
304  keys[0].key = column;
305  keys[0].flags = GRN_TABLE_SORT_ASC;
306 
307  for(i = 0; i < n_values; ++i) {
308  grn_obj record_value;
309  grn_id record_id;
310  record_id = grn_table_add(context, table, NULL, 0, NULL);
311 
312  GRN_INT32_INIT(&record_value, 0);
313  GRN_INT32_SET(context, &record_value, values[i]);
314  grn_test_assert(grn_obj_set_value(context, column, record_id,
315  &record_value, GRN_OBJ_SET));
316  GRN_OBJ_FIN(context, &record_value);
317  }
318  cut_assert_equal_int(n_values, grn_table_size(context, table));
319 
320  result = grn_table_create(context, NULL, 0, NULL, GRN_TABLE_NO_KEY,
321  NULL, table);
322  n_results = grn_table_sort(context, table,
323  gcut_data_get_int(data, "offset"),
324  gcut_data_get_int(data, "limit"),
325  result, keys, n_keys);
326  expected_values = (GList *)gcut_data_get_pointer(data, "expected_values");
327  n_expected_values = g_list_length(expected_values);
328  cut_assert_equal_int(n_expected_values, n_results);
329  cut_assert_equal_int(n_expected_values, grn_table_size(context, result));
330 
331  cursor = grn_table_cursor_open(context, result, NULL, 0, NULL, 0,
332  0, -1, GRN_CURSOR_ASCENDING);
333  while (grn_table_cursor_next(context, cursor) != GRN_ID_NIL) {
334  void *value;
335  grn_id *id;
336  grn_obj record_value;
337 
338  grn_table_cursor_get_value(context, cursor, &value);
339  id = value;
340 
341  GRN_INT32_INIT(&record_value, 0);
342  grn_obj_get_value(context, column, *id, &record_value);
343  sorted_values = g_list_append(sorted_values,
344  GINT_TO_POINTER(GRN_INT32_VALUE(&record_value)));
345  GRN_OBJ_FIN(context, &record_value);
346  }
347  gcut_take_list(sorted_values, NULL);
348  gcut_assert_equal_list_int(expected_values, sorted_values);
349 
350  grn_table_cursor_close(context, cursor);
351  grn_obj_close(context, result);
352 }
353 
354 void
356 {
357  grn_obj *table;
358  char table_name[] = "users";
359  char nonexistent_column_name[] = "nonexistent";
360 
361  table = grn_table_create(context, table_name, strlen(table_name),
362  NULL,
364  NULL, NULL);
365  grn_test_assert_null(context,
366  grn_obj_column(context, table,
367  nonexistent_column_name,
368  strlen(nonexistent_column_name)));
369 }
370 
371 void
373 {
374 #define ADD_DATUM(label, name) \
375  gcut_add_datum(label, \
376  "name", G_TYPE_STRING, name, \
377  NULL)
378 
379  ADD_DATUM("start with number", "0table");
380  ADD_DATUM("include '-'", "table-name");
381 
382 #define ADD_DATUM_VALID_CHARACTER(name) \
383  ADD_DATUM(name, name)
384 
388 
389 #undef ADD_DATUM_INVALID_CHARACTER
390 
391 #undef ADD_DATUM
392 }
393 
394 void
396 {
397  grn_obj *table;
398  const gchar *table_name;
399 
400  table_name = gcut_data_get_string(data, "name");
401  table = grn_table_create(context, table_name, strlen(table_name),
402  NULL,
404  NULL, NULL);
405  grn_test_assert_context(context);
406 }
407 
408 void
410 {
411 #define ADD_DATUM(label, name) \
412  gcut_add_datum(label, \
413  "name", G_TYPE_STRING, name, \
414  NULL)
415 
416  ADD_DATUM("start with '_'", "_users");
417  ADD_DATUM("include a space", "table name");
418  ADD_DATUM("space", " ");
419 
420 #define ADD_DATUM_INVALID_CHARACTER(name) \
421  ADD_DATUM(name, name)
422 
452 
453 #undef ADD_DATUM_INVALID_CHARACTER
454 
455 #undef ADD_DATUM
456 }
457 
458 void
460 {
461  grn_obj *table;
462  const gchar *table_name;
463 
464  table_name = gcut_data_get_string(data, "name");
465  table = grn_table_create(context, table_name, strlen(table_name),
466  NULL,
468  NULL, NULL);
471  cut_take_printf("[table][create] name can't start with '_' and "
472  "contains only 0-9, A-Z, a-z, #, @, - or _: <%s>",
473  table_name),
474  context);
475 }
476 
477 void
479 {
480 #define ADD_DATA(label, flags) \
481  gcut_add_datum(label, \
482  "flags", G_TYPE_INT, flags, \
483  NULL)
484 
485  ADD_DATA("array", GRN_OBJ_TABLE_NO_KEY);
487  ADD_DATA("patricia trie", GRN_OBJ_TABLE_PAT_KEY);
488 
489 #undef ADD_DATA
490 }
491 
492 void
493 test_truncate_anonymous(gconstpointer data)
494 {
495  grn_obj_flags flags;
496  const gchar *key;
497  grn_obj *key_type;
498  unsigned key_size;
499  grn_bool array_p;
500  int added;
501 
502  flags = gcut_data_get_int(data, "flags");
503  array_p = ((flags & GRN_OBJ_TABLE_TYPE_MASK) == GRN_OBJ_TABLE_NO_KEY);
504 
505  if (array_p) {
506  key = NULL;
507  key_size = 0;
508  key_type = NULL;
509  } else {
510  key = "groonga";
511  key_size = strlen(key);
512  key_type = grn_ctx_at(context, GRN_DB_SHORT_TEXT);
513  }
514  table = grn_table_create(context,
515  NULL, 0, NULL,
516  flags,
517  key_type, NULL);
518  if (key_type) {
519  grn_obj_unlink(context, key_type);
520  }
521 
522  grn_test_assert_not_nil(grn_table_add(context, table, key, key_size, &added));
523  cut_assert_true(added);
524 
525  cut_assert_equal_uint(1, grn_table_size(context, table));
526  grn_test_assert(grn_table_truncate(context, table));
527  cut_assert_equal_uint(0, grn_table_size(context, table));
528 }
529 
530 void
532 {
533 #define ADD_DATA(label, flags) \
534  gcut_add_datum(label, \
535  "flags", G_TYPE_INT, flags, \
536  NULL)
537 
538  ADD_DATA("array", GRN_OBJ_TABLE_NO_KEY);
540  ADD_DATA("patricia trie", GRN_OBJ_TABLE_PAT_KEY);
541 
542 #undef ADD_DATA
543 }
544 
545 void
546 test_truncate_named(gconstpointer data)
547 {
548  grn_obj_flags flags;
549  const gchar *table_name = "SearchEngines";
550  const gchar *key;
551  grn_obj *key_type;
552  unsigned key_size;
553  const gchar *column_name = "description";
554  grn_obj *column_type;
555  const gchar *column_value = "An open-source fulltext search engine";
556  grn_bool array_p;
557  grn_id record_id;
558  int added;
559 
560  flags = gcut_data_get_int(data, "flags");
561  array_p = ((flags & GRN_OBJ_TABLE_TYPE_MASK) == GRN_OBJ_TABLE_NO_KEY);
562 
563  if (array_p) {
564  key = NULL;
565  key_size = 0;
566  key_type = NULL;
567  } else {
568  key = "groonga";
569  key_size = strlen(key);
570  key_type = grn_ctx_at(context, GRN_DB_SHORT_TEXT);
571  }
572  table = grn_table_create(context,
573  table_name, strlen(table_name), NULL,
574  flags | GRN_OBJ_PERSISTENT,
575  key_type, NULL);
576  if (key_type) {
577  grn_obj_unlink(context, key_type);
578  }
579  grn_test_assert_context(context);
580 
581  column_type = grn_ctx_at(context, GRN_DB_SHORT_TEXT);
582  column = grn_column_create(context, table, column_name, strlen(column_name),
583  NULL,
585  column_type);
586  grn_obj_unlink(context, column_type);
587  grn_test_assert_context(context);
588 
589  record_id = grn_table_add(context, table, key, key_size, &added);
590  grn_test_assert_not_nil(record_id);
591  cut_assert_true(added);
592 
593  grn_obj_reinit(context, &buffer, GRN_DB_SHORT_TEXT, 0);
594  GRN_TEXT_PUTS(context, &buffer, column_value);
595  grn_test_assert(grn_obj_set_value(context, column, record_id,
596  &buffer, GRN_OBJ_SET));
597 
598  GRN_BULK_REWIND(&buffer);
599  grn_obj_get_value(context, column, record_id, &buffer);
600  GRN_TEXT_PUTC(context, &buffer, '\0');
601  cut_assert_equal_string(column_value, GRN_TEXT_VALUE(&buffer));
602  cut_assert_equal_uint(1, grn_table_size(context, table));
603 
604  grn_test_assert(grn_table_truncate(context, table));
605 
606  GRN_BULK_REWIND(&buffer);
607  grn_obj_get_value(context, column, record_id, &buffer);
608  GRN_TEXT_PUTC(context, &buffer, '\0');
609  cut_assert_equal_string("", GRN_TEXT_VALUE(&buffer));
610  cut_assert_equal_uint(0, grn_table_size(context, table));
611 }