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: column.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_ColumnDescribe 00043 * --------------------------------------------------------------------------------------------- */ 00044 00045 boolean OCI_ColumnDescribe 00046 ( 00047 OCI_Column *col, 00048 OCI_Connection *con, 00049 OCI_Statement *stmt, 00050 void *handle, 00051 int index, 00052 int ptype 00053 ) 00054 { 00055 void *param = NULL; 00056 boolean res = TRUE; 00057 ub4 htype = 0; 00058 00059 /* get descriptor */ 00060 00061 if (ptype == OCI_DESC_COLLECTION) 00062 { 00063 OCI_CALL1 00064 ( 00065 res, con, stmt, 00066 00067 OCIAttrGet((dvoid *) handle, (ub4) OCI_DTYPE_PARAM, (dvoid *) ¶m, 00068 (ub4 *) NULL, (ub4) OCI_ATTR_COLLECTION_ELEMENT, con->err) 00069 ) 00070 } 00071 else 00072 { 00073 if (ptype == OCI_DESC_RESULTSET) 00074 { 00075 htype = OCI_HTYPE_STMT; 00076 } 00077 else 00078 { 00079 htype = OCI_DTYPE_PARAM; 00080 } 00081 00082 OCI_CALL1 00083 ( 00084 res, con, stmt, 00085 00086 OCIParamGet((dvoid *) handle, htype, con->err, (void**) ¶m, (ub4) index) 00087 ) 00088 } 00089 00090 /* sql code */ 00091 00092 OCI_CALL1 00093 ( 00094 res, con, stmt, 00095 00096 OCIAttrGet((dvoid *) param, (ub4) OCI_DTYPE_PARAM, (dvoid *) &col->ocode, 00097 (ub4 *) NULL, (ub4) OCI_ATTR_DATA_TYPE, con->err) 00098 ) 00099 00100 /* size */ 00101 00102 OCI_CALL1 00103 ( 00104 res, con, stmt, 00105 00106 OCIAttrGet((dvoid *) param, (ub4) OCI_DTYPE_PARAM, (dvoid *) &col->size, 00107 (ub4 *) NULL, (ub4) OCI_ATTR_DATA_SIZE, con->err) 00108 ) 00109 00110 /* scale */ 00111 00112 OCI_CALL1 00113 ( 00114 res, con, stmt, 00115 00116 OCIAttrGet((dvoid *) param, (ub4) OCI_DTYPE_PARAM, (dvoid *) &col->scale, 00117 (ub4 *) NULL, (ub4) OCI_ATTR_SCALE, con->err) 00118 ) 00119 00120 /* precision */ 00121 00122 if (ptype == OCI_DESC_RESULTSET) 00123 { 00124 sb2 prec = 0; 00125 00126 OCI_CALL1 00127 ( 00128 res, con, stmt, 00129 00130 OCIAttrGet((dvoid *) param, (ub4) OCI_DTYPE_PARAM, (dvoid *) &prec, 00131 (ub4 *) NULL, (ub4) OCI_ATTR_PRECISION, con->err) 00132 ) 00133 00134 col->prec = (sb2) prec; 00135 } 00136 else 00137 { 00138 ub1 prec = 0; 00139 00140 OCI_CALL1 00141 ( 00142 res, con, stmt, 00143 00144 OCIAttrGet((dvoid *) param, (ub4) OCI_DTYPE_PARAM, (dvoid *) &prec, 00145 (ub4 *) NULL, (ub4) OCI_ATTR_PRECISION, con->err) 00146 ) 00147 00148 col->prec = (sb2) prec; 00149 } 00150 00151 /* charset form */ 00152 00153 OCI_CALL1 00154 ( 00155 res, con, stmt, 00156 00157 OCIAttrGet((dvoid *) param, (ub4) OCI_DTYPE_PARAM, (dvoid *) &col->csfrm, 00158 (ub4 *) NULL, (ub4) OCI_ATTR_CHARSET_FORM, con->err) 00159 ) 00160 00161 /* type of column length for string based column */ 00162 00163 #if OCI_VERSION_COMPILE >= OCI_9_0 00164 00165 if ((OCILib.version_runtime >= OCI_9_0) && (con->ver_num >= OCI_9_0)) 00166 { 00167 /* char used - no error checking because on Oracle 9.0, querying 00168 this param that is not char/varchar based will cause an 00169 error */ 00170 00171 OCI_CALL1 00172 ( 00173 res, con, stmt, 00174 00175 OCIAttrGet((dvoid *) param, (ub4) OCI_DTYPE_PARAM, 00176 (dvoid *) &col->charused, (ub4 *) NULL, 00177 (ub4) OCI_ATTR_CHAR_USED, con->err) 00178 ) 00179 } 00180 00181 /* char size */ 00182 00183 if (col->charused == TRUE) 00184 { 00185 OCI_CALL1 00186 ( 00187 res, con, stmt, 00188 00189 OCIAttrGet((dvoid *) param, (ub4) OCI_DTYPE_PARAM, 00190 (dvoid *) &col->charsize, (ub4 *) NULL, 00191 (ub4) OCI_ATTR_CHAR_SIZE, con->err) 00192 ) 00193 } 00194 00195 if ((OCILib.version_runtime >= OCI_9_0) && (con->ver_num >= OCI_9_0)) 00196 { 00197 /* fractional time precision for timestamps */ 00198 00199 if (col->ocode == SQLT_TIMESTAMP || 00200 col->ocode == SQLT_TIMESTAMP_TZ || 00201 col->ocode == SQLT_TIMESTAMP_LTZ) 00202 { 00203 OCI_CALL1 00204 ( 00205 res, con, stmt, 00206 00207 OCIAttrGet((dvoid *) param, (ub4) OCI_DTYPE_PARAM, 00208 (dvoid *) &col->prec, (ub4 *) NULL, 00209 (ub4) OCI_ATTR_FSPRECISION, con->err) 00210 ) 00211 } 00212 00213 /* leading and fractional precision for interval */ 00214 00215 if (col->ocode == SQLT_INTERVAL_DS || col->ocode == SQLT_INTERVAL_YM) 00216 { 00217 OCI_CALL1 00218 ( 00219 res, con, stmt, 00220 00221 OCIAttrGet((dvoid *) param, (ub4) OCI_DTYPE_PARAM, 00222 (dvoid *) &col->prec, (ub4 *) NULL, 00223 (ub4) OCI_ATTR_LFPRECISION, con->err) 00224 ) 00225 00226 OCI_CALL1 00227 ( 00228 res, con, stmt, 00229 00230 OCIAttrGet((dvoid *) param, (ub4) OCI_DTYPE_PARAM, 00231 (dvoid *) &col->prec2, (ub4 *) NULL, 00232 (ub4) OCI_ATTR_FSPRECISION, con->err) 00233 ) 00234 } 00235 } 00236 00237 #endif 00238 00239 /* check nullable only for table based column */ 00240 00241 if (ptype < OCI_DESC_TYPE) 00242 { 00243 OCI_CALL1 00244 ( 00245 res, con, stmt, 00246 00247 OCIAttrGet((dvoid *) param, (ub4) OCI_DTYPE_PARAM, 00248 (dvoid *) &col->null, (ub4 *) NULL, 00249 (ub4) OCI_ATTR_IS_NULL, con->err) 00250 ) 00251 } 00252 else 00253 { 00254 col->null = TRUE; 00255 } 00256 00257 /* name */ 00258 00259 if (res == TRUE) 00260 { 00261 void *ostr = NULL; 00262 int osize = 0; 00263 ub4 attrname = 0; 00264 00265 if (ptype == OCI_DESC_COLLECTION) 00266 { 00267 attrname = OCI_ATTR_TYPE_NAME; 00268 } 00269 else 00270 { 00271 attrname = OCI_ATTR_NAME; 00272 } 00273 00274 OCI_CALL1 00275 ( 00276 res, con, stmt, 00277 00278 OCIAttrGet((dvoid *) param, (ub4) OCI_DTYPE_PARAM, (dvoid *) &ostr, 00279 (ub4 *) &osize, (ub4) attrname, con->err) 00280 ) 00281 00282 if ((res == TRUE) && (ostr != NULL)) 00283 { 00284 col->name = (mtext *) OCI_MemAlloc(OCI_IPC_STRING, sizeof(mtext), 00285 (size_t) ((osize / (int) sizeof(omtext)) + 1), TRUE); 00286 00287 if (col->name != NULL) 00288 { 00289 OCI_CopyString(ostr, col->name, &osize, sizeof(omtext), sizeof(mtext)); 00290 } 00291 else 00292 { 00293 res = FALSE; 00294 } 00295 } 00296 } 00297 00298 /* user type descriptor */ 00299 00300 if (col->ocode == SQLT_NTY || col->ocode == SQLT_REF) 00301 { 00302 void *ostr_name = NULL; 00303 void *ostr_schema = NULL; 00304 int osize_name = 0; 00305 int osize_schema = 0; 00306 00307 OCI_CALL1 00308 ( 00309 res, con, stmt, 00310 00311 OCIAttrGet((dvoid *) param, (ub4) OCI_DTYPE_PARAM, 00312 (dvoid *) &ostr_name, (ub4 *) &osize_name, 00313 (ub4) OCI_ATTR_TYPE_NAME, con->err) 00314 ) 00315 00316 OCI_CALL1 00317 ( 00318 res, con, stmt, 00319 00320 OCIAttrGet((dvoid *) param, (ub4) OCI_DTYPE_PARAM, 00321 (dvoid *) &ostr_schema, (ub4 *) &osize_schema, 00322 (ub4) OCI_ATTR_SCHEMA_NAME, con->err) 00323 ) 00324 00325 if (res == TRUE) 00326 { 00327 mtext type_name[(OCI_SIZE_OBJ_NAME * 2) + 2] = MT(""); 00328 00329 if ((ostr_schema != NULL) && (osize_schema > 0)) 00330 { 00331 OCI_CopyString(ostr_schema, type_name, &osize_schema, sizeof(omtext), sizeof(mtext)); 00332 00333 mtscat(type_name, MT(".")); 00334 } 00335 00336 OCI_CopyString(ostr_name, type_name + mtextsize(type_name), &osize_name, 00337 sizeof(omtext), sizeof(mtext)); 00338 00339 col->typinf = OCI_TypeInfoGet(con, type_name, OCI_TIF_TYPE); 00340 00341 res = (col->typinf != NULL); 00342 } 00343 } 00344 00345 if (param != NULL) 00346 { 00347 res = (OCI_SUCCESS == OCIDescriptorFree(param, OCI_DTYPE_PARAM)); 00348 } 00349 00350 return res; 00351 } 00352 00353 /* --------------------------------------------------------------------------------------------- * 00354 * OCI_ColumnMap 00355 * --------------------------------------------------------------------------------------------- */ 00356 00357 boolean OCI_ColumnMap 00358 ( 00359 OCI_Column *col, 00360 OCI_Statement *stmt 00361 ) 00362 { 00363 boolean res = TRUE; 00364 00365 OCI_CHECK(col == NULL, FALSE); 00366 00367 /* map Oracle SQL code to OCILIB types and setup of internal buffer size */ 00368 00369 col->icode = col->ocode; 00370 00371 switch (col->icode) 00372 { 00373 case SQLT_INT: 00374 { 00375 col->type = OCI_CDT_NUMERIC; 00376 00377 /* set bufsize only if it's not a "returning into" placeholder */ 00378 00379 if (col->bufsize == 0) 00380 { 00381 col->subtype = OCI_NUM_INT; 00382 col->bufsize = sizeof(int); 00383 } 00384 00385 break; 00386 } 00387 case SQLT_UIN: 00388 { 00389 col->type = OCI_CDT_NUMERIC; 00390 00391 /* set bufsize only if it's not a "returning into" placeholder */ 00392 00393 if (col->bufsize == 0) 00394 { 00395 col->subtype = OCI_NUM_UINT; 00396 col->bufsize = sizeof(unsigned int); 00397 } 00398 00399 break; 00400 } 00401 case SQLT_FLT: 00402 case SQLT_VNU: 00403 case SQLT_PDN: 00404 case SQLT_NUM: 00405 00406 #if OCI_VERSION_COMPILE >= OCI_10_1 00407 00408 case SQLT_BFLOAT: 00409 case SQLT_BDOUBLE: 00410 case SQLT_IBFLOAT: 00411 case SQLT_IBDOUBLE: 00412 00413 #endif 00414 00415 { 00416 col->type = OCI_CDT_NUMERIC; 00417 col->subtype = OCI_NUM_NUMBER; 00418 col->icode = SQLT_VNU; 00419 col->bufsize = sizeof(OCINumber); 00420 00421 break; 00422 } 00423 case SQLT_DAT: 00424 case SQLT_ODT: 00425 { 00426 col->type = OCI_CDT_DATETIME; 00427 00428 /* We map to SQLT_ODT only it the column is not part of a 00429 "returning into" clause (workaround for Oracle 00430 known bug #3269146 00431 */ 00432 00433 if (col->bufsize == 0) 00434 { 00435 col->icode = SQLT_ODT; 00436 col->bufsize = sizeof(OCIDate); 00437 } 00438 00439 break; 00440 } 00441 case SQLT_CUR: 00442 case SQLT_RSET: 00443 { 00444 col->type = OCI_CDT_CURSOR; 00445 col->bufsize = sizeof(OCIStmt *); 00446 col->dtype = OCI_HTYPE_STMT; 00447 00448 break; 00449 } 00450 case SQLT_RID: 00451 case SQLT_RDD: 00452 { 00453 col->icode = SQLT_STR; 00454 col->type = OCI_CDT_TEXT; 00455 00456 if ((col->ocode == SQLT_RDD) || (col->size > sizeof(OCIRowid *))) 00457 { 00458 /* For Oracle 7 ROWIDs and regular ROWID descriptors, the 00459 max size of the hex value is defined by the constant 00460 OCI_SIZE_ROWID 00461 */ 00462 00463 col->bufsize = (OCI_SIZE_ROWID + 1) * (ub4) sizeof(dtext); 00464 } 00465 else 00466 { 00467 /* For ROWID descriptor, if column size is bigger than the size 00468 of the descriptor, it means that an UROWID column and then 00469 the column size is the maximum size needed for representing 00470 its value as an hex string 00471 */ 00472 00473 col->bufsize = (ub4) ((col->size + 1) * (ub2) sizeof(dtext)); 00474 } 00475 00476 if (OCILib.nls_utf8 == TRUE) 00477 { 00478 col->bufsize *= UTF8_BYTES_PER_CHAR; 00479 } 00480 00481 break; 00482 } 00483 case SQLT_BIN: 00484 { 00485 /* adding one extra character space for string conversion */ 00486 00487 col->type = OCI_CDT_RAW; 00488 col->bufsize = (ub4) (col->size + (ub2) sizeof(dtext)); 00489 00490 break; 00491 } 00492 case SQLT_BLOB: 00493 { 00494 col->type = OCI_CDT_LOB; 00495 col->subtype = OCI_BLOB; 00496 col->dtype = OCI_DTYPE_LOB; 00497 col->bufsize = (ub4) sizeof(OCILobLocator *); 00498 00499 break; 00500 } 00501 case SQLT_CLOB: 00502 { 00503 col->type = OCI_CDT_LOB; 00504 col->dtype = OCI_DTYPE_LOB; 00505 col->bufsize = (ub4) sizeof(OCILobLocator *); 00506 00507 if (col->csfrm == SQLCS_NCHAR) 00508 { 00509 col->subtype = OCI_NCLOB; 00510 } 00511 else 00512 { 00513 col->subtype = OCI_CLOB; 00514 } 00515 00516 break; 00517 } 00518 case SQLT_BFILE: 00519 { 00520 col->type = OCI_CDT_FILE; 00521 col->subtype = OCI_BFILE; 00522 col->dtype = OCI_DTYPE_LOB; 00523 col->bufsize = (ub4) sizeof(OCILobLocator *); 00524 00525 break; 00526 } 00527 case SQLT_CFILE: 00528 { 00529 col->type = OCI_CDT_FILE; 00530 col->subtype = OCI_CFILE; 00531 col->bufsize = (ub4) sizeof(OCILobLocator *); 00532 col->dtype = OCI_DTYPE_LOB; 00533 00534 break; 00535 } 00536 case SQLT_LNG: 00537 case SQLT_LVC: 00538 case SQLT_LBI: 00539 case SQLT_LVB: 00540 case SQLT_VBI: 00541 { 00542 if ((col->icode == SQLT_LNG || col->icode == SQLT_LVC) && 00543 (stmt != NULL && stmt->long_mode == OCI_LONG_IMPLICIT)) 00544 { 00545 col->type = OCI_CDT_TEXT; 00546 col->bufsize = (OCI_SIZE_LONG+1) * ((ub2) sizeof(dtext)); 00547 col->subtype = OCI_CLONG; 00548 00549 if (OCILib.nls_utf8 == TRUE) 00550 { 00551 col->bufsize *= UTF8_BYTES_PER_CHAR; 00552 } 00553 } 00554 else 00555 { 00556 col->type = OCI_CDT_LONG; 00557 col->bufsize = INT_MAX; 00558 00559 if (col->icode == SQLT_LBI || 00560 col->icode == SQLT_LVB || 00561 col->icode == SQLT_VBI) 00562 { 00563 col->subtype = OCI_BLONG; 00564 } 00565 else 00566 { 00567 col->subtype = OCI_CLONG; 00568 } 00569 00570 } 00571 00572 break; 00573 } 00574 00575 #if OCI_VERSION_COMPILE >= OCI_9_0 00576 00577 case SQLT_TIMESTAMP: 00578 { 00579 col->type = OCI_CDT_TIMESTAMP; 00580 col->subtype = OCI_TIMESTAMP; 00581 col->dtype = OCI_DTYPE_TIMESTAMP; 00582 col->bufsize = (ub4) sizeof(OCIDateTime *); 00583 00584 break; 00585 } 00586 case SQLT_TIMESTAMP_TZ: 00587 { 00588 col->type = OCI_CDT_TIMESTAMP; 00589 col->subtype = OCI_TIMESTAMP_TZ; 00590 col->dtype = OCI_DTYPE_TIMESTAMP_TZ; 00591 col->bufsize = (ub4) sizeof(OCIDateTime *); 00592 00593 break; 00594 } 00595 case SQLT_TIMESTAMP_LTZ: 00596 { 00597 col->type = OCI_CDT_TIMESTAMP; 00598 col->subtype = OCI_TIMESTAMP_LTZ; 00599 col->dtype = OCI_DTYPE_TIMESTAMP_LTZ; 00600 col->bufsize = (ub4) sizeof(OCIDateTime *); 00601 00602 break; 00603 } 00604 case SQLT_INTERVAL_YM: 00605 { 00606 col->type = OCI_CDT_INTERVAL; 00607 col->subtype = OCI_INTERVAL_YM; 00608 col->dtype = OCI_DTYPE_INTERVAL_YM; 00609 col->bufsize = (ub4) sizeof(OCIInterval *); 00610 00611 break; 00612 } 00613 case SQLT_INTERVAL_DS: 00614 { 00615 col->type = OCI_CDT_INTERVAL; 00616 col->subtype = OCI_INTERVAL_DS; 00617 col->dtype = OCI_DTYPE_INTERVAL_DS; 00618 col->bufsize = (ub4) sizeof(OCIInterval *); 00619 00620 break; 00621 } 00622 00623 #endif 00624 00625 #if OCI_VERSION_COMPILE >= OCI_9_0 00626 00627 case SQLT_PNTY: 00628 00629 #endif 00630 00631 case SQLT_NTY: 00632 { 00633 col->icode = SQLT_NTY; 00634 col->bufsize = (ub4) sizeof(void *); 00635 00636 if (col->typinf->tcode == SQLT_NCO) 00637 { 00638 col->type = OCI_CDT_COLLECTION; 00639 } 00640 else 00641 { 00642 col->type = OCI_CDT_OBJECT; 00643 } 00644 00645 break; 00646 } 00647 case SQLT_REF: 00648 { 00649 col->icode = SQLT_REF; 00650 col->bufsize = (ub4) sizeof(OCIRef *); 00651 col->type = OCI_CDT_REF; 00652 00653 break; 00654 } 00655 case SQLT_CHR: 00656 case SQLT_STR: 00657 case SQLT_VCS: 00658 case SQLT_AFC: 00659 case SQLT_AVC: 00660 case SQLT_VST: 00661 case SQLT_LAB: 00662 case SQLT_OSL: 00663 case SQLT_SLS: 00664 default: 00665 { 00666 col->icode = SQLT_STR; 00667 col->type = OCI_CDT_TEXT; 00668 col->bufsize = (ub4) ((col->size + 1) * (ub2) sizeof(dtext)); 00669 00670 if (OCILib.nls_utf8 == TRUE) 00671 { 00672 col->bufsize *= UTF8_BYTES_PER_CHAR; 00673 } 00674 00675 break; 00676 } 00677 } 00678 00679 return res; 00680 } 00681 00682 /* ********************************************************************************************* * 00683 * PUBLIC FUNCTIONS 00684 * ********************************************************************************************* */ 00685 00686 /* --------------------------------------------------------------------------------------------- * 00687 * OCI_ColumnGetName 00688 * --------------------------------------------------------------------------------------------- */ 00689 00690 const mtext * OCI_API OCI_ColumnGetName 00691 ( 00692 OCI_Column *col 00693 ) 00694 { 00695 OCI_CHECK_PTR(OCI_IPC_COLUMN, col, NULL); 00696 00697 return col->name; 00698 } 00699 00700 /* --------------------------------------------------------------------------------------------- * 00701 * OCI_ColumnGetType 00702 * --------------------------------------------------------------------------------------------- */ 00703 00704 unsigned int OCI_API OCI_ColumnGetType 00705 ( 00706 OCI_Column *col 00707 ) 00708 { 00709 OCI_CHECK_PTR(OCI_IPC_COLUMN, col, OCI_UNKNOWN); 00710 00711 OCI_RESULT(TRUE); 00712 00713 return col->type; 00714 } 00715 00716 /* --------------------------------------------------------------------------------------------- * 00717 * OCI_ColumnGetCharsetForm 00718 * --------------------------------------------------------------------------------------------- */ 00719 00720 unsigned int OCI_API OCI_ColumnGetCharsetForm 00721 ( 00722 OCI_Column *col 00723 ) 00724 { 00725 OCI_CHECK_PTR(OCI_IPC_COLUMN, col, OCI_CSF_NONE); 00726 00727 OCI_RESULT(TRUE); 00728 00729 if (col->csfrm == SQLCS_NCHAR) 00730 { 00731 return OCI_CSF_NATIONAL; 00732 } 00733 else if (col->csfrm == SQLCS_IMPLICIT) 00734 { 00735 return OCI_CSF_DEFAULT; 00736 } 00737 else 00738 { 00739 return OCI_CSF_NONE; 00740 } 00741 } 00742 00743 /* --------------------------------------------------------------------------------------------- * 00744 * OCI_ColumnGetSize 00745 * --------------------------------------------------------------------------------------------- */ 00746 00747 unsigned int OCI_API OCI_ColumnGetSize 00748 ( 00749 OCI_Column *col 00750 ) 00751 { 00752 OCI_CHECK_PTR(OCI_IPC_COLUMN, col, 0); 00753 00754 OCI_RESULT(TRUE); 00755 00756 /* Oracle 9i introduced CHAR attribute on string columns to indicate the 00757 size of the column is not in bytes (default) but in chars 00758 OCI_ColumnDescribe() already managed the Oracle compatibly 00759 version, so if col->charsize is zero it means : 00760 - the column is not a string column 00761 - the size is not in char 00762 - client does not support the OCI_ATTR_CHAR_SIZE attribute */ 00763 00764 if (col->charused == TRUE && col->charsize > 0) 00765 { 00766 return col->charsize; 00767 } 00768 else 00769 { 00770 return col->size; 00771 } 00772 } 00773 00774 /* --------------------------------------------------------------------------------------------- * 00775 * OCI_ColumnGetScale 00776 * --------------------------------------------------------------------------------------------- */ 00777 00778 int OCI_API OCI_ColumnGetScale 00779 ( 00780 OCI_Column *col 00781 ) 00782 { 00783 OCI_CHECK_PTR(OCI_IPC_COLUMN, col, 0); 00784 00785 OCI_RESULT(TRUE); 00786 00787 return (int) col->scale; 00788 } 00789 00790 /* --------------------------------------------------------------------------------------------- * 00791 * OCI_ColumnGetPrecision 00792 * --------------------------------------------------------------------------------------------- */ 00793 00794 int OCI_API OCI_ColumnGetPrecision 00795 ( 00796 OCI_Column *col 00797 ) 00798 { 00799 OCI_CHECK_PTR(OCI_IPC_COLUMN, col, 0); 00800 00801 OCI_RESULT(TRUE); 00802 00803 if (col->type == OCI_CDT_NUMERIC) 00804 { 00805 return (int) col->prec; 00806 } 00807 else 00808 { 00809 return 0; 00810 } 00811 } 00812 00813 /* --------------------------------------------------------------------------------------------- * 00814 * OCI_ColumnGetFractionalPrecision 00815 * --------------------------------------------------------------------------------------------- */ 00816 00817 int OCI_API OCI_ColumnGetFractionalPrecision 00818 ( 00819 OCI_Column *col 00820 ) 00821 { 00822 OCI_CHECK_PTR(OCI_IPC_COLUMN, col, 0); 00823 00824 OCI_RESULT(TRUE); 00825 00826 if (col->type == OCI_CDT_TIMESTAMP) 00827 { 00828 return (int) col->prec; 00829 } 00830 else if (col->type == OCI_CDT_INTERVAL) 00831 { 00832 return (int) col->prec2; 00833 } 00834 else 00835 { 00836 return 0; 00837 } 00838 } 00839 00840 /* --------------------------------------------------------------------------------------------- * 00841 * OCI_ColumnGetLeadingPrecision 00842 * --------------------------------------------------------------------------------------------- */ 00843 00844 int OCI_API OCI_ColumnGetLeadingPrecision 00845 ( 00846 OCI_Column *col 00847 ) 00848 { 00849 OCI_CHECK_PTR(OCI_IPC_COLUMN, col, 0); 00850 00851 OCI_RESULT(TRUE); 00852 00853 if (col->type == OCI_CDT_INTERVAL) 00854 { 00855 return (int) col->prec; 00856 } 00857 else 00858 { 00859 return 0; 00860 } 00861 } 00862 00863 /* --------------------------------------------------------------------------------------------- * 00864 * OCI_ColumnGetNullable 00865 * --------------------------------------------------------------------------------------------- */ 00866 00867 boolean OCI_API OCI_ColumnGetNullable 00868 ( 00869 OCI_Column *col 00870 ) 00871 { 00872 OCI_CHECK_PTR(OCI_IPC_COLUMN, col, FALSE); 00873 00874 OCI_RESULT(TRUE); 00875 00876 return (col->null == TRUE); 00877 } 00878 00879 /* --------------------------------------------------------------------------------------------- * 00880 * OCI_ColumnGetCharUsed 00881 * --------------------------------------------------------------------------------------------- */ 00882 00883 boolean OCI_API OCI_ColumnGetCharUsed 00884 ( 00885 OCI_Column *col 00886 ) 00887 { 00888 OCI_CHECK_PTR(OCI_IPC_COLUMN, col, FALSE); 00889 00890 OCI_RESULT(TRUE); 00891 00892 return (boolean) col->charused; 00893 } 00894 00895 /* --------------------------------------------------------------------------------------------- * 00896 * OCI_ColumnGetSQLType 00897 * --------------------------------------------------------------------------------------------- */ 00898 00899 const mtext * OCI_API OCI_ColumnGetSQLType 00900 ( 00901 OCI_Column *col 00902 ) 00903 { 00904 OCI_CHECK_PTR(OCI_IPC_COLUMN, col, NULL); 00905 00906 /* VARCHAR type will not be returned because Oracle does not make any 00907 difference with VARCHAR2. If a column is created with VARCHAR, it is 00908 internally created as VARCHAR2 00909 */ 00910 00911 OCI_RESULT(TRUE); 00912 00913 switch(col->ocode) 00914 { 00915 case SQLT_AFC: 00916 { 00917 if (col->csfrm == SQLCS_NCHAR) 00918 { 00919 return MT("NCHAR"); 00920 } 00921 else 00922 { 00923 return MT("CHAR"); 00924 } 00925 } 00926 case SQLT_AVC: 00927 case SQLT_STR: 00928 case SQLT_CHR: 00929 { 00930 if (col->csfrm == SQLCS_NCHAR) 00931 { 00932 return MT("NVARCHAR2"); 00933 } 00934 else 00935 { 00936 return MT("VARCHAR2"); 00937 } 00938 } 00939 case SQLT_NUM: 00940 { 00941 if (col->scale == -127 && col->prec > 0) 00942 { 00943 return MT("FLOAT"); 00944 } 00945 else 00946 { 00947 return MT("NUMBER"); 00948 } 00949 } 00950 case SQLT_INT: 00951 { 00952 return MT("INTEGER"); 00953 } 00954 case SQLT_FLT: 00955 { 00956 return MT("FLOAT"); 00957 } 00958 00959 #if OCI_VERSION_COMPILE >= OCI_10_1 00960 00961 case SQLT_BFLOAT: 00962 case SQLT_IBFLOAT: 00963 { 00964 return MT("BINARY FLOAT"); 00965 } 00966 case SQLT_BDOUBLE: 00967 case SQLT_IBDOUBLE: 00968 { 00969 return MT("BINARY DOUBLE"); 00970 } 00971 00972 #endif 00973 00974 case SQLT_LNG: 00975 { 00976 return MT("LONG"); 00977 } 00978 case SQLT_DAT: 00979 case SQLT_ODT: 00980 case SQLT_DATE: 00981 { 00982 return MT("DATE"); 00983 } 00984 case SQLT_RDD: 00985 case SQLT_RID: 00986 { 00987 return MT("ROWID"); 00988 } 00989 case SQLT_BIN: 00990 { 00991 return MT("RAW"); 00992 } 00993 case SQLT_LBI: 00994 { 00995 return MT("LONG RAW"); 00996 } 00997 case SQLT_RSET: 00998 { 00999 return MT("RESULTSET"); 01000 } 01001 case SQLT_CUR: 01002 { 01003 return MT("CURSOR"); 01004 } 01005 case SQLT_CLOB: 01006 { 01007 if (col->subtype == OCI_NCLOB) 01008 { 01009 return MT("NCLOB"); 01010 } 01011 else 01012 { 01013 return MT("CLOB"); 01014 } 01015 } 01016 case SQLT_BLOB: 01017 { 01018 return MT("BLOB"); 01019 } 01020 case SQLT_BFILE: 01021 { 01022 return MT("BINARY FILE LOB"); 01023 } 01024 case SQLT_CFILE: 01025 { 01026 return MT("CFILE"); 01027 } 01028 01029 #if OCI_VERSION_COMPILE >= OCI_9_0 01030 01031 case SQLT_TIMESTAMP: 01032 { 01033 return MT("TIMESTAMP"); 01034 } 01035 case SQLT_TIMESTAMP_TZ: 01036 { 01037 return MT("TIMESTAMP WITH TIME ZONE"); 01038 } 01039 case SQLT_TIMESTAMP_LTZ: 01040 { 01041 return MT("TIMESTAMP WITH LOCAL TIME ZONE"); 01042 } 01043 case SQLT_INTERVAL_YM: 01044 { 01045 return MT("INTERVAL YEAR TO MONTH"); 01046 } 01047 case SQLT_INTERVAL_DS: 01048 { 01049 return MT("INTERVAL DAY TO SECOND"); 01050 } 01051 01052 #endif 01053 01054 case SQLT_REF: 01055 { 01056 return MT("REF"); 01057 } 01058 01059 #if OCI_VERSION_COMPILE >= OCI_9_0 01060 01061 case SQLT_PNTY: 01062 01063 #endif 01064 01065 case SQLT_NTY: 01066 { 01067 if (col->typinf != NULL) 01068 { 01069 return col->typinf->name; 01070 } 01071 else 01072 { 01073 return MT("NAMED TYPE"); 01074 } 01075 } 01076 default: 01077 { 01078 /* unknown datatype ? Should not happen because all 01079 datatypes are supported */ 01080 01081 return MT("?"); 01082 } 01083 } 01084 } 01085 01086 /* --------------------------------------------------------------------------------------------- * 01087 * OCI_ColumnGetFullSQLType 01088 * --------------------------------------------------------------------------------------------- */ 01089 01090 unsigned int OCI_API OCI_ColumnGetFullSQLType 01091 ( 01092 OCI_Column *col, 01093 mtext *buffer, 01094 unsigned int len 01095 ) 01096 { 01097 OCI_CHECK_PTR(OCI_IPC_COLUMN, col, 0); 01098 OCI_CHECK_PTR(OCI_IPC_STRING, buffer, 0); 01099 01100 OCI_RESULT(TRUE); 01101 01102 buffer[0] = 0; 01103 01104 /* ISO C functions are supposed to be "standard", but we still see specific 01105 implementations that make some usage not portable and worse not compatible. 01106 MS Windows is implementing string conversion characters (%s/%ls) of the 01107 printf/wprintf family differently from unixes ! 01108 */ 01109 01110 /* This function returns the same strings as Sql*Plus DESC command */ 01111 01112 switch(col->ocode) 01113 { 01114 case SQLT_AFC: 01115 { 01116 01117 #if defined(OCI_METADATA_WIDE) && !defined(_WINDOWS) 01118 01119 len = mtsprintf(buffer, len, MT("%lsCHAR(%i%ls)"), 01120 01121 #else 01122 01123 len = mtsprintf(buffer, len, MT("%sCHAR(%i%s)"), 01124 01125 #endif 01126 col->csfrm == SQLCS_NCHAR ? MT("N") : MT(""), 01127 (int) (col->charused == TRUE ? col->charsize : col->size), 01128 col->charused == TRUE && 01129 col->csfrm != SQLCS_NCHAR ? MT(" CHAR") : MT("")); 01130 break; 01131 } 01132 case SQLT_AVC: 01133 case SQLT_STR: 01134 case SQLT_CHR: 01135 { 01136 #if defined(OCI_METADATA_WIDE) && !defined(_WINDOWS) 01137 len = mtsprintf(buffer, len, MT("%lsVARCHAR(%i%ls)"), 01138 #else 01139 len = mtsprintf(buffer, len, MT("%sVARCHAR(%i%s)"), 01140 #endif 01141 col->csfrm == SQLCS_NCHAR ? MT("N") : MT(""), 01142 (int) (col->charused == TRUE ? col->charsize : col->size), 01143 col->charused == TRUE && 01144 col->csfrm != SQLCS_NCHAR ? MT(" CHAR") : MT("")); 01145 break; 01146 } 01147 case SQLT_NUM: 01148 { 01149 if (col->scale == -127 && col->prec > 0) 01150 { 01151 len = mtsprintf(buffer, len, MT("FLOAT(%i)"), col->prec); 01152 } 01153 else if (col->scale > 0 && col->prec > 0) 01154 { 01155 len = mtsprintf(buffer, len, MT("NUMBER(%i,%i)"), (int) col->prec, (int) col->scale); 01156 } 01157 else if (col->prec > 0) 01158 { 01159 len = mtsprintf(buffer, len, MT("NUMBER(%i)"), (int) col->prec); 01160 } 01161 else 01162 { 01163 len = mtsprintf(buffer, len, MT("NUMBER")); 01164 } 01165 01166 break; 01167 } 01168 case SQLT_INT: 01169 { 01170 len = mtsprintf(buffer, len, MT("NUMBER")); 01171 break; 01172 } 01173 case SQLT_FLT: 01174 { 01175 len = mtsprintf(buffer, len, MT("FLOAT(%i)"), (int) col->prec); 01176 break; 01177 } 01178 01179 #if OCI_VERSION_COMPILE >= OCI_10_1 01180 01181 case SQLT_BFLOAT: 01182 case SQLT_IBFLOAT: 01183 { 01184 len = mtsprintf(buffer, len, MT("BINARY FLOAT")); 01185 break; 01186 } 01187 case SQLT_BDOUBLE: 01188 case SQLT_IBDOUBLE: 01189 { 01190 len = mtsprintf(buffer, len, MT("BINARY DOUBLE")); 01191 break; 01192 } 01193 01194 #endif 01195 01196 case SQLT_LNG: 01197 { 01198 len = mtsprintf(buffer, len, MT("LONG")); 01199 break; 01200 } 01201 case SQLT_DAT: 01202 case SQLT_ODT: 01203 case SQLT_DATE: 01204 { 01205 len = mtsprintf(buffer, len, MT("DATE")); 01206 break; 01207 } 01208 case SQLT_RDD: 01209 case SQLT_RID: 01210 { 01211 len = mtsprintf(buffer, len, MT("ROWID")); 01212 break; 01213 } 01214 case SQLT_BIN: 01215 { 01216 len = mtsprintf(buffer, len, MT("RAW(%i)"), (int) col->size); 01217 break; 01218 } 01219 case SQLT_LBI: 01220 { 01221 len = mtsprintf(buffer, len, MT("LONG RAW(%i)"), (int) col->size); 01222 break; 01223 } 01224 case SQLT_RSET: 01225 { 01226 len = mtsprintf(buffer, len, MT("RESULTSET")); 01227 break; 01228 } 01229 case SQLT_CUR: 01230 { 01231 len = mtsprintf(buffer, len, MT("CURSOR")); 01232 break; 01233 } 01234 case SQLT_CLOB: 01235 { 01236 if (col->subtype == OCI_NCLOB) 01237 { 01238 len = mtsprintf(buffer, len, MT("NCLOB")); 01239 } 01240 else 01241 { 01242 len = mtsprintf(buffer, len, MT("CLOB")); 01243 } 01244 01245 break; 01246 } 01247 case SQLT_BLOB: 01248 { 01249 len = mtsprintf(buffer, len, MT("BLOB")); 01250 break; 01251 } 01252 case SQLT_BFILE: 01253 { 01254 len = mtsprintf(buffer, len, MT("BINARY FILE LOB")); 01255 break; 01256 } 01257 case SQLT_CFILE: 01258 { 01259 len = mtsprintf(buffer, len, MT("CFILE")); 01260 break; 01261 } 01262 01263 #if OCI_VERSION_COMPILE >= OCI_9_0 01264 01265 case SQLT_TIMESTAMP: 01266 { 01267 len = mtsprintf(buffer, len, MT("TIMESTAMP(%i)"), (int) col->prec); 01268 break; 01269 } 01270 case SQLT_TIMESTAMP_TZ: 01271 { 01272 len = mtsprintf(buffer, len, MT("TIMESTAMP(%i) WITH TIME ZONE"), (int) col->prec); 01273 break; 01274 } 01275 case SQLT_TIMESTAMP_LTZ: 01276 { 01277 len = mtsprintf(buffer, len, MT("TIMESTAMP(%i) WITH LOCAL TIME ZONE"), (int) col->prec); 01278 break; 01279 } 01280 case SQLT_INTERVAL_YM: 01281 { 01282 len = mtsprintf(buffer, len, MT("INTERVAL(%i) YEAR TO MONTH(%i)"), 01283 (int) col->prec, (int) col->prec2); 01284 break; 01285 } 01286 case SQLT_INTERVAL_DS: 01287 { 01288 len = mtsprintf(buffer, len, MT("INTERVAL(%i) DAY TO SECOND(%i)"), 01289 (int) col->prec, (int) col->prec2); 01290 break; 01291 } 01292 01293 #endif 01294 01295 case SQLT_REF: 01296 { 01297 len = mtsprintf(buffer, len, MT("REF")); 01298 break; 01299 } 01300 01301 #if OCI_VERSION_COMPILE >= OCI_9_0 01302 01303 case SQLT_PNTY: 01304 01305 #endif 01306 01307 case SQLT_NTY: 01308 { 01309 if (col->typinf != NULL) 01310 { 01311 len = mtsprintf(buffer, len, col->typinf->name); 01312 } 01313 else 01314 { 01315 len = mtsprintf(buffer, len, MT("NAMED TYPE")); 01316 } 01317 01318 break; 01319 } 01320 default: 01321 { 01322 mtsncat(buffer, MT("?"), (size_t) len); 01323 01324 break; 01325 } 01326 } 01327 01328 return len; 01329 } 01330 01331 /* --------------------------------------------------------------------------------------------- * 01332 * OCI_ColumnGetTypeInfo 01333 * --------------------------------------------------------------------------------------------- */ 01334 01335 OCI_TypeInfo * OCI_API OCI_ColumnGetTypeInfo 01336 ( 01337 OCI_Column *col 01338 ) 01339 { 01340 OCI_CHECK_PTR(OCI_IPC_COLUMN, col, NULL); 01341 01342 OCI_RESULT(TRUE); 01343 01344 return col->typinf; 01345 } 01346 01347 /* --------------------------------------------------------------------------------------------- * 01348 * OCI_ColumnGetSubType 01349 * --------------------------------------------------------------------------------------------- */ 01350 01351 unsigned int OCI_API OCI_ColumnGetSubType 01352 ( 01353 OCI_Column *col 01354 ) 01355 { 01356 unsigned int type = OCI_UNKNOWN; 01357 01358 OCI_CHECK_PTR(OCI_IPC_COLUMN, col, OCI_UNKNOWN); 01359 01360 OCI_RESULT(TRUE); 01361 01362 if (col->type == OCI_CDT_LONG || 01363 col->type == OCI_CDT_LOB || 01364 col->type == OCI_CDT_FILE || 01365 col->type == OCI_CDT_TIMESTAMP || 01366 col->type == OCI_CDT_INTERVAL) 01367 { 01368 type = col->subtype; 01369 } 01370 01371 return type; 01372 } 01373 01374 /* --------------------------------------------------------------------------------------------- * 01375 * OCI_ColumnGetAttrInfo 01376 * --------------------------------------------------------------------------------------------- */ 01377 01378 boolean OCI_ColumnGetAttrInfo 01379 ( 01380 OCI_Column *col, 01381 unsigned int count, 01382 unsigned int index, 01383 size_t *p_size, 01384 int *p_type 01385 ) 01386 { 01387 if (index >= count) 01388 { 01389 *p_size = 0; 01390 *p_type = 0; 01391 01392 return FALSE; 01393 } 01394 01395 switch (col->type) 01396 { 01397 case OCI_CDT_NUMERIC: 01398 { 01399 int type = col->subtype; 01400 01401 if (type & OCI_NUM_SHORT) 01402 { 01403 *p_type = OCI_OFT_SHORT; 01404 *p_size = sizeof(short); 01405 } 01406 else if (type & OCI_NUM_INT) 01407 { 01408 *p_type = OCI_OFT_INT; 01409 *p_size = sizeof(int); 01410 } 01411 else if (type & OCI_NUM_BIGUINT) 01412 { 01413 *p_type = OCI_OFT_BIGINT; 01414 *p_size = sizeof(big_int); 01415 } 01416 else if (type & OCI_NUM_DOUBLE) 01417 { 01418 *p_type = OCI_OFT_DOUBLE; 01419 *p_size = sizeof(double); 01420 } 01421 else 01422 { 01423 //default mapping to big_int 01424 01425 *p_type = OCI_OFT_BIGINT; 01426 *p_size = sizeof(big_int); 01427 } 01428 break; 01429 } 01430 case OCI_CDT_OBJECT: 01431 { 01432 *p_size = OCI_ObjectGetUserStructSize(col->typinf); 01433 *p_type = OCI_OFT_STRUCT; 01434 break; 01435 } 01436 default: 01437 { 01438 *p_size = sizeof(void *); 01439 *p_type = OCI_OFT_POINTER; 01440 break; 01441 } 01442 } 01443 01444 return TRUE; 01445 }