OCILIB (C Driver for Oracle) 3.9.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-2011 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, v 3.9.1 2011-07-08 00:00 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->row_cur < 1, NULL); 00129 00130 switch (def->col.type) 00131 { 00132 case OCI_CDT_LONG: 00133 case OCI_CDT_CURSOR: 00134 case OCI_CDT_TIMESTAMP: 00135 case OCI_CDT_INTERVAL: 00136 case OCI_CDT_LOB: 00137 case OCI_CDT_FILE: 00138 case OCI_CDT_OBJECT: 00139 case OCI_CDT_COLLECTION: 00140 case OCI_CDT_REF: 00141 { 00142 /* handle based types */ 00143 00144 return def->buf.data[def->rs->row_cur-1]; 00145 } 00146 default: 00147 { 00148 /* scalar types */ 00149 00150 return (((ub1 *) (def->buf.data)) + (size_t) (def->col.bufsize * (def->rs->row_cur-1))); 00151 } 00152 } 00153 } 00154 00155 /* --------------------------------------------------------------------------------------------- * 00156 * OCI_DefineIsDataNotNull 00157 * --------------------------------------------------------------------------------------------- */ 00158 00159 boolean OCI_DefineIsDataNotNull 00160 ( 00161 OCI_Define *def 00162 ) 00163 { 00164 boolean res = FALSE; 00165 00166 if ((def != NULL) && (def->rs->row_cur > 0)) 00167 { 00168 OCIInd ind = OCI_IND_NULL; 00169 00170 if (def->col.type == OCI_CDT_OBJECT) 00171 { 00172 ind = * (OCIInd *) def->buf.obj_inds[def->rs->row_cur-1]; 00173 } 00174 else 00175 { 00176 ind = ((OCIInd *) (def->buf.inds))[def->rs->row_cur-1]; 00177 00178 } 00179 00180 res = (ind != OCI_IND_NULL); 00181 } 00182 00183 return res; 00184 } 00185 00186 00187 /* --------------------------------------------------------------------------------------------- * 00188 * OCI_DefineGetNumber 00189 * --------------------------------------------------------------------------------------------- */ 00190 00191 boolean OCI_DefineGetNumber 00192 ( 00193 OCI_Resultset *rs, 00194 unsigned int index, 00195 void *value, 00196 uword type, 00197 uword size 00198 ) 00199 { 00200 OCI_Define *def = OCI_GetDefine(rs, index); 00201 boolean res = FALSE; 00202 00203 if (OCI_DefineIsDataNotNull(def) == TRUE) 00204 { 00205 void *data = OCI_DefineGetData(def); 00206 00207 switch (def->col.type) 00208 { 00209 case OCI_CDT_NUMERIC: 00210 { 00211 res = OCI_NumberGet(rs->stmt->con, (OCINumber *) data, value, size, type); 00212 break; 00213 } 00214 case OCI_CDT_TEXT: 00215 { 00216 const mtext *fmt = OCI_GetDefaultFormatNumeric(rs->stmt->con); 00217 ub4 fmt_size = (ub4) mtslen(fmt); 00218 00219 res = OCI_NumberGetFromStr(rs->stmt->con, value, size, type, (dtext *) data, 00220 (int) dtslen((dtext *) data), fmt, fmt_size); 00221 break; 00222 } 00223 } 00224 } 00225 00226 OCI_RESULT(res); 00227 00228 return res; 00229 } 00230 00231 /* --------------------------------------------------------------------------------------------- * 00232 * OCI_DefineAlloc 00233 * --------------------------------------------------------------------------------------------- */ 00234 00235 boolean OCI_DefineAlloc 00236 ( 00237 OCI_Define *def 00238 ) 00239 { 00240 boolean res = TRUE; 00241 ub4 bufsize = 0; 00242 ub4 indsize = 0; 00243 ub4 i; 00244 00245 /* this function allocates internal buffers, handles, indicators, arrays, ... 00246 for the given output define handle */ 00247 00248 OCI_CHECK(def == NULL, FALSE); 00249 00250 /* Allocate null indicators array */ 00251 00252 if (def->col.ocode == SQLT_NTY || def->col.ocode == SQLT_REF) 00253 { 00254 indsize = (ub4) sizeof(void*); 00255 } 00256 else 00257 { 00258 indsize = (ub4) sizeof(sb2); 00259 } 00260 00261 if (res == TRUE) 00262 { 00263 def->buf.inds = (void *) OCI_MemAlloc(OCI_IPC_INDICATOR_ARRAY, (size_t) indsize, 00264 (size_t) def->buf.count, TRUE); 00265 res = (def->buf.inds != NULL); 00266 } 00267 00268 if (def->col.type == OCI_CDT_OBJECT) 00269 { 00270 def->buf.obj_inds = (void *) OCI_MemAlloc(OCI_IPC_INDICATOR_ARRAY, sizeof(void *), 00271 (size_t) def->buf.count, TRUE); 00272 res = (def->buf.obj_inds != NULL); 00273 } 00274 00275 /* Allocate row data sizes array */ 00276 00277 if (res == TRUE) 00278 { 00279 def->buf.lens = (void *) OCI_MemAlloc(OCI_IPC_LEN_ARRAY, (size_t) def->buf.sizelen, 00280 (size_t) def->buf.count, TRUE); 00281 res = (def->buf.lens != NULL); 00282 } 00283 00284 /* initialize length array with buffer default size. 00285 But, Oracle uses different sizes for static fetch and callback fetch....*/ 00286 00287 if (res == TRUE) 00288 { 00289 for (i=0; i < def->buf.count; i++) 00290 { 00291 if (def->buf.sizelen == (int) sizeof(ub2)) 00292 { 00293 *(ub2*)(((ub1 *)def->buf.lens) + (size_t) (def->buf.sizelen*i)) = (ub2) def->col.bufsize; 00294 } 00295 else if (def->buf.sizelen == (int) sizeof(ub4)) 00296 { 00297 *(ub4*)(((ub1 *)def->buf.lens) + (size_t) (def->buf.sizelen*i)) = (ub4) def->col.bufsize; 00298 } 00299 } 00300 } 00301 00302 /* Allocate buffer array */ 00303 00304 if (res == TRUE) 00305 { 00306 if (def->col.type == OCI_CDT_LONG) 00307 { 00308 bufsize = (ub4) sizeof(OCI_Long *); 00309 } 00310 else 00311 { 00312 bufsize = def->col.bufsize; 00313 } 00314 00315 def->buf.data = (void *) OCI_MemAlloc(OCI_IPC_BUFF_ARRAY, (size_t) bufsize, 00316 (size_t) def->buf.count, TRUE); 00317 00318 res = (def->buf.data != NULL); 00319 } 00320 00321 /* Allocate descriptor for cursor, lob and file, interval and timestamp */ 00322 00323 if (res == TRUE) 00324 { 00325 if (def->col.dtype != 0) 00326 { 00327 if (def->col.type == OCI_CDT_CURSOR) 00328 { 00329 for (i = 0; (i < def->buf.count) && (res == TRUE); i++) 00330 { 00331 res = (OCI_SUCCESS == OCI_HandleAlloc((dvoid *) def->rs->stmt->con->env, 00332 (dvoid **) &(def->buf.data[i]), 00333 (ub4) def->col.dtype, 00334 (size_t) 0, (dvoid **) NULL)); 00335 } 00336 } 00337 else 00338 { 00339 res = (OCI_SUCCESS == OCI_DescriptorArrayAlloc((dvoid *) def->rs->stmt->con->env, 00340 (dvoid **) def->buf.data, 00341 (ub4) def->col.dtype, 00342 (ub4) def->buf.count, 00343 (size_t) 0, (dvoid **) NULL)); 00344 00345 if ((res == TRUE) && (def->col.type == OCI_CDT_LOB)) 00346 { 00347 ub4 empty = 0; 00348 00349 for (i = 0; (i < def->buf.count) && (res == TRUE); i++) 00350 { 00351 OCI_CALL1 00352 ( 00353 res, def->rs->stmt->con, def->rs->stmt, 00354 00355 OCIAttrSet((dvoid *) def->buf.data[i], (ub4) def->col.dtype, 00356 (void *) &empty, (ub4) sizeof(empty), 00357 (ub4) OCI_ATTR_LOBEMPTY, def->rs->stmt->con->err) 00358 ) 00359 } 00360 } 00361 } 00362 } 00363 } 00364 00365 return res; 00366 } 00367 00368 /* --------------------------------------------------------------------------------------------- * 00369 * OCI_DefineDef 00370 * --------------------------------------------------------------------------------------------- */ 00371 00372 boolean OCI_DefineDef 00373 ( 00374 OCI_Define *def 00375 ) 00376 { 00377 boolean res = TRUE; 00378 ub2 fetch_mode = OCI_DEFAULT; 00379 00380 OCI_CHECK(def == NULL, FALSE); 00381 00382 /*check define mode for long columns */ 00383 00384 if (def->col.type == OCI_CDT_LONG) 00385 { 00386 fetch_mode = OCI_DYNAMIC_FETCH; 00387 } 00388 00389 /* oracle defining */ 00390 00391 OCI_CALL1 00392 ( 00393 res, def->rs->stmt->con, def->rs->stmt, 00394 00395 OCIDefineByPos(def->rs->stmt->stmt, 00396 (OCIDefine **) &def->buf.handle, 00397 def->rs->stmt->con->err, 00398 def->rs->nb_defs, 00399 (void *) def->buf.data, 00400 (sb4 ) def->col.bufsize, 00401 (ub2 ) def->col.icode, 00402 (void *) def->buf.inds, 00403 (ub2 *) def->buf.lens, 00404 (ub2 *) NULL, 00405 (ub4 ) fetch_mode) 00406 ) 00407 00408 if (def->col.ocode == SQLT_NTY || def->col.ocode == SQLT_REF) 00409 { 00410 OCI_CALL1 00411 ( 00412 res, def->rs->stmt->con, def->rs->stmt, 00413 00414 OCIDefineObject((OCIDefine *) def->buf.handle, 00415 def->rs->stmt->con->err, 00416 def->col.typinf->tdo, 00417 (void **) def->buf.data, 00418 (ub4 *) NULL, 00419 (void **) def->buf.obj_inds, 00420 (ub4 *) NULL) 00421 ) 00422 } 00423 00424 if(( def->col.type == OCI_CDT_TEXT) || 00425 ((def->col.type == OCI_CDT_LOB) && (def->col.subtype != OCI_BLOB)) || 00426 ((def->col.type == OCI_CDT_FILE) && (def->col.subtype != OCI_BFILE)) || 00427 ((def->col.type == OCI_CDT_LONG) && (def->col.subtype != OCI_BLONG))) 00428 { 00429 00430 if ((def->col.csfrm == SQLCS_NCHAR) || (OCILib.nls_utf8 == TRUE)) 00431 { 00432 ub1 csfrm = SQLCS_NCHAR; 00433 00434 OCI_CALL1 00435 ( 00436 res, def->rs->stmt->con, def->rs->stmt, 00437 00438 OCIAttrSet((dvoid *) def->buf.handle, 00439 (ub4 ) OCI_HTYPE_DEFINE, 00440 (dvoid *) &csfrm, 00441 (ub4 ) sizeof(csfrm), 00442 (ub4 ) OCI_ATTR_CHARSET_FORM, 00443 def->rs->stmt->con->err) 00444 ) 00445 } 00446 00447 #ifdef OCI_CHARSET_MIXED 00448 00449 /* setup Unicode mode for user data on mixed builds */ 00450 { 00451 ub2 csid = OCI_UTF16ID; 00452 00453 OCI_CALL1 00454 ( 00455 res, def->rs->stmt->con, def->rs->stmt, 00456 00457 OCIAttrSet((dvoid *) def->buf.handle, 00458 (ub4 ) OCI_HTYPE_DEFINE, 00459 (dvoid *) &csid, 00460 (ub4 ) sizeof(csid), 00461 (ub4 ) OCI_ATTR_CHARSET_ID, 00462 def->rs->stmt->con->err) 00463 ) 00464 } 00465 00466 #endif 00467 00468 } 00469 00470 return res; 00471 } 00472 00473 /* --------------------------------------------------------------------------------------------- * 00474 * OCI_DefineRequestBuffer 00475 * --------------------------------------------------------------------------------------------- */ 00476 00477 boolean OCI_DefineRequestBuffer 00478 ( 00479 OCI_Define *def, 00480 unsigned int size 00481 ) 00482 { 00483 boolean res = TRUE; 00484 00485 size++; 00486 00487 if (OCILib.nls_utf8 == TRUE) 00488 { 00489 size *= UTF8_BYTES_PER_CHAR; 00490 } 00491 else 00492 { 00493 size *= sizeof(dtext); 00494 } 00495 00496 if (def->buf.tmpbuf == NULL) 00497 { 00498 def->buf.tmpbuf = (dtext *) OCI_MemAlloc(OCI_IPC_STRING, (size_t) size, (size_t) 1, TRUE); 00499 00500 if (def->buf.tmpbuf != NULL) 00501 { 00502 def->buf.tmpsize = size; 00503 } 00504 else 00505 { 00506 res = FALSE; 00507 } 00508 00509 } 00510 else if (def->buf.tmpsize < size) 00511 { 00512 def->buf.tmpbuf = (dtext *) OCI_MemRealloc(def->buf.tmpbuf, OCI_IPC_STRING, (size_t) size, (size_t) 1); 00513 00514 if (def->buf.tmpbuf != NULL) 00515 { 00516 def->buf.tmpsize = size; 00517 } 00518 else 00519 { 00520 res = FALSE; 00521 } 00522 } 00523 00524 def->buf.tmpbuf[0] = 0; 00525 00526 return res; 00527 }