-
Notifications
You must be signed in to change notification settings - Fork 236
Expand file tree
/
Copy pathsql.h
More file actions
1745 lines (1471 loc) · 66.5 KB
/
sql.h
File metadata and controls
1745 lines (1471 loc) · 66.5 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
/*
Copyright 2015 Bloomberg Finance L.P.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#ifndef _SQL_H_
#define _SQL_H_
#include <openssl/asn1.h> /* for ub_common_name */
#include "cdb2api.h"
#include "comdb2.h"
#include <bdb_api.h>
#include <bdb_cursor.h>
#include <berkdb/dbinc/queue.h>
#include "tag.h"
#include "osql_srs.h"
#include "osqlsqlthr.h"
#include "osqlcheckboard.h"
#include "osqlshadtbl.h"
#include "fwd_types.h"
#include "comdb2_ruleset.h"
#include <sp.h>
#include "sql_stmt_cache.h"
#include "db_access.h"
#include "sqliteInt.h"
#include "ast.h"
#include "fingerprint.h"
/* I'm now splitting handle_fastsql_requests into two functions. The
* outer function will maintain state (such as temporary buffers etc) while
* the inner function will actually run the sql query. This will allow me
* to eventually split the socket i/o (specifically, the waiting for the next
* query part) and the running of the query into different threads. This way
* we can have a small pool of sql threads with big stacks, and a large pool
* of appsock threads with small stacks. */
#define CHECK_NEXT_QUERIES 20
/* Static rootpages numbers. */
enum { RTPAGE_SQLITE_MASTER = 1, RTPAGE_START = 2 };
struct fingerprint_track {
unsigned char fingerprint[FINGERPRINTSZ]; /* md5 digest hex string */
int64_t count; /* Cumulative number of times executed */
int64_t cost; /* Cumulative cost */
int64_t time; /* Cumulative preparation and execution time */
int64_t max_cost; /* Max cost of any query */
int64_t prepTime; /* Cumulative preparation time only */
int64_t rows; /* Cumulative number of rows selected */
int64_t curr_analyze_gen; /* If the analyze gen number is different */
int check_next_queries; /* Check cost of next these many queries */
int cost_increased; /* queries with cost greater than avg cost */
int64_t pre_cost_avg_per_row; /* Average cost before last Analyze */
char *zNormSql; /* The normalized SQL query */
size_t nNormSql; /* Length of normalized SQL query */
int typeMismatch; /* Type(s) did not match when compared to sqlitex's */
int nameMismatch; /* Column name(s) did not match when compared to sqlitex's */
hash_t *query_plan_hash; /* Query plans associated with fingerprint + cost stats */
int alert_once_query_plan; /* Alert only once if there is a better query plan for a query. Init to 1 */
int alert_once_query_plan_max; /* Alert (once) if hit max number of plans for associated query. Init to 1 */
int alert_once_truncated_col; /* Alert once if we truncated some col in the query. Init to 1 */
};
struct sql_authorizer_state {
struct sqlclntstate *clnt; /* pointer to current client info */
sqlite3 *db;
int flags; /* DDL, PRAGMA, CREATE TRIGGER denied? */
int numDdls; /* number of DDLs found */
int numVTableLocks;
char **vTableLocks;
int hasVTables;
};
/* Thread specific sql state */
struct sqlthdstate {
struct reqlogger *logger;
struct sql_thread *sqlthd;
struct thr_handle *thr_self;
sqlite3 *sqldb;
struct sql_authorizer_state authState; /* SQL authorizer state info */
uint8_t have_lastuser;
char lastuser[MAX_USERNAME_LEN]; // last user to use this sqlthd
/* SQL statement cache */
stmt_cache_t *stmt_cache;
int dbopen_gen;
int analyze_gen;
int views_gen;
/* A flag to tell us whether we are inside the query preparer plugin. This
* is especially needed to differentiate between fdb cursors opened by core
* versus query preparer plugin. */
int query_preparer_running;
void *sqldbx;
};
typedef struct osqltimings {
unsigned long long query_received; /* query received, in need of dispatch */
unsigned long long query_dispatched; /* start sql processing */
unsigned long long
query_finished; /* done processing this query (includes commit) */
unsigned long long commit_prep; /* start shipping requests (relevant for
recom/snapisol/serial) */
unsigned long long commit_start; /* send commit signal */
unsigned long long commit_end; /* received signal back (relevant for
socksql/recom/snapisol,serial) */
} osqltimings_t;
typedef struct fdbtimings {
unsigned long long
total_time; /* total time for doing remote access, synchronous part */
unsigned long long total_calls; /* total number of remote rcp calls */
unsigned long long max_call; /* longest sync call */
} fdbtimings_t;
typedef struct {
const char *spname;
genid_t genid;
} shadbq_t;
struct srs_tran;
typedef struct osqlstate {
/* == sql_thread == */
osql_target_t target; /* where to send the bplog */
unsigned long long rqid; /* per node offload request session */
uuid_t uuid; /* session id, take 2 */
char *tablename; /* malloc-ed cache of send tablename for usedb */
int tablenamelen; /* tablename length */
int sentops; /* number of operations per statement */
int tran_ops; /* actual number of operations for a transaction */
int replicant_numops; /* total num of ops sent by replicant to master which
includes USEDB, BLOB, etc. */
/* == sqlclntstate == */
int count_changes; /* enable pragma count_changes=1, for rr, sosql, recom,
snapisol, serial */
/* storage for shadow tables created by offloading */
LISTC_T(struct shad_tbl) shadtbls;
/* storage for dbq's shadtbl */
shadbq_t shadbq;
hash_t *dbq_hash;
/* storage for verify, common for all transaction */
struct temp_table * verify_tbl;
struct temp_cursor *verify_cur; /* verify cursor */
/* storage for schemachange, common for all transaction */
struct temp_table *sc_tbl;
struct temp_cursor *sc_cur; /* schemachange cursor */
/* storage for bpfunc, common for all transaction */
struct temp_table *bpfunc_tbl;
struct temp_cursor *bpfunc_cur; /* bpfunc cursor */
int bpfunc_seq;
struct errstat xerr; /* extended error */
/* performance */
osqltimings_t timings; /* measure various timings */
fdbtimings_t fdbtimes; /* measure remote access */
/* verify handling */
/* keep the log of sql strings for the current transaction */
struct srs_tran *history;
int replay; /* set this when a session is replayed, used by sorese */
int sent_column_data; /* set this if we've already sent the column data */
/* XXX for debugging */
char *replay_file;
int replay_line;
int last_replay;
int error_is_remote; /* set if xerr is the error for a distributed tran
(i.e. already translated */
int dirty; /* optimization to nop selectv only transactions */
int running_ddl; /* ddl transaction */
unsigned is_reorder_on : 1;
/* set to 1 if we have already called osql_sock_start in socksql mode */
unsigned sock_started : 1;
unsigned has_updstat : 1;
} osqlstate_t;
enum ctrl_sqleng {
/* No user specified transactions, i.e. BEGIN/COMMIT */
SQLENG_NORMAL_PROCESS,
/* "BEGIN" was submitted, mark this as user transaction begin */
SQLENG_PRE_STRT_STATE,
/* We have seen 'BEGIN' and now waiting for a non-"BEGIN" user query */
SQLENG_STRT_STATE,
/* We have a transaction, ignore further BtreeTransBegin until
* COMMIT/ROLLBACK */
SQLENG_INTRANS_STATE,
/* "COMMIT" was submitted */
SQLENG_FNSH_STATE,
/* "ROLLBACK" was submitted */
SQLENG_FNSH_RBK_STATE,
/* Transaction has been aborted due to a bad command */
SQLENG_FNSH_ABORTED_STATE,
/* We have entered a wrong stated (possibly a bug) */
SQLENG_WRONG_STATE,
};
enum trans_clntcomm {
TRANS_CLNTCOMM_NOREPLY = 0,
TRANS_CLNTCOMM_NORMAL = 1,
TRANS_CLNTCOMM_CHUNK = 2
};
void sql_set_sqlengine_state(struct sqlclntstate *clnt, char *file, int line,
int newstate);
struct fdb_distributed_tran;
typedef struct fdb_distributed_tran fdb_distributed_tran_t;
struct fdb_tbl_ent;
typedef struct fdb_tbl_ent fdb_tbl_ent_t;
struct fdb_access;
typedef struct fdb_access fdb_access_t;
struct fdb_affinity;
typedef struct fdb_affinity fdb_affinity_t;
struct fdb;
typedef struct fdb fdb_t;
typedef struct {
enum transaction_level mode; /* TRANLEVEL_SOSQL, TRANLEVEL_RECOM, ... */
struct cursor_tran *cursor_tran; /* id used to open cursors sharing same deadlock identity*/
tran_type *shadow_tran; /* used to keep local changes to btree, uncommitted yet */
tran_type *logical_tran; /* used by rowlocks ? */
fdb_distributed_tran_t *dtran; /* remote transactions, contain each remote cluster tran */
int rollbacked; /* mark this to catch out-of-order errors */
sqlite3_stmt *pStmt; /* if sql is in progress, points at the engine */
fdb_tbl_ent_t **lockedRemTables; /* list of fdb_tbl_ent_t* for read-locked
remote tables */
int nLockedRemTables; /* number of pointers in lockedRemTablesRootp */
int trans_has_sp; /* running a stored procedure */
int maxchunksize; /* multi-transaction bulk mode */
int crtchunksize; /* how many rows are processed already */
int nchunks; /* number of chunks. 0 for a non-chunked transaction. */
int throttle_txn_chunks_msec; /* wait this many milliseconds before starting a new chunk (if 0 then look at tunable) */
/* cache the versions of dta files to catch schema changes and fastinits */
table_version_cache *table_version_cache;
} dbtran_type;
typedef dbtran_type trans_t;
/* analyze sampled (previously misnamed compressed) idx */
typedef struct {
char name[MAXTABLELEN];
int ixnum;
sampler_t *sampler;
int sampling_pct;
unsigned long long n_recs;
unsigned long long n_sampled_recs;
} sampled_idx_t;
typedef struct sqlclntstate_fdb {
SBUF2 *remote_sql_sb; /* IN REMOTE DB: set if this is on behalf of a remote
sql session */
int flags; /* requester flags, like is this a sqlite_master special request
?*/
char *trim_key; /* key used in prefiltering for find ops (sqlite_packed) */
int trim_keylen; /* lenght of the trim key */
fdb_access_t *access; /* access control */
int version; /* version of the remote-cached object */
char *dbname; /* if err is set, this indicate which fdb is responsible, if
any */
char *tblname; /* if err is set, this indicate which tablename is
responsible */
int code_release; /* code release in the remote requester */
fdb_affinity_t *aff; /* location affinity information */
struct errstat
xerr; /* error in fdb component, used to override sqlite and osql.xerr
errors */
int preserve_err; /* set to ignore up-stream errors when lower system sets
xerr */
/* source side fields */
int n_fdb_affinities; /* number of fdbs in the fdb_ids and fdb_nodes arrays
*/
char **fdb_ids; /* the fdb for which we have affinity */
char **fdb_nodes; /* node numbers preferred for each fdb in fdb_ids */
int *fdb_last_status; /* used to mark a node bad after a failure */
int failed_heartbeats; /* used to signal failed communication with remotes */
} sqlclntstate_fdb_t;
enum ucancel_type {
UCANCEL_INV = 0,
UCANCEL_ALL = 1, /* both queued and running */
UCANCEL_RUN = 2, /* running only */
UCANCEL_QUE = 4, /* queued only */
UCANCEL_CNO = 8, /* filter by cnonce */
UCANCEL_FPT = 16 /* filter by fp */
};
int ucancel_sql_statements(enum ucancel_type type, char *uuid);
CurRange *currange_new();
#define CURRANGEARR_INIT_CAP 2
void currangearr_init(CurRangeArr *arr);
void currangearr_append(CurRangeArr *arr, CurRange *r);
CurRange *currangearr_get(CurRangeArr *arr, int n);
void currangearr_double_if_full(CurRangeArr *arr);
void currangearr_build_hash(CurRangeArr *arr);
void currangearr_free(CurRangeArr *arr);
void currangearr_print(CurRangeArr *arr);
void currange_free(CurRange *cr);
struct stored_proc;
struct lua_State;
struct typessql;
struct dohsql;
struct dohsql_node;
typedef struct fdb_push_connector fdb_push_connector_t;
enum early_verify_error {
EARLY_ERR_VERIFY = 1,
EARLY_ERR_SELECTV = 2,
EARLY_ERR_GENCHANGE = 3
};
enum connection_state
{
CONNECTION_NEW,
CONNECTION_IDLE,
CONNECTION_RESET,
CONNECTION_QUEUED,
CONNECTION_RUNNING
};
enum {
ERR_GENERIC = -1,
ERR_PREPARE = -2,
ERR_PREPARE_RETRY = -3,
ERR_ROW_HEADER = -4,
ERR_CONVERSION_DT = -5,
};
#define RESPONSE_TYPES \
XRESPONSE(RESPONSE_COLUMNS) \
XRESPONSE(RESPONSE_COLUMNS_LUA) \
XRESPONSE(RESPONSE_COLUMNS_STR) \
XRESPONSE(RESPONSE_COLUMNS_FDB_PUSH) \
XRESPONSE(RESPONSE_COST) \
XRESPONSE(RESPONSE_DEBUG) \
XRESPONSE(RESPONSE_EFFECTS) \
XRESPONSE(RESPONSE_ERROR) \
XRESPONSE(RESPONSE_ERROR_ACCESS) \
XRESPONSE(RESPONSE_ERROR_APPSOCK_LIMIT) \
XRESPONSE(RESPONSE_ERROR_BAD_STATE) \
XRESPONSE(RESPONSE_ERROR_PREPARE) \
XRESPONSE(RESPONSE_ERROR_PREPARE_RETRY) \
XRESPONSE(RESPONSE_ERROR_REJECT) \
XRESPONSE(RESPONSE_ERROR_INCOMPLETE) \
XRESPONSE(RESPONSE_REDIRECT_FOREIGN) \
XRESPONSE(RESPONSE_FLUSH) \
XRESPONSE(RESPONSE_HEARTBEAT) \
XRESPONSE(RESPONSE_QUERY_STATS) \
XRESPONSE(RESPONSE_ROW) \
XRESPONSE(RESPONSE_ROW_LAST) \
XRESPONSE(RESPONSE_ROW_LAST_DUMMY) \
XRESPONSE(RESPONSE_ROW_LUA) \
XRESPONSE(RESPONSE_ROW_STR) \
XRESPONSE(RESPONSE_TRACE) \
XRESPONSE(RESPONSE_ROW_REMTRAN) \
XRESPONSE(RESPONSE_RAW_PAYLOAD)
#define XRESPONSE(x) x,
enum WriteResponsesEnum { RESPONSE_TYPES };
#undef XRESPONSE
/* read response */
enum {
RESPONSE_PING_PONG,
RESPONSE_SP_CMD,
RESPONSE_BYTES,
};
struct response_data {
sqlite3_stmt *stmt;
struct errstat *err;
uint64_t row_id;
/* For RESPONSE_COLUMNS_LUA, RESPONSE_ROW_LUA */
int ncols;
int pingpong;
struct stored_proc *sp;
};
char *sp_column_name(struct response_data *, int);
int sp_column_type(struct response_data *, int, size_t, int);
int sp_column_nil(struct response_data *, int);
int sp_column_val(struct response_data *, int, int, void *);
void *sp_column_ptr(struct response_data *, int, int, size_t *);
typedef int(plugin_func)(struct sqlclntstate *);
typedef const char *(api_type_func)(struct sqlclntstate *);
typedef int(response_func)(struct sqlclntstate *, int, void *, int);
typedef void *(replay_func)(struct sqlclntstate *, void *);
typedef int(param_index_func)(struct sqlclntstate *, const char *, int64_t *);
typedef int(param_value_func)(struct sqlclntstate *, struct param_data *, int);
typedef int(cnonce_value_func)(struct sqlclntstate *, snap_uid_t *);
typedef int(get_snapshot_func)(struct sqlclntstate *, int *, int *);
typedef void(add_steps_func)(struct sqlclntstate *, double steps);
typedef void(setup_client_info_func)(struct sqlclntstate *, struct sqlthdstate *, char *);
typedef int(skip_row_func)(struct sqlclntstate *, uint64_t);
typedef int(log_context_func)(struct sqlclntstate *, struct reqlogger *);
typedef uint64_t(ret_uint64_func)(struct sqlclntstate *);
typedef int(override_type_func)(struct sqlclntstate *, int);
typedef void *(auth_func)(struct sqlclntstate *);
#define SQLITE_CALLBACK_API(ret, name) \
ret (*column_##name)(struct sqlclntstate *, sqlite3_stmt *, int)
struct plugin_callbacks {
response_func *write_response; /* newsql_write_response */
response_func *read_response; /* newsql_read_response */
replay_func *save_stmt; /* newsql_save_stmt */
replay_func *restore_stmt; /* newsql_restore_stmt */
replay_func *destroy_stmt; /* newsql_destroy_stmt */
replay_func *print_stmt; /* newsql_print_stmt */
// bound params
plugin_func *param_count; /* newsql_param_count */
plugin_query_data_func *query_data_func;
param_index_func *param_index; /* newsql_param_index */
param_value_func *param_value; /* newsql_param_value */
// run_statement_typed
plugin_func *override_count; /* newsql_override_count */
override_type_func *override_type; /* newsql_override_type */
plugin_func *has_cnonce; /* newsql_has_cnonce */
plugin_func *set_cnonce; /* newsql_set_cnonce */
plugin_func *clr_cnonce; /* newsql_clr_cnonce */
cnonce_value_func *get_cnonce; /* newsql_has_cnonce */
get_snapshot_func *get_snapshot; /* newsql_get_snapshot */
plugin_func *upd_snapshot; /* newsql_update_snapshot */
plugin_func *clr_snapshot; /* newsql_clear_snapshot */
plugin_func *has_high_availability; /* newsql_has_high_availability */
plugin_func *set_high_availability; /* newsql_set_high_availability */
plugin_func *clr_high_availability; /* newsql_clr_high_availability */
plugin_func *get_high_availability; /* newsql_get_high_availability*/
plugin_func *has_parallel_sql; /* newsql_has_parallel_sql */
add_steps_func *add_steps; /* newsql_add_steps */
setup_client_info_func *setup_client_info; /* newsql_setup_client_info */
skip_row_func *skip_row; /* newsql_skip_row */
log_context_func *log_context; /* newsql_log_context */
ret_uint64_func *get_client_starttime; /* newsql_get_client_starttime */
plugin_func *get_client_retries; /* newsql_get_client_retries */
plugin_func *send_intrans_response; /* newsql_send_intrans_response */
/* These may change depending on underlying tranport (sbuf2 or libevent) */
plugin_func *close; /* newsql_close_evbuffer */
plugin_func *flush; /* newsql_flush_evbuffer */
plugin_func *get_fileno; /* newsql_get_fileno_evbuffer */
response_func *get_x509_attr; /* newsql_get_x509_attr_evbuffer */
plugin_func *has_ssl; /* newsql_has_ssl_evbuffer */
plugin_func *has_x509; /* newsql_has_x509_evbuffer */
plugin_func *local_check; /* newsql_local_check_evbuffer */
plugin_func *peer_check; /* newsql_peer_check_evbuffer */
auth_func *get_authdata; /* newsql_get_authdata */
plugin_func *free_authdata; /* newsql_free_authdata */
api_type_func *api_type; /* newsql_api_type */
/* Optional */
void *state;
int (*column_count)(struct sqlclntstate *, sqlite3_stmt *); /* sqlite3_column_count */
int (*next_row)(struct sqlclntstate *, sqlite3_stmt *); /* sqlite3_step */
char *(*tzname)(struct sqlclntstate *, sqlite3_stmt *); /* stmt_tzname */
SQLITE_CALLBACK_API(int, type); /* sqlite3_column_type */
SQLITE_CALLBACK_API(sqlite_int64, int64); /* sqlite3_column_int64*/
SQLITE_CALLBACK_API(double, double); /* sqlite3_column_double*/
SQLITE_CALLBACK_API(const unsigned char *, text); /* sqlite3_column_text */
SQLITE_CALLBACK_API(int, bytes); /* sqlite3_column_bytes */
SQLITE_CALLBACK_API(const void *, blob); /* sqlite3_column_bytes */
SQLITE_CALLBACK_API(const dttz_t *, datetime); /* sqlite3_column_datetime */
SQLITE_CALLBACK_API(sqlite3_value *, value); /* sqlite3_column_value */
const intv_t *(*column_interval)(struct sqlclntstate *, sqlite3_stmt *, int, int); /* sqlite3_column_interval*/
int (*sqlite_error)(struct sqlclntstate *, sqlite3_stmt *, const char **errstr); /* sqlite3_errcode */
void *(*get_identity)(struct sqlclntstate *);
};
#define make_plugin_callback(clnt, name, func) \
(clnt)->plugin.func = name##_##func
#define make_plugin_optional_null(clnt, name) \
(clnt)->plugin.column_##name = NULL
#define plugin_set_callbacks(clnt, name) \
do { \
make_plugin_callback(clnt, name, write_response); \
make_plugin_callback(clnt, name, read_response); \
make_plugin_callback(clnt, name, save_stmt); \
make_plugin_callback(clnt, name, restore_stmt); \
make_plugin_callback(clnt, name, destroy_stmt); \
make_plugin_callback(clnt, name, print_stmt); \
make_plugin_callback(clnt, name, param_count); \
make_plugin_callback(clnt, name, param_index); \
make_plugin_callback(clnt, name, param_value); \
make_plugin_callback(clnt, name, override_count); \
make_plugin_callback(clnt, name, override_type); \
make_plugin_callback(clnt, name, has_cnonce); \
make_plugin_callback(clnt, name, set_cnonce); \
make_plugin_callback(clnt, name, clr_cnonce); \
make_plugin_callback(clnt, name, get_cnonce); \
make_plugin_callback(clnt, name, get_snapshot); \
make_plugin_callback(clnt, name, upd_snapshot); \
make_plugin_callback(clnt, name, clr_snapshot); \
make_plugin_callback(clnt, name, has_high_availability); \
make_plugin_callback(clnt, name, set_high_availability); \
make_plugin_callback(clnt, name, clr_high_availability); \
make_plugin_callback(clnt, name, get_high_availability); \
make_plugin_callback(clnt, name, has_parallel_sql); \
make_plugin_callback(clnt, name, add_steps); \
make_plugin_callback(clnt, name, setup_client_info); \
make_plugin_callback(clnt, name, skip_row); \
make_plugin_callback(clnt, name, log_context); \
make_plugin_callback(clnt, name, get_client_starttime); \
make_plugin_callback(clnt, name, get_client_retries); \
make_plugin_callback(clnt, name, send_intrans_response); \
make_plugin_callback(clnt, name, close); \
make_plugin_callback(clnt, name, flush); \
make_plugin_callback(clnt, name, get_fileno); \
make_plugin_callback(clnt, name, get_x509_attr); \
make_plugin_callback(clnt, name, has_ssl); \
make_plugin_callback(clnt, name, has_x509); \
make_plugin_callback(clnt, name, local_check); \
make_plugin_callback(clnt, name, peer_check); \
make_plugin_callback(clnt, name, get_authdata); \
make_plugin_callback(clnt, name, free_authdata); \
make_plugin_callback(clnt, name, api_type); \
make_plugin_callback(clnt, name, get_identity); \
make_plugin_optional_null(clnt, count); \
make_plugin_optional_null(clnt, type); \
make_plugin_optional_null(clnt, int64); \
make_plugin_optional_null(clnt, double); \
make_plugin_optional_null(clnt, text); \
make_plugin_optional_null(clnt, bytes); \
make_plugin_optional_null(clnt, blob); \
make_plugin_optional_null(clnt, datetime); \
make_plugin_optional_null(clnt, interval); \
make_plugin_optional_null(clnt, value); \
(clnt)->plugin.state = NULL; \
(clnt)->plugin.next_row = NULL; \
(clnt)->plugin.tzname = NULL; \
(clnt)->plugin.query_data_func = NULL; \
} while (0)
int param_count(struct sqlclntstate *);
int param_index(struct sqlclntstate *, const char *, int64_t *);
int param_value(struct sqlclntstate *, struct param_data *, int);
int override_count(struct sqlclntstate *);
int override_type(struct sqlclntstate *, int);
int get_cnonce(struct sqlclntstate *, snap_uid_t *);
int has_high_availability(struct sqlclntstate *);
int has_parallel_sql(struct sqlclntstate *);
int set_high_availability(struct sqlclntstate *);
int clr_high_availability(struct sqlclntstate *);
uint64_t get_client_starttime(struct sqlclntstate *);
int get_client_retries(struct sqlclntstate *);
void *get_authdata(struct sqlclntstate *);
void free_authdata(struct sqlclntstate *);
char *clnt_tzname(struct sqlclntstate *, sqlite3_stmt *);
struct clnt_ddl_context {
/* Name of the table */
char *name;
/* Pointer to a comdb2_ddl_context */
void *ctx;
/* Memory allocator of the comdb2_ddl_context */
comdb2ma mem;
};
#if INSTRUMENT_RECOVER_DEADLOCK_FAILURE
#define RECOVER_DEADLOCK_MAX_STACK 16348
#endif
enum prepare_flags {
PREPARE_NONE = 0,
PREPARE_RECREATE = 1,
PREPARE_DENY_CREATE_TRIGGER = 2,
PREPARE_DENY_PRAGMA = 4,
PREPARE_DENY_DDL = 8,
PREPARE_IGNORE_ERR = 16,
PREPARE_NO_NORMALIZE = 32,
PREPARE_ONLY = 64,
PREPARE_ALLOW_TEMP_DDL = 128,
};
/* This structure is designed to hold several pieces of data related to
* work-in-progress on client SQL requests. */
struct sqlworkstate {
const char *zNormSql; /* Normalized version of latest SQL query. */
char *zOrigNormSql; /* Normalized version of original SQL query. */
struct sql_state rec; /* Prepared statement for original SQL query. */
unsigned char aFingerprint[FINGERPRINTSZ]; /* MD5 of normalized SQL. */
char zRuleRes[300]; /* Ruleset match result, if any. */
};
struct sql_hist_cost {
double cost;
int64_t time;
int64_t prepTime;
int64_t rows;
};
struct user {
char name[MAX_USERNAME_LEN];
char password[MAX_PASSWORD_LEN];
uint8_t have_name;
uint8_t have_password;
/* 1 if the user is retrieved from a client certificate */
uint8_t is_x509_user;
/* Set to allow automatically triggered operations, like autoanalyze, to
go through. */
uint8_t bypass_auth;
};
enum remsql_type {
NO_REMSQL = 0,
IS_REMSQL = 1,
IS_REMCREATE = 2
};
struct remsql_set {
enum remsql_type is_remsql;
int server_version;
int table_version;
int is_schema;
char tablename[MAXTABLELEN];
uuid_t uuid;
char *srcdbname;
struct errstat xerr;
uint32_t numdbs;
char **dbnames;
int32_t numcols;
char **columns;
char **shardnames;
};
#define in_client_trans(clnt) ((clnt)->in_client_trans)
struct string_ref;
struct session_tbl;
void clear_session_tbls(struct sqlclntstate *);
void clear_participants(struct sqlclntstate *);
int add_participant(struct sqlclntstate *, const char *dbname, const char *tier);
struct features {
unsigned have_ssl : 1;
unsigned have_sqlite_fmt : 1;
unsigned allow_incoherent : 1;
unsigned skip_intrans_results : 1;
unsigned flat_col_vals : 1;
unsigned request_fp : 1;
unsigned require_fastsql : 1;
unsigned can_redirect_fdb : 1;
unsigned allow_master_exec : 1;
unsigned allow_master_dbinfo : 1;
unsigned queue_me : 1;
};
/* Client specific sql state */
struct sqlclntstate {
struct thdpool *pPool; /* When null, the default SQL thread pool is
* being used to service the request; otherwise,
* a specifically assigned SQL thread pool is
* being used. */
struct sqlworkstate work; /* This is the primary data related to the SQL
* client request in progress. This includes
* the original SQL query and its normalized
* variant (if applicable). */
/* appsock plugin specific data */
void *authdata;
void *appdata;
struct plugin_callbacks plugin;
struct plugin_callbacks backup; /* allow transient client state mutations */
/* typessql structs */
struct plugin_callbacks adapter;
struct plugin_callbacks adapter_backup;
struct typessql *typessql_state;
unsigned typessql : 1; // should query use typessql (determined from set stmt)
/* bplog write plugin */
int (*begin)(struct sqlclntstate *clnt, int retries, int keep_id);
int (*end)(struct sqlclntstate *clnt);
int (*wait)(struct sqlclntstate *clnt, int timeout, struct errstat *err);
dbtran_type dbtran;
pthread_mutex_t dtran_mtx; /* protect dbtran.dtran, if any,
for races betweem sql thread created and
other readers, like appsock */
/* These are only valid while a query is in progress and will point into
* the i/o thread's buf */
pthread_mutex_t sql_lk;
char *sql;
struct string_ref *sql_ref;
struct string_ref *hint_sql_ref;
int recno;
int client_understands_query_stats;
char tzname[CDB2_MAX_TZNAME];
int dtprec;
struct conninfo conninfo;
/* For SQL engine dispatch. */
int inited_mutex;
pthread_mutex_t wait_mutex;
pthread_cond_t wait_cond;
pthread_mutex_t write_lock;
pthread_cond_t write_cond;
int query_rc;
struct rawnodestats *rawnodestats;
uuid_t unifieduuid; /* assigned to any statement running, used for canceling live sql */
osqlstate_t osql; /* offload sql state is kept here */
enum ctrl_sqleng ctrl_sqlengine; /* use to mark a begin/end out of state,
see enum ctrl_sqleng
*/
int intrans; /* THIS FIELD IS USED BY sqlglue.c TO RECORD THE ENTRANCE (=1)
AND THE EXIT(=0) in a sql transaction marked by a succesfull
call to BeginTrans, and Commit/Rollback respectively
THIS DOES NOT MATCH THE CLIENT TRANSACTION EXCERPT FOR
SINGULAR STATEMENTS;
STATE OF A CLIENT TRANSACTION IS KEPT HERE
*/
struct convert_failure fail_reason; /* detailed error */
int early_retry;
/* analyze variables */
int n_cmp_idx;
sampled_idx_t *sampled_idx_tbl;
int last_check_time;
int query_timeout;
int statement_timedout;
uint8_t heartbeat;
uint8_t ready_for_heartbeats;
uint8_t no_more_heartbeats;
uint8_t done;
plugin_func *done_cb; /* newsql_done_evbuffer */
unsigned long long sqltick, sqltick_last_seen;
int using_case_insensitive_like;
int deadlock_recovered;
struct timeval last_sql_recover_time;
/* lua stored procedure */
struct stored_proc *sp;
int exec_lua_thread;
int want_stored_procedure_trace;
int want_stored_procedure_debug;
char spname[MAX_SPNAME + 1];
struct spversion_t spversion;
unsigned int bdb_osql_trak; /* 32 debug bits interpreted by bdb for your
"set debug bdb"*/
struct client_query_stats *query_stats;
SBUF2 *dbglog;
int queryid;
unsigned long long dbglog_cookie;
unsigned long long master_dbglog_cookie;
int have_query_limits;
struct query_limits limits;
/* effects: per txn. keeps track of replicant effects when in-txn, and master effects when committed.
* log_effects: per chunked-txn. keeps track of replicant effects of all chunks,
* including the current chunk which hasn't committed yet.
* chunk_effects: per chunked-txn. keeps track of master effects of all committed chunks.
* remote_effects: cummulation of all distributed effects
*
* I hope the example below explains these effects a little better.
*
* CREATE TABLE t (i INTEGER)$$
* SET TRANSACTION CHUNK 1
* BEGIN
* INSERT INTO t VALUES(1) -- Nothing is committed yet. effects: 1; log_effects: 1; chunk_effects: 0.
* INSERT INTO t VALUES(2) -- (1) is committed. effects: 1; log_effects: 2; chunk_effects: 1;
* INSERT INTO t VALUES(3) -- (2) is committed. effects: 1; log_effects: 3; chunk_effects: 2;
* COMMIT -- (3) is committed. effects: 1; log_effects: 3; chunk_effects: 3;
*
* NOTE: handling the num_selects
* - any standalone query will use effects.num_selected
* - any standalone write will use and preserve effects.num_selected upon receiving master effects
* - any client transaction query will use effects.num_selected, incremented for each new query
* - any client transaction write will use effects.num_selected, returned or not based on verifyretry
* - any client transaction commit will preserve (i.e. not reset) effects.num_selected
*
*/
struct query_effects effects;
struct query_effects log_effects;
struct query_effects chunk_effects;
struct query_effects remote_effects;
int64_t nsteps;
struct user current_user;
int authgen;
char *origin;
TAILQ_HEAD(, session_tbl) session_tbls;
int had_errors; /* to remain compatible with blocksql: if a user starts a
transaction, we
need to pend the first error until a commit is issued.
any statements
past the first error are ignored. */
int in_client_trans; /* clnt is in a client transaction (ie. client ran
"begin" but not yet commit or rollback */
char *saved_errstr; /* if had_errors, save the error string */
int saved_rc; /* if had_errors, save the return code */
char *sqlite_errstr; /* sqlite error string, static, never allocated */
int prep_rc; /* last value returned from sqlite3_prepare_v3() */
int step_rc; /* last value returned from sqlite3_step() */
int isselect; /* track if the query is a select query.*/
int isUnlocked;
int writeTransaction;
int prepare_only;
int verify_retries; /* how many verify retries we've borne */
int verifyretry_off;
int pageordertablescan;
int snapshot; /* snapshot epoch placeholder */
int snapshot_file;
int snapshot_offset;
int is_hasql_retry;
int is_readonly;
int is_readonly_set; /* Whether 'readonly' was set explicitly via SET command? */
int force_readonly;
int is_expert;
int is_fast_expert; /* 1 if not scanning data to generate stat1 */
int added_to_hist;
struct thr_handle *thr_self;
arch_tid appsock_id;
int holding_pagelocks_flag; /* Rowlocks optimization */
/* remote settings, used in run_sql */
sqlclntstate_fdb_t fdb_state;
int nrows;
struct sql_hist_cost spcost;
int planner_effort;
int osql_max_trans;
int group_concat_mem_limit;
/* read-set validation */
CurRangeArr *arr;
CurRangeArr *selectv_arr;
char *prev_cost_string;
int num_retry;
unsigned int file;
unsigned int offset;
uint64_t enque_timeus;
uint64_t deque_timeus;
/* due to some sqlite vagaries, cursor is closed
and I lose the side row; cache it here! */
unsigned long long keyDdl;
int nDataDdl;
char *dataDdl;
/* partial indexes */
unsigned long long ins_keys;
unsigned long long del_keys;
int has_sqliterow;
int verify_indexes;
void *schema_mems;
/* indexes on expressions */
uint8_t **idxInsert;
uint8_t **idxDelete;
int8_t wrong_db;
int8_t high_availability_flag;
int8_t hasql_on;
int8_t has_recording;
int8_t is_retry;
int8_t get_cost;
int8_t is_explain;
uint8_t is_analyze;
uint8_t is_overlapping;
uint32_t init_gen;
int8_t gen_changed;
uint8_t skip_peer_chk; /* 1 if this is a temp table operation from an SP,
where peer check and the dbopen_gen check at commit time are skipped. */
uint8_t queue_me;
uint8_t fail_dispatch;
uint8_t in_sqlite_init; /* clnt is in sqlite init phase when this is set */
uint8_t secure; /* clnt is forwarded from pmux over the secure port, */
int where_trace_flags;
int ncontext;
char **context;
hash_t *ddl_tables;
hash_t *dml_tables;
hash_t *ddl_contexts;
int statement_query_effects;
int verify_remote_schemas;
/* sharding scheme */
struct dohsql *conns;
int nconns;
int conns_idx;
int shard_slice;
fdb_push_connector_t *fdb_push;
char *argv0;
char *stack;
/* api driver information */
char *api_driver_name;
char *api_driver_version;
int translevel_changed;
int admin;
/* Grab this mutex when calling sql_tick. This is to prevent race when
multiple threads are working on a single clnt (parallel-count, for instance). */
pthread_mutex_t sql_tick_lk;
uint32_t start_gen;
int emitting_flag;
int need_recover_deadlock;
int recover_deadlock_rcode;
int heartbeat_lock;
#ifdef INSTRUMENT_RECOVER_DEADLOCK_FAILURE
const char *recover_deadlock_func;
int recover_deadlock_line;
pthread_t recover_deadlock_thd;
char recover_deadlock_stack[RECOVER_DEADLOCK_MAX_STACK];
#endif
struct sqlthdstate *thd;
int had_lease_at_begin;
int64_t connid;
int64_t total_sql;
int64_t sql_since_reset;
int64_t num_resets;
time_t connect_time;
time_t last_reset_time;
int state_start_time;
int64_t netwaitus;
enum connection_state state;
pthread_mutex_t state_lk;
/* The node doesn't change. The pid does as connections get donated. We
* latch both values here since conninfo is lost when connections are reset. */
int last_pid;
char* origin_host;
int8_t sent_data_to_client;
int8_t is_asof_snapshot;
LINKC_T(struct sqlclntstate) lnk; /* appsock + sbuf */
TAILQ_ENTRY(sqlclntstate) lru_entry; /* libevent connections which can be closed */
TAILQ_ENTRY(sqlclntstate) sql_entry; /* all libevent connections */
int last_sent_row_sec; /* used to delay releasing locks when bdb_lock is desired */
int8_t rowbuffer;
/* 1 if client has requested flat column values. */
int flat_col_vals;
plugin_func *recover_ddlk;