Groonga 3.0.9 Source Code Document
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
table.c
Go to the documentation of this file.
1 /* -*- c-basic-offset: 2; indent-tabs-mode: nil -*- */
2 /* Copyright(C) 2012 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 version 2.1 as published by the Free Software Foundation.
7 
8  This library is distributed in the hope that it will be useful,
9  but WITHOUT ANY WARRANTY; without even the implied warranty of
10  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11  Lesser General Public License for more details.
12 
13  You should have received a copy of the GNU Lesser General Public
14  License along with this library; if not, write to the Free Software
15  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16 */
17 
18 #include <string.h>
19 
20 #include "ctx.h"
21 #include "db.h"
22 #include "output.h"
23 #include "util.h"
24 #include <groonga/plugin.h>
25 
26 #define VAR GRN_PROC_GET_VAR_BY_OFFSET
27 #define CONST_STR_LEN(x) x, x ? sizeof(x) - 1 : 0
28 #define TEXT_VALUE_LEN(x) GRN_TEXT_VALUE(x), GRN_TEXT_LEN(x)
29 
30 static grn_obj *
31 grn_ctx_get_table_by_name_or_id(grn_ctx *ctx,
32  const char *name, unsigned int name_len)
33 {
34  grn_obj *table;
35  const char *end = name + name_len;
36  const char *rest = NULL;
37  grn_id id = grn_atoui(name, end, &rest);
38  if (rest == end) {
39  table = grn_ctx_at(ctx, id);
40  } else {
41  table = grn_ctx_get(ctx, name, name_len);
42  }
43  if (!GRN_OBJ_TABLEP(table)) {
44  ERR(GRN_INVALID_ARGUMENT, "invalid table name: <%.*s>", name_len, name);
45  if (table) {
46  grn_obj_unlink(ctx, table);
47  table = NULL;
48  }
49  }
50  return table;
51 }
52 
53 static void
54 grn_output_table_name_or_id(grn_ctx *ctx, grn_obj *table)
55 {
56  if (table) {
57  if (((grn_db_obj *)table)->id & GRN_OBJ_TMP_OBJECT) {
58  GRN_OUTPUT_INT64(((grn_db_obj *)table)->id);
59  } else {
60  int name_len;
61  char name_buf[GRN_TABLE_MAX_KEY_SIZE];
62  name_len = grn_obj_name(ctx, table, name_buf, GRN_TABLE_MAX_KEY_SIZE);
63  GRN_OUTPUT_STR(name_buf, name_len);
64  }
65  } else {
67  }
68 }
69 
70 static grn_bool
71 parse_bool_value(grn_ctx *ctx, grn_obj *text)
72 {
73  grn_bool value = GRN_FALSE;
74  if (GRN_TEXT_LEN(text) == 3 &&
75  memcmp("yes", GRN_TEXT_VALUE(text), 3) == 0) {
76  value = GRN_TRUE;
77  }
78  return value;
79 }
80 
81 static grn_operator
82 parse_set_operator_value(grn_ctx *ctx, grn_obj *text)
83 {
84  grn_operator value = GRN_OP_OR;
85  if (GRN_TEXT_LEN(text) == 3) {
86  if (memcmp("and", GRN_TEXT_VALUE(text), 3) == 0) {
87  value = GRN_OP_AND;
88  } else if (memcmp("but", GRN_TEXT_VALUE(text), 3) == 0) {
89  value = GRN_OP_AND_NOT;
90  }
91  } else if (GRN_TEXT_LEN(text) == 6 &&
92  memcmp("adjust", GRN_TEXT_VALUE(text), 6) == 0) {
93  value = GRN_OP_ADJUST;
94  } else if (GRN_TEXT_LEN(text) == 7 &&
95  memcmp("and_not", GRN_TEXT_VALUE(text), 7) == 0) {
96  value = GRN_OP_AND_NOT;
97  }
98  return value;
99 }
100 
101 static grn_obj *
102 command_match(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_data)
103 {
104  grn_obj *result_set = NULL;
105  grn_obj *table = grn_ctx_get_table_by_name_or_id(ctx, TEXT_VALUE_LEN(VAR(0)));
106  if (table) {
108  grn_obj *v, *query, *columns = NULL;
109  GRN_EXPR_CREATE_FOR_QUERY(ctx, table, query, v);
110  if (query) {
111  if (GRN_TEXT_LEN(VAR(1))) {
112  GRN_EXPR_CREATE_FOR_QUERY(ctx, table, columns, v);
113  if (columns) {
114  grn_expr_parse(ctx, columns, TEXT_VALUE_LEN(VAR(1)),
115  NULL, GRN_OP_MATCH, GRN_OP_AND,
117  }
118  }
119  if (parse_bool_value(ctx, VAR(5))) {
120  flags |= GRN_EXPR_ALLOW_COLUMN;
121  }
122  if (parse_bool_value(ctx, VAR(6))) {
123  flags |= GRN_EXPR_ALLOW_PRAGMA;
124  }
125  grn_expr_parse(ctx, query, TEXT_VALUE_LEN(VAR(2)),
126  columns, GRN_OP_MATCH, GRN_OP_AND, flags);
127  if (GRN_TEXT_LEN(VAR(3))) {
128  result_set = grn_ctx_get_table_by_name_or_id(ctx, TEXT_VALUE_LEN(VAR(3)));
129  } else {
130  result_set = grn_table_create(ctx, NULL, 0, NULL,
133  table, NULL);
134  }
135  if (result_set) {
136  grn_table_select(ctx, table, query, result_set,
137  parse_set_operator_value(ctx, VAR(4)));
138  }
139  grn_obj_unlink(ctx, columns);
140  grn_obj_unlink(ctx, query);
141  }
142  }
143  grn_output_table_name_or_id(ctx, result_set);
144  return NULL;
145 }
146 
147 static grn_obj *
148 command_filter_by_script(grn_ctx *ctx, int nargs,
149  grn_obj **args, grn_user_data *user_data)
150 {
151  grn_obj *result_set = NULL;
152  grn_obj *table = grn_ctx_get_table_by_name_or_id(ctx, TEXT_VALUE_LEN(VAR(0)));
153  if (table) {
155  grn_obj *v, *query;
156  GRN_EXPR_CREATE_FOR_QUERY(ctx, table, query, v);
157  if (query) {
158  if (parse_bool_value(ctx, VAR(4))) {
159  flags |= GRN_EXPR_ALLOW_UPDATE;
160  }
161  grn_expr_parse(ctx, query, TEXT_VALUE_LEN(VAR(1)),
162  NULL, GRN_OP_MATCH, GRN_OP_AND, flags);
163  if (GRN_TEXT_LEN(VAR(2))) {
164  result_set = grn_ctx_get_table_by_name_or_id(ctx, TEXT_VALUE_LEN(VAR(2)));
165  } else {
166  result_set = grn_table_create(ctx, NULL, 0, NULL,
169  table, NULL);
170  }
171  if (result_set) {
172  grn_table_select(ctx, table, query, result_set,
173  parse_set_operator_value(ctx, VAR(3)));
174  }
175  grn_obj_unlink(ctx, query);
176  }
177  }
178  grn_output_table_name_or_id(ctx, result_set);
179  return NULL;
180 }
181 
182 static grn_obj *
183 command_filter(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_data)
184 {
185  grn_operator operator = GRN_OP_NOP;
186  grn_obj *table, *column, *result_set = NULL;
187  if (!(table = grn_ctx_get_table_by_name_or_id(ctx, TEXT_VALUE_LEN(VAR(0))))) {
188  goto exit;
189  }
190  if (!(column = grn_obj_column(ctx, table, TEXT_VALUE_LEN(VAR(1))))) {
191  ERR(GRN_INVALID_ARGUMENT, "invalid column name: <%.*s>",
192  (int)GRN_TEXT_LEN(VAR(1)), GRN_TEXT_VALUE(VAR(1)));
193  goto exit;
194  }
195  if (GRN_TEXT_LEN(VAR(2)) == 0) {
196  ERR(GRN_INVALID_ARGUMENT, "missing mandatory argument: operator");
197  goto exit;
198  } else {
199  uint32_t operator_len = GRN_TEXT_LEN(VAR(2));
200  const char *operator_text = GRN_TEXT_VALUE(VAR(2));
201  switch (operator_text[0]) {
202  case '<' :
203  if (operator_len == 1) {
204  operator = GRN_OP_LESS;
205  }
206  break;
207  }
208  if (operator == GRN_OP_NOP) {
209  ERR(GRN_INVALID_ARGUMENT, "invalid operator: <%.*s>",
210  operator_len, operator_text);
211  goto exit;
212  }
213  }
214  if (GRN_TEXT_LEN(VAR(4))) {
215  result_set = grn_ctx_get_table_by_name_or_id(ctx, TEXT_VALUE_LEN(VAR(4)));
216  } else {
217  result_set = grn_table_create(ctx, NULL, 0, NULL,
220  table, NULL);
221  }
222  if (result_set) {
223  grn_column_filter(ctx, column, operator, VAR(3), result_set,
224  parse_set_operator_value(ctx, VAR(5)));
225  }
226 exit :
227  grn_output_table_name_or_id(ctx, result_set);
228  return NULL;
229 }
230 
231 static grn_obj *
232 command_group(grn_ctx *ctx, int nargs, grn_obj **args,
233  grn_user_data *user_data)
234 {
235  const char *table = GRN_TEXT_VALUE(VAR(0));
236  unsigned int table_len = GRN_TEXT_LEN(VAR(0));
237  const char *key = GRN_TEXT_VALUE(VAR(1));
238  unsigned int key_len = GRN_TEXT_LEN(VAR(1));
239  const char *set = GRN_TEXT_VALUE(VAR(2));
240  unsigned int set_len = GRN_TEXT_LEN(VAR(2));
241  grn_obj *table_ = grn_ctx_get_table_by_name_or_id(ctx, table, table_len);
242  grn_obj *set_ = NULL;
243  if (table_) {
244  uint32_t ngkeys;
245  grn_table_sort_key *gkeys;
246  gkeys = grn_table_sort_key_from_str(ctx, key, key_len, table_, &ngkeys);
247  if (gkeys) {
248  if (set_len) {
249  set_ = grn_ctx_get_table_by_name_or_id(ctx, set, set_len);
250  } else {
251  set_ = grn_table_create_for_group(ctx, NULL, 0, NULL,
252  gkeys[0].key, table_, 0);
253  }
254  if (set_) {
255  if (GRN_TEXT_LEN(VAR(3))) {
256  uint32_t gap = grn_atoui(GRN_TEXT_VALUE(VAR(3)),
257  GRN_BULK_CURR(VAR(3)), NULL);
258  grn_table_group_with_range_gap(ctx, table_, gkeys, set_, gap);
259  } else {
261  set_, 0, 0, 1,
263  };
264  grn_table_group(ctx, table_, gkeys, 1, &g, 1);
265  }
266  }
267  grn_table_sort_key_close(ctx, gkeys, ngkeys);
268  }
269  }
270  grn_output_table_name_or_id(ctx, set_);
271  return NULL;
272 }
273 
274 #define DEFAULT_LIMIT 10
275 
276 static grn_obj *
277 command_sort(grn_ctx *ctx, int nargs, grn_obj **args,
278  grn_user_data *user_data)
279 {
280  const char *table = GRN_TEXT_VALUE(VAR(0));
281  unsigned int table_len = GRN_TEXT_LEN(VAR(0));
282  const char *keys = GRN_TEXT_VALUE(VAR(1));
283  unsigned int keys_len = GRN_TEXT_LEN(VAR(1));
284  int offset = GRN_TEXT_LEN(VAR(2))
285  ? grn_atoi(GRN_TEXT_VALUE(VAR(2)), GRN_BULK_CURR(VAR(2)), NULL)
286  : 0;
287  int limit = GRN_TEXT_LEN(VAR(3))
288  ? grn_atoi(GRN_TEXT_VALUE(VAR(3)), GRN_BULK_CURR(VAR(3)), NULL)
289  : DEFAULT_LIMIT;
290  grn_obj *table_ = grn_ctx_get_table_by_name_or_id(ctx, table, table_len);
291  grn_obj *sorted = NULL;
292  if (table_) {
293  uint32_t nkeys;
294  grn_table_sort_key *keys_;
295  if (keys_len &&
296  (keys_ = grn_table_sort_key_from_str(ctx, keys, keys_len,
297  table_, &nkeys))) {
298  if ((sorted = grn_table_create(ctx, NULL, 0, NULL,
299  GRN_OBJ_TABLE_NO_KEY, NULL, table_))) {
300  int table_size = (int)grn_table_size(ctx, table_);
301  grn_normalize_offset_and_limit(ctx, table_size, &offset, &limit);
302  grn_table_sort(ctx, table_, offset, limit, sorted, keys_, nkeys);
303  grn_table_sort_key_close(ctx, keys_, nkeys);
304  }
305  }
306  }
307  grn_output_table_name_or_id(ctx, sorted);
308  return NULL;
309 }
310 
311 static grn_obj *
312 command_output(grn_ctx *ctx, int nargs, grn_obj **args,
313  grn_user_data *user_data)
314 {
315  const char *table = GRN_TEXT_VALUE(VAR(0));
316  unsigned int table_len = GRN_TEXT_LEN(VAR(0));
317  const char *columns = GRN_TEXT_VALUE(VAR(1));
318  unsigned int columns_len = GRN_TEXT_LEN(VAR(1));
319  int offset = GRN_TEXT_LEN(VAR(2))
320  ? grn_atoi(GRN_TEXT_VALUE(VAR(2)), GRN_BULK_CURR(VAR(2)), NULL)
321  : 0;
322  int limit = GRN_TEXT_LEN(VAR(3))
323  ? grn_atoi(GRN_TEXT_VALUE(VAR(3)), GRN_BULK_CURR(VAR(3)), NULL)
324  : DEFAULT_LIMIT;
325  grn_obj *table_ = grn_ctx_get_table_by_name_or_id(ctx, table, table_len);
326  if (table_) {
327  grn_obj_format format;
328  int table_size = (int)grn_table_size(ctx, table_);
329  GRN_OBJ_FORMAT_INIT(&format, table_size, 0, limit, offset);
330  format.flags =
333  /* TODO: accept only comma separated expr as columns */
334  grn_obj_columns(ctx, table_, columns, columns_len, &format.columns);
335  GRN_OUTPUT_OBJ(table_, &format);
336  GRN_OBJ_FORMAT_FIN(ctx, &format);
337  }
338  return NULL;
339 }
340 
341 static grn_obj *
342 command_each(grn_ctx *ctx, int nargs, grn_obj **args,
343  grn_user_data *user_data)
344 {
345  const char *table = GRN_TEXT_VALUE(VAR(0));
346  unsigned int table_len = GRN_TEXT_LEN(VAR(0));
347  const char *expr = GRN_TEXT_VALUE(VAR(1));
348  unsigned int expr_len = GRN_TEXT_LEN(VAR(1));
349  grn_obj *table_ = grn_ctx_get_table_by_name_or_id(ctx, table, table_len);
350  if (table_) {
351  grn_obj *v, *expr_;
352  GRN_EXPR_CREATE_FOR_QUERY(ctx, table_, expr_, v);
353  if (expr_ && v) {
354  grn_table_cursor *tc;
355  grn_expr_parse(ctx, expr_, expr, expr_len,
356  NULL, GRN_OP_MATCH, GRN_OP_AND,
358  if ((tc = grn_table_cursor_open(ctx, table_, NULL, 0,
359  NULL, 0, 0, -1, 0))) {
360  grn_id id;
361  while ((id = grn_table_cursor_next(ctx, tc)) != GRN_ID_NIL) {
362  GRN_RECORD_SET(ctx, v, id);
363  grn_expr_exec(ctx, expr_, 0);
364  }
365  grn_table_cursor_close(ctx, tc);
366  }
367  grn_obj_unlink(ctx, expr_);
368  }
369  }
370  GRN_OUTPUT_BOOL(!ctx->rc);
371  return NULL;
372 }
373 
374 static grn_obj *
375 command_unlink(grn_ctx *ctx, int nargs, grn_obj **args,
376  grn_user_data *user_data)
377 {
378  const char *table = GRN_TEXT_VALUE(VAR(0));
379  unsigned int table_len = GRN_TEXT_LEN(VAR(0));
380  grn_obj *table_ = grn_ctx_get_table_by_name_or_id(ctx, table, table_len);
381  if (table_) {
382  grn_obj_unlink(ctx, table_);
383  }
384  GRN_OUTPUT_BOOL(!ctx->rc);
385  return NULL;
386 }
387 
388 static grn_obj *
389 command_add(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_data)
390 {
393  NULL, 0,
395  NULL, 0, NULL, 0, 0);
397  if (ctx->impl->loader.table) {
398  grn_db_touch(ctx, DB_OBJ(ctx->impl->loader.table)->db);
399  }
400  return NULL;
401 }
402 
403 static grn_obj *
404 command_set(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_data)
405 {
406  int table_name_len = GRN_TEXT_LEN(VAR(0));
407  const char *table_name = GRN_TEXT_VALUE(VAR(0));
408  grn_obj *table = grn_ctx_get(ctx, table_name, table_name_len);
409  if (table) {
410  grn_id id = GRN_ID_NIL;
411  int key_len = GRN_TEXT_LEN(VAR(2));
412  int id_len = GRN_TEXT_LEN(VAR(5));
413  if (key_len) {
414  const char *key = GRN_TEXT_VALUE(VAR(2));
415  id = grn_table_get(ctx, table, key, key_len);
416  } else {
417  if (id_len) {
418  id = grn_atoui(GRN_TEXT_VALUE(VAR(5)), GRN_BULK_CURR(VAR(5)), NULL);
419  }
420  id = grn_table_at(ctx, table, id);
421  }
422  if (id) {
423  grn_obj obj;
424  grn_obj_format format;
425  GRN_RECORD_INIT(&obj, 0, ((grn_db_obj *)table)->id);
426  GRN_OBJ_FORMAT_INIT(&format, 1, 0, 1, 0);
427  GRN_RECORD_SET(ctx, &obj, id);
428  grn_obj_columns(ctx, table,
429  GRN_TEXT_VALUE(VAR(4)),
430  GRN_TEXT_LEN(VAR(4)), &format.columns);
431  format.flags = 0 /* GRN_OBJ_FORMAT_WITH_COLUMN_NAMES */;
432  GRN_OUTPUT_OBJ(&obj, &format);
433  GRN_OBJ_FORMAT_FIN(ctx, &format);
434  }
435  } else {
437  "nonexistent table name: <%.*s>", table_name_len, table_name);
438  }
439  return NULL;
440 }
441 
442 static grn_rc
443 command_get_resolve_parameters(grn_ctx *ctx, grn_user_data *user_data,
444  grn_obj **table, grn_id *id)
445 {
446  const char *table_text, *id_text, *key_text;
447  int table_length, id_length, key_length;
448 
449  table_text = GRN_TEXT_VALUE(VAR(0));
450  table_length = GRN_TEXT_LEN(VAR(0));
451  if (table_length == 0) {
452  ERR(GRN_INVALID_ARGUMENT, "[table][get] table isn't specified");
453  return ctx->rc;
454  }
455 
456  *table = grn_ctx_get(ctx, table_text, table_length);
457  if (!*table) {
459  "[table][get] table doesn't exist: <%.*s>", table_length, table_text);
460  return ctx->rc;
461  }
462 
463  key_text = GRN_TEXT_VALUE(VAR(1));
464  key_length = GRN_TEXT_LEN(VAR(1));
465  id_text = GRN_TEXT_VALUE(VAR(3));
466  id_length = GRN_TEXT_LEN(VAR(3));
467  switch ((*table)->header.type) {
468  case GRN_TABLE_NO_KEY:
469  if (key_length) {
471  "[table][get] should not specify key for NO_KEY table: <%.*s>: "
472  "table: <%.*s>",
473  key_length, key_text,
474  table_length, table_text);
475  return ctx->rc;
476  }
477  if (id_length) {
478  const char *rest = NULL;
479  *id = grn_atoi(id_text, id_text + id_length, &rest);
480  if (rest == id_text) {
482  "[table][get] ID should be a number: <%.*s>: table: <%.*s>",
483  id_length, id_text,
484  table_length, table_text);
485  }
486  } else {
488  "[table][get] ID isn't specified: table: <%.*s>",
489  table_length, table_text);
490  }
491  break;
492  case GRN_TABLE_HASH_KEY:
493  case GRN_TABLE_PAT_KEY:
494  case GRN_TABLE_DAT_KEY:
495  if (key_length && id_length) {
497  "[table][get] should not specify both key and ID: "
498  "key: <%.*s>: ID: <%.*s>: table: <%.*s>",
499  key_length, key_text,
500  id_length, id_text,
501  table_length, table_text);
502  return ctx->rc;
503  }
504  if (key_length) {
505  *id = grn_table_get(ctx, *table, key_text, key_length);
506  if (!*id) {
508  "[table][get] nonexistent key: <%.*s>: table: <%.*s>",
509  key_length, key_text,
510  table_length, table_text);
511  }
512  } else {
513  if (id_length) {
514  const char *rest = NULL;
515  *id = grn_atoi(id_text, id_text + id_length, &rest);
516  if (rest == id_text) {
518  "[table][get] ID should be a number: <%.*s>: table: <%.*s>",
519  id_length, id_text,
520  table_length, table_text);
521  }
522  } else {
524  "[table][get] key nor ID isn't specified: table: <%.*s>",
525  table_length, table_text);
526  }
527  }
528  break;
529  default:
531  "[table][get] not a table: <%.*s>", table_length, table_text);
532  break;
533  }
534 
535  return ctx->rc;
536 }
537 
538 static grn_obj *
539 command_get(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_data)
540 {
541  grn_id id = GRN_ID_NIL;
542  grn_obj *table = NULL;
543  if (!command_get_resolve_parameters(ctx, user_data, &table, &id)) {
544  grn_obj obj;
545  grn_obj_format format;
546  GRN_OUTPUT_ARRAY_OPEN("RESULT", 2);
547  GRN_RECORD_INIT(&obj, 0, ((grn_db_obj *)table)->id);
548  GRN_OBJ_FORMAT_INIT(&format, 1, 0, 1, 0);
549  GRN_RECORD_SET(ctx, &obj, id);
550  grn_obj_columns(ctx, table, GRN_TEXT_VALUE(VAR(2)), GRN_TEXT_LEN(VAR(2)),
551  &format.columns);
552  format.flags =
555  GRN_OUTPUT_OBJ(&obj, &format);
556  GRN_OBJ_FORMAT_FIN(ctx, &format);
558  }
559  return NULL;
560 }
561 
562 static grn_obj *
563 command_push(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_data)
564 {
565  grn_obj *table = grn_ctx_get(ctx, GRN_TEXT_VALUE(VAR(0)), GRN_TEXT_LEN(VAR(0)));
566  if (table) {
567  switch (table->header.type) {
568  case GRN_TABLE_NO_KEY:
569  {
570  grn_array *array = (grn_array *)table;
571  grn_table_queue *queue = grn_array_queue(ctx, array);
572  if (queue) {
573  MUTEX_LOCK(queue->mutex);
574  if (grn_table_queue_head(queue) == queue->cap) {
575  grn_array_clear_curr_rec(ctx, array);
576  }
579  NULL, 0,
581  NULL, 0, NULL, 0, 0);
582  if (grn_table_queue_size(queue) == queue->cap) {
584  }
586  COND_SIGNAL(queue->cond);
587  MUTEX_UNLOCK(queue->mutex);
589  if (ctx->impl->loader.table) {
590  grn_db_touch(ctx, DB_OBJ(ctx->impl->loader.table)->db);
591  }
592  } else {
593  ERR(GRN_OPERATION_NOT_SUPPORTED, "table '%.*s' doesn't support push",
594  (int)GRN_TEXT_LEN(VAR(0)), GRN_TEXT_VALUE(VAR(0)));
595  }
596  }
597  break;
598  default :
599  ERR(GRN_OPERATION_NOT_SUPPORTED, "table '%.*s' doesn't support push",
600  (int)GRN_TEXT_LEN(VAR(0)), GRN_TEXT_VALUE(VAR(0)));
601  }
602  } else {
603  ERR(GRN_INVALID_ARGUMENT, "table '%.*s' does not exist.",
604  (int)GRN_TEXT_LEN(VAR(0)), GRN_TEXT_VALUE(VAR(0)));
605  }
606  return NULL;
607 }
608 
609 static grn_obj *
610 command_pull(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_data)
611 {
612  grn_obj *table = grn_ctx_get(ctx, GRN_TEXT_VALUE(VAR(0)), GRN_TEXT_LEN(VAR(0)));
613  if (table) {
614  switch (table->header.type) {
615  case GRN_TABLE_NO_KEY:
616  {
617  grn_array *array = (grn_array *)table;
618  grn_table_queue *queue = grn_array_queue(ctx, array);
619  if (queue) {
620  MUTEX_LOCK(queue->mutex);
621  while (grn_table_queue_size(queue) == 0) {
622  if (GRN_TEXT_LEN(VAR(2))) {
623  MUTEX_UNLOCK(queue->mutex);
624  GRN_OUTPUT_BOOL(0);
625  return NULL;
626  }
627  COND_WAIT(queue->cond, queue->mutex);
628  }
630  {
631  grn_obj obj;
632  grn_obj_format format;
633  GRN_RECORD_INIT(&obj, 0, ((grn_db_obj *)table)->id);
634  GRN_OBJ_FORMAT_INIT(&format, 1, 0, 1, 0);
635  GRN_RECORD_SET(ctx, &obj, grn_table_queue_tail(queue));
636  grn_obj_columns(ctx, table, GRN_TEXT_VALUE(VAR(1)), GRN_TEXT_LEN(VAR(1)),
637  &format.columns);
638  format.flags = 0 /* GRN_OBJ_FORMAT_WITH_COLUMN_NAMES */;
639  GRN_OUTPUT_OBJ(&obj, &format);
640  GRN_OBJ_FORMAT_FIN(ctx, &format);
641  }
642  MUTEX_UNLOCK(queue->mutex);
643  } else {
644  ERR(GRN_OPERATION_NOT_SUPPORTED, "table '%.*s' doesn't support pull",
645  (int)GRN_TEXT_LEN(VAR(0)), GRN_TEXT_VALUE(VAR(0)));
646  }
647  }
648  break;
649  default :
650  ERR(GRN_OPERATION_NOT_SUPPORTED, "table '%.*s' doesn't support pull",
651  (int)GRN_TEXT_LEN(VAR(0)), GRN_TEXT_VALUE(VAR(0)));
652  }
653  } else {
654  ERR(GRN_INVALID_ARGUMENT, "table '%.*s' does not exist.",
655  (int)GRN_TEXT_LEN(VAR(0)), GRN_TEXT_VALUE(VAR(0)));
656  }
657  return NULL;
658 }
659 
660 grn_rc
662 {
663  return GRN_SUCCESS;
664 }
665 
666 #define DEF_VAR(v,x) do {\
667  (v).name = (x);\
668  (v).name_size = (x) ? sizeof(x) - 1 : 0;\
669  GRN_TEXT_INIT(&(v).value, 0);\
670 } while (0)
671 
672 #define DEF_COMMAND(name,func,nvars,vars)\
673  (grn_proc_create(ctx, CONST_STR_LEN(name),\
674  GRN_PROC_COMMAND, (func), NULL, NULL, (nvars), (vars)))
675 
676 grn_rc
678 {
679  grn_expr_var vars[18];
680 
681  DEF_VAR(vars[0], "table");
682  DEF_VAR(vars[1], "expression");
683  DEF_VAR(vars[2], "result_set");
684  DEF_VAR(vars[3], "set_operation");
685  DEF_VAR(vars[4], "allow_update");
686  DEF_COMMAND("filter_by_script", command_filter_by_script, 5, vars);
687 
688  DEF_VAR(vars[0], "table");
689  DEF_VAR(vars[1], "column");
690  DEF_VAR(vars[2], "operator");
691  DEF_VAR(vars[3], "value");
692  DEF_VAR(vars[4], "result_set");
693  DEF_VAR(vars[5], "set_operation");
694  DEF_COMMAND("filter", command_filter, 6, vars);
695 
696  DEF_VAR(vars[0], "table");
697  DEF_VAR(vars[1], "key");
698  DEF_VAR(vars[2], "result_set");
699  DEF_VAR(vars[3], "range_gap");
700  DEF_COMMAND("group", command_group, 4, vars);
701 
702  DEF_VAR(vars[0], "table");
703  DEF_VAR(vars[1], "keys");
704  DEF_VAR(vars[2], "offset");
705  DEF_VAR(vars[3], "limit");
706  DEF_COMMAND("sort", command_sort, 4, vars);
707 
708  DEF_VAR(vars[0], "table");
709  DEF_VAR(vars[1], "columns");
710  DEF_VAR(vars[2], "offset");
711  DEF_VAR(vars[3], "limit");
712  DEF_COMMAND("output", command_output, 4, vars);
713 
714  DEF_VAR(vars[0], "table");
715  DEF_VAR(vars[1], "expression");
716  DEF_COMMAND("each", command_each, 2, vars);
717 
718  DEF_VAR(vars[0], "table");
719  DEF_COMMAND("unlink", command_unlink, 1, vars);
720 
721  DEF_VAR(vars[0], "table");
722  DEF_VAR(vars[1], "values");
723  DEF_VAR(vars[2], "key");
724  DEF_VAR(vars[3], "columns");
725  DEF_VAR(vars[4], "output_columns");
726  DEF_VAR(vars[5], "id");
727  DEF_COMMAND("add", command_add, 2, vars);
728  DEF_COMMAND("push", command_push, 2, vars);
729  DEF_COMMAND("set", command_set, 6, vars);
730 
731  DEF_VAR(vars[0], "table");
732  DEF_VAR(vars[1], "key");
733  DEF_VAR(vars[2], "output_columns");
734  DEF_VAR(vars[3], "id");
735  DEF_COMMAND("get", command_get, 4, vars);
736 
737  DEF_VAR(vars[0], "table");
738  DEF_VAR(vars[1], "output_columns");
739  DEF_VAR(vars[2], "non_block");
740  DEF_COMMAND("pull", command_pull, 3, vars);
741 
742  DEF_VAR(vars[0], "table");
743  DEF_VAR(vars[1], "columns");
744  DEF_VAR(vars[2], "query");
745  DEF_VAR(vars[3], "result_set");
746  DEF_VAR(vars[4], "set_operation");
747  DEF_VAR(vars[5], "allow_column_expression");
748  DEF_VAR(vars[6], "allow_pragma");
749  DEF_COMMAND("match", command_match, 7, vars);
750 
751  return ctx->rc;
752 }
753 
754 grn_rc
756 {
757  return GRN_SUCCESS;
758 }