Милостивые господа!
Приношу свои извинения, но согласно принятой идеологии мне пришлось внести коррективы в функции общения с БД. Все дело в том, что мы договорились, что память отводит тот, кто ее чистит, а посему, клиенту приходится делать запрос в БД в несколько приемов для того, чтобы получать длины строк в структурах, отводить память под них и под параметры сообщения, заполнять их, заодно получая длины строк в параметрах сообщения. Затем следует отводить память под строки в параметрах сообщения и опять делать запрос для заполнения этих строк.
Вообще, мне только сейчас пришла мысль, что можно просить БД полностью заполнять структуры вместе с отведением памяти, а затем просить БД ее очищать (т.е. в библиотеке должны быть функции очистки структур). Черт, почему умные мысли приходят только после написания кода??? С другой стороны, клиент может копировать структуры с соответствующим выделением памяти и может возникнуть путаница.
Вобщем, жду высказывания мыслей - надо ли все переделывать под отведение/очистку памяти из БД?
Из общих соображений, мне кажется, что все это должен делать клиент.
Если принять это за аксиому, то выозникает проблема. Один запрос осуществляется за несколько обращений к БД, а за это время в БД могут произойти изменения.
Посему, предлагается ввести еще один парметр в функции запроса к БД - указатель на идентификатор запроса
int *IDSet;
В начальнном запросе IDSet=0;
БД выполняет запрос, помещает выборку во внутреннюю структуру, и ее идентификатор помещает в IDSet Далее, если IDSet!=0, то БД берет выборку из соответствующей сохраненной структуры и уже совсем не смотрит на сам запрос.
Черт, возник вопрос с уничтожением этой внутренней выборки. Предложения принимаются.
Итак, получается, что, например, сообщения можно выудить только на 3 запроса (!):

int IDSet=0,N=0; CMessageEvent *event=NULL; CMessageEventRequest request;
if(FDBGetEvents(&N, NULL, &request,&IDSet)==0) //get N and IDSet
{
if(N>0)
{
event=new CMessageEvent[N];
FDBGetEvents(&N, event, &request,&IDSet); //get strings length and parameters number
for(i=0;i FDBGetEvents(&N, event, &request,&IDSet); //get strings and strings length in parameters
for(i=0;i FDBGetEvents(&N, event, &request,&IDSet); //get strings in parameters
}
}

Кошмарно, но, похоже, правильно!!!

Можно добавить пятый вызов, который должен чистить память выборки с номером IDSet:
DBGetEvents(NULL, NULL, NULL,&IDSet); //clean internal memory
от первого вызова этот вызов отличается IDSet!=0

//==========================================================================
//==========================================================================
//------------------------------------------------------------
class CSensor
{public:
//--
int SensorType;
char *SensorID; int LSensorID;
char *Description; int LDescription;
//-- for KEEPALIVE:
int MessageType;//1)IsAlive; 2)IsDead
time_t EventTime;
int Status;//bits: 1=Alive/Not alive
//--
};
//------------------------------------------------------------
class CMessageEventParam
{public:
//--
int Type;//text: 1)int; 2)double; 3)text
char *Name;int LName;//0-terminated
char *Val; int LVal;
//--
};
//==========================================================================
class CMessageEvent
{public:
//---
int MessageType;
char *SensorID; int LSensorID;
int MessageID;
int SensorType;
char *EventName; int LEventName;
time_t EventTime;
int ParNum;
CMessageEventParam *par;
//---
};
//==========================================================================
class CMessageEventRequest
{public:
//--
int NMax;int TakeFirst1_Last0;
int MessageID0,MessageID1; int UseMessageID0,UseMessageID1;
int MessageType; int UseMessageType;
char *SensorID; int LSensorID; int UseSensorID;
int SensorType; int UseSensorType;
char *EventName; int LEventName; int UseEventName;
time_t EventTime0; int UseEventTime0;
time_t EventTime1; int UseEventTime1;
//--
};
//==========================================================================
class CMessageCommand
{public:
//---
int MessageType;
char *SensorID; int LSensorID;
int CommandID;
int CommandType;
time_t EventTime;
int ParNum;
CMessageEventParam *par;
//---
};
//==========================================================================
class CMessageCommandRequest
{public:
//--
int NMax;int TakeFirst1_Last0;
int MessageType; int UseMessageType;
char *SensorID; int LSensorID; int UseSensorID;
int CommandID0,CommandID1; int UseCommandID0,UseCommandID1;
int CommandType; int UseCommandType;
time_t CommandTime0; int UseCommandTime0;
time_t CommandTime1; int UseCommandTime1;
//--
};
//==========================================================================
int FDBGetSensors(int *N, CSensor *s);//if N==NULL then return sizeof(CSensor)
; if N!=NULL then set <=*N sensors

int FInitDBEvents(const char *ConfigDir);
int FDBGetEvents(int *N, CMessageEvent *event, CMessageEventRequest *request);
//if N==NULL then return
//sizeof(CMessageEvent)<<16+sizeof(CMessageEventRequest) ; if N!=NULL then set
//<=*N events

//==========================================================================
int FInitDBSensors(const char* ConfigDir);
int FDBGetSensors(int *N, CSensor *s,int *IDSet);
//if N==NULL then return sizeof(CSensor)

//example of use:
int IDSet=0,NSensors=0; CSensor *Sensor=NULL;
int rtn=FDBGetSensors(&NSensors, NULL,&IDSet);
if(irtn==0 && NSensors>0)
{int i;
Sensor=new CSensor[NSensors];
rtn=FDBGetSensors(&NSensors, Sensor,&IDSet);
for(i=0;i //strings
FDBGetSensors(&NSensors, Sensor,&IDSet);
}
//==========================================================================
int FInitDBEvents(const char *ConfigDir);
int FDBGetEvents(int *N, CMessageEvent *event, CMessageEventRequest *request, int *IDSet);
//if N==NULL then return
//sizeof(CMessageEvent)<<16+sizeof(CMessageEventRequest) ; if N!=NULL then set

//example of use:
int IDSet=0,N=0; CMessageEvent *event=NULL; CMessageEventRequest request;
if(FDBGetEvents(&N, NULL, &request,&IDSet)==0)
{
if(N>0)
{
event=new CMessageEvent[N];
FDBGetEvents(&N, event, &request,&IDSet);
for(i=0;i FDBGetEvents(&N, event, &request,&IDSet);
for(i=0;i //parameters
FDBGetEvents(&N, event, &request,&IDSet);
}
}
//==========================================================================
int FInitDBCommands(const char *ConfigDir);
int FDBGetCommands(int *N, CMessageCommand *cmd, CMessageCommandRequest *request, int *IDSet);
//if N==NULL then return
//sizeof(CMessageCommand)<<16+sizeof(CMessageCommandRequest) ; if N!=NULL then set

//example of use:
int IDSet=0,N=0; CMessageCommand *event=NULL; CMessageCommandRequest request;
if(FDBGetCommands(&N, NULL, &request,&IDSet)==0)
{
if(N>0)
{
command=new CMessageCommand[N];
FDBGetCommands(&N, command, &request,&IDSet);
for(i=0;i FDBGetCommands(&N, command, &request,&IDSet);
for(i=0;i //parameters
FDBGetCommands(&N, command, &request,&IDSet);
}
}

//==========================================================================