Привет !
Пишу расширенную хранимую процедуру — dll
на С++ ,"Visual Studio 2008"
для MS SQL Server 2005 Express
Использую #include <atldbcli.h>
Моя хранимка по сути близка к OpenRowset/OpenQuery
т.е. она получает на вход
— строку подключения к другому источнику данных,
— sql — запрос
на выход — выдает таблицу- резултат выборки.
Со стоковыми стобцами все просто — их уже получаю правильно.
Но как правильно преобразовать
DBTYPE_DBTIMESTAMP в -> SRVDATETIME
и
DBTYPE_NUMERIC в -> непонятно что ? это SRVINT4 ? SRVMONEY ? SRVFLT4 ?...
Нашел множество простых примеров написания таких хранимок,
но нигде не могу найти приверов как правильно преобразовывать типы данных...
Основной вопрос к моей функции BYTE GetSRV_TYPE(DBCOLUMNINFO ci);
— как ее правильно написать:
//.............................................
BYTE GetSRV_TYPE(DBCOLUMNINFO ci); // - ее надо дописать
// ...
CCommand<CDynamicAccessor> dinamic;
// здесть открытие базы и выполнение SQL...
// далее...
int ulColumns = dinamic.GetColumnCount();
char ColumnName[255];
for (int i=1; i<ulColumns; i++) // обьявляем поля таблицы
{
lp=dinamic.m_pColumnInfo[i].pwszName;
wcstombs((CHAR*)&ColumnName,(OLECHAR*)lp,sizeof(ColumnName));
tp=dinamic.m_pColumnInfo[i].wType;
srv_describe(pSrvProc, i, (CHAR*)&ColumnName,SRV_NULLTERM, GetSRV_TYPE(dinamic.m_pColumnInfo[i]),dinamic.m_pColumnInfo[i].ulColumnSize, GetSRV_TYPE(dinamic.m_pColumnInfo[i]), dinamic.m_pColumnInfo[i].ulColumnSize, NULL);
}
while (dinamic.MoveNext() == S_OK) // заполняем поля данными
{
for (ULONG i=1; i<ulColumns; i++)
{
srv_setcollen(pSrvProc, i, dinamic.m_pColumnInfo[i].ulColumnSize);
srv_setcoldata(pSrvProc,i, dinamic.GetValue(i)); // здесь наверно тоже не все так просто ?
}
srv_sendrow(pSrvProc); //Посылаем строку клиенту
CountRec++;
}
//.............................................
BYTE GetSRV_TYPE(DBCOLUMNINFO ci)// - ее надо дописать
{
if (ci.wType==DBTYPE_I8) {return SRVINT4 ;}
if (ci.wType==DBTYPE_BYTES) {return SRVBINARY ;}
if (ci.wType==DBTYPE_BOOL) {return SRVBIT ;}
if (ci.wType==DBTYPE_BSTR) {return SRVTEXT ;}
if (ci.wType==DBTYPE_HCHAPTER) {return SRVINT4 ;}
if (ci.wType==DBTYPE_STR) {return SRVVARCHAR ;}
if (ci.wType==DBTYPE_CY) {return SRVINT4 ;}
if (ci.wType==DBTYPE_DATE) {return SRVDATETIM4 ;}
if (ci.wType==DBTYPE_DBDATE) {return SRVDATETIM4 ;}
if (ci.wType==DBTYPE_DBTIME) {return SRVDATETIM4 ;}
if (ci.wType==DBTYPE_DBTIMESTAMP) {return SRVDATETIM4 ;}
if (ci.wType==DBTYPE_DECIMAL) {return SRVINT4 ;}
if (ci.wType==DBTYPE_R8) {return SRVINT4 ;}
if (ci.wType==DBTYPE_ERROR) {return SRVINT4 ;}
if (ci.wType==DBTYPE_FILETIME) {return SRVINT4 ;}
if (ci.wType==DBTYPE_GUID) {return SRVINT4 ;}
if (ci.wType==DBTYPE_IDISPATCH) {return SRVINT4 ;}
if (ci.wType==DBTYPE_I4) {return SRVINT4 ;}
if (ci.wType==DBTYPE_IUNKNOWN) {return SRVINT4 ;}
if (ci.wType==DBTYPE_NUMERIC) {return SRVMONEY4 ;}
if (ci.wType==DBTYPE_PROPVARIANT) {return SRVINT4 ;}
if (ci.wType==DBTYPE_R4) {return SRVINT4 ;}
if (ci.wType==DBTYPE_I2) {return SRVINT4 ;}
if (ci.wType==DBTYPE_I1) {return SRVINT4 ;}
if (ci.wType==DBTYPE_UI8) {return SRVINT4 ;}
if (ci.wType==DBTYPE_UI4) {return SRVINT4 ;}
if (ci.wType==DBTYPE_UI2) {return SRVINT4 ;}
if (ci.wType==DBTYPE_UI1) {return SRVINT4 ;}
if (ci.wType==DBTYPE_VARIANT) {return SRVINT4 ;}
if (ci.wType==DBTYPE_WSTR) {return SRVINT4 ;}
if (ci.wType==DBTYPE_UDT) {return SRVINT4 ;}
if (ci.wType==DBTYPE_VARNUMERIC) {return SRVMONEY4 ;}
return SRVINT4; // временная заглушка типом SRVINT4 - это когда я не знаю что написать :)
}
//.............................................
Ситуация начинает немного проясняться...
if (dinamic.m_pColumnInfo[i].wType==DBTYPE_DBTIMESTAMP)
{
int idays=0;
DBTIMESTAMP * ts=( DBTIMESTAMP* )dinamic.GetValue(i);
srv_datetime sdt;
// здесь переконвертим данные из DBTIMESTAMP в srv_datetime...
// нужно как -то получить количество дней с 1900 года до ts->day, ts->month, ts->year
sdt.dtdays=idays;
sdt.dttime=((int)ts->hour*60*60)+((int)ts->minute*60)+ts->second;
srv_setcoldata(pSrvProc,i, &sdt);
//..............
if (dinamic.m_pColumnInfo[i].wType==DBTYPE_VARNUMERIC)
{
float fValue;
DB_VARNUMERIC *vn=( DB_VARNUMERIC* )dinamic.GetValue(i);
int prec = vn->precision;
int scale = vn->scale;
int sign = ( vn->sign > 0 ) ? 1 : -1;
// здесь как-то нужно переконвертить во float
srv_setcoldata(pSrvProc,i,&fValue);
Помощь в конвертации все еще требуется
Давно в С++ не работал...