in driver/desc.cc [739:925]
SQLRETURN DESC::set_field(SQLSMALLINT recnum, SQLSMALLINT fldid,
SQLPOINTER val, SQLINTEGER buflen)
{
desc_field *fld = getfield(fldid);
void *dest_struct;
void *dest;
error.clear();
/* check for invalid IRD modification */
if (is_ird())
{
switch (fldid)
{
case SQL_DESC_ARRAY_STATUS_PTR:
case SQL_DESC_ROWS_PROCESSED_PTR:
break;
default:
return set_error("HY016",
"Cannot modify an implementation row descriptor",
MYERR_S1016);
}
}
if ((fld == NULL) ||
/* header permissions check */
(fld->loc == DESC_HDR &&
((ref_type == DESC_APP && (~fld->perms & P_WA)) ||
(ref_type == DESC_IMP && (~fld->perms & P_WI)))))
{
return set_error("HY091",
"Invalid descriptor field identifier",
MYERR_S1091);
}
else if (fld->loc == DESC_REC)
{
int perms= 0; /* needed perms to access */
if (ref_type == DESC_APP)
perms= P_WA;
else if (ref_type == DESC_IMP)
perms= P_WI;
if (desc_type == DESC_PARAM)
perms= P_PAR(perms);
else if (desc_type == DESC_ROW)
perms= P_ROW(perms);
if ((~fld->perms & perms) == perms)
return set_error("HY091",
"Invalid descriptor field identifier",
MYERR_S1091);
}
/* get the dest struct */
if (fld->loc == DESC_HDR)
dest_struct= this;
else
{
if (recnum < 1 && stmt->stmt_options.bookmarks == SQL_UB_OFF)
return set_error("07009",
"Invalid descriptor index",
MYERR_07009);
else
dest_struct= desc_get_rec(this, recnum - 1, TRUE);
}
dest= ((char *)dest_struct) + fld->offset;
/* some applications and even MSDN examples don't give a correct constant */
if (buflen == 0)
buflen= fld->data_type;
/* TODO checks when strings? */
if ((fld->data_type == SQL_IS_POINTER && buflen != SQL_IS_POINTER) ||
(fld->data_type != SQL_IS_POINTER && buflen == SQL_IS_POINTER))
return set_error("HY015",
"Invalid parameter type",
MYERR_S1015);
/* per-field checks/functionality */
switch (fldid)
{
case SQL_DESC_COUNT:
/* we just force the descriptor record count to expand */
(void)desc_get_rec(this, (int)((size_t)val - 1), TRUE);
break;
case SQL_DESC_NAME:
{
// dest_struct already points to the correct DESCREC*
DESCREC *name_rec = (DESCREC*)dest_struct;
// Add name as parameter data and zero terminating character
name_rec->par.add_param_data((char*)val, (unsigned long)strlen((char*)val) + 1);
// Get a pointer to allocated copy of the name
val = name_rec->par.val();
}
break;
/* We don't support named parameters, values stay as initialized */
//return set_desc_error(desc, "01S01",
// "Option value changed",
// MYERR_01S02);
case SQL_DESC_UNNAMED:
if ((size_t)val == SQL_NAMED)
return set_error("HY092",
"Invalid attribute/option identifier",
MYERR_S1092);
}
/* We have to unbind the value if not setting a buffer */
switch (fldid)
{
case SQL_DESC_DATA_PTR:
case SQL_DESC_OCTET_LENGTH_PTR:
case SQL_DESC_INDICATOR_PTR:
break;
default:
if (fld->loc == DESC_REC)
{
DESCREC *rec= (DESCREC *) dest_struct;
rec->data_ptr= NULL;
}
}
apply_desc_val(dest, fld->data_type, val, buflen);
/* post-set responsibilities */
/*http://msdn.microsoft.com/en-us/library/ms710963%28v=vs.85%29.aspx
"ParameterType Argument" sectiosn - basically IPD has to be heres as well with same rules
C and SQL types match. Thus we can use same function for calculation of type and dti code.
*/
if ((is_ard() || is_apd() || is_ipd()) && fld->loc == DESC_REC)
{
DESCREC *rec= (DESCREC *) dest_struct;
switch (fldid)
{
case SQL_DESC_TYPE:
rec->concise_type= rec->type;
rec->datetime_interval_code= 0;
break;
case SQL_DESC_CONCISE_TYPE:
rec->type= get_type_from_concise_type(rec->concise_type);
rec->datetime_interval_code=
get_dticode_from_concise_type(rec->concise_type);
break;
case SQL_DESC_DATETIME_INTERVAL_CODE: /* TODO validation for this value? */
/* SQL_DESC_TYPE has to have already been set */
if (rec->type == SQL_DATETIME)
rec->concise_type=
get_concise_type_from_datetime_code(rec->datetime_interval_code);
else
rec->concise_type=
get_concise_type_from_interval_code(rec->datetime_interval_code);
break;
}
switch (fldid)
{
case SQL_DESC_TYPE:
case SQL_DESC_CONCISE_TYPE:
/* setup type specific defaults (TODO others besides SQL_C_NUMERIC)? */
if (is_ard() && rec->type == SQL_C_NUMERIC)
{
rec->precision= 38;
rec->scale= 0;
}
}
}
/*
Set "real_param_done" for parameters if all fields needed to bind
a parameter are set.
*/
if (is_apd() && val != NULL && fld->loc == DESC_REC)
{
DESCREC *rec= (DESCREC *) dest_struct;
switch (fldid)
{
case SQL_DESC_DATA_PTR:
case SQL_DESC_OCTET_LENGTH_PTR:
case SQL_DESC_INDICATOR_PTR:
rec->par.real_param_done= TRUE;
break;
}
}
return SQL_SUCCESS;
}