OCILIB (C Driver for Oracle) 3.12.1
|
00001 /* 00002 +-----------------------------------------------------------------------------------------+ 00003 | | 00004 | OCILIB - C Driver for Oracle | 00005 | | 00006 | (C Wrapper for Oracle OCI) | 00007 | | 00008 | Website : http://www.ocilib.net | 00009 | | 00010 | Copyright (c) 2007-2013 Vincent ROGIER <vince.rogier@ocilib.net> | 00011 | | 00012 +-----------------------------------------------------------------------------------------+ 00013 | | 00014 | This library is free software; you can redistribute it and/or | 00015 | modify it under the terms of the GNU Lesser General Public | 00016 | License as published by the Free Software Foundation; either | 00017 | version 2 of the License, or (at your option) any later version. | 00018 | | 00019 | This library is distributed in the hope that it will be useful, | 00020 | but WITHOUT ANY WARRANTY; without even the implied warranty of | 00021 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | 00022 | Lesser General Public License for more details. | 00023 | | 00024 | You should have received a copy of the GNU Lesser General Public | 00025 | License along with this library; if not, write to the Free | 00026 | Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | 00027 | | 00028 +-----------------------------------------------------------------------------------------+ 00029 */ 00030 00031 /* --------------------------------------------------------------------------------------------- * 00032 * $Id: define.c, Vincent Rogier $ 00033 * --------------------------------------------------------------------------------------------- */ 00034 00035 #include "ocilib_internal.h" 00036 00037 /* ********************************************************************************************* * 00038 * PRIVATE FUNCTIONS 00039 * ********************************************************************************************* */ 00040 00041 /* --------------------------------------------------------------------------------------------- * 00042 * OCI_GetDefine 00043 * --------------------------------------------------------------------------------------------- */ 00044 00045 OCI_Define * OCI_GetDefine 00046 ( 00047 OCI_Resultset *rs, 00048 unsigned int index 00049 ) 00050 { 00051 OCI_Define * def = NULL; 00052 00053 OCI_CHECK_PTR(OCI_IPC_RESULTSET, rs, NULL); 00054 OCI_CHECK_BOUND(rs->stmt->con, index, 1, rs->nb_defs, NULL); 00055 00056 if ((rs->stmt->exec_mode != OCI_DESCRIBE_ONLY) && (rs->stmt->exec_mode != OCI_PARSE_ONLY)) 00057 { 00058 def = &rs->defs[index-1]; 00059 } 00060 00061 return def; 00062 } 00063 00064 /* --------------------------------------------------------------------------------------------- * 00065 * OCI_GetDefineIndex 00066 * --------------------------------------------------------------------------------------------- */ 00067 00068 int OCI_GetDefineIndex 00069 ( 00070 OCI_Resultset *rs, 00071 const mtext *name 00072 ) 00073 { 00074 OCI_HashEntry *he = NULL; 00075 int index = -1; 00076 00077 OCI_CHECK_PTR(OCI_IPC_RESULTSET, rs, -1); 00078 OCI_CHECK_PTR(OCI_IPC_STRING, name, -1); 00079 00080 if (rs->map == NULL) 00081 { 00082 /* create the map at the first call to OCI_Getxxxxx2() to save 00083 time and memory when it's not needed */ 00084 00085 rs->map = OCI_HashCreate(OCI_HASH_DEFAULT_SIZE, OCI_HASH_INTEGER); 00086 00087 if (rs->map != NULL) 00088 { 00089 ub4 i; 00090 00091 for (i = 0; i < rs->nb_defs; i++) 00092 { 00093 OCI_HashAddInt(rs->map, rs->defs[i].col.name, (i+1)); 00094 } 00095 } 00096 } 00097 00098 /* check out we got our map object */ 00099 00100 OCI_CHECK(rs->map == NULL, -1); 00101 00102 he = OCI_HashLookup(rs->map, name, FALSE); 00103 00104 while (he != NULL) 00105 { 00106 /* no more entries or key matched => so we got it ! */ 00107 00108 if (he->next == NULL || mtscasecmp(he->key, name) == 0) 00109 { 00110 index = he->values->value.num; 00111 break; 00112 } 00113 } 00114 00115 return index; 00116 } 00117 00118 /* --------------------------------------------------------------------------------------------- * 00119 * OCI_DefineGetData 00120 * --------------------------------------------------------------------------------------------- */ 00121 00122 void * OCI_DefineGetData 00123 ( 00124 OCI_Define *def 00125 ) 00126 { 00127 OCI_CHECK(def == NULL, NULL); 00128 OCI_CHECK(def->rs == NULL, NULL); 00129 OCI_CHECK(def->rs->row_cur < 1, NULL); 00130 00131 switch (def->col.type) 00132 { 00133 case OCI_CDT_LONG: 00134 case OCI_CDT_CURSOR: 00135 case OCI_CDT_TIMESTAMP: 00136 case OCI_CDT_INTERVAL: 00137 case OCI_CDT_LOB: 00138 case OCI_CDT_FILE: 00139 case OCI_CDT_OBJECT: 00140 case OCI_CDT_COLLECTION: 00141 case OCI_CDT_REF: 00142 { 00143 /* handle based types */ 00144 00145 return def->buf.data[def->rs->row_cur-1]; 00146 } 00147 default: 00148 { 00149 /* scalar types */ 00150 00151 return (((ub1 *) (def->buf.data)) + (size_t) (def->col.bufsize * (def->rs->row_cur-1))); 00152 } 00153 } 00154 } 00155 00156 /* --------------------------------------------------------------------------------------------- * 00157 * OCI_DefineIsDataNotNull 00158 * --------------------------------------------------------------------------------------------- */ 00159 00160 boolean OCI_DefineIsDataNotNull 00161 ( 00162 OCI_Define *def 00163 ) 00164 { 00165 boolean res = FALSE; 00166 00167 if ((def != NULL) && (def->rs->row_cur > 0)) 00168 { 00169 OCIInd ind = OCI_IND_NULL; 00170 00171 if (def->col.type == OCI_CDT_OBJECT) 00172 { 00173 ind = * (OCIInd *) def->buf.obj_inds[def->rs->row_cur-1]; 00174 } 00175 else 00176 { 00177 ind = ((OCIInd *) (def->buf.inds))[def->rs->row_cur-1]; 00178 00179 } 00180 00181 res = (ind != OCI_IND_NULL); 00182 } 00183 00184 return res; 00185 } 00186 00187 00188 /* --------------------------------------------------------------------------------------------- * 00189 * OCI_DefineGetNumber 00190 * --------------------------------------------------------------------------------------------- */ 00191 00192 boolean OCI_DefineGetNumber 00193 ( 00194 OCI_Resultset *rs, 00195 unsigned int index, 00196 void *value, 00197 uword type, 00198 uword size 00199 ) 00200 { 00201 OCI_Define *def = OCI_GetDefine(rs, index); 00202 boolean res = FALSE; 00203 00204 if (OCI_DefineIsDataNotNull(def) == TRUE) 00205 { 00206 void *data = OCI_DefineGetData(def); 00207 00208 switch (def->col.type) 00209 { 00210 case OCI_CDT_NUMERIC: 00211 { 00212 res = OCI_NumberGet(rs->stmt->con, data, size, type, def->col.icode, value); 00213 break; 00214 } 00215 case OCI_CDT_TEXT: 00216 { 00217 res = OCI_NumberFromString(rs->stmt->con, value, size, type, def->col.icode, (const dtext *) data, NULL); 00218 break; 00219 } 00220 } 00221 } 00222 00223 OCI_RESULT(res); 00224 00225 return res; 00226 } 00227 00228 /* --------------------------------------------------------------------------------------------- * 00229 * OCI_DefineAlloc 00230 * --------------------------------------------------------------------------------------------- */ 00231 00232 boolean OCI_DefineAlloc 00233 ( 00234 OCI_Define *def 00235 ) 00236 { 00237 boolean res = TRUE; 00238 ub4 indsize = 0; 00239 ub4 i; 00240 00241 /* this function allocates internal buffers, handles, indicators, arrays, ... 00242 for the given output define handle */ 00243 00244 OCI_CHECK(def == NULL, FALSE); 00245 00246 /* Allocate null indicators array */ 00247 00248 if (def->col.ocode == SQLT_NTY || def->col.ocode == SQLT_REF) 00249 { 00250 indsize = (ub4) sizeof(void*); 00251 } 00252 else 00253 { 00254 indsize = (ub4) sizeof(sb2); 00255 } 00256 00257 if (res == TRUE) 00258 { 00259 def->buf.inds = (void *) OCI_MemAlloc(OCI_IPC_INDICATOR_ARRAY, (size_t) indsize, 00260 (size_t) def->buf.count, TRUE); 00261 res = (def->buf.inds != NULL); 00262 } 00263 00264 if (def->col.type == OCI_CDT_OBJECT) 00265 { 00266 def->buf.obj_inds = (void *) OCI_MemAlloc(OCI_IPC_INDICATOR_ARRAY, sizeof(void *), 00267 (size_t) def->buf.count, TRUE); 00268 res = (def->buf.obj_inds != NULL); 00269 } 00270 00271 /* Allocate row data sizes array */ 00272 00273 if (res == TRUE) 00274 { 00275 def->buf.lens = (void *) OCI_MemAlloc(OCI_IPC_LEN_ARRAY, (size_t) def->buf.sizelen, 00276 (size_t) def->buf.count, TRUE); 00277 res = (def->buf.lens != NULL); 00278 } 00279 00280 /* initialize length array with buffer default size. 00281 But, Oracle uses different sizes for static fetch and callback fetch....*/ 00282 00283 if (res == TRUE) 00284 { 00285 ub4 bufsize = 0; 00286 00287 for (i=0; i < def->buf.count; i++) 00288 { 00289 if (def->buf.sizelen == (int) sizeof(ub2)) 00290 { 00291 *(ub2*)(((ub1 *)def->buf.lens) + (size_t) (def->buf.sizelen*i)) = (ub2) def->col.bufsize; 00292 } 00293 else if (def->buf.sizelen == (int) sizeof(ub4)) 00294 { 00295 *(ub4*)(((ub1 *)def->buf.lens) + (size_t) (def->buf.sizelen*i)) = (ub4) def->col.bufsize; 00296 } 00297 } 00298 00299 /* Allocate buffer array */ 00300 00301 if (def->col.type == OCI_CDT_LONG) 00302 { 00303 bufsize = (ub4) sizeof(OCI_Long *); 00304 } 00305 else 00306 { 00307 bufsize = def->col.bufsize; 00308 } 00309 00310 def->buf.data = (void *) OCI_MemAlloc(OCI_IPC_BUFF_ARRAY, (size_t) bufsize, 00311 (size_t) def->buf.count, TRUE); 00312 00313 res = (def->buf.data != NULL); 00314 } 00315 00316 /* Allocate descriptor for cursor, lob and file, interval and timestamp */ 00317 00318 if (res == TRUE) 00319 { 00320 if (def->col.dtype != 0) 00321 { 00322 if (def->col.type == OCI_CDT_CURSOR) 00323 { 00324 for (i = 0; (i < def->buf.count) && (res == TRUE); i++) 00325 { 00326 res = (OCI_SUCCESS == OCI_HandleAlloc((dvoid *) def->rs->stmt->con->env, 00327 (dvoid **) &(def->buf.data[i]), 00328 (ub4) def->col.dtype, 00329 (size_t) 0, (dvoid **) NULL)); 00330 } 00331 } 00332 else 00333 { 00334 res = (OCI_SUCCESS == OCI_DescriptorArrayAlloc((dvoid *) def->rs->stmt->con->env, 00335 (dvoid **) def->buf.data, 00336 (ub4) def->col.dtype, 00337 (ub4) def->buf.count, 00338 (size_t) 0, (dvoid **) NULL)); 00339 00340 if ((res == TRUE) && (def->col.type == OCI_CDT_LOB)) 00341 { 00342 ub4 empty = 0; 00343 00344 for (i = 0; (i < def->buf.count) && (res == TRUE); i++) 00345 { 00346 OCI_CALL1 00347 ( 00348 res, def->rs->stmt->con, def->rs->stmt, 00349 00350 OCIAttrSet((dvoid *) def->buf.data[i], (ub4) def->col.dtype, 00351 (void *) &empty, (ub4) sizeof(empty), 00352 (ub4) OCI_ATTR_LOBEMPTY, def->rs->stmt->con->err) 00353 ) 00354 } 00355 } 00356 } 00357 } 00358 } 00359 00360 return res; 00361 } 00362 00363 /* --------------------------------------------------------------------------------------------- * 00364 * OCI_DefineDef 00365 * --------------------------------------------------------------------------------------------- */ 00366 00367 boolean OCI_DefineDef 00368 ( 00369 OCI_Define *def, 00370 ub4 position 00371 ) 00372 { 00373 boolean res = TRUE; 00374 ub2 fetch_mode = OCI_DEFAULT; 00375 00376 OCI_CHECK(def == NULL, FALSE); 00377 00378 /*check define mode for long columns */ 00379 00380 if (def->col.type == OCI_CDT_LONG) 00381 { 00382 fetch_mode = OCI_DYNAMIC_FETCH; 00383 } 00384 00385 /* oracle defining */ 00386 00387 OCI_CALL1 00388 ( 00389 res, def->rs->stmt->con, def->rs->stmt, 00390 00391 OCIDefineByPos(def->rs->stmt->stmt, 00392 (OCIDefine **) &def->buf.handle, 00393 def->rs->stmt->con->err, 00394 position, 00395 (void *) def->buf.data, 00396 (sb4 ) def->col.bufsize, 00397 (ub2 ) def->col.icode, 00398 (void *) def->buf.inds, 00399 (ub2 *) def->buf.lens, 00400 (ub2 *) NULL, 00401 (ub4 ) fetch_mode) 00402 ) 00403 00404 if (def->col.ocode == SQLT_NTY || def->col.ocode == SQLT_REF) 00405 { 00406 OCI_CALL1 00407 ( 00408 res, def->rs->stmt->con, def->rs->stmt, 00409 00410 OCIDefineObject((OCIDefine *) def->buf.handle, 00411 def->rs->stmt->con->err, 00412 def->col.typinf->tdo, 00413 (void **) def->buf.data, 00414 (ub4 *) NULL, 00415 (void **) def->buf.obj_inds, 00416 (ub4 *) NULL) 00417 ) 00418 } 00419 00420 if(( def->col.type == OCI_CDT_TEXT) || 00421 ((def->col.type == OCI_CDT_LOB) && (def->col.subtype != OCI_BLOB)) || 00422 ((def->col.type == OCI_CDT_FILE) && (def->col.subtype != OCI_BFILE)) || 00423 ((def->col.type == OCI_CDT_LONG) && (def->col.subtype != OCI_BLONG))) 00424 { 00425 00426 if ((def->col.csfrm == SQLCS_NCHAR) || (OCILib.nls_utf8 == TRUE)) 00427 { 00428 ub1 csfrm = SQLCS_NCHAR; 00429 00430 OCI_CALL1 00431 ( 00432 res, def->rs->stmt->con, def->rs->stmt, 00433 00434 OCIAttrSet((dvoid *) def->buf.handle, 00435 (ub4 ) OCI_HTYPE_DEFINE, 00436 (dvoid *) &csfrm, 00437 (ub4 ) sizeof(csfrm), 00438 (ub4 ) OCI_ATTR_CHARSET_FORM, 00439 def->rs->stmt->con->err) 00440 ) 00441 } 00442 00443 #ifdef OCI_CHARSET_MIXED 00444 00445 /* setup Unicode mode for user data on mixed builds */ 00446 { 00447 ub2 csid = OCI_UTF16ID; 00448 00449 OCI_CALL1 00450 ( 00451 res, def->rs->stmt->con, def->rs->stmt, 00452 00453 OCIAttrSet((dvoid *) def->buf.handle, 00454 (ub4 ) OCI_HTYPE_DEFINE, 00455 (dvoid *) &csid, 00456 (ub4 ) sizeof(csid), 00457 (ub4 ) OCI_ATTR_CHARSET_ID, 00458 def->rs->stmt->con->err) 00459 ) 00460 } 00461 00462 #endif 00463 00464 } 00465 00466 return res; 00467 } 00468 00469 /* --------------------------------------------------------------------------------------------- * 00470 * OCI_DefineRequestBuffer 00471 * --------------------------------------------------------------------------------------------- */ 00472 00473 boolean OCI_DefineRequestBuffer 00474 ( 00475 OCI_Define *def, 00476 unsigned int size 00477 ) 00478 { 00479 boolean res = TRUE; 00480 00481 size++; 00482 00483 if (OCILib.nls_utf8 == TRUE) 00484 { 00485 size *= UTF8_BYTES_PER_CHAR; 00486 } 00487 else 00488 { 00489 size *= sizeof(dtext); 00490 } 00491 00492 if (def->buf.tmpbuf == NULL) 00493 { 00494 def->buf.tmpbuf = (dtext *) OCI_MemAlloc(OCI_IPC_STRING, (size_t) size, (size_t) 1, TRUE); 00495 00496 if (def->buf.tmpbuf != NULL) 00497 { 00498 def->buf.tmpsize = size; 00499 } 00500 else 00501 { 00502 res = FALSE; 00503 } 00504 00505 } 00506 else if (def->buf.tmpsize < size) 00507 { 00508 def->buf.tmpbuf = (dtext *) OCI_MemRealloc(def->buf.tmpbuf, OCI_IPC_STRING, (size_t) size, (size_t) 1); 00509 00510 if (def->buf.tmpbuf != NULL) 00511 { 00512 def->buf.tmpsize = size; 00513 } 00514 else 00515 { 00516 res = FALSE; 00517 } 00518 } 00519 00520 if (def->buf.tmpbuf != NULL) 00521 { 00522 def->buf.tmpbuf[0] = 0; 00523 } 00524 00525 return res; 00526 }