Groonga 3.0.9 Source Code Document
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
test-table-sort-geo.c
Go to the documentation of this file.
1 /* -*- c-basic-offset: 2; coding: utf-8 -*- */
2 /*
3  Copyright (C) 2010-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 #include <db.h>
21 
22 #include <gcutter.h>
23 #include <glib/gstdio.h>
24 
25 #include "../lib/grn-assertions.h"
26 
27 #define COORDINATE(hours, minutes, seconds) \
28  ((hours) * 3600 + (minutes) * 60 + (seconds)) * 1000
29 
30 #define POINT(latitude_hours, latitude_minutes, latitude_seconds, \
31  longitude_hours, longitude_minutes, longitude_seconds) \
32  g_strdup_printf( \
33  "%dx%d", \
34  COORDINATE(latitude_hours, latitude_minutes, latitude_seconds), \
35  COORDINATE(longitude_hours, longitude_minutes, longitude_seconds))
36 
37 #define TAKEN_POINT(latitude_hours, latitude_minutes, latitude_seconds, \
38  longitude_hours, longitude_minutes, longitude_seconds) \
39  cut_take_string(POINT(latitude_hours, latitude_minutes, latitude_seconds, \
40  longitude_hours, longitude_minutes, longitude_seconds))
41 
42 #define INSPECTED_POINT(latitude_hours, latitude_minutes, latitude_seconds, \
43  longitude_hours, longitude_minutes, longitude_seconds) \
44  inspect_point( \
45  COORDINATE(latitude_hours, latitude_minutes, latitude_seconds), \
46  COORDINATE(longitude_hours, longitude_minutes, longitude_seconds))
47 
48 #define TAKEN_INSPECTED_POINT(latitude_hours, \
49  latitude_minutes, \
50  latitude_seconds, \
51  longitude_hours, \
52  longitude_minutes, \
53  longitude_seconds) \
54  cut_take_string(INSPECTED_POINT(latitude_hours, \
55  latitude_minutes, \
56  latitude_seconds, \
57  longitude_hours, \
58  longitude_minutes, \
59  longitude_seconds))
60 
61 void data_near_geo_point(void);
62 void test_near_geo_point(gpointer data);
63 
64 static gchar *tmp_directory;
65 
66 static grn_ctx *context;
67 static grn_obj *database, *table, *column, *result;
68 static grn_table_cursor *cursor;
69 
70 void
72 {
73  tmp_directory = g_build_filename(grn_test_get_tmp_dir(),
74  "table-patricia-trie-sort",
75  NULL);
76 }
77 
78 void
80 {
81  g_free(tmp_directory);
82 }
83 
84 static void
85 remove_tmp_directory(void)
86 {
87  cut_remove_path(tmp_directory, NULL);
88 }
89 
90 void
91 cut_setup(void)
92 {
93  const gchar *database_path;
94 
95  remove_tmp_directory();
96  g_mkdir_with_parents(tmp_directory, 0700);
97 
98  context = g_new0(grn_ctx, 1);
99  grn_ctx_init(context, 0);
100 
101  database_path = cut_build_path(tmp_directory, "database.groonga", NULL);
102  database = grn_db_create(context, database_path, NULL);
103  table = NULL;
104  column = NULL;
105  result = NULL;
106  cursor = NULL;
107 }
108 
109 void
111 {
112  if (cursor) {
113  grn_obj_unlink(context, cursor);
114  }
115 
116  if (result) {
117  grn_obj_unlink(context, result);
118  }
119 
120  if (column) {
121  grn_obj_unlink(context, column);
122  }
123 
124  if (table) {
125  grn_obj_unlink(context, table);
126  }
127 
128  grn_obj_close(context, database);
129  grn_ctx_fin(context);
130  g_free(context);
131 
132  remove_tmp_directory();
133 }
134 
135 static void
136 create_geo_table(const gchar *load_data)
137 {
138  const char *table_name = "Data";
139  const char *column_name = "location";
140 
142  cut_take_printf("table_create %s TABLE_NO_KEY", table_name));
144  cut_take_printf("column_create %s %s COLUMN_SCALAR WGS84GeoPoint",
145  table_name, column_name));
146  assert_send_commands("table_create Index TABLE_PAT_KEY WGS84GeoPoint");
148  cut_take_printf("column_create Index %s_%s COLUMN_INDEX %s %s",
149  table_name, column_name,
150  table_name, column_name));
152  cut_take_printf("load --table %s\n"
153  "[\n"
154  " [\"%s\"],\n"
155  "%s\n"
156  "]",
157  table_name,
158  column_name,
159  load_data));
160 
161  table = grn_ctx_get(context, table_name, strlen(table_name));
162  column = grn_obj_column(context, table, column_name, strlen(column_name));
163 }
164 
165 static gchar *
166 inspect_point (gint latitude, gint longitude)
167 {
168  return g_strdup_printf("((%d, %d, %d), (%d, %d, %d))",
169  latitude / 1000 / 3600 % 3600,
170  latitude / 1000 / 60 % 60,
171  latitude / 1000 % 60,
172  longitude / 1000 / 3600 % 3600,
173  longitude / 1000 / 60 % 60,
174  longitude / 1000 % 60);
175 }
176 
177 void
179 {
180 #define ADD_DATA(label, expected, base, offset, limit) \
181  gcut_add_datum(label, \
182  "expected", G_TYPE_POINTER, \
183  expected, g_list_free, \
184  "base", G_TYPE_INT, base, \
185  "offset", G_TYPE_INT, offset, \
186  "limit", G_TYPE_INT, limit, \
187  NULL)
188 
189  ADD_DATA("no limit",
190  gcut_list_string_new(TAKEN_INSPECTED_POINT(-1, -1, -1,
191  0, 0, 0),
192  TAKEN_INSPECTED_POINT(1, 0, 0,
193  1, 0, 0),
194  TAKEN_INSPECTED_POINT(-1, 0, 0,
195  1, 1, 1),
196  TAKEN_INSPECTED_POINT(1, 1, 0,
197  1, 1, 0),
198  TAKEN_INSPECTED_POINT(1, 1, 1,
199  1, 1, 1),
200  TAKEN_INSPECTED_POINT(1, 1, 10,
201  -1, -1, -1),
202  TAKEN_INSPECTED_POINT(-1, -2, -1,
203  -1, -1, -1),
204  TAKEN_INSPECTED_POINT(90, 0, 0,
205  0, 0, 0),
206  TAKEN_INSPECTED_POINT(-90, 0, 0,
207  1, 0, 0),
208  TAKEN_INSPECTED_POINT(-2, -1, -1,
209  -179, -59, -59),
210  TAKEN_INSPECTED_POINT(2, 1, 1,
211  180, 0, 0),
212  TAKEN_INSPECTED_POINT(1, 2, 1,
213  -179, -59, -59),
214  TAKEN_INSPECTED_POINT(-1, -1, -1,
215  180, 0, 0),
216  TAKEN_INSPECTED_POINT(0, 0, 0,
217  -179, -59, -59),
218  TAKEN_INSPECTED_POINT(0, 0, 0,
219  180, 0, 0),
220  NULL),
221  TAKEN_POINT(0, 0, 0,
222  0, 0, 0),
223  0, -1);
224 
225  ADD_DATA("limit",
226  gcut_list_string_new(TAKEN_INSPECTED_POINT(-1, -1, -1,
227  0, 0, 0),
228  TAKEN_INSPECTED_POINT(1, 0, 0,
229  1, 0, 0),
230  TAKEN_INSPECTED_POINT(-1, 0, 0,
231  1, 1, 1),
232  NULL),
233  TAKEN_POINT(0, 0, 0,
234  0, 0, 0),
235  0, 3);
236 
237  ADD_DATA("offset - limit",
238  gcut_list_string_new(TAKEN_INSPECTED_POINT(-1, 0, 0,
239  1, 1, 1),
240  TAKEN_INSPECTED_POINT(1, 1, 0,
241  1, 1, 0),
242  TAKEN_INSPECTED_POINT(1, 1, 1,
243  1, 1, 1),
244  NULL),
245  TAKEN_POINT(0, 0, 0,
246  0, 0, 0),
247  2, 3);
248 
249 #undef ADD_DATA
250 }
251 
252 void
253 test_near_geo_point(gpointer data)
254 {
255  grn_id id;
256  int offset, limit;
257  const GList *expected_keys;
258  GList *actual_keys = NULL;
259  grn_table_sort_key keys[2];
260  grn_obj base, base_string, location;
261 
262  create_geo_table(cut_take_printf(" [\"%s\"],\n"
263  " [\"%s\"],\n"
264  " [\"%s\"],\n"
265  " [\"%s\"],\n"
266  " [\"%s\"],\n"
267  " [\"%s\"],\n"
268  " [\"%s\"],\n"
269  " [\"%s\"],\n"
270  " [\"%s\"],\n"
271  " [\"%s\"],\n"
272  " [\"%s\"],\n"
273  " [\"%s\"],\n"
274  " [\"%s\"],\n"
275  " [\"%s\"],\n"
276  " [\"%s\"]",
277  TAKEN_POINT(0, 0, 0,
278  180, 0, 0),
279  TAKEN_POINT(0, 0, 0,
280  -179, -59, -59),
281  TAKEN_POINT(-1, -1, -1,
282  180, 0, 0),
283  TAKEN_POINT(2, 1, 1,
284  180, 0, 0),
285  TAKEN_POINT(-2, -1, -1,
286  -179, -59, -59),
287  TAKEN_POINT(1, 2, 1,
288  -179, -59, -59),
289  TAKEN_POINT(90, 0, 0,
290  0, 0, 0),
291  TAKEN_POINT(-90, 0, 0,
292  1, 0, 0),
293  TAKEN_POINT(1, 0, 0,
294  1, 0, 0),
295  TAKEN_POINT(1, 1, 0,
296  1, 1, 0),
297  TAKEN_POINT(1, 1, 1,
298  1, 1, 1),
299  TAKEN_POINT(-1, 0, 0,
300  1, 1, 1),
301  TAKEN_POINT(-1, -1, -1,
302  0, 0, 0),
303  TAKEN_POINT(-1, -2, -1,
304  -1, -1, -1),
305  TAKEN_POINT(1, 1, 10,
306  -1, -1, -1)));
307 
308  result = grn_table_create(context, NULL, 0, NULL, GRN_TABLE_NO_KEY,
309  NULL, table);
310  grn_test_assert_context(context);
311 
312  GRN_TEXT_INIT(&base_string, 0);
313  GRN_TEXT_SETS(context, &base_string, gcut_data_get_string(data, "base"));
314  GRN_WGS84_GEO_POINT_INIT(&base, 0);
315  grn_obj_cast(context, &base_string, &base, FALSE);
316  GRN_OBJ_FIN(context, &base_string);
317 
318  offset = gcut_data_get_int(data, "offset");
319  if (offset > 0) {
320  cut_omit("geo sort doesn't support offset yet.");
321  }
322  limit = gcut_data_get_int(data, "limit");
323  keys[0].key = column;
324  keys[0].flags = GRN_TABLE_SORT_GEO;
325  keys[0].offset = 0;
326  keys[1].key = &base;
327  keys[1].flags = 0;
328  keys[1].offset = 0;
329  grn_table_sort(context, table, offset, limit, result, keys, 2);
330  GRN_OBJ_FIN(context, &base);
331  grn_test_assert_context(context);
332  cursor = grn_table_cursor_open(context, result,
333  NULL, 0, NULL, 0, 0, -1,
335  grn_test_assert_context(context);
336  GRN_WGS84_GEO_POINT_INIT(&location, 0);
337  while ((id = grn_table_cursor_next(context, cursor))) {
338  gint32 *key;
339  int key_size;
340  gint latitude, longitude;
341 
342  key_size = grn_table_cursor_get_value(context, cursor, (void **)&key);
343  GRN_BULK_REWIND(&location);
344  grn_obj_get_value(context, column, *key, &location);
345  GRN_GEO_POINT_VALUE(&location, latitude, longitude);
346  actual_keys = g_list_append(actual_keys,
347  inspect_point(latitude, longitude));
348  }
349  GRN_OBJ_FIN(context, &location);
350  gcut_take_list(actual_keys, g_free);
351 
352  expected_keys = gcut_data_get_pointer(data, "expected");
353  gcut_assert_equal_list_string(expected_keys, actual_keys);
354 }