Oracle® Call Interface Programmer's Guide, 11g Release 1 (11.1) Part Number B28395-01 |
|
|
View PDF |
The direct path loading functions are used to load data from external files into tables and partitions.
This chapter contains these topics:
The direct path load interface enables an OCI application to access the direct path load engine of the Oracle database server to perform the functions of the Oracle SQL*Loader utility. This functionality provides the ability to load data from external files into either a table or a partition of a partitioned table.
Figure 13-1, "Direct Path Loading" introduces the subject of this chapter:
The OCI direct path load interface has the ability to load multiple rows by loading a direct path stream that contains data for multiple rows.
To use the direct path API, the client application performs the following steps:
Perform the OCI initialization.
Allocate a direct path context handle and set the attributes.
Supply the name of the object (table, partition, or sub-partition) to be loaded.
Describe the external datatypes of the columns of the object(s).
Prepare the direct path interface.
Allocate one or more column arrays.
Allocate one or more direct path streams.
Set entries in the column array to point to the input data value for each column.
Convert a column array to a direct path stream format.
Load the direct path stream.
Retrieve any errors that may have occurred.
Invoke the direct path finishing function.
Free handles and data structures.
Disconnect from the server.
Steps 8 through 11 can be repeated many times, depending on the data to be loaded.
A direct load operation requires that the object being loaded is locked to prevent DML on the object. Note that queries are lock-free and are allowed while the object is being loaded. The mode of the DML lock, and which DML locks are obtained depend upon the specification of the OCI_ATTR_DIRPATH_PARALLEL
option, and if a partition or sub-partition load is being done as opposed to an entire table load.
For a table load, if the OCI_ATTR_DIRPATH_PARALLEL
option is set to:
FALSE, then the table DML X-Lock is acquired.
TRUE, then the table DML S-Lock is acquired.
For a partition load, if the OCI_ATTR_DIRPATH_PARALLEL
option is set to:
FALSE, then the table DML SX-Lock and partition DML X-Lock is acquired.
TRUE, then the table DML SS-Lock and partition DML S-Lock is acquired.
The following external datatypes are valid for scalar columns in a direct path load operation:
SQLT_CHR
SQLT_DAT
SQLT_INT
SQLT_UIN
SQLT_FLT
SQLT_BIN
SQLT_NUM
SQLT_PDN
SQLT_DATE
SQLT_TIMESTAMP
SQLT_TIMESTAMP_TZ
SQLT_TIMESTAMP_LTZ
SQLT_INTERVAL_YM
SQLT_INTERVAL_DS
The following external object datatypes are supported:
SQLT_NTY - column objects (FINAL
and NOT FINAL
) and SQL string columns
SQLT_REF - REF columns (FINAL
and NOT FINAL
)
The following table types are supported:
Nested tables
Object tables (FINAL
and NOT FINAL
)
See Also:
For information on setting or retrieving the datatype of a column, see "Accessing Column Parameter Attributes". For information on datatypes, see Table 3-2, "External Datatypes and Codes".A direct path load corresponds to a direct path array insert operation. The direct path load interface uses the following handles to keep track of the objects loaded and the specification of the data operated on:
direct path context
direct path function context
direct path column array
direct path function context column array
direct path stream
See Also:
"Direct Path Loading Handle Attributes" and all the descriptions of direct path attributes followingThis handle must be allocated for each object, either a table or a partition of a partitioned table, being loaded. Because a OCIDirPathCtx
handle is the parent handle of the OCIDirPathFuncCtx
, OCIDirPathColArray,
and OCIDirPathStream
handles, freeing a OCIDirPathCtx
handle frees its child handles also (although for good coding practices, free child handles individually before you free the parent handle).
A direct path context is allocated with OCIHandleAlloc(). Note that the parent handle of a direct path context is always the environment handle. A direct path context is freed with OCIHandleFree(). Include the header files in the first two lines in all direct path programs:
... #include <cdemodp0.h> #include <cdemodp.h> OCIEnv *envp; OCIDirPathCtx *dpctx; sword error; error = OCIHandleAlloc((void *)envp, (void **)&dpctx, OCI_HTYPE_DIRPATH_CTX, (size_t)0,(void **)0); ... error = OCIHandleFree(dpctx, OCI_HTYPE_DIRPATH_CTX);
See Also:
For more about the datatypes supported, see Oracle Database Object-Relational Developer's GuideThis handle, of type OCIDirPathFuncCtx
, is used to describe the following named type and REF columns:
Column objects. The function context here describes the object type, which will be used as the default constructor to construct the object, and the object attributes of the constructor.
REF columns. The function context here describes a single object table (optional) to reference row objects from, and the REF arguments that identify the row object.
SQL string columns. The function context here describes a SQL string and its arguments to compute the value to be loaded into the column.
The handle type OCI_HTYPE_DIRPATH_FN_CTX
is passed to OCIHandleAlloc()
to indicate that a function context is to be allocated, as in the following example.
OCIDirPathCtx *dpctx; /* direct path context */ OCIDirPathFuncCtx *dpfnctx; /* direct path function context */ sword error; error = OCIHandleAlloc((void *)dpctx, (void **)&dpfnctx, OCI_HTYPE_DIRPATH_FN_CTX, (size_t)0, (void **)0);
Note that the parent handle of a direct path function context is always the direct path context handle. A direct path function context handle is freed with:
error = OCIHandleFree(dpfnctx, OCI_HTYPE_DIRPATH_FN_CTX);
These handles are used to present an array of rows to the direct path interface. A row is represented by three arrays: column values, column lengths, and column flags. Methods used on a column array include: allocate the array handle and set or get values corresponding to an array entry.
Both handles share the same data structure, OCIDirPathColArray
. But these column array handles differ in parent handles and handle types.
A direct path column array handle is allocated with OCIHandleAlloc()
. The following code fragment shows explicit allocation of the direct path column array handle:
OCIDirPathCtx *dpctx; /* direct path context */ OCIDirPathColArray *dpca; /* direct path column array */ sword error; error = OCIHandleAlloc((void *)dpctx, (void **)&dpca, OCI_HTYPE_DIRPATH_COLUMN_ARRAY, (size_t)0, (void **)0);
A direct path column array handle is freed with OCIHandleFree()
.
error = OCIHandleFree(dpca, OCI_HTYPE_DIRPATH_COLUMN_ARRAY);
A direct path function column array handle is allocated in almost the same way:
OCIDirPathFuncCtx *dpfnctx; /* direct path function context */ OCIDirPathColArray *dpfnca; /* direct path function column array */ sword error; error = OCIHandleAlloc((void *)dpfnctx, (void **)&dpfnca, (ub4)OCI_HTYPE_DIRPATH_FN_COL_ARRAY, (size_t)0, (void **)0);
A direct path function column array is freed with OCIHandleFree()
:
error = OCIHandleFree(dpfnca, OCI_HTYPE_DIRPATH_FN_COL_ARRAY);
Freeing a OCIDirPathColArray
handle also frees the column array associated with the handle.
This handle is used by the conversion operation, OCIDirPathColArrayToStream(), and by the load operation, OCIDirPathLoadStream().
Direct path stream handles is allocated by the client with OCIHandleAlloc()
. The structure of a OCIDirPathStream
handle can be thought of as a pair in the form (buffer, buffer length).
A direct path stream is a linear representation of Oracle table data. The conversion operations always append to the end of the stream. Load operations always start from the beginning of the stream. After a stream is completely loaded, the stream must be reset by calling OCIDirPathStreamReset()
.
The following example shows a direct path stream handle allocated with OCIHandleAlloc()
. The parent handle is always an OCIDirPathCtx
handle:
OCIDirPathCtx *dpctx; /* direct path context */ OCIDirPathStream *dpstr; /* direct path stream */ sword error; error = OCIHandleAlloc((void *)dpctx, (void **)&dpstr, OCI_HTYPE_DIRPATH_STREAM, (size_t)0,(void **)0);
A direct path stream handle is freed using OCIHandleFree()
.
error = OCIHandleFree(dpstr, OCI_HTYPE_DIRPATH_STREAM);
Freeing an OCIDirPathStream
handle also frees the stream buffer associated with the handle.
The functions listed in this section are used with the direct path load interface.
See Also:
Detailed descriptions of each function can be found in "Direct Path Loading Functions"Operations on the direct path context are performed by the functions in Table 13-1.
Table 13-1 Direct Path Context Functions
Function | Purpose |
---|---|
|
Aborts a direct path operation |
|
Executes a data savepoint |
|
Commits the loaded data |
|
Flushes a partially loaded row from server. This function is deprecated. |
|
Loads data that has been converted to direct path stream format |
|
Prepares direct path interface to convert or load rows |
Operations on the direct path column array are performed by the functions in Table 13-2, "Direct Path Column Array Functions".
Table 13-2 Direct Path Column Array Functions
Function | Purpose |
---|---|
|
Gets a specified entry in a column array |
|
Sets a specified entry in a column array to a specific value |
|
Gets the base row pointers for a specified row number |
|
Resets the row array state |
|
Converts from a column array format to a direct path stream format |
Operations on the direct path stream are performed by the function OCIDirPathStreamReset() which resets the direct stream state.
The direct path load interface has the following limitations that are the same as SQL*Loader:
Triggers are not supported.
Referential integrity constraints are not supported.
Clustered tables are not supported.
Loading of remote objects is not supported.
LONGs
must be specified last.
SQL strings that return LOBs, objects, or collections are not supported.
All partitioning columns must come before any LOBs. This is because we need to determine what partition the LOB will go into before we start writing to it.
Here are some code examples for scalar columns.
The following data structure is used in the example.
/* load control structure */ struct loadctl { ub4 nrow_ctl; /* number of rows in column array */ ub2 ncol_ctl; /* number of columns in column array */ OCIEnv *envhp_ctl; /* environment handle */ OCIServer *srvhp_ctl; /* server handle */ OCIError *errhp_ctl; /* error handle */ OCIError *errhp2_ctl; /* yet another error handle */ OCISvcCtx *svchp_ctl; /* service context */ OCISession *authp_ctl; /* authentication context */ OCIParam *colLstDesc_ctl; /* column list parameter handle */ OCIDirPathCtx *dpctx_ctl; /* direct path context */ OCIDirPathColArray *dpca_ctl; /* direct path column array handle */ OCIDirPathColArray *dpobjca_ctl; /* dp column array handle for obj*/ OCIDirPathColArray *dpnestedobjca_ctl; /* dp col array hndl for nested obj*/ OCIDirPathStream *dpstr_ctl; /* direct path stream handle */ ub1 *buf_ctl; /* pre-alloc'd buffer for out-of-line data */ ub4 bufsz_ctl; /* size of buf_ctl in bytes */ ub4 bufoff_ctl; /* offset into buf_ctl */ ub4 *otor_ctl; /* Offset to Recnum mapping */ ub1 *inbuf_ctl; /* buffer for input records */ struct pctx pctx_ctl; /* partial field context */ boolean loadobjcol_ctl; /* load to obj col(s)? T/F */ };
The header file cdemodp.h
, which is from the demo
directory, defines several structs:
#ifndef cdemodp_ORACLE # define cdemodp_ORACLE # include <oratypes.h> # ifndef externdef # define externdef # endif /* External column attributes */ struct col { text *name_col; /* column name */ ub2 id_col; /* column load id */ ub2 exttyp_col; /* external type */ text *datemask_col; /* datemask, if applicable */ ub1 prec_col; /* precision, if applicable */ sb1 scale_col; /* scale, if applicable */ ub2 csid_col; /* character set id */ ub1 date_col; /* is column a chrdate or date? 1=TRUE. 0=FALSE */ struct obj * obj_col; /* description of object, if applicable */ #define COL_OID 0x1 /* col is an OID */ ub4 flag_col; }; /* Input field descriptor * For this example (and simplicity), * fields are strictly positional. */ struct fld { ub4 begpos_fld; /* 1-based beginning position */ ub4 endpos_fld; /* 1-based ending position */ ub4 maxlen_fld; /* max length for out of line field */ ub4 flag_fld; #define FLD_INLINE 0x1 #define FLD_OUTOFLINE 0x2 #define FLD_STRIP_LEAD_BLANK 0x4 #define FLD_STRIP_TRAIL_BLANK 0x8 }; struct obj { text *name_obj; /* type name*/ ub2 ncol_obj; /* number of columns in col_obj*/ struct col *col_obj; /* column attributes*/ struct fld *fld_obj; /* field descriptor*/ ub4 rowoff_obj; /* current row offset in the column array*/ ub4 nrows_obj; /* number of rows in col array*/ OCIDirPathFuncCtx *ctx_obj; /* Function context for this obj column*/ OCIDirPathColArray *ca_obj; /* column array for this obj column*/ ub4 flag_obj; /* type of obj */ #define OBJ_OBJ 0x1 /* obj col */ #define OBJ_OPQ 0x2 /* opaque/sql str col */ #define OBJ_REF 0x4 /* ref col */ }; struct tbl { text *owner_tbl; /* table owner */ text *name_tbl; /* table name */ text *subname_tbl; /* subname, if applicable */ ub2 ncol_tbl; /* number of columns in col_tbl */ text *dfltdatemask_tbl; /* table level default date mask */ struct col *col_tbl; /* column attributes */ struct fld *fld_tbl; /* field descriptor */ ub1 parallel_tbl; /* parallel: 1 for true */ ub1 nolog_tbl; /* no logging: 1 for true */ ub4 xfrsz_tbl; /* transfer buffer size in bytes */ text *objconstr_tbl; /* obj constr/type if loading a derived obj */ }; struct sess /* options for a direct path load session */ { text *username_sess; /* user */ text *password_sess; /* password */ text *inst_sess; /* remote instance name */ text *outfn_sess; /* output filename */ ub4 maxreclen_sess; /* max size of input record in bytes */ }; #endif /* cdemodp_ORACLE */
The following sample code illustrates the use of several of the OCI direct path interfaces. It is not a complete code example.
The init_load function performs a direct path load using the direct path API on the table described by tblp. The loadctl structure given by ctlp has an appropriately initialized environment and service context. A connection has been made to the server.
STATICF void init_load(ctlp, tblp) struct loadctl *ctlp; struct tbl *tblp; { struct col *colp; struct fld *fldp; sword ociret; /* return code from OCI calls */ OCIDirPathCtx *dpctx; /* direct path context */ OCIParam *colDesc; /* column parameter descriptor */ ub1 parmtyp; ub1 *timestamp = (ub1 *)0; ub4 size; ub4 i; ub4 pos; /* allocate and initialize a direct path context */ /* See cdemodp.c for the definition of OCI_CHECK */ OCI_CHECK(ctlp->envhp_ctl, OCI_HTYPE_ENV, ociret, ctlp, OCIHandleAlloc((void *)ctlp->envhp_ctl, (void **)&ctlp->dpctx_ctl, (ub4)OCI_HTYPE_DIRPATH_CTX, (size_t)0, (void **)0)); dpctx = ctlp->dpctx_ctl; /* shorthand */ OCI_CHECK(ctlp->errhp_ctl, OCI_HTYPE_ERROR, ociret, ctlp, OCIAttrSet((void *)dpctx, (ub4)OCI_HTYPE_DIRPATH_CTX, (void *)tblp->name_tbl, (ub4)strlen((const char *)tblp->name_tbl), (ub4)OCI_ATTR_NAME, ctlp->errhp_ctl));
Additional attributes, such as OCI_ATTR_SUB_NAME
and OCI_ATTR_SCHEMA_NAME
, are also set here. After the attributes have been set, prepare the load.
OCI_CHECK(ctlp->errhp_ctl, OCI_HTYPE_ERROR, ociret, ctlp, OCIDirPathPrepare(dpctx, ctlp->svchp_ctl, ctlp->errhp_ctl));
Note that the direct path context handle is the parent handle for the column array and stream handles. Also note that errors are returned with the environment handle associated with the direct path context.
OCI_CHECK(ctlp->envhp_ctl, OCI_HTYPE_ENV, ociret, ctlp, OCIHandleAlloc((void *)ctlp->dpctx_ctl, (void **)&ctlp->dpca_ctl, (ub4)OCI_HTYPE_DIRPATH_COLUMN_ARRAY, (size_t)0, (void **)0)); OCI_CHECK(ctlp->envhp_ctl, OCI_HTYPE_ENV, ociret, ctlp, OCIHandleAlloc((void *)ctlp->dpctx_ctl,(void **)&ctlp->dpstr_ctl, (ub4)OCI_HTYPE_DIRPATH_STREAM, (size_t)0, (void **)0));
Get number of rows and columns in the column array just allocated.
OCI_CHECK(ctlp->errhp_ctl, OCI_HTYPE_ERROR, ociret, ctlp, OCIAttrGet(ctlp->dpca_ctl, (ub4)OCI_HTYPE_DIRPATH_COLUMN_ARRAY, &ctlp->nrow_ctl, 0, OCI_ATTR_NUM_ROWS, ctlp->errhp_ctl)); OCI_CHECK(ctlp->errhp_ctl, OCI_HTYPE_ERROR, ociret, ctlp, OCIAttrGet(ctlp->dpca_ctl, (ub4)OCI_HTYPE_DIRPATH_COLUMN_ARRAY, &ctlp->ncol_ctl, 0, OCI_ATTR_NUM_COLS, ctlp->errhp_ctl));
Set the input data fields to their corresponding data columns.
ub4 rowoff; /* column array row offset */ ub4 clen; /* column length */ ub1 cflg; /* column state flag */ ub1 *cval; /* column character value */ OCI_CHECK(ctlp->errhp_ctl, OCI_HTYPE_ERROR, ociret, ctlp, OCIDirPathColArrayEntrySet(ctlp->dpca_ctl, ctlp->errhp_ctl, rowoff, colp->id_col, cval, clen, cflg));
Reset column array state in case a previous conversion needed to be continued or a row is expecting more data.
(void) OCIDirPathColArrayReset(ctlp->dpca_ctl, ctlp->errhp_ctl);
Reset the stream state to start a new stream. Otherwise, data in the stream is appended to existing data.
(void) OCIDirPathStreamReset(ctlp->dpstr_ctl, ctlp->errhp_ctl);
After inputting the data, convert the data in the column array to stream format and filter out any bad records.
ub4 rowcnt; /* number of rows in column array */ ub4 startoff; /* starting row offset into column array */ /* convert array to stream, filter out bad records */ ocierr = OCIDirPathColArrayToStream(ctlp->dpca_ctl, ctlp->dpctx_ctl, ctlp->dpstr_ctl, ctlp->errhp_ctl, rowcnt, startoff);
Note that the position in the stream is maintained internally to the stream handle, along with offset information for the column array which produced the stream. When the conversion to stream format is done, the data is appended to the stream. It is the responsibility of the caller to reset the stream when appropriate. On errors, the position is moved to the next row, or the end of the stream if the error occurs on the last row. The next OCIDirPathLoadStream()
call starts on the next row, if any. If a OCIDirPathLoadStream()
call is made, and the end of a stream has been reached, OCI_NO_DATA
is returned.
/* load the stream */ ociret = OCIDirPathLoadStream(ctlp->dpctx_ctl, ctlp->dpstr_ctl, ctlp->errhp_ctl);
/* free up server data structures for the load */ OCI_CHECK(ctlp->errhp_ctl, OCI_HTYPE_ERROR, ociret, ctlp, OCIDirPathFinish(ctlp->dpctx_ctl, ctlp->errhp_ctl));
Free all the direct path handles allocated. Note that direct path column array and stream handles are freed before the parent direct path context handle is freed.
ociret = OCIHandleFree((void *)ctlp->dpca_ctl, OCI_HTYPE_DIRPATH_COLUMN_ARRAY); ociret = OCIHandleFree((void *)ctlp->dpstr_ctl, OCI_HTYPE_DIRPATH_STREAM); ociret = OCIHandleFree((void *)ctlp->dpctx_ctl, OCI_HTYPE_DIRPATH_CTX);
The date cache feature provides improved performance when loading Oracle date and timestamp values that require datatype conversions in order to be stored in the table.
This feature is specifically targeted to loads where the same input date values are loaded over and over again. Date conversions are very expensive and can account for a large percentage of the total load time, especially if there are multiple date columns loaded. This feature can significantly improve performance by reducing the actual number of date conversions done when many duplicate date values occur in the input data. However, date cache will only improve performance when many duplicate input date values are loaded into date columns (the word date in this chapter applies to all the date and timestamp datatypes).
When you explicitly specify the date cache size, the date cache feature will not be disabled, by default. To override this behavior, set OCI_ATTR_DIRPATH_DCACHE_DISABLE
to 1. Otherwise, the cache will continue to be searched to avoid date conversions. However any misses will be converted the hard way.
Query the attributes OCI_ATTR_DIRPATH_DCACHE_NUM
, OCI_ATTR_DIRPATH_DCACHE_MISSES
, OCI_ATTR_DIRPATH_DCACHE_HITS
and then tune the cache size for future loads.
You can lower the cache size when there are no misses and the number of elements in the cache is less than the cache size. The cache size can be increased if there are many cache misses and relatively few hits. Note that increasing the cache size too much can cause other problems, like paging or exhausting memory. If increasing the cache size does not improve performance, the feature should not be used.
The date cache feature can be explicitly and totally disabled by setting the date cache size to 0.
The following OCI direct path context attributes support this functionality:
This attribute, when not equal to 0, sets the date cache size (in elements) for a table. For example, if the date cache size is set to 200, then at most 200 unique date or timestamp values can be stored in the cache. The date cache size cannot be changed once OCIDirPathPrepare()
has been called. The default value is 0, meaning a date cache will not be created for a table. A date cache will be created for a table only if one or more date or timestamp values are loaded that require datatype conversions and the attribute value is nonzero.
This attribute is used to query the current number of entries in a date cache.
This attribute is used to query the current number of date cache misses. If this number is high, consider tuning the application with a larger date cache size. If increasing the date cache size doesn't cause this number to decrease significantly, the date cache should probably not be used. Date cache misses are expensive, due to hashing and look up times.
This attribute is used to query the number of date cache hits. This number should be relatively large in order to see any benefit of using the date cache support.
Setting this attribute to 1 indicates that the date cache should be disabled if the size is exceeded. Note that this attribute cannot be changed or set after OCIDirPathPrepare()
has been called.
The default (= 0) is to not disable a cache on overflow. When not disabled, the cache is searched to avoid conversions, but overflow input date value entries will not be added to the date cache, and will be converted using expensive date conversion functions. Again, excessive date cache misses can cause the application to run slower than not using the date cache at all.
This attribute can also be queried to see if a date cache has been disabled due to overflow.
The use of the direct path function contexts to load various non-scalar types is discussed in this section.
The non-scalar types are:
nested tables
object tables (FINAL
and NOT FINAL
)
column objects (FINAL
and NOT FINAL
)
REF columns (FINAL
and NOT FINAL
)
SQL string columns
See Also:
Table B-1, "OCI Demonstration Programs" for a listing of the programs demonstrating direct path loading that are available with your Oracle installation.Nested tables are stored in a separate table. Using the direct path loading API, a nested table is loaded separately from its parent table with a foreign key, called a SETID
, to link the two tables together.
Note:
Currently, the SETID
s must be user-supplied, and are not system-generated.
When loading the parent and child tables separately, it is possible that orphaned children can be created when the rows are inserted in the child table, but the corresponding parent row is not inserted in the parent table. It is also possible to insert a parent row in the parent table, but that the child rows are not inserted in the child table and therefore it will have missing children.
Note:
Steps that are different from loading scalar data are in italics.Loading the parent table with a nested table column is a separate action from loading the child nested table.
To load the parent table with a nested-table column:
Describe the parent table and its columns as usual, except:
When describing the nested-table column, this is the column that stores the SETIDs. Its external datatype is SQLT_CHR if the SETIDs in the data file are in characters, SQLT_BIN if binary.
To load the nested table (child):
Describe the nested table and its columns as usual.
The SETID column is required.
Set its OCI_ATTR_NAME using a dummy name (for example "setid") because the API does not expect you to know its system name.
Set the column attribute with OCI_ATTR_DIRPATH_SID to indicate that this is a SETID column:
ub1 flg = 1; sword error; error = OCIAttrSet((void *)colDesc, OCI_DTYPE_PARAM, (void *)&flg, (ub4)0, OCI_ATTR_DIRPATH_SID, ctlp->errhp_ctl);
A column object is a table column that is defined as an object. Currently only the default constructor, which consists of all of the constituent attributes, is supported.
To describe a column object and its object attributes, use a direct path function context. Describing a column object requires setting its object constructor. Describing object attributes is similar to describing a list of scalar columns.
To describe a column object:
Note:
Nested column objects are supported.
The steps here are similar to that of describing a list of scalar columns to be loaded for a table. Steps that are new are in italics.
1. Allocate a parameter handle on the column object with OCI_DTYPE_PARAM
. This parameter handle is used to set the column's external attributes.
2. Set the column name and its other external column attributes (for example, maximum data size, precision, scale).
3. Set the external type as SQLT_NTY (named type) with OCI_ATTR_DATA_TYPE.
4. Allocate a direct path function context handle. This context will be used to describe the column's object type and attributes:
OCIDirPathFuncCtx *dpfnctx /* direct path function context */; sword error; error = OCIHandleAlloc((void *)dpctx, (void **)&dpfnctx, OCI_HTYPE_DIRPATH_FN_CTX, (size_t)0, (void **)0);
5. Set the column's object type name (for example, "Employee") with OCI_ATTR_NAME in the function context:
OCIDirPathFuncCtx *dpfnctx; /* direct path function context */ text *obj_type; /* column object's object type */ sword error; error = OCIAttrSet((void *)dpfnctx, OCI_HTYPE_DIRPATH_FN_CTX, (void *)obj_type, (ub4)strlen((const char *)obj_type), OCI_ATTR_NAME, ctlp->errhp_ctl);
6. Set the expression type, OCI_ATTR_DIRPATH_EXPR_TYPE, to be OCI_DIRPATH_EXPR_OBJ_CONSTR. This indicates that the expression set with OCI_ATTR_NAME will be used as the default object constructor:
OCIDirPathFuncCtx *dpfnctx; /* direct path function context */ ub1 expr_type = OCI_DIRPATH_EXPR_OBJ_CONSTR; sword error; error = OCIAttrSet((void *)dpfnctx, OCI_HTYPE_DIRPATH_FN_CTX, (void *)&expr_type, (ub4)0, OCI_ATTR_DIRPATH_EXPR_TYPE, ctlp->errhp_ctl);
7. Set the number of columns or object attributes that will be loaded for this column object using OCI_ATTR_NUM_COLS.
8. Get the column/attribute parameter list for the function context OCIDirPathFuncCtx
.
9. For each object attribute:
Get the column descriptor for the object attribute with OCI_DTYPE_PARAM
.
Set the attribute's column name with OCI_ATTR_NAME
.
Set the external column type (the type of the data that will be passed to the direct path API) with OCI_ATTR_DATA_TYPE
.
Set any other external column attributes (maximum data size, precision, scale, and so on.)
If this attribute column is a column object, then do steps 3-10 for its object attributes.
Free the handle to the column descriptor.
10. Set the function context OCIDirPathFuncCtx
that was created in step 4 into the parent column object's parameter handle with OCI_ATTR_DIRPATH_FN_CTX.
When loading a column object, the data for its object attributes will be loaded into a separate column array created just for that object. A child column array is allocated for each column object, whether it is nested or not. Each row of object attributes in the child column array maps back to the corresponding non-NULL row of its parent column object in the parent column array.
Use the column object's direct path function context handle and column array type OCI_HTYPE_DIRPATH_FN_COL_ARRAY
.
To allocate a child column array for a column object:
OCIDirPathFuncCtx *dpfnctx; /* direct path function context */ OCIDirPathColArray *dpfnca; /* direct path function column array */ sword error; error = OCIHandleAlloc((void *)dpfnctx, (void **)&dpfnca, OCI_HTYPE_DIRPATH_FN_COL_ARRAY, (size_t)0, (void **)0);
If a column is scalar, its value is set in the column array by passing the address of its value to OCIDirPathColArrayEntrySet()
. And if a column is an object, the address of its child column array handle is passed instead. The child column array will contain the data of the object attributes.
To load data into a column object:
Note:
Steps that are different from loading scalar data are in italics.(Start.) For each column object:
If the column is non-NULL:
For each of its object attribute columns:
If an object attribute is a nested column object, then go to (Start.) and do this entire procedure recursively.
Set the data in the child column array using OCIDirPathColArrayEntrySet().
Set the column object's data in the column array by passing the address of its child column array handle to OCIDirPathColArrayEntrySet()
.
Else if the column is NULL:
Set the column object's data in the column array by passing a NULL address for the data, a length of 0, and an OCI_DIRPATH_COL_NULL
flag to OCIDirPathColArrayEntrySet()
.
This value is passed to OCIDirPathColArrayEntry()
to indicate that the current column array row should be ignored. A typical use of this value is to back out all previous conversions for a row when an error occurs providing more data for a partial column (OCI_NEED_DATA
was returned from the previous OCIDirPathColArrayToStream()
call). Any previously converted data placed in the output stream buffer for the current row is removed. Conversion then continues with the next row in the column array. The purged row is counted in the converted row count.
When OCI_DIRPATH_COL_ERROR
is specified, the current row is ignored, as well as are any corresponding rows in any child column arrays referenced, starting from the top level column array row. Any NULL
child column array references are ignored when moving all referenced child column arrays to their next row.
A column value can be computed by a SQL string. SQL strings can be used for scalar column types. SQL strings cannot be used for object types, but can be used for object attributes of scalar column types. They cannot be used for nested tables and LONGs.
A SQL expression is represented to the direct path API using the OCIDirPathFuncCtx
. Its OCI_ATTR_NAME
value will be the SQL string with the parameter list of the named bind variables for the expression.
The bind variable namespace is limited to a column's SQL string. The same bind variable name can be used for multiple columns, but any arguments with the same name only apply to the SQL string of that column.
If a SQL string of a column contains multiple references to a bind variable and multiple arguments are specified for that name, all of the values must be the same, otherwise the results are undefined. Only one argument is actually required for this case, as all references to the same bind variable name in a particular SQL expression will be bound to that single argument.
A SQL string example is:
substr(substr(:string, :offset, :length), :offset, :length)
Things to note about this example are:
SQL expressions can be nested.
Bind variable names can be repeated within the expression.
Note:
Steps that are different from loading scalar data are in italics.Allocate a parameter handle on the SQL string column with OCI_DTYPE_PARAM
. This parameter handle is used to set the column's external attributes.
Set the column name and its other external column attributes (for example, maximum data size, precision, scale).
Set the SQL string column's external type as SQLT_NTY with OCI_ATTR_DATA_TYPE.
Allocate a direct path function context handle. This context will be used to describe the arguments of the SQL string.
OCIDirPathFuncCtx *dpfnctx /* direct path function context */; sword error; error = OCIHandleAlloc((void *)dpctx, (void **)&dpfnctx, OCI_HTYPE_DIRPATH_FN_CTX, (size_t)0, (void **)0);
Set the column's SQL string in OCI_ATTR_NAME in the function context.
OCIDirPathFuncCtx *dpfnctx; /* direct path function context */ text *sql_str; /* column's SQL string expression */ sword error; error = OCIAttrSet((void *)dpfnctx, OCI_HTYPE_DIRPATH_FN_CTX, (void *)sql_str, (ub4)strlen((const char *)sql_str), OCI_ATTR_NAME, ctlp->errhp_ctl);
Set the expression type, OCI_ATTR_DIRPATH_EXPR_TYPE, to be OCI_DIRPATH_EXPR_SQL. This indicates that the expression set with OCI_ATTR_NAME will be used as the SQL string to derive the value from.
OCIDirPathFuncCtx *dpfnctx; /* direct path function context */ ub1 expr_type = OCI_DIRPATH_EXPR_SQL; sword error; error = OCIAttrSet((void *)dpfnctx, OCI_HTYPE_DIRPATH_FN_CTX, (void *)&expr_type, (ub4)0, OCI_ATTR_DIRPATH_EXPR_TYPE, ctlp->errhp_ctl);
Set the number of arguments that will be passed to the SQL string with OCI_ATTR_NUM_COLS.
Get the column/attribute parameter list for the function context.
For each SQL string argument:
Get the column descriptor for the object attribute with OCI_DTYPE_PARAM
.
The order in which the SQL string arguments are defined does not matter. The order does not have to match the order used in the SQL string.
Set the attribute's column name with OCI_ATTR_NAME
.
There is a naming convention for SQL string arguments.
The argument names must match the bind variable names used in the SQL string in content but not in case. For example, if the SQL string is "substr(:INPUT_STRING, 3, 5)", then it is acceptable if you give the argument name as "input_string".
If an argument is used multiple times in an SQL string, declaring it once and counting it as one argument only is correct.
Set the external column type (the type of the data that will be passed to the direct path API) with OCI_ATTR_DATA_TYPE
.
Set any other external column attributes (maximum data size, precision, scale, and so on).
Free the handle to the column descriptor.
Set the function context OCIDirPathFuncCtx
that was created in step 4 into the parent column object's parameter handle with OCI_ATTR_DIRPATH_FN_CTX.
When loading a SQL string column, the data for its arguments will be loaded into a separate column array created just for that SQL string column. A child column array is allocated for each SQL string column. Each row of arguments in the child column array maps back to the corresponding non-NULL row of its parent SQL string column in the parent column array.
To allocate a child column array for a SQL string column:
OCIDirPathFuncCtx *dpfnctx; /* direct path function context */ OCIDirPathColArray *dpfnca; /* direct path function column array */ sword error; error = OCIHandleAlloc((void *)dpfnctx, (void **)&dpfnca, OCI_HTYPE_DIRPATH_FN_COL_ARRAY, (size_t)0, (void **)0);
If a column is scalar, its value would be set in the column array by passing the address of its value to OCIDirPathColArrayEntrySet()
. If a column is of a SQL string type, the address of its child column array handle would be passed instead. The child column array would contain the SQL string's argument data.
To load data into a SQL string column:
Note:
Steps that are different from loading scalar data are in italics.For each SQL string column:
If the column is non-NULL:
For each of its function argument columns:
Set the data in the child column array using OCIDirPathColArrayEntrySet().
Set the SQL string column's data into the column array by passing the address of its child column array handle to OCIDirPathColArrayEntrySet().
Else if the column is NULL:
Set the SQL string column data into the column array by passing a NULL address for the data, a length of 0, and an OCI_DIRPATH_COL_NULL
flag to OCIDirPathColArrayEntrySet()
.
This process is similar to that for column objects.
See Also:
"OCI_DIRPATH_COL_ERROR"The REF type is a pointer, or reference, to a row object in an object table.
Describing the arguments to a REF column is similar to describing the list of columns to be loaded for a table.
Note:
A REF column can be a top-table-level column or nested as an object attribute to a column object.Steps that are different from loading scalar data are in italics.
Get a parameter handle on the REF column with OCI_DTYPE_PARAM
. This parameter handle is used to set the column's external attributes.
Set the column name and its other external column attributes (for example, maximum data size, precision, scale).
Set the REF column's external type as SQLT_REF with OCI_ATTR_DATA_TYPE.
Allocate a direct path function context handle. This context is used to describe the REF column's arguments.
OCIDirPathFuncCtx *dpfnctx; /* direct path function context */ sword error; error = OCIHandleAlloc((void *)dpctx, (void **)&dpfnctx, OCI_HTYPE_DIRPATH_FN_CTX, (size_t)0, (void **)0);
OPTIONAL: Set the REF column's table name in OCI_ATTR_NAME in the function context. See the next step for more details.
OCIDirPathFuncCtx *dpfnctx; /* direct path function context */ text *ref_tbl; /* column's reference table */ sword error; error = OCIAttrSet((void *)dpfnctx, OCI_HTYPE_DIRPATH_FN_CTX, (void *)ref_tbl, (ub4)strlen((const char *)ref_tbl), OCI_ATTR_NAME, ctlp->errhp_ctl);
OPTIONAL: Set the expression type, OCI_ATTR_DIRPATH_EXPR_TYPE, to be OCI_DIRPATH_EXPR_REF_TBLNAME. Set this only if step 5 was done. This indicates that the expression set with OCI_ATTR_NAME will be used as the object table to reference row objects from. This parameter is optional. The behavior for this parameter varies for the REF type.
Unscoped REF columns (unscoped, system-OID-based):
If not set, then by the definition of an "unscoped" REF column, this REF column is required to have a reference table name as its argument for every data row.
If set, this REF column can only refer to row objects from this specified object table for the duration of the load. And the REF column is not allowed to have a reference table name as its argument. (The direct path API is providing this parameter as a short cut to users who will be loading to an unscoped REF column that refers to the same reference object table during the entire load.)
Scoped REF columns (scoped, system-OID-based and primary-key-based):
If not set, the direct path API will use the reference table specified in the schema.
If set, the reference table name must match the object table specified in the schema for this scoped REF column. An error occurs if the table names do not match.
Whether this parameter is set or not, it does not matter to the API whether this reference table name is in the data row or not. If the name is in the data row, it has to match the table name specified in the schema. If it is not in the data row, the API will use the reference table specified in the schema.
Set the number of REF arguments that will be used to reference a row object. with OCI_ATTR_NUM_COLS. The number of arguments required varies for the REF column type. This number is derived from step 6 earlier.
Unscoped REF columns (unscoped, system-OID-based REF columns):
One if OCI_DIRPATH_EXPR_REF_TBLNAME is used. None for the reference table name, and one for the OID value.
Two if OCI_DIRPATH_EXPR_REF_TBLNAME is not used. One for the reference table name, and one for the OID value.
Scoped REF columns (scoped, system-OID-based and primary-key-based):
N or N+1 are acceptable, where N is the number of columns making up the object id, regardless if OCI_DIRPATH_EXPR_REF_TBLNAME is used or not. Minimum is N if the reference table name is not in the data row. It's N+1 if the reference table name is in the data row. Note: If the REF is system-OID-based, then N is one. If the REF is primary-key-based, then N is the number of component columns that make up the primary key. If the reference table name is in the data row, then add one to N.
Note:
To simplify the error message if you were to pass in a number of REF arguments other than N or N+1, the error message will say that it found so-and-so number of arguments when it expects N. Although N+1 is not stated in the message, N+1 is acceptable (even though the reference table name is not needed) and will not invoke an error message.Get the column/attribute parameter list for the function context.
For each REF argument or attribute:
Get the column descriptor for the REF argument using OCI_DTYPE_PARAM
.
Set the attribute's column name using OCI_ATTR_NAME
.
The order of the REF arguments given matter. The reference table name comes first, if given. The object id, whether it is system-generated or primary-key-based, comes next.
There is a naming convention for the REF arguments. Since the reference table name is not a table column, you can use any dummy names for its column name, such as "ref-tbl". For a system-generated OID column, you can use any dummy names for its column name, such as. "sys-OID". For a primary-key-based object id, list all the primary-key columns to load into. There is no need to create a dummy name for OID. The component column names, if given (see short cut note later), can be given in any order.
Do not set the attribute column name(s) for the object id if you want to use the short cut.
Short cut. If loading a system-OID-based REF column, do not set the column name with a name. The API will figure it out. But you will still have to set other column attributes, such as external datatype.
If loading a primary-key REF column and its primary key consists of multiple columns, the short cut is not to set their column names. But you will still have to set other column attributes, such as external datatype.
Note:
If the component column names are NULL, then the API code determines the column names in the position or order in which they were defined for the primary key. So, when you set column attributes other than the name, make sure the attributes are set for the component columns in the correct order.Set the external column type (the type of the data that will be passed to the direct path API) using OCI_ATTR_DATA_TYPE
.
Set any other external column attributes (max data size, precision, scale, and so on).
Free the handle to the column descriptor.
Set the function context OCIDirPathFuncCtx
that was created in step 4 in the parent column object's parameter handle using OCI_ATTR_DIRPATH_FN_CTX.
To allocate a child column array for a REF column:
OCIDirPathFuncCtx *dpfnctx; /* direct path function context */ OCIDirPathColArray *dpfnca; /* direct path function column array */ sword error; error = OCIHandleAlloc((void *)dpfnctx, (void **)&dpfnca, OCI_HTYPE_DIRPATH_FN_COL_ARRAY, (size_t)0, (void **)0);
If a column is scalar, its value would be set in the column array by passing the address of its value to OCIDirPathColArrayEntrySet()
. If a column is a REF, the address of its child column array handle would be passed instead. The child column array will contain the REF arguments' data.
To load data into a REF column:
Note:
Steps that are different from loading scalar data are in italics.For each REF column:
If the column is non-NULL:
For each of its REF argument columns:
Set its data in the child column array using OCIDirPathColArrayEntrySet().
Set the REF column's data into the column array by passing the address of its child column array handle to OCIDirPathColArrayEntrySet().
Else if the column is NULL:
Set the REF column's data into the column array by passing a NULL address for the data, length of 0, and a OCI_DIRPATH_COL_NULL
flag to OCIDirPathColArrayEntrySet()
.
See Also:
"OCI_DIRPATH_COL_ERROR"An example of an inheritance hierarchy is shown in the following section.
In this example, Person
is at the top of the hierarchy. It has two sub-types, Employee
and Student
. ParttimeEmployee
is a sub-type of Employee
. Therefore, the types which can be stored in a Person
column are shown in this diagram:
Person (Name, Address) | | | | Student(Units, GPA) Employee (Manager, Deptid) | | ParttimeEmployee (Hours)
When loading a table which contains a column of type Person
, the actual set of types could include any of these four: the NOT FINAL
type Person
, and its three sub-types: Student
, Employee
, and ParttimeEmployee
. The direct path API only supports the loading of one fixed, derived type to this NOT FINAL
column for the duration of this load. Thus, the API needs to know which one of these types will be loaded, the attributes to load for this type, and the function used to create this type.
Note:
A NOT FINAL
column in a table can only store one fixed, derived type for the duration of the load.
When describing and loading a derived type, all of the attributes for that type that are to be loaded must be specified. Think of a subtype as a flattened representation of all the object attributes that are unique to this type plus all the attributes of its ancestors. Therefore, any of these attribute columns that are to be loaded into will have to be described and counted.
For example, if loading to all columns in ParttimeEmployee
, there are 5 object attributes to load into: Name
, Address
, Manager
, Deptid
, and Hours.
To describe a NOT FINAL
or substitutable object and REF columns of a fixed, derived type:
Note:
The steps describing aNOT FINAL
column of a fixed, derived type is similar to describing its FINAL
counterpart.To describe a NOT FINAL
column of type X (where X is object or REF), refer to previous sections to describe a FINAL
column of this type. Because the derived type (could be a supertype or a subtype) is fixed for the duration of the load, the client interface for describing a NOT FINAL
column is the same as for a FINAL
column.
A subtype can be thought of as a flattened representation of all the object attributes that are unique to this type plus all the attributes of its ancestors. Therefore, any of these attribute columns that are to be loaded into will have to be described and counted.
An object table is a table in which each row is an object (or row object). Each column in the table is an object attribute.
Describing an object table is very similar to describing a non-object table. Each object attribute is a column in the table. The only difference is that you may need to describe the OID, which could be system-generated, user-generated, or primary-key based.
To describe an object table:
Note:
Steps that are different from loading a non-object table are in italics.For each object attribute column:
Describe each object attribute column as it needs to be described, depending on its type (for example, NUMBER, REF):
For the object table OID (Oracle Internet Directory):
If the object id is system-generated:
Nothing extra to do. The system will generate OIDs for each row object.
If the object id is user-generated:
Use a dummy name to represent the column name for the OID (for example, "cust_oid").
Set the OID column attribute with OCI_ATTR_DIRPATH_OID.
If the object id is primary-key-based:
All of the primary-key columns making up the OID must be loaded.
Do not set OCI_ATTR_DIRPATH_OID, because no OID column with a dummy name was created.
A NOT FINAL
object table supports inheritance and a FINAL
object table cannot.
Describing a NOT FINAL
object table of a fixed derived type is very similar to describing a FINAL
object table.
To describe a NOT FINAL
object table of a fixed derived type:
Note:
Steps that are different from loading a FINAL object table are in italics.Set the object table's object type in the direct path context with OCI_ATTR_DIRPATH_OBJ_CONSTR. This indicates that the object type, whether it is a supertype or a derived type, will be used as the default object constructor when loading to this table for the duration of the load.
text *obj_type; /* the object type to load into this NOT FINAL */ /* object table */ sword error; error = OCIAttrSet((void *)dpctx, OCI_HTYPE_DIRPATH_CTX, (void *) obj_type, (ub4)strlen((const char *) obj_type), OCI_ATTR_DIRPATH_OBJ_CONSTR, ctlp->errhp_ctl);
For each of the object attribute columns to be loaded, describe them according to their datatypes. Describe the object id, if needed. This is the same as describing a FINAL
object table.
To support loading data that will not all fit in memory at one time, use loading in pieces.
The direct path API already supports loading LONGs and LOBs incrementally. This is accomplished through the following sequence of steps:
Set the first piece into the column array using OCIDirPathColArrayEntrySet()
and passing in the OCI_DIRPATH_COL_PARTIAL
flag to indicate that all the data for this column has not been loaded yet.
Convert the column array to a stream.
Load the stream.
Set the next piece of that data into the column array. If it is not complete, set the partial flag and go back to step 2. If it is complete, then set the OCI_DIRPATH_COL_COMPLETE
flag and continue on to the next column.
This approach is essentially the same for dealing with large attributes for column objects and large arguments for SQL string types.
See Also:
"OCI_DIRPATH_COL_ERROR"Note:
Collections are not loaded in pieces, as such. Nested tables are loaded separately and are loaded like a top-level table. Nested tables can be loaded incrementally and can have columns which are loaded in pieces. Therefore, do not set theOCI_DIRPATH_COL_PARTIAL
flag for the column containing the collection.Objects are loaded into a separate column array from the parent table which contains them. Therefore, when they need to be loaded in pieces you must set the elements in the child column array up to and including the pieced element.
The general steps are:
For the pieced element, set the OCI_DIRPATH_COL_PARTIAL
flag.
Set the child column array handle into the parent column array and mark that entry with the OCI_DIRPATH_COL_PARTIAL
flag as well.
At this point, convert the parent column array to a stream. This will convert the child column array as well.
Then load the stream.
Go back to step one and continue loading the remaining data for that element until it is complete.
Here are some rules about loading in pieces:
There can only be one partial element at a time at any level. Once one partial element is marked complete then another one at that level could be partial.
If an element is partial and it is not top-level, then all of its ancestors up the containment hierarchy must be marked partial as well.
If there are multiple levels of nesting, it is necessary to go up to a level where the data can be converted into a stream. This will be a top-level table.
See Also:
"OCI_DIRPATH_COL_ERROR"The following discussion gives the supplemental details of the handles and attributes that are listed in the appendix A.
There is one.
Indicates the object type to load into a NOT FINAL
object table.
ttext *obj_type; /* the object type to load into this NOT FINAL */ /* object table */ sword error; error = OCIAttrSet((void *)dpctx, OCI_HTYPE_DIRPATH_CTX, (void *) obj_type, (ub4)strlen((const char *) obj_type), OCI_ATTR_DIRPATH_OBJ_CONSTR, ctlp->errhp_ctl);
Here is a summary of the attributes for function context handles.
Indicates the object type to load into a substitutable object table.
text *obj_type; /* stores an object type name */ sword error; error = OCIAttrSet((void *)dpctx, OCI_HTYPE_DIRPATH_CTX, (void *) obj_type, (ub4)strlen((const char *) obj_type), OCI_ATTR_DIRPATH_OBJ_CONSTR, ctlp->errhp_ctl);
When a function context is created, set OCI_ATTR_NAME
equal to the expression that describes the non-scalar column. Then set an OCI attribute to indicate the type of the expression. The expression type varies as follows:
Column objects:
REF columns:
This optional expression is the reference table name. This table is the object table from which the REF column will be referencing row objects.
Set the expression type OCI_ATTR_DIRPATH_EXPR_TYPE
to OCI_DIRPATH_EXPR_REF_TBLNAME
to indicate this expression is a reference object table.
The behavior for this parameter, set or not set, varies for each REF type.
Unscoped REF columns (unscoped, system-OID-based):
If not set, then by the definition of an "unscoped" REF column, this REF column is required to have a reference table name as its argument for every data row.
If set, this REF column can only refer to row objects from this specified object table for the duration of the load. And the REF column is not allowed to have a reference table name as its argument. (Direct path API is providing this parameter as a short cut to the users who will be loading to an unscoped REF column that refers to the same reference object table during the entire load.)
Scoped REF columns (scoped, system-OID-based and primary-key-based):
If not set, the direct path API will use the reference table specified in the schema.
If set, the reference table name must match the object table specified in the schema for this scoped REF column. An error occurs if the table names do not match.
Whether this parameter is set or not, it will not matter to the API whether this reference table name is in the data row or not. If the name is in the data row, it has to match the table name specified in the schema. If it is not in the data row, the API will use the reference table defined in the schema.
SQL string columns:
This mandatory expression contains a SQL string to derive the value that will be stored in the column.
Set the expression type OCI_ATTR_DIRPATH_EXPR_TYPE
to OCI_DIRPATH_EXPR_SQL
to indicate that this expression is a SQL string.
This attribute is used to indicate the type of the expression specified in OCI_ATTR_NAME
for the non-scalar column's function context.
If OCI_ATTR_NAME
is set, then OCI_ATTR_DIRPATH_EXPR_TYPE
is required.
The possible values for OCI_ATTR_DIRPATH_EXPR_TYPE
are:
Indicates that the expression is an object type name and will be used as the default object constructor for a column object.
Required for column objects.
Indicates that the expression is a reference object table name. This table is the object table from which the REF column will be referencing row objects.
Optional for REF columns.
Indicates that the expression is a SQL string, which is executed to derive a value to be stored in the column.
Required for SQL string columns.
The following pseudocode example illustrates the preceding rules:
OCIDirPathFuncCtx *dpfnctx; /* function context for this non-scalar column */ ub1 expr_type; /* expression type */ sword error; if (...) /* (column type is an object) */ expr_type = OCI_DIRPATH_EXPR_OBJ_CONSTR; ... if (...) /* (column_type is a REF && function context name exists) */ expr_type = OCI_DIRPATH_EXPR_REF_TBLNAME; ... if (...) /* (column_type is a SQL string) */ expr_type = OCI_DIRPATH_EXPR_SQL; ... error = OCIAttrSet((void *)(dpfnctx), OCI_HTYPE_DIRPATH_FN_CTX, (void *)&expr_type, (ub4)0, OCI_ATTR_DIRPATH_EXPR_TYPE, ctlp->errhp_ctl);
This attribute describes the number of attributes or arguments that will be loaded or processed for a non-scalar column. This parameter must be set before the column list can be retrieved.
Column objects:
The number of object attribute columns to be loaded for this column object.
SQL string columns:
The number of arguments to be passed to the SQL string.
If an argument is used multiple times in the function, counting it as one is correct.
REF columns:
The number of REF arguments to identify the row object the REF column should point to.
The number of arguments required varies for the REF column type:
Unscoped REF columns (unscoped, system-OID-based REF columns):
If OCI_DIRPATH_EXPR_REF_TBLNAME
is used. None for the reference table name, and one for the OID value. (Only the OID values will be in the data rows.)
If OCI_DIRPATH_EXPR_REF_TBLNAME
is not used. One for the reference table name, and one for the OID value. (Both the reference table names and the OID values will be in the data rows.)
Scoped REF columns (scoped, system-OID-based and primary-key-based):
N or N+1 are acceptable, where N is the number of columns making up the object id, regardless if OCI_DIRPATH_EXPR_REF_TBLNAME
is used or not. The minimum is N if the reference table name is not in the data row. Use N+1 if the reference table name is in the data row.
If the REF is system-OID-based, then N is one. If the REF is primary-key-based, then N is the number of component columns that make up the primary key. If the reference table name is in the data row, then add one to N.
Note:
To simplify the error message if you pass in a number of REF arguments other than N or N+1, the error message will say that it found so-and-so number of arguments when it expects N. Although N+1 is not stated in the message, N+1 is acceptable (even though the reference table name is not needed) and will not invoke an error message.This attribute, when used for a OCI_HTYPE_DIRPATH_FN_CTX
(function context), is retrievable only, and cannot be set by the user. You can only use this attribute in OCIAttrGet()
and not OCIAttrSet()
. When called with OCIAttrGet()
, the number of rows loaded so far is returned.
However, the attribute OCI_ATTR_NUM_ROWS
, when used for a OCI_HTYPE_DIRPATH_CTX
(table-level context), can be set and can be retrieved by the user.
Calling OCIAttrSet()
with OCI_ATTR_NUM_ROWS
and OCI_HTYPE_DIRPATH_CTX
sets the number of rows to be allocated for the table-level column array. If not set, the direct path API code will derive a "reasonable" number based on the maximum record size and the transfer buffer size. To see how many rows were allocated, call OCIAttrGet()
with OCI_ATTR_NUM_ROWS
on OCI_HTYPE_DIRPATH_COLUMN_ARRAY
for a table-level column array, and with OCI_HTYPE_DIRPATH_FN_COL_ARRAY
for a function column array.
Calling OCIAttrGet()
with OCI_ATTR_NUM_ROWS
and OCI_HTYPE_DIRPATH_CTX
returns the number of rows loaded so far.
This attribute cannot be set by the user for a function context. You are not allowed to specify the number of rows desired in a function column array through OCI_ATTR_NUM_ROWS
with OCIAttrSet() because then all function column arrays will have the same number of rows as the table-level column array. Thus this attribute can only be set for a table-level context and not for a function context.
When describing an object, SQL string, or REF column, one of its column attributes is a function context.
If a column is an object, then its function context describes its object type and object attributes. If a SQL string, the expression to be called. If REF, its reference table name and row object identifiers.
When setting a function context as a column attribute, OCI_ATTR_DIRPATH_FN_CTX
is used in OCIAttrSet()
:
OCIDirPathFuncCtx *dpfnctx; /* direct path function context */ sword error; error = OCIAttrSet((void *)colDesc, OCI_DTYPE_PARAM, (void *)(dpfnctx), (ub4)0, OCI_ATTR_DIRPATH_FN_CTX, ctlp->errhp_ctl);
Attributes for column parameter context handles follow.
The naming conventions when loading nested tables, object tables, SQL string columns, and REF columns are described in the following paragraphs.
In general, a dummy column name is used if are loading data into a column that is a system column with a system name that you are not aware of (for example, an object table's system-generated object id (OID
) column or a nested table's SETID
(SID
) column) or if a column is an argument that doesn't have a database table column (for example, SQL string and REF arguments).
If the column is a database table column, but a dummy name was used, then a column attribute has to be set so that the function can identify the column even though it's not under the name known to the database.
The naming rules are:
Child nested table's SETID
(SID
) column:
The SETID column is required. Set its OCI_ATTR_NAME
using a dummy name, because the API doesn't expect the user to know its system name. Then set the column attribute with OCI_ATTR_DIRPATH_SID
to indicate that this is a SID
column.
Object table's object id (OID
) column:
An object id is required if:
If the object id is system-generated:
Use a dummy name as its column name (for example, "cust_oid").
Set its column attribute with OCI_ATTR_DIRPATH_OID
. So if you have multiple columns with dummy names, you know which one represents the system-generated OID
.
If the object id is primary-key-based:
You cannot use a dummy name as its column name. Therefore, you do not need to set its column attribute with OCI_ATTR_DIRPATH_OID
.
SQL string argument:
Set the attribute's column name with OCI_ATTR_NAME
.
The order of the SQL string arguments given does not matter. The order does not have to match the order used in the SQL string.
There is a naming convention for SQL string arguments.
The argument names must match the bind variable names used in the SQL string in content but not in case. For example, if the SQL string is substr(:INPUT_STRING, 3, 5)
, then you can give the argument name as "input_string".
If an argument is used multiple times in an SQL string, then you can declare it once and count it as only one argument.
REF argument:
Set the attribute's column name using OCI_ATTR_NAME
.
The order of the REF arguments does matter.
The reference table name comes first, if given.
The object id, whether it is system-generated or primary-key-based, comes next.
There is a naming convention for the REF arguments.
For the reference table name argument, use any dummy names for its column name, for example, "ref-tbl".
For the system-generated OID argument, use any dummy names for its column name, such as "sys-OID". Note: Since this column is used as an argument and not as a column to load into, do not set this column with OCI_ATTR_DIRPATH_OID
.
For a primary-key-based object id, list all the primary-key columns to load into. There is no need to create a dummy name for OID. The component column names, if given (see step for short cut later), can be given in any order.
Do not set the attribute column name(s) for the object id if you want to use the short cut.
Short cut. If loading a system-OID-based REF column, do not set the column name with a name. The API will figure it out. But you still have to set other column attributes, such as external datatype.
If loading a primary-key REF column and its primary key consists of multiple columns, the short cut is not to set their column names. But user will still have to set other column attributes, such as external datatype.
Note:
If the component column names are NULL, then the API code determines the column names in the position or order in which they were defined for the primary key. So, when you set column attributes other than the name, make sure the attributes are set for the component columns in the correct order.The handle type OCI_HTYPE_DIRPATH_FN_COL_ARRAY
is used if the column is an object, SQL string, or REF. The structure OCIDirPathColArray
is the same for both scalar and non-scalar columns.
To allocate a child column array for a function context:
OCIDirPathFuncCtx *dpfnctx; /* direct path function context */ OCIDirPathColArray *dpfnca; /* direct path function column array */ sword error; error = OCIHandleAlloc((void *)dpfnctx, (void **)&dpfnca, OCI_HTYPE_DIRPATH_FN_COL_ARRAY, (size_t)0, (void **)0);