StRoot  1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
DbUse.cxx
1 /***************************************************************************
2  *
3  * $Id: DbUse.cxx,v 1.14 2016/05/24 17:44:16 dmitry Exp $
4  *
5  * Author: S. Vanyashin
6  ***************************************************************************
7  *
8  * Description: low-level C-code to read from "params" database
9  *
10  *
11  ***************************************************************************
12  *
13  * $Log: DbUse.cxx,v $
14  * Revision 1.14 2016/05/24 17:44:16 dmitry
15  * first batch of fixes for Coverity findings
16  *
17  * Revision 1.13 2012/06/11 14:33:19 fisyak
18  * std namespace
19  *
20  * Revision 1.12 2007/05/16 22:47:54 deph
21  * Replaced cerr with LOG_ERROR <<endm; for logger
22  *
23  * Revision 1.11 2005/12/06 21:33:03 deph
24  * clean up to remove warnings
25  *
26  * Revision 1.10 2003/09/02 17:55:35 perev
27  * gcc 3.2 updates + WarnOff
28  *
29  * Revision 1.9 2000/04/13 20:22:56 porter
30  * - reconnected tableDescriptor that had been broken via St_tableDescriptor.
31  * - added unix timestamp as standard
32  * - top node returned via InitConfig will be a database type
33  *
34  * Revision 1.8 2000/03/26 16:47:13 fine
35  * Adjusted to ROOT 2.24
36  *
37  * Revision 1.7 2000/01/31 17:11:18 porter
38  * fix break caused by the interaction design between
39  * 'StRoot/St_base/tableDescriptor.h' & 'StDbBroker::Descriptor'
40  * Now StDbBroker::Descriptor==tableDescriptor_st
41  * And StDbBroker::GetTableDescriptor() returns abstract StTableDescriptorI*
42  * Interface to StDbLib is (and was) handle correctly.
43  * StDbBroker is now tied to StRoot/St_base via tableDescriptor.h
44  * No problems would have occured if St_base interactions were based
45  * on StTableDesciptorI in the first place.
46  *
47  * Revision 1.6 2000/01/10 20:31:16 porter
48  * modified StDbBroker to be an interface to the DB-interface, StDbLib.
49  * - old functionality is retained for the short-term & modifications
50  * are extensions
51  *
52  *
53  **************************************************************************/
54 // idea: to get data from database
55 // DbUse allocate memory for the DbData array of fetched structures
56 // returning number of structures that was found
57 //
59 // //
60 // database data are stored in binary LITTLE_ENDIAN format //
61 // on BIG_ENDIAN machines byte swapping has to be done here //
62 // //
64 
65 #include <stdio.h>
66 #include <stdlib.h>
67 #include <string.h>
68 #include "Stiostream.h"
69 #include "Stsstream.h"
70 #include "mysql.h"
71 #include "mysql_com.h"
72 #include "DbEndian.h"
73 #include "StMessMgr.h"
74 #include "StDbBroker.h"
75 
76 extern "C" void * DbUse(uint *nRows,
77  uint *datetime,
78  const char * tableName,
79  const char * structName,
80  uint nVar,
81  uint sizeOfStruct,
83 {
84  enum EColumnType {kNAN, kFloat, kInt, kLong, kShort, kDouble, kUInt
85  ,kULong, kUShort, kUChar, kChar };
86 
87 //cout << "DbUse, event date time " << datetime[0]<<" "<< datetime[1] <<endl;
88 // cout << "DbUse, structure: "<<structName<<", table: "<<tableName<< endl;
89 // cout << " nVar"<<nVar<<", sizeOfStruct "<<sizeOfStruct<< endl;
90 
91  uint j;
92 uint count;
93 
94 MYSQL mysql;
95 MYSQL_RES *result;
96 MYSQL_ROW row;
97 
98 unsigned int num_fields;
99 unsigned int num_rows;
100 //unsigned int num_struct;
101 
102 //const int MAXBUF=1024;
103 std::ostringstream Query;
104 char temps[128];
105 
106 char validFrom[20];
107 char currentDateTime[20];
108 char time[7];
109 
110 sprintf(currentDateTime,"%.8d",datetime[0]);
111 sprintf(time,"%.6d",datetime[1]);
112 strcat(currentDateTime,time);
113 
114 currentDateTime[19]='\0';
115 currentDateTime[18]=currentDateTime[13];
116 currentDateTime[17]=currentDateTime[12];
117 currentDateTime[16]=':';
118 currentDateTime[15]=currentDateTime[11];
119 currentDateTime[14]=currentDateTime[10];
120 currentDateTime[13]=':';
121 currentDateTime[12]=currentDateTime[9];
122 currentDateTime[11]=currentDateTime[8];
123 currentDateTime[10]=' ';
124 currentDateTime[9]=currentDateTime[7];
125 currentDateTime[8]=currentDateTime[6];
126 currentDateTime[7]='-';
127 currentDateTime[6]=currentDateTime[5];
128 currentDateTime[5]=currentDateTime[4];
129 currentDateTime[4]='-';
130 
131 mysql_init(&mysql);
132 
133 //set timout in seconds for bnl.local domain
134 
135 //on sun:
136 //Program received signal SIGBUS, Bus error.
137 //0xed737d68 in mysql_options ()
138 
139 //mysql_options(&mysql,MYSQL_OPT_CONNECT_TIMEOUT,"4");
140 
141 // Establish a connection to the MySQL database engine
142 
143 char *dbName=new char[strlen("params")+1]; strcpy(dbName,"params");
144 //only db1 is visible from rcas0202 machine
145 char *dbHost=new char[strlen("db1.star.bnl.gov")+1];strcpy(dbHost,"db1.star.bnl.gov");
146 //char *dbHost="duvall.star.bnl.gov";
147 
148 //if (!mysql_real_connect(&mysql,"localhost","","",dbName,0,"/tmp/mysql.sock",0))
149 //mysql_real_connect(MYSQL *mysql, const char *host, const char *user, const char *passwd, const char *db, uint port, const char *unix_socket, uint client_flag)
150 //if (!mysql_real_connect(&mysql,"duvall.star.bnl.gov","","",dbName,0,NULL,0))
151 
152 if (!mysql_real_connect(&mysql,dbHost,"","",dbName,0,NULL,0))
153  {
154  LOG_ERROR << "Failed to connect to database: Error: "
155  << mysql_error(&mysql) << endm;
156  *nRows=0;
157  return NULL;
158  }
159 
160 //check if the instance+structure pair already exist
161 
162 Query.seekp(0);
163 if(strlen(tableName)>0)
164  {
165  //find latest date
166  Query << "SELECT DISTINCT MAX(instances.validFrom) FROM instances, structures WHERE instances.strID=structures.ID AND instances.name=\"" << tableName << "\" AND structures.name=\"" << structName << "\" AND instances.validFrom<\""<<currentDateTime<<"\" GROUP BY instances.name"<< std::ends;
167 // cout << "database query: " << Query.str() << endl;
168  }
169 else
170  {
171  LOG_ERROR<<"ERROR: Zero length for Table Name is not allowed"<<endm;
172  return NULL;
173  }
174 
175 uint num_latest;
176 int latestDirDate;
177 int latestDirTime;
178 
179 if (mysql_real_query(&mysql, Query.str().c_str(), int(Query.tellp())-1))
180  {
181  LOG_ERROR << "Failed to query: Error: " << mysql_error(&mysql) << endm;
182  mysql_close(&mysql);
183  return NULL;
184  }
185 else // query succeeded, get result
186  {
187  result = mysql_store_result(&mysql);
188  if (result)
189  {
190  num_fields = mysql_num_fields(result);
191  if (num_fields!=1) LOG_ERROR << "ERROR: wrong size of LATEST query"<<endm;
192 
193  num_latest = mysql_num_rows(result);
194 
195  if (num_latest==0)// found nothing
196  {
197  LOG_ERROR << "INFO: db " << dbName << " on host "<< dbHost
198  << " has no struct+table pair "<<structName<<"+"<< tableName
199  << " valid for "<<currentDateTime <<endm;
200  mysql_close(&mysql);
201  return NULL;
202  }
203  else // this structure name already exists
204  {
205  if (num_latest>1) LOG_ERROR << "ERROR: found more than one latest date"
206  << tableName << endm;
207 
208 // cout<<"Found "<<num_latest<<" struct "<<structName<<" for table "<<tableName<<endl;
209  row = mysql_fetch_row(result);
210 //convert hhmmss from: 1999-06-17 12:48:33
211  strncpy(validFrom,row[0],19);validFrom[19]='\0';
212  //start from blank at position row[0][10]
213  int ic=10;
214  for(int i3=0;i3<3;i3++,++ic) {
215  for(int i2=0;i2<2;i2++,++ic) {
216  temps[ic]=row[0][ic];
217  }
218  }
219  temps[6]='\0';
220  latestDirTime = atoi(temps);
221 
222  //get date from: 1999-06-17 12:48:33
223 
224  strncpy(temps,validFrom,10);
225  temps[4]=temps[5];
226  temps[5]=temps[6];
227  temps[6]=temps[8];
228  temps[7]=temps[9];
229  temps[8]='\0';
230 
231  latestDirDate = atoi(temps);
232  }
233  mysql_free_result(result);
234  }
235  else // query OK but, no result?!
236  {
237  LOG_ERROR << "no result: Error: " << mysql_error(&mysql) << endm;
238  mysql_close(&mysql);
239  return NULL;
240  }
241  }
242 
243  //find if there are many entries with the latest date
244 Query.seekp(0);
245  Query << "SELECT DISTINCT instances.ID, instances.nRows, instances.strID, structures.sizeOfStruct, structures.nElements FROM instances, structures WHERE instances.strID=structures.ID AND instances.name=\"" << tableName << "\" AND structures.name=\"" << structName << "\" AND instances.validFrom=\""<<validFrom<<"\" ORDER BY instances.entered"<< std::ends;
246 
247 //cout << "database query: " << Query.str() << endl;
248 
249 uint num_instances=99999;
250 int latestDirID=99999;
251 int latestStrID=99999;
252 uint sizeOfDbStruct=99999;
253 uint nDbVar=99999;
254 
255 if (mysql_real_query(&mysql, Query.str().c_str(), int(Query.tellp())-1))
256  {
257  LOG_ERROR << "Failed to query: Error: " << mysql_error(&mysql) << endm;
258  mysql_close(&mysql);
259  return NULL;
260  }
261 else // query succeeded, get result
262  {
263  result = mysql_store_result(&mysql);
264  if (result)
265  {
266  num_fields = mysql_num_fields(result);
267  if (num_fields!=5) LOG_ERROR << "ERROR: wrong size of latest entries query"<<endm;
268 
269  num_instances = mysql_num_rows(result);
270 
271  if (num_instances==0)// found nothing
272  {
273  LOG_ERROR << "ERROR: db " << dbName << " has lost the struct+table pair "
274  <<structName<<"+"<< tableName << endm;
275  mysql_close(&mysql);
276  return NULL;
277  }
278  else
279  {
280  if (num_instances>1)// bad
281  {
282  LOG_ERROR << "INFO: db " << dbName << " has more then one struct+table pair "
283  <<structName<<"+"<< tableName
284  << " valid for "<<currentDateTime
285  <<", the LAST INSERTED is used"<<endl;
286  LOG_ERROR << "database query: " << Query.str() << endm;
287  }
288  for (uint id=0;id<num_instances;id++)
289  {
290  row = mysql_fetch_row(result);
291  latestDirID = atoi(row[0]);
292  *nRows = (uint) atoi(row[1]);
293  latestStrID = atoi(row[2]);
294  sizeOfDbStruct = (uint)atoi(row[3]);
295  nDbVar = (uint)atoi(row[4]);
296  }
297  }
298  mysql_free_result(result);
299  }
300  else // query OK but, no result?!
301  {
302  LOG_ERROR << "no result: Error: " << mysql_error(&mysql) << endm;
303  mysql_close(&mysql);
304  return NULL;
305  }
306  }
307 
308 Query.seekp(0);
309 
310 if(sizeOfDbStruct!=sizeOfStruct)
311  {
312  LOG_ERROR<<"ERROR: DB struct byteSize is "<<sizeOfDbStruct<<endm;
313  LOG_ERROR<<" user struct byteSize is "<<sizeOfStruct<<endm;
314  LOG_ERROR << "structure: "<<structName<<endm;
315  *nRows=0;
316  return NULL;
317  }
318 
319 if(nVar!=nDbVar)
320  {
321  LOG_ERROR << "ERROR: DB struct nVariables is "<<nDbVar<<endm;
322  LOG_ERROR << " user struct nVariables is "<<nVar<<endm;
323  LOG_ERROR << "structure: "<<structName<<endm;
324  *nRows = 0;
325  return NULL;
326  }
327 
328 //to compare header file info in db and descriptor fetch db header info
329 char **types =0;
330 char **names =0;
331 int *offset=0;
332 int *nDims=0;
333 int *firstDim=0;
334 
335 
336 Query.seekp(0);
337 Query<<"SELECT name, type, offset, nDims, firstDim FROM headers WHERE strID="
338  << latestStrID << " ORDER BY offset" << std::ends;
339  //cout << "database query: " << Query.str() << endl;
340 
341 if (mysql_real_query(&mysql, Query.str().c_str(), int(Query.tellp())-1))
342  {
343  LOG_ERROR << "Failed to query: Error: " << mysql_error(&mysql) << endm;
344  mysql_close(&mysql);
345  return NULL;
346  }
347 else // query succeeded, get result
348  {
349  result = mysql_store_result(&mysql);
350  if (result)// query OK
351  {
352  num_fields = mysql_num_fields(result);
353  if (num_fields!=5) LOG_ERROR<<"ERROR: wrong size of headers query"<<endm;
354 
355  num_rows = mysql_num_rows(result);
356  // cout<<"total variables: "<< num_rows <<endl;
357 
358  if (num_rows!=nVar) //size is different from this ID
359  {
360  cout<<"WARNING: database structure is of "<< num_rows
361  <<" variables, this structure is "<< nVar <<endl;
362  }
363 
364  types = new char*[num_rows];
365  names = new char*[num_rows];
366  offset = new int[num_rows];
367  nDims = new int[num_rows];
368  firstDim = new int[num_rows];
369 
370  for (j=0;j<num_rows;j++)
371  {
372  row = mysql_fetch_row(result);
373 
374  names[j] = strdup(row[0]);
375  types[j] = strdup(row[1]);
376  offset[j] = atoi(row[2]);
377  nDims[j] = atoi(row[3]);
378  firstDim[j] = atoi(row[4]);
379 
380  //cout<<"name: \""<<row[0]<<"\""<<endl;
381  //cout<<"type: \""<<row[1]<<"\""<<endl;
382  //cout<<"offset: "<<offset[j]<<endl;
383  //cout<<"nDims: "<<nDims[j]<<endl;
384  //cout<<"firstDim: "<<firstDim[j]<<endl;
385  }
386  mysql_free_result(result);
387  }
388  }
389 
390 //now compare header file info in db and descriptor
391 
392 //same variables counter
393 count = 0;
394 
395 for (j=0;j<nVar;j++)
396  {
397  if (strcmp(d[j].fColumnName,names[j]))
398  break;
399 
400  //cout<<"offset: \""<<d[j].offset<<"\" \""<<row[1]<<"\""<<endl;
401  if ( d[j].fOffset!=(unsigned int)offset[j] )
402  break;
403 
404  //same offset: check nDims
405  //cout<<"nDims: \""<<d[j].dimensions<<"\" \""<<row[2]<<"\""<<endl;
406  if ( d[j].fDimensions!=(unsigned int)nDims[j] )
407  break;
408 
409  //same nDims: check firstDim
410  //cout<<"nDims: \""<<d[j].firstDimension<<"\" \""<<row[3]<<"\""<<endl;
411  if ( d[j].fIndexArray[0]!=(unsigned int)firstDim[j] )
412  break;
413 
414  //cout<<"variable "<< j+1 <<" is the same"<<endl;
415  count++;
416  }
417 
418 if (count!=nVar)
419  {
420  LOG_ERROR<<"structure " << structName
421  <<" is not compatible with database instance ID "<<latestDirID<<endm;
422  LOG_ERROR <<"nVar "<<nVar<<", count "<<count<<endm;
423 
424  for (j=0;j<nVar;j++)
425  {
426  LOG_ERROR<<"names: \""<<d[j].fColumnName<<"\" \""<<names[j]<<"\""<<endm;
427  if (strcmp(d[j].fColumnName,names[j]))
428  break;
429 
430  LOG_ERROR<<"offset: "<<d[j].fOffset<<" "<<offset[j]<<endm;
431  if ( d[j].fOffset!=(unsigned int)offset[j] )
432  break;
433 
434  LOG_ERROR<<"nDims: "<<d[j].fDimensions<<" "<<nDims[j]<<endm;
435  if ( d[j].fDimensions!=(unsigned int)nDims[j] )
436  break;
437 
438  LOG_ERROR<<"firstDim: "<<d[j].fIndexArray[0]<<" "<<firstDim[j]<<endm;
439  if ( d[j].fIndexArray[0]!=(unsigned int)firstDim[j] )
440  break;
441  }
442 
443  *nRows=0;
444  delete [] types;
445  delete [] names;
446  delete [] offset;
447  delete [] nDims;
448  delete [] firstDim;
449  return NULL;
450  }
451 
452 //char* pCurrent=new char[num_struct*sizeOfStruct];
453 //void * pDbData = (void*) pCurrent;
454 //Valeri Fine need's malloc() for ROOT free()
455 //void* pCurrent = malloc((size_t) num_struct*sizeOfStruct);
456 //use calloc() for array of structs?
457 void* pDbData = calloc((size_t) *nRows, (size_t) sizeOfDbStruct);
458 
459 if (pDbData==NULL){
460  LOG_ERROR<<"DbUse: failed to allocate memory nedeed for the array of "
461  << *nRows <<" structs " <<structName <<" each of "
462  <<sizeOfStruct <<" bytes"<<endm;
463  *nRows=0;
464  delete [] types;
465  delete [] names;
466  delete [] offset;
467  delete [] nDims;
468  delete [] firstDim;
469  free(pDbData);
470  return NULL;
471 }
472 
473 char* pCurrent = (char*) pDbData;
474 
475 uint num_blobs;
476 unsigned long *lengths;
477 
478 Query.seekp(0);
479 Query << "SELECT bytes FROM bytes WHERE instanceID="<<latestDirID<< std::ends;
480 
481 // cout << "database query: " << Query.str() << endl;
482 
483 if (mysql_real_query(&mysql, Query.str().c_str(), int(Query.tellp())-1))
484  {
485  LOG_ERROR << "Failed to query: Error: " << mysql_error(&mysql) << endm;
486  LOG_ERROR << "database query: " << Query.str() << endm;
487  mysql_close(&mysql);
488  return NULL;
489  }
490 else // query succeeded, get result
491  {
492  result = mysql_store_result(&mysql);
493  if (!result) // query OK but, no result?!
494  {
495  LOG_ERROR << "no result: Error: " << mysql_error(&mysql) << endm;
496  mysql_close(&mysql);
497  delete [] types;
498  delete [] names;
499  delete [] offset;
500  delete [] nDims;
501  delete [] firstDim;
502  free(pDbData);
503  pCurrent = 0;
504 
505  return NULL;
506  }
507  else
508  {
509  num_fields = mysql_num_fields(result);
510  if (num_fields!=1) LOG_ERROR << "ERROR: wrong size of blob query"<<endm;
511 
512  num_blobs = mysql_num_rows(result);
513 
514  if (num_blobs==0)// found nothing
515  {
516  LOG_ERROR << "ERROR: db " << dbName << " has lost BLOB for struct+table pair "
517  <<structName<<"+"<< tableName
518  << " valid for "<<currentDateTime <<endm;
519  mysql_close(&mysql);
520  delete [] types;
521  delete [] names;
522  delete [] offset;
523  delete [] nDims;
524  delete [] firstDim;
525  free(pDbData);
526  pCurrent = 0;
527  return NULL;
528  }
529  else
530  {
531  if (num_blobs>1) LOG_ERROR << "ERROR: found more than one BLOB for "
532  <<tableName<<endm;
533  //this is the place where data are fethched
534  row = mysql_fetch_row(result);
535 
536  if (row)
537  {
538  lengths = mysql_fetch_lengths(result);
539 
540  //cout << "blob size "<<lengths[0]<<" for table "<<tableName<<endl;
541  if (lengths[0]!=(*nRows)*sizeOfDbStruct)
542  {
543  LOG_ERROR << "ERROR: wrong blob size "
544  <<tableName<<endm;
545  LOG_ERROR <<"lengths[0] "<<lengths[0]
546  <<", nRows "<<(*nRows)
547  <<", sizeOfDbStruct "<<sizeOfDbStruct
548  <<", nRows*sizeOfDbStruct "<<(*nRows)*sizeOfDbStruct
549  <<endm;
550  mysql_close(&mysql);
551  *nRows=0;
552 
553  delete [] types;
554  delete [] names;
555  delete [] offset;
556  delete [] nDims;
557  delete [] firstDim;
558  free(pDbData);
559  return NULL;
560  }
561 
562 #ifndef BIG_ENDIAN
563  memcpy(pCurrent,row[0],(size_t) (*nRows)*sizeOfDbStruct);
564 #else // do byte swapping
565  //memset(pCurrent,0,(size_t) (*nRows)*sizeOfDbStruct);
566  uint i, k, nTimes, firstByte, firstDbByte;
567  //convert to user type (not Db type)
568 
569  for (i=0;i<*nRows;i++)
570  {
571  for (j=0;j<nVar;j++)
572  {
573 
574  switch(d[j].fDimensions)
575  {
576  case 0:
577  nTimes=1;
578  break;
579  case 1:
580  nTimes=d[j].fIndexArray[0];
581  break;
582  case 2:
583  LOG_ERROR<<"two-dims not handled yet"<<endm;
584  nTimes=0;
585  //nTimes=d[j].firstDimension*d[j].secondDimension;
586  break;
587  default:
588  LOG_ERROR << "ERROR: more that one dimension "<<endm;
589  nTimes=0;
590  break;
591  }
592 
593  //from db offset to user offset
594  firstByte=i*sizeOfStruct+d[j].fOffset;
595  firstDbByte=i*sizeOfDbStruct+offset[j];
596 
597  for (k=0;k<nTimes;k++) {
598 
599  //MYSQL_ROW row is just char**
600  switch((StDbBroker::EColumnType)d[j].fType)
601  {
602  case kUChar:
603  case kChar:
604  pCurrent[firstByte+k]=row[0][firstDbByte+k];
605  break;
606 
607  case kShort:
608  case kUShort:
609  pCurrent[firstByte+2*k+1]=row[0][+2*k ];
610  pCurrent[firstByte+2*k ]=row[0][firstDbByte+2*k+1];
611  break;
612 
613  case kInt:
614  case kUInt:
615 
616  case kULong:
617  case kLong:
618 
619  case kFloat:
620 
621  pCurrent[firstByte+4*k+3]=row[0][firstDbByte+4*k ];
622  pCurrent[firstByte+4*k+2]=row[0][firstDbByte+4*k+1];
623  pCurrent[firstByte+4*k+1]=row[0][firstDbByte+4*k+2];
624  pCurrent[firstByte+4*k ]=row[0][firstDbByte+4*k+3];
625  break;
626 
627  case kDouble:
628  //and long long
629  pCurrent[firstByte+8*k+7]=row[0][firstDbByte+8*k ];
630  pCurrent[firstByte+8*k+6]=row[0][firstDbByte+8*k+1];
631  pCurrent[firstByte+8*k+5]=row[0][firstDbByte+8*k+2];
632  pCurrent[firstByte+8*k+4]=row[0][firstDbByte+8*k+3];
633  pCurrent[firstByte+8*k+3]=row[0][firstDbByte+8*k+4];
634  pCurrent[firstByte+8*k+2]=row[0][firstDbByte+8*k+5];
635  pCurrent[firstByte+8*k+1]=row[0][firstDbByte+8*k+6];
636  pCurrent[firstByte+8*k ]=row[0][firstDbByte+8*k+7];
637  break;
638 
639  case kNAN:
640  default:
641  LOG_ERROR << "ERROR: unknown type!"<<endm;
642  break;
643  }
644  }//end loop over array variable
645  }//end loop over variables
646  }//end loop over nRows
647 #endif
648  }
649  }
650  mysql_free_result(result);
651  }
652  }
653 
654 // select just one table with the smallest date after the datetime
655 Query.seekp(0);
656  //find latest date
657  Query << "SELECT DISTINCT MIN(instances.validFrom) FROM instances, structures WHERE instances.strID=structures.ID AND instances.name=\"" << tableName << "\" AND structures.name=\"" << structName << "\" AND instances.validFrom>\""<<currentDateTime<<"\" GROUP BY instances.name"<<std::ends;
658 
659 // cout << "database query: " << Query.str() << endl;
660 
661 uint num_next;
662 int nextDirDate;
663 int nextDirTime;
664 
665 if (mysql_real_query(&mysql, Query.str().c_str(), int(Query.tellp())-1))
666  {
667  LOG_ERROR << "Failed to query: Error: " << mysql_error(&mysql) << endm;
668  mysql_close(&mysql);
669  return NULL;
670  }
671 else // query succeeded, get result
672  {
673  result = mysql_store_result(&mysql);
674  if (result)
675  {
676  num_fields = mysql_num_fields(result);
677  if (num_fields!=1) LOG_ERROR << "ERROR: wrong size of next date query"<<endm;
678 
679  num_next = mysql_num_rows(result);
680 
681  if (num_next==0)// found nothing no next table = no validity limit
682  {
683 // cout << "INFO: db " << dbName << " has no struct+table pair "
684 // << structName<<"+"<< tableName
685 // << " limiting validity for "<<setw(8)<<datetime[0]<<setw(6)<<datetime[1]<<endl;
686  nextDirDate=20380101;
687  nextDirTime=0;
688  }
689  else //validity limit exists
690  {
691  if (num_next>1) LOG_ERROR << "ERROR: found more than one next date"
692  <<tableName<<endm;
693 // cout<<"Found next "<<num_next<<" struct "<<structName<<" for table "<<tableName<<endl;
694 
695  row = mysql_fetch_row(result);
696 
697 
698 //convert hhmmss from: 1999-06-17 12:48:33
699  strncpy(validFrom,row[0],19);validFrom[19]='\0';
700  //start from blank at position row[0][10]
701  int ic=10;
702  for(int i3=0;i3<3;i3++,++ic) {
703  for(int i2=0;i2<2;i2++,++ic) {
704  temps[ic]=row[0][ic];
705  }
706  }
707  temps[6]='\0';
708  nextDirTime = atoi(temps);
709 
710  //get date from: 1999-06-17 12:48:33
711  strncpy(temps,validFrom,10);
712  temps[4]=temps[5];
713  temps[5]=temps[6];
714  temps[6]=temps[8];
715  temps[7]=temps[9];
716  temps[8]='\0';
717 
718  nextDirDate = atoi(temps);
719  }
720  mysql_free_result(result);
721  }
722  else // query OK but, no result?!
723  {
724  LOG_ERROR << "no result: Error: " << mysql_error(&mysql) << endm;
725  mysql_close(&mysql);
726  delete [] types;
727  delete [] names;
728  delete [] offset;
729  delete [] nDims;
730  delete [] firstDim;
731  free(pDbData);
732  pCurrent = 0;
733  return NULL;
734  }
735  }
736 
737 // We are done with the connection, call mysql_close() to terminate it
738 
739 mysql_close(&mysql);
740 
741 delete [] types;
742 delete [] names;
743 delete [] offset;
744 delete [] nDims;
745 delete [] firstDim;
746 
747 //fill return datetime values
748 
749 datetime[0] = latestDirDate;
750 datetime[1] = latestDirTime;
751 datetime[2] = nextDirDate;
752 datetime[3] = nextDirTime;
753 
754 // cout<<"Begin "<<datetime[0]<<" "<<datetime[1]<<endl;
755 // cout<<"End "<<datetime[2]<<" "<<datetime[3]<<endl;
756 
757 //cout <<"nRows = "<<*nRows<<endl;
758 return pDbData;
759 
760 }
761 
762