~ubuntu-branches/debian/jessie/sysbench/jessie

« back to all changes in this revision

Viewing changes to sysbench/drivers/oracle/drv_oracle.c

  • Committer: Bazaar Package Importer
  • Author(s): Hendrik Frenzel
  • Date: 2009-02-23 00:32:52 UTC
  • Revision ID: james.westby@ubuntu.com-20090223003252-u6psmnqbivepsj0n
Tags: upstream-0.4.10
ImportĀ upstreamĀ versionĀ 0.4.10

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Copyright (C) 2005 MySQL AB
 
2
 
 
3
   This program is free software; you can redistribute it and/or modify
 
4
   it under the terms of the GNU General Public License as published by
 
5
   the Free Software Foundation; either version 2 of the License, or
 
6
   (at your option) any later version.
 
7
 
 
8
   This program is distributed in the hope that it will be useful,
 
9
   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
10
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
11
   GNU General Public License for more details.
 
12
 
 
13
   You should have received a copy of the GNU General Public License
 
14
   along with this program; if not, write to the Free Software
 
15
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
16
*/
 
17
 
 
18
#ifdef HAVE_CONFIG_H
 
19
# include "config.h"
 
20
#endif
 
21
 
 
22
#ifdef HAVE_STRING_H
 
23
# include <string.h>
 
24
#endif
 
25
#ifdef HAVE_STRINGS_H
 
26
# include <strings.h>
 
27
#endif
 
28
 
 
29
#include <oci.h>
 
30
 
 
31
#include "sb_options.h"
 
32
#include "db_driver.h"
 
33
 
 
34
 
 
35
/* Number of rows to prefetch for result sets */
 
36
#define ORA_DRV_PREFETCH_COUNT 1000
 
37
 
 
38
#define CHECKERR(stmt)                          \
 
39
  do { \
 
40
    if (rc != OCI_SUCCESS) \
 
41
    { \
 
42
      log_text(LOG_FATAL, "%s failed in %s:%d", stmt, __FILE__, __LINE__); \
 
43
      checkerr(ora_con->errhp, rc); \
 
44
      goto error; \
 
45
    } \
 
46
  } while(0);
 
47
 
 
48
static sb_arg_t ora_drv_args[] =
 
49
{
 
50
  {"oracle-user", "Oracle user", SB_ARG_TYPE_STRING, "sbtest"},
 
51
  {"oracle-password", "Oracle password", SB_ARG_TYPE_STRING, ""},
 
52
  {"oracle-db", "Oracle database name", SB_ARG_TYPE_STRING, "sbtest"},
 
53
  
 
54
  {NULL, NULL, SB_ARG_TYPE_NULL, NULL}
 
55
};
 
56
 
 
57
typedef struct
 
58
{
 
59
  OCISvcCtx  *svchp;
 
60
  OCIServer  *srvhp;
 
61
  OCIError   *errhp;
 
62
  OCITrans   *transhp;
 
63
  OCISession *usrhp;
 
64
} ora_conn_t;
 
65
 
 
66
typedef struct
 
67
{
 
68
  sb2 ind;
 
69
} ora_bind_t;
 
70
 
 
71
typedef enum
 
72
{
 
73
  STMT_TYPE_BEGIN,
 
74
  STMT_TYPE_COMMIT,
 
75
  STMT_TYPE_SELECT,
 
76
  STMT_TYPE_UPDATE
 
77
} ora_stmt_type_t;
 
78
 
 
79
typedef struct
 
80
{
 
81
  OCIStmt         *ptr;
 
82
  ora_stmt_type_t type;
 
83
  ora_bind_t      *params;
 
84
  ora_bind_t      *results;
 
85
} ora_stmt_t;
 
86
 
 
87
typedef struct
 
88
{
 
89
  ub2       type;
 
90
  text      *name;
 
91
  ub2       len;
 
92
  OCIDefine *defhp;
 
93
  void      *value;
 
94
  sb2       ind;
 
95
  
 
96
  sb_list_item_t listitem;
 
97
} ora_column_t;
 
98
 
 
99
typedef struct
 
100
{
 
101
  void *value;
 
102
  sb2  ind;
 
103
} ora_data_t;
 
104
 
 
105
typedef struct
 
106
{
 
107
  ora_data_t *data;
 
108
  sb_list_item_t listitem;
 
109
} ora_row_t;
 
110
 
 
111
typedef struct
 
112
{
 
113
  ub4       ncolumns;
 
114
  ub4       nrows;
 
115
  sb_list_t columns;
 
116
  sb_list_t rows;
 
117
} ora_result_set_t;
 
118
 
 
119
typedef struct
 
120
{
 
121
  char               *user;
 
122
  char               *password;
 
123
  char               *db;
 
124
} ora_drv_args_t;
 
125
 
 
126
/* Structure used for DB-to-Oracle bind types map */
 
127
 
 
128
typedef struct
 
129
{
 
130
  db_bind_type_t   db_type;
 
131
  ub2              ora_type;
 
132
  sb4              ora_len;
 
133
} db_oracle_bind_map_t;
 
134
 
 
135
/* DB-to-Oracle bind types map */
 
136
db_oracle_bind_map_t db_oracle_bind_map[] =
 
137
{
 
138
 
 
139
  {DB_TYPE_TINYINT,   SQLT_INT,       sizeof(char)},
 
140
  {DB_TYPE_SMALLINT,  SQLT_INT,       sizeof(short)},
 
141
  {DB_TYPE_INT,       SQLT_INT,       sizeof(int)} ,
 
142
  {DB_TYPE_BIGINT,    SQLT_INT,       sizeof(long long)},
 
143
  {DB_TYPE_FLOAT,     SQLT_FLT,       sizeof(float)},
 
144
  {DB_TYPE_DOUBLE,    SQLT_FLT,       sizeof(double)},
 
145
  {DB_TYPE_DATETIME,  SQLT_DATE,      sizeof(void *)},
 
146
  {DB_TYPE_TIMESTAMP, SQLT_TIMESTAMP, sizeof(void *)},
 
147
  {DB_TYPE_CHAR,      SQLT_AFC,       0},
 
148
  {DB_TYPE_VARCHAR,   SQLT_VCS,       0},
 
149
  {DB_TYPE_NONE,      0,              0}
 
150
};
 
151
 
 
152
/* Oracle driver capabilities */
 
153
 
 
154
static drv_caps_t ora_drv_caps =
 
155
{
 
156
  .multi_rows_insert = 0,
 
157
  .transactions = 1,
 
158
  .prepared_statements = 1,
 
159
  .needs_commit = 1,
 
160
  .table_options_str = NULL
 
161
};
 
162
 
 
163
 
 
164
static OCIEnv *ora_env; /* OCI environmental handle */
 
165
 
 
166
static ora_drv_args_t args;          /* driver args */
 
167
 
 
168
/* Oracle driver operations */
 
169
 
 
170
static int ora_drv_init(void);
 
171
static int ora_drv_describe(drv_caps_t *, const char *);
 
172
static int ora_drv_connect(db_conn_t *);
 
173
static int ora_drv_disconnect(db_conn_t *);
 
174
static int ora_drv_prepare(db_stmt_t *, const char *);
 
175
static int ora_drv_bind_param(db_stmt_t *, db_bind_t *, unsigned int);
 
176
static int ora_drv_bind_result(db_stmt_t *, db_bind_t *, unsigned int);
 
177
static int ora_drv_execute(db_stmt_t *, db_result_set_t *);
 
178
static int ora_drv_fetch(db_result_set_t *);
 
179
static int ora_drv_fetch_row(db_result_set_t *, db_row_t *);
 
180
static unsigned long long ora_drv_num_rows(db_result_set_t *);
 
181
static int ora_drv_query(db_conn_t *, const char *, db_result_set_t *);
 
182
static int ora_drv_free_results(db_result_set_t *);
 
183
static int ora_drv_close(db_stmt_t *);
 
184
static int ora_drv_store_results(db_result_set_t *);
 
185
static int ora_drv_done(void);
 
186
 
 
187
/* Oracle driver definition */
 
188
 
 
189
static db_driver_t oracle_driver =
 
190
{
 
191
  .sname = "oracle",
 
192
  .lname = "Oracle driver",
 
193
  .args = ora_drv_args,
 
194
  .ops =
 
195
  {
 
196
    ora_drv_init,
 
197
    ora_drv_describe,
 
198
    ora_drv_connect,
 
199
    ora_drv_disconnect,
 
200
    ora_drv_prepare,
 
201
    ora_drv_bind_param,
 
202
    ora_drv_bind_result,
 
203
    ora_drv_execute,
 
204
    ora_drv_fetch,
 
205
    ora_drv_fetch_row,
 
206
    ora_drv_num_rows,
 
207
    ora_drv_free_results,
 
208
    ora_drv_close,
 
209
    ora_drv_query,
 
210
    ora_drv_store_results,
 
211
    ora_drv_done
 
212
  },
 
213
  .listitem = {NULL, NULL}
 
214
};
 
215
 
 
216
 
 
217
/* Local functions */
 
218
 
 
219
static sword get_oracle_bind_type(db_bind_t *, ub2 *, sb4 *, sb2 *);
 
220
static sb4 get_oracle_type_size(sword);
 
221
static ora_stmt_type_t get_stmt_type(const char *);
 
222
static void checkerr(OCIError *, sword);
 
223
 
 
224
/* Register Oracle driver */
 
225
 
 
226
 
 
227
int register_driver_oracle(sb_list_t *drivers)
 
228
{
 
229
  SB_LIST_ADD_TAIL(&oracle_driver.listitem, drivers);
 
230
 
 
231
  return 0;
 
232
}
 
233
 
 
234
 
 
235
/* Oracle driver initialization */
 
236
 
 
237
 
 
238
int ora_drv_init(void)
 
239
{
 
240
  sword   rc;
 
241
 
 
242
  args.user = sb_get_value_string("oracle-user");
 
243
  args.password = sb_get_value_string("oracle-password");
 
244
  args.db = sb_get_value_string("oracle-db");
 
245
 
 
246
  /* Initialize the environment */
 
247
  rc = OCIEnvCreate(&ora_env, OCI_THREADED | OCI_OBJECT, NULL, NULL, NULL, NULL,
 
248
                    0, NULL);
 
249
  if (rc != OCI_SUCCESS || ora_env == NULL)
 
250
  {
 
251
    log_text(LOG_FATAL, "OCIEnvCreate failed!");
 
252
    return 1;
 
253
  }
 
254
  
 
255
  return 0;
 
256
}
 
257
 
 
258
 
 
259
/* Describe database capabilities  */
 
260
 
 
261
 
 
262
int ora_drv_describe(drv_caps_t *caps, const char * table_name)
 
263
{
 
264
  (void)table_name;
 
265
  *caps = ora_drv_caps;
 
266
  
 
267
  return 0;
 
268
}
 
269
 
 
270
 
 
271
/* Connect to the database */
 
272
 
 
273
 
 
274
int ora_drv_connect(db_conn_t *sb_conn)
 
275
{
 
276
  sword       rc;
 
277
  ora_conn_t *ora_con = NULL;
 
278
 
 
279
  ora_con = (ora_conn_t *)malloc(sizeof(ora_conn_t));
 
280
  if (ora_con == NULL)
 
281
    goto error;
 
282
  
 
283
  /* Allocate a service handle */
 
284
  rc = OCIHandleAlloc(ora_env, (dvoid **)&(ora_con->svchp), OCI_HTYPE_SVCCTX, 0,
 
285
                      (dvoid **)NULL);
 
286
  if (rc != OCI_SUCCESS)
 
287
  {
 
288
    log_text(LOG_FATAL, "OCIHandleAlloc (OCI_HTYPE_SVCCTX) failed");
 
289
    goto error;
 
290
  }
 
291
 
 
292
  /* Allocate an error handle */
 
293
  rc = OCIHandleAlloc(ora_env, (dvoid **)&(ora_con->errhp), OCI_HTYPE_ERROR, 0,
 
294
                      (dvoid **)NULL);
 
295
  if (rc != OCI_SUCCESS)
 
296
  {
 
297
    log_text(LOG_FATAL, "OCIHandleAlloc (OCI_HTYPE_ERROR) failed");
 
298
    goto error;
 
299
  }
 
300
 
 
301
  /* Allocate an server handle */
 
302
  rc = OCIHandleAlloc(ora_env, (dvoid **)&(ora_con->srvhp), OCI_HTYPE_SERVER, 0,
 
303
                      (dvoid **)NULL);
 
304
  CHECKERR("OCIHandleAlloc");
 
305
  
 
306
  /* Allocate a user session handle */
 
307
  rc = OCIHandleAlloc(ora_env, (dvoid **)&(ora_con->usrhp), OCI_HTYPE_SESSION, 0,
 
308
                      (dvoid **)NULL);
 
309
  CHECKERR("OCIHandleAlloc");
 
310
 
 
311
  /* Attach to the server */
 
312
  rc = OCIServerAttach(ora_con->srvhp, ora_con->errhp, args.db, strlen(args.db),
 
313
                       OCI_DEFAULT);
 
314
  CHECKERR("OCIServerAttach");
 
315
 
 
316
  /* Set the server attribute in the service context handler */
 
317
  rc = OCIAttrSet(ora_con->svchp, OCI_HTYPE_SVCCTX, ora_con->srvhp, 0,
 
318
                  OCI_ATTR_SERVER, ora_con->errhp);
 
319
  CHECKERR("OCIAttrSet");
 
320
 
 
321
  /* Set the user name attribute in the user session handler */
 
322
  rc = OCIAttrSet(ora_con->usrhp, OCI_HTYPE_SESSION, args.user,
 
323
                  strlen(args.user), OCI_ATTR_USERNAME, ora_con->errhp);
 
324
  CHECKERR("OCIAttrSet");
 
325
 
 
326
  /* Set the password attribute in the user session handler */
 
327
  rc = OCIAttrSet(ora_con->usrhp, OCI_HTYPE_SESSION, args.password,
 
328
                  strlen(args.password), OCI_ATTR_PASSWORD, ora_con->errhp);
 
329
  CHECKERR("OCIAttrSet");
 
330
 
 
331
  /* Allocate the transaction handle and set it to service context */
 
332
  rc = OCIHandleAlloc(ora_env, (dvoid **)&(ora_con->transhp), OCI_HTYPE_TRANS, 0,
 
333
                      (dvoid **)NULL);
 
334
  CHECKERR("OCIHandleAlloc");
 
335
  rc = OCIAttrSet(ora_con->svchp, OCI_HTYPE_SVCCTX, ora_con->transhp, 0,
 
336
                  OCI_ATTR_TRANS, ora_con->errhp);
 
337
  CHECKERR("OCIAttrSet");
 
338
    
 
339
  /* Start the session */
 
340
  rc = OCISessionBegin (ora_con->svchp, ora_con->errhp, ora_con->usrhp,
 
341
                        OCI_CRED_RDBMS, OCI_DEFAULT);
 
342
  CHECKERR("OCISessionBegin");
 
343
  
 
344
  /* Set the user session attribute in the service context handler */
 
345
  rc = OCIAttrSet(ora_con->svchp, OCI_HTYPE_SVCCTX, ora_con->usrhp, 0,
 
346
                  OCI_ATTR_SESSION, ora_con->errhp);
 
347
  CHECKERR("OCIAttrSet");
 
348
  
 
349
  sb_conn->ptr = ora_con;
 
350
  
 
351
  return 0;
 
352
 
 
353
 error:
 
354
  if (ora_con != NULL)
 
355
    free(ora_con);
 
356
  
 
357
  return 1;
 
358
}
 
359
 
 
360
 
 
361
/* Disconnect from database */
 
362
 
 
363
 
 
364
int ora_drv_disconnect(db_conn_t *sb_conn)
 
365
{
 
366
  ora_conn_t *con = sb_conn->ptr;
 
367
  sword       rc;
 
368
  int         res = 0;
 
369
  
 
370
  if (con == NULL)
 
371
    return 1;
 
372
 
 
373
  rc = OCISessionEnd(con->svchp, con->errhp, con->usrhp, 0);
 
374
  if (rc != OCI_SUCCESS)
 
375
  {
 
376
    log_text(LOG_FATAL, "OCISessionEnd failed");
 
377
    res = 1;
 
378
  }
 
379
 
 
380
  rc = OCIServerDetach(con->srvhp, con->errhp, OCI_DEFAULT);
 
381
  if (rc != OCI_SUCCESS)
 
382
  {
 
383
    log_text(LOG_FATAL, "OCIServerDetach failed");
 
384
    res = 1;
 
385
  }
 
386
 
 
387
  /* Free handles */
 
388
  
 
389
  if (OCIHandleFree(con->usrhp, OCI_HTYPE_SESSION) != OCI_SUCCESS)
 
390
    res = 1;
 
391
  if (OCIHandleFree(con->srvhp, OCI_HTYPE_SERVER) != OCI_SUCCESS)
 
392
    res = 1;
 
393
  if (OCIHandleFree(con->svchp, OCI_HTYPE_SVCCTX) != OCI_SUCCESS)
 
394
    res = 1;
 
395
  if (OCIHandleFree(con->errhp, OCI_HTYPE_ERROR) != OCI_SUCCESS)
 
396
    res = 1;
 
397
  
 
398
  free(con);
 
399
  
 
400
  return res;
 
401
}
 
402
 
 
403
 
 
404
/* Prepare statement */
 
405
 
 
406
 
 
407
int ora_drv_prepare(db_stmt_t *stmt, const char *query)
 
408
{
 
409
  ora_conn_t   *ora_con = (ora_conn_t *)stmt->connection->ptr;
 
410
  sword        rc;
 
411
  ora_stmt_t   *ora_stmt = NULL;
 
412
  char         *buf = NULL;
 
413
  unsigned int vcnt;
 
414
  unsigned int need_realloc;
 
415
  unsigned int i,j;
 
416
  unsigned int buflen;
 
417
  int          n;
 
418
  ub4          prefetch_cnt = ORA_DRV_PREFETCH_COUNT;
 
419
  
 
420
  if (ora_con == NULL)
 
421
    return 1;
 
422
 
 
423
  if (db_globals.ps_mode != DB_PS_MODE_DISABLE)
 
424
  {
 
425
    ora_stmt = (ora_stmt_t *)calloc(1, sizeof(ora_stmt_t));
 
426
    if (ora_stmt == NULL)
 
427
      goto error;
 
428
    
 
429
    rc = OCIHandleAlloc(ora_env, (dvoid **)&(ora_stmt->ptr), OCI_HTYPE_STMT, 0,
 
430
                        NULL);
 
431
    if (rc != OCI_SUCCESS)
 
432
      goto error;
 
433
 
 
434
    /* Convert query to Oracle-style named placeholders */
 
435
    need_realloc = 1;
 
436
    vcnt = 1;
 
437
    buflen = 0;
 
438
    for (i = 0, j = 0; query[i] != '\0'; i++)
 
439
    {
 
440
    again:
 
441
      if (j+1 >= buflen || need_realloc)
 
442
      {
 
443
        buflen = (buflen > 0) ? buflen * 2 : 256;
 
444
        buf = realloc(buf, buflen);
 
445
        if (buf == NULL)
 
446
          goto error;
 
447
        need_realloc = 0;
 
448
      }
 
449
 
 
450
      if (query[i] != '?')
 
451
      {
 
452
        buf[j++] = query[i];
 
453
        continue;
 
454
      }
 
455
 
 
456
      n = snprintf(buf + j, buflen - j, ":%d", vcnt);
 
457
      if (n < 0 || n >= (int)(buflen - j))
 
458
      {
 
459
        need_realloc = 1;
 
460
        goto again;
 
461
      }
 
462
 
 
463
      j += n;
 
464
      vcnt++;
 
465
    }
 
466
    buf[j] = '\0';
 
467
    
 
468
    ora_stmt->type = get_stmt_type(buf);
 
469
    
 
470
    if (ora_stmt->type != STMT_TYPE_BEGIN &&
 
471
        ora_stmt->type != STMT_TYPE_COMMIT)
 
472
    {
 
473
      rc = OCIStmtPrepare(ora_stmt->ptr, ora_con->errhp, buf, strlen(buf),
 
474
                          OCI_NTV_SYNTAX, OCI_DEFAULT);
 
475
      CHECKERR("OCIStmtPrepare");
 
476
 
 
477
      rc = OCIAttrSet(ora_stmt->ptr, OCI_HTYPE_STMT, &prefetch_cnt, 0,
 
478
                      OCI_ATTR_PREFETCH_ROWS, ora_con->errhp);
 
479
      CHECKERR("OCIAttrSet");
 
480
    }
 
481
    
 
482
    free(buf);
 
483
    
 
484
    stmt->ptr = (void *)ora_stmt;
 
485
  }
 
486
  else
 
487
  {
 
488
    /* Use client-side PS */
 
489
    stmt->emulated = 1;
 
490
  }
 
491
  stmt->query = strdup(query);
 
492
  
 
493
  return 0;
 
494
  
 
495
 error:
 
496
  if (ora_stmt != NULL)
 
497
  {
 
498
    if (ora_stmt->ptr != NULL)
 
499
      OCIHandleFree(ora_stmt->ptr, OCI_HTYPE_STMT);
 
500
 
 
501
    free(ora_stmt);
 
502
  }
 
503
  log_text(LOG_FATAL, "Failed to prepare statement: '%s'", query);
 
504
  
 
505
  return 1;
 
506
}
 
507
 
 
508
 
 
509
/* Bind parameters for prepared statement */
 
510
 
 
511
 
 
512
int ora_drv_bind_param(db_stmt_t *stmt, db_bind_t *params, unsigned int len)
 
513
{
 
514
  ora_conn_t  *con = (ora_conn_t *)stmt->connection->ptr;
 
515
  ora_stmt_t  *ora_stmt = (ora_stmt_t *)stmt->ptr;
 
516
  OCIBind *   bindp;
 
517
  unsigned int i;
 
518
  sword       rc;
 
519
  ub2         dtype;
 
520
  sb4         dlen;
 
521
  
 
522
  if (con == NULL)
 
523
    return 1;
 
524
 
 
525
  if (!stmt->emulated)
 
526
  {
 
527
    if (ora_stmt == NULL || ora_stmt->ptr == NULL)
 
528
      return 1;
 
529
 
 
530
    if (ora_stmt->params != NULL)
 
531
      free(ora_stmt->params);
 
532
    ora_stmt->params = (ora_bind_t *)malloc(len * sizeof(ora_bind_t));
 
533
    if (ora_stmt->params == NULL)
 
534
      return 1;
 
535
    
 
536
    /* Convert SysBench bind structures to Oracle ones */
 
537
    bindp = NULL;
 
538
    for (i = 0; i < len; i++)
 
539
    {
 
540
      if (get_oracle_bind_type(params+i, &dtype, &dlen,
 
541
                               &ora_stmt->params[i].ind))
 
542
      {
 
543
        free(ora_stmt->params);
 
544
        ora_stmt->params = NULL;
 
545
        return 1;
 
546
      }
 
547
      
 
548
      rc = OCIBindByPos(ora_stmt->ptr, &bindp, con->errhp, i+1, params[i].buffer,
 
549
                        dlen, dtype, (dvoid *)&ora_stmt->params[i].ind, NULL,
 
550
                        NULL, 0, NULL, OCI_DEFAULT);
 
551
      if (rc != OCI_SUCCESS)
 
552
      {
 
553
        log_text(LOG_FATAL, "OCIBindByPos failed");
 
554
        free(ora_stmt->params);
 
555
        ora_stmt->params = NULL;
 
556
        return 1;
 
557
      }
 
558
    }
 
559
 
 
560
    return 0;
 
561
  }
 
562
 
 
563
  /* Use emulation */
 
564
  if (stmt->bound_param != NULL)
 
565
    free(stmt->bound_param);
 
566
  stmt->bound_param = (db_bind_t *)malloc(len * sizeof(db_bind_t));
 
567
  if (stmt->bound_param == NULL)
 
568
    return 1;
 
569
  memcpy(stmt->bound_param, params, len * sizeof(db_bind_t));
 
570
  stmt->bound_param_len = len;
 
571
  
 
572
  return 0;
 
573
}
 
574
 
 
575
 
 
576
/* Bind results for prepared statement */
 
577
 
 
578
 
 
579
int ora_drv_bind_result(db_stmt_t *stmt, db_bind_t *params, unsigned int len)
 
580
{
 
581
  /* NYI */
 
582
 
 
583
  (void)stmt;
 
584
  (void)params;
 
585
  (void)len;
 
586
  
 
587
  return 1;
 
588
}
 
589
 
 
590
 
 
591
/* Execute prepared statement */
 
592
 
 
593
 
 
594
int ora_drv_execute(db_stmt_t *stmt, db_result_set_t *rs)
 
595
{
 
596
  db_conn_t       *db_con = stmt->connection;
 
597
  ora_stmt_t      *ora_stmt = stmt->ptr;
 
598
  ora_conn_t      *ora_con;
 
599
  ub4             iters;
 
600
  char            *buf = NULL;
 
601
  unsigned int    buflen = 0;
 
602
  unsigned int    i, j, vcnt;
 
603
  char            need_realloc;
 
604
  int             n;
 
605
  sword           rc;
 
606
  
 
607
  (void)rs; /* unused */
 
608
 
 
609
  if (db_con == NULL)
 
610
    return SB_DB_ERROR_FAILED;
 
611
  ora_con = db_con->ptr;
 
612
  if (ora_con == NULL)
 
613
    return SB_DB_ERROR_FAILED;
 
614
  
 
615
  if (!stmt->emulated)
 
616
  {
 
617
    if (stmt->ptr == NULL)
 
618
      return SB_DB_ERROR_FAILED;
 
619
 
 
620
    if (ora_stmt->type == STMT_TYPE_BEGIN)
 
621
    {
 
622
      rc = OCITransStart(ora_con->svchp, ora_con->errhp, 3600, OCI_TRANS_NEW);
 
623
      CHECKERR("OCITransStart");
 
624
 
 
625
      return SB_DB_ERROR_NONE;
 
626
    }
 
627
    else if (ora_stmt->type == STMT_TYPE_COMMIT)
 
628
    {
 
629
      rc = OCITransCommit(ora_con->svchp, ora_con->errhp, OCI_DEFAULT);
 
630
      CHECKERR("OCITransCommit");
 
631
 
 
632
      return SB_DB_ERROR_NONE;
 
633
    }
 
634
    else if (ora_stmt->type == STMT_TYPE_SELECT)
 
635
      iters = 0;
 
636
    else
 
637
      iters = 1;
 
638
  
 
639
    rc = OCIStmtExecute(ora_con->svchp, ora_stmt->ptr, ora_con->errhp, iters, 0,
 
640
                        NULL, NULL, OCI_DEFAULT);
 
641
    CHECKERR("OCIStmtExecute");
 
642
    
 
643
    return SB_DB_ERROR_NONE;
 
644
  }
 
645
 
 
646
  /* Build the actual query string from parameters list */
 
647
  need_realloc = 1;
 
648
  vcnt = 0;
 
649
  for (i = 0, j = 0; stmt->query[i] != '\0'; i++)
 
650
  {
 
651
  again:
 
652
    if (j+1 >= buflen || need_realloc)
 
653
    {
 
654
      buflen = (buflen > 0) ? buflen * 2 : 256;
 
655
      buf = realloc(buf, buflen);
 
656
      if (buf == NULL)
 
657
      {
 
658
        return SB_DB_ERROR_FAILED;
 
659
      }
 
660
      need_realloc = 0;
 
661
    }
 
662
 
 
663
    if (stmt->query[i] != '?')
 
664
    {
 
665
      buf[j++] = stmt->query[i];
 
666
      continue;
 
667
    }
 
668
 
 
669
    n = db_print_value(stmt->bound_param + vcnt, buf + j, buflen - j);
 
670
    if (n < 0)
 
671
    {
 
672
      need_realloc = 1;
 
673
      goto again;
 
674
    }
 
675
    j += n;
 
676
    vcnt++;
 
677
  }
 
678
  buf[j] = '\0';
 
679
  
 
680
  db_con->db_errno = ora_drv_query(db_con, buf, rs);
 
681
  free(buf);
 
682
 
 
683
  return SB_DB_ERROR_NONE;
 
684
 
 
685
 error:
 
686
  log_text(LOG_FATAL, "failed query was: '%s'", stmt->query);
 
687
  
 
688
  return SB_DB_ERROR_FAILED;
 
689
}
 
690
 
 
691
 
 
692
/* Execute SQL query */
 
693
 
 
694
 
 
695
int ora_drv_query(db_conn_t *sb_conn, const char *query,
 
696
                      db_result_set_t *rs)
 
697
{
 
698
  ora_conn_t      *ora_con = sb_conn->ptr;
 
699
  sword           rc = 0;
 
700
  void            *tmp = NULL;
 
701
  ub4             iters;
 
702
  ora_stmt_type_t type;
 
703
  OCIStmt         *stmt = NULL;
 
704
 
 
705
  (void)rs; /* unused */
 
706
 
 
707
  type = get_stmt_type(query);
 
708
 
 
709
  if (type == STMT_TYPE_BEGIN)
 
710
  {
 
711
    rc = OCITransStart(ora_con->svchp, ora_con->errhp, 3600, OCI_TRANS_NEW);
 
712
    CHECKERR("OCITransStart");
 
713
 
 
714
    return SB_DB_ERROR_NONE;
 
715
  }
 
716
  else if (type == STMT_TYPE_COMMIT)
 
717
  {
 
718
    rc = OCITransCommit(ora_con->svchp, ora_con->errhp, OCI_DEFAULT);
 
719
    CHECKERR("OCITransCommit");
 
720
 
 
721
    return SB_DB_ERROR_NONE;
 
722
  }
 
723
  else if (type == STMT_TYPE_SELECT)
 
724
    iters = 0;
 
725
  else
 
726
    iters = 1;
 
727
  
 
728
  rc = OCIHandleAlloc(ora_env, (dvoid **)&tmp, OCI_HTYPE_STMT, 0, (dvoid **)NULL);
 
729
  CHECKERR("OCIHandleAlloc");
 
730
 
 
731
  stmt = (OCIStmt *)tmp;
 
732
  
 
733
  rc = OCIStmtPrepare(stmt, ora_con->errhp, (OraText *)query, strlen(query),
 
734
                      OCI_NTV_SYNTAX, OCI_DEFAULT);
 
735
  CHECKERR("OCIStmtPrepare");
 
736
 
 
737
  rc = OCIStmtExecute(ora_con->svchp, stmt, ora_con->errhp, iters, 0, NULL, NULL,
 
738
                      OCI_DEFAULT);
 
739
  CHECKERR("OCIStmtExecute");
 
740
 
 
741
  OCIHandleFree(stmt, OCI_HTYPE_STMT);
 
742
 
 
743
  return SB_DB_ERROR_NONE;
 
744
 
 
745
 error:
 
746
  log_text(LOG_FATAL, "failed query was: '%s'", query);
 
747
  if (stmt != NULL)
 
748
    OCIHandleFree(stmt, OCI_HTYPE_STMT);
 
749
  
 
750
  return SB_DB_ERROR_FAILED;
 
751
}
 
752
 
 
753
 
 
754
/* Fetch row from result set of a prepared statement */
 
755
 
 
756
 
 
757
int ora_drv_fetch(db_result_set_t *rs)
 
758
{
 
759
  /* NYI */
 
760
  (void)rs;
 
761
 
 
762
  return 1;
 
763
}
 
764
 
 
765
 
 
766
/* Fetch row from result set of a query */
 
767
 
 
768
 
 
769
int ora_drv_fetch_row(db_result_set_t *rs, db_row_t *row)
 
770
{
 
771
  /* NYI */
 
772
  (void)rs;  /* unused */
 
773
  (void)row; /* unused */
 
774
  
 
775
  return 1;
 
776
}
 
777
 
 
778
 
 
779
/* Return the number of rows in a result set */
 
780
 
 
781
 
 
782
unsigned long long ora_drv_num_rows(db_result_set_t *rs)
 
783
{
 
784
  ora_result_set_t *ora_rs = (ora_result_set_t *)rs->ptr;
 
785
  
 
786
  /* Check if the results are already fetched */
 
787
  if (ora_rs != NULL)
 
788
    return ora_rs->nrows;
 
789
 
 
790
  return 0;
 
791
}
 
792
 
 
793
 
 
794
/* Store results from the last query */
 
795
 
 
796
 
 
797
int ora_drv_store_results(db_result_set_t *rs)
 
798
{
 
799
  unsigned int     i;
 
800
  sword            rc;
 
801
  db_stmt_t        *db_stmt = rs->statement;
 
802
  db_conn_t        *db_conn = rs->connection;
 
803
  ora_stmt_t       *ora_stmt;
 
804
  ora_conn_t       *ora_con;
 
805
  ora_result_set_t *ora_rs;
 
806
  ora_column_t     *column;
 
807
  ora_row_t        *row;
 
808
  OCIParam         *parm;
 
809
  void             *tmp = NULL;
 
810
  unsigned int     col_len;
 
811
  ub4              semantics;
 
812
  sb_list_item_t   *pos;
 
813
  text             *fnamep;
 
814
  
 
815
  if (db_stmt == NULL || db_conn == NULL)
 
816
    return 1;
 
817
  
 
818
  ora_stmt = (ora_stmt_t *)db_stmt->ptr;
 
819
  ora_con = (ora_conn_t *)db_conn->ptr;
 
820
  if (ora_stmt == NULL || ora_con == NULL)
 
821
    return 1;
 
822
 
 
823
  if (rs->ptr != NULL)
 
824
    return 1;
 
825
  ora_rs = (ora_result_set_t *)calloc(1, sizeof(ora_result_set_t));
 
826
  if (ora_rs == NULL)
 
827
    return 1;
 
828
  rs->ptr = ora_rs;
 
829
  SB_LIST_INIT(&ora_rs->columns);
 
830
  SB_LIST_INIT(&ora_rs->rows);
 
831
 
 
832
  i = 1;
 
833
  rc = OCIParamGet((dvoid *)ora_stmt->ptr, OCI_HTYPE_STMT, ora_con->errhp, 
 
834
                   (dvoid **)&tmp, i);
 
835
  parm = (OCIParam *)tmp;
 
836
 
 
837
  /* Loop to get description of all columns */
 
838
  while (rc == OCI_SUCCESS)
 
839
  {
 
840
    column = (ora_column_t *)calloc(1, sizeof(ora_column_t));
 
841
    if (column == NULL)
 
842
      goto error;
 
843
    SB_LIST_ADD_TAIL(&column->listitem, &ora_rs->columns);
 
844
 
 
845
    /* Get the column type attribute */
 
846
    rc = OCIAttrGet((dvoid *)parm, OCI_DTYPE_PARAM, (dvoid *)&column->type,
 
847
                    NULL, OCI_ATTR_DATA_TYPE, ora_con->errhp);
 
848
    CHECKERR("OCIAttrGet");
 
849
 
 
850
    /* Get the column name attribute */
 
851
    rc = OCIAttrGet((dvoid *)parm, OCI_DTYPE_PARAM, &fnamep,
 
852
                    (ub4 *)&col_len, OCI_ATTR_NAME, ora_con->errhp);
 
853
    CHECKERR("OCIAttrGet");
 
854
    column->name = (char *)malloc(col_len + 1);
 
855
    if (column->name == NULL)
 
856
      goto error;
 
857
    strncpy(column->name, fnamep, col_len + 1);
 
858
    
 
859
 
 
860
    /* Get the length semantics */
 
861
    rc = OCIAttrGet((dvoid *)parm, OCI_DTYPE_PARAM, (dvoid *)&semantics,
 
862
                    NULL, OCI_ATTR_CHAR_USED, ora_con->errhp);
 
863
    CHECKERR("OCIAttrGet");
 
864
 
 
865
    if (semantics)
 
866
    {
 
867
      /* Get the column width in characters */
 
868
      rc = OCIAttrGet((dvoid *)parm, OCI_DTYPE_PARAM, (dvoid *)&column->len,
 
869
                      NULL, OCI_ATTR_CHAR_SIZE, ora_con->errhp);
 
870
      if (column->len == 0)
 
871
        column->len = get_oracle_type_size(column->type);
 
872
    }
 
873
    else
 
874
    {
 
875
      /* Get the column width in bytes */
 
876
      rc = OCIAttrGet((dvoid *)parm, OCI_DTYPE_PARAM, (dvoid *)&column->len,
 
877
                      NULL, OCI_ATTR_DATA_SIZE, ora_con->errhp);
 
878
      if (column->len == 0)
 
879
        column->len = get_oracle_type_size(column->type);
 
880
    }
 
881
    CHECKERR("OCIAttrGet");
 
882
 
 
883
    OCIDescriptorFree(parm, OCI_DTYPE_PARAM);
 
884
    
 
885
    /* Describe the column */
 
886
    column->value = malloc(column->len);
 
887
    if (column->value == NULL)
 
888
      goto error;
 
889
    rc = OCIDefineByPos(ora_stmt->ptr, &column->defhp, ora_con->errhp, i,
 
890
                        column->value, column->len, column->type, &column->ind,
 
891
                        NULL, NULL, OCI_DEFAULT);
 
892
    CHECKERR("OCIDefineByPos");
 
893
                        
 
894
    i++;
 
895
    rc = OCIParamGet(ora_stmt->ptr, OCI_HTYPE_STMT, ora_con->errhp,
 
896
                     (dvoid **)&tmp, i);
 
897
    parm = (OCIParam *)tmp;
 
898
  }
 
899
  ora_rs->ncolumns = i-1;
 
900
  
 
901
  /* Now fetch the actual data */
 
902
  while(1)
 
903
  {
 
904
    rc = OCIStmtFetch2(ora_stmt->ptr, ora_con->errhp, 1, OCI_FETCH_NEXT, 0,
 
905
                      OCI_DEFAULT);
 
906
    if (rc == OCI_NO_DATA)
 
907
      break;
 
908
    CHECKERR("OCIStmtFetch");
 
909
    
 
910
    row = (ora_row_t *)calloc(1, sizeof(ora_row_t));
 
911
    if (row == NULL)
 
912
      goto error;
 
913
    row->data = (ora_data_t *)calloc(ora_rs->ncolumns, sizeof(ora_data_t));
 
914
    i = 0;
 
915
    SB_LIST_FOR_EACH(pos, &ora_rs->columns)
 
916
    {
 
917
      column = SB_LIST_ENTRY(pos, ora_column_t, listitem);
 
918
      row->data[i].value = (void *)malloc(column->len);
 
919
      if (row->data[i].value == NULL)
 
920
        goto error;
 
921
      memcpy(row->data[i].value, column->value, column->len);
 
922
      row->data[i].ind = column->ind;
 
923
      i++;
 
924
    }
 
925
    SB_LIST_ADD_TAIL(&row->listitem, &ora_rs->rows);
 
926
    ora_rs->nrows++;
 
927
  }
 
928
  
 
929
  return 0;
 
930
  
 
931
 error:
 
932
  
 
933
  return 1;
 
934
}
 
935
 
 
936
 
 
937
/* Free result set */
 
938
 
 
939
 
 
940
int ora_drv_free_results(db_result_set_t *rs)
 
941
{
 
942
  ora_result_set_t *ora_rs = (ora_result_set_t *)rs->ptr;
 
943
  ora_row_t        *row;
 
944
  ora_column_t     *column;
 
945
  sb_list_item_t   *cur;
 
946
  sb_list_item_t   *next;
 
947
  unsigned int     i;
 
948
  
 
949
  if (ora_rs == NULL)
 
950
    return 1;
 
951
  
 
952
  SB_LIST_FOR_EACH_SAFE(cur, next, &ora_rs->rows)
 
953
  {
 
954
    row = SB_LIST_ENTRY(cur, ora_row_t, listitem);
 
955
 
 
956
    if (row->data != NULL)
 
957
    {
 
958
      for (i = 0; i < ora_rs->ncolumns; i++)
 
959
      {
 
960
        if (row->data[i].value != NULL)
 
961
          free(row->data[i].value);
 
962
      }
 
963
      free(row->data);
 
964
    }
 
965
 
 
966
    SB_LIST_DELETE(cur);
 
967
    free(row);
 
968
  }
 
969
  
 
970
  SB_LIST_FOR_EACH_SAFE(cur, next, &ora_rs->columns)
 
971
  {
 
972
    column = SB_LIST_ENTRY(cur, ora_column_t, listitem);
 
973
 
 
974
    if (column->name != NULL)
 
975
      free(column->name);
 
976
    if (column->value != NULL)
 
977
      free(column->value);
 
978
      
 
979
    SB_LIST_DELETE(cur);
 
980
    free(column);
 
981
  }
 
982
 
 
983
  free(ora_rs);
 
984
  
 
985
  return 0;
 
986
}
 
987
 
 
988
 
 
989
/* Close prepared statement */
 
990
 
 
991
 
 
992
int ora_drv_close(db_stmt_t *stmt)
 
993
{
 
994
  ora_stmt_t *ora_stmt = stmt->ptr;
 
995
 
 
996
  if (ora_stmt == NULL)
 
997
    return 1;
 
998
  OCIHandleFree(stmt, OCI_HTYPE_STMT);
 
999
 
 
1000
  return 0;
 
1001
}
 
1002
 
 
1003
 
 
1004
/* Uninitialize driver */
 
1005
 
 
1006
 
 
1007
int ora_drv_done(void)
 
1008
{
 
1009
  sword rc;
 
1010
 
 
1011
  if (ora_env == NULL)
 
1012
    return 1;
 
1013
 
 
1014
  rc = OCIHandleFree(ora_env, OCI_HTYPE_ENV);
 
1015
  if (rc != OCI_SUCCESS)
 
1016
  {
 
1017
    log_text(LOG_FATAL, "OCIHandleFree failed");
 
1018
    return 1;
 
1019
  }
 
1020
 
 
1021
  return 0;
 
1022
}
 
1023
 
 
1024
 
 
1025
/* Get Oracle type, type length and indicator values from SysBench parameter */
 
1026
 
 
1027
sword get_oracle_bind_type(db_bind_t *param, ub2 *type, sb4 *len,
 
1028
                           sb2 *ind)
 
1029
{
 
1030
  unsigned int i;
 
1031
 
 
1032
  for (i = 0; db_oracle_bind_map[i].db_type != DB_TYPE_NONE; i++)
 
1033
    if (db_oracle_bind_map[i].db_type == param->type)
 
1034
    {
 
1035
      *type = db_oracle_bind_map[i].ora_type;
 
1036
      *len = db_oracle_bind_map[i].ora_len;
 
1037
      if (param->type == DB_TYPE_CHAR || param->type == DB_TYPE_VARCHAR)
 
1038
        *len = strlen(param->buffer);
 
1039
      *ind = (param->is_null) ? -1 : 0;
 
1040
      
 
1041
      return 0;
 
1042
    }
 
1043
 
 
1044
  return 1;
 
1045
}
 
1046
 
 
1047
 
 
1048
/* Get Oracle type size in bytes */
 
1049
 
 
1050
 
 
1051
sb4 get_oracle_type_size(sword type)
 
1052
{
 
1053
  unsigned int i;
 
1054
  sb4          size = 0;
 
1055
 
 
1056
  if (type == SQLT_NUM)
 
1057
    return 21;
 
1058
  
 
1059
  for (i = 0; db_oracle_bind_map[i].db_type != DB_TYPE_NONE; i++)
 
1060
    if (db_oracle_bind_map[i].ora_type == type &&
 
1061
        size < db_oracle_bind_map[i].ora_len)
 
1062
      size = db_oracle_bind_map[i].ora_len;
 
1063
 
 
1064
  return size;
 
1065
}
 
1066
 
 
1067
ora_stmt_type_t get_stmt_type(const char *query)
 
1068
{
 
1069
    if (!strncmp(query, "BEGIN", 5))
 
1070
      return STMT_TYPE_BEGIN;
 
1071
    else if (!strncmp(query, "COMMIT", 6))
 
1072
      return STMT_TYPE_COMMIT;
 
1073
    else if (!strncmp(query, "SELECT", 6))
 
1074
      return STMT_TYPE_SELECT;
 
1075
 
 
1076
    return STMT_TYPE_UPDATE;
 
1077
}
 
1078
 
 
1079
db_bind_type_t get_db_bind_type(sword type)
 
1080
{
 
1081
  unsigned int i;
 
1082
 
 
1083
  for (i = 0; db_oracle_bind_map[i].db_type != DB_TYPE_NONE; i++)
 
1084
    if (db_oracle_bind_map[i].ora_type == type)
 
1085
      return db_oracle_bind_map[i].db_type;
 
1086
 
 
1087
  return DB_TYPE_NONE;
 
1088
}
 
1089
 
 
1090
 
 
1091
/* Check and display Oracle error */
 
1092
 
 
1093
 
 
1094
void checkerr(OCIError *errhp, sword status)
 
1095
{
 
1096
  text errbuf[512];
 
1097
  sword errcode;
 
1098
 
 
1099
  switch (status)
 
1100
  {
 
1101
    case OCI_SUCCESS:
 
1102
      break;
 
1103
    case OCI_SUCCESS_WITH_INFO:
 
1104
      log_text(LOG_ALERT, "Error - OCI_SUCCESS_WITH_INFO");
 
1105
      break;
 
1106
    case OCI_NEED_DATA:
 
1107
      log_text(LOG_ALERT, "Error - OCI_NEED_DATA");
 
1108
      break;
 
1109
    case OCI_NO_DATA:
 
1110
      log_text(LOG_ALERT, "Error - OCI_NO_DATA");
 
1111
      break;
 
1112
    case OCI_ERROR:
 
1113
      OCIErrorGet((dvoid *) errhp, (ub4) 1,
 
1114
                  (text *) NULL, (sb4 *) &errcode,
 
1115
                  errbuf, (ub4) sizeof(errbuf),
 
1116
                  (ub4) OCI_HTYPE_ERROR);
 
1117
      log_text(LOG_ALERT, "Error - %s", errbuf);
 
1118
      break;
 
1119
    case OCI_INVALID_HANDLE:
 
1120
      log_text(LOG_ALERT, "Error - OCI_INVALID_HANDLE");
 
1121
      break;
 
1122
    case OCI_STILL_EXECUTING:
 
1123
      log_text(LOG_ALERT, "Error - OCI_STILL_EXECUTE");
 
1124
      break;
 
1125
    case OCI_CONTINUE:
 
1126
      log_text(LOG_ALERT, "Error - OCI_CONTINUE");
 
1127
      break;
 
1128
    default:
 
1129
      break;
 
1130
  }
 
1131
}