static grn_rc grn_ctx_init_internal(grn_ctx *ctx, int flags) { if (!ctx) { return GRN_INVALID_ARGUMENT; } // if (ctx->stat != GRN_CTX_FIN) { return GRN_INVALID_ARGUMENT; } ERRCLR(ctx); ctx->flags = flags; if (grn_ctx_per_db) { ctx->flags |= GRN_CTX_PER_DB; } ctx->stat = GRN_CTX_INITED; ctx->encoding = grn_gctx.encoding; ctx->seqno = 0; ctx->seqno2 = 0; ctx->subno = 0; ctx->impl = NULL; ctx->user_data.ptr = NULL; CRITICAL_SECTION_ENTER(grn_glock); ctx->next = grn_gctx.next; ctx->prev = &grn_gctx; grn_gctx.next->prev = ctx; grn_gctx.next = ctx; CRITICAL_SECTION_LEAVE(grn_glock); ctx->errline = 0; ctx->errfile = ""; ctx->errfunc = ""; ctx->trace[0] = NULL; ctx->errbuf[0] = '\0'; return GRN_SUCCESS; }
grn_rc grn_ctx_init(grn_ctx *ctx, int flags) { if (!ctx) { return GRN_INVALID_ARGUMENT; } // if (ctx->stat != GRN_QL_FIN) { return GRN_INVALID_ARGUMENT; } ERRCLR(ctx); ctx->flags = flags; ctx->stat = GRN_QL_WAIT_EXPR; ctx->encoding = grn_gctx.encoding; ctx->seqno = 0; ctx->seqno2 = 0; ctx->subno = 0; ctx->impl = NULL; if (flags & GRN_CTX_USE_QL) { grn_ctx_ql_init(ctx, flags); if (ERRP(ctx, GRN_ERROR)) { return ctx->rc; } } MUTEX_LOCK(grn_glock); ctx->next = grn_gctx.next; ctx->prev = &grn_gctx; grn_gctx.next->prev = ctx; grn_gctx.next = ctx; MUTEX_UNLOCK(grn_glock); return ctx->rc; }
grn_rc grn_com_event_poll(grn_ctx *ctx, grn_com_event *ev, int timeout) { int nevents; grn_com *com; #ifdef USE_SELECT uint32_t dummy; grn_sock *pfd; int nfds = 0; fd_set rfds; fd_set wfds; struct timeval tv; if (timeout >= 0) { tv.tv_sec = timeout / 1000; tv.tv_usec = (timeout % 1000) * 1000; } FD_ZERO(&rfds); FD_ZERO(&wfds); ctx->errlvl = GRN_OK; ctx->rc = GRN_SUCCESS; { grn_hash_cursor *cursor; cursor = grn_hash_cursor_open(ctx, ev->hash, NULL, 0, NULL, 0, 0, -1, 0); if (cursor) { grn_id id; while ((id = grn_hash_cursor_next(ctx, cursor))) { grn_hash_cursor_get_key_value(ctx, cursor, (void **)(&pfd), &dummy, (void **)(&com)); if ((com->events & GRN_COM_POLLIN)) { FD_SET(*pfd, &rfds); } if ((com->events & GRN_COM_POLLOUT)) { FD_SET(*pfd, &wfds); } # ifndef WIN32 if (*pfd > nfds) { nfds = *pfd; } # endif /* WIN32 */ } grn_hash_cursor_close(ctx, cursor); } } nevents = select(nfds + 1, &rfds, &wfds, NULL, (timeout >= 0) ? &tv : NULL); if (nevents < 0) { SOERR("select"); if (ctx->rc == GRN_INTERRUPTED_FUNCTION_CALL) { ERRCLR(ctx); } return ctx->rc; } if (timeout < 0 && !nevents) { GRN_LOG(ctx, GRN_LOG_NOTICE, "select returns 0 events"); } GRN_HASH_EACH(ctx, ev->hash, eh, &pfd, &dummy, &com, { if (FD_ISSET(*pfd, &rfds)) { grn_com_receiver(ctx, com); } });
static void grn_com_receiver(grn_ctx *ctx, grn_com *com) { grn_com_event *ev = com->ev; ERRCLR(ctx); if (ev->acceptor == com) { grn_com *ncs; grn_sock fd = accept(com->fd, NULL, NULL); if (fd == -1) { if (errno == EMFILE) { grn_com_event_stop_accept(ctx, ev); } else { SOERR("accept"); } return; } if (grn_com_event_add(ctx, ev, fd, GRN_COM_POLLIN, (grn_com **)&ncs)) { grn_sock_close(fd); return; } ncs->has_sid = 0; ncs->closed = 0; ncs->opaque = NULL; GRN_COM_QUEUE_INIT(&ncs->new_); // GRN_LOG(ctx, GRN_LOG_NOTICE, "accepted (%d)", fd); return; } else { grn_msg *msg = (grn_msg *)grn_msg_open(ctx, com, &ev->recv_old); grn_com_recv(ctx, msg->u.peer, &msg->header, (grn_obj *)msg); if (msg->u.peer /* is_edge_request(msg)*/) { grn_memcpy(&msg->edge_id, &ev->curr_edge_id, sizeof(grn_com_addr)); if (!com->has_sid) { com->has_sid = 1; com->sid = ev->curr_edge_id.sid++; } msg->edge_id.sid = com->sid; } msg->acceptor = ev->acceptor; ev->msg_handler(ctx, (grn_obj *)msg); } }
static void grn_db_reindex(grn_ctx *ctx, grn_obj *db) { grn_table_cursor *cursor; grn_id id; cursor = grn_table_cursor_open(ctx, db, NULL, 0, NULL, 0, 0, -1, GRN_CURSOR_BY_ID); if (!cursor) { return; } while ((id = grn_table_cursor_next(ctx, cursor)) != GRN_ID_NIL) { grn_obj *object; object = grn_ctx_at(ctx, id); if (!object) { ERRCLR(ctx); continue; } switch (object->header.type) { case GRN_TABLE_HASH_KEY : case GRN_TABLE_PAT_KEY : case GRN_TABLE_DAT_KEY : grn_obj_reindex(ctx, object); break; default: break; } grn_obj_unlink(ctx, object); if (ctx->rc != GRN_SUCCESS) { break; } } grn_table_cursor_close(ctx, cursor); }
static void brace_close(grn_ctx *ctx, grn_loader *loader) { grn_id id = GRN_ID_NIL; grn_obj *value, *value_begin, *value_end; grn_obj *id_value = NULL, *key_value = NULL; uint32_t begin; GRN_UINT32_POP(&loader->level, begin); value_begin = (grn_obj *)GRN_TEXT_VALUE(&loader->values) + begin; value_end = (grn_obj *)GRN_TEXT_VALUE(&loader->values) + loader->values_size; GRN_ASSERT(value->header.domain == GRN_JSON_LOAD_OPEN_BRACE); GRN_UINT32_SET(ctx, value_begin, loader->values_size - begin - 1); value_begin++; if (GRN_BULK_VSIZE(&loader->level) > sizeof(uint32_t) * loader->emit_level) { return; } if (!loader->table) { goto exit; } /* Scan values to find _id or _key. */ for (value = value_begin; value + 1 < value_end; value = values_next(ctx, value)) { const char *name = GRN_TEXT_VALUE(value); unsigned int name_size = GRN_TEXT_LEN(value); if (value->header.domain != GRN_DB_TEXT) { grn_obj buffer; GRN_TEXT_INIT(&buffer, 0); grn_inspect(ctx, &buffer, value); GRN_LOG(ctx, GRN_LOG_ERROR, "column name must be string: <%.*s>", (int)GRN_TEXT_LEN(&buffer), GRN_TEXT_VALUE(&buffer)); GRN_OBJ_FIN(ctx, &buffer); goto exit; } value++; if (name_equal(name, name_size, GRN_COLUMN_NAME_ID)) { if (id_value || key_value) { if (loader->table->header.type == GRN_TABLE_NO_KEY) { GRN_LOG(ctx, GRN_LOG_ERROR, "duplicated '_id' column"); goto exit; } else { GRN_LOG(ctx, GRN_LOG_ERROR, "duplicated key columns: %s and %s", id_value ? GRN_COLUMN_NAME_ID : GRN_COLUMN_NAME_KEY, GRN_COLUMN_NAME_ID); goto exit; } } id_value = value; } else if (name_equal(name, name_size, GRN_COLUMN_NAME_KEY)) { if (id_value || key_value) { GRN_LOG(ctx, GRN_LOG_ERROR, "duplicated key columns: %s and %s", id_value ? GRN_COLUMN_NAME_ID : GRN_COLUMN_NAME_KEY, GRN_COLUMN_NAME_KEY); goto exit; } key_value = value; } } switch (loader->table->header.type) { case GRN_TABLE_HASH_KEY : case GRN_TABLE_PAT_KEY : case GRN_TABLE_DAT_KEY : /* The target table requires _id or _key. */ if (!id_value && !key_value) { GRN_LOG(ctx, GRN_LOG_ERROR, "neither _key nor _id is assigned"); goto exit; } break; default : /* The target table does not have _key. */ if (key_value) { GRN_LOG(ctx, GRN_LOG_ERROR, "nonexistent key value"); goto exit; } break; } if (id_value) { id = parse_id_value(ctx, id_value); if (grn_table_at(ctx, loader->table, id) == GRN_ID_NIL) { if (ctx->rc == GRN_SUCCESS) { id = grn_table_add(ctx, loader->table, NULL, 0, NULL); } } } else if (key_value) { id = loader_add(ctx, key_value); } else { id = grn_table_add(ctx, loader->table, NULL, 0, NULL); } if (id == GRN_ID_NIL) { /* Target record is not available. */ goto exit; } for (value = value_begin; value + 1 < value_end; value = values_next(ctx, value)) { grn_obj *col; const char *name = GRN_TEXT_VALUE(value); unsigned int name_size = GRN_TEXT_LEN(value); value++; if (value == id_value || value == key_value) { /* Skip _id and _key, because it's already used to get id. */ continue; } col = grn_obj_column(ctx, loader->table, name, name_size); if (!col) { GRN_LOG(ctx, GRN_LOG_ERROR, "invalid column('%.*s')", (int)name_size, name); /* Automatic column creation is disabled. */ /* if (value->header.domain == GRN_JSON_LOAD_OPEN_BRACKET) { grn_obj *v = value + 1; col = grn_column_create(ctx, loader->table, name, name_size, NULL, GRN_OBJ_PERSISTENT|GRN_OBJ_COLUMN_VECTOR, grn_ctx_at(ctx, v->header.domain)); } else { col = grn_column_create(ctx, loader->table, name, name_size, NULL, GRN_OBJ_PERSISTENT, grn_ctx_at(ctx, value->header.domain)); } */ } else { if (value->header.domain == GRN_JSON_LOAD_OPEN_BRACKET) { set_vector(ctx, col, id, value); } else if (value->header.domain == GRN_JSON_LOAD_OPEN_BRACE) { set_weight_vector(ctx, col, id, value); } else { grn_obj_set_value(ctx, col, id, value, GRN_OBJ_SET); } if (ctx->rc != GRN_SUCCESS) { grn_loader_save_error(ctx, loader); report_set_column_value_failure(ctx, key_value, name, name_size, value); loader->n_column_errors++; ERRCLR(ctx); } grn_obj_unlink(ctx, col); } } if (loader->each) { value = grn_expr_get_var_by_offset(ctx, loader->each, 0); GRN_RECORD_SET(ctx, value, id); grn_expr_exec(ctx, loader->each, 0); } loader->nrecords++; exit: if (ctx->rc != GRN_SUCCESS) { loader->n_record_errors++; } if (loader->output_ids) { GRN_UINT32_PUT(ctx, &(loader->ids), id); } if (loader->output_errors) { GRN_INT32_PUT(ctx, &(loader->return_codes), ctx->rc); grn_vector_add_element(ctx, &(loader->error_messages), ctx->errbuf, strlen(ctx->errbuf), 0, GRN_DB_TEXT); } loader->values_size = begin; ERRCLR(ctx); }
static void bracket_close(grn_ctx *ctx, grn_loader *loader) { grn_id id = GRN_ID_NIL; grn_obj *value, *value_end, *id_value = NULL, *key_value = NULL; grn_obj *col, **cols; /* Columns except _id and _key. */ uint32_t i, begin; uint32_t ncols; /* Number of columns except _id and _key. */ uint32_t nvalues; /* Number of values in brackets. */ uint32_t depth; grn_bool is_record_load = GRN_FALSE; cols = (grn_obj **)GRN_BULK_HEAD(&loader->columns); ncols = GRN_BULK_VSIZE(&loader->columns) / sizeof(grn_obj *); GRN_UINT32_POP(&loader->level, begin); value = (grn_obj *)GRN_TEXT_VALUE(&loader->values) + begin; value_end = (grn_obj *)GRN_TEXT_VALUE(&loader->values) + loader->values_size; GRN_ASSERT(value->header.domain == GRN_JSON_LOAD_OPEN_BRACKET); GRN_UINT32_SET(ctx, value, loader->values_size - begin - 1); value++; depth = GRN_BULK_VSIZE(&loader->level); if (depth > sizeof(uint32_t) * loader->emit_level) { return; } if (depth == 0 || !loader->table || loader->columns_status == GRN_LOADER_COLUMNS_BROKEN) { goto exit; } nvalues = values_len(ctx, value, value_end); if (loader->columns_status == GRN_LOADER_COLUMNS_UNSET) { /* * Target columns and _id or _key are not specified yet and values are * handled as column names and "_id" or "_key". */ for (i = 0; i < nvalues; i++) { const char *col_name; unsigned int col_name_size; if (value->header.domain != GRN_DB_TEXT) { grn_obj buffer; GRN_TEXT_INIT(&buffer, 0); grn_inspect(ctx, &buffer, value); ERR(GRN_INVALID_ARGUMENT, "column name must be string: <%.*s>", (int)GRN_TEXT_LEN(&buffer), GRN_TEXT_VALUE(&buffer)); grn_loader_save_error(ctx, loader); GRN_OBJ_FIN(ctx, &buffer); loader->columns_status = GRN_LOADER_COLUMNS_BROKEN; goto exit; } col_name = GRN_TEXT_VALUE(value); col_name_size = GRN_TEXT_LEN(value); col = grn_obj_column(ctx, loader->table, col_name, col_name_size); if (!col) { ERR(GRN_INVALID_ARGUMENT, "nonexistent column: <%.*s>", col_name_size, col_name); grn_loader_save_error(ctx, loader); loader->columns_status = GRN_LOADER_COLUMNS_BROKEN; goto exit; } if (name_equal(col_name, col_name_size, GRN_COLUMN_NAME_ID)) { grn_obj_unlink(ctx, col); if (loader->id_offset != -1 || loader->key_offset != -1) { /* _id and _key must not appear more than once. */ if (loader->id_offset != -1) { ERR(GRN_INVALID_ARGUMENT, "duplicated id and key columns: <%s> at %d and <%s> at %d", GRN_COLUMN_NAME_ID, i, GRN_COLUMN_NAME_ID, loader->id_offset); } else { ERR(GRN_INVALID_ARGUMENT, "duplicated id and key columns: <%s> at %d and <%s> at %d", GRN_COLUMN_NAME_ID, i, GRN_COLUMN_NAME_KEY, loader->key_offset); } grn_loader_save_error(ctx, loader); loader->columns_status = GRN_LOADER_COLUMNS_BROKEN; goto exit; } loader->id_offset = i; } else if (name_equal(col_name, col_name_size, GRN_COLUMN_NAME_KEY)) { grn_obj_unlink(ctx, col); if (loader->id_offset != -1 || loader->key_offset != -1) { /* _id and _key must not appear more than once. */ if (loader->id_offset != -1) { ERR(GRN_INVALID_ARGUMENT, "duplicated id and key columns: <%s> at %d and <%s> at %d", GRN_COLUMN_NAME_KEY, i, GRN_COLUMN_NAME_ID, loader->id_offset); } else { ERR(GRN_INVALID_ARGUMENT, "duplicated id and key columns: <%s> at %d and <%s> at %d", GRN_COLUMN_NAME_KEY, i, GRN_COLUMN_NAME_KEY, loader->key_offset); } grn_loader_save_error(ctx, loader); loader->columns_status = GRN_LOADER_COLUMNS_BROKEN; goto exit; } loader->key_offset = i; } else { GRN_PTR_PUT(ctx, &loader->columns, col); } value++; } switch (loader->table->header.type) { case GRN_TABLE_HASH_KEY : case GRN_TABLE_PAT_KEY : case GRN_TABLE_DAT_KEY : if (loader->id_offset == -1 && loader->key_offset == -1) { ERR(GRN_INVALID_ARGUMENT, "missing id or key column"); grn_loader_save_error(ctx, loader); loader->columns_status = GRN_LOADER_COLUMNS_BROKEN; goto exit; } break; } loader->columns_status = GRN_LOADER_COLUMNS_SET; goto exit; } is_record_load = GRN_TRUE; /* Target columns and _id or _key are already specified. */ if (!nvalues) { /* * Accept empty arrays because a dump command may output a load command * which contains empty arrays for a table with deleted records. */ id = grn_table_add(ctx, loader->table, NULL, 0, NULL); } else { uint32_t expected_nvalues = ncols; if (loader->id_offset != -1 || loader->key_offset != -1) { expected_nvalues++; } if (nvalues != expected_nvalues) { ERR(GRN_INVALID_ARGUMENT, "unexpected #values: expected:%u, actual:%u", expected_nvalues, nvalues); grn_loader_save_error(ctx, loader); goto exit; } if (loader->id_offset != -1) { id_value = value + loader->id_offset; id = parse_id_value(ctx, id_value); if (grn_table_at(ctx, loader->table, id) == GRN_ID_NIL) { id = grn_table_add(ctx, loader->table, NULL, 0, NULL); } } else if (loader->key_offset != -1) { key_value = value + loader->key_offset; id = loader_add(ctx, key_value); } else { id = grn_table_add(ctx, loader->table, NULL, 0, NULL); } } if (id == GRN_ID_NIL) { /* Target record is not available. */ goto exit; } for (i = 0; i < nvalues; i++, value = values_next(ctx, value)) { if (i == loader->id_offset || i == loader->key_offset) { /* Skip _id and _key, because it's already used to get id. */ continue; } col = *cols; if (value->header.domain == GRN_JSON_LOAD_OPEN_BRACKET) { set_vector(ctx, col, id, value); } else if (value->header.domain == GRN_JSON_LOAD_OPEN_BRACE) { set_weight_vector(ctx, col, id, value); } else { grn_obj_set_value(ctx, col, id, value, GRN_OBJ_SET); } if (ctx->rc != GRN_SUCCESS) { char column_name[GRN_TABLE_MAX_KEY_SIZE]; unsigned int column_name_size; grn_loader_save_error(ctx, loader); column_name_size = grn_obj_name(ctx, col, column_name, GRN_TABLE_MAX_KEY_SIZE); report_set_column_value_failure(ctx, key_value, column_name, column_name_size, value); loader->n_column_errors++; ERRCLR(ctx); } cols++; } if (loader->each) { grn_obj *v = grn_expr_get_var_by_offset(ctx, loader->each, 0); GRN_RECORD_SET(ctx, v, id); grn_expr_exec(ctx, loader->each, 0); } loader->nrecords++; exit: if (is_record_load) { if (ctx->rc != GRN_SUCCESS) { loader->n_record_errors++; } if (loader->output_ids) { GRN_UINT32_PUT(ctx, &(loader->ids), id); } if (loader->output_errors) { GRN_INT32_PUT(ctx, &(loader->return_codes), ctx->rc); grn_vector_add_element(ctx, &(loader->error_messages), ctx->errbuf, strlen(ctx->errbuf), 0, GRN_DB_TEXT); } } loader->values_size = begin; ERRCLR(ctx); }
void grn_output_obj(grn_ctx *ctx, grn_obj *outbuf, grn_content_type output_type, grn_obj *obj, grn_obj_format *format) { grn_obj buf; GRN_TEXT_INIT(&buf, 0); switch (obj->header.type) { case GRN_BULK : switch (obj->header.domain) { case GRN_DB_VOID : grn_output_void(ctx, outbuf, output_type, GRN_BULK_HEAD(obj), GRN_BULK_VSIZE(obj)); break; case GRN_DB_SHORT_TEXT : case GRN_DB_TEXT : case GRN_DB_LONG_TEXT : grn_output_str(ctx, outbuf, output_type, GRN_BULK_HEAD(obj), GRN_BULK_VSIZE(obj)); break; case GRN_DB_BOOL : grn_output_bool(ctx, outbuf, output_type, GRN_BULK_VSIZE(obj) ? GRN_UINT8_VALUE(obj) : 0); break; case GRN_DB_INT8 : grn_output_int32(ctx, outbuf, output_type, GRN_BULK_VSIZE(obj) ? GRN_INT8_VALUE(obj) : 0); break; case GRN_DB_UINT8 : grn_output_int32(ctx, outbuf, output_type, GRN_BULK_VSIZE(obj) ? GRN_UINT8_VALUE(obj) : 0); break; case GRN_DB_INT16 : grn_output_int32(ctx, outbuf, output_type, GRN_BULK_VSIZE(obj) ? GRN_INT16_VALUE(obj) : 0); break; case GRN_DB_UINT16 : grn_output_int32(ctx, outbuf, output_type, GRN_BULK_VSIZE(obj) ? GRN_UINT16_VALUE(obj) : 0); break; case GRN_DB_INT32 : grn_output_int32(ctx, outbuf, output_type, GRN_BULK_VSIZE(obj) ? GRN_INT32_VALUE(obj) : 0); break; case GRN_DB_UINT32 : grn_output_int64(ctx, outbuf, output_type, GRN_BULK_VSIZE(obj) ? GRN_UINT32_VALUE(obj) : 0); break; case GRN_DB_INT64 : grn_output_int64(ctx, outbuf, output_type, GRN_BULK_VSIZE(obj) ? GRN_INT64_VALUE(obj) : 0); break; case GRN_DB_UINT64 : grn_output_uint64(ctx, outbuf, output_type, GRN_BULK_VSIZE(obj) ? GRN_UINT64_VALUE(obj) : 0); break; case GRN_DB_FLOAT : grn_output_float(ctx, outbuf, output_type, GRN_BULK_VSIZE(obj) ? GRN_FLOAT_VALUE(obj) : 0); break; case GRN_DB_TIME : grn_output_time(ctx, outbuf, output_type, GRN_BULK_VSIZE(obj) ? GRN_INT64_VALUE(obj) : 0); break; case GRN_DB_TOKYO_GEO_POINT : case GRN_DB_WGS84_GEO_POINT : grn_output_geo_point(ctx, outbuf, output_type, GRN_BULK_VSIZE(obj) ? (grn_geo_point *)GRN_BULK_HEAD(obj) : NULL); break; default : if (format) { int j; int ncolumns = GRN_BULK_VSIZE(&format->columns)/sizeof(grn_obj *); grn_obj **columns = (grn_obj **)GRN_BULK_HEAD(&format->columns); if (format->flags & GRN_OBJ_FORMAT_WITH_COLUMN_NAMES) { grn_output_array_open(ctx, outbuf, output_type, "COLUMNS", ncolumns); for (j = 0; j < ncolumns; j++) { grn_id range_id; grn_output_array_open(ctx, outbuf, output_type, "COLUMN", 2); GRN_BULK_REWIND(&buf); grn_column_name_(ctx, columns[j], &buf); grn_output_obj(ctx, outbuf, output_type, &buf, NULL); /* column range */ range_id = grn_obj_get_range(ctx, columns[j]); if (range_id == GRN_ID_NIL) { GRN_TEXT_PUTS(ctx, outbuf, "null"); } else { int name_len; grn_obj *range_obj; char name_buf[GRN_TABLE_MAX_KEY_SIZE]; range_obj = grn_ctx_at(ctx, range_id); name_len = grn_obj_name(ctx, range_obj, name_buf, GRN_TABLE_MAX_KEY_SIZE); GRN_BULK_REWIND(&buf); GRN_TEXT_PUT(ctx, &buf, name_buf, name_len); grn_output_obj(ctx, outbuf, output_type, &buf, NULL); } grn_output_array_close(ctx, outbuf, output_type); } grn_output_array_close(ctx, outbuf, output_type); } grn_output_array_open(ctx, outbuf, output_type, "HIT", ncolumns); for (j = 0; j < ncolumns; j++) { grn_text_atoj_o(ctx, outbuf, output_type, columns[j], obj); } grn_output_array_close(ctx, outbuf, output_type); } else { grn_obj *table = grn_ctx_at(ctx, obj->header.domain); grn_id id = *((grn_id *)GRN_BULK_HEAD(obj)); if (table && table->header.type != GRN_TABLE_NO_KEY) { grn_obj *accessor = grn_obj_column(ctx, table, "_key", 4); if (accessor) { grn_obj_get_value(ctx, accessor, id, &buf); grn_obj_unlink(ctx, accessor); } grn_output_obj(ctx, outbuf, output_type, &buf, format); } else { grn_output_int64(ctx, outbuf, output_type, id); } } break; } break; case GRN_UVECTOR : if (format) { int i, j; grn_id *v = (grn_id *)GRN_BULK_HEAD(obj), *ve = (grn_id *)GRN_BULK_CURR(obj); int ncolumns = GRN_BULK_VSIZE(&format->columns) / sizeof(grn_obj *); grn_obj **columns = (grn_obj **)GRN_BULK_HEAD(&format->columns); grn_output_array_open(ctx, outbuf, output_type, "RESULTSET", -1); grn_output_array_open(ctx, outbuf, output_type, "NHITS", 1); grn_text_itoa(ctx, outbuf, ve - v); grn_output_array_close(ctx, outbuf, output_type); if (v < ve) { if (format->flags & GRN_OBJ_FORMAT_WITH_COLUMN_NAMES) { grn_output_array_open(ctx, outbuf, output_type, "COLUMNS", -1); for (j = 0; j < ncolumns; j++) { grn_id range_id; grn_output_array_open(ctx, outbuf, output_type, "COLUMN", -1); GRN_BULK_REWIND(&buf); grn_column_name_(ctx, columns[j], &buf); grn_output_obj(ctx, outbuf, output_type, &buf, NULL); /* column range */ range_id = grn_obj_get_range(ctx, columns[j]); if (range_id == GRN_ID_NIL) { GRN_TEXT_PUTS(ctx, outbuf, "null"); } else { int name_len; grn_obj *range_obj; char name_buf[GRN_TABLE_MAX_KEY_SIZE]; range_obj = grn_ctx_at(ctx, range_id); name_len = grn_obj_name(ctx, range_obj, name_buf, GRN_TABLE_MAX_KEY_SIZE); GRN_BULK_REWIND(&buf); GRN_TEXT_PUT(ctx, &buf, name_buf, name_len); grn_output_obj(ctx, outbuf, output_type, &buf, NULL); } grn_output_array_close(ctx, outbuf, output_type); } grn_output_array_close(ctx, outbuf, output_type); } for (i = 0;; i++) { grn_output_array_open(ctx, outbuf, output_type, "HITS", -1); for (j = 0; j < ncolumns; j++) { GRN_BULK_REWIND(&buf); grn_obj_get_value(ctx, columns[j], *v, &buf); grn_output_obj(ctx, outbuf, output_type, &buf, NULL); } grn_output_array_close(ctx, outbuf, output_type); v++; if (v < ve) { } else { break; } } } grn_output_array_close(ctx, outbuf, output_type); } else { grn_obj *range = grn_ctx_at(ctx, obj->header.domain); if (range && range->header.type == GRN_TYPE) { int value_size = ((struct _grn_type *)range)->obj.range; char *v = (char *)GRN_BULK_HEAD(obj), *ve = (char *)GRN_BULK_CURR(obj); grn_output_array_open(ctx, outbuf, output_type, "VECTOR", -1); if (v < ve) { for (;;) { grn_obj value; GRN_OBJ_INIT(&value, GRN_BULK, 0, obj->header.domain); grn_bulk_write_from(ctx, &value, v, 0, value_size); grn_output_obj(ctx, outbuf, output_type, &value, NULL); v += value_size; if (v < ve) { } else { break; } } } grn_output_array_close(ctx, outbuf, output_type); } else { grn_id *v = (grn_id *)GRN_BULK_HEAD(obj), *ve = (grn_id *)GRN_BULK_CURR(obj); grn_output_array_open(ctx, outbuf, output_type, "VECTOR", ve - v); if (v < ve) { grn_obj key; GRN_OBJ_INIT(&key, GRN_BULK, 0, range->header.domain); for (;;) { if (range->header.type != GRN_TABLE_NO_KEY) { grn_table_get_key2(ctx, range, *v, &key); grn_output_obj(ctx, outbuf, output_type, &key, NULL); GRN_BULK_REWIND(&key); } else { grn_obj id; GRN_UINT32_INIT(&id, 0); GRN_UINT32_SET(ctx, &id, *v); grn_output_obj(ctx, outbuf, output_type, &id, NULL); GRN_OBJ_FIN(ctx, &id); } v++; if (v < ve) { } else { break; } } GRN_OBJ_FIN(ctx, &key); } grn_output_array_close(ctx, outbuf, output_type); } } break; case GRN_VECTOR : if (obj->header.domain == GRN_DB_VOID) { ERR(GRN_INVALID_ARGUMENT, "invalid obj->header.domain"); } if (format) { ERR(GRN_FUNCTION_NOT_IMPLEMENTED, "cannot print GRN_VECTOR using grn_obj_format"); } else { unsigned int i, n; grn_obj value; GRN_VOID_INIT(&value); n = grn_vector_size(ctx, obj); grn_output_array_open(ctx, outbuf, output_type, "VECTOR", -1); for (i = 0; i < n; i++) { const char *_value; unsigned int weight, length; grn_id domain; length = grn_vector_get_element(ctx, obj, i, &_value, &weight, &domain); if (domain != GRN_DB_VOID) { grn_obj_reinit(ctx, &value, domain, 0); } else { grn_obj_reinit(ctx, &value, obj->header.domain, 0); } grn_bulk_write(ctx, &value, _value, length); grn_output_obj(ctx, outbuf, output_type, &value, NULL); } grn_output_array_close(ctx, outbuf, output_type); GRN_OBJ_FIN(ctx, &value); } break; case GRN_PVECTOR : if (format) { ERR(GRN_FUNCTION_NOT_IMPLEMENTED, "cannot print GRN_PVECTOR using grn_obj_format"); } else { unsigned int i, n; grn_output_array_open(ctx, outbuf, output_type, "VECTOR", -1); n = GRN_BULK_VSIZE(obj) / sizeof(grn_obj *); for (i = 0; i < n; i++) { grn_obj *value; value = GRN_PTR_VALUE_AT(obj, i); grn_output_obj(ctx, outbuf, output_type, value, NULL); } grn_output_array_close(ctx, outbuf, output_type); } break; case GRN_TABLE_HASH_KEY : case GRN_TABLE_PAT_KEY : case GRN_TABLE_NO_KEY : case GRN_TABLE_VIEW : if (format) { int i, j; int ncolumns = GRN_BULK_VSIZE(&format->columns)/sizeof(grn_obj *); grn_obj **columns = (grn_obj **)GRN_BULK_HEAD(&format->columns); grn_table_cursor *tc = grn_table_cursor_open(ctx, obj, NULL, 0, NULL, 0, format->offset, format->limit, GRN_CURSOR_ASCENDING); int resultset_size = -1; if (!tc) { ERRCLR(ctx); } #ifdef HAVE_MESSAGE_PACK resultset_size = 1; /* [NHITS, (COLUMNS), (HITS)] */ if (format->flags & GRN_OBJ_FORMAT_WITH_COLUMN_NAMES) { resultset_size++; } resultset_size += format->limit; #endif grn_output_array_open(ctx, outbuf, output_type, "RESULTSET", resultset_size); grn_output_array_open(ctx, outbuf, output_type, "NHITS", 1); if (output_type == GRN_CONTENT_XML) { grn_text_itoa(ctx, outbuf, format->nhits); } else { grn_output_int32(ctx, outbuf, output_type, format->nhits); } grn_output_array_close(ctx, outbuf, output_type); if (format->flags & GRN_OBJ_FORMAT_WITH_COLUMN_NAMES) { grn_output_array_open(ctx, outbuf, output_type, "COLUMNS", ncolumns); for (j = 0; j < ncolumns; j++) { grn_id range_id; grn_output_array_open(ctx, outbuf, output_type, "COLUMN", 2); GRN_BULK_REWIND(&buf); grn_column_name_(ctx, columns[j], &buf); grn_output_obj(ctx, outbuf, output_type, &buf, NULL); /* column range */ range_id = grn_obj_get_range(ctx, columns[j]); if (range_id == GRN_ID_NIL) { GRN_TEXT_PUTS(ctx, outbuf, "null"); } else { int name_len; grn_obj *range_obj; char name_buf[GRN_TABLE_MAX_KEY_SIZE]; range_obj = grn_ctx_at(ctx, range_id); name_len = grn_obj_name(ctx, range_obj, name_buf, GRN_TABLE_MAX_KEY_SIZE); GRN_BULK_REWIND(&buf); GRN_TEXT_PUT(ctx, &buf, name_buf, name_len); grn_output_obj(ctx, outbuf, output_type, &buf, NULL); } grn_output_array_close(ctx, outbuf, output_type); } grn_output_array_close(ctx, outbuf, output_type); } if (tc) { grn_obj id; GRN_TEXT_INIT(&id, 0); for (i = 0; !grn_table_cursor_next_o(ctx, tc, &id); i++) { grn_output_array_open(ctx, outbuf, output_type, "HIT", ncolumns); for (j = 0; j < ncolumns; j++) { grn_text_atoj_o(ctx, outbuf, output_type, columns[j], &id); } grn_output_array_close(ctx, outbuf, output_type); } GRN_OBJ_FIN(ctx, &id); grn_table_cursor_close(ctx, tc); } grn_output_array_close(ctx, outbuf, output_type); } else { int i; grn_obj *column = grn_obj_column(ctx, obj, "_key", 4); grn_table_cursor *tc = grn_table_cursor_open(ctx, obj, NULL, 0, NULL, 0, 0, -1, GRN_CURSOR_ASCENDING); grn_output_array_open(ctx, outbuf, output_type, "HIT", -1); if (tc) { grn_obj id; GRN_TEXT_INIT(&id, 0); for (i = 0; !grn_table_cursor_next_o(ctx, tc, &id); i++) { /* todo: grn_text_atoj_o(ctx, outbuf, output_type, column, &id); */ GRN_BULK_REWIND(&buf); grn_obj_get_value_o(ctx, column, &id, &buf); grn_text_esc(ctx, outbuf, GRN_BULK_HEAD(&buf), GRN_BULK_VSIZE(&buf)); } GRN_OBJ_FIN(ctx, &id); grn_table_cursor_close(ctx, tc); } grn_output_array_close(ctx, outbuf, output_type); grn_obj_unlink(ctx, column); } break; } GRN_OBJ_FIN(ctx, &buf); }