1 //-< CLI.CPP >-------------------------------------------------------*--------*
2 // FastDB Version 1.0 (c) 1999 GARRET * ? *
3 // (Main Memory Database Management System) * /\| *
4 // * / \ *
5 // Created: 13-Jan-2000 K.A. Knizhnik * / [] \ *
6 // Last update: 13-Jan-2000 K.A. Knizhnik * GARRET *
7 //-------------------------------------------------------------------*--------*
8 // Call level interface client part implementation
9 //-------------------------------------------------------------------*--------*
10
11 #define INSIDE_FASTDB
12
13 #include "stdtp.h"
14 #include "sockio.h"
15 #include "repsock.h"
16 #include "sync.h"
17 #include "cli.h"
18 #include "cliproto.h"
19
20 #include <wchar.h>
21 #include <ctype.h>
22
23 BEGIN_FASTDB_NAMESPACE
24
25 struct parameter_binding {
26 parameter_binding* next;
27 char* name;
28 int var_type;
29 int var_len;
30 void* var_ptr;
31
~parameter_bindingparameter_binding32 ~parameter_binding() {
33 delete[] name;
34 }
35 };
36
37 struct column_binding {
38 column_binding* next;
39 char* name;
40 int var_type;
41 int* var_len;
42 void* var_ptr;
43 void* arr_ptr;
44 int arr_len;
45 cli_column_get_ex get_fnc;
46 cli_column_set_ex set_fnc;
47 void* user_data;
48
~column_bindingcolumn_binding49 ~column_binding() {
50 delete[] name;
51 }
52 };
53
54 struct session_desc;
55
56 #define DEFAULT_BUF_SIZE 256
57
58 struct statement_desc {
59 int id;
60 statement_desc* next;
61 char* stmt;
62 column_binding* columns;
63 parameter_binding* params;
64 session_desc* session;
65 bool for_update;
66 bool updated;
67 bool prepared;
68 bool autoincrement;
69 cli_oid_t oid;
70 int stmt_len;
71 int n_params;
72 int n_columns;
73 int columns_len;
74 char* buf;
75 size_t buf_size;
76
deallocatestatement_desc77 void deallocate() {
78 delete[] stmt;
79 column_binding *cb, *next_cb;
80 for (cb = columns; cb != NULL; cb = next_cb) {
81 next_cb = cb->next;
82 delete cb;
83 }
84 if (buf != NULL) {
85 delete[] buf;
86 buf_size = 0;
87 buf = NULL;
88 }
89 parameter_binding *pb, *next_pb;
90 for (pb = params; pb != NULL; pb = next_pb) {
91 next_pb = pb->next;
92 delete pb;
93 }
94 }
statement_descstatement_desc95 statement_desc(int id, statement_desc* next) {
96 this->id = id;
97 this->next = next;
98 buf = NULL;
99 buf_size = 0;
100 }
statement_descstatement_desc101 statement_desc() {}
102 };
103
104 struct session_desc {
105 int id;
106 session_desc* next;
107 socket_t* sock;
108 statement_desc* stmts;
109
session_descsession_desc110 session_desc(int id, session_desc* next) {
111 this->id = id;
112 this->next = next;
113 }
session_descsession_desc114 session_desc() {}
115 };
116
117 template<class T>
118 class descriptor_table {
119 protected:
120 T** table;
121 T* free_desc;
122 int descriptor_table_size;
123 dbMutex mutex;
124
125 public:
descriptor_table()126 descriptor_table() {
127 int i;
128 descriptor_table_size = 16;
129 table = new T*[descriptor_table_size];
130 T* next = NULL;
131 for (i = 0; i < descriptor_table_size; i++) {
132 table[i] = next = new T(i, next);
133 }
134 free_desc = next;
135 }
136
~descriptor_table()137 ~descriptor_table() {
138 for (int i = 0; i < descriptor_table_size; i++) {
139 delete table[i];
140 }
141 delete[] table;
142 }
143
get(int desc)144 T* get(int desc) {
145 dbCriticalSection cs(mutex);
146 return (desc >= descriptor_table_size) ? (T*)0 : table[desc];
147 }
148
allocate()149 T* allocate() {
150 dbCriticalSection cs(mutex);
151 if (free_desc == NULL) {
152 int i, n;
153 T** desc = new T*[descriptor_table_size * 2];
154 memcpy(desc, table, descriptor_table_size*sizeof(T*));
155 delete[] table;
156 table = desc;
157 T* next = NULL;
158 for (i = descriptor_table_size, n = i*2; i < n; i++) {
159 table[i] = next = new T(i, next);
160 }
161 free_desc = next;
162 descriptor_table_size = n;
163 }
164 T* desc = free_desc;
165 free_desc = desc->next;
166 return desc;
167 }
168
deallocate(T * desc)169 void deallocate(T* desc) {
170 dbCriticalSection cs(mutex);
171 desc->next = free_desc;
172 free_desc = desc;
173 }
174 };
175
176 static descriptor_table<session_desc> sessions;
177 static descriptor_table<statement_desc> statements;
178
179 END_FASTDB_NAMESPACE
180 USE_FASTDB_NAMESPACE
181
cli_open(char const * server_url,int max_connect_attempts,int reconnect_timeout_sec)182 int cli_open(char const* server_url,
183 int max_connect_attempts,
184 int reconnect_timeout_sec)
185 {
186 socket_t* sock;
187 int n_addresses = 1;
188 char const* start = server_url;
189 char const* end;
190 while ((end = strchr(start, ',')) != NULL) {
191 start = end + 1;
192 n_addresses += 1;
193 }
194 if (n_addresses == 1) {
195 sock = socket_t::connect(server_url,
196 socket_t::sock_any_domain,
197 max_connect_attempts,
198 reconnect_timeout_sec);
199 } else {
200 char** addresses = new char*[n_addresses];
201 start = server_url;
202 for (int i = 0; i < n_addresses; i++) {
203 end = strchr(start, ',');
204 if (end == NULL) {
205 end = start + strlen(start);
206 }
207 int len = (int)(end - start);
208 char* addr = new char[len+1];
209 memcpy(addr, start, len);
210 addr[len] = '\0';
211 start = end + 1;
212 addresses[i] = addr;
213 }
214 sock = replication_socket_t::connect((char const**)addresses,
215 n_addresses,
216 max_connect_attempts,
217 reconnect_timeout_sec);
218 while (--n_addresses >= 0) {
219 delete[] addresses[n_addresses];
220 }
221 delete[] addresses;
222 }
223 if (!sock->is_ok()) {
224 delete sock;
225 return cli_connection_refused;
226 }
227 session_desc* session = sessions.allocate();
228 session->sock = sock;
229 session->stmts = NULL;
230 return session->id;
231 }
232
233
cli_close(int session)234 int cli_close(int session)
235 {
236 statement_desc *stmt, *next;
237 session_desc* s = sessions.get(session);
238 if (s == NULL) {
239 return cli_bad_descriptor;
240 }
241 cli_request req;
242 req.length = sizeof(req);
243 req.cmd = cli_cmd_close_session;
244 req.pack();
245 int result = cli_ok;
246 if (!s->sock->write(&req, sizeof req)) {
247 result = cli_network_error;
248 }
249 delete s->sock;
250 s->sock = NULL;
251 for (stmt = s->stmts; stmt != NULL; stmt = next) {
252 next = stmt->next;
253 stmt->deallocate();
254 statements.deallocate(stmt);
255 }
256 sessions.deallocate(s);
257 return result;
258 }
259
cli_statement(int session,char const * stmt_str)260 int cli_statement(int session, char const* stmt_str)
261 {
262 session_desc* s = sessions.get(session);
263 if (s == NULL) {
264 return cli_bad_descriptor;
265 }
266 statement_desc* stmt = statements.allocate();
267 stmt->stmt = new char[strlen(stmt_str)+1];
268 stmt->columns = NULL;
269 stmt->params = NULL;
270 stmt->session = s;
271 stmt->for_update = 0;
272 stmt->prepared = false;
273 stmt->n_params = 0;
274 stmt->n_columns = 0;
275 stmt->columns_len = 0;
276 stmt->oid = 0;
277 stmt->next = s->stmts;
278 stmt->updated = false;
279 s->stmts = stmt;
280 char const* p = stmt_str;
281 char* dst = stmt->stmt;
282 parameter_binding** last = &stmt->params;
283 while (*p != '\0') {
284 if (*p == '\'') {
285 do {
286 do {
287 *dst++ = *p++;
288 } while (*p != '\0' && *p != '\'');
289 *dst++ = *p;
290 if (*p == '\0') {
291 *last = NULL;
292 stmt->deallocate();
293 statements.deallocate(stmt);
294 return cli_bad_statement;
295 }
296 } while (*++p == '\'');
297 } else if (*p == '%') {
298 stmt->n_params += 1;
299 char const* q = p++;
300 while (isalnum((unsigned char)*p) || *p == '_') p += 1;
301 if (*p == '%') {
302 *last = NULL;
303 stmt->deallocate();
304 statements.deallocate(stmt);
305 return cli_bad_statement;
306 }
307 parameter_binding* pb = new parameter_binding;
308 int len = (int)(p - q);
309 pb->name = new char[len+1];
310 memcpy(pb->name, q, len);
311 pb->name[len] = '\0';
312 *last = pb;
313 last = &pb->next;
314 pb->var_ptr = NULL;
315 *dst++ = '\0';
316 } else {
317 *dst++ = *p++;
318 }
319 }
320 if (dst == stmt->stmt || *(dst-1) != '\0') {
321 *dst++ = '\0';
322 }
323 stmt->stmt_len = (int)(dst - stmt->stmt);
324 *last = NULL;
325 return stmt->id;
326 }
327
cli_parameter(int statement,char const * param_name,int var_type,void * var_ptr)328 int cli_parameter(int statement,
329 char const* param_name,
330 int var_type,
331 void* var_ptr)
332 {
333 if (var_type != cli_rectangle
334 && var_type != cli_wstring
335 && var_type != cli_pwstring
336 && ((unsigned)var_type >= cli_array_of_oid || var_type == cli_decimal))
337 {
338 return cli_unsupported_type;
339 }
340 statement_desc* s = statements.get(statement);
341 if (s == NULL) {
342 return cli_bad_descriptor;
343 }
344 s->prepared = false;
345 for (parameter_binding* pb = s->params; pb != NULL; pb = pb->next) {
346 if (strcmp(pb->name, param_name) == 0) {
347 pb->var_ptr = var_ptr;
348 pb->var_type = var_type;
349 return cli_ok;
350 }
351 }
352 return cli_parameter_not_found;
353 }
354
cli_column(int statement,char const * column_name,int var_type,int * var_len,void * var_ptr)355 int cli_column(int statement,
356 char const* column_name,
357 int var_type,
358 int* var_len,
359 void* var_ptr)
360 {
361 statement_desc* s = statements.get(statement);
362 if (s == NULL) {
363 return cli_bad_descriptor;
364 }
365 s->prepared = false;
366 column_binding* cb = new column_binding;
367 int len = (int)strlen(column_name) + 1;
368 cb->name = new char[len];
369 s->columns_len += len;
370 cb->next = s->columns;
371 s->columns = cb;
372 s->n_columns += 1;
373 strcpy(cb->name, column_name);
374 cb->var_type = var_type;
375 cb->var_len = var_len;
376 cb->var_ptr = var_ptr;
377 cb->set_fnc = NULL;
378 cb->get_fnc = NULL;
379 return cli_ok;
380 }
381
cli_array_column(int statement,char const * column_name,int var_type,void * var_ptr,cli_column_set set,cli_column_get get)382 int cli_array_column(int statement,
383 char const* column_name,
384 int var_type,
385 void* var_ptr,
386 cli_column_set set,
387 cli_column_get get)
388 {
389 return cli_array_column_ex(statement, column_name, var_type, var_ptr,
390 (cli_column_set_ex)set, (cli_column_get_ex)get, NULL);
391 }
392
cli_array_column_ex(int statement,char const * column_name,int var_type,void * var_ptr,cli_column_set_ex set,cli_column_get_ex get,void * user_data)393 int cli_array_column_ex(int statement,
394 char const* column_name,
395 int var_type,
396 void* var_ptr,
397 cli_column_set_ex set,
398 cli_column_get_ex get,
399 void* user_data)
400 {
401 statement_desc* s = statements.get(statement);
402 if (s == NULL) {
403 return cli_bad_descriptor;
404 }
405 if (!((var_type >= cli_asciiz && var_type <= cli_array_of_string)
406 || (var_type >= cli_wstring && var_type <= cli_array_of_wstring)))
407 {
408 return cli_unsupported_type;
409 }
410 s->prepared = false;
411 column_binding* cb = new column_binding;
412 int len = (int)strlen(column_name) + 1;
413 cb->name = new char[len];
414 s->columns_len += len;
415 cb->next = s->columns;
416 s->columns = cb;
417 s->n_columns += 1;
418 strcpy(cb->name, column_name);
419 cb->var_type = var_type;
420 cb->var_len = NULL;
421 cb->var_ptr = var_ptr;
422 cb->set_fnc = set;
423 cb->get_fnc = get;
424 cb->user_data = user_data;
425 return cli_ok;
426 }
427
cli_fetch_ex(int statement,int cursor_type,cli_cardinality_t * n_fetched_records)428 int cli_fetch_ex(int statement, int cursor_type, cli_cardinality_t* n_fetched_records)
429 {
430 int rc = cli_fetch(statement, cursor_type);
431 if (rc >= 0) {
432 *n_fetched_records = rc;
433 return cli_ok;
434 }
435 return rc;
436 }
437
cli_fetch(int statement,int for_update)438 int cli_fetch(int statement, int for_update)
439 {
440 parameter_binding* pb;
441 column_binding* cb;
442 statement_desc* stmt = statements.get(statement);
443 char *p, *s;
444
445 if (stmt == NULL) {
446 return cli_bad_descriptor;
447 }
448 stmt->for_update = for_update;
449 size_t msg_size = sizeof(cli_request) + 1;
450 for (pb = stmt->params; pb != NULL; pb = pb->next) {
451 if (pb->var_ptr == NULL) {
452 return cli_unbound_parameter;
453 }
454 if (pb->var_type == cli_asciiz) {
455 msg_size += strlen((char*)pb->var_ptr) + 1;
456 } else if (pb->var_type == cli_pasciiz) {
457 msg_size += strlen(*(char**)pb->var_ptr) + 1;
458 } else if (pb->var_type == cli_wstring) {
459 msg_size += (wcslen((wchar_t*)pb->var_ptr) + 1)*sizeof(wchar_t);
460 } else if (pb->var_type == cli_pwstring) {
461 msg_size += (wcslen(*(wchar_t**)pb->var_ptr) + 1)*sizeof(wchar_t);
462 } else {
463 msg_size += sizeof_type[pb->var_type];
464 }
465 }
466 stmt->oid = 0;
467 if (!stmt->prepared) {
468 msg_size += 4 + stmt->stmt_len + stmt->n_params;
469 msg_size += stmt->columns_len + stmt->n_columns;
470 }
471 dbSmallBuffer buf(msg_size);
472 p = buf;
473 cli_request* req = (cli_request*)p;
474 req->length = (int)msg_size;
475 req->cmd = stmt->prepared
476 ? cli_cmd_execute : cli_cmd_prepare_and_execute;
477 req->stmt_id = statement;
478 req->pack();
479 p += sizeof(cli_request);
480
481 if (!stmt->prepared) {
482 *p++ = stmt->n_params;
483 *p++ = stmt->n_columns;
484 p = pack2(p, stmt->stmt_len + stmt->n_params);
485 pb = stmt->params;
486 char* end = p + stmt->stmt_len + stmt->n_params;
487 char* src = stmt->stmt;
488 while (p < end) {
489 while ((*p++ = *src++) != '\0');
490 if (pb != NULL) {
491 *p++ = pb->var_type == cli_pasciiz ? cli_asciiz
492 : pb->var_type == cli_pwstring ? cli_wstring : pb->var_type;
493 pb = pb->next;
494 }
495 }
496 for (cb = stmt->columns; cb != NULL; cb = cb->next) {
497 *p++ = cb->var_type;
498 s = cb->name;
499 while ((*p++ = *s++) != '\0');
500 }
501 }
502 *p++ = for_update;
503 for (pb = stmt->params; pb != NULL; pb = pb->next) {
504 switch (pb->var_type) {
505 case cli_rectangle:
506 p = pack_rectangle(p, (cli_rectangle_t*)pb->var_ptr);
507 continue;
508 case cli_asciiz:
509 s = (char*)pb->var_ptr;
510 while ((*p++ = *s++) != '\0');
511 continue;
512 case cli_pasciiz:
513 s = *(char**)pb->var_ptr;
514 while ((*p++ = *s++) != '\0');
515 continue;
516 case cli_wstring:
517 {
518 wchar_t* src = (wchar_t*)pb->var_ptr;
519 wchar_t* dst = (wchar_t*)p;
520 while ((*dst++ = *src++) != 0);
521 p = (char*)dst;
522 continue;
523 }
524 case cli_pwstring:
525 {
526 wchar_t* src = *(wchar_t**)pb->var_ptr;
527 wchar_t* dst = (wchar_t*)p;
528 while ((*dst++ = *src++) != 0);
529 p = (char*)dst;
530 continue;
531 }
532 default:
533 switch (sizeof_type[pb->var_type]) {
534 case 1:
535 *p++ = *(char*)pb->var_ptr;
536 continue;
537 case 2:
538 p = pack2(p, *(int2*)pb->var_ptr);
539 continue;
540 case 4:
541 p = pack4(p, *(int4*)pb->var_ptr);
542 continue;
543 case 8:
544 p = pack8(p, *(db_int8*)pb->var_ptr);
545 continue;
546 }
547 }
548 }
549 assert(msg_size == (size_t)(p - buf.base()));
550 if (!stmt->session->sock->write(buf, msg_size)) {
551 return cli_network_error;
552 }
553 int4 response;
554 if (!stmt->session->sock->read(&response, sizeof response)) {
555 return cli_network_error;
556 }
557 unpack4(response);
558 if (response >= 0) {
559 stmt->prepared = true;
560 }
561 return response;
562 }
563
cli_send_columns(int statement,int cmd)564 static int cli_send_columns(int statement, int cmd)
565 {
566 statement_desc* s = statements.get(statement);
567 column_binding* cb;
568 if (s == NULL) {
569 return cli_bad_descriptor;
570 }
571 size_t msg_size = sizeof(cli_request);
572 if (cmd == cli_cmd_update) {
573 if (!s->prepared) {
574 return cli_not_fetched;
575 }
576 if (s->oid == 0) {
577 return cli_not_found;
578 }
579 if (s->updated) {
580 return cli_already_updated;
581 }
582 if (!s->for_update) {
583 return cli_not_update_mode;
584 }
585 } else {
586 if (!s->prepared) {
587 cmd = cli_cmd_prepare_and_insert;
588 msg_size += 1 + s->stmt_len + s->n_columns + s->columns_len;
589 }
590 }
591 s->autoincrement = false;
592 for (cb = s->columns; cb != NULL; cb = cb->next) {
593 if (cb->get_fnc != NULL) {
594 cb->arr_ptr = cb->get_fnc(cb->var_type, cb->var_ptr, &cb->arr_len,
595 cb->name, statement, cb->user_data);
596 int len = cb->arr_len;
597 msg_size += 4;
598 if (cb->var_type == cli_array_of_string) {
599 char** p = (char**)cb->arr_ptr;
600 while (--len >= 0) {
601 msg_size += strlen(*p++) + 1;
602 }
603 } else if (cb->var_type == cli_array_of_wstring) {
604 wchar_t** p = (wchar_t**)cb->arr_ptr;
605 while (--len >= 0) {
606 msg_size += (wcslen(*p++) + 1)*sizeof(wchar_t);
607 }
608 } else if (cb->var_type == cli_wstring || cb->var_type == cli_pwstring) {
609 msg_size += len * sizeof(wchar_t);
610 } else if (cb->var_type >= cli_array_of_oid) {
611 msg_size += len * sizeof_type[cb->var_type - cli_array_of_oid];
612 } else {
613 msg_size += len;
614 }
615 } else {
616 switch (cb->var_type) {
617 case cli_autoincrement:
618 s->autoincrement = true;
619 break;
620 case cli_asciiz:
621 msg_size += 4 + (strlen((char*)cb->var_ptr) + 1);
622 break;
623 case cli_pasciiz:
624 msg_size += 4 + (strlen(*(char**)cb->var_ptr) + 1);
625 break;
626 case cli_wstring:
627 msg_size += 4 + (wcslen((wchar_t*)cb->var_ptr) + 1)*sizeof(wchar_t);
628 break;
629 case cli_pwstring:
630 msg_size += 4 + (wcslen(*(wchar_t**)cb->var_ptr) + 1)*sizeof(wchar_t);
631 break;
632 case cli_array_of_string:
633 {
634 char** p = (char**)cb->var_ptr;
635 int len;
636 msg_size += 4;
637 for (len = *cb->var_len; --len >= 0;) {
638 msg_size += (strlen(*p++) + 1);
639 }
640 break;
641 }
642 case cli_array_of_wstring:
643 {
644 wchar_t** p = (wchar_t**)cb->var_ptr;
645 int len;
646 msg_size += 4;
647 for (len = *cb->var_len; --len >= 0;) {
648 msg_size += (wcslen(*p++) + 1)*sizeof(wchar_t);
649 }
650 break;
651 }
652 default:
653 if (cb->var_type >= cli_array_of_oid && cb->var_type < cli_array_of_string) {
654 msg_size += 4 + *cb->var_len * sizeof_type[cb->var_type-cli_array_of_oid];
655 } else {
656 msg_size += sizeof_type[cb->var_type];
657 }
658 }
659 }
660 }
661 dbSmallBuffer buf(msg_size);
662 char* p = buf;
663 cli_request* req = (cli_request*)p;
664 req->length = (int)msg_size;
665 req->cmd = cmd;
666 req->stmt_id = statement;
667 req->pack();
668 p += sizeof(cli_request);
669 if (cmd == cli_cmd_prepare_and_insert) {
670 char* cmd = s->stmt;
671 while ((*p++ = *cmd++) != '\0');
672 *p++ = s->n_columns;
673 for (cb = s->columns; cb != NULL; cb = cb->next) {
674 char* src = cb->name;
675 *p++ = cb->var_type;
676 while ((*p++ = *src++) != '\0');
677 }
678 }
679 for (cb = s->columns; cb != NULL; cb = cb->next) {
680 int n = 0;
681 char* src;
682 if (cb->get_fnc != NULL) {
683 src = (char*)cb->arr_ptr;
684 n = cb->arr_len;
685 } else {
686 src = (char*)cb->var_ptr;
687 if (cb->var_type >= cli_array_of_oid && (cb->var_type <= cli_array_of_string || cb->var_type == cli_array_of_wstring)) {
688 n = *cb->var_len;
689 }
690 }
691 if (cb->var_type >= cli_array_of_oid && (cb->var_type <= cli_array_of_string || cb->var_type == cli_array_of_wstring)) {
692 p = pack4(p, n);
693 if (cb->var_type == cli_array_of_string) {
694 while (--n >= 0) {
695 strcpy(p, *(char**)src);
696 p += strlen(p) + 1;
697 src += sizeof(char*);
698 }
699 } else if (cb->var_type == cli_array_of_wstring) {
700 while (--n >= 0) {
701 wcscpy((wchar_t*)p, *(wchar_t**)src);
702 p += (wcslen((wchar_t*)p) + 1)*sizeof(wchar_t);
703 src += sizeof(wchar_t*);
704 }
705 } else {
706 switch (sizeof_type[cb->var_type-cli_array_of_oid]) {
707 case 2:
708 while (--n >= 0) {
709 p = pack2(p, src);
710 src += 2;
711 }
712 break;
713 case 4:
714 while (--n >= 0) {
715 p = pack4(p, src);
716 src += 4;
717 }
718 break;
719 case 8:
720 while (--n >= 0) {
721 p = pack8(p, src);
722 src += 8;
723 }
724 break;
725 default:
726 memcpy(p, src, n);
727 p += n;
728 }
729 }
730 } else if (cb->var_type == cli_asciiz) {
731 p = pack4(p, (int)strlen(src)+1);
732 while ((*p++ = *src++) != 0);
733 } else if (cb->var_type == cli_pasciiz) {
734 src = *(char**)src;
735 p = pack4(p, (int)strlen(src)+1);
736 while ((*p++ = *src++) != 0);
737 } else if (cb->var_type == cli_wstring) {
738 wchar_t* body = (wchar_t*)src;
739 p = pack4(p, (int)wcslen(body)+1);
740 wchar_t* dst = (wchar_t*)p;
741 while ((*dst++ = *body++) != 0);
742 p = (char*)dst;
743 } else if (cb->var_type == cli_pwstring) {
744 wchar_t* body = *(wchar_t**)src;
745 p = pack4(p, (int)wcslen(body)+1);
746 wchar_t* dst = (wchar_t*)p;
747 while ((*dst++ = *body++) != 0);
748 p = (char*)dst;
749 } else if (cb->var_type == cli_rectangle) {
750 p = pack_rectangle(p, (cli_rectangle_t*)src);
751 } else if (cb->var_type != cli_autoincrement) {
752 switch (sizeof_type[cb->var_type]) {
753 case 2:
754 p = pack2(p, src);
755 break;
756 case 4:
757 p = pack4(p, src);
758 break;
759 case 8:
760 p = pack8(p, src);
761 break;
762 default:
763 *p++ = *src;
764 }
765 }
766 }
767 assert((size_t)(p - buf.base()) == msg_size);
768 if (!s->session->sock->write(buf, msg_size)) {
769 return cli_network_error;
770 }
771 return cli_ok;
772 }
773
cli_insert(int statement,cli_oid_t * oid)774 int cli_insert(int statement, cli_oid_t* oid)
775 {
776 int rc = cli_send_columns(statement, cli_cmd_insert);
777 if (rc == cli_ok) {
778 char buf[sizeof(cli_oid_t) + 8];
779 statement_desc* s = statements.get(statement);
780 if (!s->session->sock->read(buf, sizeof buf)) {
781 rc = cli_network_error;
782 } else {
783 rc = unpack4(buf);
784 s->prepared = true;
785 s->oid = unpack_oid(buf + 8);
786 if (oid != NULL) {
787 *oid = s->oid;
788 }
789 if (s->autoincrement) {
790 int4 rowid = unpack4(buf + 4);
791 for (column_binding* cb = s->columns; cb != NULL; cb = cb->next) {
792 if (cb->var_type == cli_autoincrement) {
793 *(int4*)cb->var_ptr = rowid;
794 }
795 }
796 }
797 }
798 }
799 return rc;
800 }
801
cli_update(int statement)802 int cli_update(int statement)
803 {
804 int rc = cli_send_columns(statement, cli_cmd_update);
805 if (rc == cli_ok) {
806 int4 response;
807 statement_desc* s = statements.get(statement);
808 s->updated = true;
809 if (!s->session->sock->read(&response, sizeof response)) {
810 rc = cli_network_error;
811 } else {
812 unpack4(response);
813 rc = response;
814 }
815 }
816 return rc;
817 }
818
cli_get(int statement,int cmd,cli_oid_t value=0)819 static int cli_get(int statement, int cmd, cli_oid_t value = 0)
820 {
821 statement_desc* s = statements.get(statement);
822 if (s == NULL) {
823 return cli_bad_descriptor;
824 }
825 if (!s->prepared) {
826 return cli_not_fetched;
827 }
828 struct get_req {
829 cli_request req;
830 cli_oid_t value;
831 } get;
832 int length = sizeof(cli_request);
833 if (cmd == cli_cmd_skip) {
834 length += 4;
835 pack4((char*)(&get.req+1), (int)value);
836 } else if (cmd == cli_cmd_seek) {
837 length += sizeof(cli_oid_t);
838 pack_oid((char*)(&get.req+1), value);
839 }
840 get.req.length = length;
841 get.req.cmd = cmd;
842 get.req.stmt_id = statement;
843 get.req.pack();
844 if (!s->session->sock->write(&get.req, length)) {
845 return cli_network_error;
846 }
847 int4 response;
848 if (!s->session->sock->read(&response, sizeof response)) {
849 return cli_network_error;
850 }
851 unpack4(response);
852 if (response <= 0) {
853 return response;
854 }
855 if (s->buf_size < (size_t)response-4) {
856 delete[] s->buf;
857 s->buf_size = response-4 < DEFAULT_BUF_SIZE ? DEFAULT_BUF_SIZE : response-4;
858 s->buf = new char[s->buf_size];
859 }
860 char* buf = s->buf;
861 if (!s->session->sock->read(buf, response-4)) {
862 return cli_network_error;
863 }
864 char* p = buf;
865 int result = cli_ok;
866 if (cmd == cli_cmd_seek) {
867 s->oid = value;
868 } else {
869 s->oid = unpack_oid(p);
870 if (s->oid == 0) {
871 return cli_not_found;
872 }
873 }
874 p += sizeof(cli_oid_t);
875 for (column_binding* cb = s->columns; cb != NULL; cb = cb->next) {
876 int type = *p++;
877 if (cb->var_type == cli_any) {
878 cb->var_type = type;
879 } else {
880 assert(cb->var_type == type);
881 }
882 if (cb->set_fnc != NULL) {
883 int len = unpack4(p);
884 p += 4;
885 char* dst = (char*)cb->set_fnc(cb->var_type, cb->var_ptr, len,
886 cb->name, statement, p, cb->user_data);
887 if (dst == NULL) {
888 continue;
889 }
890 if (cb->var_type == cli_array_of_string) {
891 char** s = (char**)dst;
892 while (--len >= 0) {
893 *s++ = p;
894 p += strlen(p) + 1;
895 }
896 } else if (cb->var_type == cli_array_of_wstring) {
897 wchar_t** s = (wchar_t**)dst;
898 while (--len >= 0) {
899 *s++ = (wchar_t*)p;
900 p += (wcslen((wchar_t*)p) + 1)*sizeof(wchar_t);
901 }
902 } else if (cb->var_type >= cli_array_of_oid && cb->var_type < cli_array_of_string) {
903 switch (sizeof_type[cb->var_type-cli_array_of_oid]) {
904 case 2:
905 while (--len >= 0) {
906 p = unpack2(dst, p);
907 dst += 2;
908 }
909 break;
910 case 4:
911 while (--len >= 0) {
912 p = unpack4(dst, p);
913 dst += 4;
914 }
915 break;
916 case 8:
917 while (--len >= 0) {
918 p = unpack8(dst, p);
919 dst += 8;
920 }
921 break;
922 default:
923 memcpy(dst, p, len);
924 p += len;
925 }
926 } else {
927 memcpy(dst, p, len);
928 p += len;
929 }
930 } else {
931 if (cb->var_type >= cli_asciiz && (cb->var_type <= cli_array_of_string || cb->var_type == cli_array_of_wstring)) {
932 int len = unpack4(p);
933 p += 4;
934 char* dst = (char*)cb->var_ptr;
935 char* src = p;
936 int n = len;
937 if (cb->var_len != NULL) {
938 if (n > *cb->var_len) {
939 n = *cb->var_len;
940 }
941 *cb->var_len = n;
942 }
943 if (cb->var_type == cli_wstring || cb->var_type == cli_pwstring) {
944 if (cb->var_type == cli_pwstring) {
945 dst = *(char**)dst;
946 }
947 memcpy(dst, p, n*sizeof(wchar_t));
948 p += len*sizeof(wchar_t);
949 } else if (cb->var_type >= cli_array_of_oid) {
950 if (cb->var_type == cli_array_of_string) {
951 char** s = (char**)dst;
952 len -= n;
953 while (--n >= 0) {
954 *s++ = p;
955 p += strlen(p) + 1;
956 }
957 while (--len >= 0) {
958 p += strlen(p) + 1;
959 }
960 } else if (cb->var_type == cli_array_of_wstring) {
961 wchar_t** s = (wchar_t**)dst;
962 len -= n;
963 while (--n >= 0) {
964 *s++ = (wchar_t*)p;
965 p += (wcslen((wchar_t*)p) + 1)*sizeof(wchar_t);
966 }
967 while (--len >= 0) {
968 p += (wcslen((wchar_t*)p) + 1)*sizeof(wchar_t);
969 }
970 } else {
971 switch (sizeof_type[cb->var_type-cli_array_of_oid]) {
972 case 2:
973 while (--n >= 0) {
974 src = unpack2(dst, src);
975 dst += 2;
976 }
977 p += len*2;
978 break;
979 case 4:
980 while (--n >= 0) {
981 src = unpack4(dst, src);
982 dst += 4;
983 }
984 p += len*4;
985 break;
986 case 8:
987 while (--n >= 0) {
988 src = unpack8(dst, src);
989 dst += 8;
990 }
991 p += len*8;
992 break;
993 default:
994 memcpy(dst, p, n);
995 p += len;
996 }
997 }
998 } else {
999 if (cb->var_type == cli_pasciiz) {
1000 dst = *(char**)dst;
1001 }
1002 memcpy(dst, p, n);
1003 p += len;
1004 }
1005 } else if (cb->var_type == cli_rectangle) {
1006 p = unpack_rectangle((cli_rectangle_t*)cb->var_ptr, p);
1007 } else {
1008 switch (sizeof_type[cb->var_type]) {
1009 case 2:
1010 p = unpack2((char*)cb->var_ptr, p);
1011 break;
1012 case 4:
1013 p = unpack4((char*)cb->var_ptr, p);
1014 break;
1015 case 8:
1016 p = unpack8((char*)cb->var_ptr, p);
1017 break;
1018 default:
1019 *(char*)cb->var_ptr = *p++;
1020 }
1021 }
1022 }
1023 }
1024 s->updated = false;
1025 return result;
1026 }
1027
cli_get_first(int statement)1028 int cli_get_first(int statement)
1029 {
1030 return cli_get(statement, cli_cmd_get_first);
1031 }
1032
cli_get_last(int statement)1033 int cli_get_last(int statement)
1034 {
1035 return cli_get(statement, cli_cmd_get_last);
1036 }
1037
cli_get_next(int statement)1038 int cli_get_next(int statement)
1039 {
1040 return cli_get(statement, cli_cmd_get_next);
1041 }
1042
cli_get_prev(int statement)1043 int cli_get_prev(int statement)
1044 {
1045 return cli_get(statement, cli_cmd_get_prev);
1046 }
1047
cli_skip(int statement,int n)1048 int cli_skip(int statement, int n)
1049 {
1050 return cli_get(statement, cli_cmd_skip, n);
1051 }
1052
cli_seek(int statement,cli_oid_t oid)1053 int cli_seek(int statement, cli_oid_t oid)
1054 {
1055 return cli_get(statement, cli_cmd_seek, oid);
1056 }
1057
1058
send_receive(int statement,int cmd)1059 static int send_receive(int statement, int cmd)
1060 {
1061 statement_desc* s = statements.get(statement);
1062 if (s == NULL) {
1063 return cli_bad_descriptor;
1064 }
1065 if (!s->prepared) {
1066 return cli_not_fetched;
1067 }
1068 cli_request req;
1069 req.length = sizeof(req);
1070 req.cmd = cmd;
1071 req.stmt_id = statement;
1072 req.pack();
1073 int4 response = cli_ok;
1074 if (!s->session->sock->write(&req, sizeof req)) {
1075 return cli_network_error;
1076 }
1077 if (!s->session->sock->read(&response, sizeof response)) {
1078 return cli_network_error;
1079 }
1080 unpack4(response);
1081 return response;
1082 }
1083
cli_freeze(int statement)1084 int cli_freeze(int statement)
1085 {
1086 return send_receive(statement, cli_cmd_freeze);
1087 }
1088
cli_unfreeze(int statement)1089 int cli_unfreeze(int statement)
1090 {
1091 return send_receive(statement, cli_cmd_unfreeze);
1092 }
1093
cli_get_oid(int statement)1094 cli_oid_t cli_get_oid(int statement)
1095 {
1096 statement_desc* s = statements.get(statement);
1097 if (s == NULL) {
1098 return 0;
1099 }
1100 return s->oid;
1101 }
1102
1103
cli_send_command(int session,int statement,int cmd)1104 static int cli_send_command(int session, int statement, int cmd)
1105 {
1106 session_desc* s = sessions.get(session);
1107 if (s == NULL) {
1108 return cli_bad_descriptor;
1109 }
1110 cli_request req;
1111 req.length = sizeof(cli_request);
1112 req.cmd = cmd;
1113 req.stmt_id = statement;
1114 req.pack();
1115 if (!s->sock->write(&req, sizeof req)) {
1116 return cli_network_error;
1117 }
1118 int4 response;
1119 if (!s->sock->read(&response, sizeof response)) {
1120 return cli_network_error;
1121 }
1122 unpack4(response);
1123 return response;
1124 }
1125
cli_close_cursor(int statement)1126 int cli_close_cursor(int statement)
1127 {
1128 return cli_ok;
1129 }
1130
cli_free(int statement)1131 int cli_free(int statement)
1132 {
1133 statement_desc* stmt = statements.get(statement);
1134 session_desc* s = stmt->session;
1135 if (s == NULL) {
1136 return cli_bad_descriptor;
1137 }
1138 statement_desc *sp, **spp = &s->stmts;
1139 while ((sp = *spp) != stmt) {
1140 if (sp == NULL) {
1141 return cli_bad_descriptor;
1142 }
1143 spp = &sp->next;
1144 }
1145 *spp = stmt->next;
1146 stmt->deallocate();
1147 statements.deallocate(stmt);
1148 cli_request req;
1149 req.length = sizeof(cli_request);
1150 req.cmd = cli_cmd_free_statement;
1151 req.stmt_id = statement;
1152 req.pack();
1153 if (!s->sock->write(&req, sizeof req)) {
1154 return cli_network_error;
1155 }
1156 return cli_ok;
1157 }
1158
cli_lock(int session)1159 int cli_lock(int session)
1160 {
1161 session_desc* s = sessions.get(session);
1162 if (s == NULL) {
1163 return cli_bad_descriptor;
1164 }
1165 cli_request req;
1166 req.length = sizeof(req);
1167 req.cmd = cli_cmd_lock;
1168 req.stmt_id = 0;
1169 req.pack();
1170 return s->sock->write(&req, sizeof req) ? cli_ok : cli_network_error;
1171 }
1172
1173
cli_commit(int session)1174 int cli_commit(int session)
1175 {
1176 return cli_send_command(session, 0, cli_cmd_commit);
1177 }
1178
cli_precommit(int session)1179 int cli_precommit(int session)
1180 {
1181 return cli_send_command(session, 0, cli_cmd_precommit);
1182 }
1183
cli_abort(int session)1184 int cli_abort(int session)
1185 {
1186 return cli_send_command(session, 0, cli_cmd_abort);
1187 }
1188
cli_remove(int statement)1189 int cli_remove(int statement)
1190 {
1191 statement_desc* s = statements.get(statement);
1192 if (s == NULL) {
1193 return cli_bad_descriptor;
1194 }
1195 if (s->oid == 0) {
1196 return cli_not_found;
1197 }
1198 if (!s->for_update) {
1199 return cli_not_update_mode;
1200 }
1201 return cli_send_command(s->session->id, s->id, cli_cmd_remove);
1202 }
1203
cli_remove_current(int statement)1204 int cli_remove_current(int statement)
1205 {
1206 statement_desc* s = statements.get(statement);
1207 if (s == NULL) {
1208 return cli_bad_descriptor;
1209 }
1210 if (s->oid == 0) {
1211 return cli_not_found;
1212 }
1213 if (!s->for_update) {
1214 return cli_not_update_mode;
1215 }
1216 return cli_send_command(s->session->id, s->id, cli_cmd_remove_current);
1217 }
1218
1219
cli_describe(int session,char const * table,cli_field_descriptor ** fields)1220 int cli_describe(int session, char const* table, cli_field_descriptor** fields)
1221 {
1222 int len = (int)(sizeof(cli_request) + strlen(table) + 1);
1223 dbSmallBuffer buf(len);
1224 cli_request* req = (cli_request*)buf.base();
1225 req->length = len;
1226 req->cmd = cli_cmd_describe_table;
1227 req->stmt_id = 0;
1228 strcpy((char*)(req+1), table);
1229 session_desc* s = sessions.get(session);
1230 if (s == NULL) {
1231 return cli_bad_descriptor;
1232 }
1233 req->pack();
1234 if (!s->sock->write(buf, len)) {
1235 return cli_network_error;
1236 }
1237 int4 response[2];
1238 if (!s->sock->read(&response, sizeof response)) {
1239 return cli_network_error;
1240 }
1241 unpack4(response[0]);
1242 unpack4(response[1]);
1243 len = response[0];
1244 int nFields = response[1];
1245 if (nFields == -1) {
1246 return cli_table_not_found;
1247 }
1248 char* p = (char*)malloc(nFields*sizeof(cli_field_descriptor) + len);
1249 cli_field_descriptor* fp = (cli_field_descriptor*)p;
1250 p += nFields*sizeof(cli_field_descriptor);
1251 if (!s->sock->read(p, len)) {
1252 return cli_network_error;
1253 }
1254 *fields = fp;
1255 for (int i = nFields; --i >= 0; fp++) {
1256 fp->type = (enum cli_var_type)*p++;
1257 fp->flags = *p++ & 0xFF;
1258 fp->name = p;
1259 p += strlen(p) + 1;
1260 if (*p != 0) {
1261 fp->refTableName = p;
1262 } else {
1263 fp->refTableName = NULL;
1264 }
1265 p += strlen(p) + 1;
1266 if (*p != 0) {
1267 fp->inverseRefFieldName = p;
1268 } else {
1269 fp->inverseRefFieldName = NULL;
1270 }
1271 p += strlen(p) + 1;
1272 }
1273 return nFields;
1274 }
1275
cli_describe_layout(int session,char const * table,cli_field_layout ** fields,int * rec_size)1276 int cli_describe_layout(int session, char const* table, cli_field_layout** fields, int* rec_size)
1277 {
1278 return cli_not_implemented;
1279 }
1280
cli_show_tables(int session,cli_table_descriptor ** tables)1281 int cli_show_tables(int session, cli_table_descriptor** tables)
1282 {
1283 session_desc* s = sessions.get(session);
1284 if (s == NULL) {
1285 return cli_bad_descriptor;
1286 }
1287 cli_request req;
1288 req.length = sizeof(cli_request);
1289 req.cmd = cli_cmd_show_tables;
1290 req.stmt_id = 0;
1291 req.pack();
1292 if (!s->sock->write(&req, sizeof req)) {
1293 return cli_network_error;
1294 }
1295 int4 response[2];
1296 if (!s->sock->read(&response, sizeof response)) {
1297 return cli_network_error;
1298 }
1299 unpack4(response[0]);
1300 unpack4(response[1]);
1301 int len = response[0];
1302 int nTables = response[1];
1303 if (nTables == -1) {
1304 return cli_table_not_found;
1305 }
1306 char* p = (char*)malloc(nTables*sizeof(cli_table_descriptor) + len);
1307 cli_table_descriptor* fp = (cli_table_descriptor*)p;
1308 p += nTables*sizeof(cli_table_descriptor);
1309 if (!s->sock->read(p, len)) {
1310 free(p);
1311 return cli_network_error;
1312 }
1313 *tables = fp;
1314 for (int i = nTables; --i >= 0; fp++) {
1315 fp->name = (char*)p;
1316 p += strlen((char*)p)+1;
1317 }
1318 return nTables;
1319 }
1320
1321
cli_create(char_t const * databaseName,char_t const * filePath,unsigned transactionCommitDelay,int openAttr,size_t initDatabaseSize,size_t extensionQuantum,size_t initIndexSize,size_t fileSizeLimit)1322 int cli_create(char_t const* databaseName,
1323 char_t const* filePath,
1324 unsigned transactionCommitDelay,
1325 int openAttr,
1326 size_t initDatabaseSize,
1327 size_t extensionQuantum,
1328 size_t initIndexSize,
1329 size_t fileSizeLimit)
1330 {
1331 return cli_bad_address;
1332 }
1333
1334
cli_update_table(int cmd,int session,char const * tableName,int nColumns,cli_field_descriptor * columns)1335 static int cli_update_table(int cmd, int session, char const* tableName, int nColumns,
1336 cli_field_descriptor* columns)
1337 {
1338 int i;
1339 session_desc* s = sessions.get(session);
1340 if (s == NULL) {
1341 return cli_bad_descriptor;
1342 }
1343 size_t size = sizeof(cli_request) + 4 + strlen(tableName)+1;
1344 for (i = 0; i < nColumns; i++) {
1345 size += 2 + (strlen(columns[i].name)+3);
1346 if (columns[i].refTableName != NULL) {
1347 size += strlen(columns[i].refTableName);
1348 }
1349 if (columns[i].inverseRefFieldName != NULL) {
1350 size += strlen(columns[i].inverseRefFieldName);
1351 }
1352 }
1353 dbSmallBuffer buf(size);
1354 cli_request* req = (cli_request*)buf.base();
1355 req->length = (int)size;
1356 req->cmd = cmd;
1357 req->stmt_id = 0;
1358 char* dst = (char*)(req + 1);
1359 strcpy(dst, tableName);
1360 dst += strlen(dst) + 1;
1361 *dst++ = (char)nColumns;
1362 for (i = 0; i < nColumns; i++) {
1363 *dst++ = (char)columns[i].type;
1364 *dst++ = (char)columns[i].flags;
1365 strcpy(dst, columns[i].name);
1366 dst += strlen(dst) + 1;
1367 if (columns[i].refTableName != NULL) {
1368 strcpy(dst, columns[i].refTableName);
1369 dst += strlen(dst) + 1;
1370 } else {
1371 *dst++ = 0;
1372 }
1373 if (columns[i].inverseRefFieldName != NULL) {
1374 strcpy(dst, columns[i].inverseRefFieldName);
1375 dst += strlen(dst) + 1;
1376 } else {
1377 *dst++ = 0;
1378 }
1379 }
1380 req->pack();
1381 if (!s->sock->write(buf, size)) {
1382 return cli_network_error;
1383 }
1384 int4 response;
1385 if (!s->sock->read(&response, sizeof response)) {
1386 return cli_network_error;
1387 }
1388 unpack4(response);
1389 return response;
1390 }
1391
cli_create_table(int session,char const * tableName,int nColumns,cli_field_descriptor * columns)1392 int cli_create_table(int session, char const* tableName, int nColumns,
1393 cli_field_descriptor* columns)
1394 {
1395 return cli_update_table(cli_cmd_create_table, session, tableName, nColumns, columns);
1396 }
1397
cli_alter_table(int session,char const * tableName,int nColumns,cli_field_descriptor * columns)1398 int cli_alter_table(int session, char const* tableName, int nColumns,
1399 cli_field_descriptor* columns)
1400 {
1401 return cli_update_table(cli_cmd_alter_table, session, tableName, nColumns, columns);
1402 }
1403
cli_drop_table(int session,char const * tableName)1404 int cli_drop_table(int session, char const* tableName)
1405 {
1406 session_desc* s = sessions.get(session);
1407 if (s == NULL) {
1408 return cli_bad_descriptor;
1409 }
1410 int size = (int)(sizeof(cli_request) + strlen(tableName) + 1);
1411 dbSmallBuffer buf(size);
1412 cli_request* req = (cli_request*)buf.base();
1413 req->length = size;
1414 req->cmd = cli_cmd_drop_table;
1415 req->stmt_id = 0;
1416 strcpy((char*)(req + 1), tableName);
1417 req->pack();
1418 if (!s->sock->write(buf, size)) {
1419 return cli_network_error;
1420 }
1421 int4 response;
1422 if (!s->sock->read(&response, sizeof response)) {
1423 return cli_network_error;
1424 }
1425 unpack4(response);
1426 return response;
1427 }
1428
cli_alter_index(int session,char const * tableName,char const * fieldName,int newFlags)1429 int cli_alter_index(int session, char const* tableName, char const* fieldName, int newFlags)
1430 {
1431 session_desc* s = sessions.get(session);
1432 if (s == NULL) {
1433 return cli_bad_descriptor;
1434 }
1435 int size = (int)(sizeof(cli_request) + 1 + strlen(tableName)+strlen(fieldName)+2);
1436 dbSmallBuffer buf(size);
1437 cli_request* req = (cli_request*)buf.base();
1438 req->length = size;
1439 req->cmd = cli_cmd_alter_index;
1440 req->stmt_id = 0;
1441 char* dst = (char*)(req + 1);
1442 strcpy(dst, tableName);
1443 dst += strlen(dst) + 1;
1444 strcpy(dst, fieldName);
1445 dst += strlen(dst) + 1;
1446 *dst++ = newFlags;
1447 req->pack();
1448 if (!s->sock->write(buf, size)) {
1449 return cli_network_error;
1450 }
1451 int4 response;
1452 if (!s->sock->read(&response, sizeof response)) {
1453 return cli_network_error;
1454 }
1455 unpack4(response);
1456 return response;
1457 }
1458
1459
cli_set_error_handler(int session,cli_error_handler new_handler,void * context)1460 cli_error_handler cli_set_error_handler(int session, cli_error_handler new_handler, void* context)
1461 {
1462 return NULL;
1463 }
1464
cli_create_replication_node(int nodeId,int nServers,char * nodeNames[],char const * databaseName,char const * filePath,int openAttr,size_t initDatabaseSize,size_t extensionQuantum,size_t initIndexSize,size_t fileSizeLimit)1465 int cli_create_replication_node(int nodeId,
1466 int nServers,
1467 char* nodeNames[],
1468 char const* databaseName,
1469 char const* filePath,
1470 int openAttr,
1471 size_t initDatabaseSize,
1472 size_t extensionQuantum,
1473 size_t initIndexSize,
1474 size_t fileSizeLimit)
1475 {
1476 return cli_not_implemented;
1477 }
1478
cli_attach(int session)1479 int cli_attach(int session)
1480 {
1481 return cli_not_implemented;
1482 }
1483
cli_detach(int session,int detach_mode)1484 int cli_detach(int session, int detach_mode)
1485 {
1486 return cli_not_implemented;
1487 }
1488
cli_free_memory(int,void * ptr)1489 void cli_free_memory(int, void* ptr)
1490 {
1491 free(ptr);
1492 }
1493
cli_get_database_state(int session,cli_database_monitor * monitor)1494 int cli_get_database_state(int session, cli_database_monitor* monitor)
1495 {
1496 return cli_not_implemented;
1497 }
1498
cli_set_trace_function(cli_trace_function_t)1499 void cli_set_trace_function(cli_trace_function_t)
1500 {
1501 }
1502
cli_prepare_query(int session,char const * query)1503 int cli_prepare_query(int session, char const* query)
1504 {
1505 return cli_not_implemented;
1506 }
1507
cli_execute_query(int statement,int for_update,void * record_struct,...)1508 int cli_execute_query(int statement, int for_update, void* record_struct, ...)
1509 {
1510 return cli_not_implemented;
1511 }
1512
cli_execute_query_ex(int statement,int for_update,void * record_struct,int n_params,int * param_types,void ** param_value)1513 int cli_execute_query_ex(int statement, int for_update, void* record_struct, int n_params, int* param_types, void** param_value)
1514 {
1515 return cli_not_implemented;
1516 }
1517
cli_insert_struct(int session,char const * table_name,void * record_struct,cli_oid_t * oid)1518 int cli_insert_struct(int session, char const* table_name, void* record_struct, cli_oid_t* oid)
1519 {
1520 return cli_not_implemented;
1521 }
1522
cli_get_field_size(cli_field_descriptor * fields,int field_no)1523 int cli_get_field_size(cli_field_descriptor* fields, int field_no)
1524 {
1525 return sizeof_type[fields[field_no].type];
1526 }
1527
1528
cli_get_field_offset(cli_field_descriptor * fields,int field_no)1529 int cli_get_field_offset(cli_field_descriptor* fields, int field_no)
1530 {
1531 int offs = 0;
1532 int size = 0;
1533 for (int i = 0; i <= field_no; i++) {
1534 size = sizeof_type[fields[i].type];
1535 offs = DOALIGN(offs, alignof_type[fields[i].type]);
1536 offs += size;
1537 }
1538 return offs - size;
1539 }
1540
cli_xml_export(int session,FILE * out)1541 int cli_xml_export(int session, FILE* out)
1542 {
1543 return cli_not_implemented;
1544 }
1545
cli_xml_import(int session,FILE * in)1546 int cli_xml_import(int session, FILE* in)
1547 {
1548 return cli_not_implemented;
1549 }
1550
cli_backup(int session,char const * file_name,int compactify)1551 int cli_backup(int session, char const* file_name, int compactify)
1552 {
1553 return cli_not_implemented;
1554 }
1555
cli_schedule_backup(int session,char const * file_name,int period)1556 int cli_schedule_backup(int session, char const* file_name, int period)
1557 {
1558 return cli_not_implemented;
1559 }
1560
cli_get_wrapping_rectangle(int session,char const * table,char const * field,cli_rectangle_t * rect)1561 int cli_get_wrapping_rectangle(int session, char const* table, char const* field, cli_rectangle_t* rect)
1562 {
1563 return cli_not_implemented;
1564 }
1565