VgwDocFieldReadFnc


Use the VgwDocFieldReadFnc function to return the values of external fields associated with a document. The Verity engine calls your VgwDocFieldReadFnc function when it needs to read the contents of specific fields or when it is indexing and the gateway’s style file contains a copy statement to create an internal field from an external field.


Syntax

VdkError VgwDocFieldReadFnc(
   VgwAppSession vgwSession,
   VdkUser vdkUser,
   VgwDocFieldReadArg   vgwFieldReadArg,
   VgwDataTable*        pvgwTable)

Arguments

 


vgwSession

VgwAppSession   The session handle that contains session-related data, which was set in your driver’s VgwSessionNewFnc function.

vdkUser

VdkUser   A handle that identifies the user requesting access to the specified document.

vgwFieldReadArg

VgwDocFieldReadArg   A pointer to information about the document and fields whose values are requested.

pvgwTable

VgwDataTable*   A pointer to the structure that will return the field values and related information.


Member Descriptions

 

Table 5-1    VgwDocFieldReadArgRec Members 


Member

Type/Description

key

VdkDocKey   The document key of the document whose external fields are being requested.

maxColumnSize

VdkUint2   The maximum size for each stream or text field, or 0 if there is no maximum size specified.

columnCount

VdkUint2   The number of fields to read.

columnArray

VdkString*   A list that contains the names of the fields to read.

docSet

VdkDocSet   Reserved for future use.

docSetRow

VdkUint4   Reserved for future use.


 

Table 5-2    VgwDataTableRec Members


Member

Type/Description

session

VgwAppSession   The session handle, which is passed in via the vgwSession argument.

numRows

VdkUint4   The number of documents in the values array; set numRows to 1.

numColumns

VdkUint2   The number of fields in the values array.

columnArray

VgwColumnInfo*   A pointer to an array of VgwColumnInfo pointers that contain information about each field. (See VgwColumnInfoRec members below.)

values

VdkVoidp*   A pointer to a table of values.

internal

VdkVoidp   For internal use by the gateway.


 

Table 5-3    VgwColumnInfoRec Members


Member

Type/Description

type

VdkFieldType   The field data type flag. Valid values are:

VdkFieldType_Invalid for unsupported field names

VdkFieldType_Text for text strings

VdkFieldType_Signed for signed integers

VdkFieldType_Unsigned for unsigned integers

VdkFieldType_Date for VdkDate type data

VdkFieldType_Float for double floats

VdkFieldType_Stream for a binary blob of data

name

VdkCString   Name of the external field.

size

VdkUint4   The data size, in bytes, or 0 for ASCIIZ (null-terminated strings).

flags

VdkInt2   Behavior flags, which are ORed together to specify how to treat this field when it is retrieved from the repository. You can set the following values:

VgwColumn_ReadOnly for field values that are not to be changed

VgwColumn_Inline for fields that contain the actual value, not a pointer to the value

VgwColumn_PrimaryKey for fields whose value is the primary key for the gateway; for example, the VdkVgwKey field should have this flag set

VgwColumn_RedirectFile for fields whose value is a the full pathname of a data file

VgwColumn_Redirect_URL for fields whose value is a URL to a data file

VgwColumn_Attachment for fields whose value is the full pathname to an attachment or subdocument

internal

VdkVoidp   For internal use by the gateway.

precedence

VdkInt2   Internal.



Returns

This function must return one of the following error codes:

VdkSuccess for success

 

VdkError_* for a standard Verity Developer Kit API error as described in the Verity Developer’s Kit Programming Reference

 

VdkFail for a non-specific error

 


Discussion

Your VgwDocFieldReadFnc function must populate a VgwDataTable structure with the values of the requested external fields that the specified user is allowed to access. The function should then assign the structure to pvgwTable. External fields are defined by your driver’s VgwGetSchemaFnc callback function.

The requested fields are specified in the columnArray member of the VgwDocFieldReadArgRec structure, which is passed to your function. Your VgwDocFieldReadFnc function must assign values for these fields to the values member of the VgwDataTableRec structure.

The values member is a pointer to a vector of values that can represent a two-dimensional array (table), in which the innermost iterator specifies a document and the outermost iterator specifies the field values for the document. Because the VgwDocFieldReadFnc function is called for only one document at a time, your function should only fill the first row. Thus, you can treat the values member as a one-dimensional array in which you store field values in the order that they are specified in the columnArray member of the VgwDocFieldReadArgRec structure.

For each field, you must also include the field’s attributes in the columnArray member of the VgwDataTableRec structure. The columnArray member points to an array of VgwColumnInfoRec structures that contain information about each field, which is the same information, with three exceptions, that you specified in your driver’s VgwGetSchemaFnc callback function. If this information was saved in the session data, you can retrieve it via the vgwSession argument.

The three exceptions to using the same VgwColumnInfoRec structures are as follows:

If the requested field does not exist in the schema, you must still provide a VgwColumnInfoRec structure; however, the type member must be set to VdkFieldType_Invalid.

 

If the specified user is not allowed access to the requested field, you must still provide a VgwColumnInfoRec structure; however, the type member must be set to VdkFieldType_Invalid.

 

If you change the behavior of a structure; for example, if your function returns a pointer yet the schema indicated that the data would be returned “in line.”

 

You should call VdkStructInit on your pvgwTable structure before assigning values to it; this action guarantees that optional or empty fields in the structure are set to NULL. You only set a value if the field exists for the document and the user is allowed to access it; otherwise, leave the field’s value as NULL.

The field values that you assign to the values table depend on the field’s data type and the behavior flags associated with the field, as explained in the following table:

 


Data Type

Explanation

VdkFieldType_Text

The value must be a null-terminated ASCII string in the proper character set. Strings that exceed the value specified in the maxColumnSize member of the VgwDocFieldReadArgRec structure must be truncated to the specified size.

VdkFieldType_Signed
VdkFieldType_Unsigned
VdkFieldType_Date

The value must be a four-byte integer. If the behavior flag is VgwColumn_Inline, the value must be an integer or date of the specified type; otherwise it is a pointer to a value. Integer and date values must be cast into pointers because the values array is defined as pointers.

VdkFieldType_Float

The value must be an eight-byte IEEE 754 double-precision floating point value. If the behavior flag is VgwColumn_Inline, the value must be a floating point number; otherwise it is a pointer to a value. These values are typically set using the C memcpy function.

VdkFieldType_Stream

The value must be a fixed-length binary blob in the proper character set. Blobs that exceed the value specified in the maxColumnSize member of the VgwDocFieldReadArgRec structure must be truncated to the specified size.Variable-length blobs are not supported for fields.


If the behavior flags are VgwColumn_RedirectFile or VgwColumn_RedirectURL, the value must be a pointer to a null-terminated ASCII string in the proper character set that contains the full pathname or URL.

If execution of your VgwDocFieldReadFnc function results in an error, you are responsible for freeing any resources used by the objects that you have created before returning from this function.


Example

#define FIELDCOUNT 5
#define FIXEDACL "294"

#define VGWF_SECFLAG (VdkCString)"_VgwAccessType"
#define VGWF_ACLCACHE (VdkCString)"_VgwAccessValue"
#define VGWF_DOCFLD (VdkCString)"DOC"
#define VGWF_DOCKEY (VdkCString)"VgwDocKey"
#define VGWF_VWURL (VdkCString)"VgwViewURL"

static VgwColumnInfoRec reposColInfo[] = {
{VdkFieldType_Invalid, (VdkCString)"", 0,
VgwColumn_ReadOnly, 0, 0},
{VdkFieldType_Unsigned, VGWF_SECFLAG, 0,
VgwColumn_ReadOnly | VgwColumn_InLine, 0, 0},
{VdkFieldType_Text, VGWF_ACLCACHE, 0,
VgwColumn_ReadOnly, 0, 0},
{VdkFieldType_Stream, VGWF_DOCFLD, 0,
VgwColumn_ReadOnly, 0, 0},
{VdkFieldType_Text, VGWF_DOCKEY, 0,
VgwColumn_PrimaryKey | VgwColumn_ReadOnly, 0, 0},
{VdkFieldType_Text, VGWF_VWURL, 0,
VgwColumn_RedirectURL | VgwColumn_ReadOnly, 0, 0}
};

static VdkError
VDK_CALLBACK VgwDocFieldRead(VgwAppSession pSession,
VdkUser pUser,
VgwDocFieldReadArg pReadArg,
VgwDataTable* ppTable)
{
VdkError error = VdkSuccess;
VdkUint2 j, k;
VgwColumnInfo pInfos;
VgwDataTable pTable = NULL;
VgwDocExistArgRec arg;

if (!ppTable)
return VdkError_InvalidArgs;
*ppTable = NULL;

if (!pReadArg)
return VdkError_InvalidArgs;

/**************************************************
* honor document level security whenever possible
**************************************************/

VdkStructInit(&arg);
arg.docKey = pReadArg->key;
if (VdkSuccess != (error = VgwDocExist(pSession, pUser, &arg)))
return error;

/***********************************************
* allocate the table, values array, and the
* VgwColumnInfo array and structs in one chunk
***********************************************/

if( !(pTable =
(VgwDataTable)malloc(sizeof(VgwDataTableRec) +
pReadArg->columnCount * (sizeof(VdkVoidp) +
sizeof(VgwColumnInfo) + sizeof(VgwColumnInfoRec)))) )
return VdkError_OutOfMemory;

VdkStructInit(pTable);
pTable->session = pSession;

/**********************************************************
* initialize the data table for one row, multiple columns
**********************************************************/

pTable->numRows = 1;
pTable->numColumns = pReadArg->columnCount;
pTable->values = (VdkVoidp*)&pTable[1];
pTable->columnArray =
(VgwColumnInfo*)(&pTable->values[pReadArg->columnCount]);

pInfos =
(VgwColumnInfo)(&pTable->columnArray[pReadArg->columnCount]);

for( j = 0; j < pReadArg->columnCount; j++ ){
pTable->columnArray[j] = &pInfos[j];

/ ***************************************************************
 * reads field column info from static array and populate value
****************************************************************/

for( k = 1; k <= FIELDCOUNT; k++ ){
if (stricmp((const char*)reposColInfo[k].name,
(const char*)pReadArg->columnArray[j]))
continue;
      *pTable->columnArray[j] = reposColInfo[k];

/*********************************
* an invalid external field type
*********************************/

if (reposColInfo[k].type == VdkFieldType_Invalid)
pTable->values[j] = NULL;

/*******************************
* decide if document is public
*******************************/

else if (!stricmp(VGWF_SECFLAG, reposColInfo[k].name)) {

/**********************************
* assume all documents are secure
**********************************/

pTable->values[j] = (VdkVoidp)VGW_SECURITY_CHECK_ACCESS;

/*****************************
* gather document acl labels
*****************************/

} else if (!stricmp(VGWF_ACLCACHE, reposColInfo[k].name)) {

/*************************************************
* assume all documents have FIXEDACL access list
* which is equivalent to USERUID ('a'+'b'+'c')
*************************************************/

pTable->values[j] = (VdkVoidp)FIXEDACL;

/*******************************************************
* copy the key value to field values in sample gateway
*******************************************************/

} else if( !stricmp(VGWF_DOCKEY, reposColInfo[k].name) ||
!stricmp(VGWF_VWURL, reposColInfo[k].name) ){

pTable->values[j] =
malloc(strlen((const char*)pReadArg->key) + 1);
strcpy((char*)pTable->values[j],
                                      (const char*)pReadArg->key);

/*********************************
* an invalid external field name
*********************************/

} else {

reposColInfo[k].type = VdkFieldType_Invalid;
pTable->values[j] = NULL;
}
}

if (k > FIELDCOUNT)
*pTable->columnArray[j] = reposColInfo[0];
}

*ppTable = pTable;
return VdkSuccess;
}