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: typeinfo.c, 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_TypeInfo *syn_typinf = NULL; 00084 OCI_Item *item = NULL; 00085 OCIDescribe *dschp = NULL; 00086 OCIParam *parmh1 = NULL; 00087 OCIParam *parmh2 = NULL; 00088 mtext *str = NULL; 00089 int ptype = 0; 00090 ub1 desc_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 obj_schema[0] = 0; 00106 obj_name[0] = 0; 00107 00108 /* is the schema provided in the object name ? */ 00109 00110 for (str = (mtext *) name; *str != 0; str++) 00111 { 00112 if (*str == MT('.')) 00113 { 00114 mtsncat(obj_schema, name, str-name); 00115 mtsncat(obj_name, ++str, (size_t) OCI_SIZE_OBJ_NAME); 00116 break; 00117 } 00118 } 00119 00120 /* if the schema is not provided, we just copy the object name */ 00121 00122 if (obj_name[0] == 0) 00123 { 00124 mtsncat(obj_name, name, (size_t) OCI_SIZE_OBJ_NAME); 00125 } 00126 00127 /* type name must be uppercase */ 00128 00129 for (str = obj_name; *str != 0; str++) 00130 { 00131 *str = (mtext) mttoupper(*str); 00132 } 00133 00134 /* schema name must be uppercase */ 00135 00136 for (str = obj_schema; *str != 0; str++) 00137 { 00138 *str = (mtext) mttoupper(*str); 00139 } 00140 00141 /* first try to find it in list */ 00142 00143 item = con->tinfs->head; 00144 00145 /* walk along the list to find the type */ 00146 00147 while (item != NULL) 00148 { 00149 typinf = (OCI_TypeInfo *) item->data; 00150 00151 if ((typinf != NULL) && (typinf->type == type)) 00152 { 00153 if ((mtscasecmp(typinf->name, obj_name ) == 0) && 00154 (mtscasecmp(typinf->schema, obj_schema) == 0)) 00155 { 00156 found = TRUE; 00157 break; 00158 } 00159 } 00160 00161 item = item->next; 00162 } 00163 00164 /* Not found, so create type object */ 00165 00166 if (found == FALSE) 00167 { 00168 item = OCI_ListAppend(con->tinfs, sizeof(OCI_TypeInfo)); 00169 00170 res = (item != NULL); 00171 00172 /* allocate describe handle */ 00173 00174 if (res == TRUE) 00175 { 00176 typinf = (OCI_TypeInfo *) item->data; 00177 00178 typinf->type = type; 00179 typinf->con = con; 00180 typinf->name = mtsdup(obj_name); 00181 typinf->schema = mtsdup(obj_schema); 00182 typinf->struct_size = 0; 00183 00184 res = (OCI_SUCCESS == OCI_HandleAlloc(typinf->con->env, 00185 (dvoid **) (void *) &dschp, 00186 OCI_HTYPE_DESCRIBE, (size_t) 0, 00187 (dvoid **) NULL)); 00188 } 00189 00190 /* perfom describe */ 00191 00192 if (res == TRUE) 00193 { 00194 mtext buffer[(OCI_SIZE_OBJ_NAME*2) + 2] = MT(""); 00195 00196 size_t size = sizeof(buffer)/sizeof(mtext); 00197 void *ostr1 = NULL; 00198 int osize1 = -1; 00199 sb4 pbsp = 1; 00200 00201 str = buffer; 00202 00203 /* compute full object name */ 00204 00205 if ((typinf->schema != NULL) && (typinf->schema[0] != 0)) 00206 { 00207 str = mtsncat(buffer, typinf->schema, size); 00208 size -= mtslen(typinf->schema); 00209 str = mtsncat(str, MT("."), size); 00210 size -= (size_t) 1; 00211 } 00212 00213 mtsncat(str, typinf->name, size); 00214 00215 ostr1 = OCI_GetInputMetaString(str, &osize1); 00216 00217 /* set public scope to include synonyms */ 00218 00219 OCI_CALL2 00220 ( 00221 res, con, 00222 00223 OCIAttrSet(dschp, OCI_HTYPE_DESCRIBE, &pbsp, (ub4) sizeof(pbsp), 00224 OCI_ATTR_DESC_PUBLIC, con->err) 00225 ) 00226 00227 /* describe call */ 00228 00229 OCI_CALL2 00230 ( 00231 res, con, 00232 00233 OCIDescribeAny(con->cxt, con->err, (dvoid *) ostr1, 00234 (ub4) osize1, OCI_OTYPE_NAME, 00235 OCI_DEFAULT, OCI_PTYPE_UNK, dschp) 00236 ) 00237 00238 OCI_ReleaseMetaString(ostr1); 00239 00240 /* get parameter handle */ 00241 00242 OCI_CALL2 00243 ( 00244 res, con, 00245 00246 OCIAttrGet(dschp, OCI_HTYPE_DESCRIBE, &parmh1, 00247 NULL, OCI_ATTR_PARAM, con->err) 00248 ) 00249 00250 /* get object type */ 00251 00252 OCI_CALL2 00253 ( 00254 res, con, 00255 00256 OCIAttrGet(parmh1, OCI_DTYPE_PARAM, &desc_type, 00257 NULL, OCI_ATTR_PTYPE, con->err) 00258 ) 00259 } 00260 00261 /* on sucessfull describe call, retrieve all information about the object 00262 if it is not a synonym */ 00263 00264 if (res == TRUE) 00265 { 00266 switch (desc_type) 00267 { 00268 case OCI_PTYPE_TYPE: 00269 { 00270 if (typinf->type != OCI_UNKNOWN) 00271 { 00272 res = (typinf->type == OCI_TIF_TYPE); 00273 00274 } 00275 00276 typinf->type = OCI_TIF_TYPE; 00277 00278 if (res == TRUE) 00279 { 00280 boolean pdt = FALSE; 00281 void *ostr1 = NULL; 00282 void *ostr2 = NULL; 00283 int osize1 = -1; 00284 int osize2 = -1; 00285 00286 attr_type = OCI_ATTR_LIST_TYPE_ATTRS; 00287 num_type = OCI_ATTR_NUM_TYPE_ATTRS; 00288 ptype = OCI_DESC_TYPE; 00289 00290 /* get the object tdo */ 00291 00292 ostr1 = OCI_GetInputMetaString(typinf->schema, &osize1); 00293 ostr2 = OCI_GetInputMetaString(typinf->name, &osize2); 00294 00295 OCI_CALL2 00296 ( 00297 res, con, 00298 00299 OCITypeByName(typinf->con->env, con->err, con->cxt, 00300 (text *) ostr1, (ub4) osize1, 00301 (text *) ostr2, (ub4) osize2, 00302 (text *) NULL, (ub4) 0, 00303 OCI_DURATION_SESSION, OCI_TYPEGET_ALL, 00304 &typinf->tdo) 00305 ) 00306 00307 OCI_ReleaseMetaString(ostr1); 00308 OCI_ReleaseMetaString(ostr2); 00309 00310 /* check if it's system predefined type if order to avoid the next call 00311 that is not allowed on system types */ 00312 00313 OCI_CALL2 00314 ( 00315 res, con, 00316 00317 OCIAttrGet(parmh1, OCI_DTYPE_PARAM, &pdt, 00318 NULL, OCI_ATTR_IS_PREDEFINED_TYPE, con->err) 00319 ) 00320 00321 if (pdt == FALSE) 00322 { 00323 OCI_CALL2 00324 ( 00325 res, con, 00326 00327 OCIAttrGet(parmh1, OCI_DTYPE_PARAM, &typinf->tcode, 00328 NULL, OCI_ATTR_TYPECODE, con->err) 00329 ) 00330 } 00331 00332 } 00333 00334 break; 00335 } 00336 case OCI_PTYPE_TABLE: 00337 case OCI_PTYPE_VIEW: 00338 #if OCI_VERSION_COMPILE >= OCI_10_1 00339 case OCI_PTYPE_TABLE_ALIAS: 00340 #endif 00341 { 00342 if (typinf->type != OCI_UNKNOWN) 00343 { 00344 res = (((typinf->type == OCI_TIF_TABLE) && (desc_type != OCI_PTYPE_VIEW)) || 00345 ((typinf->type == OCI_TIF_VIEW ) && (desc_type == OCI_PTYPE_VIEW))); 00346 } 00347 00348 typinf->type = (desc_type == OCI_PTYPE_VIEW ? OCI_TIF_VIEW : OCI_TIF_TABLE); 00349 00350 if (res == TRUE) 00351 { 00352 attr_type = OCI_ATTR_LIST_COLUMNS; 00353 num_type = OCI_ATTR_NUM_COLS; 00354 ptype = OCI_DESC_TABLE; 00355 } 00356 00357 break; 00358 } 00359 case OCI_PTYPE_SYN: 00360 { 00361 mtext *syn_schema_name = NULL; 00362 mtext *syn_object_name = NULL; 00363 mtext *syn_link_name = NULL; 00364 00365 mtext syn_fullname[(OCI_SIZE_OBJ_NAME*3) + 3] = MT(""); 00366 00367 /* get link schema, object and databaselink names */ 00368 00369 res = res && OCI_StringGetFromAttrHandle (con, parmh1, OCI_DTYPE_PARAM, 00370 OCI_ATTR_SCHEMA_NAME, 00371 &syn_schema_name); 00372 00373 res = res && OCI_StringGetFromAttrHandle (con, parmh1, OCI_DTYPE_PARAM, 00374 OCI_ATTR_NAME, 00375 &syn_object_name); 00376 00377 res = res && OCI_StringGetFromAttrHandle (con, parmh1, OCI_DTYPE_PARAM, 00378 OCI_ATTR_LINK, &syn_link_name); 00379 00380 /* compute link full name */ 00381 00382 if ((syn_schema_name != NULL) && (syn_schema_name[0] != 0)) 00383 { 00384 mtsncat(syn_fullname, syn_schema_name, (size_t) OCI_SIZE_OBJ_NAME); 00385 mtsncat(syn_fullname, MT("."), 1); 00386 } 00387 00388 if ((syn_object_name != NULL) && (syn_object_name[0] != 0)) 00389 { 00390 mtsncat(syn_fullname, syn_object_name, (size_t) OCI_SIZE_OBJ_NAME); 00391 } 00392 00393 if ((syn_link_name != NULL) && (syn_link_name[0] != 0)) 00394 { 00395 mtsncat(syn_fullname, MT("@"), 1); 00396 mtsncat(syn_fullname, syn_link_name, (size_t) OCI_SIZE_OBJ_NAME); 00397 } 00398 00399 /* retrieve the type info of the real object */ 00400 00401 syn_typinf = OCI_TypeInfoGet (con, syn_fullname, typinf->type); 00402 00403 /* free temporay strings */ 00404 00405 OCI_MemFree (syn_link_name); 00406 OCI_MemFree (syn_object_name); 00407 OCI_MemFree (syn_schema_name); 00408 00409 /* do we have a valid object ? */ 00410 00411 res = (syn_typinf != NULL); 00412 00413 break; 00414 } 00415 } 00416 00417 /* did we handle a supported object other than a synonym */ 00418 00419 if ((res == TRUE) && (ptype != 0)) 00420 { 00421 /* do we need get more attributes for collections ? */ 00422 00423 if (typinf->tcode == SQLT_NCO) 00424 { 00425 typinf->nb_cols = 1; 00426 00427 ptype = OCI_DESC_COLLECTION; 00428 parmh2 = parmh1; 00429 00430 OCI_CALL2 00431 ( 00432 res, con, 00433 00434 OCIAttrGet(parmh1, OCI_DTYPE_PARAM, &typinf->ccode, 00435 NULL, OCI_ATTR_COLLECTION_TYPECODE, con->err) 00436 ) 00437 } 00438 else 00439 { 00440 OCI_CALL2 00441 ( 00442 res, con, 00443 00444 OCIAttrGet(parmh1, OCI_DTYPE_PARAM, &parmh2, 00445 NULL, attr_type, con->err) 00446 ) 00447 00448 OCI_CALL2 00449 ( 00450 res, con, 00451 00452 OCIAttrGet(parmh1, OCI_DTYPE_PARAM, &typinf->nb_cols, 00453 NULL, num_type, con->err) 00454 ) 00455 } 00456 00457 /* allocates memory for cached offsets */ 00458 00459 if (typinf->nb_cols > 0) 00460 { 00461 typinf->offsets = (int *) OCI_MemAlloc(OCI_IPC_ARRAY, 00462 sizeof(*typinf->offsets), 00463 (size_t) typinf->nb_cols, 00464 FALSE); 00465 00466 res = (typinf->offsets != NULL); 00467 00468 if (res == TRUE) 00469 { 00470 memset(typinf->offsets, -1, sizeof(*typinf->offsets) * typinf->nb_cols); 00471 } 00472 } 00473 00474 /* allocates memory for children */ 00475 00476 if (typinf->nb_cols > 0) 00477 { 00478 typinf->cols = (OCI_Column *) OCI_MemAlloc(OCI_IPC_COLUMN, sizeof(*typinf->cols), 00479 (size_t) typinf->nb_cols, TRUE); 00480 00481 /* describe children */ 00482 00483 if (typinf->cols != NULL) 00484 { 00485 for (i = 0; i < typinf->nb_cols; i++) 00486 { 00487 res = res && OCI_ColumnDescribe(&typinf->cols[i], con, 00488 NULL, parmh2, i + 1, ptype); 00489 00490 res = res && OCI_ColumnMap(&typinf->cols[i], NULL); 00491 00492 if (res == FALSE) 00493 { 00494 break; 00495 } 00496 } 00497 } 00498 else 00499 { 00500 res = FALSE; 00501 } 00502 } 00503 } 00504 } 00505 } 00506 00507 /* free describe handle */ 00508 00509 if (dschp != NULL) 00510 { 00511 OCI_HandleFree(dschp, OCI_HTYPE_DESCRIBE); 00512 } 00513 00514 /* increment type info reference counter on success */ 00515 00516 if (typinf != NULL) 00517 { 00518 typinf->refcount++; 00519 00520 /* type checking sanity checks */ 00521 00522 if ((type != OCI_UNKNOWN) && (typinf->type != type)) 00523 { 00524 OCI_ExceptionTypeInfoWrongType(con, name); 00525 00526 res = FALSE; 00527 } 00528 } 00529 00530 /* handle errors */ 00531 00532 if ((res == FALSE) || (syn_typinf != NULL)) 00533 { 00534 OCI_TypeInfoFree(typinf); 00535 typinf = NULL; 00536 } 00537 00538 OCI_RESULT(res); 00539 00540 return syn_typinf ? syn_typinf : typinf; 00541 } 00542 00543 /* --------------------------------------------------------------------------------------------- * 00544 * OCI_TypeInfoFree 00545 * --------------------------------------------------------------------------------------------- */ 00546 00547 boolean OCI_API OCI_TypeInfoFree 00548 ( 00549 OCI_TypeInfo *typinf 00550 ) 00551 { 00552 boolean res = TRUE; 00553 00554 OCI_CHECK_PTR(OCI_IPC_TYPE_INFO, typinf, FALSE); 00555 00556 typinf->refcount--; 00557 00558 if (typinf->refcount == 0) 00559 { 00560 OCI_ListRemove(typinf->con->tinfs, typinf); 00561 00562 res = OCI_TypeInfoClose(typinf); 00563 00564 OCI_FREE(typinf); 00565 } 00566 00567 OCI_RESULT(res); 00568 00569 return res; 00570 } 00571 00572 /* --------------------------------------------------------------------------------------------- * 00573 * OCI_TypeInfoGetType 00574 * --------------------------------------------------------------------------------------------- */ 00575 00576 unsigned int OCI_API OCI_TypeInfoGetType 00577 ( 00578 OCI_TypeInfo *typinf 00579 ) 00580 { 00581 OCI_CHECK_PTR(OCI_IPC_TYPE_INFO, typinf, OCI_UNKNOWN); 00582 00583 OCI_RESULT(TRUE); 00584 00585 return typinf->type; 00586 } 00587 00588 /* --------------------------------------------------------------------------------------------- * 00589 * OCI_TypeInfoGetColumnCount 00590 * --------------------------------------------------------------------------------------------- */ 00591 00592 unsigned int OCI_API OCI_TypeInfoGetColumnCount 00593 ( 00594 OCI_TypeInfo *typinf 00595 ) 00596 { 00597 OCI_CHECK_PTR(OCI_IPC_TYPE_INFO, typinf, 0); 00598 00599 OCI_RESULT(TRUE); 00600 00601 return typinf->nb_cols; 00602 } 00603 00604 /* --------------------------------------------------------------------------------------------- * 00605 * OCI_TypeInfoGetColumn 00606 * --------------------------------------------------------------------------------------------- */ 00607 00608 OCI_Column * OCI_API OCI_TypeInfoGetColumn 00609 ( 00610 OCI_TypeInfo *typinf, 00611 unsigned int index 00612 ) 00613 { 00614 OCI_CHECK_PTR(OCI_IPC_TYPE_INFO, typinf, NULL); 00615 OCI_CHECK_BOUND(typinf->con, index, 1, typinf->nb_cols, NULL); 00616 00617 OCI_RESULT(TRUE); 00618 00619 return &(typinf->cols[index-1]); 00620 } 00621 00622 /* --------------------------------------------------------------------------------------------- * 00623 * OCI_TypeInfoGetName 00624 * --------------------------------------------------------------------------------------------- */ 00625 00626 const mtext * OCI_API OCI_TypeInfoGetName 00627 ( 00628 OCI_TypeInfo *typinf 00629 ) 00630 { 00631 OCI_CHECK_PTR(OCI_IPC_TYPE_INFO, typinf, NULL); 00632 00633 OCI_RESULT(TRUE); 00634 00635 return typinf->name; 00636 }