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; }
void test_insert_field() { header(); printf("# insert tuple\n"); struct tnt_tuple *tuple = tnt_tuple(NULL, "%d%s", 9, "eleven"); insert_tuple(tuple); tnt_tuple_free(tuple); printf("# insert new field before primary key\n"); struct tnt_stream *stream = tnt_buf(NULL); update_insert_i32(stream, 0, 7); update_insert_i32(stream, 0, 8); update(9, stream); tnt_stream_free(stream); printf("# insert a new field before last field\n"); stream = tnt_buf(NULL); update_insert_i32(stream, 3, 10); update(7, stream); tnt_stream_free(stream); printf("# double insert at the end\n"); stream = tnt_buf(NULL); update_set_i32(stream, 5, 14); update_insert_i32(stream, 6, 12); update_insert_i32(stream, 5, 13); update(7, stream); tnt_stream_free(stream); printf("# multi insert \n"); stream = tnt_buf(NULL); update_insert_i32(stream, 5, 15); update_insert_i32(stream, 5, 14); update_insert_i32(stream, 5, 13); update_insert_i32(stream, 5, 12); update(7, stream); tnt_stream_free(stream); printf("# insert before next to last field\n"); stream = tnt_buf(NULL); update_insert_i32(stream, 8, 15); update(7, stream); tnt_stream_free(stream); printf("# insert before next to last field\n"); stream = tnt_buf(NULL); update_set_i32(stream, 9, 17); update_insert_i32(stream, 9, 16); update_set_i32(stream, 10, 19); update_insert_i32(stream, 10, 18); update(7, stream); tnt_stream_free(stream); printf("# insert second tuple\n"); tuple = tnt_tuple(NULL, "%d%s%d", 0, "one", 11); insert_tuple(tuple); tnt_tuple_free(tuple); stream = tnt_buf(NULL); printf("# multi insert\n"); update_set_i32(stream, 1, -11); tnt_update_arith(stream, 1, TNT_UPDATE_ADD, 1); update_insert_i32(stream, 1, 1); tnt_update_arith(stream, 1, TNT_UPDATE_ADD, 2); update_insert_i32(stream, 1, 2); update_insert_i32(stream, 1, 3); tnt_update_arith(stream, 1, TNT_UPDATE_ADD, 3); tnt_update_arith(stream, 1, TNT_UPDATE_ADD, 4); tnt_update_arith(stream, 1, TNT_UPDATE_ADD, 5); update_insert_i32(stream, 1, 4); update_insert_i32(stream, 1, 5); tnt_update_arith(stream, 1, TNT_UPDATE_ADD, 6); update_insert_i32(stream, 1, 6); update_insert_i32(stream, 1, 7); update_insert_i32(stream, 1, 8); update_insert_i32(stream, 1, 9); update(0, stream); tnt_stream_free(stream); printf("# insert before invalid field number\n"); stream = tnt_buf(NULL); update_insert_str(stream, 100000, "ooppps!"); update(7, stream); tnt_stream_free(stream); footer(); }