00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include <stdio.h>
00026 #include <string.h>
00027 #include <stdlib.h>
00028 #include <time.h>
00029 #include <oci.h>
00030 #include "../../mem/mem.h"
00031 #include "../../dprint.h"
00032 #include "../../db/db_pool.h"
00033 #include "../../db/db_ut.h"
00034 #include "../../db/db_res.h"
00035 #include "../../db/db_query.h"
00036 #include "val.h"
00037 #include "ora_con.h"
00038 #include "res.h"
00039 #include "asynch.h"
00040 #include "dbase.h"
00041
00042
00043 #define MAX_BIND_HANDLES 128
00044
00045 char st_buf[STATIC_BUF_LEN];
00046
00047
00048
00049
00050
00051 int sql_buf_small(void)
00052 {
00053 LM_ERR("static buffer too small\n");
00054 return -11;
00055 }
00056
00057
00058
00059
00060 static char errbuf[512];
00061
00062 static const char* db_oracle_errorinfo(ora_con_t* con)
00063 {
00064 sword errcd;
00065 if (OCIErrorGet(con->errhp, 1, NULL, &errcd,
00066 (OraText*)errbuf, sizeof(errbuf),
00067 OCI_HTYPE_ERROR) != OCI_SUCCESS) errbuf[0] = '\0';
00068 else switch (errcd) {
00069 case 28:
00070 case 30:
00071 case 31:
00072 case 41:
00073 case 107:
00074 case 115:
00075 case 1033:
00076 case 1034:
00077 case 1089:
00078 case 1090:
00079 case 1092:
00080 case 1573:
00081 case 2049:
00082 case 3113:
00083 case 3114:
00084 case 3135:
00085 case 6033:
00086 case 6034:
00087 case 6037:
00088 case 6039:
00089 case 6042:
00090 case 6043:
00091 case 6107:
00092 case 6108:
00093 case 6109:
00094 case 6110:
00095 case 6114:
00096 case 6124:
00097 case 6135:
00098 case 6144:
00099 case 6413:
00100 case 12150:
00101 case 12152:
00102 case 12153:
00103 case 12161:
00104 case 12170:
00105 case 12224:
00106 case 12225:
00107 case 12230:
00108 case 12525:
00109 case 12521:
00110 case 12537:
00111 case 12541:
00112 case 12543:
00113 case 12547:
00114 case 12560:
00115 case 12561:
00116 case 12608:
00117 case 12609:
00118 LM_ERR("conneciom dropped\n");
00119 db_oracle_disconnect(con);
00120 default:
00121 break;
00122 }
00123
00124 return errbuf;
00125 }
00126
00127 const char* db_oracle_error(ora_con_t* con, sword status)
00128 {
00129 switch (status) {
00130 case OCI_SUCCESS:
00131 return "internal (success)";
00132
00133 case OCI_SUCCESS_WITH_INFO:
00134 case OCI_ERROR:
00135 return db_oracle_errorinfo(con);
00136
00137 case OCI_NEED_DATA:
00138 return "need data";
00139
00140 case OCI_NO_DATA:
00141 return "no data";
00142
00143 case OCI_INVALID_HANDLE:
00144 return "invalid handle";
00145
00146 case OCI_STILL_EXECUTING:
00147 return "executing (logic)";
00148
00149 case OCI_CONTINUE:
00150 return "continue (library)";
00151
00152 default:
00153 snprintf(errbuf, sizeof(errbuf),
00154 "unknown status %u", status);
00155 return errbuf;
00156 }
00157 }
00158
00159
00160
00161
00162
00163
00164 db_con_t* db_oracle_init(const str* _url)
00165 {
00166 return db_do_init(_url, (void *)db_oracle_new_connection);
00167 }
00168
00169
00170
00171
00172
00173
00174 void db_oracle_close(db_con_t* _h)
00175 {
00176 db_do_close(_h, db_oracle_free_connection);
00177 }
00178
00179
00180
00181
00182
00183 int db_oracle_free_result(db_con_t* _h, db_res_t* _r)
00184 {
00185 if (!_h || !_r) {
00186 LM_ERR("invalid parameter value\n");
00187 return -1;
00188 }
00189
00190 if (db_free_result(_r) < 0)
00191 {
00192 LM_ERR("failed to free result structure\n");
00193 return -1;
00194 }
00195 return 0;
00196 }
00197
00198
00199
00200
00201
00202 static int db_oracle_submit_query(const db_con_t* _h, const str* _s)
00203 {
00204 OCIBind* bind[MAX_BIND_HANDLES];
00205 OCIDate odt[sizeof(bind)/sizeof(bind[0])];
00206 str tmps;
00207 sword status;
00208 int pass;
00209 ora_con_t* con = CON_ORA(_h);
00210 query_data_t* pqd = con->pqdata;
00211 size_t hc = pqd->_n + pqd->_nw;
00212 OCIStmt *stmthp;
00213
00214 if (hc >= sizeof(bind)/sizeof(bind[0])) {
00215 LM_ERR("too many bound. Rebuild with MAX_BIND_HANDLES >= %u\n",
00216 (unsigned)hc);
00217 return -1;
00218 }
00219
00220 if (!pqd->_rs) {
00221
00222
00223
00224
00225 tmps.len = snprintf(st_buf, sizeof(st_buf),
00226 "begin %.*s; commit write batch nowait; end;",
00227 _s->len, _s->s);
00228 if ((unsigned)tmps.len >= sizeof(st_buf))
00229 return sql_buf_small();
00230 tmps.s = st_buf;
00231 _s = &tmps;
00232 }
00233
00234 pass = 1;
00235 if (!con->connected) {
00236 status = db_oracle_reconnect(con);
00237 if (status != OCI_SUCCESS) {
00238 LM_ERR("can't restore connection: %s\n", db_oracle_error(con, status));
00239 return -2;
00240 }
00241 LM_INFO("connection restored\n");
00242 --pass;
00243 }
00244 repeat:
00245 stmthp = NULL;
00246 status = OCIHandleAlloc(con->envhp, (dvoid**)(dvoid*)&stmthp,
00247 OCI_HTYPE_STMT, 0, NULL);
00248 if (status != OCI_SUCCESS)
00249 goto ora_err;
00250 status = OCIStmtPrepare(stmthp, con->errhp, (text*)_s->s, _s->len,
00251 OCI_NTV_SYNTAX, OCI_DEFAULT);
00252 if (status != OCI_SUCCESS)
00253 goto ora_err;
00254
00255 if (hc) {
00256 bmap_t bmap;
00257 size_t pos = 1;
00258 int i;
00259
00260 memset(bind, 0, hc*sizeof(bind[0]));
00261 for (i = 0; i < pqd->_n; i++) {
00262 if (db_oracle_val2bind(&bmap, &pqd->_v[i], &odt[pos]) < 0)
00263 goto bind_err;
00264 status = OCIBindByPos(stmthp, &bind[pos], con->errhp,
00265 pos, bmap.addr, bmap.size, bmap.type,
00266 NULL, NULL, NULL, 0, NULL, OCI_DEFAULT);
00267 if (status != OCI_SUCCESS)
00268 goto ora_err;
00269 ++pos;
00270 }
00271 for (i = 0; i < pqd->_nw; i++) {
00272 if (db_oracle_val2bind(&bmap, &pqd->_w[i], &odt[pos]) < 0) {
00273 bind_err:
00274 OCIHandleFree(stmthp, OCI_HTYPE_STMT);
00275 LM_ERR("can't map values\n");
00276 return -3;
00277 }
00278 status = OCIBindByPos(stmthp, &bind[pos], con->errhp,
00279 pos, bmap.addr, bmap.size, bmap.type,
00280 NULL, NULL, NULL, 0, NULL, OCI_DEFAULT);
00281 if (status != OCI_SUCCESS)
00282 goto ora_err;
00283 ++pos;
00284 }
00285 }
00286
00287
00288 status = begin_timelimit(con, 0);
00289 if (status != OCI_SUCCESS) goto ora_err;
00290 do status = OCIStmtExecute(con->svchp, stmthp, con->errhp,
00291 !pqd->_rs, 0, NULL, NULL,
00292 pqd->_rs ? OCI_STMT_SCROLLABLE_READONLY : OCI_DEFAULT);
00293 while (wait_timelimit(con, status));
00294 if (done_timelimit(con, status)) goto stop_exec;
00295 switch (status) {
00296 case OCI_SUCCESS_WITH_INFO:
00297 LM_WARN("driver: %s\n", db_oracle_errorinfo(con));
00298
00299 case OCI_SUCCESS:
00300 if (pqd->_rs)
00301 *pqd->_rs = stmthp;
00302 else
00303 OCIHandleFree(stmthp, OCI_HTYPE_STMT);
00304 return 0;
00305 default:
00306 pass = -pass;
00307 break;
00308 }
00309
00310 ora_err:
00311 LM_ERR("driver: %s\n", db_oracle_error(con, status));
00312 stop_exec:
00313 if (stmthp)
00314 OCIHandleFree(stmthp, OCI_HTYPE_STMT);
00315 if (pass == -1 && !con->connected) {
00316
00317 if (db_oracle_reconnect(con) == OCI_SUCCESS) {
00318 LM_NOTICE("attempt repeat after reconnect\n");
00319 pass = 0;
00320 goto repeat;
00321 }
00322 LM_ERR("connection loss\n");
00323 }
00324 return -4;
00325 }
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339 int db_oracle_query(const db_con_t* _h, const db_key_t* _k, const db_op_t* _op,
00340 const db_val_t* _v, const db_key_t* _c, int _n, int _nc,
00341 const db_key_t _o, db_res_t** _r)
00342 {
00343 query_data_t cb;
00344 OCIStmt* reshp;
00345 int rc;
00346
00347 if (!_h || !CON_TABLE(_h) || !_r) {
00348 LM_ERR("invalid parameter value\n");
00349 return -1;
00350 }
00351
00352 cb._rs = &reshp;
00353 cb._v = _v;
00354 cb._n = _n;
00355 cb._w = NULL;
00356 cb._nw = 0;
00357 CON_ORA(_h)->pqdata = &cb;
00358 CON_ORA(_h)->bindpos = 0;
00359 rc = db_do_query(_h, _k, _op, _v, _c, _n, _nc, _o, _r,
00360 db_oracle_val2str, db_oracle_submit_query, db_oracle_store_result);
00361 CON_ORA(_h)->pqdata = NULL;
00362 return rc;
00363 }
00364
00365
00366
00367
00368
00369 int db_oracle_raw_query(const db_con_t* _h, const str* _s, db_res_t** _r)
00370 {
00371 query_data_t cb;
00372 OCIStmt* reshp;
00373 int len;
00374 const char *p;
00375
00376 if (!_h || !_s || !_s->s) {
00377 badparam:
00378 LM_ERR("invalid parameter value\n");
00379 return -1;
00380 }
00381
00382
00383 memset(&cb, 0, sizeof(cb));
00384
00385 p = _s->s;
00386 len = _s->len;
00387 while (len && *p == ' ') ++p, --len;
00388 #define _S_DIFF(p, l, S) (l <= sizeof(S)-1 || strncasecmp(p, S, sizeof(S)-1))
00389 if (!_S_DIFF(p, len, "select ")) {
00390 if (!_r) goto badparam;
00391 cb._rs = &reshp;
00392 } else {
00393 if ( _S_DIFF(p, len, "insert ")
00394 && _S_DIFF(p, len, "delete ")
00395 && _S_DIFF(p, len, "update "))
00396 {
00397 LM_ERR("unknown raw_query: '%.*s'\n", _s->len, _s->s);
00398 return -2;
00399 }
00400 #undef _S_DIFF
00401 if (_r) goto badparam;
00402 cb._rs = NULL;
00403 }
00404
00405 len = db_do_raw_query(_h, _s, _r, db_oracle_submit_query, db_oracle_store_result);
00406 CON_ORA(_h)->pqdata = NULL;
00407 return len;
00408 }
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418 int db_oracle_insert(const db_con_t* _h, const db_key_t* _k, const db_val_t* _v,
00419 int _n)
00420 {
00421 query_data_t cb;
00422 int rc;
00423
00424 if (!_h || !CON_TABLE(_h)) {
00425 LM_ERR("invalid parameter value\n");
00426 return -1;
00427 }
00428
00429 cb._rs = NULL;
00430 cb._v = _v;
00431 cb._n = _n;
00432 cb._w = NULL;
00433 cb._nw = 0;
00434 CON_ORA(_h)->pqdata = &cb;
00435 CON_ORA(_h)->bindpos = 0;
00436 rc = db_do_insert(_h, _k, _v, _n, db_oracle_val2str, db_oracle_submit_query);
00437 CON_ORA(_h)->pqdata = NULL;
00438 return rc;
00439 }
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450 int db_oracle_delete(const db_con_t* _h, const db_key_t* _k, const db_op_t* _o,
00451 const db_val_t* _v, int _n)
00452 {
00453 query_data_t cb;
00454 int rc;
00455
00456 if (!_h || !CON_TABLE(_h)) {
00457 LM_ERR("invalid parameter value\n");
00458 return -1;
00459 }
00460
00461 cb._rs = NULL;
00462 cb._v = _v;
00463 cb._n = _n;
00464 cb._w = NULL;
00465 cb._nw = 0;
00466 CON_ORA(_h)->pqdata = &cb;
00467 CON_ORA(_h)->bindpos = 0;
00468 rc = db_do_delete(_h, _k, _o, _v, _n, db_oracle_val2str, db_oracle_submit_query);
00469 CON_ORA(_h)->pqdata = NULL;
00470 return rc;
00471 }
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485 int db_oracle_update(const db_con_t* _h, const db_key_t* _k, const db_op_t* _o,
00486 const db_val_t* _v, const db_key_t* _uk, const db_val_t* _uv,
00487 int _n, int _un)
00488 {
00489 query_data_t cb;
00490 int rc;
00491
00492 if (!_h || !CON_TABLE(_h)) {
00493 LM_ERR("invalid parameter value\n");
00494 return -1;
00495 }
00496
00497 cb._rs = NULL;
00498 cb._v = _uv;
00499 cb._n = _un;
00500 cb._w = _v;
00501 cb._nw = _n;
00502 CON_ORA(_h)->pqdata = &cb;
00503 CON_ORA(_h)->bindpos = 0;
00504 rc = db_do_update(_h, _k, _o, _v, _uk, _uv, _n, _un,
00505 db_oracle_val2str, db_oracle_submit_query);
00506 CON_ORA(_h)->pqdata = NULL;
00507 return rc;
00508 }
00509
00510
00511
00512
00513
00514
00515 int db_oracle_use_table(db_con_t* _h, const str* _t)
00516 {
00517 return db_use_table(_h, _t);
00518 }