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