You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
664 lines
19 KiB
664 lines
19 KiB
//---------------------------------------------------------------------------
|
|
// RowsetColumn.cpp : RowsetColumn implementation
|
|
//
|
|
// Copyright (c) 1996 Microsoft Corporation, All Rights Reserved
|
|
// Developed by Sheridan Software Systems, Inc.
|
|
//---------------------------------------------------------------------------
|
|
|
|
#include "stdafx.h"
|
|
#include "RSColumn.h"
|
|
|
|
SZTHISFILE
|
|
|
|
|
|
//=--------------------------------------------------------------------------=
|
|
// CVDRowsetColumn - Constructor
|
|
//
|
|
CVDRowsetColumn::CVDRowsetColumn()
|
|
{
|
|
m_ulOrdinal = 0;
|
|
|
|
m_wType = 0;
|
|
|
|
m_pwszBaseColumnName = NULL;
|
|
m_pwszBaseName = NULL;
|
|
m_dwBindType = 0;
|
|
m_lcidCollatingOrder = 0;
|
|
m_pwszDefaultValue = NULL;
|
|
m_cbEntryIDMaxLength = 0;
|
|
m_cbMaxLength = 0;
|
|
m_pwszName = NULL;
|
|
m_dwNumber = 0;
|
|
m_dwScale = 0;
|
|
m_dwCursorType = 0;
|
|
m_dwUpdatable = 0;
|
|
m_dwVersion = 0;
|
|
m_dwStatus = 0;
|
|
|
|
m_bool.fInitialized = FALSE;
|
|
m_bool.fAutoIncrement = FALSE;
|
|
m_bool.fCaseSensitive = TRUE;
|
|
m_bool.fDataColumn = FALSE;
|
|
m_bool.fFixed = FALSE;
|
|
m_bool.fHasDefault = FALSE;
|
|
m_bool.fMultiValued = FALSE;
|
|
m_bool.fNullable = FALSE;
|
|
m_bool.fSearchable = FALSE;
|
|
m_bool.fUnique = FALSE;
|
|
|
|
m_ulMaxStrLen = 0;
|
|
|
|
memset(&m_columnID, 0, sizeof(DBID));
|
|
memset(&m_cursorColumnID, 0, sizeof(CURSOR_DBCOLUMNID));
|
|
|
|
#ifdef _DEBUG
|
|
g_cVDRowsetColumnCreated++;
|
|
#endif
|
|
}
|
|
|
|
//=--------------------------------------------------------------------------=
|
|
// ~CVDRowsetColumn - Destructor
|
|
//
|
|
CVDRowsetColumn::~CVDRowsetColumn()
|
|
{
|
|
delete [] m_pwszBaseColumnName;
|
|
delete [] m_pwszBaseName;
|
|
delete [] m_pwszDefaultValue;
|
|
delete [] m_pwszName;
|
|
|
|
if (m_columnID.eKind == DBKIND_PGUID_NAME || m_columnID.eKind == DBKIND_PGUID_PROPID)
|
|
delete m_columnID.uGuid.pguid;
|
|
|
|
if (m_columnID.eKind == DBKIND_GUID_NAME || m_columnID.eKind == DBKIND_NAME || m_columnID.eKind == DBKIND_PGUID_NAME)
|
|
delete [] m_columnID.uName.pwszName;
|
|
|
|
if (m_cursorColumnID.dwKind == CURSOR_DBCOLKIND_GUID_NAME || m_cursorColumnID.dwKind == CURSOR_DBCOLKIND_NAME)
|
|
delete [] m_cursorColumnID.lpdbsz;
|
|
|
|
#ifdef _DEBUG
|
|
g_cVDRowsetColumnDestroyed++;
|
|
#endif
|
|
}
|
|
|
|
//=--------------------------------------------------------------------------=
|
|
// Initialize - Initialize rowset column object from IRowset metadata (#1)
|
|
//=--------------------------------------------------------------------------=
|
|
// This function converts and stores IRowset metadata in ICursor format
|
|
//
|
|
// Parameters:
|
|
// ulOrdinal - [in] original IRowset ordinal of column
|
|
// ulCursorOrdinal - [in] newly assigned ICursor ordinal of column
|
|
// pColumnInfo - [in] a pointer to an IRowset DBCOLUMNINFO structure
|
|
// where to retrieve metadata
|
|
// cbMaxBookmark - [in] maximum size of an IRowset bookmark
|
|
// pBookmarkColumnID - [in] a pointer to bookmark column identifier if this
|
|
// is a bookmark column, otherwise NULL
|
|
//
|
|
// Output:
|
|
// BOOL - TRUE if successful
|
|
//
|
|
// Notes:
|
|
// This function should only be called once
|
|
//
|
|
BOOL CVDRowsetColumn::Initialize(ULONG ulOrdinal,
|
|
ULONG ulCursorOrdinal,
|
|
DBCOLUMNINFO * pColumnInfo,
|
|
ULONG cbMaxBookmark,
|
|
CURSOR_DBCOLUMNID * pBookmarkColumnID)
|
|
{
|
|
if (m_bool.fInitialized)
|
|
{
|
|
ASSERT(FALSE, VD_ASSERTMSG_COLALREADYINITIALIZED)
|
|
return FALSE;
|
|
}
|
|
|
|
m_ulOrdinal = ulOrdinal;
|
|
|
|
// Store IRowset metadata
|
|
m_wType = pColumnInfo->wType;
|
|
m_columnID = pColumnInfo->columnid;
|
|
|
|
// make copy of guid if necessary
|
|
if (m_columnID.eKind == DBKIND_PGUID_NAME || m_columnID.eKind == DBKIND_PGUID_PROPID)
|
|
{
|
|
m_columnID.uGuid.pguid = new GUID;
|
|
|
|
if (!m_columnID.uGuid.pguid)
|
|
return E_OUTOFMEMORY;
|
|
|
|
memcpy(m_columnID.uGuid.pguid, pColumnInfo->columnid.uGuid.pguid, sizeof(GUID));
|
|
}
|
|
|
|
// make copy of name if necessary
|
|
if (m_columnID.eKind == DBKIND_GUID_NAME || m_columnID.eKind == DBKIND_NAME || m_columnID.eKind == DBKIND_PGUID_NAME)
|
|
{
|
|
const int nLength = lstrlenW(pColumnInfo->columnid.uName.pwszName);
|
|
|
|
m_columnID.uName.pwszName = new WCHAR[nLength + 1];
|
|
|
|
if (!m_columnID.uName.pwszName)
|
|
return E_OUTOFMEMORY;
|
|
|
|
memcpy(m_columnID.uName.pwszName, pColumnInfo->columnid.uName.pwszName, (nLength + 1) * sizeof(WCHAR));
|
|
}
|
|
|
|
// Store ICursor metadata
|
|
if (pColumnInfo->dwFlags & DBCOLUMNFLAGS_MAYDEFER)
|
|
m_dwBindType = CURSOR_DBBINDTYPE_BOTH;
|
|
else
|
|
m_dwBindType = CURSOR_DBBINDTYPE_DATA;
|
|
|
|
if (!pBookmarkColumnID)
|
|
m_cursorColumnID = ColumnIDToCursorColumnID(pColumnInfo->columnid, ulCursorOrdinal);
|
|
else
|
|
m_cursorColumnID = *pBookmarkColumnID; // use supplied bookmark column identifier
|
|
|
|
if (m_dwBindType == CURSOR_DBBINDTYPE_BOTH)
|
|
m_cbEntryIDMaxLength = sizeof(ULONG) + sizeof(ULONG) + cbMaxBookmark;
|
|
else
|
|
m_cbEntryIDMaxLength = 0;
|
|
|
|
// rowset types DBTYPE_GUID and DBTYPE_DBTIMESTAMP are returned as CURSOR_DBTYPE_LPWSTRs
|
|
|
|
if (pColumnInfo->wType == DBTYPE_GUID || pColumnInfo->wType == DBTYPE_DBTIMESTAMP)
|
|
m_cbMaxLength = 64;
|
|
else
|
|
m_cbMaxLength = pColumnInfo->ulColumnSize;
|
|
|
|
if (pColumnInfo->pwszName)
|
|
{
|
|
const int nLength = lstrlenW(pColumnInfo->pwszName);
|
|
|
|
m_pwszName = new WCHAR[nLength + 1];
|
|
|
|
if (!m_pwszName)
|
|
return E_OUTOFMEMORY;
|
|
|
|
memcpy(m_pwszName, pColumnInfo->pwszName, (nLength + 1) * sizeof(WCHAR));
|
|
}
|
|
|
|
m_dwNumber = ulCursorOrdinal;
|
|
|
|
m_dwScale = pColumnInfo->bScale;
|
|
|
|
m_dwCursorType = TypeToCursorType(pColumnInfo->wType);
|
|
|
|
if (pColumnInfo->dwFlags & DBCOLUMNFLAGS_WRITE)
|
|
m_dwUpdatable = CURSOR_DBUPDATEABLE_UPDATEABLE;
|
|
|
|
if (!(pColumnInfo->dwFlags & DBCOLUMNFLAGS_ISBOOKMARK))
|
|
m_bool.fDataColumn = TRUE;
|
|
|
|
if (pColumnInfo->dwFlags & DBCOLUMNFLAGS_ISFIXEDLENGTH)
|
|
{
|
|
m_bool.fFixed = TRUE;
|
|
m_ulMaxStrLen = GetCursorTypeMaxStrLen(m_dwCursorType, m_cbMaxLength);
|
|
}
|
|
|
|
if (pColumnInfo->dwFlags & DBCOLUMNFLAGS_MAYBENULL)
|
|
m_bool.fNullable = TRUE;
|
|
|
|
m_bool.fInitialized = TRUE;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
//=--------------------------------------------------------------------------=
|
|
// Initialize - Initialize rowset column object from meta-metadata (#2)
|
|
//=--------------------------------------------------------------------------=
|
|
// The function stores ICursor meta-metadata
|
|
//
|
|
// Parameters:
|
|
// cursorColumnID - [in] ICursor column identifier
|
|
// fDataColumn - [in] is data column?
|
|
// cbMaxLength - [in] maximum length of this datatype
|
|
// pszName - [in] column name
|
|
// dwCursorType - [in] datatype
|
|
// dwNumber - [in] ordinal position
|
|
//
|
|
// Output:
|
|
// BOOL - TRUE if successful
|
|
//
|
|
// Notes:
|
|
// This function should only be called once
|
|
//
|
|
BOOL CVDRowsetColumn::Initialize(const CURSOR_DBCOLUMNID * pCursorColumnID,
|
|
BOOL fDataColumn,
|
|
ULONG cbMaxLength,
|
|
CHAR * pszName,
|
|
DWORD dwCursorType,
|
|
DWORD dwNumber)
|
|
{
|
|
if (m_bool.fInitialized)
|
|
{
|
|
ASSERT(FALSE, VD_ASSERTMSG_COLALREADYINITIALIZED)
|
|
return FALSE;
|
|
}
|
|
|
|
// Store ICursor meta-metadata
|
|
m_dwBindType = CURSOR_DBBINDTYPE_DATA;
|
|
|
|
m_cursorColumnID = *pCursorColumnID;
|
|
|
|
m_cbEntryIDMaxLength = 0;
|
|
|
|
m_cbMaxLength = cbMaxLength;
|
|
|
|
if (pszName)
|
|
{
|
|
MAKE_WIDEPTR_FROMANSI(pwszName, pszName);
|
|
|
|
const int nLength = lstrlenW(pwszName);
|
|
|
|
m_pwszName = new WCHAR[nLength + 1];
|
|
|
|
if (!m_pwszName)
|
|
return E_OUTOFMEMORY;
|
|
|
|
memcpy(m_pwszName, pwszName, (nLength + 1) * sizeof(WCHAR));
|
|
}
|
|
|
|
m_dwNumber = dwNumber;
|
|
|
|
m_dwScale = 0;
|
|
|
|
m_dwCursorType = dwCursorType;
|
|
|
|
m_dwUpdatable = CURSOR_DBUPDATEABLE_NOTUPDATEABLE;
|
|
|
|
m_bool.fDataColumn = fDataColumn;
|
|
m_bool.fFixed = TRUE;
|
|
m_bool.fNullable = FALSE;
|
|
|
|
m_bool.fInitialized = TRUE;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
//=--------------------------------------------------------------------------=
|
|
// SetStringProperty
|
|
//=--------------------------------------------------------------------------=
|
|
// The function is called from SetBaseColumnName, SetBaseName and SetDefaultValue
|
|
//
|
|
// Parameters:
|
|
// ppStringProp - [in] A ptr to the ptr that holds the string value
|
|
// pNewString - [in] A pointer to the new string value
|
|
// ulLength - [in] the length of the string in bytes
|
|
//
|
|
// Notes:
|
|
//
|
|
|
|
void CVDRowsetColumn::SetStringProperty(WCHAR ** ppStringProp,
|
|
WCHAR * pNewString,
|
|
ULONG ulLength)
|
|
{
|
|
// free old string prop if any
|
|
delete [] *ppStringProp;
|
|
|
|
// if ulLength = zero then just return
|
|
if (!ulLength)
|
|
{
|
|
*ppStringProp = NULL;
|
|
return;
|
|
}
|
|
|
|
ASSERT_POINTER_LEN(pNewString, ulLength);
|
|
*ppStringProp = new WCHAR[ulLength + sizeof(WCHAR)];
|
|
|
|
if (*ppStringProp)
|
|
{
|
|
// init null terminator
|
|
(*ppStringProp)[ulLength] = 0;
|
|
// copy string over
|
|
memcpy(*ppStringProp, pNewString, ulLength);
|
|
}
|
|
}
|
|
|
|
//=--------------------------------------------------------------------------=
|
|
// ColumnIDToCursorColumnID - Convert rowset column ID to cursor column ID
|
|
//=--------------------------------------------------------------------------=
|
|
// Converts an IRowset DBID structure into its ICursor DBCOLUMNID equivalent
|
|
//
|
|
// Parameters:
|
|
// columnID - [in] the IRowset column identifier
|
|
// ulCursorOrdinal - [in] the column's ordinal position in ICursor
|
|
//
|
|
// Output:
|
|
// CURSOR_DBCOLUMNID - The ICursor CURSOR_DBCOLUMNID equivalent of columnID
|
|
//
|
|
// Notes:
|
|
//
|
|
|
|
CURSOR_DBCOLUMNID CVDRowsetColumn::ColumnIDToCursorColumnID(const DBID& columnID, ULONG ulCursorOrdinal)
|
|
{
|
|
CURSOR_DBCOLUMNID cursorColumnID;
|
|
|
|
GUID guidNumberOnly = CURSOR_GUID_NUMBERONLY;
|
|
|
|
cursorColumnID.guid = guidNumberOnly;
|
|
cursorColumnID.dwKind = CURSOR_DBCOLKIND_GUID_NUMBER;
|
|
cursorColumnID.lNumber = ulCursorOrdinal;
|
|
|
|
return cursorColumnID;
|
|
|
|
// The following code is the old implementation of this function. It caused problems with some
|
|
// cursor consumers because it tried to create a cursor column identifier as close as possible
|
|
// to the rowset column identifier, thus utilized the problematic lpdbsz member.
|
|
|
|
/*
|
|
CURSOR_DBCOLUMNID ID;
|
|
|
|
switch (columnID.eKind)
|
|
{
|
|
case DBKIND_GUID_NAME:
|
|
ID.guid = columnID.uGuid.guid;
|
|
ID.dwKind = CURSOR_DBCOLKIND_GUID_NAME;
|
|
ID.lpdbsz = columnID.uName.pwszName;
|
|
break;
|
|
|
|
case DBKIND_GUID_PROPID:
|
|
ID.guid = columnID.uGuid.guid;
|
|
ID.dwKind = CURSOR_DBCOLKIND_GUID_NUMBER;
|
|
ID.lNumber = ulCursorOrdinal;
|
|
break;
|
|
|
|
case DBKIND_NAME:
|
|
ID.dwKind = CURSOR_DBCOLKIND_NAME;
|
|
ID.lpdbsz = columnID.uName.pwszName;
|
|
break;
|
|
|
|
case DBKIND_PGUID_NAME:
|
|
ID.guid = *columnID.uGuid.pguid;
|
|
ID.dwKind = CURSOR_DBCOLKIND_GUID_NAME;
|
|
ID.lpdbsz = columnID.uName.pwszName;
|
|
break;
|
|
|
|
case DBKIND_PGUID_PROPID:
|
|
ID.guid = *columnID.uGuid.pguid;
|
|
ID.dwKind = CURSOR_DBCOLKIND_GUID_NUMBER;
|
|
ID.lNumber = ulCursorOrdinal;
|
|
break;
|
|
|
|
case DBKIND_GUID:
|
|
ID.guid = columnID.uGuid.guid;
|
|
ID.dwKind = CURSOR_DBCOLKIND_GUID_NUMBER;
|
|
ID.lNumber = ulCursorOrdinal;
|
|
break;
|
|
|
|
case DBKIND_PROPID:
|
|
memset(&ID.guid, 0, sizeof(GUID)); // encode ordinal in guid
|
|
ID.guid.Data1 = ulCursorOrdinal;
|
|
ID.dwKind = CURSOR_DBCOLKIND_GUID_NUMBER;
|
|
ID.lNumber = ulCursorOrdinal;
|
|
break;
|
|
}
|
|
|
|
// make copy of name if necessary
|
|
if (ID.dwKind == CURSOR_DBCOLKIND_GUID_NAME || ID.dwKind == CURSOR_DBCOLKIND_NAME)
|
|
{
|
|
const int nLength = lstrlenW(columnID.uName.pwszName);
|
|
|
|
ID.lpdbsz = new WCHAR[nLength + 1];
|
|
|
|
if (ID.lpdbsz)
|
|
memcpy(ID.lpdbsz, columnID.uName.pwszName, (nLength + 1) * sizeof(WCHAR));
|
|
}
|
|
|
|
return ID;
|
|
*/
|
|
}
|
|
|
|
//=--------------------------------------------------------------------------=
|
|
// TypeToCursorType - Convert rowset datatype to cursor datatype
|
|
//=--------------------------------------------------------------------------=
|
|
// Converts a IRowset DBTYPE value into its ICursor DBVARENUM equivalent
|
|
//
|
|
// Parameters:
|
|
// wType - [in] the IRowset datatype
|
|
//
|
|
// Output:
|
|
// CURSOR_DBVARENUM - The ICursor DBVARENUM equivalent of DBTYPE
|
|
//
|
|
// Notes:
|
|
//
|
|
CURSOR_DBVARENUM CVDRowsetColumn::TypeToCursorType(DBTYPE wType)
|
|
{
|
|
DWORD dwType = 0;
|
|
|
|
switch (wType)
|
|
{
|
|
case DBTYPE_ERROR:
|
|
dwType = CURSOR_DBTYPE_HRESULT;
|
|
break;
|
|
|
|
case DBTYPE_VARIANT:
|
|
dwType = CURSOR_DBTYPE_ANYVARIANT;
|
|
break;
|
|
|
|
case DBTYPE_UI2:
|
|
dwType = CURSOR_DBTYPE_UI2;
|
|
break;
|
|
|
|
case DBTYPE_UI4:
|
|
dwType = CURSOR_DBTYPE_UI4;
|
|
break;
|
|
|
|
case DBTYPE_UI8:
|
|
dwType = CURSOR_DBTYPE_UI8;
|
|
break;
|
|
|
|
case DBTYPE_BYTES:
|
|
dwType = CURSOR_DBTYPE_BLOB;
|
|
break;
|
|
|
|
case DBTYPE_STR:
|
|
dwType = VT_BSTR;
|
|
break;
|
|
|
|
case DBTYPE_WSTR:
|
|
dwType = CURSOR_DBTYPE_LPWSTR;
|
|
break;
|
|
|
|
case DBTYPE_NUMERIC:
|
|
dwType = CURSOR_DBTYPE_R8;
|
|
break;
|
|
|
|
//case DBTYPE_HCHAPTER: <- doesn't exist in new spec
|
|
// break; // no equivalent
|
|
|
|
case DBTYPE_UDT:
|
|
break; // no equivalent
|
|
|
|
case DBTYPE_DBDATE:
|
|
dwType = CURSOR_DBTYPE_DATE;
|
|
break;
|
|
|
|
case DBTYPE_DBTIME:
|
|
dwType = CURSOR_DBTYPE_DATE;
|
|
break;
|
|
|
|
// rowset types DBTYPE_GUID and DBTYPE_DBTIMESTAMP are returned as CURSOR_DBTYPE_LPWSTRs
|
|
|
|
case DBTYPE_GUID:
|
|
case DBTYPE_DBTIMESTAMP:
|
|
dwType = CURSOR_DBTYPE_LPWSTR;
|
|
break;
|
|
|
|
default:
|
|
dwType = wType;
|
|
}
|
|
|
|
return (CURSOR_DBVARENUM)dwType;
|
|
}
|
|
|
|
//=--------------------------------------------------------------------------=
|
|
// CursorTypeToType - Convert cursor datatype to rowset datatype
|
|
//=--------------------------------------------------------------------------=
|
|
// Converts a ICursor DBVARENUM value into its IRowset DBTYPE equivalent
|
|
//
|
|
// Parameters:
|
|
// CURSOR_DBVARENUM - [in] the ICursor value
|
|
//
|
|
// Output:
|
|
// DBTYPE - The IRowset DBTYPE equivalent of DBVARENUM
|
|
//
|
|
// Notes:
|
|
//
|
|
DBTYPE CVDRowsetColumn::CursorTypeToType(CURSOR_DBVARENUM dwCursorType)
|
|
{
|
|
DBTYPE wType = 0;
|
|
|
|
switch (dwCursorType)
|
|
{
|
|
case CURSOR_DBTYPE_HRESULT:
|
|
wType = DBTYPE_ERROR;
|
|
break;
|
|
|
|
case CURSOR_DBTYPE_LPSTR:
|
|
wType = DBTYPE_STR;
|
|
break;
|
|
|
|
case CURSOR_DBTYPE_LPWSTR:
|
|
wType = DBTYPE_WSTR;
|
|
break;
|
|
|
|
case CURSOR_DBTYPE_FILETIME:
|
|
wType = DBTYPE_DBTIMESTAMP;
|
|
break;
|
|
|
|
case CURSOR_DBTYPE_BLOB:
|
|
wType = DBTYPE_BYTES;
|
|
break;
|
|
|
|
case CURSOR_DBTYPE_DBEXPR:
|
|
break; // no equivalent
|
|
|
|
case CURSOR_DBTYPE_UI2:
|
|
wType = DBTYPE_UI2;
|
|
break;
|
|
|
|
case CURSOR_DBTYPE_UI4:
|
|
wType = DBTYPE_UI4;
|
|
break;
|
|
|
|
case CURSOR_DBTYPE_UI8:
|
|
wType = DBTYPE_UI8;
|
|
break;
|
|
|
|
case CURSOR_DBTYPE_COLUMNID:
|
|
wType = DBTYPE_GUID;
|
|
break;
|
|
|
|
case CURSOR_DBTYPE_BYTES:
|
|
wType = DBTYPE_BYTES;
|
|
break;
|
|
|
|
case CURSOR_DBTYPE_CHARS:
|
|
wType = DBTYPE_STR;
|
|
break;
|
|
|
|
case CURSOR_DBTYPE_WCHARS:
|
|
wType = DBTYPE_WSTR;
|
|
break;
|
|
|
|
case CURSOR_DBTYPE_ANYVARIANT:
|
|
wType = DBTYPE_VARIANT;
|
|
break;
|
|
|
|
default:
|
|
wType = (WORD)dwCursorType;
|
|
}
|
|
|
|
return wType;
|
|
}
|
|
|
|
//=--------------------------------------------------------------------------=
|
|
// GetCursorTypeMaxStrLen - Get the buffer size in characters required by
|
|
// cursor data type when represented as a string
|
|
// (doesn't include NULL terminator)
|
|
//
|
|
// Notes:
|
|
//
|
|
// The way these values where computed is as follows:
|
|
//
|
|
// (1) the maximum precision for each datatype was taken from "Precision of Numeric Data Types" in
|
|
// appendix A of the "OLE DB Programmer's Reference, Volume 2".
|
|
// (2) the precision was then divided by two and added to the original precision to allow space for
|
|
// numberic symbols, like negative signs, dollar signs, commas, etc., that might be present.
|
|
// (3) the sum was then doubled to allow for multibyte character sets.
|
|
//
|
|
// Since this table is not appropriate for floating point datatypes, their values where computed based
|
|
// on the string length of the minimum/maximum possible values for these datatypes, then doubled.
|
|
//
|
|
// datatype minimum value maximum value length
|
|
// -------- ------------- ------------- ------
|
|
// float 1.175494351e-38 3.402823466e+38 15
|
|
// double 2.2250738585072014e-308 1.7976931348623158e+308 23
|
|
//
|
|
ULONG CVDRowsetColumn::GetCursorTypeMaxStrLen(DWORD dwCursorType, ULONG cbMaxLength)
|
|
{
|
|
ULONG ulMaxStrLen = cbMaxLength; // default for fixed length strings
|
|
|
|
switch (dwCursorType)
|
|
{
|
|
case VT_I1:
|
|
ulMaxStrLen = (3 + 1) * 2;
|
|
break;
|
|
|
|
case CURSOR_DBTYPE_I2:
|
|
ulMaxStrLen = (5 + 2) * 2;
|
|
break;
|
|
|
|
case CURSOR_DBTYPE_I4:
|
|
ulMaxStrLen = (10 + 5) * 2;
|
|
break;
|
|
|
|
case CURSOR_DBTYPE_I8:
|
|
ulMaxStrLen = (19 + 9) * 2;
|
|
break;
|
|
|
|
case CURSOR_DBTYPE_R4:
|
|
ulMaxStrLen = (15) * 2;
|
|
break;
|
|
|
|
case CURSOR_DBTYPE_R8:
|
|
ulMaxStrLen = (23) * 2;
|
|
break;
|
|
|
|
case CURSOR_DBTYPE_CY:
|
|
ulMaxStrLen = (19 + 9) * 2;
|
|
break;
|
|
|
|
case CURSOR_DBTYPE_DATE:
|
|
ulMaxStrLen = (32 + 16) * 2;
|
|
break;
|
|
|
|
case CURSOR_DBTYPE_FILETIME:
|
|
ulMaxStrLen = (32 + 16) * 2;
|
|
break;
|
|
|
|
case CURSOR_DBTYPE_BOOL:
|
|
ulMaxStrLen = (5 + 2) * 2;
|
|
break;
|
|
|
|
case VT_UI1:
|
|
ulMaxStrLen = (3 + 1) * 2;
|
|
break;
|
|
|
|
case CURSOR_DBTYPE_UI2:
|
|
ulMaxStrLen = (5 + 2) * 2;
|
|
break;
|
|
|
|
case CURSOR_DBTYPE_UI4:
|
|
ulMaxStrLen = (10 + 5) * 2;
|
|
break;
|
|
|
|
case CURSOR_DBTYPE_UI8:
|
|
ulMaxStrLen = (20 + 10) * 2;
|
|
break;
|
|
}
|
|
|
|
return ulMaxStrLen;
|
|
}
|
|
|
|
|