Skip to content

Commit de3238d

Browse files
committed
Add SET STATEMENT RETURN TYPES
Signed-off-by: Salil Chandra <schandra107@bloomberg.net>
1 parent 8e99faa commit de3238d

File tree

2 files changed

+7199
-17
lines changed

2 files changed

+7199
-17
lines changed

cdb2api/cdb2api.c

Lines changed: 146 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1004,6 +1004,11 @@ typedef struct cnonce {
10041004
#define TYPE_LEN 64
10051005
#define POLICY_LEN 24
10061006

1007+
struct cdb2_stmt_types {
1008+
int n;
1009+
int types[0];
1010+
};
1011+
10071012
struct cdb2_hndl {
10081013
char dbname[DBNAME_LEN];
10091014
char cluster[64];
@@ -1102,6 +1107,7 @@ struct cdb2_hndl {
11021107
struct cdb2_hndl *fdb_hndl;
11031108
int is_child_hndl;
11041109
CDB2SQLQUERY__IdentityBlob *id_blob;
1110+
struct cdb2_stmt_types *stmt_types;
11051111
};
11061112

11071113
static void *cdb2_protobuf_alloc(void *allocator_data, size_t size)
@@ -3766,6 +3772,11 @@ int cdb2_close(cdb2_hndl_tp *hndl)
37663772
if (!hndl)
37673773
return 0;
37683774

3775+
if (hndl->stmt_types) {
3776+
free(hndl->stmt_types);
3777+
hndl->stmt_types = NULL;
3778+
}
3779+
37693780
if (hndl->fdb_hndl) {
37703781
cdb2_close(hndl->fdb_hndl);
37713782
hndl->fdb_hndl = NULL;
@@ -4399,6 +4410,94 @@ static inline void clear_snapshot_info(cdb2_hndl_tp *hndl, int line)
43994410
hndl->is_retry = 0;
44004411
}
44014412

4413+
static const struct {
4414+
const char *name;
4415+
size_t name_sz;
4416+
cdb2_coltype type;
4417+
} all_types[] = {{"INTEGER", sizeof("INTEGER") - 1, CDB2_INTEGER},
4418+
{"CSTRING", sizeof("CSTRING") - 1, CDB2_CSTRING},
4419+
{"REAL", sizeof("REAL") - 1, CDB2_REAL},
4420+
{"BLOB", sizeof("BLOB") - 1, CDB2_BLOB},
4421+
{"DATETIME", sizeof("DATETIME") - 1, CDB2_DATETIME},
4422+
{"DATETIMEUS", sizeof("DATETIMEUS") - 1, CDB2_DATETIMEUS},
4423+
{"INTERVALDS", sizeof("INTERVALDS") - 1, CDB2_INTERVALDS},
4424+
{"INTERVALDSUS", sizeof("INTERVALDSUS") - 1, CDB2_INTERVALDSUS},
4425+
{"INTERVALYM", sizeof("INTERVALYM") - 1, CDB2_INTERVALYM}};
4426+
4427+
static const int total_types = sizeof(all_types) / sizeof(all_types[0]);
4428+
4429+
#define get_toklen(tok) \
4430+
({ \
4431+
cdb2_skipws(tok); \
4432+
int len = 0; \
4433+
while (tok[len] && !isspace(tok[len])) \
4434+
++len; \
4435+
len; \
4436+
})
4437+
4438+
static int process_set_stmt_return_types(cdb2_hndl_tp *hndl, const char *sql)
4439+
{
4440+
int toklen;
4441+
const char *tok = sql + 3; /* if we're here, first token is "set" */
4442+
4443+
toklen = get_toklen(tok);
4444+
if (toklen != 9 || strncasecmp(tok, "statement", 9) != 0)
4445+
return -1;
4446+
tok += toklen;
4447+
4448+
toklen = get_toklen(tok);
4449+
if (toklen != 6 || strncasecmp(tok, "return", 6) != 0)
4450+
return -1;
4451+
tok += toklen;
4452+
4453+
toklen = get_toklen(tok);
4454+
if (toklen != 5 || strncasecmp(tok, "types", 5) != 0)
4455+
return -1;
4456+
tok += toklen;
4457+
4458+
if (hndl->stmt_types) {
4459+
sprintf(hndl->errstr, "%s: already have %d parameter(s)", __func__, hndl->stmt_types->n);
4460+
return 1;
4461+
}
4462+
4463+
const int max_args = 1024;
4464+
uint8_t types[max_args];
4465+
int count = 0;
4466+
4467+
while (1) {
4468+
toklen = get_toklen(tok);
4469+
if (toklen == 0)
4470+
break;
4471+
if (count == max_args) {
4472+
sprintf(hndl->errstr, "%s: max number of columns:%d", __func__, max_args);
4473+
return 1;
4474+
}
4475+
int i;
4476+
for (i = 0; i < total_types; ++i) {
4477+
if (toklen == all_types[i].name_sz && strncasecmp(tok, all_types[i].name, toklen) == 0) {
4478+
tok += toklen;
4479+
types[count++] = all_types[i].type;
4480+
break;
4481+
}
4482+
}
4483+
if (i >= total_types) {
4484+
snprintf(hndl->errstr, sizeof(hndl->errstr), "%s: column:%d has bad type:'%.*s'", __func__, count, toklen,
4485+
tok);
4486+
return 1;
4487+
}
4488+
}
4489+
if (count == 0) {
4490+
sprintf(hndl->errstr, "%s: bad number of columns:%d", __func__, count);
4491+
return 1;
4492+
}
4493+
hndl->stmt_types = malloc(sizeof(struct cdb2_stmt_types) + sizeof(int) * count);
4494+
hndl->stmt_types->n = count;
4495+
for (int i = 0; i < count; ++i) {
4496+
hndl->stmt_types->types[i] = types[i];
4497+
}
4498+
return 0;
4499+
}
4500+
44024501
static int process_set_command(cdb2_hndl_tp *hndl, const char *sql)
44034502
{
44044503
int i, j, k;
@@ -4411,8 +4510,10 @@ static int process_set_command(cdb2_hndl_tp *hndl, const char *sql)
44114510
return CDB2ERR_BADREQ;
44124511
}
44134512

4414-
int rc = process_ssl_set_command(hndl, sql);
4415-
if (rc >= 0)
4513+
int rc;
4514+
if ((rc = process_ssl_set_command(hndl, sql)) >= 0)
4515+
return rc;
4516+
if ((rc = process_set_stmt_return_types(hndl, sql)) >= 0)
44164517
return rc;
44174518

44184519
i = hndl->num_set_commands;
@@ -4573,8 +4674,8 @@ static void attach_to_handle(cdb2_hndl_tp *child, cdb2_hndl_tp *parent)
45734674
child->context_msgs.has_changed = child->context_msgs.count > 0;
45744675
}
45754676

4576-
static int cdb2_run_statement_typed_int(cdb2_hndl_tp *hndl, const char *sql,
4577-
int ntypes, int *types, int line)
4677+
static int cdb2_run_statement_typed_int(cdb2_hndl_tp *hndl, const char *sql, int ntypes, int *types, int line,
4678+
int *set_stmt)
45784679
{
45794680
int return_value;
45804681
int using_hint = 0;
@@ -4597,9 +4698,20 @@ static int cdb2_run_statement_typed_int(cdb2_hndl_tp *hndl, const char *sql,
45974698

45984699
/* sniff out 'set hasql on' here */
45994700
if (strncasecmp(sql, "set", 3) == 0) {
4701+
*set_stmt = 1;
46004702
return process_set_command(hndl, sql);
46014703
}
46024704

4705+
if (hndl->stmt_types) {
4706+
if (ntypes || types) {
4707+
sprintf(hndl->errstr, "%s: provided %d type(s), but already have %d", __func__, ntypes,
4708+
hndl->stmt_types->n);
4709+
return -1;
4710+
}
4711+
ntypes = hndl->stmt_types->n;
4712+
types = hndl->stmt_types->types;
4713+
}
4714+
46034715
if (strncasecmp(sql, "begin", 5) == 0) {
46044716
debugprint("setting is_begin flag\n");
46054717
is_begin = 1;
@@ -5262,7 +5374,7 @@ int cdb2_run_statement_typed(cdb2_hndl_tp *hndl, const char *sql, int ntypes,
52625374
{
52635375
int rc = 0;
52645376

5265-
void *callbackrc;
5377+
int set_stmt = 0;
52665378
int overwrite_rc = 0;
52675379
cdb2_event *e = NULL;
52685380

@@ -5280,15 +5392,21 @@ int cdb2_run_statement_typed(cdb2_hndl_tp *hndl, const char *sql, int ntypes,
52805392

52815393
while ((e = cdb2_next_callback(hndl, CDB2_AT_ENTER_RUN_STATEMENT, e)) !=
52825394
NULL) {
5283-
callbackrc = cdb2_invoke_callback(hndl, e, 1, CDB2_SQL, sql);
5395+
void *callbackrc = cdb2_invoke_callback(hndl, e, 1, CDB2_SQL, sql);
52845396
PROCESS_EVENT_CTRL_BEFORE(hndl, e, rc, callbackrc, overwrite_rc);
52855397
}
52865398

5287-
if (overwrite_rc)
5399+
if (overwrite_rc) {
5400+
const char *first = sql;
5401+
int len = get_toklen(first);
5402+
if (len == 3 && strncasecmp(first, "set", 3) == 0) {
5403+
set_stmt = 1;
5404+
}
52885405
goto after_callback;
5406+
}
52895407

52905408
if (hndl->temp_trans && hndl->in_trans) {
5291-
cdb2_run_statement_typed_int(hndl, "rollback", 0, NULL, __LINE__);
5409+
cdb2_run_statement_typed_int(hndl, "rollback", 0, NULL, __LINE__, &set_stmt);
52925410
}
52935411

52945412
hndl->temp_trans = 0;
@@ -5297,7 +5415,7 @@ int cdb2_run_statement_typed(cdb2_hndl_tp *hndl, const char *sql, int ntypes,
52975415
(strncasecmp(sql, "set", 3) != 0 && strncasecmp(sql, "begin", 5) != 0 &&
52985416
strncasecmp(sql, "commit", 6) != 0 &&
52995417
strncasecmp(sql, "rollback", 8) != 0)) {
5300-
rc = cdb2_run_statement_typed_int(hndl, "begin", 0, NULL, __LINE__);
5418+
rc = cdb2_run_statement_typed_int(hndl, "begin", 0, NULL, __LINE__, &set_stmt);
53015419
if (rc) {
53025420
debugprint("cdb2_run_statement_typed_int rc = %d\n", rc);
53035421
goto after_callback;
@@ -5306,47 +5424,58 @@ int cdb2_run_statement_typed(cdb2_hndl_tp *hndl, const char *sql, int ntypes,
53065424
}
53075425

53085426
cdb2_skipws(sql);
5309-
rc = cdb2_run_statement_typed_int(hndl, sql, ntypes, types, __LINE__);
5427+
rc = cdb2_run_statement_typed_int(hndl, sql, ntypes, types, __LINE__, &set_stmt);
53105428
if (rc)
53115429
debugprint("rc = %d\n", rc);
53125430

53135431
// XXX This code does not work correctly for WITH statements
53145432
// (they can be either read or write)
53155433
if (hndl->temp_trans && !is_sql_read(sql)) {
53165434
if (rc == 0) {
5317-
int commit_rc =
5318-
cdb2_run_statement_typed_int(hndl, "commit", 0, NULL, __LINE__);
5435+
int commit_rc = cdb2_run_statement_typed_int(hndl, "commit", 0, NULL, __LINE__, &set_stmt);
53195436
debugprint("rc = %d\n", commit_rc);
53205437
rc = commit_rc;
53215438
} else {
5322-
cdb2_run_statement_typed_int(hndl, "rollback", 0, NULL, __LINE__);
5439+
cdb2_run_statement_typed_int(hndl, "rollback", 0, NULL, __LINE__, &set_stmt);
53235440
}
53245441
hndl->temp_trans = 0;
53255442
}
53265443

53275444
if (log_calls) {
5328-
if (ntypes == 0)
5445+
if (set_stmt || (ntypes == 0 && hndl->stmt_types == NULL))
53295446
fprintf(stderr, "%p> cdb2_run_statement(%p, \"%s\") = %d\n",
53305447
(void *)pthread_self(), hndl, sql, rc);
5331-
else {
5448+
else if (ntypes) {
53325449
fprintf(stderr, "%p> cdb2_run_statement_typed(%p, \"%s\", [",
53335450
(void *)pthread_self(), hndl, sql);
53345451
for (int i = 0; i < ntypes; i++) {
53355452
fprintf(stderr, "%s%s", cdb2_type_str(types[i]),
53365453
i == ntypes - 1 ? "" : ", ");
53375454
}
53385455
fprintf(stderr, "] = %d\n", rc);
5456+
} else {
5457+
int n = hndl->stmt_types->n;
5458+
int *t = hndl->stmt_types->types;
5459+
fprintf(stderr, "%p> cdb2_run_statement_typed(%p, \"%s\", [", (void *)pthread_self(), hndl, sql);
5460+
for (int i = 0; i < n; ++i) {
5461+
fprintf(stderr, "%s%s", cdb2_type_str(t[i]), i == n - 1 ? "" : ", ");
5462+
}
5463+
fprintf(stderr, "] = %d\n", rc);
53395464
}
53405465
}
53415466

53425467
after_callback:
53435468
while ((e = cdb2_next_callback(hndl, CDB2_AT_EXIT_RUN_STATEMENT, e)) !=
53445469
NULL) {
5345-
callbackrc = cdb2_invoke_callback(hndl, e, 2, CDB2_SQL, sql,
5346-
CDB2_RETURN_VALUE, (intptr_t)rc);
5470+
void *callbackrc = cdb2_invoke_callback(hndl, e, 2, CDB2_SQL, sql, CDB2_RETURN_VALUE, (intptr_t)rc);
53475471
PROCESS_EVENT_CTRL_AFTER(hndl, e, rc, callbackrc);
53485472
}
53495473

5474+
if (hndl->stmt_types && !set_stmt) {
5475+
free(hndl->stmt_types);
5476+
hndl->stmt_types = NULL;
5477+
}
5478+
53505479
return rc;
53515480
}
53525481

0 commit comments

Comments
 (0)