OCILIB (C Driver for Oracle) 3.9.2
D:/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     |                              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 *) &param,
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**) &param, (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 }