// -*-C++-*- (for Emacs)
/*
* This file is part of rasdaman community.
*
* Rasdaman community is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Rasdaman community is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with rasdaman community. If not, see .
*
* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann /
rasdaman GmbH.
*
* For more information please see
* or contact Peter Baumann via .
*/
/*************************************************************
*
* SOURCE: test_db2blob.cc
*
* MODULE: rasodmg
*
* PURPOSE:
*
* COMMENTS:
*
************************************************************/
#ifdef LINUX
#define __EXECUTABLE__
#include "raslib/template_inst.hh"
#endif
#ifdef __VISUALC__
#include
#else
#include
#endif
#include
#include
#include
#include
#include // for drand48()
#include "rasodmg/marray.hh"
#include "raslib/shhopt.h"
#include
#include "sql.h"
// number of repetitions for each query
unsigned long repeat = 20;
static int printFlag = 0;
EXEC SQL INCLUDE SQLCA;
#define CHECKERR(CE_STR) if (check_error (CE_STR, &sqlca) != 0)
// copied from DB2 example program
int check_error (char eString[], struct sqlca *caPointer) {
char eBuffer[1024];
char sBuffer[1024];
short rc, Erc;
if (caPointer->sqlcode != 0) {
printf ("--- error report ---\n");
printf ("ERROR occured : %s.\nSQLCODE : %ld\n", eString,
caPointer->sqlcode);
/**********************\
* GET SQLSTATE MESSAGE *
\**********************/
rc = sqlogstt (sBuffer, 1024, 80, caPointer->sqlstate);
/******************************\
* GET ERROR MESSAGE API called *
\******************************/
Erc = sqlaintp (eBuffer, 1024, 80, caPointer);
/* return code is the length of the eBuffer string */
if (Erc > 0) printf ("%s", eBuffer);
if (caPointer->sqlcode < 0) {
if (rc == 0) {
printf ("\n%s", sBuffer);
}
printf ("--- end error report ---\n");
return 1;
} else {
/* errorCode is just a Warning message */
if (rc == 0) {
printf ("\n%s", sBuffer);
}
printf ("--- end error report ---\n");
printf ("WARNING - CONTINUING PROGRAM WITH WARNINGS!\n");
return 0;
} /* endif */
} /* endif */
return 0;
}
class BMTimer
{
public:
/// constructor, initializes members
inline BMTimer();
inline void start();
inline void stop();
private:
/// reference parameter for gettimeofday().
timeval acttime;
// reference parameter for gettimeofday, not used.
static struct timezone dummy;
/// used to calculate time spent in function.
static long oldsec;
/// used to calculate time spent in function.
static long oldusec;
};
struct timezone BMTimer::dummy;
long BMTimer::oldsec;
long BMTimer::oldusec;
inline
BMTimer::BMTimer()
{
oldsec = 0;
oldusec = 0;
}
inline void
BMTimer::start()
{
gettimeofday(&acttime, &dummy);
}
inline void
BMTimer::stop()
{
oldsec = acttime.tv_sec;
oldusec = acttime.tv_usec;
gettimeofday(&acttime, &dummy);
cout << (acttime.tv_sec-oldsec)*1000000 + acttime.tv_usec
- oldusec << "us";
}
BMTimer myTimer;
r_Marray*
blobRead(r_Minterval& sd)
{
EXEC SQL BEGIN DECLARE SECTION;
long beginLoc;
long endLoc;
SQL TYPE IS BLOB_LOCATOR tomoLoc;
short tomo_ind;
// buf will be a structure with a char[] element called data and
// an unsigned long called length
SQL TYPE IS BLOB(256) blobBuf;
EXEC SQL END DECLARE SECTION;
int i,j;
// storing result
r_Marray* result = new r_Marray(sd);
char* resBuf = result->get_array();
EXEC SQL CONNECT TO sample;
myTimer.start();
EXEC SQL DECLARE curs1 CURSOR FOR
SELECT blob_col
FROM tomo_blob;
EXEC SQL OPEN curs1;
EXEC SQL FETCH curs1 INTO :tomoLoc :tomo_ind;
if (SQLCODE != 0) {
cout << "FETCH curs1: " << SQLCODE << endl;
}
if(tomo_ind < 0)
cout << "No BLOB there!" << endl;
// iterating through the Minterval
for(i=sd[0].low(); i<=sd[0].high(); i++) {
for(j=sd[1].low(); j<=sd[1].high(); j++) {
beginLoc = sd[2].low() + j*256 + i*256*256;
endLoc = sd[2].high() + j*256 + i*256*256;
unsigned long rowSize = endLoc - beginLoc + 1;
EXEC SQL VALUES (SUBSTR( :tomoLoc, :beginLoc, :endLoc - :beginLoc + 1))
INTO :blobBuf;
memcpy(resBuf, blobBuf.data, rowSize);
resBuf += rowSize;
}
}
EXEC SQL CLOSE curs1;
myTimer.stop();
EXEC SQL CONNECT RESET;
return result;
}
r_Marray*
blob1DRead(float sel)
{
EXEC SQL BEGIN DECLARE SECTION;
long beginLoc2;
long endLoc2;
SQL TYPE IS BLOB_LOCATOR tomoLoc2;
short tomo_ind2;
// buf will be a structure with a char[] element called data and
// an unsigned long called length
SQL TYPE IS BLOB(4000000) blobBuf2;
EXEC SQL END DECLARE SECTION;
int i,j;
// storing result
r_Minterval* sd_res;
sd_res = new r_Minterval("[0:255,0:255,0:153]");
r_Marray* result = new r_Marray(*sd_res);
char* resBuf = result->get_array();
EXEC SQL CONNECT TO sample;
EXEC SQL DECLARE curs2 CURSOR FOR
SELECT blob_col
FROM tomo_blob;
EXEC SQL OPEN curs2;
EXEC SQL FETCH curs2 INTO :tomoLoc2 :tomo_ind2;
if (SQLCODE != 0) {
cout << "FETCH curs2: " << SQLCODE << endl;
}
if(tomo_ind2 < 0)
cout << "No BLOB there!" << endl;
unsigned long rowSize = (int)(sel/100 * 10092544);
beginLoc2 = (int)(drand48() * (10092544 - rowSize));
endLoc2 = beginLoc2 + rowSize;
EXEC SQL VALUES (SUBSTR( :tomoLoc2, :beginLoc2, :endLoc2 - :beginLoc2 + 1))
INTO :blobBuf2;
memcpy(resBuf, blobBuf2.data, rowSize);
resBuf += rowSize;
EXEC SQL CLOSE curs2;
EXEC SQL CONNECT RESET;
delete sd_res;
return result;
}
void
blobInsert( char *fileName )
{
EXEC SQL BEGIN DECLARE SECTION;
SQL TYPE IS BLOB_FILE tomoFile;
EXEC SQL END DECLARE SECTION;
EXEC SQL CONNECT TO sample;
CHECKERR ("CONNECT TO") exit(1);
strcpy(tomoFile.name, fileName);
tomoFile.name_length = strlen(fileName);
tomoFile.file_options = SQL_FILE_READ;
EXEC SQL INSERT INTO tomo_blob
VALUES(:tomoFile);
CHECKERR ("INSERT INTO") exit(1);
EXEC SQL CONNECT RESET;
}
void
blob1DExec(int queryNum, float sel)
{
int i;
// storing the result
r_Marray* res;
for(i=1; i<=repeat; i++) {
myTimer.start();
res = blob1DRead(sel);
cout << queryNum << "." << i << ": ";
myTimer.stop();
cout << endl;
delete res;
}
// optionally printing the result
if( printFlag )
((r_GMarray*)(res))->r_GMarray::print_status();
}
void
execQuery(char* myRectStr, int queryNum, int i)
{
// storing the result
r_Marray* res;
// the query rectangle
r_Minterval* sd_res;
sd_res = new r_Minterval(myRectStr);
cout << queryNum << "." << i << ": ";
res = blobRead(*sd_res);
cout << endl;
delete res;
delete sd_res;
// optionally printing the result
if( printFlag )
((r_GMarray*)(res))->r_GMarray::print_status();
}
static void
printUsage(void)
{
cout << "Usage: test_db2blob [options] aFileName"
<< endl;
cout << " aFileName Name of file with query rectangles "
<< endl
<< " or BLOB data when inserting." << endl;
cout << " -h, --help Print this message and exit." << endl;
cout << " -i, --insert Insert BLOB instead of querying"
<< endl;
cout << " -p, --print Print data queried."
<< endl;
exit(0);
}
int
main( int argc, char** argv )
{
int iFlag = 0;
int queryNum = 0;
char fName[1024] = "";
float selArray[] = { 0.5, 1, 2, 5, 10, 20, 50, 100 };
optStruct testDB2BLOBOpt[] = {
/* short long type var/func special */
{ 'h', "help", OPT_FLAG, printUsage, OPT_CALLFUNC },
{ 'i', "insert", OPT_FLAG, &iFlag, 0 },
{ 'p', "print", OPT_FLAG, &printFlag, 0 },
{ 0, 0, OPT_END, 0, 0 } /* no more options */
};
/* parse all options */
optParseOptions(&argc, argv, testDB2BLOBOpt, 0);
strcpy(fName, argv[argc-1]);
if( iFlag ) {
blobInsert( fName );
exit(1);
}
ifstream fileStream( fName );
char buf[256];
char dummy;
int j = 0;
while( fileStream.get( buf, 255, '\n' ) ) {
fileStream.get(dummy);
if((buf[0] == '/' && buf[1] == '/') || buf[0] == 0) {
queryNum++;
cout << "Query " << queryNum << ": " << buf << endl;
j=0;
} else if(buf[0] != 0) {
execQuery(buf, queryNum, ++j);
}
}
// // Selectivity 50% and 100% does not work
// for(int i=0; i<6; i++) {
// cout << "BLOB selectivity " << selArray[i] << endl;
// blob1DExec(++queryNum, selArray[i]);
// }
}