Exemplo n.º 1
0
/*
 * tnt_query_is()
 *
 * Tells if the supplied query should be processed as SQL.
 *
 * q     - sql query string
 * qsize - query size
 * 
 * returns 1 if yes, 0 otherwise.
*/
int
tnt_query_is(char *q, size_t qsize)
{
	struct tnt_lex l;
	if (!tnt_lex_init(&l, tnt_sql_keywords, (unsigned char*)q, qsize))
		return 0;
	int rc = 0;
	struct tnt_tk *tk;
	switch (tnt_lex(&l, &tk)) {
	case TNT_TK_ERROR:
	case TNT_TK_EOF:
		break;
	default:
		if (tk->tk == TNT_TK_PING    ||
		    tk->tk == TNT_TK_INSERT  ||
		    tk->tk == TNT_TK_REPLACE ||
		    tk->tk == TNT_TK_UPDATE  ||
		    tk->tk == TNT_TK_SELECT  ||
		    tk->tk == TNT_TK_DELETE  ||
		    tk->tk == TNT_TK_CALL)
			rc = 1;
		break;
	}
	tnt_lex_free(&l);
	return rc;
}
Exemplo n.º 2
0
static bool
tnt_sql_keyval(struct tnt_sql *sql, struct tnt_tuple *tu, bool key, struct tnt_tk **kt)
{
	/* key */
	struct tnt_tk *k = NULL;
	if (key && (!tnt_sqltkv(sql, TNT_TK_KEY, &k) || !tnt_sqltk(sql, '=')))
		return false;
	if (kt)
		*kt = k;
	/* value */
	struct tnt_tk *v = NULL;
	if (tnt_lex(sql->l, &v) == TNT_TK_ERROR)
		return tnt_sql_error(sql, NULL, "%s", sql->l->error);
	switch (v->tk) {
	case TNT_TK_NUM32:
		tnt_tuple_add(tu, (char*)&TNT_TK_I32(v), 4);
		break;
	case TNT_TK_NUM64:
		tnt_tuple_add(tu, (char*)&TNT_TK_I64(v), 8);
		break;
	case TNT_TK_STRING:
		tnt_tuple_add(tu, (char*)TNT_TK_S(v)->data,
			      TNT_TK_S(v)->size);
		break;
	default:
		return tnt_sql_error(sql, k, "expected NUM32 or NUM64 or STRING");
	}
	return true;
}
Exemplo n.º 3
0
static bool
tnt_sql_try(struct tnt_sql *sql, int tk, struct tnt_tk **tkp) {
	struct tnt_tk *tkp_ = NULL;
	int tk_ = tnt_lex(sql->l, &tkp_);
	if (tk_ == TNT_TK_ERROR) 
		return tnt_sql_error(sql, NULL, "%s", sql->l->error);
	if (tk_ != tk) {
		tnt_lex_push(sql->l, tkp_);
		return false;
	}
	if (tkp)
		*tkp = tkp_;
	return true;
}
Exemplo n.º 4
0
static bool
tnt_sql_tk(struct tnt_sql *sql, int tk, struct tnt_tk **tkp)
{
	struct tnt_tk *tkp_ = NULL;
	int tk_ = tnt_lex(sql->l, &tkp_);
	if (tk_ == TNT_TK_ERROR)
		return tnt_sql_error(sql, NULL, "%s", sql->l->error);
	if (tk_ != tk) {
		if (tk < 0xff && ispunct(tk))
			return tnt_sql_error(sql, tkp_, "expected '%c'", tk);
		return tnt_sql_error(sql, tkp_, "expected '%s'", tnt_lex_nameof(sql->l, tk));
	}
	if (tkp)
		*tkp = tkp_;
	return true;
}
Exemplo n.º 5
0
static int
nb_config_expect(struct nb_config *cfg, int tk, struct tnt_tk **tkp)
{
	struct tnt_tk *tkp_ = NULL;
	int tk_ = tnt_lex(&cfg->lex, &tkp_);
	if (tk_ == TNT_TK_ERROR)
		return nb_config_error(cfg, NULL, "%s", cfg->lex.error);
	if (tk_ != tk) {
		if (tk < 0xff && ispunct(tk))
			return nb_config_error(cfg, tkp_, "expected '%c'", tk);
		return nb_config_error(cfg, tkp_, "expected '%s'",
				       tnt_lex_nameof(&cfg->lex, tk));
	}
	if (tkp)
		*tkp = tkp_;
	return 0;
}
Exemplo n.º 6
0
static int nb_config_process(struct nb_config *cfg)
{
	struct tnt_tk *tk;
	if (nb_config_expect(cfg, NB_TK_CONFIGURATION, NULL) == -1)
		return -1;
	if (nb_config_expect(cfg, '{', NULL) == -1)
		return -1;
	int eoc = 0;
	while (!eoc) {
		tnt_lex(&cfg->lex, &tk);
		if (nb_config_read(cfg, tk) == 0)
			continue;
		if (tk->tk == TNT_TK_PUNCT && tk->v.i32 == '}')
			eoc = 1;
		else
			return nb_config_error(cfg, tk, "unknown option");
	}
	return 0;
}
Exemplo n.º 7
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;
}
Exemplo n.º 8
0
static bool
tnt_sql_stmt_update(struct tnt_sql *sql, struct tnt_tuple *tu, struct tnt_stream *u)
{
	/* UPDATE TABLE SET operations WHERE predicate */
	bool rc = false;
	struct tnt_tk *tn = NULL;
	tnt_expect(tnt_sqltkv(sql, TNT_TK_TABLE, &tn));
	tnt_expect(tnt_sqltk(sql, TNT_TK_SET));
	while (1) {
		struct tnt_tk *k = NULL;
		tnt_expect(tnt_sqltkv(sql, TNT_TK_KEY, &k));
		tnt_expect(tnt_sqltk(sql, '='));
		struct tnt_tk *v;
		switch (tnt_lex(sql->l, &v)) {
		/* k = k op v */
		case TNT_TK_KEY:
			if (TNT_TK_I32(k) != TNT_TK_I32(v)) {
				tnt_sql_error(sql, k, "can't update on different keys");
				goto error;
			}
			int ut;
			switch (tnt_lex(sql->l, &v)) {
			case TNT_TK_ERROR:
				tnt_sql_error(sql, k, "%s", sql->l->error);
				goto error;
			case '+': ut = TNT_UPDATE_ADD;
				break;
			case '&': ut = TNT_UPDATE_AND;
				break;
			case '^': ut = TNT_UPDATE_XOR;
				break;
			case '|': ut = TNT_UPDATE_OR;
				break;
			default:
				tnt_sql_error(sql, k, "bad update operation");
				goto error;
			}
			tnt_expect(tnt_sqltkv(sql, TNT_TK_NUM32, &v));
			tnt_update_arith(u, TNT_TK_I32(k), ut, TNT_TK_I32(v));
			break;
		/* k = string */
		case TNT_TK_STRING:
			tnt_update_assign(u, TNT_TK_I32(k), (char*)TNT_TK_S(v)->data,
					  TNT_TK_S(v)->size);
			break;
		/* k = num32 */
		case TNT_TK_NUM32:
			tnt_update_assign(u, TNT_TK_I32(k), (char*)&TNT_TK_I32(v), 4);
			break;
		/* k = num64 */
		case TNT_TK_NUM64:
			tnt_update_assign(u, TNT_TK_I64(k), (char*)&TNT_TK_I64(v), 8);
			break;
		/* k = splice(k, a, b) */
		case TNT_TK_SPLICE: {
			struct tnt_tk *field = NULL, *off = NULL,
				      *len = NULL, *list = NULL;
			tnt_expect(tnt_sqltk(sql, '('));
			tnt_expect(tnt_sqltkv(sql, TNT_TK_KEY, &field));
			if (TNT_TK_I32(k) != TNT_TK_I32(field)) {
				tnt_sql_error(sql, k, "can't update on different keys");
				goto error;
			}
			tnt_expect(tnt_sqltk(sql, ','));
			tnt_expect(tnt_sqltkv(sql, TNT_TK_NUM32, &off));
			tnt_expect(tnt_sqltk(sql, ','));
			tnt_expect(tnt_sqltkv(sql, TNT_TK_NUM32, &len));
			tnt_expect(tnt_sqltk(sql, ','));
			tnt_expect(tnt_sqltkv(sql, TNT_TK_STRING, &list));
			tnt_expect(tnt_sqltk(sql, ')'));
			tnt_update_splice(u, TNT_TK_I32(k), TNT_TK_I32(off), TNT_TK_I32(len),
					  (char*)TNT_TK_S(list)->data,
					  TNT_TK_S(list)->size);
			break;
		}
		case TNT_TK_ERROR:
			tnt_sql_error(sql, k, "%s", sql->l->error);
			goto error;
		}
		if (tnt_sqltry(sql, ','))
			continue;
		if (sql->error)
			goto error;
		break;
	}
	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_update(sql->s, TNT_TK_I32(tn), 0, tu, u) == -1) {
		tnt_sql_error(sql, tn, "update failed");
		goto error;
	}
	rc = true;
error:
	return rc;
}