OCILIB (C Driver for Oracle) 3.9.2
|
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: typeinfo.c, v 3.9.2 2011-07-13 00:00 Vincent Rogier $ 00033 * --------------------------------------------------------------------------------------------- */ 00034 00035 #include "ocilib_internal.h" 00036 00037 /* ********************************************************************************************* * 00038 * PRIVATE FUNCTIONS 00039 * ********************************************************************************************* */ 00040 00041 /* --------------------------------------------------------------------------------------------- * 00042 * OCI_TypeInfoClose 00043 * --------------------------------------------------------------------------------------------- */ 00044 00045 boolean OCI_TypeInfoClose 00046 ( 00047 OCI_TypeInfo *typinf 00048 ) 00049 { 00050 ub2 i; 00051 00052 OCI_CHECK(typinf == NULL, FALSE); 00053 00054 for (i=0; i < typinf->nb_cols; i++) 00055 { 00056 OCI_FREE(typinf->cols[i].name); 00057 } 00058 00059 OCI_FREE(typinf->cols); 00060 OCI_FREE(typinf->name); 00061 OCI_FREE(typinf->schema); 00062 OCI_FREE(typinf->offsets); 00063 00064 return TRUE; 00065 } 00066 00067 /* ********************************************************************************************* * 00068 * PUBLIC FUNCTIONS 00069 * ********************************************************************************************* */ 00070 00071 /* --------------------------------------------------------------------------------------------- * 00072 * OCI_TypeInfoGet 00073 * --------------------------------------------------------------------------------------------- */ 00074 00075 OCI_TypeInfo * OCI_API OCI_TypeInfoGet 00076 ( 00077 OCI_Connection *con, 00078 const mtext *name, 00079 unsigned int type 00080 ) 00081 { 00082 OCI_TypeInfo *typinf = NULL; 00083 OCI_Item *item = NULL; 00084 OCIDescribe *dschp = NULL; 00085 OCIParam *parmh1 = NULL; 00086 OCIParam *parmh2 = NULL; 00087 mtext *str = NULL; 00088 int etype = OCI_DESC_COLUMN; 00089 int ptype = 0; 00090 ub1 item_type = 0; 00091 ub4 attr_type = 0; 00092 ub4 num_type = 0; 00093 boolean res = TRUE; 00094 boolean found = FALSE; 00095 ub2 i; 00096 00097 mtext obj_schema[OCI_SIZE_OBJ_NAME+1]; 00098 mtext obj_name[OCI_SIZE_OBJ_NAME+1]; 00099 00100 OCI_CHECK_INITIALIZED(NULL); 00101 00102 OCI_CHECK_PTR(OCI_IPC_CONNECTION, con, NULL); 00103 OCI_CHECK_PTR(OCI_IPC_STRING, name, NULL); 00104 00105 if (type == OCI_TIF_TABLE) 00106 { 00107 item_type = OCI_PTYPE_TABLE; 00108 } 00109 else if (type == OCI_TIF_VIEW) 00110 { 00111 item_type = OCI_PTYPE_VIEW; 00112 } 00113 else if (type == OCI_TIF_TYPE) 00114 { 00115 item_type = OCI_PTYPE_TYPE; 00116 } 00117 else 00118 { 00119 return NULL; 00120 } 00121 00122 obj_schema[0] = 0; 00123 obj_name[0] = 0; 00124 00125 /* is the schema provided in the object name ? */ 00126 00127 for (str = (mtext *) name; *str != 0; str++) 00128 { 00129 if (*str == MT('.')) 00130 { 00131 mtsncat(obj_schema, name, str-name); 00132 mtsncat(obj_name, ++str, (size_t) OCI_SIZE_OBJ_NAME); 00133 break; 00134 } 00135 } 00136 00137 /* if the schema is not provided, we just copy the object name */ 00138 00139 if (obj_name[0] == 0) 00140 { 00141 mtsncat(obj_name, name, (size_t) OCI_SIZE_OBJ_NAME); 00142 } 00143 00144 /* type name must be uppercase */ 00145 00146 for (str = obj_name; *str != 0; str++) 00147 { 00148 *str = (mtext) mttoupper(*str); 00149 } 00150 00151 /* schema name must be uppercase */ 00152 00153 for (str = obj_schema; *str != 0; str++) 00154 { 00155 *str = (mtext) mttoupper(*str); 00156 } 00157 00158 /* first try to find it in list */ 00159 00160 item = con->tinfs->head; 00161 00162 /* walk along the list to find the type */ 00163 00164 while (item != NULL) 00165 { 00166 typinf = (OCI_TypeInfo *) item->data; 00167 00168 if ((typinf != NULL) && (typinf->type == type)) 00169 { 00170 if ((mtscasecmp(typinf->name, obj_name ) == 0) && 00171 (mtscasecmp(typinf->schema, obj_schema) == 0)) 00172 { 00173 found = TRUE; 00174 break; 00175 } 00176 } 00177 00178 item = item->next; 00179 } 00180 00181 /* Not found, so create type object */ 00182 00183 if (found == FALSE) 00184 { 00185 item = OCI_ListAppend(con->tinfs, sizeof(OCI_TypeInfo)); 00186 00187 res = (item != NULL); 00188 00189 if (res == TRUE) 00190 { 00191 typinf = (OCI_TypeInfo *) item->data; 00192 00193 typinf->type = type; 00194 typinf->con = con; 00195 typinf->name = mtsdup(obj_name); 00196 typinf->schema = mtsdup(obj_schema); 00197 typinf->struct_size = 0; 00198 00199 res = (OCI_SUCCESS == OCI_HandleAlloc(typinf->con->env, 00200 (dvoid **) (void *) &dschp, 00201 OCI_HTYPE_DESCRIBE, (size_t) 0, 00202 (dvoid **) NULL)); 00203 } 00204 00205 if (res == TRUE) 00206 { 00207 if (type == OCI_TIF_TYPE) 00208 { 00209 void *ostr1 = NULL; 00210 void *ostr2 = NULL; 00211 int osize1 = -1; 00212 int osize2 = -1; 00213 00214 attr_type = OCI_ATTR_LIST_TYPE_ATTRS; 00215 num_type = OCI_ATTR_NUM_TYPE_ATTRS; 00216 ptype = OCI_DESC_TYPE; 00217 00218 ostr1 = OCI_GetInputMetaString(typinf->schema, &osize1); 00219 ostr2 = OCI_GetInputMetaString(typinf->name, &osize2); 00220 00221 OCI_CALL2 00222 ( 00223 res, con, 00224 00225 OCITypeByName(typinf->con->env, con->err, con->cxt, 00226 (text *) ostr1, (ub4) osize1, 00227 (text *) ostr2, (ub4) osize2, 00228 (text *) NULL, (ub4) 0, 00229 OCI_DURATION_SESSION, OCI_TYPEGET_ALL, 00230 &typinf->tdo) 00231 ) 00232 00233 OCI_CALL2 00234 ( 00235 res, con, 00236 00237 OCIDescribeAny(con->cxt, con->err, (void *) typinf->tdo, 00238 0, OCI_OTYPE_PTR, OCI_DEFAULT, 00239 OCI_PTYPE_TYPE, dschp) 00240 ) 00241 00242 OCI_ReleaseMetaString(ostr1); 00243 OCI_ReleaseMetaString(ostr2); 00244 } 00245 else 00246 { 00247 mtext buffer[(OCI_SIZE_OBJ_NAME*2) + 2]; 00248 00249 size_t size = sizeof(buffer)/sizeof(mtext); 00250 void *ostr1 = NULL; 00251 int osize1 = -1; 00252 00253 attr_type = OCI_ATTR_LIST_COLUMNS; 00254 num_type = OCI_ATTR_NUM_COLS; 00255 ptype = OCI_DESC_TABLE; 00256 str = buffer; 00257 00258 str[0] = 0; 00259 00260 if ((typinf->schema != NULL) && (typinf->schema[0] != 0)) 00261 { 00262 str = mtsncat(buffer, typinf->schema, size); 00263 size -= mtslen(typinf->schema); 00264 str = mtsncat(str, MT("."), size); 00265 size -= (size_t) 1; 00266 } 00267 00268 mtsncat(str, typinf->name, size); 00269 00270 ostr1 = OCI_GetInputMetaString(str, &osize1); 00271 00272 OCI_CALL2 00273 ( 00274 res, con, 00275 00276 OCIDescribeAny(con->cxt, con->err, (dvoid *) ostr1, 00277 (ub4) osize1, OCI_OTYPE_NAME, 00278 OCI_DEFAULT, item_type, dschp) 00279 ) 00280 00281 OCI_ReleaseMetaString(ostr1); 00282 } 00283 00284 OCI_CALL2 00285 ( 00286 res, con, 00287 00288 OCIAttrGet(dschp, OCI_HTYPE_DESCRIBE, &parmh1, 00289 NULL, OCI_ATTR_PARAM, con->err) 00290 ) 00291 00292 00293 if (type == OCI_TIF_TYPE) 00294 { 00295 boolean pdt = FALSE; 00296 00297 /* check if it's system predefined type if order to avoid the next call 00298 that is not allowed on system types */ 00299 00300 OCI_CALL2 00301 ( 00302 res, con, 00303 00304 OCIAttrGet(parmh1, OCI_DTYPE_PARAM, &pdt, 00305 NULL, OCI_ATTR_IS_PREDEFINED_TYPE, con->err) 00306 ) 00307 00308 if (pdt == FALSE) 00309 { 00310 OCI_CALL2 00311 ( 00312 res, con, 00313 00314 OCIAttrGet(parmh1, OCI_DTYPE_PARAM, &typinf->tcode, 00315 NULL, OCI_ATTR_TYPECODE, con->err) 00316 ) 00317 } 00318 } 00319 00320 /* do we need get more attributes for collections ? */ 00321 00322 if (typinf->tcode == SQLT_NCO) 00323 { 00324 typinf->nb_cols = 1; 00325 00326 ptype = OCI_DESC_COLLECTION; 00327 etype = OCI_DESC_TYPE; 00328 parmh2 = parmh1; 00329 00330 OCI_CALL2 00331 ( 00332 res, con, 00333 00334 OCIAttrGet(parmh1, OCI_DTYPE_PARAM, &typinf->ccode, 00335 NULL, OCI_ATTR_COLLECTION_TYPECODE, con->err) 00336 ) 00337 } 00338 else 00339 { 00340 OCI_CALL2 00341 ( 00342 res, con, 00343 00344 OCIAttrGet(parmh1, OCI_DTYPE_PARAM, &parmh2, 00345 NULL, attr_type, con->err) 00346 ) 00347 00348 OCI_CALL2 00349 ( 00350 res, con, 00351 00352 OCIAttrGet(parmh1, OCI_DTYPE_PARAM, &typinf->nb_cols, 00353 NULL, num_type, con->err) 00354 ) 00355 } 00356 00357 /* allocates memory for cached offsets */ 00358 00359 if (typinf->nb_cols > 0) 00360 { 00361 typinf->offsets = (int *) OCI_MemAlloc(OCI_IPC_ARRAY, 00362 sizeof(*typinf->offsets), 00363 (size_t) typinf->nb_cols, 00364 FALSE); 00365 00366 res = (typinf->offsets != NULL); 00367 00368 if (res == TRUE) 00369 { 00370 memset(typinf->offsets, -1, sizeof(*typinf->offsets) * typinf->nb_cols); 00371 } 00372 } 00373 00374 /* allocates memory for children */ 00375 00376 if (typinf->nb_cols > 0) 00377 { 00378 typinf->cols = (OCI_Column *) OCI_MemAlloc(OCI_IPC_COLUMN, 00379 sizeof(*typinf->cols), 00380 (size_t) typinf->nb_cols, 00381 TRUE); 00382 00383 /* describe children */ 00384 00385 if (typinf->cols != NULL) 00386 { 00387 for (i = 0; i < typinf->nb_cols; i++) 00388 { 00389 res = res && OCI_ColumnDescribe(&typinf->cols[i], con, 00390 NULL, parmh2, i + 1, ptype); 00391 00392 res = res && OCI_ColumnMap(&typinf->cols[i], NULL); 00393 00394 if (res == FALSE) 00395 { 00396 break; 00397 } 00398 } 00399 } 00400 else 00401 { 00402 res = FALSE; 00403 } 00404 } 00405 00406 /* free describe handle */ 00407 00408 if (dschp != NULL) 00409 { 00410 OCI_HandleFree(dschp, OCI_HTYPE_DESCRIBE); 00411 } 00412 } 00413 } 00414 00415 /* handle errors */ 00416 00417 if (res == FALSE) 00418 { 00419 OCI_TypeInfoFree(typinf); 00420 typinf = NULL; 00421 } 00422 00423 OCI_RESULT(res); 00424 00425 /* increment type info reference counter on success */ 00426 00427 if (typinf != NULL) 00428 { 00429 typinf->refcount++; 00430 } 00431 00432 return typinf; 00433 } 00434 00435 /* --------------------------------------------------------------------------------------------- * 00436 * OCI_TypeInfoFree 00437 * --------------------------------------------------------------------------------------------- */ 00438 00439 boolean OCI_API OCI_TypeInfoFree 00440 ( 00441 OCI_TypeInfo *typinf 00442 ) 00443 { 00444 boolean res = TRUE; 00445 00446 OCI_CHECK_PTR(OCI_IPC_TYPE_INFO, typinf, FALSE); 00447 00448 typinf->refcount--; 00449 00450 if (typinf->refcount == 0) 00451 { 00452 OCI_ListRemove(typinf->con->tinfs, typinf); 00453 00454 res = OCI_TypeInfoClose(typinf); 00455 00456 OCI_FREE(typinf); 00457 } 00458 00459 OCI_RESULT(res); 00460 00461 return res; 00462 } 00463 00464 /* --------------------------------------------------------------------------------------------- * 00465 * OCI_TypeInfoGetType 00466 * --------------------------------------------------------------------------------------------- */ 00467 00468 unsigned int OCI_API OCI_TypeInfoGetType 00469 ( 00470 OCI_TypeInfo *typinf 00471 ) 00472 { 00473 OCI_CHECK_PTR(OCI_IPC_TYPE_INFO, typinf, OCI_UNKNOWN); 00474 00475 OCI_RESULT(TRUE); 00476 00477 return typinf->type; 00478 } 00479 00480 /* --------------------------------------------------------------------------------------------- * 00481 * OCI_TypeInfoGetColumnCount 00482 * --------------------------------------------------------------------------------------------- */ 00483 00484 unsigned int OCI_API OCI_TypeInfoGetColumnCount 00485 ( 00486 OCI_TypeInfo *typinf 00487 ) 00488 { 00489 OCI_CHECK_PTR(OCI_IPC_TYPE_INFO, typinf, 0); 00490 00491 OCI_RESULT(TRUE); 00492 00493 return typinf->nb_cols; 00494 } 00495 00496 /* --------------------------------------------------------------------------------------------- * 00497 * OCI_TypeInfoGetColumn 00498 * --------------------------------------------------------------------------------------------- */ 00499 00500 OCI_Column * OCI_API OCI_TypeInfoGetColumn 00501 ( 00502 OCI_TypeInfo *typinf, 00503 unsigned int index 00504 ) 00505 { 00506 OCI_CHECK_PTR(OCI_IPC_TYPE_INFO, typinf, NULL); 00507 OCI_CHECK_BOUND(typinf->con, index, 1, typinf->nb_cols, NULL); 00508 00509 OCI_RESULT(TRUE); 00510 00511 return &(typinf->cols[index-1]); 00512 } 00513 00514 /* --------------------------------------------------------------------------------------------- * 00515 * OCI_TypeInfoGetName 00516 * --------------------------------------------------------------------------------------------- */ 00517 00518 const mtext * OCI_API OCI_TypeInfoGetName 00519 ( 00520 OCI_TypeInfo *typinf 00521 ) 00522 { 00523 OCI_CHECK_PTR(OCI_IPC_TYPE_INFO, typinf, NULL); 00524 00525 OCI_RESULT(TRUE); 00526 00527 return typinf->name; 00528 }