Example #1
0
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;
}
Example #3
0
/*
 * 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;
}
Example #4
0
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, &ltk));
			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;
}