C:/Users/vincent/Data/Perso/dev/ocilib/ocilib/src/column.c

00001 /*
00002    +----------------------------------------------------------------------+   
00003    |                                                                      |
00004    |                     OCILIB - C Driver for Oracle                     |
00005    |                                                                      |
00006    |                      (C Wrapper for Oracle OCI)                      |
00007    |                                                                      |
00008    +----------------------------------------------------------------------+
00009    |                      Website : http://www.ocilib.net                 |
00010    +----------------------------------------------------------------------+
00011    |               Copyright (c) 2007-2009 Vincent ROGIER                 |
00012    +----------------------------------------------------------------------+
00013    | This library is free software; you can redistribute it and/or        |
00014    | modify it under the terms of the GNU Lesser General Public           |
00015    | License as published by the Free Software Foundation; either         |
00016    | version 2 of the License, or (at your option) any later version.     |
00017    |                                                                      |
00018    | This library is distributed in the hope that it will be useful,      |
00019    | but WITHOUT ANY WARRANTY; without even the implied warranty of       |
00020    | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU    |
00021    | Lesser General Public License for more details.                      |
00022    |                                                                      |
00023    | You should have received a copy of the GNU Lesser General Public     |
00024    | License along with this library; if not, write to the Free           |
00025    | Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.   |
00026    +----------------------------------------------------------------------+
00027    |          Author: Vincent ROGIER <vince.rogier@gmail.com>             |
00028    +----------------------------------------------------------------------+ 
00029 */
00030 
00031 /* ------------------------------------------------------------------------ *
00032  * $Id: column.c, v 3.4.0 2009-07-30 17:40 Vince $
00033  * ------------------------------------------------------------------------ */
00034 
00035 #include "ocilib_internal.h"
00036 
00037 /* ************************************************************************ *
00038  *                             PRIVATE FUNCTIONS
00039  * ************************************************************************ */
00040 
00041 /* ------------------------------------------------------------------------ *
00042  * OCI_ColumnDescribe
00043  * ------------------------------------------------------------------------ */
00044 
00045 boolean OCI_ColumnDescribe(OCI_Column *col, OCI_Connection *con, 
00046                            OCI_Statement *stmt, void *handle, int index,
00047                            int ptype)
00048 {
00049     void       *ostr     = NULL;
00050     void       *param    = NULL;
00051     boolean     res      = TRUE;
00052     int         osize    = 0;
00053     ub4         htype    = 0;
00054     ub4         attrname = 0;
00055 
00056     /* get descriptor */
00057 
00058     if (ptype == OCI_DESC_COLLECTION)
00059     {
00060         OCI_CALL1
00061         (
00062             res, con, stmt,
00063             
00064             OCIAttrGet((dvoid *) handle, (ub4) OCI_DTYPE_PARAM, (dvoid *) &param, 
00065                        (ub4 *) NULL, (ub4) OCI_ATTR_COLLECTION_ELEMENT, con->err)
00066         )
00067 
00068         attrname = OCI_ATTR_TYPE_NAME;
00069     }
00070     else
00071     {
00072         if (ptype == OCI_DESC_RESULTSET)
00073             htype = OCI_HTYPE_STMT;
00074         else
00075             htype = OCI_DTYPE_PARAM;
00076 
00077         OCI_CALL1
00078         (
00079             res, con, stmt,
00080             
00081             OCIParamGet((dvoid *) handle, htype,  con->err, (void**) &param, 
00082                         (ub4) index)
00083         )
00084     }
00085 
00086     /* sql code */
00087 
00088     OCI_CALL1
00089     (
00090         res, con, stmt,
00091         
00092         OCIAttrGet((dvoid *) param, (ub4) OCI_DTYPE_PARAM, (dvoid *) &col->ocode,
00093                    (ub4 *) NULL, (ub4) OCI_ATTR_DATA_TYPE, con->err)
00094     )
00095  
00096    /* size */
00097 
00098     OCI_CALL1
00099     (
00100         res, con, stmt,
00101         
00102         OCIAttrGet((dvoid *) param, (ub4)  OCI_DTYPE_PARAM, (dvoid *) &col->size,
00103                    (ub4 *) NULL, (ub4) OCI_ATTR_DATA_SIZE, con->err)
00104     )
00105 
00106     /* scale */
00107 
00108     OCI_CALL1
00109     (
00110         res, con, stmt,
00111         
00112         OCIAttrGet((dvoid *) param, (ub4) OCI_DTYPE_PARAM, (dvoid *) &col->scale,
00113                    (ub4 *) NULL, (ub4) OCI_ATTR_SCALE, con->err)
00114     )
00115 
00116     /* precision */
00117 
00118     OCI_CALL1
00119     (
00120         res, con, stmt,
00121         
00122         OCIAttrGet((dvoid *) param, (ub4) OCI_DTYPE_PARAM, (dvoid *) &col->prec,
00123                    (ub4 *) NULL, (ub4) OCI_ATTR_PRECISION, con->err)
00124     )
00125 
00126     /* charset form */
00127 
00128     OCI_CALL1
00129     (
00130         res, con, stmt,
00131         
00132         OCIAttrGet((dvoid *) param, (ub4) OCI_DTYPE_PARAM, (dvoid *) &col->csfrm, 
00133                    (ub4 *) NULL, (ub4) OCI_ATTR_CHARSET_FORM, con->err)
00134     )
00135 
00136     /* type of column length for string based column */
00137 
00138 #if OCI_VERSION_COMPILE >= OCI_9_0 
00139 
00140     if ((OCILib.version_runtime >= OCI_9_0) && (con->ver_num >= OCI_9_0))
00141     {
00142         /* char used - no error checking because on Oracle 9.0, querying
00143                        this param that is not char/varchar based will cause an 
00144                        error */
00145 
00146         OCI_CALL1
00147         (
00148             res, con, stmt,
00149             
00150             OCIAttrGet((dvoid *) param, (ub4) OCI_DTYPE_PARAM, 
00151                        (dvoid *) &col->charused, (ub4 *) NULL, 
00152                        (ub4) OCI_ATTR_CHAR_USED, con->err)
00153         )
00154     }
00155 
00156     /* char size */
00157     
00158     if (col->charused == TRUE)
00159     {
00160         OCI_CALL1
00161         (
00162             res, con, stmt,
00163         
00164             OCIAttrGet((dvoid *) param, (ub4) OCI_DTYPE_PARAM, 
00165                        (dvoid *) &col->charsize, (ub4 *) NULL, 
00166                        (ub4) OCI_ATTR_CHAR_SIZE, con->err)
00167         )
00168     }
00169 
00170     if ((OCILib.version_runtime >= OCI_9_0) && (con->ver_num >= OCI_9_0))
00171     {
00172         /* fractional time precision for timestamps */
00173 
00174          if (col->ocode == SQLT_TIMESTAMP    ||
00175              col->ocode == SQLT_TIMESTAMP_TZ ||
00176              col->ocode == SQLT_TIMESTAMP_LTZ)
00177         {
00178             OCI_CALL1
00179             (
00180                 res, con, stmt,
00181         
00182                 OCIAttrGet((dvoid *) param, (ub4) OCI_DTYPE_PARAM,
00183                            (dvoid *) &col->prec, (ub4 *) NULL, 
00184                            (ub4) OCI_ATTR_FSPRECISION, con->err)
00185             )
00186         }
00187 
00188         /* leading and fractional precision for interval */
00189 
00190         if (col->ocode == SQLT_INTERVAL_DS ||
00191             col->ocode == SQLT_INTERVAL_YM)
00192         {
00193             OCI_CALL1
00194             (
00195                 res, con, stmt,
00196         
00197                 OCIAttrGet((dvoid *) param, (ub4) OCI_DTYPE_PARAM, 
00198                            (dvoid *) &col->prec, (ub4 *) NULL, 
00199                            (ub4) OCI_ATTR_LFPRECISION, con->err)
00200             )
00201 
00202             OCI_CALL1
00203             (
00204                 res, con, stmt,
00205         
00206                 OCIAttrGet((dvoid *) param, (ub4) OCI_DTYPE_PARAM, 
00207                            (dvoid *) &col->prec2, (ub4 *) NULL, 
00208                            (ub4) OCI_ATTR_FSPRECISION, con->err)
00209             )
00210         }
00211     }
00212 
00213 #endif
00214 
00215     /* check nullable only for table based column */
00216 
00217     if (ptype == OCI_DESC_TABLE)
00218     {
00219         OCI_CALL1
00220         (
00221             res, con, stmt,
00222         
00223             OCIAttrGet((dvoid *) param, (ub4) OCI_DTYPE_PARAM, 
00224                        (dvoid *) &col->null, (ub4 *) NULL, 
00225                        (ub4) OCI_ATTR_IS_NULL, con->err)
00226         )
00227    }
00228    else
00229        col->null = TRUE;
00230 
00231     /* name */
00232 
00233     if (ptype == OCI_DESC_COLLECTION) 
00234         attrname = OCI_ATTR_TYPE_NAME;
00235     else
00236         attrname = OCI_ATTR_NAME;
00237 
00238     OCI_CALL1
00239     (
00240         res, con, stmt,
00241         
00242         OCIAttrGet((dvoid *) param, (ub4) OCI_DTYPE_PARAM, (dvoid *) &ostr,
00243                    (ub4 *) &osize, (ub4) attrname, con->err)
00244     )
00245 
00246     if ((res == TRUE) && (ostr != NULL))
00247     {
00248         col->name = (mtext *) OCI_MemAlloc(OCI_IPC_STRING, sizeof(mtext),
00249                                            ((osize/sizeof(omtext))+ 1), TRUE);
00250   
00251         if (col->name != NULL)
00252         {
00253             OCI_CopyString(ostr, col->name, &osize, 
00254                            sizeof(omtext), sizeof(mtext));
00255         }
00256         else
00257             res = FALSE;
00258     }
00259 
00260     /* user type descriptor */
00261 
00262     if (col->ocode == SQLT_NTY || col->ocode == SQLT_REF)
00263     {
00264         OCI_CALL1
00265         (
00266             res, con, stmt,
00267         
00268             OCIAttrGet((dvoid *) param, (ub4) OCI_DTYPE_PARAM, 
00269                        (dvoid *) &ostr, (ub4 *) &osize, 
00270                        (ub4) OCI_ATTR_TYPE_NAME, con->err)
00271         )
00272       
00273         if ((res == TRUE) && (ostr != NULL))
00274         {   
00275             mtext *tmp = (mtext *) OCI_MemAlloc(OCI_IPC_STRING, sizeof(mtext),
00276                                                ((osize/sizeof(omtext))+ 1), TRUE);
00277         
00278             if (tmp != NULL)
00279             {
00280                OCI_CopyString(ostr, tmp, &osize, sizeof(omtext), sizeof(mtext));
00281                col->typinf = OCI_TypeInfoGet(con, tmp, OCI_SCHEMA_TYPE);
00282             }
00283 
00284             res = (col->typinf != NULL);
00285             
00286             OCI_FREE(tmp);
00287         }
00288     }
00289 
00290     if (param != NULL)
00291     {
00292         res = (OCI_SUCCESS == OCIDescriptorFree(param, OCI_DTYPE_PARAM));
00293     }
00294 
00295     return res;
00296 }
00297     
00298 /* ------------------------------------------------------------------------ *
00299  * OCI_ColumnMap
00300  * ------------------------------------------------------------------------ */
00301 
00302 boolean OCI_ColumnMap(OCI_Column *col, OCI_Statement *stmt)
00303 {
00304     boolean res = TRUE;
00305     
00306     OCI_CHECK(col == NULL, FALSE);
00307 
00308     /* map Oracle SQL code to OCILIB types and setup of internal buffer size */
00309 
00310     col->icode = col->ocode;
00311 
00312     switch (col->icode)
00313     {
00314         case SQLT_INT:
00315 
00316             col->type = OCI_CDT_NUMERIC;
00317             
00318             /* set bufsize only if it's not a "returning into" placeholder */
00319          
00320             if (col->bufsize == 0) 
00321             {
00322                 col->subtype = OCI_NUM_INT;
00323                 col->bufsize = sizeof(int);
00324             }
00325 
00326             break;
00327 
00328        case SQLT_UIN:
00329 
00330             col->type = OCI_CDT_NUMERIC;
00331            
00332             /* set bufsize only if it's not a "returning into" placeholder */
00333 
00334             if (col->bufsize == 0) 
00335             {
00336                 col->subtype = OCI_NUM_UINT;
00337                 col->bufsize = sizeof(unsigned int);
00338             }
00339 
00340             break;
00341 
00342         case SQLT_FLT:
00343         case SQLT_VNU:
00344         case SQLT_PDN:
00345         case SQLT_NUM:
00346 
00347 #if OCI_VERSION_COMPILE >= OCI_10_1
00348 
00349         case SQLT_BFLOAT:
00350         case SQLT_BDOUBLE:
00351         case SQLT_IBFLOAT:
00352         case SQLT_IBDOUBLE:
00353 
00354 #endif  
00355             col->type    = OCI_CDT_NUMERIC;
00356             col->subtype = OCI_NUM_NUMBER;
00357             col->icode   = SQLT_VNU;
00358             col->bufsize = sizeof(OCINumber);
00359 
00360             break;
00361 
00362         case SQLT_DAT:
00363         case SQLT_ODT:
00364 
00365             col->type    = OCI_CDT_DATETIME;
00366 
00367             /* We map to SQLT_ODT only it the column is not part of a 
00368                "returning into" clause (workaround for Oracle 
00369                known bug #3269146 
00370             */
00371 
00372             if (col->bufsize == 0)
00373             {
00374                 col->icode   = SQLT_ODT;
00375                 col->bufsize = sizeof(OCIDate);
00376             }
00377 
00378             break;
00379 
00380         case SQLT_CUR:
00381         case SQLT_RSET:
00382 
00383             col->type     = OCI_CDT_CURSOR;
00384             col->bufsize  = sizeof(OCIStmt *);
00385             col->dtype    = OCI_HTYPE_STMT;
00386             break;
00387 
00388         case SQLT_RID:
00389         case SQLT_RDD:
00390 
00391             col->icode   = SQLT_STR;
00392             col->type    = OCI_CDT_TEXT;
00393 
00394             if ((col->ocode == SQLT_RDD) || (col->size > sizeof(OCIRowid *)))
00395             {
00396                 /* For Oracle 7 ROWIDs and regular ROWID descriptors, the 
00397                    max size of the hex value is defined by the constant
00398                    OCI_SIZE_ROWID 
00399                 */
00400 
00401                 col->bufsize = (OCI_SIZE_ROWID + 1) * sizeof(dtext);
00402             }
00403             else
00404             {
00405                 /* For ROWID descriptor, if column size is bigger than the size
00406                     of the descriptor, it means that an UROWID column and then 
00407                     the column size is the maximum size needed for representing
00408                     its value as an hex string
00409                 */
00410 
00411                 col->bufsize = (col->size + 1) * sizeof(dtext);
00412             }
00413 
00414             break;
00415  
00416         case SQLT_BIN:
00417 
00418             col->type    = OCI_CDT_RAW;
00419             col->bufsize = col->size + sizeof(dtext); /* for string conversion */
00420             break;
00421 
00422         case SQLT_BLOB:
00423 
00424             col->type    = OCI_CDT_LOB;
00425             col->subtype = OCI_BLOB;
00426             col->dtype   = OCI_DTYPE_LOB;
00427             col->bufsize = sizeof(OCILobLocator *);
00428             break;
00429 
00430         case SQLT_CLOB:
00431 
00432             col->type    = OCI_CDT_LOB;
00433             col->dtype   = OCI_DTYPE_LOB;
00434             col->bufsize = sizeof(OCILobLocator *);
00435            
00436             if (col->csfrm == SQLCS_NCHAR)
00437                 col->subtype = OCI_NCLOB;
00438             else
00439                 col->subtype = OCI_CLOB;
00440 
00441             break;
00442 
00443         case SQLT_BFILE:
00444 
00445             col->type    = OCI_CDT_FILE;
00446             col->subtype = OCI_BFILE;
00447             col->dtype   = OCI_DTYPE_LOB;
00448             col->bufsize = sizeof(OCILobLocator *);
00449             break;
00450 
00451         case SQLT_CFILE:
00452 
00453             col->type    = OCI_CDT_FILE;
00454             col->subtype = OCI_CFILE;
00455             col->bufsize = sizeof(OCILobLocator *);
00456             col->dtype   = OCI_DTYPE_LOB;
00457             break;
00458 
00459         case SQLT_LNG:
00460         case SQLT_LVC:
00461         case SQLT_LBI:
00462         case SQLT_LVB:
00463         case SQLT_VBI:
00464 
00465             if ((col->icode == SQLT_LNG || col->icode == SQLT_LVC) &&
00466                 (stmt != NULL && stmt->long_mode == OCI_LONG_IMPLICIT))
00467             {
00468                  col->type = OCI_CDT_TEXT;
00469                  col->bufsize = (OCI_SIZE_LONG+1);
00470                  col->subtype = OCI_CLONG;
00471             }
00472             else
00473             {
00474                 col->type    = OCI_CDT_LONG;
00475                 col->bufsize = INT_MAX;
00476                 
00477                 if (col->icode == SQLT_LBI ||
00478                     col->icode == SQLT_LVB ||
00479                     col->icode == SQLT_VBI)
00480                 {
00481                     col->subtype = OCI_BLONG;
00482                 }
00483                 else
00484                 {
00485                     col->subtype = OCI_CLONG;
00486                 }
00487 
00488             }
00489 
00490             break;
00491 
00492 #if OCI_VERSION_COMPILE >= OCI_9_0
00493 
00494         case SQLT_TIMESTAMP:
00495 
00496             col->type    = OCI_CDT_TIMESTAMP;
00497             col->subtype = OCI_TIMESTAMP;
00498             col->dtype   = OCI_DTYPE_TIMESTAMP;
00499             col->bufsize = sizeof(OCIDateTime *);
00500             break;
00501 
00502         case SQLT_TIMESTAMP_TZ:
00503 
00504             col->type    = OCI_CDT_TIMESTAMP;
00505             col->subtype = OCI_TIMESTAMP_TZ;
00506             col->dtype   = OCI_DTYPE_TIMESTAMP_TZ;
00507             col->bufsize = sizeof(OCIDateTime *);
00508             break;
00509 
00510         case SQLT_TIMESTAMP_LTZ:
00511 
00512             col->type    = OCI_CDT_TIMESTAMP;
00513             col->subtype = OCI_TIMESTAMP_LTZ;
00514             col->dtype   = OCI_DTYPE_TIMESTAMP_LTZ;
00515             col->bufsize = sizeof(OCIDateTime *);
00516             break;
00517 
00518         case SQLT_INTERVAL_YM:
00519 
00520             col->type    = OCI_CDT_INTERVAL;
00521             col->subtype = OCI_INTERVAL_YM;
00522             col->dtype   = OCI_DTYPE_INTERVAL_YM;
00523             col->bufsize = sizeof(OCIInterval *);
00524             break;
00525 
00526         case SQLT_INTERVAL_DS:
00527 
00528             col->type    = OCI_CDT_INTERVAL;
00529             col->subtype = OCI_INTERVAL_DS;
00530             col->dtype   = OCI_DTYPE_INTERVAL_DS;
00531             col->bufsize = sizeof(OCIInterval *);
00532             break;
00533 
00534 #endif
00535 
00536 #if OCI_VERSION_COMPILE >= OCI_9_0
00537 
00538         case SQLT_PNTY:
00539 
00540 #endif
00541 
00542         case SQLT_NTY:
00543 
00544             col->icode   = SQLT_NTY;
00545             col->bufsize = sizeof(void *);
00546 
00547             if (col->typinf->tcode == SQLT_NCO)
00548                 col->type = OCI_CDT_COLLECTION;                    
00549             else
00550                 col->type = OCI_CDT_OBJECT;                    
00551 
00552             break;
00553 
00554         case SQLT_REF:
00555 
00556             col->icode   = SQLT_REF;
00557             col->bufsize = sizeof(OCIRef *);
00558             col->type    = OCI_CDT_REF;                    
00559 
00560             break;
00561 
00562         case SQLT_CHR:
00563         case SQLT_STR:
00564         case SQLT_VCS:
00565         case SQLT_AFC:
00566         case SQLT_AVC:
00567         case SQLT_VST:
00568         case SQLT_LAB:
00569         case SQLT_OSL:
00570         case SQLT_SLS:
00571         default:
00572 
00573             col->icode   = SQLT_STR;
00574             col->type    = OCI_CDT_TEXT;
00575             col->bufsize = (col->size + 1) * sizeof(dtext);
00576             break;
00577     }
00578 
00579     return res;
00580 }
00581 
00582 /* ************************************************************************ *
00583  *                            PUBLIC FUNCTIONS
00584  * ************************************************************************ */
00585 
00586 /* ------------------------------------------------------------------------ *
00587  * OCI_ColumnGetName
00588  * ------------------------------------------------------------------------ */
00589 
00590 const mtext * OCI_API OCI_ColumnGetName(OCI_Column *col)
00591 {
00592     OCI_CHECK_PTR(OCI_IPC_COLUMN, col, NULL);
00593 
00594     return col->name;
00595 }
00596 
00597 /* ------------------------------------------------------------------------ *
00598  * OCI_ColumnGetType
00599  * ------------------------------------------------------------------------ */
00600 
00601 unsigned int OCI_API OCI_ColumnGetType(OCI_Column *col)
00602 {
00603     OCI_CHECK_PTR(OCI_IPC_COLUMN, col, OCI_UNKNOWN);
00604 
00605     OCI_RESULT(TRUE);
00606 
00607     return col->type;
00608 }
00609 
00610 /* ------------------------------------------------------------------------ *
00611  * OCI_ColumnGetCharsetForm
00612  * ------------------------------------------------------------------------ */
00613 
00614 unsigned int OCI_API OCI_ColumnGetCharsetForm(OCI_Column *col)
00615 {
00616     OCI_CHECK_PTR(OCI_IPC_COLUMN, col, OCI_CSF_NONE);
00617 
00618     OCI_RESULT(TRUE);
00619 
00620     if (col->csfrm == SQLCS_NCHAR)
00621         return OCI_CSF_NATIONAL;
00622     else if (col->csfrm == SQLCS_IMPLICIT)
00623         return OCI_CSF_CHARSET;
00624     else
00625         return OCI_CSF_NONE;
00626 }
00627 
00628 /* ------------------------------------------------------------------------ *
00629  * OCI_ColumnGetSize
00630  * ------------------------------------------------------------------------ */
00631 
00632 unsigned int OCI_API OCI_ColumnGetSize(OCI_Column *col)
00633 {
00634     OCI_CHECK_PTR(OCI_IPC_COLUMN, col, 0);
00635 
00636     OCI_RESULT(TRUE);
00637 
00638     /* Oracle 9i introduced CHAR attribute on string columns to indicate the 
00639        size of the column is not in bytes (default) but in chars
00640        OCI_ColumnDescribe() already managed the Oracle compatibly
00641        version, so if col->charsize is zero it means :
00642        - the column is not a string column 
00643        - the size is not in char
00644        - client does not support the OCI_ATTR_CHAR_SIZE attribute */
00645        
00646     if (col->charused == TRUE && col->charsize > 0)
00647         return col->charsize;
00648     else
00649         return col->size;
00650 }
00651 
00652 /* ------------------------------------------------------------------------ *
00653  * OCI_ColumnGetScale
00654  * ------------------------------------------------------------------------ */
00655 
00656 int OCI_API OCI_ColumnGetScale(OCI_Column *col)
00657 {
00658     OCI_CHECK_PTR(OCI_IPC_COLUMN, col, 0);
00659 
00660     OCI_RESULT(TRUE);
00661 
00662     return (int) col->scale;
00663 }
00664 
00665 /* ------------------------------------------------------------------------ *
00666  * OCI_ColumnGetPrecision
00667  * ------------------------------------------------------------------------ */
00668 
00669 int OCI_API OCI_ColumnGetPrecision(OCI_Column *col)
00670 {
00671     OCI_CHECK_PTR(OCI_IPC_COLUMN, col, 0);
00672 
00673     OCI_RESULT(TRUE);
00674 
00675     if (col->type == OCI_CDT_NUMERIC)
00676         return (int) col->prec;
00677     else
00678         return 0;
00679 }
00680 
00681 /* ------------------------------------------------------------------------ *
00682  * OCI_ColumnGetFractionalPrecision
00683  * ------------------------------------------------------------------------ */
00684 
00685 int OCI_API OCI_ColumnGetFractionalPrecision(OCI_Column *col)
00686 {
00687     OCI_CHECK_PTR(OCI_IPC_COLUMN, col, 0);
00688 
00689     OCI_RESULT(TRUE);
00690 
00691     if (col->type == OCI_CDT_TIMESTAMP)
00692         return (int) col->prec;
00693     else if (col->type == OCI_CDT_INTERVAL)
00694         return (int) col->prec2;
00695     else
00696         return 0;
00697 }
00698 
00699 /* ------------------------------------------------------------------------ *
00700  * OCI_ColumnGetLeadingPrecision
00701  * ------------------------------------------------------------------------ */
00702 
00703 int OCI_API OCI_ColumnGetLeadingPrecision(OCI_Column *col)
00704 {
00705     OCI_CHECK_PTR(OCI_IPC_COLUMN, col, 0);
00706 
00707     OCI_RESULT(TRUE);
00708 
00709     if (col->type == OCI_CDT_INTERVAL)
00710         return (int) col->prec;
00711     else
00712         return 0;
00713 }
00714 
00715 /* ------------------------------------------------------------------------ *
00716  * OCI_ColumnGetNullable
00717  * ------------------------------------------------------------------------ */
00718 
00719 boolean OCI_API OCI_ColumnGetNullable(OCI_Column *col)
00720 {
00721     OCI_CHECK_PTR(OCI_IPC_COLUMN, col, FALSE);
00722 
00723     OCI_RESULT(TRUE);
00724 
00725     return (col->null == TRUE);
00726 }
00727 
00728 /* ------------------------------------------------------------------------ *
00729  * OCI_ColumnGetCharUsed
00730  * ------------------------------------------------------------------------ */
00731 
00732 boolean OCI_API OCI_ColumnGetCharUsed(OCI_Column *col)
00733 {
00734     OCI_CHECK_PTR(OCI_IPC_COLUMN, col, FALSE);
00735 
00736     OCI_RESULT(TRUE);
00737 
00738     return (boolean) col->charused;
00739 }
00740 
00741 /* ------------------------------------------------------------------------ *
00742  * OCI_ColumnGetSQLType
00743  * ------------------------------------------------------------------------ */
00744 
00745 const mtext * OCI_API OCI_ColumnGetSQLType(OCI_Column *col)
00746 {
00747     OCI_CHECK_PTR(OCI_IPC_COLUMN, col, NULL);
00748 
00749     /* VARCHAR type will not be returned because Oracle does not make any 
00750        difference with VARCHAR2. If a column is created with VARCHAR, it is
00751        internally created as VARCHAR2
00752     */       
00753 
00754     OCI_RESULT(TRUE);
00755 
00756     switch(col->ocode)
00757     {
00758         case SQLT_AFC:
00759 
00760             if (col->csfrm == SQLCS_NCHAR)
00761                 return MT("NCHAR");
00762             else
00763                 return MT("CHAR");
00764 
00765         case SQLT_AVC:
00766         case SQLT_STR:
00767         case SQLT_CHR:
00768 
00769             if (col->csfrm == SQLCS_NCHAR)
00770                 return MT("NVARCHAR2");
00771             else
00772                 return MT("VARCHAR2");
00773 
00774         case SQLT_NUM:
00775 
00776             if (col->scale == -127 && col->prec > 0)
00777                  return MT("FLOAT");
00778              else
00779                  return MT("NUMBER");
00780 
00781         case SQLT_INT:
00782 
00783              return MT("INTEGER");
00784 
00785         case SQLT_FLT:
00786 
00787              return MT("FLOAT");
00788 
00789 #if OCI_VERSION_COMPILE >= OCI_10_1
00790 
00791         case SQLT_BFLOAT:
00792         case SQLT_IBFLOAT:
00793 
00794              return MT("BINARY FLOAT");
00795 
00796         case SQLT_BDOUBLE:
00797         case SQLT_IBDOUBLE:
00798 
00799              return MT("BINARY DOUBLE");
00800 
00801  #endif
00802 
00803         case SQLT_LNG:
00804 
00805              return MT("LONG");
00806 
00807         case SQLT_DAT:
00808         case SQLT_ODT:
00809         case SQLT_DATE:
00810 
00811             return MT("DATE");
00812 
00813         case SQLT_RDD:
00814         case SQLT_RID:
00815 
00816             return MT("ROWID");
00817 
00818         case SQLT_BIN:
00819 
00820             return MT("RAW");
00821 
00822         case SQLT_LBI:
00823 
00824             return MT("LONG RAW");
00825 
00826         case SQLT_RSET:
00827 
00828             return MT("RESULTSET");
00829 
00830         case SQLT_CUR:
00831 
00832             return MT("CURSOR");
00833 
00834         case SQLT_CLOB:
00835 
00836             if (col->subtype == OCI_NCLOB)
00837                 return MT("NCLOB");
00838             else
00839                 return MT("CLOB");
00840 
00841         case SQLT_BLOB:
00842 
00843             return MT("BLOB");
00844 
00845         case SQLT_BFILE:
00846 
00847             return MT("BINARY FILE LOB");
00848 
00849         case SQLT_CFILE:
00850 
00851             return MT("CFILE");
00852 
00853 #if OCI_VERSION_COMPILE >= OCI_9_0
00854 
00855         case SQLT_TIMESTAMP:
00856 
00857             return MT("TIMESTAMP");
00858 
00859         case SQLT_TIMESTAMP_TZ:
00860 
00861             return MT("TIMESTAMP WITH TIME ZONE");
00862 
00863         case SQLT_TIMESTAMP_LTZ:
00864 
00865             return MT("TIMESTAMP WITH LOCAL TIME ZONE");
00866 
00867         case SQLT_INTERVAL_YM:
00868 
00869             return MT("INTERVAL YEAR TO MONTH");
00870 
00871         case SQLT_INTERVAL_DS:
00872 
00873             return MT("INTERVAL DAY TO SECOND");
00874 
00875 #endif
00876 
00877         case SQLT_REF:
00878 
00879             return MT("REF");
00880 
00881 #if OCI_VERSION_COMPILE >= OCI_9_0
00882 
00883         case SQLT_PNTY:
00884 #endif
00885 
00886         case SQLT_NTY:
00887 
00888             if (col->typinf != NULL)
00889                 return col->typinf->name;
00890             else
00891                 return MT("NAMED TYPE");
00892 
00893        default:
00894 
00895             /* for all other types not supported */
00896             return MT("?");
00897     }
00898 }
00899 
00900 
00901 /* ------------------------------------------------------------------------ *
00902  * OCI_ColumnGetFullSQLType
00903  * ------------------------------------------------------------------------ */
00904 
00905 unsigned int OCI_API OCI_ColumnGetFullSQLType(OCI_Column *col, mtext *buffer, 
00906                                               unsigned int len)
00907 {
00908     OCI_CHECK_PTR(OCI_IPC_COLUMN, col, 0);
00909     OCI_CHECK_PTR(OCI_IPC_STRING, buffer, 0);
00910 
00911     OCI_RESULT(TRUE);
00912 
00913     buffer[0] = 0;
00914 
00915     /* ISO C functions are supposed to be "standard", but we still see specific
00916        implementations that make some usage not portable and worse not compatible.
00917        MS Windows is implementing string conversion characters (%s/%ls) of the 
00918        printf/wprintf family differently from unixes !
00919     */
00920 
00921     /* This function returns the same strings as Sql*Plus DESC command */
00922 
00923     switch(col->ocode)
00924     {
00925         case SQLT_AFC:
00926 
00927 #if defined(OCI_METADATA_UNICODE) && !defined(_WINDOWS)
00928             len = mtsprintf(buffer, len, MT("%lsCHAR(%i%ls)"), 
00929 #else
00930             len = mtsprintf(buffer, len, MT("%sCHAR(%i%s)"), 
00931 #endif
00932                             col->csfrm    == SQLCS_NCHAR ? MT("N") : MT(""),
00933                             (int) (col->charused == TRUE ? col->charsize : col->size),
00934                             col->charused == TRUE &&
00935                             col->csfrm    != SQLCS_NCHAR ? MT(" CHAR") : MT(""));
00936             break;
00937  
00938         case SQLT_AVC:
00939         case SQLT_STR:
00940         case SQLT_CHR:
00941  
00942 #if defined(OCI_METADATA_UNICODE) && !defined(_WINDOWS)
00943             len = mtsprintf(buffer, len, MT("%lsVARCHAR(%i%ls)"), 
00944 #else
00945             len = mtsprintf(buffer, len, MT("%sVARCHAR(%i%s)"), 
00946 #endif
00947                             col->csfrm    == SQLCS_NCHAR ? MT("N") : MT(""),
00948                             (int) (col->charused == TRUE ? col->charsize : col->size),
00949                             col->charused == TRUE &&
00950                             col->csfrm    != SQLCS_NCHAR ? MT(" CHAR") : MT(""));
00951             break;
00952 
00953         case SQLT_NUM:
00954  
00955             if (col->scale == -127 && col->prec > 0)
00956                 len = mtsprintf(buffer, len,  MT("FLOAT(%i)"), col->prec);
00957             else if (col->scale > 0 && col->prec > 0)
00958                 len = mtsprintf(buffer, len,  MT("NUMBER(%i,%i)"), 
00959                                 (int) col->prec, (int) col->scale);
00960             else if (col->prec > 0)
00961                 len = mtsprintf(buffer, len,  MT("NUMBER(%i)"), (int) col->prec);
00962             else
00963                 len = mtsprintf(buffer, len,  MT("NUMBER"));
00964         
00965             break;
00966  
00967         case SQLT_INT:
00968 
00969             len = mtsprintf(buffer, len,  MT("NUMBER"));
00970             break;
00971 
00972         case SQLT_FLT:
00973 
00974             len = mtsprintf(buffer, len,  MT("FLOAT(%i)"), (int) col->prec);
00975             break;
00976 
00977 #if OCI_VERSION_COMPILE >= OCI_10_1
00978 
00979         case SQLT_BFLOAT:
00980         case SQLT_IBFLOAT:
00981 
00982             len = mtsprintf(buffer, len,  MT("BINARY FLOAT"));
00983             break;
00984 
00985         case SQLT_BDOUBLE:
00986         case SQLT_IBDOUBLE:
00987 
00988              len = mtsprintf(buffer, len,  MT("BINARY DOUBLE"));
00989             break;
00990 
00991 #endif
00992 
00993         case SQLT_LNG:
00994 
00995             len = mtsprintf(buffer, len, MT("LONG"));
00996             break;
00997 
00998         case SQLT_DAT:
00999         case SQLT_ODT:
01000         case SQLT_DATE:
01001 
01002             len = mtsprintf(buffer, len, MT("DATE"));
01003             break;
01004 
01005         case SQLT_RDD:
01006         case SQLT_RID:
01007 
01008             len = mtsprintf(buffer, len,  MT("ROWID"));
01009             break;
01010 
01011         case SQLT_BIN:
01012             len = mtsprintf(buffer, len, MT("RAW(%i)"), (int) col->size);
01013             break;
01014 
01015         case SQLT_LBI:
01016 
01017             len = mtsprintf(buffer, len, MT("LONG RAW(%i)"), (int) col->size);
01018             break;
01019 
01020         case SQLT_RSET:
01021 
01022             len = mtsprintf(buffer, len,  MT("RESULTSET"));
01023             break;
01024 
01025         case SQLT_CUR:
01026 
01027             len = mtsprintf(buffer, len,  MT("CURSOR"));
01028             break;
01029 
01030         case SQLT_CLOB:
01031 
01032             if (col->subtype == OCI_NCLOB)
01033                 len = mtsprintf(buffer, len,  MT("NCLOB"));
01034             else
01035                 len = mtsprintf(buffer, len,  MT("CLOB"));
01036             break;
01037 
01038         case SQLT_BLOB:
01039 
01040             len = mtsprintf(buffer, len,  MT("BLOB"));
01041             break;
01042 
01043         case SQLT_BFILE:
01044 
01045             len = mtsprintf(buffer, len,  MT("BINARY FILE LOB"));
01046             break;
01047  
01048         case SQLT_CFILE:
01049  
01050             len = mtsprintf(buffer, len,  MT("CFILE"));
01051             break;
01052  
01053 #if OCI_VERSION_COMPILE >= OCI_9_0
01054 
01055         case SQLT_TIMESTAMP:
01056 
01057             len = mtsprintf(buffer, len,  MT("TIMESTAMP(%i)"), (int) col->prec);
01058             break;
01059  
01060         case SQLT_TIMESTAMP_TZ:
01061  
01062             len = mtsprintf(buffer, len,  MT("TIMESTAMP(%i) WITH TIME ZONE"),
01063                             (int) col->prec);
01064             break;
01065  
01066         case SQLT_TIMESTAMP_LTZ:
01067  
01068             len = mtsprintf(buffer, len,  MT("TIMESTAMP(%i) WITH LOCAL TIME ZONE"),
01069                             (int) col->prec);
01070             break;
01071  
01072         case SQLT_INTERVAL_YM:
01073  
01074            len = mtsprintf(buffer, len,  MT("INTERVAL(%i) YEAR TO MONTH(%i)"),
01075                             (int) col->prec, (int) col->prec2);
01076             break;
01077  
01078        case SQLT_INTERVAL_DS:
01079  
01080             len = mtsprintf(buffer, len,  MT("INTERVAL(%i) DAY TO SECOND(%i)"),
01081                             (int) col->prec, (int) col->prec2);
01082             break;
01083 
01084 #endif
01085        
01086        case SQLT_REF:
01087 
01088             len = mtsprintf(buffer, len,  MT("REF"));
01089             break;
01090 
01091 #if OCI_VERSION_COMPILE >= OCI_9_0
01092 
01093         case SQLT_PNTY:
01094 #endif
01095 
01096         case SQLT_NTY:
01097  
01098             if (col->typinf != NULL)
01099                 len = mtsprintf(buffer, len, col->typinf->name);
01100             else
01101                 len = mtsprintf(buffer, len, MT("NAMED TYPE"));
01102             break;
01103 
01104         default:
01105 
01106             mtsncat(buffer, MT("?"), len);
01107     }
01108 
01109     return len;
01110 }
01111     
01112 /* ------------------------------------------------------------------------ *
01113  * OCI_ColumnGetTypeInfo
01114  * ------------------------------------------------------------------------ */
01115 
01116 OCI_TypeInfo * OCI_API OCI_ColumnGetTypeInfo(OCI_Column *col)
01117 {
01118     OCI_CHECK_PTR(OCI_IPC_COLUMN, col, FALSE);
01119 
01120     OCI_RESULT(TRUE);
01121 
01122     return col->typinf;
01123 }
01124 
01125 /* ------------------------------------------------------------------------ *
01126  * OCI_ColumnGetSubType
01127  * ------------------------------------------------------------------------ */
01128 
01129 unsigned int OCI_API OCI_ColumnGetSubType(OCI_Column *col)
01130 {
01131     unsigned int type = OCI_UNKNOWN;
01132 
01133     OCI_CHECK_PTR(OCI_IPC_COLUMN, col, OCI_UNKNOWN);
01134 
01135     OCI_RESULT(TRUE);
01136 
01137     if (col->type == OCI_CDT_LONG      || 
01138         col->type == OCI_CDT_LOB       ||
01139         col->type == OCI_CDT_FILE      ||
01140         col->type == OCI_CDT_TIMESTAMP ||
01141         col->type == OCI_CDT_INTERVAL)
01142     {
01143         type = col->subtype;
01144     }
01145 
01146     return type;
01147 }

Generated on Thu Jul 30 17:41:52 2009 for OCILIB (C Driver for Oracle) by  doxygen 1.5.4