📄 cli.cpp
字号:
*p++ = cb->var_type;
s = cb->name;
while ((*p++ = *s++) != '\0');
}
}
*p++ = for_update;
for (pb = stmt->params; pb != NULL; pb = pb->next) {
switch (pb->var_type) {
case cli_asciiz:
s = (char*)pb->var_ptr;
while ((*p++ = *s++) != '\0');
continue;
case cli_rectangle:
p = pack_rectangle(p, (cli_rectangle_t*)pb->var_ptr);
continue;
case cli_pasciiz:
s = *(char**)pb->var_ptr;
while ((*p++ = *s++) != '\0');
continue;
default:
switch (sizeof_type[pb->var_type]) {
case 1:
*p++ = *(char*)pb->var_ptr;
continue;
case 2:
p = pack2(p, *(int2*)pb->var_ptr);
continue;
case 4:
p = pack4(p, *(int4*)pb->var_ptr);
continue;
case 8:
p = pack8(p, *(db_int8*)pb->var_ptr);
continue;
}
}
}
assert(msg_size == p - buf.base());
if (!stmt->session->sock->write(buf, msg_size)) {
return cli_network_error;
}
int4 response;
if (!stmt->session->sock->read(&response, sizeof response)) {
return cli_network_error;
}
unpack4(response);
if (response >= 0) {
stmt->prepared = true;
}
return response;
}
static int cli_send_columns(int statement, int cmd)
{
statement_desc* s = statements.get(statement);
column_binding* cb;
if (s == NULL) {
return cli_bad_descriptor;
}
long msg_size = sizeof(cli_request);
if (cmd == cli_cmd_update) {
if (!s->prepared) {
return cli_not_fetched;
}
if (s->oid == 0) {
return cli_not_found;
}
if (s->updated) {
return cli_already_updated;
}
if (!s->for_update) {
return cli_not_update_mode;
}
} else {
if (!s->prepared) {
cmd = cli_cmd_prepare_and_insert;
msg_size += 1 + s->stmt_len + s->n_columns + s->columns_len;
}
}
s->autoincrement = false;
for (cb = s->columns; cb != NULL; cb = cb->next) {
if (cb->get_fnc != NULL) {
cb->arr_ptr = cb->get_fnc(cb->var_type, cb->var_ptr, &cb->arr_len,
cb->name, statement, cb->user_data);
int len = cb->arr_len;
msg_size += 4;
if (cb->var_type == cli_array_of_string) {
char** p = (char**)cb->arr_ptr;
while (--len >= 0) {
msg_size += strlen(*p++) + 1;
}
} else if (cb->var_type >= cli_array_of_oid) {
msg_size += len * sizeof_type[cb->var_type - cli_array_of_oid];
} else {
msg_size += len;
}
} else {
if (cb->var_type == cli_asciiz) {
msg_size += 4 + strlen((char*)cb->var_ptr) + 1;
} else if (cb->var_type == cli_pasciiz) {
msg_size += 4 + strlen(*(char**)cb->var_ptr) + 1;
} else if (cb->var_type == cli_autoincrement) {
s->autoincrement = true;
} else if (cb->var_type == cli_array_of_string) {
char** p = (char**)cb->var_ptr;
msg_size += 4;
for (int len = *cb->var_len; --len >= 0;) {
msg_size += strlen(*p++) + 1;
}
} else if (cb->var_type >= cli_array_of_oid) {
msg_size += 4 +
*cb->var_len * sizeof_type[cb->var_type-cli_array_of_oid];
} else {
msg_size += sizeof_type[cb->var_type];
}
}
}
dbSmallBuffer buf(msg_size);
char* p = buf;
cli_request* req = (cli_request*)p;
req->length = msg_size;
req->cmd = cmd;
req->stmt_id = statement;
req->pack();
p += sizeof(cli_request);
if (cmd == cli_cmd_prepare_and_insert) {
char* cmd = s->stmt;
while ((*p++ = *cmd++) != '\0');
*p++ = s->n_columns;
for (cb = s->columns; cb != NULL; cb = cb->next) {
char* src = cb->name;
*p++ = cb->var_type;
while ((*p++ = *src++) != '\0');
}
}
for (cb = s->columns; cb != NULL; cb = cb->next) {
int n = 0;
char* src;
if (cb->get_fnc != NULL) {
src = (char*)cb->arr_ptr;
n = cb->arr_len;
} else {
src = (char*)cb->var_ptr;
if (cb->var_type >= cli_array_of_oid && cb->var_type <= cli_array_of_real8) {
n = *cb->var_len;
}
}
if (cb->var_type >= cli_array_of_oid && cb->var_type <= cli_array_of_real8) {
p = pack4(p, n);
if (cb->var_type == cli_array_of_string) {
while (--n >= 0) {
strcpy(p, *(char**)src);
p += strlen(p) + 1;
src += sizeof(char*);
}
} else {
switch (sizeof_type[cb->var_type-cli_array_of_oid]) {
case 2:
while (--n >= 0) {
p = pack2(p, src);
src += 2;
}
break;
case 4:
while (--n >= 0) {
p = pack4(p, src);
src += 4;
}
break;
case 8:
while (--n >= 0) {
p = pack8(p, src);
src += 8;
}
break;
default:
memcpy(p, src, n);
p += n;
}
}
} else if (cb->var_type == cli_asciiz) {
p = pack4(p, strlen(src)+1);
while ((*p++ = *src++) != 0);
} else if (cb->var_type == cli_pasciiz) {
src = *(char**)src;
p = pack4(p, strlen(src)+1);
while ((*p++ = *src++) != 0);
} else if (cb->var_type == cli_rectangle) {
p = pack_rectangle(p, (cli_rectangle_t*)src);
} else if (cb->var_type != cli_autoincrement) {
switch (sizeof_type[cb->var_type]) {
case 2:
p = pack2(p, src);
break;
case 4:
p = pack4(p, src);
break;
case 8:
p = pack8(p, src);
break;
default:
*p++ = *src;
}
}
}
assert(p - buf.base() == msg_size);
if (!s->session->sock->write(buf, msg_size)) {
return cli_network_error;
}
return cli_ok;
}
int cli_insert(int statement, cli_oid_t* oid)
{
int rc = cli_send_columns(statement, cli_cmd_insert);
if (rc == cli_ok) {
char buf[sizeof(cli_oid_t) + 8];
statement_desc* s = statements.get(statement);
if (!s->session->sock->read(buf, sizeof buf)) {
rc = cli_network_error;
} else {
rc = unpack4(buf);
s->prepared = true;
s->oid = unpack_oid(buf + 8);
if (oid != NULL) {
*oid = s->oid;
}
if (s->autoincrement) {
int4 rowid = unpack4(buf + 4);
for (column_binding* cb = s->columns; cb != NULL; cb = cb->next) {
if (cb->var_type == cli_autoincrement) {
*(int4*)cb->var_ptr = rowid;
}
}
}
}
}
return rc;
}
int cli_update(int statement)
{
int rc = cli_send_columns(statement, cli_cmd_update);
if (rc == cli_ok) {
int4 response;
statement_desc* s = statements.get(statement);
s->updated = true;
if (!s->session->sock->read(&response, sizeof response)) {
rc = cli_network_error;
} else {
unpack4(response);
rc = response;
}
}
return rc;
}
static int cli_get(int statement, int cmd, cli_oid_t value = 0)
{
statement_desc* s = statements.get(statement);
if (s == NULL) {
return cli_bad_descriptor;
}
if (!s->prepared) {
return cli_not_fetched;
}
struct get_req {
cli_request req;
cli_oid_t value;
} get;
int length = sizeof(cli_request);
if (cmd == cli_cmd_skip) {
length += 4;
pack4((char*)(&get.req+1), (int)value);
} else if (cmd == cli_cmd_seek) {
length += sizeof(cli_oid_t);
pack_oid((char*)(&get.req+1), value);
}
get.req.length = length;
get.req.cmd = cmd;
get.req.stmt_id = statement;
get.req.pack();
if (!s->session->sock->write(&get.req, length)) {
return cli_network_error;
}
int4 response;
if (!s->session->sock->read(&response, sizeof response)) {
return cli_network_error;
}
unpack4(response);
if (response <= 0) {
return response;
}
if (s->buf_size < (size_t)response-4) {
delete[] s->buf;
s->buf_size = response-4 < DEFAULT_BUF_SIZE ? DEFAULT_BUF_SIZE : response-4;
s->buf = new char[s->buf_size];
}
char* buf = s->buf;
if (!s->session->sock->read(buf, response-4)) {
return cli_network_error;
}
char* p = buf;
int result = cli_ok;
if (cmd == cli_cmd_seek) {
s->oid = value;
result = unpack_oid(p);
} else {
s->oid = unpack_oid(p);
if (s->oid == 0) {
return cli_not_found;
}
}
p += sizeof(cli_oid_t);
for (column_binding* cb = s->columns; cb != NULL; cb = cb->next) {
if (cb->set_fnc != NULL) {
int len = unpack4(p);
p += 4;
char* dst = (char*)cb->set_fnc(cb->var_type, cb->var_ptr, len,
cb->name, statement, p, cb->user_data);
if (dst == NULL) {
continue;
}
if (cb->var_type == cli_array_of_string) {
char** s = (char**)dst;
while (--len >= 0) {
*s++ = p;
p += strlen(p) + 1;
}
} else if (cb->var_type >= cli_array_of_oid && cb->var_type <= cli_array_of_real8) {
switch (sizeof_type[cb->var_type-cli_array_of_oid]) {
case 2:
while (--len >= 0) {
p = unpack2(dst, p);
dst += 2;
}
break;
case 4:
while (--len >= 0) {
p = unpack4(dst, p);
dst += 4;
}
break;
case 8:
while (--len >= 0) {
p = unpack8(dst, p);
dst += 8;
}
break;
default:
memcpy(dst, p, len);
p += len;
}
} else {
memcpy(dst, p, len);
p += len;
}
} else {
if (cb->var_type >= cli_asciiz && cb->var_type <= cli_array_of_string) {
int len = unpack4(p);
p += 4;
char* dst = (char*)cb->var_ptr;
char* src = p;
int n = len;
if (cb->var_len != NULL) {
if (n > *cb->var_len) {
n = *cb->var_len;
}
*cb->var_len = n;
}
if (cb->var_type >= cli_array_of_oid) {
if (cb->var_type == cli_array_of_string) {
char** s = (char**)dst;
len -= n;
while (--n >= 0) {
*s++ = p;
p += strlen(p) + 1;
}
while (--len >= 0) {
p += strlen(p) + 1;
}
} else {
switch (sizeof_type[cb->var_type-cli_array_of_oid]) {
case 2:
while (--n >= 0) {
src = unpack2(dst, src);
dst += 2;
}
p += len*2;
break;
case 4:
while (--n >= 0) {
src = unpack4(dst, src);
dst += 4;
}
p += len*4;
break;
case 8:
while (--n >= 0) {
src = unpack8(dst, src);
dst += 8;
}
p += len*8;
break;
default:
memcpy(dst, p, n);
p += len;
}
}
} else {
if (cb->var_type == cli_pasciiz) {
dst = *(char**)dst;
}
memcpy(dst, p, n);
p += len;
}
} else if (cb->var_type == cli_rectangle) {
p = unpack_rectangle((cli_rectangle_t*)cb->var_ptr, p);
} else {
switch (sizeof_type[cb->var_type]) {
case 2:
p = unpack2((char*)cb->var_ptr, p);
break;
case 4:
p = unpack4((char*)cb->var_ptr, p);
break;
case 8:
p = unpack8((char*)cb->var_ptr, p);
break;
default:
*(char*)cb->var_ptr = *p++;
}
}
}
}
s->updated = false;
return result;
}
int cli_get_first(int statement)
{
return cli_get(statement, cli_cmd_get_first);
}
int cli_get_last(int statement)
{
return cli_get(statement, cli_cmd_get_last);
}
int cli_get_next(int statement)
{
return cli_get(statement, cli_cmd_get_next);
}
int cli_get_prev(int statement)
{
return cli_get(statement, cli_cmd_get_prev);
}
int cli_skip(int statement, int n)
{
return cli_get(statement, cli_cmd_skip, n);
}
int cli_seek(int statement, cli_oid_t oid)
{
return cli_get(statement, cli_cmd_seek, oid);
}
static int send_receive(int statement, int cmd)
{
statement_desc* s = statements.get(statement);
if (s == NULL) {
return cli_bad_descriptor;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -