void select_tuple(int32_t key) { struct tnt_list tuple_list; tnt_list_init(&tuple_list); struct tnt_tuple *tuple = tnt_list_at(&tuple_list, NULL); tnt_tuple(tuple, "%d", key); if (tnt_select(tnt, 0, 0, 0, 1, &tuple_list) < 0) fail_tnt_perror("tnt_select"); if (tnt_flush(tnt) < 0) fail_tnt_perror("tnt_flush"); recv_command("select"); tnt_list_free(&tuple_list); }
static int tnt_request_select(struct tnt_request *r, tnt_request_t rcv, void *ptr) { if (rcv(ptr, (char*)&r->r.select, sizeof(struct tnt_header_select)) == -1) return -1; uint32_t size = r->h.len - sizeof(struct tnt_header_select); char *buf = tnt_mem_alloc(size); if (buf == NULL) goto error; if (rcv(ptr, buf, size) == -1) goto error; /* count of tuples */ uint32_t i, count = *(uint32_t*)buf; uint32_t off = 4; /* processing tuples */ tnt_list_init(&r->r.select.l); for (i = 0 ; i < count ; i++) { /* calculating tuple size */ uint32_t j, cardinality = *(uint32_t*)(buf + off); uint32_t size = 4; for (j = 0 ; j < cardinality ; j++) { uint32_t fld_size = 0; int fld_esize = tnt_enc_read(buf + off + size, &fld_size); if (fld_esize == -1) goto error; size += fld_esize + fld_size; } /* initializing tuple and adding to list */ struct tnt_tuple *tu = tnt_list_at(&r->r.select.l, NULL); if (tnt_tuple_set(tu, buf + off, size) == NULL) goto error; off += size; } tnt_mem_free(buf); return 0; error: tnt_list_free(&r->r.select.l); if (buf) tnt_mem_free(buf); return -1; }
/* * tnt_reply_from() * * process iproto reply with supplied recv function; * * r - reply object pointer * rcv - supplied recv function * ptr - recv function argument * * returns zero on fully read reply, or -1 on error. */ int tnt_reply_from(struct tnt_reply *r, tnt_replyf_t rcv, void *ptr) { /* reading iproto header */ struct tnt_header hdr; if (rcv(ptr, (char*)&hdr, sizeof(struct tnt_header)) == -1) return -1; uint32_t size = hdr.len; tnt_list_init(&r->tuples); r->count = 0; r->error = NULL; r->reqid = hdr.reqid; r->code = 0; r->op = hdr.type; /* ping is the simplest case */ if (r->op == TNT_OP_PING) return 0; /* checking validity of operation */ if (r->op != TNT_OP_INSERT && r->op != TNT_OP_UPDATE && r->op != TNT_OP_DELETE && r->op != TNT_OP_SELECT && r->op != TNT_OP_CALL) return -1; /* reading code */ if (rcv(ptr, (char*)&r->code, sizeof(r->code)) == -1) return -1; size -= 4; /* error handling */ if (r->code != 0) { r->error = tnt_mem_alloc(size); if (r->error == NULL) return -1; if (rcv(ptr, r->error, size) == -1) { tnt_mem_free(r->error); return -1; } return 0; } /* code only (BOX_QUIET flag) */ if (size == 0) return 0; /* reading count */ if (rcv(ptr, (char*)&r->count, sizeof(r->count)) == -1) return -1; size -= 4; /* count only */ if (size == 0) return 0; /* allocating and reading data */ char *buf = tnt_mem_alloc(size); if (buf == NULL) return -1; if (rcv(ptr, buf, size) == -1) { free(buf); return -1; } char *p = buf; /* processing tuples */ uint32_t total = 0; uint32_t i; for (i = 0 ; i < r->count ; i++) { uint32_t tsize = *(uint32_t*)(p); /* tuple size */ if (tsize > (size - total)) goto rollback; p += 4; /* [count, enc0, data0, ...] */ struct tnt_tuple *t = tnt_tuple_set(NULL, p, tsize + 4 /* count */); if (t == NULL) goto rollback; tnt_list_at(&r->tuples, t); p += tsize + 4; total += (4 + 4 + tsize); /* length + cardinality + tuple size */ } free(buf); return 0; rollback: tnt_list_free(&r->tuples); free(buf); return -1; }
static bool tnt_sql_stmt(struct tnt_sql *sql) { struct tnt_tuple tu; struct tnt_list tuples; struct tnt_stream update; tnt_tuple_init(&tu); tnt_list_init(&tuples); tnt_buf(&update); int flags = 0; struct tnt_tk *tk = NULL, *tn = NULL; bool rc = false; switch (tnt_lex(sql->l, &tk)) { /* <INSERT|REPLACE> [INTO] TABLE VALUES ( list ) */ case TNT_TK_INSERT: case TNT_TK_REPLACE: tnt_sqltry(sql, TNT_TK_INTO); if (sql->error) goto error; tnt_expect(tnt_sqltkv(sql, TNT_TK_TABLE, &tn)); tnt_expect(tnt_sqltk(sql, TNT_TK_VALUES)); tnt_expect(tnt_sqltk(sql, '(')); while (1) { tnt_expect(tnt_sql_kv(sql, &tu, false)); if (tnt_sqltry(sql, ',')) continue; if (sql->error) goto error; break; } flags = TNT_FLAG_ADD; if (tk->tk == TNT_TK_REPLACE) flags = TNT_FLAG_REPLACE; tnt_expect(tnt_sqltk(sql, ')')); tnt_expect(tnt_sqltk(sql, TNT_TK_EOF)); if (tnt_insert(sql->s, TNT_TK_I32(tn), flags, &tu) == -1) { tnt_sql_error(sql, tk, "insert failed"); goto error; } break; /* UPDATE TABLE SET operations WHERE predicate */ case TNT_TK_UPDATE: if (!tnt_sql_stmt_update(sql, &tu, &update)) goto error; break; /* DELETE FROM TABLE WHERE predicate */ case TNT_TK_DELETE: tnt_expect(tnt_sqltk(sql, TNT_TK_FROM)); tnt_expect(tnt_sqltkv(sql, TNT_TK_TABLE, &tn)); tnt_expect(tnt_sqltk(sql, TNT_TK_WHERE)); /* predicate */ tnt_expect(tnt_sql_kv(sql, &tu, true)); tnt_expect(tnt_sqltk(sql, TNT_TK_EOF)); if (tnt_delete(sql->s, TNT_TK_I32(tn), 0, &tu) == -1) { tnt_sql_error(sql, tk, "delete failed"); goto error; } break; /* SELECT * FROM TABLE WHERE predicate OR predicate... LIMIT NUM */ case TNT_TK_SELECT: { tnt_expect(tnt_sqltk(sql, '*')); tnt_expect(tnt_sqltk(sql, TNT_TK_FROM)); tnt_expect(tnt_sqltkv(sql, TNT_TK_TABLE, &tn)); tnt_expect(tnt_sqltk(sql, TNT_TK_WHERE)); int32_t index = -1; while (1) { struct tnt_tuple *tup = tnt_list_at(&tuples, NULL); while (1) { tnt_expect(tnt_sql_kv_select(sql, tup, &index)); if (tnt_sqltry(sql, TNT_TK_AND)) continue; if (sql->error) goto error; break; } if (tnt_sqltry(sql, TNT_TK_OR)) continue; if (sql->error) goto error; break; } uint32_t limit = UINT32_MAX; if (tnt_sqltry(sql, TNT_TK_LIMIT)) { struct tnt_tk *ltk; tnt_expect(tnt_sqltkv(sql, TNT_TK_NUM32, <k)); limit = TNT_TK_I32(ltk); } else if (sql->error) goto error; tnt_expect(tnt_sqltk(sql, TNT_TK_EOF)); if (tnt_select(sql->s, TNT_TK_I32(tn), index, 0, limit, &tuples) == -1) { tnt_sql_error(sql, tk, "select failed"); goto error; } break; } /* CALL NAME[{.NAME}+](STRING [{,STRING}+]) */ case TNT_TK_CALL: { char proc[512]; int len = 0; while (1) { struct tnt_tk *name = NULL; tnt_lex_idonly(sql->l, true); tnt_expect(tnt_sqltkv(sql, TNT_TK_ID, &name)); tnt_lex_idonly(sql->l, false); len += snprintf(proc + len, sizeof(proc) - len, "%.*s", (int)TNT_TK_S(name)->size, TNT_TK_S(name)->data); if (!tnt_sqltry(sql, '.')) break; if (sql->error) goto error; len += snprintf(proc + len, sizeof(proc) - len, "%s", "."); } tnt_expect(tnt_sqltk(sql, '(')); if (tnt_sqltry(sql, ')')) goto noargs; if (sql->error) goto error; while (1) { tnt_expect(tnt_sql_kv(sql, &tu, false)); if (tnt_sqltry(sql, ',')) continue; if (sql->error) goto error; break; } tnt_expect(tnt_sqltk(sql, ')')); noargs: tnt_expect(tnt_sqltk(sql, TNT_TK_EOF)); if (tnt_call(sql->s, 0, proc, &tu) == -1) { tnt_sql_error(sql, tk, "call failed"); goto error; } break; } /* PING */ case TNT_TK_PING: tnt_expect(tnt_sqltk(sql, TNT_TK_EOF)); if (tnt_ping(sql->s) == -1) { tnt_sql_error(sql, tk, "ping failed"); goto error; } break; case TNT_TK_EOF: break; case TNT_TK_ERROR: return tnt_sql_error(sql, tk, "%s", sql->l->error); default: return tnt_sql_error(sql, tk, "insert, replace, update, delete, select, call, ping are expected"); } rc = true; error: tnt_tuple_free(&tu); tnt_list_free(&tuples); tnt_stream_free(&update); return rc; }