Skip to content

Commit 4060b7f

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

2 files changed

Lines changed: 148 additions & 17 deletions

File tree

cdb2api/cdb2api.c

Lines changed: 145 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -3608,6 +3608,11 @@ int cdb2_close(cdb2_hndl_tp *hndl)
36083608
if (!hndl)
36093609
return 0;
36103610

3611+
if (hndl->stmt_types) {
3612+
free(hndl->stmt_types);
3613+
hndl->stmt_types = NULL;
3614+
}
3615+
36113616
if (hndl->fdb_hndl) {
36123617
cdb2_close(hndl->fdb_hndl);
36133618
hndl->fdb_hndl = NULL;
@@ -3800,6 +3805,11 @@ static int cdb2_query_with_hint(cdb2_hndl_tp *hndl, const char *sqlquery,
38003805
return 0;
38013806
}
38023807

3808+
struct cdb2_stmt_types {
3809+
int n;
3810+
int types[0];
3811+
};
3812+
38033813
int cdb2_run_statement(cdb2_hndl_tp *hndl, const char *sql)
38043814
{
38053815
return cdb2_run_statement_typed(hndl, sql, 0, NULL);
@@ -4241,6 +4251,94 @@ static inline void clear_snapshot_info(cdb2_hndl_tp *hndl, int line)
42414251
hndl->is_retry = 0;
42424252
}
42434253

4254+
static const struct {
4255+
const char *name;
4256+
size_t name_sz;
4257+
cdb2_coltype type;
4258+
} all_types[] = {{"INTEGER", sizeof("INTEGER") - 1, CDB2_INTEGER},
4259+
{"CSTRING", sizeof("CSTRING") - 1, CDB2_CSTRING},
4260+
{"REAL", sizeof("REAL") - 1, CDB2_REAL},
4261+
{"BLOB", sizeof("BLOB") - 1, CDB2_BLOB},
4262+
{"DATETIME", sizeof("DATETIME") - 1, CDB2_DATETIME},
4263+
{"DATETIMEUS", sizeof("DATETIMEUS") - 1, CDB2_DATETIMEUS},
4264+
{"INTERVALDS", sizeof("INTERVALDS") - 1, CDB2_INTERVALDS},
4265+
{"INTERVALDSUS", sizeof("INTERVALDSUS") - 1, CDB2_INTERVALDSUS},
4266+
{"INTERVALYM", sizeof("INTERVALYM") - 1, CDB2_INTERVALYM}};
4267+
4268+
static const int total_types = sizeof(all_types) / sizeof(all_types[0]);
4269+
4270+
#define get_toklen(tok) \
4271+
({ \
4272+
cdb2_skipws(tok); \
4273+
int len = 0; \
4274+
while (tok[len] && !isspace(tok[len])) \
4275+
++len; \
4276+
len; \
4277+
})
4278+
4279+
static int process_set_stmt_return_types(cdb2_hndl_tp *hndl, const char *sql)
4280+
{
4281+
int toklen;
4282+
const char *tok = sql + 3; /* if we're here, first token is "set" */
4283+
4284+
toklen = get_toklen(tok);
4285+
if (toklen != 9 || strncasecmp(tok, "statement", 9) != 0)
4286+
return -1;
4287+
tok += toklen;
4288+
4289+
toklen = get_toklen(tok);
4290+
if (toklen != 6 || strncasecmp(tok, "return", 6) != 0)
4291+
return -1;
4292+
tok += toklen;
4293+
4294+
toklen = get_toklen(tok);
4295+
if (toklen != 5 || strncasecmp(tok, "types", 5) != 0)
4296+
return -1;
4297+
tok += toklen;
4298+
4299+
if (hndl->stmt_types) {
4300+
sprintf(hndl->errstr, "%s: already have %d parameter(s)", __func__, hndl->stmt_types->n);
4301+
return 1;
4302+
}
4303+
4304+
const int max_args = 1024;
4305+
uint8_t types[max_args];
4306+
int count = 0;
4307+
4308+
while (1) {
4309+
toklen = get_toklen(tok);
4310+
if (toklen == 0)
4311+
break;
4312+
if (count == max_args) {
4313+
sprintf(hndl->errstr, "%s: max number of columns:%d", __func__, max_args);
4314+
return 1;
4315+
}
4316+
int i;
4317+
for (i = 0; i < total_types; ++i) {
4318+
if (toklen == all_types[i].name_sz && strncasecmp(tok, all_types[i].name, toklen) == 0) {
4319+
tok += toklen;
4320+
types[count++] = all_types[i].type;
4321+
break;
4322+
}
4323+
}
4324+
if (i >= total_types) {
4325+
snprintf(hndl->errstr, sizeof(hndl->errstr), "%s: column:%d has bad type:'%.*s'", __func__, count, toklen,
4326+
tok);
4327+
return 1;
4328+
}
4329+
}
4330+
if (count == 0) {
4331+
sprintf(hndl->errstr, "%s: bad number of columns:%d", __func__, count);
4332+
return 1;
4333+
}
4334+
hndl->stmt_types = malloc(sizeof(struct cdb2_stmt_types) + sizeof(int) * count);
4335+
hndl->stmt_types->n = count;
4336+
for (int i = 0; i < count; ++i) {
4337+
hndl->stmt_types->types[i] = types[i];
4338+
}
4339+
return 0;
4340+
}
4341+
42444342
static int process_set_command(cdb2_hndl_tp *hndl, const char *sql)
42454343
{
42464344
int i, j, k;
@@ -4253,8 +4351,10 @@ static int process_set_command(cdb2_hndl_tp *hndl, const char *sql)
42534351
return CDB2ERR_BADREQ;
42544352
}
42554353

4256-
int rc = process_ssl_set_command(hndl, sql);
4257-
if (rc >= 0)
4354+
int rc;
4355+
if ((rc = process_ssl_set_command(hndl, sql)) >= 0)
4356+
return rc;
4357+
if ((rc = process_set_stmt_return_types(hndl, sql)) >= 0)
42584358
return rc;
42594359

42604360
i = hndl->num_set_commands;
@@ -4415,8 +4515,8 @@ static void attach_to_handle(cdb2_hndl_tp *child, cdb2_hndl_tp *parent)
44154515
child->context_msgs.has_changed = child->context_msgs.count > 0;
44164516
}
44174517

4418-
static int cdb2_run_statement_typed_int(cdb2_hndl_tp *hndl, const char *sql,
4419-
int ntypes, int *types, int line)
4518+
static int cdb2_run_statement_typed_int(cdb2_hndl_tp *hndl, const char *sql, int ntypes, int *types, int line,
4519+
int *set_stmt)
44204520
{
44214521
int return_value;
44224522
int using_hint = 0;
@@ -4439,9 +4539,20 @@ static int cdb2_run_statement_typed_int(cdb2_hndl_tp *hndl, const char *sql,
44394539

44404540
/* sniff out 'set hasql on' here */
44414541
if (strncasecmp(sql, "set", 3) == 0) {
4542+
*set_stmt = 1;
44424543
return process_set_command(hndl, sql);
44434544
}
44444545

4546+
if (hndl->stmt_types) {
4547+
if (ntypes || types) {
4548+
sprintf(hndl->errstr, "%s: provided %d type(s), but already have %d", __func__, ntypes,
4549+
hndl->stmt_types->n);
4550+
return -1;
4551+
}
4552+
ntypes = hndl->stmt_types->n;
4553+
types = hndl->stmt_types->types;
4554+
}
4555+
44454556
if (strncasecmp(sql, "begin", 5) == 0) {
44464557
debugprint("setting is_begin flag\n");
44474558
is_begin = 1;
@@ -5103,7 +5214,7 @@ int cdb2_run_statement_typed(cdb2_hndl_tp *hndl, const char *sql, int ntypes,
51035214
{
51045215
int rc = 0;
51055216

5106-
void *callbackrc;
5217+
int set_stmt = 0;
51075218
int overwrite_rc = 0;
51085219
cdb2_event *e = NULL;
51095220

@@ -5121,15 +5232,21 @@ int cdb2_run_statement_typed(cdb2_hndl_tp *hndl, const char *sql, int ntypes,
51215232

51225233
while ((e = cdb2_next_callback(hndl, CDB2_AT_ENTER_RUN_STATEMENT, e)) !=
51235234
NULL) {
5124-
callbackrc = cdb2_invoke_callback(hndl, e, 1, CDB2_SQL, sql);
5235+
void *callbackrc = cdb2_invoke_callback(hndl, e, 1, CDB2_SQL, sql);
51255236
PROCESS_EVENT_CTRL_BEFORE(hndl, e, rc, callbackrc, overwrite_rc);
51265237
}
51275238

5128-
if (overwrite_rc)
5239+
if (overwrite_rc) {
5240+
const char *first = sql;
5241+
int len = get_toklen(first);
5242+
if (len == 3 && strncasecmp(first, "set", 3) == 0) {
5243+
set_stmt = 1;
5244+
}
51295245
goto after_callback;
5246+
}
51305247

51315248
if (hndl->temp_trans && hndl->in_trans) {
5132-
cdb2_run_statement_typed_int(hndl, "rollback", 0, NULL, __LINE__);
5249+
cdb2_run_statement_typed_int(hndl, "rollback", 0, NULL, __LINE__, &set_stmt);
51335250
}
51345251

51355252
hndl->temp_trans = 0;
@@ -5138,7 +5255,7 @@ int cdb2_run_statement_typed(cdb2_hndl_tp *hndl, const char *sql, int ntypes,
51385255
(strncasecmp(sql, "set", 3) != 0 && strncasecmp(sql, "begin", 5) != 0 &&
51395256
strncasecmp(sql, "commit", 6) != 0 &&
51405257
strncasecmp(sql, "rollback", 8) != 0)) {
5141-
rc = cdb2_run_statement_typed_int(hndl, "begin", 0, NULL, __LINE__);
5258+
rc = cdb2_run_statement_typed_int(hndl, "begin", 0, NULL, __LINE__, &set_stmt);
51425259
if (rc) {
51435260
debugprint("cdb2_run_statement_typed_int rc = %d\n", rc);
51445261
goto after_callback;
@@ -5147,47 +5264,58 @@ int cdb2_run_statement_typed(cdb2_hndl_tp *hndl, const char *sql, int ntypes,
51475264
}
51485265

51495266
cdb2_skipws(sql);
5150-
rc = cdb2_run_statement_typed_int(hndl, sql, ntypes, types, __LINE__);
5267+
rc = cdb2_run_statement_typed_int(hndl, sql, ntypes, types, __LINE__, &set_stmt);
51515268
if (rc)
51525269
debugprint("rc = %d\n", rc);
51535270

51545271
// XXX This code does not work correctly for WITH statements
51555272
// (they can be either read or write)
51565273
if (hndl->temp_trans && !is_sql_read(sql)) {
51575274
if (rc == 0) {
5158-
int commit_rc =
5159-
cdb2_run_statement_typed_int(hndl, "commit", 0, NULL, __LINE__);
5275+
int commit_rc = cdb2_run_statement_typed_int(hndl, "commit", 0, NULL, __LINE__, &set_stmt);
51605276
debugprint("rc = %d\n", commit_rc);
51615277
rc = commit_rc;
51625278
} else {
5163-
cdb2_run_statement_typed_int(hndl, "rollback", 0, NULL, __LINE__);
5279+
cdb2_run_statement_typed_int(hndl, "rollback", 0, NULL, __LINE__, &set_stmt);
51645280
}
51655281
hndl->temp_trans = 0;
51665282
}
51675283

51685284
if (log_calls) {
5169-
if (ntypes == 0)
5285+
if (set_stmt || (ntypes == 0 && hndl->stmt_types == NULL))
51705286
fprintf(stderr, "%p> cdb2_run_statement(%p, \"%s\") = %d\n",
51715287
(void *)pthread_self(), hndl, sql, rc);
5172-
else {
5288+
else if (ntypes) {
51735289
fprintf(stderr, "%p> cdb2_run_statement_typed(%p, \"%s\", [",
51745290
(void *)pthread_self(), hndl, sql);
51755291
for (int i = 0; i < ntypes; i++) {
51765292
fprintf(stderr, "%s%s", cdb2_type_str(types[i]),
51775293
i == ntypes - 1 ? "" : ", ");
51785294
}
51795295
fprintf(stderr, "] = %d\n", rc);
5296+
} else {
5297+
int n = hndl->stmt_types->n;
5298+
int *t = hndl->stmt_types->types;
5299+
fprintf(stderr, "%p> cdb2_run_statement_typed(%p, \"%s\", [", (void *)pthread_self(), hndl, sql);
5300+
for (int i = 0; i < n; ++i) {
5301+
fprintf(stderr, "%s%s", cdb2_type_str(t[i]), i == n - 1 ? "" : ", ");
5302+
}
5303+
fprintf(stderr, "] = %d\n", rc);
51805304
}
51815305
}
51825306

51835307
after_callback:
51845308
while ((e = cdb2_next_callback(hndl, CDB2_AT_EXIT_RUN_STATEMENT, e)) !=
51855309
NULL) {
5186-
callbackrc = cdb2_invoke_callback(hndl, e, 2, CDB2_SQL, sql,
5187-
CDB2_RETURN_VALUE, (intptr_t)rc);
5310+
void *callbackrc = cdb2_invoke_callback(hndl, e, 2, CDB2_SQL, sql, CDB2_RETURN_VALUE, (intptr_t)rc);
51885311
PROCESS_EVENT_CTRL_AFTER(hndl, e, rc, callbackrc);
51895312
}
51905313

5314+
if (hndl->stmt_types && !set_stmt) {
5315+
free(hndl->stmt_types);
5316+
hndl->stmt_types = NULL;
5317+
}
5318+
51915319
return rc;
51925320
}
51935321

cdb2api/cdb2api_hndl.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,8 @@ struct context_messages {
8484
int has_changed;
8585
};
8686

87+
struct cdb2_stmt_types;
88+
8789
typedef struct cdb2_query_list_item {
8890
void *buf;
8991
int len;
@@ -202,6 +204,7 @@ struct cdb2_hndl {
202204
struct cdb2_hndl *fdb_hndl;
203205
int is_child_hndl;
204206
CDB2SQLQUERY__IdentityBlob *id_blob;
207+
struct cdb2_stmt_types *stmt_types;
205208
};
206209

207210
#endif

0 commit comments

Comments
 (0)