1 /* Copyright (C) 2004 MySQL AB
2    Copyright (C) 2004-2017 Alexey Kopytov <akopytov@gmail.com>
3 
4    This program is free software; you can redistribute it and/or modify
5    it under the terms of the GNU General Public License as published by
6    the Free Software Foundation; either version 2 of the License, or
7    (at your option) any later version.
8 
9    This program is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12    GNU General Public License for more details.
13 
14    You should have received a copy of the GNU General Public License
15    along with this program; if not, write to the Free Software
16    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17 */
18 
19 #ifndef DB_DRIVER_H
20 #define DB_DRIVER_H
21 
22 #ifdef HAVE_CONFIG_H
23 # include "config.h"
24 #endif
25 
26 #include "sysbench.h"
27 #include "sb_list.h"
28 #include "sb_histogram.h"
29 #include "sb_counter.h"
30 
31 /* Prepared statements usage modes */
32 
33 typedef enum
34 {
35   DB_PS_MODE_AUTO,
36   DB_PS_MODE_DISABLE,
37 } db_ps_mode_t;
38 
39 /* Global DB API options */
40 
41 typedef struct
42 {
43   db_ps_mode_t  ps_mode;   /* Requested prepared statements usage mode */
44   char          *driver;   /* Requested database driver */
45   unsigned char debug;     /* debug flag */
46 } db_globals_t;
47 
48 /* Driver capabilities definition */
49 
50 typedef struct
51 {
52   char     multi_rows_insert;   /* 1 if database supports multi-row inserts */
53   char     prepared_statements; /* 1 if database supports prepared statements */
54   char     auto_increment;      /* 1 if database supports AUTO_INCREMENT clause */
55   char     needs_commit;        /* 1 if database needs explicit commit after INSERTs */
56   char     serial;              /* 1 if database supports SERIAL clause */
57   char     unsigned_int;        /* 1 if database supports UNSIGNED INTEGER types */
58 } drv_caps_t;
59 
60 /* Database errors definition */
61 
62 typedef enum
63 {
64   DB_ERROR_NONE,                /* no error(s) */
65   DB_ERROR_IGNORABLE,           /* error should be ignored as defined by command
66                                 line arguments or a custom error handler */
67   DB_ERROR_FATAL                /* non-ignorable error */
68 } db_error_t;
69 
70 
71 /* Available buffer types (for parameters binding) */
72 
73 typedef enum
74 {
75   DB_TYPE_NONE,
76   DB_TYPE_TINYINT,
77   DB_TYPE_SMALLINT,
78   DB_TYPE_INT,
79   DB_TYPE_BIGINT,
80   DB_TYPE_FLOAT,
81   DB_TYPE_DOUBLE,
82   DB_TYPE_TIME,
83   DB_TYPE_DATE,
84   DB_TYPE_DATETIME,
85   DB_TYPE_TIMESTAMP,
86   DB_TYPE_CHAR,
87   DB_TYPE_VARCHAR
88 } db_bind_type_t;
89 
90 
91 /* Structure used to represent DATE, TIME, DATETIME and TIMESTAMP values */
92 
93 typedef struct
94 {
95   unsigned int year;
96   unsigned int month;
97   unsigned int day;
98   unsigned int hour;
99   unsigned int minute;
100   unsigned int second;
101 } db_time_t;
102 
103 
104 /* Structure used to bind data for prepared statements */
105 
106 typedef struct
107 {
108   db_bind_type_t   type;
109   void             *buffer;
110   unsigned long    *data_len;
111   unsigned long    max_len;
112   char             *is_null;
113 } db_bind_t;
114 
115 /* Forward declarations */
116 
117 struct db_conn;
118 struct db_stmt;
119 struct db_result;
120 struct db_row;
121 
122 /* Driver operations definition */
123 
124 typedef int drv_op_init(void);
125 typedef int drv_op_thread_init(int);
126 typedef int drv_op_describe(drv_caps_t *);
127 typedef int drv_op_connect(struct db_conn *);
128 typedef int drv_op_reconnect(struct db_conn *);
129 typedef int drv_op_disconnect(struct db_conn *);
130 typedef int drv_op_prepare(struct db_stmt *, const char *, size_t);
131 typedef int drv_op_bind_param(struct db_stmt *, db_bind_t *, size_t);
132 typedef int drv_op_bind_result(struct db_stmt *, db_bind_t *, size_t);
133 typedef db_error_t drv_op_execute(struct db_stmt *, struct db_result *);
134 typedef int drv_op_fetch(struct db_result *);
135 typedef int drv_op_fetch_row(struct db_result *, struct db_row *);
136 typedef db_error_t drv_op_query(struct db_conn *, const char *, size_t,
137                                 struct db_result *);
138 typedef int drv_op_free_results(struct db_result *);
139 typedef int drv_op_close(struct db_stmt *);
140 typedef int drv_op_thread_done(int);
141 typedef int drv_op_done(void);
142 
143 typedef struct
144 {
145   drv_op_init            *init;           /* initializate driver */
146   drv_op_thread_init     *thread_init;    /* thread-local driver initialization */
147   drv_op_describe        *describe;       /* describe database capabilities */
148   drv_op_connect         *connect;        /* connect to database */
149   drv_op_disconnect      *disconnect;     /* disconnect from database */
150   drv_op_reconnect       *reconnect;      /* reconnect with the same parameters */
151   drv_op_prepare         *prepare;        /* prepare statement */
152   drv_op_bind_param      *bind_param;     /* bind params for prepared statement */
153   drv_op_bind_result     *bind_result;    /* bind results for prepared statement */
154   drv_op_execute         *execute;        /* execute prepared statement */
155   drv_op_fetch           *fetch;          /* fetch row for prepared statement */
156   drv_op_fetch_row       *fetch_row;      /* fetch row for queries */
157   drv_op_free_results    *free_results;   /* free result set */
158   drv_op_close           *close;          /* close prepared statement */
159   drv_op_query           *query;          /* execute non-prepared statement */
160   drv_op_thread_done     *thread_done;    /* thread-local driver deinitialization */
161   drv_op_done            *done;           /* uninitialize driver */
162 } drv_ops_t;
163 
164 /* Database driver definition */
165 
166 typedef struct
167 {
168   const char      *sname;   /* short name */
169   const char      *lname;   /* long name */
170   sb_arg_t        *args;    /* driver command line arguments */
171   drv_ops_t       ops;      /* driver operations */
172 
173   sb_list_item_t  listitem; /* can be linked in a list */
174   bool            initialized;
175   pthread_mutex_t mutex;
176 } db_driver_t;
177 
178 /* Row value definition */
179 
180 typedef struct {
181   uint32_t        len;         /* Value length */
182   const char      *ptr;        /* Value string */
183 } db_value_t;
184 
185 /* Result set row definition */
186 
187 typedef struct db_row
188 {
189   void            *ptr;        /* Driver-specific row data */
190   db_value_t      *values;     /* Array of column values */
191 } db_row_t;
192 
193 /* Result set definition */
194 
195 typedef struct db_result
196 {
197   sb_counter_type_t counter;     /* Statistical counter type */
198   uint32_t       nrows;         /* Number of affected rows */
199   uint32_t       nfields;       /* Number of fields */
200   struct db_stmt *statement;    /* Pointer to prepared statement (if used) */
201   void           *ptr;          /* Pointer to driver-specific data */
202   db_row_t       row;           /* Last fetched row */
203 } db_result_t;
204 
205 typedef enum {
206   DB_CONN_READY,
207   DB_CONN_RESULT_SET,
208   DB_CONN_INVALID
209 } db_conn_state_t;
210 
211 /* Database connection structure */
212 
213 typedef struct db_conn
214 {
215   db_error_t      error;             /* Database-independent error code */
216   int             sql_errno;         /* Database-specific error code */
217   const char      *sql_state;        /* Database-specific SQL state */
218   const char      *sql_errmsg;       /* Database-specific error message */
219   db_driver_t     *driver;           /* DB driver for this connection */
220   void            *ptr;              /* Driver-specific data */
221   db_result_t     rs;                /* Result set */
222   db_conn_state_t state;             /* Connection state */
223   int             thread_id;         /* Thread this connection belongs to */
224 
225   unsigned int    bulk_cnt;          /* Current number of rows in bulk insert buffer */
226   unsigned int    bulk_buflen;       /* Current length of bulk_buffer */
227   char            *bulk_buffer;      /* Bulk insert query buffer */
228   unsigned int    bulk_ptr;          /* Current position in bulk_buffer */
229   unsigned int    bulk_values;       /* Save value of bulk_ptr */
230   unsigned int    bulk_commit_cnt;   /* Current value of uncommitted rows */
231   unsigned int    bulk_commit_max;   /* Maximum value of uncommitted rows */
232 
233   char            pad[SB_CACHELINE_PAD(sizeof(db_error_t) +
234                                        sizeof(int) +
235                                        sizeof(void *) +
236                                        sizeof(void *) +
237                                        sizeof(void *) +
238                                        sizeof(void *) +
239                                        sizeof(db_result_t) +
240                                        sizeof(db_conn_state_t) +
241                                        sizeof(int) +
242                                        sizeof(int) * 2 +
243                                        sizeof(void *) +
244                                        sizeof(int) * 4
245                                        )];
246 } db_conn_t;
247 
248 /* Prepared statement definition */
249 
250 typedef struct db_stmt
251 {
252   db_conn_t       *connection;     /* Connection which this statement belongs to */
253   char            *query;          /* Query string for emulated PS */
254   db_bind_t       *bound_param;    /* Array of bound parameters for emulated PS */
255   unsigned int    bound_param_len; /* Length of the bound_param array */
256   db_bind_t       *bound_res;      /* Array of bound results for emulated PS */
257   db_bind_t       *bound_res_len;  /* Length of the bound_res array */
258   char            emulated;        /* Should this statement be emulated? */
259   sb_counter_type_t  counter;       /* Query type */
260   void            *ptr;            /* Pointer to driver-specific data structure */
261 } db_stmt_t;
262 
263 extern db_globals_t db_globals;
264 
265 /* Database abstraction layer calls */
266 
267 int db_register(void);
268 
269 void db_print_help(void);
270 
271 db_driver_t *db_create(const char *);
272 
273 int db_destroy(db_driver_t *);
274 
275 int db_describe(db_driver_t *, drv_caps_t *);
276 
277 db_conn_t *db_connection_create(db_driver_t *);
278 
279 int db_connection_close(db_conn_t *);
280 
281 int db_connection_reconnect(db_conn_t *con);
282 
283 void db_connection_free(db_conn_t *con);
284 
285 db_stmt_t *db_prepare(db_conn_t *, const char *, size_t);
286 
287 int db_bind_param(db_stmt_t *, db_bind_t *, size_t);
288 
289 int db_bind_result(db_stmt_t *, db_bind_t *, size_t);
290 
291 db_result_t *db_execute(db_stmt_t *);
292 
293 db_row_t *db_fetch_row(db_result_t *);
294 
295 db_result_t *db_query(db_conn_t *, const char *, size_t len);
296 
297 int db_free_results(db_result_t *);
298 
299 int db_store_results(db_result_t *);
300 
301 int db_close(db_stmt_t *);
302 
303 void db_done(void);
304 
305 int db_print_value(db_bind_t *, char *, int);
306 
307 /* Initialize multi-row insert operation */
308 int db_bulk_insert_init(db_conn_t *, const char *, size_t);
309 
310 /* Add row to multi-row insert operation */
311 int db_bulk_insert_next(db_conn_t *, const char *, size_t);
312 
313 /* Finish multi-row insert operation */
314 int db_bulk_insert_done(db_conn_t *);
315 
316 /* Print database-specific test stats */
317 void db_report_intermediate(sb_stat_t *);
318 void db_report_cumulative(sb_stat_t *);
319 
320 /* DB drivers registrars */
321 
322 #ifdef USE_MYSQL
323 int register_driver_mysql(sb_list_t *);
324 #endif
325 
326 #ifdef USE_DRIZZLE
327 int register_driver_drizzle(sb_list_t *);
328 #endif
329 
330 #ifdef USE_ATTACHSQL
331 int register_driver_attachsql(sb_list_t *);
332 #endif
333 
334 #ifdef USE_DRIZZLECLIENT
335 int register_driver_drizzleclient(sb_list_t *);
336 #endif
337 
338 #ifdef USE_ORACLE
339 int register_driver_oracle(sb_list_t *);
340 #endif
341 
342 #ifdef USE_PGSQL
343 int register_driver_pgsql(sb_list_t *);
344 #endif
345 
346 #endif /* DB_DRIVER_H */
347