/*
* 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: oqlquery.cc
*
* MODULE: rasodmg
* CLASS: r_OQL_Query
* FUNCTION: r_oql_execute()
*
* COMMENTS:
* None
*/
static const char rcsid[] = "@(#)rasodmg, r_OQL_Query and r_oql_execute(): $Id: oqlquery.cc,v 1.25 2002/08/28 12:21:57 coman Exp $";
#include "rasodmg/oqlquery.hh"
#include
#include // isdigit()
#ifdef __VISUALC__
#include
#else
#include
#endif
#ifdef __VISUALC__
#ifndef __EXECUTABLE__
#define __EXECUTABLE__
#define OQLQUERY_NOT_SET
#endif
#endif
#include "rasodmg/database.hh"
#include "rasodmg/transaction.hh"
#include "rasodmg/set.hh"
#include "rasodmg/gmarray.hh"
#include "raslib/rmdebug.hh"
#include "clientcomm/clientcomm.hh"
#ifdef OQLQUERY_NOT_SET
#undef __EXECUTABLE__
#endif
r_OQL_Query::r_OQL_Query()
: queryString(0),
parameterizedQueryString(0),
mddConstants(0)
{
}
r_OQL_Query::r_OQL_Query( const char* s )
: queryString(0),
mddConstants(0)
{
parameterizedQueryString = new char[strlen(s)+1];
strcpy( parameterizedQueryString, s );
reset_query();
}
r_OQL_Query::r_OQL_Query( const r_OQL_Query& q )
: queryString(0),
parameterizedQueryString(0),
mddConstants(0)
{
// copy the query string
if(q.queryString) {
queryString = new char[strlen(q.queryString)+1];
strcpy( queryString, q.queryString);
}
// copy the parameterized query string
if(q.parameterizedQueryString) {
parameterizedQueryString = new char[strlen(q.parameterizedQueryString)+1];
strcpy( parameterizedQueryString, q.parameterizedQueryString );
}
if( q.mddConstants ) {
mddConstants = new r_Set< r_GMarray* >( *(q.mddConstants) );
}
}
r_OQL_Query::~r_OQL_Query()
{
if( queryString )
delete[] queryString;
queryString = 0;
if( parameterizedQueryString )
delete[] parameterizedQueryString;
parameterizedQueryString = 0;
if( mddConstants )
delete mddConstants;
mddConstants = 0;
}
const r_OQL_Query&
r_OQL_Query::operator=( const r_OQL_Query& q )
{
if( this != &q )
{
// clean up and copy the query string
if( queryString )
{
delete[] queryString;
queryString = 0;
}
if( q.queryString )
{
queryString = new char[strlen(q.queryString)+1];
strcpy( queryString, q.queryString );
}
if( mddConstants )
{
delete mddConstants;
mddConstants = 0;
}
if( q.mddConstants )
{
mddConstants = new r_Set< r_GMarray* >( *(q.mddConstants) );
}
// clean up and copy the parameterized query string
if( parameterizedQueryString )
{
delete[] parameterizedQueryString;
parameterizedQueryString = 0;
}
if( q.parameterizedQueryString )
{
parameterizedQueryString = new char[strlen(q.parameterizedQueryString)+1];
strcpy( parameterizedQueryString, q.parameterizedQueryString );
}
}
return *this;
}
r_OQL_Query&
r_OQL_Query::operator<<( const char* s ) throw( r_Error )
{
try
{
replaceNextArgument( s );
}
catch( ... )
{
throw;
}
return *this;
}
r_OQL_Query&
r_OQL_Query::operator<<( r_Char c ) throw( r_Error )
{
char valueString[2];
valueString[0] = c;
valueString[1] = '\0';
try
{
replaceNextArgument( valueString );
}
catch( ... )
{
throw;
}
return *this;
}
r_OQL_Query&
r_OQL_Query::operator<<( r_Short s ) throw( r_Error )
{
char valueString[256];
std::ostrstream valueStream( valueString, 256 );
valueStream << s << std::ends;
try
{
replaceNextArgument( valueString );
}
catch( ... )
{
throw;
}
return *this;
}
r_OQL_Query&
r_OQL_Query::operator<<( r_UShort us ) throw( r_Error )
{
char valueString[256];
std::ostrstream valueStream( valueString, 256 );
valueStream << us << std::ends;
try
{
replaceNextArgument( valueString );
}
catch( ... )
{
throw;
}
return *this;
}
r_OQL_Query&
r_OQL_Query::operator<<( r_Long l ) throw( r_Error )
{
char valueString[256];
std::ostrstream valueStream( valueString, 256 );
valueStream << l << std::ends;
try
{
replaceNextArgument( valueString );
}
catch( ... )
{
throw;
}
return *this;
}
r_OQL_Query&
r_OQL_Query::operator<<( r_ULong ul ) throw( r_Error )
{
char valueString[256];
std::ostrstream valueStream( valueString, 256 );
valueStream << ul << std::ends;
try
{
replaceNextArgument( valueString );
}
catch( ... )
{
throw;
}
return *this;
}
r_OQL_Query&
r_OQL_Query::operator<<( r_Point pt ) throw( r_Error )
{
char valueString[256];
std::ostrstream valueStream( valueString, 256 );
valueStream << pt << std::ends;
try
{
replaceNextArgument( valueString );
}
catch( ... )
{
throw;
}
return *this;
}
r_OQL_Query&
r_OQL_Query::operator<<( r_Sinterval in ) throw( r_Error )
{
char valueString[256];
std::ostrstream valueStream( valueString, 256 );
valueStream << in << std::ends;
try
{
replaceNextArgument( valueString );
}
catch( ... )
{
throw;
}
return *this;
}
r_OQL_Query&
r_OQL_Query::operator<<( r_Minterval in ) throw( r_Error )
{
char valueString[256];
std::ostrstream valueStream( valueString, 256 );
valueStream << in << std::ends;
try
{
replaceNextArgument( valueString );
}
catch( ... )
{
throw;
}
return *this;
}
r_OQL_Query&
r_OQL_Query::operator<<( r_GMarray& in ) throw( r_Error )
{
// determine number of next mdd (starting with 0)
unsigned long mddNo = 0;
if( mddConstants )
mddNo = mddConstants->cardinality();
char valueString[256];
std::ostrstream valueStream( valueString, 256 );
valueStream << "#MDD" << mddNo << "#" << std::ends;
try
{
replaceNextArgument( valueString );
}
catch( ... )
{
throw;
}
// save reference to in
if( !mddConstants )
mddConstants = new r_Set< r_GMarray* >();
mddConstants->insert_element( &in );
return *this;
}
int
r_OQL_Query::is_update_query() const
{
return !is_retrieval_query();
}
int
r_OQL_Query::is_retrieval_query() const
{
int returnValue = 0;
if( parameterizedQueryString )
returnValue = strstr( parameterizedQueryString, "select" ) ||
strstr( parameterizedQueryString, "SELECT" );
return returnValue;
}
void
r_OQL_Query::reset_query()
{
if( queryString )
delete[] queryString;
queryString = new char[strlen(parameterizedQueryString)+1];
strcpy( queryString, parameterizedQueryString );
if( mddConstants )
{
delete mddConstants;
mddConstants = 0;
}
}
void
r_OQL_Query::replaceNextArgument( const char* valueString )
throw( r_Error )
{
char* argumentBegin=NULL;
char* argumentEnd=NULL;
char* argumentVal=NULL;
int argumentLength=0;
char* tmpString=NULL;
int length=0;
// locate the next argument in the query string
argumentBegin = argumentEnd = strchr( queryString, '$' );
if( !argumentBegin )
{
r_Error err = r_Error( r_Error::r_Error_QueryParameterCountInvalid );
throw err;
}
// while( *argumentEnd != ' ' && *argumentEnd != '\0' )
argumentEnd++;
//is digit or invalid argument format
if(!isdigit(*argumentEnd))
throw r_Error( QUERYPARAMETERINVALID );
while( isdigit(*argumentEnd) && *argumentEnd != ' ' && *argumentEnd != '\0' )
argumentEnd++;
argumentLength = argumentEnd - argumentBegin;
argumentVal = new char[ argumentLength + 1];
strncpy(argumentVal, argumentBegin, argumentLength);
argumentVal[argumentLength] = '\0';
while(true)
{
// allocate a new query string and fill it
tmpString = queryString;
length = strlen(queryString) - argumentLength + strlen(valueString);
queryString = new char[ length + 1 ];
*argumentBegin = '\0';
std::ostrstream queryStream( queryString, length + 1 );
queryStream << tmpString << valueString << argumentEnd << std::ends;
//update the reference
argumentEnd=queryString+strlen(tmpString)+strlen(valueString);
//remove buffer
delete[] tmpString;
//search again for this parameter
argumentEnd = argumentBegin = strstr( argumentEnd, argumentVal );
//end string?
if(argumentBegin == NULL)
break;
//skip $
argumentEnd++;
//is digit or invalid argument format
if(!isdigit(*argumentEnd))
{
delete [] argumentVal;
throw r_Error( QUERYPARAMETERINVALID );
}
//skip digits
while( isdigit(*argumentEnd) && *argumentEnd != ' ' && *argumentEnd != '\0' )
argumentEnd++;
}
delete[] argumentVal;
}
// HP COMPILER BUG
// The iterator type needs a typedef because otherwise the compiler creates a duplicate
// definition for each instance of the following template function.
typedef r_Iterator r_Iterator_r_GMarray;
void r_oql_execute( r_OQL_Query& query, r_Set< r_Ref_Any > &result )
throw( r_Error )
{
if( r_Database::actual_database == 0 || r_Database::actual_database->get_status() == r_Database::not_open )
{
r_Error err = r_Error( r_Error::r_Error_DatabaseClosed );
throw err;
}
if( r_Transaction::actual_transaction == 0 || r_Transaction::actual_transaction->get_status() != r_Transaction::active )
{
r_Error err = r_Error( r_Error::r_Error_TransactionNotOpen );
throw err;
}
try
{
r_Database::actual_database->getComm()->executeQuery( query, result );
}
catch( ... )
{
throw; // re-throw the exception
}
// reset the arguments of the query object
query.reset_query();
}
void r_oql_execute( r_OQL_Query& query, r_Set< r_Ref< r_GMarray > > &result )
throw( r_Error )
{
if( r_Database::actual_database == 0 || r_Database::actual_database->get_status() == r_Database::not_open )
{
r_Error err = r_Error( r_Error::r_Error_DatabaseClosed );
throw err;
}
if( r_Transaction::actual_transaction == 0 || r_Transaction::actual_transaction->get_status() != r_Transaction::active )
{
r_Error err = r_Error( r_Error::r_Error_TransactionNotOpen );
throw err;
}
try
{
r_Set< r_Ref_Any > genericSet;
r_Database::actual_database->getComm()->executeQuery( query, genericSet );
const r_Type* typeSchema = genericSet.get_element_type_schema();
if( !typeSchema || typeSchema->type_id() != r_Type::MARRAYTYPE )
{
r_Error err( r_Error::r_Error_TypeInvalid );
throw err;
}
//
// iterate through the generic set and build a specific one
//
result.set_type_by_name( genericSet.get_type_name() );
result.set_type_structure( genericSet.get_type_structure() );
r_Iterator< r_Ref_Any > iter;
for( iter=genericSet.create_iterator(); iter.not_done(); iter++ )
result.insert_element( r_Ref(*iter) );
}
catch( ... )
{
throw; // re-throw the exception
}
// reset the arguments of the query object
query.reset_query();
}
void r_oql_execute( r_OQL_Query& query )
throw( r_Error )
{
if( r_Database::actual_database == 0 || r_Database::actual_database->get_status() == r_Database::not_open )
{
r_Error err = r_Error( r_Error::r_Error_DatabaseClosed );
throw err;
}
if( r_Transaction::actual_transaction == 0 || r_Transaction::actual_transaction->get_status() != r_Transaction::active )
{
r_Error err = r_Error( r_Error::r_Error_TransactionNotOpen );
throw err;
}
try
{
r_Database::actual_database->getComm()->executeQuery( query );
}
catch( ... )
{
throw; // re-throw the exception
}
// reset the arguments of the query object
query.reset_query();
}