#include "dbqop.h"
namespace databases{
namespace odbc_database_operations{
//STRUCTS DEFINITIONS
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//DBConnection DEFINITIONS
DBConnection::DBConnection():
environment_handle(nullptr),database_connection_handle(nullptr),
environment_handle_allocated(false),connection_handle_allocated(false),
sql_command_prepared(false),asynch_support(false),is_connected(false),
is_open(false),flag(0),connection_string(""),output_connection_string(""),
server_string(""),user_string(""),password_string(""),last_message("")
{
}
DBConnection::~DBConnection()
{
// Connection
if(database_connection_handle!=SQL_NULL_HDBC)
{
SQLDisconnect(database_connection_handle);
SQLFreeHandle(SQL_HANDLE_DBC,database_connection_handle);
database_connection_handle=SQL_NULL_HDBC;
}
// Environment
if(environment_handle!=SQL_NULL_HENV)
{
SQLFreeHandle(SQL_HANDLE_ENV,environment_handle);
environment_handle=SQL_NULL_HENV;
}
}
DBConnection& DBConnection::operator=(const DBConnection& rhs)
{
if(this != &rhs)// handle self assignment
{
this->environment_handle_allocated=rhs.environment_handle_allocated;
this->connection_handle_allocated=rhs.connection_handle_allocated;
this->sql_command_prepared=rhs.sql_command_prepared;
this->asynch_support=rhs.asynch_support;
this->is_connected=rhs.is_connected;
this->is_open=rhs.is_open;
this->connection_string=rhs.connection_string;
this->output_connection_string=rhs.output_connection_string;
this->server_string=rhs.server_string;
this->user_string=rhs.user_string;
this->password_string=rhs.password_string;
this->last_message=rhs.last_message;
this->flag=rhs.flag;
this->environment_handle=rhs.environment_handle;//Environment handle
this->database_connection_handle=rhs.database_connection_handle;//Database connection handle
}
return *this;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//DBColumn DEFINITIONS
DBColumn::DBColumn():
table_owner(0),column_type(0),catalog_name_length(0),schema_name_length(0),
table_name_length(0),column_name_length(0),column_type_name_length(0),
data_length_indicator(0),column_buffer_length(0),column_buffer(nullptr)
{
}
DBColumn::~DBColumn()
{
delete[] column_buffer;
}
DBColumn::DBColumn(const short& new_column_type,const long& buffer_length):
table_owner(0),column_type(new_column_type),catalog_name_length(0),
schema_name_length(0),table_name_length(0),column_name_length(0),
column_type_name_length(0),data_length_indicator(0),
column_buffer_length(buffer_length),column_buffer(nullptr)
{
column_buffer=new SQLCHAR[buffer_length];
}
DBColumn::DBColumn(const DBColumn& other):
table_owner(0),column_type(0),catalog_name_length(0),schema_name_length(0),
table_name_length(0),column_name_length(0),column_type_name_length(0),
data_length_indicator(0),column_buffer_length(0),column_buffer(nullptr)
{
table_owner=other.table_owner;
column_type=other.column_type;
catalog_name_length=other.catalog_name_length;
schema_name_length=other.schema_name_length;
table_name_length=other.table_name_length;
column_name_length=other.column_name_length;
column_type_name_length=other.column_type_name_length;
data_length_indicator=other.data_length_indicator;
column_buffer_length=other.column_buffer_length;//Max byte length of the column
memcpy(catalog_name,other.catalog_name,SQL_MAX_CATALOG_NAME_LEN);
memcpy(schema_name,other.schema_name,SQL_MAX_SCHEMA_NAME_LEN);
memcpy(table_name,other.table_name,SQL_MAX_TABLE_NAME_LEN);
memcpy(column_name,other.column_name,SQL_MAX_COLUMN_NAME_LEN);
memcpy(column_type_name,other.column_type_name,MAX_COL_TYPE_NAME_LENGTH);
column_buffer=new SQLCHAR[other.column_buffer_length];
memcpy(column_buffer,other.column_buffer,other.column_buffer_length);
}
DBColumn& DBColumn::operator=(const DBColumn& rhs)
{
if(this != &rhs)
{
this->table_owner=rhs.table_owner;
this->column_type=rhs.column_type;
this->catalog_name_length=rhs.catalog_name_length;
this->schema_name_length=rhs.schema_name_length;
this->table_name_length=rhs.table_name_length;
this->column_name_length=rhs.column_name_length;
this->column_type_name_length=rhs.column_type_name_length;
this->data_length_indicator=rhs.data_length_indicator;
this->column_buffer_length=rhs.column_buffer_length;//Max byte length of the column
memcpy(this->catalog_name,rhs.catalog_name,SQL_MAX_CATALOG_NAME_LEN);
memcpy(this->schema_name,rhs.schema_name,SQL_MAX_SCHEMA_NAME_LEN);
memcpy(this->table_name,rhs.table_name,SQL_MAX_TABLE_NAME_LEN);
memcpy(this->column_name,rhs.column_name,SQL_MAX_COLUMN_NAME_LEN);
memcpy(this->column_type_name,rhs.column_type_name,MAX_COL_TYPE_NAME_LENGTH);
this->column_buffer=new SQLCHAR[rhs.column_buffer_length];
memcpy(this->column_buffer,rhs.column_buffer,rhs.column_buffer_length);
}
return *this;
}
brw::Archive& DBColumn::operator&(brw::Archive& ar)
{
return ar;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//DBRow DEFINITIONS
DBRow::DBRow():
table_owner(0),row_index(0),row_data()
{
}
DBRow::DBRow(const DBRow& other):
table_owner(other.table_owner),row_index(other.row_index),row_data(other.row_data)
{
}
DBRow::DBRow(const uintptr_t& row_table_owner,const UINT& new_row_index):
table_owner(0),row_index(new_row_index),row_data()
{
DBTable table=*reinterpret_cast<DBTable*>(row_table_owner);
table_owner=row_table_owner;
//row_index=new_row_index;
row_data=RowData(table.total_columns);
for(short i=0;i<table.total_columns;i++)
{
CellData value;
value.buffer_size=table.table_columns[i].column_buffer_length;
value.buffer=new SQLCHAR[table.table_columns[i].column_buffer_length];
row_data[i]=value;
}
}
DBRow& DBRow::operator=(const DBRow& rhs)
{
if(this != &rhs)
{
this->table_owner=rhs.table_owner;
this->row_index=rhs.row_index;
this->row_data=rhs.row_data;
}
return *this;
}
DBRow::~DBRow()
{
}
void* DBRow::getValue(const short& column_index) const
{
DBTable table=*reinterpret_cast<DBTable*>(table_owner);
if(table.total_columns==0)
{
return nullptr;
}
CellData value=row_data[column_index];
if(!value.buffer)
{
return nullptr;
}
long len=value.buffer_size;
switch(table.table_columns[column_index].column_type)
{
case SQL_BIT:
{
break;
}
case SQL_CHAR:
{
char data1[len+1];
for(long i=0;i<len;i++)
{
data1[i]=(char)value.buffer[i];
}
data1[len]='\0';
static std::string value1;
value1=std::string(data1);
return &value1;
}
case SQL_VARCHAR:
{
char* data2=new char[len+1];
for(long i=0;i<len;i++)
{
data2[i]=(char)value.buffer[i];
}
data2[len]='\0';
static std::string value2;
value2=std::string(data2);
return &value2;
}
case SQL_LONGVARCHAR:
{
break;
}
case SQL_WCHAR:
{
break;
}
case SQL_WVARCHAR:
{
break;
}
case SQL_WLONGVARCHAR:
{
break;
}
case SQL_TINYINT:
{
PSQLCHAR data7=reinterpret_cast<PSQLCHAR>(value.buffer);
static unsigned char value7;
value7=(unsigned char)(*data7);
return &value7;
}
case SQL_SMALLINT:
{
short* data8=reinterpret_cast<short*>(value.buffer);
static short value8;
value8=(short)(*data8);
return &value8;
}
case SQL_INTEGER:
{
int* data9=reinterpret_cast<int*>(value.buffer);
static int value9;
value9=(int)(*data9);
return &value9;
break;
}
case SQL_BIGINT:
{
long* data10=reinterpret_cast<long*>(value.buffer);
static long value10;
value10=long(*data10);
return &value10;
}
case SQL_DECIMAL:
{
break;
}
case SQL_NUMERIC:
{
break;
}
case SQL_REAL:
{
break;
}
case SQL_FLOAT:
{
float* data14=reinterpret_cast<float*>(value.buffer);
static float value14;
value14=float(*data14);
return &value14;
}
case SQL_DOUBLE:
{
double* data15=reinterpret_cast<double*>(value.buffer);
static double value15;
value15=double(*data15);
return &value15;
}
case SQL_DATE:
{
break;
}
case SQL_TIME:
{
break;
}
case SQL_TYPE_TIMESTAMP:
{
PTIMESTAMP buffer18=reinterpret_cast<PTIMESTAMP>(value.buffer);
tm data18;
data18.tm_year=buffer18->year;
data18.tm_mon=buffer18->month;
data18.tm_mday=buffer18->day;
data18.tm_hour=buffer18->hour;
data18.tm_min=buffer18->minute;
data18.tm_sec=buffer18->second;
tm timeinfo = {};
timeinfo.tm_year = data18.tm_year - 1900;
timeinfo.tm_mon = data18.tm_mon - 1;
timeinfo.tm_mday = data18.tm_mday;
mktime(&timeinfo);
data18.tm_yday = timeinfo.tm_yday;
data18.tm_wday=timeinfo.tm_wday;
static tm value18;
value18=data18;
return &value18;
}
case SQL_BINARY:
{
break;
}
case SQL_VARBINARY:
{
break;
}
case SQL_LONGVARBINARY:
{
break;
}
default:
{
break;
}
}
return nullptr;
}
void DBRow::getValue(const short& column_index,CellData& value) const
{
DBTable table=*reinterpret_cast<DBTable*>(table_owner);
if(table.total_columns==0)
{
value.buffer=nullptr;
value.buffer_size=0;
}
else
{
CellData value_data;
CellData cell=row_data[column_index];
value_data.buffer_size=cell.buffer_size;
value_data.buffer=new SQLCHAR[value_data.buffer_size];
memcpy(
value_data.buffer,
cell.buffer,
cell.buffer_size
);
value=value_data;
}
}
void DBRow::setValue(const short& column_index,void* value) const
{
}
void DBRow::setValue(const short& column_index,const CellData& value)
{
row_data[column_index]=value;
}
DBRow DBRow::cloneRow() const
{
DBRow clone;
clone.table_owner=table_owner;
clone.row_index=row_index;
clone.row_data=row_data;
return clone;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//DBTable DEFINITIONS
DBTable::DBTable():
sql_statement(""),database_name(""),catalog_name(""),schema_name(""),table_name(""),
total_columns(0),total_primary_key_columns(0),total_foreign_key_columns(0),
primary_key_columns(nullptr),foreign_key_columns(nullptr),total_rows(0),
table_columns(nullptr),statement_handle(nullptr),table_data(),
is_primary_keys_set(false),is_foreign_keys_set(false)
{
}
DBTable::~DBTable()
{
if(statement_handle!=SQL_NULL_HSTMT)
{
SQLFreeHandle(SQL_HANDLE_STMT,statement_handle);
statement_handle=SQL_NULL_HSTMT;
}
delete[] table_columns;
delete[] primary_key_columns;
}
DBTable::DBTable(const short& new_total_columns,DBColumn* new_table_columns):
sql_statement(""),database_name(""),catalog_name(""),schema_name(""),table_name(""),
total_columns(0),total_primary_key_columns(0),total_foreign_key_columns(0),
primary_key_columns(nullptr),foreign_key_columns(nullptr),total_rows(0),
table_columns(nullptr),statement_handle(nullptr),table_data(),
is_primary_keys_set(false),is_foreign_keys_set(false)
{
total_columns=new_total_columns;
table_columns=new DBColumn[new_total_columns];
primary_key_columns=new short[new_total_columns];
foreign_key_columns=new short[new_total_columns];
for(short i=0;i<new_total_columns;i++)
{
table_columns[i]=DBColumn(new_table_columns[i]);
}
table_data=TableData();
}
DBTable::DBTable(const DBTable& other):
sql_statement(other.sql_statement),database_name(other.database_name),
catalog_name(other.catalog_name),schema_name(other.schema_name),
table_name(other.table_name),total_columns(0),total_primary_key_columns(0),
total_foreign_key_columns(0),primary_key_columns(nullptr),
foreign_key_columns(nullptr),total_rows(other.total_rows),table_columns(nullptr),
statement_handle(nullptr),table_data(),is_primary_keys_set(false),
is_foreign_keys_set(false)
{
total_columns=other.total_columns;
total_primary_key_columns=other.total_primary_key_columns;
total_foreign_key_columns=other.total_foreign_key_columns;
table_columns=new DBColumn[other.total_columns];
primary_key_columns=new short[other.total_primary_key_columns];
foreign_key_columns=new short[other.total_foreign_key_columns];
for(short i=0;i<other.total_columns;i++)
{
table_columns[i]=other.table_columns[i];
}
for(short i=0;i<other.total_primary_key_columns;i++)
{
primary_key_columns[i]=other.primary_key_columns[i];
}
for(short i=0;i<other.total_foreign_key_columns;i++)
{
foreign_key_columns[i]=other.foreign_key_columns[i];
}
statement_handle=other.statement_handle;
table_data=other.table_data;
}
DBTable& DBTable::operator=(const DBTable& rhs)
{
if(this != &rhs)
{
this->sql_statement=rhs.sql_statement;
this->database_name=rhs.database_name;
this->catalog_name=rhs.catalog_name;
this->schema_name=rhs.schema_name;
this->table_name=rhs.table_name;
this->total_columns=rhs.total_columns;
this->total_primary_key_columns=rhs.total_primary_key_columns;
this->total_foreign_key_columns=rhs.total_foreign_key_columns;
this->total_rows=rhs.total_rows;
this->table_columns=new DBColumn[rhs.total_columns];
this->primary_key_columns=new short[rhs.total_primary_key_columns];
this->foreign_key_columns=new short[rhs.total_foreign_key_columns];
for(short i=0;i<rhs.total_columns;i++)
{
this->table_columns[i]=rhs.table_columns[i];
}
for(short i=0;i<rhs.total_primary_key_columns;i++)
{
this->primary_key_columns[i]=rhs.primary_key_columns[i];
}
for(short i=0;i<rhs.total_foreign_key_columns;i++)
{
this->foreign_key_columns[i]=rhs.foreign_key_columns[i];
}
this->statement_handle=rhs.statement_handle;
this->table_data=rhs.table_data;
this->is_primary_keys_set=rhs.is_primary_keys_set;
this->is_foreign_keys_set=rhs.is_foreign_keys_set;
}
return *this;
}
brw::Archive& DBTable::operator&(brw::Archive& ar)
{
switch(ar.getFileVersion())
{
case FILE_VERSION:
{
break;
}
default:
{
break;
}
}
return ar;
}
DBRow DBTable::newRow() const
{
DBRow new_row=DBRow(reinterpret_cast<uintptr_t>(this),0);
return new_row;
}
DBRow DBTable::getRow(const UINT& row_index) const
{
DBRow row=DBRow(reinterpret_cast<uintptr_t>(this),row_index);
for(short i=0;i<total_columns;i++)
{
CellData value;
getValue(row_index,i,value);
row.setValue(i,value);
}
return row;
}
void DBTable::addRow(UINT& new_row_index)
{
RowData row_data=RowData(total_columns);
for(short i=0;i<total_columns;i++)
{
CellData value;
value.buffer_size=table_columns[i].column_buffer_length;
value.buffer=new SQLCHAR[table_columns[i].column_buffer_length];
row_data[i]=value;
}
table_data.push_back(row_data);
new_row_index=total_rows;
total_rows++;
}
void DBTable::addRow(const DBRow& new_row)
{
RowData row_data=RowData(total_columns);
for(short i=0;i<total_columns;i++)
{
CellData value;
new_row.getValue(i,value);
row_data[i]=value;
}
table_data.push_back(row_data);
total_rows++;
}
void* DBTable::getValue(const UINT& row_index,const short& column_index) const
{
if((total_columns==0) || (total_rows==0))
{
return nullptr;
}
CellData value=table_data[row_index][column_index];
if(!value.buffer)
{
return nullptr;
}
long len=value.buffer_size;
switch(table_columns[column_index].column_type)
{
case SQL_BIT:
{
break;
}
case SQL_CHAR:
{
char data1[len+1];
for(long i=0;i<len;i++)
{
data1[i]=(char)value.buffer[i];
}
data1[len]='\0';
static std::string value1;
value1=std::string(data1);
return &value1;
}
case SQL_VARCHAR:
{
char* data2=new char[len+1];
for(long i=0;i<len;i++)
{
data2[i]=(char)value.buffer[i];
}
data2[len]='\0';
static std::string value2;
value2=std::string(data2);
return &value2;
}
case SQL_LONGVARCHAR:
{
break;
}
case SQL_WCHAR:
{
break;
}
case SQL_WVARCHAR:
{
break;
}
case SQL_WLONGVARCHAR:
{
break;
}
case SQL_TINYINT:
{
PSQLCHAR data7=reinterpret_cast<PSQLCHAR>(value.buffer);
static unsigned char value7;
value7=(unsigned char)(*data7);
return &value7;
}
case SQL_SMALLINT:
{
short* data8=reinterpret_cast<short*>(value.buffer);
static short value8;
value8=(short)(*data8);
return &value8;
}
case SQL_INTEGER:
{
int* data9=reinterpret_cast<int*>(value.buffer);
static int value9;
value9=(int)(*data9);
return &value9;
break;
}
case SQL_BIGINT:
{
long* data10=reinterpret_cast<long*>(value.buffer);
static long value10;
value10=long(*data10);
return &value10;
}
case SQL_DECIMAL:
{
break;
}
case SQL_NUMERIC:
{
break;
}
case SQL_REAL:
{
break;
}
case SQL_FLOAT:
{
float* data14=reinterpret_cast<float*>(value.buffer);
static float value14;
value14=float(*data14);
return &value14;
}
case SQL_DOUBLE:
{
double* data15=reinterpret_cast<double*>(value.buffer);
static double value15;
value15=double(*data15);
return &value15;
}
case SQL_DATE:
{
break;
}
case SQL_TIME:
{
break;
}
case SQL_TYPE_TIMESTAMP:
{
PTIMESTAMP buffer18=reinterpret_cast<PTIMESTAMP>(value.buffer);
tm data18;
data18.tm_year=buffer18->year;
data18.tm_mon=buffer18->month;
data18.tm_mday=buffer18->day;
data18.tm_hour=buffer18->hour;
data18.tm_min=buffer18->minute;
data18.tm_sec=buffer18->second;
tm timeinfo = {};
timeinfo.tm_year = data18.tm_year - 1900;
timeinfo.tm_mon = data18.tm_mon - 1;
timeinfo.tm_mday = data18.tm_mday;
mktime(&timeinfo);
data18.tm_yday = timeinfo.tm_yday;
data18.tm_wday=timeinfo.tm_wday;
static tm value18;
value18=data18;
return &value18;
}
case SQL_BINARY:
{
break;
}
case SQL_VARBINARY:
{
break;
}
case SQL_LONGVARBINARY:
{
break;
}
default:
{
}
}
return nullptr;
}
void DBTable::getValue
(
const UINT& row_index,
const short& column_index,
CellData& value
) const
{
CellData cell=table_data[row_index][column_index];
if(!cell.buffer)
{
value.buffer=nullptr;
value.buffer_size=0;
}
else
{
value.buffer_size=cell.buffer_size;
value.buffer=new SQLCHAR[cell.buffer_size];
memcpy(value.buffer,cell.buffer,cell.buffer_size);
}
}
void DBTable::setValue
(
const UINT& row_index,
const short& column_index,
void* value,
const long& value_length
)
{
CellData cell_value;
if(!value)
{
cell_value.buffer=nullptr;
cell_value.buffer_size=0;
}
else
{
long len;
switch(table_columns[column_index].column_type)
{
case SQL_BIT:
{
break;
}
case SQL_CHAR:
{
char* buffer1=reinterpret_cast<char*>(value);
len=sizeof(char);
cell_value.buffer=new SQLCHAR[len];
cell_value.buffer_size=len;
memcpy(cell_value.buffer,buffer1,len);
break;
}
case SQL_VARCHAR:
{
char* buffer2=reinterpret_cast<char*>(value);
len=value_length;
cell_value.buffer=new SQLCHAR[len];
cell_value.buffer_size=len;
memcpy(cell_value.buffer,buffer2,len);
break;
}
case SQL_LONGVARCHAR:
{
break;
}
case SQL_WCHAR:
{
break;
}
case SQL_WVARCHAR:
{
break;
}
case SQL_WLONGVARCHAR:
{
break;
}
case SQL_TINYINT:
{
unsigned char* buffer7=reinterpret_cast<unsigned char*>(value);
len=sizeof(unsigned char);
cell_value.buffer=new SQLCHAR[len];
cell_value.buffer_size=len;
memcpy(cell_value.buffer,buffer7,len);
break;
}
case SQL_SMALLINT:
{
short* buffer8=reinterpret_cast<short*>(value);
len=sizeof(short);
cell_value.buffer=new SQLCHAR[len];
cell_value.buffer_size=len;
memcpy(cell_value.buffer,buffer8,len);
break;
}
case SQL_INTEGER:
{
int* buffer9=reinterpret_cast<int*>(value);
len=sizeof(int);
cell_value.buffer=new SQLCHAR[len];
cell_value.buffer_size=len;
memcpy(cell_value.buffer,buffer9,len);
break;
}
case SQL_BIGINT:
{
long* buffer10=reinterpret_cast<long*>(value);
len=sizeof(long);
cell_value.buffer=new SQLCHAR[len];
cell_value.buffer_size=len;
memcpy(cell_value.buffer,buffer10,len);
break;
}
case SQL_DECIMAL:
{
break;
}
case SQL_NUMERIC:
{
break;
}
case SQL_REAL:
{
break;
}
case SQL_FLOAT:
{
float* buffer14=reinterpret_cast<float*>(value);
len=sizeof(float);
cell_value.buffer=new SQLCHAR[len];
cell_value.buffer_size=len;
memcpy(cell_value.buffer,buffer14,len);
break;
}
case SQL_DOUBLE:
{
double* buffer15=reinterpret_cast<double*>(value);
len=sizeof(double);
cell_value.buffer=new SQLCHAR[len];
cell_value.buffer_size=len;
memcpy(cell_value.buffer,buffer15,len);
break;
}
case SQL_DATE:
{
break;
}
case SQL_TIME:
{
break;
}
case SQL_TYPE_TIMESTAMP:
{
PTIMESTAMP buffer18=reinterpret_cast<PTIMESTAMP>(value);
len=sizeof(SQL_TIMESTAMP_STRUCT);
cell_value.buffer=new SQLCHAR[len];
cell_value.buffer_size=len;
memcpy(cell_value.buffer,buffer18,len);
break;
}
case SQL_BINARY:
{
break;
}
case SQL_VARBINARY:
{
break;
}
case SQL_LONGVARBINARY:
{
break;
}
default:
{
break;
}
}
}
table_data[row_index][column_index]=cell_value;
}
void DBTable::setValue
(
const UINT& row_index,
const short& column_index,
const CellData& value
)
{
CellData cell;
if(!value.buffer)
{
cell.buffer=nullptr;
cell.buffer_size=0;
}
else
{
cell.buffer_size=value.buffer_size;
cell.buffer=new SQLCHAR[value.buffer_size];
memcpy(cell.buffer,value.buffer,value.buffer_size);
}
table_data[row_index][column_index]=cell;
}
bool DBTable::findRow
(
const short& key_column_index,
const CellData& value,
const UINT& starting_row_index,
DBRow& row
)
{
if(total_columns==0 || total_rows==0)
{
return false;
}
for(UINT i=starting_row_index;i<total_rows;i++)
{
if(memcmp
(
table_data[i][key_column_index].buffer,
value.buffer,
value.buffer_size
)==0)
{
row=getRow(i);
return true;
}
}
return false;
}
bool DBTable::findRowPattern
(
const short& key_column_index,
const std::string& value,
const UINT& starting_row_index,
DBRow& row
) const
{
if(total_columns==0 || total_rows==0)
{
return false;
}
const char* pattern;
CellData cell;
std::string::size_type pos=value.find_first_of('%');
if(pos==std::string::npos)//When search is an exact search
{
pattern=new char[value.size()];
memcpy((char*)pattern,value.c_str(),value.size());
for(UINT i=starting_row_index;i<total_rows;i++)
{
cell=table_data[i][key_column_index];
if(cell.buffer)
{
if(std::strcmp(reinterpret_cast<char*>(cell.buffer),pattern)==0)
{
row=getRow(i);
return true;
}
}
}
}
else if(pos==0 && value.find_last_of('%')==(value.size()-1))//When search pattern is of the form %pattern%
{
std::string::size_type len=value.size()-2;
pattern=new char[len];
memcpy((char*)pattern,value.substr(1,len).c_str(),len);
for(UINT i=starting_row_index;i<total_rows;i++)
{
cell=table_data[i][key_column_index];
if(cell.buffer)
{
if(std::strstr(reinterpret_cast<char*>(cell.buffer),pattern))
{
row=getRow(i);
return true;
}
}
}
}
else if(pos==0)//When search pattern is of the form %pattern
{
std::string::size_type len=value.size()-1;
pattern=new char[len];
memcpy((char*)pattern,value.substr(1,len).c_str(),len);
char* match;
for(UINT i=starting_row_index;i<total_rows;i++)
{
cell=table_data[i][key_column_index];
if(cell.buffer)
{
if(cell.buffer_size>=(long)len)
{
match=std::strstr(reinterpret_cast<char*>(cell.buffer),pattern);
if(match)
{
if((match-reinterpret_cast<char*>(cell.buffer))==
(long)(cell.buffer_size-len))
{
row=getRow(i);
return true;
}
}
}
}
}
}
else//When search pattern is of the form pattern%
{
std::string::size_type len=value.size()-1;
pattern=new char[len];
memcpy((char*)pattern,value.substr(0,len).c_str(),len);
char* match;
for(UINT i=starting_row_index;i<total_rows;i++)
{
cell=table_data[i][key_column_index];
if(cell.buffer)
{
if(cell.buffer_size>=(long)len)
{
match=std::strstr(reinterpret_cast<char*>(cell.buffer),pattern);
if(match)
{
if((match-reinterpret_cast<char*>(cell.buffer))==0)
{
row=getRow(i);
return true;
}
}
}
}
}
}
return false;
}
bool DBTable::getPrimaryKeys
(
short*& primary_keys,
short& total_primary_keys,
std::string& message
)
{
if(!is_primary_keys_set)
{
DBKeyColumn* table_primary_keys;
if(!DBGetPrimaryKeys
(
*this,
table_primary_keys,
total_primary_key_columns,
message
))
{
return false;
}
primary_key_columns=new short[total_primary_key_columns];
for(short i=0;i<total_primary_key_columns;i++)
{
primary_key_columns[i]=table_primary_keys[i].key_ordinal;
}
}
total_primary_keys=total_primary_key_columns;
primary_keys=new short[total_primary_key_columns];
for(short i=0;i<total_primary_key_columns;i++)
{
primary_keys[i]=primary_key_columns[i];
}
is_primary_keys_set=true;
return true;
}
bool DBTable::getForeignKeys
(
short*& foreign_keys,
short& total_foreign_keys,
std::string& message
)
{
if(!is_foreign_keys_set)
{
DBKeyColumn* table_foreign_keys;
if(!DBGetPrimaryKeys
(
*this,
table_foreign_keys,
total_foreign_key_columns,
message
))
{
return false;
}
foreign_key_columns=new short[total_foreign_key_columns];
for(short i=0;i<total_primary_key_columns;i++)
{
foreign_key_columns[i]=table_foreign_keys[i].key_ordinal;
}
}
total_foreign_keys=total_foreign_key_columns;
foreign_keys=new short[total_foreign_key_columns];
for(short i=0;i<total_foreign_key_columns;i++)
{
foreign_keys[i]=foreign_key_columns[i];
}
is_foreign_keys_set=true;
return true;
}
DBTable DBTable::cloneTable()
{
DBTable table;
table.sql_statement=sql_statement;
table.database_name=database_name;
table.catalog_name=catalog_name;
table.schema_name=schema_name;
table.table_name=table_name;
table.total_columns=total_columns;
table.total_primary_key_columns=total_primary_key_columns;
table.total_rows=total_rows;
table.table_columns=new DBColumn[total_columns];
table.primary_key_columns=new short[total_columns];
for(short i=0;i<total_columns;i++)
{
table.table_columns[i]=DBColumn(table_columns[i]);
table.primary_key_columns[i]=primary_key_columns[i];
}
table.table_columns=table_columns;
table.statement_handle=nullptr;
table.table_data=TableData(table_data);
return table;
}
DBTable DBTable::cloneSchema()
{
DBTable table;
table.sql_statement=sql_statement;
table.database_name=database_name;
table.catalog_name=catalog_name;
table.schema_name=schema_name;
table.table_name=table_name;
table.total_columns=total_columns;
table.total_primary_key_columns=total_primary_key_columns;
table.total_rows=total_rows;
table.table_columns=new DBColumn[total_columns];
table.primary_key_columns=new short[total_columns];
for(short i=0;i<total_columns;i++)
{
table.table_columns[i]=DBColumn(table_columns[i]);
table.primary_key_columns[i]=primary_key_columns[i];
}
table.statement_handle=nullptr;
table.table_data=TableData();
return table;
}
DBTable DBTable::getSubTable
(
const short columns_indices[],
const short& total_sub_columns
)
{
DBColumn* columns;
DBTable table;
UINT n;
CellData value;
columns=new DBColumn[total_sub_columns];
for(short i=0;i<total_sub_columns;i++)
{
columns[i]=table_columns[columns_indices[i]];
}
table=DBTable(total_sub_columns,columns);
for(UINT i=0;i<total_rows;i++)
{
table.addRow(n);
for(short j=0;j<total_sub_columns;j++)
{
getValue(i,columns_indices[j],value);
table.setValue(n,j,value);
}
}
return table;
}
void DBTable::splitPKFKDC
(
DBTable& primary_keys,
DBTable& foreign_keys,
DBTable& data_columns,
bool& has_primary_keys,
bool& has_foreign_keys
)
{
if(!is_primary_keys_set)
{
short* pk_indices;
short total_pk;
std::string message;
getPrimaryKeys(pk_indices,total_pk,message);
}
if(!is_foreign_keys_set)
{
short* fk_indices;
short total_fk;
std::string message;
getForeignKeys(fk_indices,total_fk,message);
}
UINT n;
CellData value;
short* column_iterator;
short* pk_end=primary_key_columns+total_primary_key_columns;
short* fk_end=foreign_key_columns+total_foreign_key_columns;
short pk_count=0;
short fk_count=0;
short dc_count=0;
short total_data_columns=total_columns-total_primary_key_columns
-total_foreign_key_columns;
DBColumn* pk_columns=new DBColumn[total_primary_key_columns];
DBColumn* fk_columns=new DBColumn[total_foreign_key_columns];
DBColumn* dc_columns=new DBColumn[total_data_columns];
TABLE_COLUMN_TYPES column_types[total_columns];
for(short i=0;i<total_columns;i++)
{
column_iterator=std::find
(
primary_key_columns,
pk_end,
i
);
if(column_iterator!=pk_end)
{
column_types[i]=TABLE_COLUMN_TYPES::PRIMARY_KEY;
pk_columns[pk_count]=table_columns[i];
pk_count++;
}
else
{
column_iterator=std::find
(
foreign_key_columns,
fk_end,
i
);
if(column_iterator!=fk_end)
{
column_types[i]=TABLE_COLUMN_TYPES::FOREIGN_KEY;
fk_columns[fk_count]=table_columns[i];
fk_count++;
}
else
{
column_types[i]=TABLE_COLUMN_TYPES::DATA_COLUMN;
dc_columns[dc_count]=table_columns[i];
dc_count++;
}
}
}
if(pk_count>0)
{
primary_keys=DBTable(pk_count,pk_columns);
has_primary_keys=true;
}
else
{
has_primary_keys=false;
}
if(fk_count>0)
{
foreign_keys=DBTable(fk_count,fk_columns);
has_foreign_keys=true;
}
else
{
has_foreign_keys=false;
}
if(dc_count>0)
{
data_columns=DBTable(dc_count,dc_columns);
}
pk_count=0;
fk_count=0;
dc_count=0;
for(short j=0;j<total_columns;j++)
{
switch(column_types[j])
{
case TABLE_COLUMN_TYPES::PRIMARY_KEY:
{
for(UINT i=0;i<total_rows;i++)
{
getValue(i,j,value);
primary_keys.addRow(n);
primary_keys.setValue(n,pk_count,value);
}
pk_count++;
break;
}
case TABLE_COLUMN_TYPES::FOREIGN_KEY:
{
for(UINT i=0;i<total_rows;i++)
{
getValue(i,j,value);
foreign_keys.addRow(n);
foreign_keys.setValue(n,fk_count,value);
}
fk_count++;
break;
}
case TABLE_COLUMN_TYPES::DATA_COLUMN:
{
for(UINT i=0;i<total_rows;i++)
{
getValue(i,j,value);
data_columns.addRow(n);
data_columns.setValue(n,dc_count,value);
}
dc_count++;
break;
}
}
}
}
SQLHSTMT& getStatementHandle(DBTable& table)
{
return table.statement_handle;
}
void setStatementHandle(DBTable& table,const SQLHSTMT handle)
{
table.statement_handle=handle;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//DBDataSet DEFINITIONS
DBDataSet::DBDataSet():
data_connection(),data_tables(),total_data_tables(0)
{
total_data_tables=0;
}
DBDataSet::DBDataSet
(
const std::string& sql_statement,
const std::string& driver,
const std::string& server,
const std::string& user,
const std::string& password
):
data_connection(),data_tables(),total_data_tables(0)
{
DBConnect(data_connection,driver,server,user,password);
}
DBDataSet::~DBDataSet()
{}
std::vector<DBTable>::iterator DBDataSet::begin()
{
return data_tables.begin();
}
std::vector<DBTable>::iterator DBDataSet::end()
{
return data_tables.end();
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//PROCEDURES DEFINITIONS
bool DBConnect
(
DBConnection& connection,
const std::string& driver,
const std::string& server,
const std::string& user,
const std::string& password
)
{
SQLHWND app_handle;
SQLRETURN rcode;
int nstr;
char* msg;
#ifdef __linux__
app_handle=nullptr;
#endif // __linux__
#ifdef __windows__
app_handle=GetDesktopWindow();
#endif // __windows__
//Allocate environment handle
rcode=SQLAllocHandle(SQL_HANDLE_ENV,SQL_NULL_HANDLE,&connection.environment_handle);
if(rcode!=SQL_SUCCESS && rcode!=SQL_SUCCESS_WITH_INFO)
{
connection.environment_handle_allocated=false;
connection.last_message="\n[DBConnect] Error allocating handle in \
SQLAllocHandle!";
return false;
}
connection.environment_handle_allocated=true;
//Set ODBC version environmet attribute
rcode=SQLSetEnvAttr
(
connection.environment_handle,
SQL_ATTR_ODBC_VERSION,
(SQLPOINTER)SQL_OV_ODBC3,
0
);
if(rcode!=SQL_SUCCESS && rcode!=SQL_SUCCESS_WITH_INFO)
{
connection.last_message="\n[DBConnect] Error setting environment attribute in \
SQLSetEnvAttr with SQL_ATTR_ODBC_VERSION attribute!";
return false;
}
//Allocate database connection handle
rcode=SQLAllocHandle
(
SQL_HANDLE_DBC,
connection.environment_handle,
&connection.database_connection_handle
);
if(rcode!=SQL_SUCCESS && rcode!=SQL_SUCCESS_WITH_INFO)
{
connection.connection_handle_allocated=false;
connection.last_message="\n[DBConnect] Error allocating connection handle in \
SQLAllocHandle!";
return false;
}
PSQLCHAR input_connection_string;
SQLSMALLINT input_connection_string_length;//(SQLSMALLINT)(sizeof(inConStr)/sizeof(SQLCHAR));
SQLSMALLINT output_connection_string_buffer_length=1024;//Applications should allocate at least 1,024 characters for this buffer
SQLCHAR output_connection_string[output_connection_string_buffer_length];
SQLSMALLINT output_connection_string_length;
//===========================================================================================================================================================================
//VERY SENSITIVE PART OF THE APPLICATION
//AN EXAMPLE OF CONNECTION STRING THAT WORKS IS "DRIVER={Oracle73 Ver 2.5};UID=DAVALILLOCM;ASY=ON;DBQ=OCCP05;PWD=DAVALILLOCM&PDV;SAVEFILE=CONSTR.dsn;Trusted_Connection=YES;"
//AN EXAMPLE OF FILEDSN THAT WORKS IS "FILEDSN=d:\\Documents and Settings\\davalillocm\\Escritorio\\CONNECTION.dsn;";
nstr=0;
connection.connection_string="DRIVER={DRIVERPAR};UID=UIDPAR;ASY=ON;DBQ=SERVERPAR;\
PWD=PWDPAR;SAVEFILE=CONSTR.dsn;Trusted_Connection=YES;";
//Replace driver parameter
connection.connection_string=
connection.connection_string.replace
(
connection.connection_string.find("DRIVERPAR",nstr),
9,
driver
);
nstr+=driver.length();
//Replace user id parameter
connection.connection_string=
connection.connection_string.replace
(
connection.connection_string.find("UIDPAR",nstr),
6,
user
);
nstr+=user.length();
//Replace server parameter
connection.connection_string=
connection.connection_string.replace
(
connection.connection_string.find("SERVERPAR",nstr),
9,
server
);
nstr+=server.length();
//Replace password parameter
connection.connection_string=
connection.connection_string.replace
(
connection.connection_string.find("PWDPAR",nstr),
6,
password
);
nstr+=password.length();
//===========================================================================================================================================================================
input_connection_string=(PSQLCHAR)connection.connection_string.c_str();
input_connection_string_length=(SQLSMALLINT)connection.connection_string.length();
//(SQLSMALLINT)(sizeof(inConStr)/sizeof(SQLCHAR));
rcode=SQLDriverConnect
(
connection.database_connection_handle,
app_handle,
input_connection_string,
input_connection_string_length,
output_connection_string,
output_connection_string_buffer_length,
&output_connection_string_length,
SQL_DRIVER_NOPROMPT
);//SQL_DRIVER_NOPROMPT
if(rcode != SQL_SUCCESS && rcode != SQL_SUCCESS_WITH_INFO)
{
msg=new char[output_connection_string_length+1];
memcpy
(
msg,
(char*)output_connection_string,
output_connection_string_buffer_length
);
connection.last_message="\n[DBConnect] ";
connection.last_message+=msg;
connection.last_message+=DBGetErrorMsg
(
connection.database_connection_handle,
SQL_HANDLE_DBC
);
connection.flag=(int)input_connection_string_length;//(int)rcode;
delete[] msg;
return false;
}
msg=new char[output_connection_string_length+1];
memcpy(msg,(char*)output_connection_string,output_connection_string_length);
connection.last_message=std::string(msg);
connection.is_connected=true;
connection.is_open=true;
connection.connection_string="";
connection.server_string=server;
connection.user_string=user;
connection.password_string=password;
connection.flag=0;
return true;
}
bool DBDisconnect(DBConnection& connection)
{
if(SQLDisconnect(connection.database_connection_handle)==SQL_SUCCESS)
{
return true;
}
return false;
}
VECSTR DBGetDrivers(DBConnection& connection)
{
SQLRETURN rcode;
SQLCHAR driverName[SQL_MAX_DSN_LENGTH];
SQLSMALLINT driverNameLength;
SQLCHAR driverAttr[1024];
SQLSMALLINT driverAttrLength;
bool odbcsucceed;
int n;
int m;
VECSTR drivers=VECSTR();
odbcsucceed=true;
while(odbcsucceed)
{
rcode=SQLDrivers
(
connection.environment_handle,
SQL_FETCH_NEXT,
driverName,
SQL_MAX_DSN_LENGTH,
&driverNameLength,
driverAttr,
1024,
&driverAttrLength
);
if(rcode!=SQL_SUCCESS && rcode!=SQL_SUCCESS_WITH_INFO)
{
odbcsucceed=false;
}
else
{
n=(int)driverNameLength+1;
m=(int)driverAttrLength+1;
char DN[n];
char DNAttrs[m];
memcpy(DN,(char*)driverName,n);
memcpy(DNAttrs,(char*)driverAttr,m);
drivers.push_back(std::string(DN));
drivers.push_back(std::string(DNAttrs));
}
}
return drivers;
}
VECSTR DBGetDataSources(DBConnection& connection)
{
SQLRETURN rcode;
SQLSMALLINT bufferLengthSN=SQL_MAX_DSN_LENGTH;
SQLCHAR sourceName[bufferLengthSN];
SQLSMALLINT sourceNameLength;
SQLCHAR sourceNameDesc[1024];
SQLSMALLINT sourceNameDescLength;
bool odbcsucceed;
int n;
int m;
VECSTR dataSources=VECSTR();
rcode=SQLDataSources
(
connection.environment_handle,
SQL_FETCH_FIRST,
sourceName,
bufferLengthSN,
&sourceNameLength,
sourceNameDesc,
1024,
&sourceNameDescLength
);
if(rcode!=SQL_SUCCESS && rcode!=SQL_SUCCESS_WITH_INFO)
{
return dataSources;
}
n=(int)sourceNameLength+1;
m=(int)sourceNameDescLength+1;
char SN[n];
char SNDesc[m];
memcpy(SN,(char*)sourceName,n);
memcpy(SNDesc,(char*)sourceNameDesc,m);
dataSources.push_back(std::string(SN));
dataSources.push_back(std::string(SNDesc));
odbcsucceed=true;
while(odbcsucceed)
{
rcode=SQLDataSources
(
connection.environment_handle,
SQL_FETCH_NEXT,
sourceName,
bufferLengthSN,
&sourceNameLength,
sourceNameDesc,
1024,
&sourceNameDescLength
);
if(rcode!=SQL_SUCCESS && rcode!=SQL_SUCCESS_WITH_INFO)
{
odbcsucceed=false;
}
else
{
n=(int)sourceNameLength+1;
m=(int)sourceNameDescLength+1;
char SNI[n];
char SNIDesc[m];
memcpy(SNI,(char*)sourceName,n);
memcpy(SNIDesc,(char*)sourceNameDesc,m);
dataSources.push_back(std::string(SNI));
dataSources.push_back(std::string(SNIDesc));
}
}
return dataSources;
}
bool DBSelect(DBConnection& connection,const std::string& sqlcmd,DBTable& select_table)
{
//Prevents go any further if the connection is closed
if(!connection.is_open)
{
connection.last_message="\n[DBSelect] Connection not established or closed!";
return false;
}
SQLHSTMT statement_handle;
//Prepare the SQL statement
if(!DBPrepareSelect(connection,statement_handle,sqlcmd))
{
return false;
}
SQLRETURN rcode;
SQLSMALLINT stmt_columns=0;
DBColumn* sql_columns=nullptr;
SQLSMALLINT i;
SQLCHAR sql_command_text[MAX_COMMAND_LENGTH];
SQLINTEGER sql_command_length;
//==================================================================
//EXECUTE STATEMENT
rcode=SQLExecDirect
(
statement_handle,
(PSQLCHAR)sqlcmd.c_str(),
(SQLINTEGER)sqlcmd.length()
);
while(rcode==SQL_STILL_EXECUTING)
{
rcode=SQLExecDirect
(
statement_handle,
(PSQLCHAR)sqlcmd.c_str(),
(SQLINTEGER)sqlcmd.length()
);
}
if(rcode==SQL_ERROR && rcode!=SQL_SUCCESS_WITH_INFO)
{
connection.last_message="\n[DBSelect] SQLExecDirect error!";
connection.last_message+=DBGetErrorMsg(statement_handle,SQL_HANDLE_STMT);
return false;
}
else if(rcode==SQL_NEED_DATA)
{
connection.last_message="\n[DBSelect] SQLExecDirect execution requires \
data!";
connection.last_message+=DBGetErrorMsg(statement_handle,SQL_HANDLE_STMT);
return false;
}
//cout << "SQLExecDirect execution succeed!" << endl;
//==================================================================
//==================================================================
//SHOW EXECUTED SQL COMMAND
rcode=SQLNativeSql
(
connection.database_connection_handle,
(PSQLCHAR)sqlcmd.c_str(),
(SQLINTEGER)sqlcmd.length(),
sql_command_text,
MAX_COMMAND_LENGTH,
&sql_command_length
);
if(rcode==SQL_SUCCESS || rcode==SQL_SUCCESS_WITH_INFO)
{
std::string sended_command;
sended_command=std::string((size_t)sql_command_length,'\0');
std::copy
(
sql_command_text,
sql_command_text+sql_command_length,
sended_command.begin()
);
//cout << "\n \n Command executed \n \n " << endl;
//cout << sended_command << " \n \n " << endl;
}
else
{
connection.last_message="\n[DBSelect] SQLNativeSql error requesting sent \
statement!";
connection.last_message+=DBGetErrorMsg(statement_handle,SQL_HANDLE_STMT);
return false;
}
//==================================================================
//==================================================================
//GET NUMBER OF COLUMNS
//After be prepared the total number of columns must be retrieved
//but before the statement execution is performed
rcode=SQLNumResultCols(statement_handle,&stmt_columns);
if(rcode!=SQL_SUCCESS && rcode!=SQL_SUCCESS_WITH_INFO)
{
connection.last_message="\n[DBSelect] SQLNumResultCols error getting the \
total number of columns!";
connection.last_message+=DBGetErrorMsg(statement_handle,SQL_HANDLE_STMT);
return false;
}
//==================================================================
//==================================================================
//CREATE COLUMNS AND BIND THEM
if(!DBGetColumnsAndBind(connection,statement_handle,stmt_columns,sql_columns))
{
return false;
}
select_table=DBTable(stmt_columns,sql_columns);
//==================================================================
//==================================================================
//FETCH VALUES
select_table.total_rows=0;
UINT row_index;
//Call SQLFetch function
rcode=SQL_SUCCESS;
while(rcode==SQL_SUCCESS)
{
DBSELECT_FETCH:
rcode=SQLFetch(statement_handle);
if(rcode==SQL_STILL_EXECUTING)
{
goto DBSELECT_FETCH;
}
if(rcode==SQL_SUCCESS || rcode==SQL_SUCCESS_WITH_INFO)
{
select_table.addRow(row_index);//Add an empty row
for(i=0;i<stmt_columns;i++)
{
CellData value;
if(sql_columns[i].data_length_indicator==SQL_NULL_DATA)
{
value.buffer=nullptr;
value.buffer_size=0;
//cout << "row field is NULL " << endl;
}
else
{
value.buffer=new SQLCHAR[sql_columns[i].data_length_indicator];
value.buffer_size=sql_columns[i].data_length_indicator;
memcpy
(
value.buffer,
sql_columns[i].column_buffer,
sql_columns[i].data_length_indicator
);
}
select_table.setValue(row_index,i,value);
}
if(rcode==SQL_SUCCESS_WITH_INFO)
{
//Show state
connection.last_message+="\n Row state ";
connection.last_message+=DBGetErrorMsg(statement_handle,SQL_HANDLE_STMT);
//cout << connection.last_message << endl;
}
}
}
switch(rcode)
{
case SQL_SUCCESS_WITH_INFO:
{
//Show state
connection.last_message+="\n";
connection.last_message+=DBGetErrorMsg(statement_handle,SQL_HANDLE_STMT);
//cout << connection.last_message << endl;
break;
}
case SQL_NO_DATA:
{
//Show state
connection.last_message+="\n[DBSelect] All rows fetched!";
//cout << connection.last_message << endl;
break;
}
case SQL_ERROR:
{
//Show error
connection.last_message+="\n[DBSelect] Error in SQLFetch ";
connection.last_message+=DBGetErrorMsg(statement_handle,SQL_HANDLE_STMT);
//cout << "Error setting cursor's position!" << endl;
return false;
}
case SQL_INVALID_HANDLE:
{
connection.last_message+="\n[DBSelect] Invalid statement handle!";
//cout << "Invalid statement handle!" << endl;
return false;
}
default:
{
break;
}
}
//==================================================================
//cout << "Total rows " << select_table.total_rows << endl;
setStatementHandle(select_table,statement_handle);
//==================================================================
//TO SET TABLE NAME, CATALOG NAME AND SCHEMA NAME
select_table.catalog_name=std::string
(
(char*)select_table.table_columns[0].catalog_name
);
select_table.schema_name=std::string
(
(char*)select_table.table_columns[0].schema_name
);
select_table.table_name=std::string
(
(char*)select_table.table_columns[0].table_name
);
//==================================================================
//Close the cursor
rcode=SQLCloseCursor(statement_handle);
if(rcode!=SQL_SUCCESS && rcode!=SQL_SUCCESS_WITH_INFO)
{
connection.last_message="\n[DBSelect] SQLCloseCursor error closing cursor!";
connection.last_message+=DBGetErrorMsg(statement_handle,SQL_HANDLE_STMT);
return false;
}
rcode=SQLFreeStmt(statement_handle,SQL_RESET_PARAMS);
if(rcode!=SQL_SUCCESS && rcode!=SQL_SUCCESS_WITH_INFO)
{
connection.last_message="\n[DBSelect] SQLFreeStmt error resetting parameters!";
connection.last_message+=DBGetErrorMsg(statement_handle,SQL_HANDLE_STMT);
return false;
}
return true;
}
bool DBInsert
(
DBConnection& connection,
const std::string& sqlcmd,
const DBTable& rows_to_insert,
DBTable& rows_rejected
)
{
//Prevents go any further if the connection is closed
if(!connection.is_open)
{
connection.last_message="\n[DBInsert] Connection not established or closed!";
return false;
}
SQLRETURN rcode;
SQLHSTMT statement_handle;
DBColumn* sql_columns=new DBColumn[rows_to_insert.total_columns];
for(short i=0;i<rows_to_insert.total_columns;i++)
{
sql_columns[i]=rows_to_insert.table_columns[i];
}
//Prepare the SQL statement
if(!DBPrepareInsert(connection,statement_handle,sqlcmd))
{
return false;
}
if(!DBBindInsertParameters
(
connection,
statement_handle,
rows_to_insert.total_columns,
sql_columns
))
{
return false;
}
//cout << "SQL parameters bounded!" << endl;
//Prepare SQl command
rcode=SQLPrepare
(
statement_handle,
(PSQLCHAR)sqlcmd.c_str(),
(SQLINTEGER)strlen(sqlcmd.c_str())
);
if(rcode!=SQL_SUCCESS && rcode!=SQL_SUCCESS_WITH_INFO)
{
connection.sql_command_prepared=false;
connection.last_message="\n[DBInsert] Can't prepare SQL statement!";
connection.last_message+=DBGetErrorMsg(statement_handle,SQL_HANDLE_STMT);
return false;
}
connection.sql_command_prepared=true;
//cout << "SQL Insert prepared!" << endl;
rows_rejected=DBTable(rows_to_insert.total_columns,rows_to_insert.table_columns);
for(UINT i=0;i<rows_to_insert.total_rows;i++)
{
//Set data to bounded buffer
for(short j=0;j<rows_to_insert.total_columns;j++)
{
CellData value;
rows_to_insert.getValue(i,j,value);
if(!value.buffer)
{
sql_columns[j].column_buffer_length=0;
sql_columns[j].data_length_indicator=SQL_NULL_DATA;
}
else
{
memcpy(sql_columns[j].column_buffer,value.buffer,value.buffer_size);
sql_columns[j].data_length_indicator=value.buffer_size;
}
}
rcode=SQLExecute(statement_handle);
if(rcode != SQL_SUCCESS && rcode != SQL_SUCCESS_WITH_INFO)
{
DBRow rejected;
rejected=rows_to_insert.getRow(i);
rows_rejected.addRow(rejected);
//cout << "Row " << i << " rejected" << endl;
//cout << DBGetErrorMsg(statement_handle,SQL_HANDLE_STMT) << endl;
}
}
rcode=SQLFreeStmt(statement_handle,SQL_RESET_PARAMS);
if(rcode!=SQL_SUCCESS && rcode!=SQL_SUCCESS_WITH_INFO)
{
connection.last_message="\n[DBInsert] SQLFreeStmt error resetting parameters!";
connection.last_message+=DBGetErrorMsg(statement_handle,SQL_HANDLE_STMT);
return false;
}
return true;
}
bool DBUpdate
(
DBConnection& connection,
const std::string& sqlcmd,
const DBTable& rows_to_update,
const DBTable& primary_keys_values,
DBTable& rows_rejected
)
{
//Prevents go any further if the connection is closed
if(!connection.is_open)
{
connection.last_message="\n[DBUpdate] Connection not established or closed!";
return false;
}
SQLRETURN rcode;
SQLHSTMT statement_handle;
DBColumn* sql_columns=new DBColumn[rows_to_update.total_columns];
DBColumn* pk_columns=new DBColumn[primary_keys_values.total_columns];
CellData value;
for(short i=0;i<rows_to_update.total_columns;i++)
{
sql_columns[i]=rows_to_update.table_columns[i];
}
for(short i=0;i<primary_keys_values.total_columns;i++)
{
pk_columns[i]=primary_keys_values.table_columns[i];
}
//Prepare the SQL statement
if(!DBPrepareUpdate(connection,statement_handle,sqlcmd))
{
return false;
}
if(!DBBindUpdateParameters
(
connection,
statement_handle,
rows_to_update.total_columns,
primary_keys_values.total_columns,
sql_columns,
pk_columns
))
{
return false;
}
//cout << "SQL parameters bounded!" << endl;
//Prepare SQl command
rcode=SQLPrepare
(
statement_handle,
(PSQLCHAR)sqlcmd.c_str(),
(SQLINTEGER)strlen(sqlcmd.c_str())
);
if(rcode!=SQL_SUCCESS && rcode!=SQL_SUCCESS_WITH_INFO)
{
connection.sql_command_prepared=false;
connection.last_message="\n[DBUpdate] Can't prepare SQL statement!";
connection.last_message+="";
connection.last_message+=DBGetErrorMsg(statement_handle,SQL_HANDLE_STMT);
return false;
}
connection.sql_command_prepared=true;
//cout << "SQL Update prepared!" << endl;
rows_rejected=DBTable(rows_to_update.total_columns,rows_to_update.table_columns);
for(UINT i=0;i<rows_to_update.total_rows;i++)
{
//Set data to bounded buffer
for(short j=0;j<rows_to_update.total_columns;j++)
{
rows_to_update.getValue(i,j,value);
if(!value.buffer)
{
sql_columns[j].column_buffer_length=0;
sql_columns[j].data_length_indicator=SQL_NULL_DATA;
}
else
{
sql_columns[j].column_buffer_length=value.buffer_size;
sql_columns[j].data_length_indicator=value.buffer_size;
memcpy(sql_columns[j].column_buffer,value.buffer,value.buffer_size);
}
}
for(short j=0;j<primary_keys_values.total_columns;j++)
{
primary_keys_values.getValue(i,j,value);
pk_columns[j].column_buffer_length=value.buffer_size;
pk_columns[j].data_length_indicator=value.buffer_size;
memcpy(pk_columns[j].column_buffer,value.buffer,value.buffer_size);
}
rcode=SQLExecute(statement_handle);
if(rcode != SQL_SUCCESS && rcode != SQL_SUCCESS_WITH_INFO)
{
DBRow rejected;
rejected=rows_to_update.getRow(i);
rows_rejected.addRow(rejected);
//cout << "Row " << i << " rejected" << endl;
//cout << DBGetErrorMsg(statement_handle,SQL_HANDLE_STMT) << endl;
}
}
return true;
}
bool DBDelete
(
DBConnection& connection,
const std::string& sqlcmd,
const DBTable& primary_keys_values,
DBTable& rows_rejected
)
{
//Prevents go any further if the connection is closed
if(!connection.is_open)
{
connection.last_message="\n[DBDelete] Connection not established or closed!";
return false;
}
SQLRETURN rcode;
SQLHSTMT statement_handle;
DBColumn* pk_columns=new DBColumn[primary_keys_values.total_columns];
CellData value;
for(short i=0;i<primary_keys_values.total_columns;i++)
{
pk_columns[i]=primary_keys_values.table_columns[i];
}
//Prepare the SQL statement
if(!DBPrepareDelete(connection,statement_handle,sqlcmd))
{
return false;
}
if(!DBBindDeleteParameters
(
connection,
statement_handle,
primary_keys_values.total_columns,
pk_columns
))
{
return false;
}
//cout << "SQL parameters bounded!" << endl;
//Prepare SQl command
rcode=SQLPrepare
(
statement_handle,
(PSQLCHAR)sqlcmd.c_str(),
(SQLINTEGER)strlen(sqlcmd.c_str())
);
if(rcode!=SQL_SUCCESS && rcode!=SQL_SUCCESS_WITH_INFO)
{
connection.sql_command_prepared=false;
connection.last_message="\n[DBDelete] Can't prepare SQL statement!";
connection.last_message+="";
connection.last_message+=DBGetErrorMsg(statement_handle,SQL_HANDLE_STMT);
return false;
}
connection.sql_command_prepared=true;
//cout << "SQL Delete prepared!" << endl;
rows_rejected=DBTable
(
primary_keys_values.total_columns,
primary_keys_values.table_columns
);
for(UINT i=0;i<primary_keys_values.total_rows;i++)
{
for(short j=0;j<primary_keys_values.total_columns;j++)
{
primary_keys_values.getValue(i,j,value);
pk_columns[j].column_buffer_length=value.buffer_size;
pk_columns[j].data_length_indicator=value.buffer_size;
memcpy(pk_columns[j].column_buffer,value.buffer,value.buffer_size);
}
rcode=SQLExecute(statement_handle);
if(rcode != SQL_SUCCESS && rcode != SQL_SUCCESS_WITH_INFO)
{
DBRow rejected;
rejected=primary_keys_values.getRow(i);
rows_rejected.addRow(rejected);
//cout << "Row " << i << " rejected" << endl;
//cout << DBGetErrorMsg(statement_handle,SQL_HANDLE_STMT) << endl;
}
}
return true;
}
bool DBGetPrimaryKeys
(
DBTable& table,
DBKeyColumn*& primary_keys,
short& total_primary_keys,
std::string& message
)
{
SQLRETURN rcode;
HSTMT handle=getStatementHandle(table);
PSQLCHAR table_catalog_name=(PSQLCHAR)table.catalog_name.c_str();
PSQLCHAR table_schema_name=(PSQLCHAR)table.schema_name.c_str();
PSQLCHAR table_name=(PSQLCHAR)table.table_name.c_str();
SQLSMALLINT table_catalog_name_length=(SQLSMALLINT)table.catalog_name.size();
SQLSMALLINT table_schema_name_length=(SQLSMALLINT)table.schema_name.size();
SQLSMALLINT table_name_length=(SQLSMALLINT)table.table_name.size();
SQLSMALLINT key_ordinal;
SQLSMALLINT k;
std::vector<DBKeyColumn> table_primary_keys;
SQLBindCol(handle,6,SQL_C_SSHORT,(SQLPOINTER)&key_ordinal,sizeof(SQLSMALLINT),NULL);
rcode=SQLPrimaryKeys
(
handle,
table_catalog_name,
table_catalog_name_length,
table_schema_name,
table_schema_name_length,
table_name,
table_name_length
);
while(rcode==SQL_STILL_EXECUTING)
{
rcode=SQLPrimaryKeys
(
handle,
table_catalog_name,
table_catalog_name_length,
table_schema_name,
table_schema_name_length,
table_name,
table_name_length
);
}
if(rcode==SQL_ERROR)
{
message="\n[DBGetPrimaryKeys] Error executing SQLPrimaryKeys!\n";
message+=DBGetErrorMsg(handle,SQL_HANDLE_STMT);
return false;
}
while(rcode==SQL_SUCCESS || rcode==SQL_SUCCESS_WITH_INFO)
{
rcode=SQLFetch(handle);
while(rcode==SQL_STILL_EXECUTING)
{
rcode=SQLFetch(handle);
}
if(rcode==SQL_SUCCESS || rcode==SQL_SUCCESS_WITH_INFO)
{
DBKeyColumn key;
memcpy
(
key.key_catalog_name,
table_catalog_name,
table_catalog_name_length
);
memcpy
(
key.key_schema_name,
table_schema_name,
table_schema_name_length
);
memcpy
(
key.key_table_name,
table_name,
table_name_length
);
k=key_ordinal;
memcpy
(
key.key_column_name,
table.table_columns[k].column_name,
table.table_columns[k].column_name_length
);
key.key_ordinal=key_ordinal;
key.key_catalog_name_length=table_catalog_name_length;
key.key_schema_name_length=table_schema_name_length;
key.key_table_name_length=table_name_length;
key.key_column_name_length=table.table_columns[k].column_name_length;
key.key_name_length=0;
table_primary_keys.push_back(key);
}
}
primary_keys=new DBKeyColumn[table_primary_keys.size()];
for(size_t i=0;i<table_primary_keys.size();i++)
{
primary_keys[i]=table_primary_keys[i];
}
total_primary_keys=(short)table_primary_keys.size();
rcode=SQLFreeStmt(handle,SQL_RESET_PARAMS);
if(rcode!=SQL_SUCCESS && rcode!=SQL_SUCCESS_WITH_INFO)
{
message="\n[DBGetPrimaryKeys] SQLFreeStmt error resetting parameters!";
message+=DBGetErrorMsg(handle,SQL_HANDLE_STMT);
return false;
}
return true;
}
bool DBGetForeignKeys
(
DBTable& table,
DBKeyColumn*& foreign_keys,
short& total_foreign_keys,
std::string& message
)
{
SQLRETURN rcode;
HSTMT handle=getStatementHandle(table);
PSQLCHAR table_catalog_name=(PSQLCHAR)table.catalog_name.c_str();
PSQLCHAR table_schema_name=(PSQLCHAR)table.schema_name.c_str();
PSQLCHAR table_name=(PSQLCHAR)table.table_name.c_str();
SQLSMALLINT table_catalog_name_length=(SQLSMALLINT)table.catalog_name.size();
SQLSMALLINT table_schema_name_length=(SQLSMALLINT)table.schema_name.size();
SQLSMALLINT table_name_length=(SQLSMALLINT)table.table_name.size();
SQLSMALLINT key_ordinal;
SQLSMALLINT k;
std::vector<DBKeyColumn> table_foreign_keys;
SQLBindCol(handle,6,SQL_C_SSHORT,(SQLPOINTER)&key_ordinal,sizeof(SQLSMALLINT),NULL);
rcode=SQLForeignKeys
(
handle,
NULL,
0,
NULL,
0,
NULL,
0,
table_catalog_name,
table_catalog_name_length,
table_schema_name,
table_schema_name_length,
table_name,
table_name_length
);
while(rcode==SQL_STILL_EXECUTING)
{
rcode=SQLForeignKeys
(
handle,
NULL,
0,
NULL,
0,
NULL,
0,
table_catalog_name,
table_catalog_name_length,
table_schema_name,
table_schema_name_length,
table_name,
table_name_length
);
}
if(rcode==SQL_ERROR)
{
message="\n[DBGetPrimaryKeys] Error executing SQLPrimaryKeys!\n";
message+=DBGetErrorMsg(handle,SQL_HANDLE_STMT);
return false;
}
while(rcode==SQL_SUCCESS || rcode==SQL_SUCCESS_WITH_INFO)
{
rcode=SQLFetch(handle);
while(rcode==SQL_STILL_EXECUTING)
{
rcode=SQLFetch(handle);
}
if(rcode==SQL_SUCCESS || rcode==SQL_SUCCESS_WITH_INFO)
{
DBKeyColumn key;
memcpy
(
key.key_catalog_name,
table_catalog_name,
table_catalog_name_length
);
memcpy
(
key.key_schema_name,
table_schema_name,
table_schema_name_length
);
memcpy
(
key.key_table_name,
table_name,
table_name_length
);
k=key_ordinal;
memcpy
(
key.key_column_name,
table.table_columns[k].column_name,
table.table_columns[k].column_name_length
);
key.key_ordinal=key_ordinal;
key.key_catalog_name_length=table_catalog_name_length;
key.key_schema_name_length=table_schema_name_length;
key.key_table_name_length=table_name_length;
key.key_column_name_length=table.table_columns[k].column_name_length;
key.key_name_length=0;
table_foreign_keys.push_back(key);
}
}
foreign_keys=new DBKeyColumn[table_foreign_keys.size()];
for(size_t i=0;i<table_foreign_keys.size();i++)
{
foreign_keys[i]=table_foreign_keys[i];
}
total_foreign_keys=(short)table_foreign_keys.size();
rcode=SQLFreeStmt(handle,SQL_RESET_PARAMS);
if(rcode!=SQL_SUCCESS && rcode!=SQL_SUCCESS_WITH_INFO)
{
message="\n[DBGetForeignKeys] SQLFreeStmt error resetting parameters!";
message+=DBGetErrorMsg(handle,SQL_HANDLE_STMT);
return false;
}
return true;
}
short DBGetNumberOfColumns(SQLHSTMT& statement_handle)
{
SQLRETURN rcode;
SQLSMALLINT total_columns;
rcode=SQLNumResultCols(statement_handle,&total_columns);
if(rcode!=SQL_SUCCESS && rcode!=SQL_SUCCESS_WITH_INFO)
{
return -1;
}
return (short)total_columns;
}
UINT DBGetNumberOfRows(SQLHSTMT& statement_handle)
{
SQLRETURN rcode;
SQLLEN total_rows;
rcode=SQLRowCount(statement_handle,&total_rows);
if(rcode!=SQL_SUCCESS && rcode!=SQL_SUCCESS_WITH_INFO)
{
return -1;
}
return (UINT)total_rows;
}
std::string DBGetErrorMsg(SQLHANDLE handle,SQLSMALLINT handle_type)
{
std::string msg="";
std::string error_message;
std::string error_message_code;
SQLSMALLINT total_messages=1;
SQLRETURN rcode;
SQLCHAR sql_state[6];
SQLCHAR sql_error_message[SQL_MAX_MESSAGE_LENGTH];
SQLINTEGER sql_native_error;
SQLSMALLINT sql_error_message_length;
SQLSMALLINT handle_type_enum;
switch(handle_type)
{
case SQL_HANDLE_DBC:
{
handle_type_enum=SQL_HANDLE_DBC;
break;
}
case SQL_HANDLE_DESC:
{
handle_type_enum=SQL_HANDLE_DESC;
break;
}
case SQL_HANDLE_ENV:
{
handle_type_enum=SQL_HANDLE_ENV;
break;
}
case SQL_HANDLE_STMT:
{
handle_type_enum=SQL_HANDLE_STMT;
break;
}
default:
break;
}
while(true)
{
rcode = SQLGetDiagRec
(
handle_type_enum,
handle,
total_messages,
sql_state,
&sql_native_error,
sql_error_message,
SQL_MAX_MESSAGE_LENGTH,
&sql_error_message_length
);
if(rcode==SQL_SUCCESS)
{
error_message=std::string((size_t)sql_error_message_length,'\0');
std::copy
(
sql_error_message,
sql_error_message+sql_error_message_length,
error_message.begin()
);
error_message_code="\n["+std::string((char*)sql_state)+"]";
msg+=error_message_code+error_message+"";
total_messages++;
if(total_messages>MAX_ERROR_MESSAGES)
{
break;
}
}
else
{
break;
}
}
if(!(msg.compare("")==0))
{
msg+="";
}
return msg;
}
std::string GetSQLTypeName(const short sql_type_id,bool& is_type_variable)
{
std::string type_name;
is_type_variable=false;
switch(sql_type_id)
{
case SQL_BIT:
{
type_name="SQL_BIT";
break;
}
case SQL_CHAR:
{
type_name="SQL_CHAR";
break;
}
case SQL_VARCHAR:
{
type_name="SQL_VARCHAR";
break;
}
case SQL_LONGVARCHAR:
{
type_name="SQL_LONGVARCHAR";
break;
}
case SQL_WCHAR:
{
type_name="SQL_WCHAR";
is_type_variable=true;
break;
}
case SQL_WVARCHAR:
{
type_name="SQL_WVARCHAR";
is_type_variable=true;
break;
}
case SQL_WLONGVARCHAR:
{
type_name="SQL_WLONGVARCHAR";
is_type_variable=true;
break;
}
case SQL_TINYINT:
{
type_name="SQL_TINYINT";
break;
}
case SQL_SMALLINT:
{
type_name="SQL_SMALLINT";
break;
}
case SQL_INTEGER:
{
type_name="SQL_INTEGER";
break;
}
case SQL_BIGINT:
{
type_name="SQL_BIGINT";
break;
}
case SQL_DECIMAL:
{
type_name="SQL_DECIMAL";
break;
}
case SQL_NUMERIC:
{
type_name="SQL_NUMERIC";
break;
}
case SQL_REAL:
{
type_name="SQL_REAL";
break;
}
case SQL_FLOAT:
{
type_name="SQL_FLOAT";
break;
}
case SQL_DOUBLE:
{
type_name="SQL_DOUBLE";
break;
}
case SQL_DATE:
{
type_name="SQL_DATE";
break;
}
case SQL_TIME:
{
type_name="SQL_TIME";
break;
}
case SQL_TIMESTAMP:
{
type_name="SQL_TIMESTAMP";
break;
}
case SQL_BINARY:
{
type_name="SQL_BINARY";
is_type_variable=true;
break;
}
case SQL_VARBINARY:
{
type_name="SQL_VARBINARY";
is_type_variable=true;
break;
}
case SQL_LONGVARBINARY:
{
type_name="SQL_LONGVARBINARY";
is_type_variable=true;
break;
}
default:
{
type_name="SQL_INTEGER";
break;
}
}
return type_name;
}
//==========================================================================================
//METHODS FOR INTEROPERABILITY WITH EXCEL LIBREOFFICE MACRO
bool DBGetColumnsAndBind
(
DBConnection& connection,
SQLHSTMT& statement_handle,
const short& total_columns,
DBColumn*& columns
)
{
SQLRETURN rcode;
SQLSMALLINT type_enum;
short i,j;
long column_type;
long column_length;
columns=new DBColumn[total_columns];
for(i=0;i<total_columns;i++)
{
j=i+1;
//some drivers may only write the lower 32-bit or 16-bit of a buffer and leave
//the higher-order bit unchanged. Therefore, applications should initialize the
//value to 0 before calling SQLColAttribute
column_type=0;
column_length=0;
//Get the column's type
rcode=SQLColAttribute
(
statement_handle,
j,
SQL_DESC_CONCISE_TYPE,
NULL,
0,
NULL,
&column_type
);
if(rcode!=SQL_SUCCESS)
{
//Show state
connection.last_message+="\n[DBGetColumnsAndBind] SQLColAttribute error!";
connection.last_message+=DBGetErrorMsg(statement_handle,SQL_HANDLE_STMT);
//cout << connection.last_message << endl;
return false;
}
columns[i].column_type=(short)(column_type);
//Get the column's byte length
rcode=SQLColAttribute
(
statement_handle,
j,
SQL_COLUMN_LENGTH,
NULL,
0,
NULL,
&column_length
);
if(rcode!=SQL_SUCCESS)
{
//Show state
connection.last_message+="\n[DBGetColumnsAndBind] SQLColAttribute error!";
connection.last_message+=DBGetErrorMsg(statement_handle,SQL_HANDLE_STMT);
//cout << connection.last_message << endl;
return false;
}
columns[i].column_buffer_length=column_length;
//Get column's name
rcode=SQLColAttribute
(
statement_handle,
j,
SQL_DESC_NAME,
columns[i].column_name,
SQL_MAX_COLUMN_NAME_LEN,
&columns[i].column_name_length,
NULL
);
if(rcode!=SQL_SUCCESS)
{
//Show state
connection.last_message+="\n[DBGetColumnsAndBind] SQLColAttribute error!";
connection.last_message+=DBGetErrorMsg(statement_handle,SQL_HANDLE_STMT);
//cout << connection.last_message << endl;
return false;
}
//Get table name that contains the column
rcode=SQLColAttribute
(
statement_handle,
j,
SQL_COLUMN_TABLE_NAME,
columns[i].table_name,
SQL_MAX_TABLE_NAME_LEN,
&columns[i].table_name_length,
NULL
);
if(rcode!=SQL_SUCCESS)
{
//Show state
connection.last_message+="\n[DBGetColumnsAndBind] SQLColAttribute error!";
connection.last_message+=DBGetErrorMsg(statement_handle,SQL_HANDLE_STMT);
//cout << connection.last_message << endl;
return false;
}
//Get column's type name
rcode=SQLColAttribute
(
statement_handle,
j,
SQL_DESC_TYPE_NAME,
columns[i].column_type_name,
MAX_COL_TYPE_NAME_LENGTH,
&columns[i].column_type_name_length,
NULL
);
if(rcode!=SQL_SUCCESS)
{
//Show state
connection.last_message+="\n[DBGetColumnsAndBind] SQLColAttribute error!";
connection.last_message+=DBGetErrorMsg(statement_handle,SQL_HANDLE_STMT);
//cout << connection.last_message << endl;
return false;
}
//Get column's catalog name
rcode=SQLColAttribute
(
statement_handle,
j,
SQL_DESC_CATALOG_NAME,
columns[i].catalog_name,
SQL_MAX_CATALOG_NAME_LEN,
&columns[i].catalog_name_length,
NULL
);
if(rcode!=SQL_SUCCESS)
{
//Show state
connection.last_message+="\n[DBGetColumnsAndBind] SQLColAttribute error!";
connection.last_message+=DBGetErrorMsg(statement_handle,SQL_HANDLE_STMT);
//cout << connection.last_message << endl;
return false;
}
//Get column's schema name
rcode=SQLColAttribute
(
statement_handle,
j,
SQL_DESC_SCHEMA_NAME,
columns[i].schema_name,
SQL_MAX_SCHEMA_NAME_LEN,
&columns[i].schema_name_length,
NULL
);
if(rcode!=SQL_SUCCESS)
{
//Show state
connection.last_message+="\n[DBGetColumnsAndBind] SQLColAttribute error!";
connection.last_message+=DBGetErrorMsg(statement_handle,SQL_HANDLE_STMT);
//cout << connection.last_message << endl;
return false;
}
columns[i].column_buffer=new SQLCHAR[column_length];
switch(columns[i].column_type)
{
case SQL_BIT:
{
break;
}
case SQL_CHAR:
{
type_enum=SQL_C_CHAR;
break;
}
case SQL_VARCHAR:
{
type_enum=SQL_C_CHAR;
break;
}
case SQL_LONGVARCHAR:
{
break;
}
case SQL_WCHAR:
{
break;
}
case SQL_WVARCHAR:
{
break;
}
case SQL_WLONGVARCHAR:
{
break;
}
case SQL_TINYINT:
{
type_enum=SQL_C_TINYINT;
break;
}
case SQL_SMALLINT:
{
type_enum=SQL_C_SHORT;
break;
}
case SQL_INTEGER:
{
type_enum=SQL_C_LONG;
break;
}
case SQL_BIGINT:
{
type_enum=SQL_C_SBIGINT;
break;
}
case SQL_DECIMAL:
{
break;
}
case SQL_NUMERIC:
{
break;
}
case SQL_REAL:
{
break;
}
case SQL_FLOAT:
{
type_enum=SQL_C_FLOAT;
break;
}
case SQL_DOUBLE:
{
type_enum=SQL_C_DOUBLE;
break;
}
case SQL_DATE:
{
break;
}
case SQL_TIME:
{
break;
}
case SQL_TYPE_TIMESTAMP:
{
type_enum=SQL_C_TYPE_TIMESTAMP;
break;
}
case SQL_BINARY:
{
break;
}
case SQL_VARBINARY:
{
break;
}
case SQL_LONGVARBINARY:
{
break;
}
default:
{
break;
}
}
rcode=SQLBindCol
(
statement_handle,
j,
type_enum,
columns[i].column_buffer,
columns[i].column_buffer_length,
&columns[i].data_length_indicator
);
if(rcode!=SQL_SUCCESS)
{
//Show state
connection.last_message+="\n[DBGetColumnsAndBind] SQLBindCol error!";
connection.last_message+=DBGetErrorMsg(statement_handle,SQL_HANDLE_STMT);
return false;
}
}
return true;
}
bool DBBindInsertParameters
(
DBConnection& connection,
SQLHSTMT& statement_handle,
const short& total_columns,
DBColumn*& columns
)
{
SQLRETURN rcode;
SQLSMALLINT type_enum;
SQLSMALLINT format_size=0;
short i,j;
for(i=0;i<total_columns;i++)
{
j=i+1;
switch(columns[i].column_type)
{
case SQL_BIT:
{
break;
}
case SQL_CHAR:
{
type_enum=SQL_C_CHAR;
columns[i].data_length_indicator=sizeof(char);
break;
}
case SQL_VARCHAR:
{
type_enum=SQL_C_CHAR;
columns[i].data_length_indicator=SQL_NTS;
break;
}
case SQL_LONGVARCHAR:
{
break;
}
case SQL_WCHAR:
{
break;
}
case SQL_WVARCHAR:
{
break;
}
case SQL_WLONGVARCHAR:
{
break;
}
case SQL_TINYINT:
{
type_enum=SQL_C_TINYINT;
columns[i].data_length_indicator=sizeof(unsigned char);
break;
}
case SQL_SMALLINT:
{
type_enum=SQL_C_SHORT;
columns[i].data_length_indicator=sizeof(short);
break;
}
case SQL_INTEGER:
{
type_enum=SQL_C_LONG;
columns[i].data_length_indicator=sizeof(int);
break;
}
case SQL_BIGINT:
{
type_enum=SQL_C_SBIGINT;
columns[i].data_length_indicator=sizeof(long);
break;
}
case SQL_DECIMAL:
{
break;
}
case SQL_NUMERIC:
{
break;
}
case SQL_REAL:
{
break;
}
case SQL_FLOAT:
{
type_enum=SQL_C_FLOAT;
format_size=9;
columns[i].data_length_indicator=sizeof(float);
break;
}
case SQL_DOUBLE:
{
type_enum=SQL_C_DOUBLE;
columns[i].data_length_indicator=sizeof(double);
format_size=16;
break;
}
case SQL_DATE:
{
break;
}
case SQL_TIME:
{
break;
}
case SQL_TYPE_TIMESTAMP:
{
type_enum=SQL_C_TYPE_TIMESTAMP;
format_size=4;
columns[i].data_length_indicator=sizeof(SQL_TIMESTAMP_STRUCT);
break;
}
case SQL_BINARY:
{
break;
}
case SQL_VARBINARY:
{
break;
}
case SQL_LONGVARBINARY:
{
break;
}
default:
{
break;
}
}
rcode = SQLBindParameter
(
statement_handle,
j,
SQL_PARAM_INPUT,
type_enum,
columns[i].column_type,
columns[i].column_buffer_length,
format_size,
columns[i].column_buffer,
columns[i].column_buffer_length,
&columns[i].data_length_indicator
);
if(rcode!=SQL_SUCCESS)
{
//Show state
connection.last_message+="\n[DBBindInsertParameters] ";
connection.last_message+=DBGetErrorMsg(statement_handle,SQL_HANDLE_STMT);
//cout << connection.last_message << endl;
return false;
}
}
return true;
}
bool DBBindUpdateParameters
(
DBConnection& connection,
SQLHSTMT& statement_handle,
const short& total_data_columns,
const short& total_primary_keys,
DBColumn*& data_columns,
DBColumn*& primary_keys
)
{
SQLRETURN rcode;
SQLSMALLINT type_enum;
SQLSMALLINT format_size=0;
short i;
short parameter_count=0;
for(i=0;i<total_data_columns;i++)
{
parameter_count++;
switch(data_columns[i].column_type)
{
case SQL_BIT:
{
break;
}
case SQL_CHAR:
{
type_enum=SQL_C_CHAR;
data_columns[i].data_length_indicator=sizeof(char);
break;
}
case SQL_VARCHAR:
{
type_enum=SQL_C_CHAR;
data_columns[i].data_length_indicator=SQL_NTS;
break;
}
case SQL_LONGVARCHAR:
{
break;
}
case SQL_WCHAR:
{
break;
}
case SQL_WVARCHAR:
{
break;
}
case SQL_WLONGVARCHAR:
{
break;
}
case SQL_TINYINT:
{
type_enum=SQL_C_TINYINT;
data_columns[i].data_length_indicator=sizeof(unsigned char);
break;
}
case SQL_SMALLINT:
{
type_enum=SQL_C_SHORT;
data_columns[i].data_length_indicator=sizeof(short);
break;
}
case SQL_INTEGER:
{
type_enum=SQL_C_LONG;
data_columns[i].data_length_indicator=sizeof(int);
break;
}
case SQL_BIGINT:
{
type_enum=SQL_C_SBIGINT;
data_columns[i].data_length_indicator=sizeof(long);
break;
}
case SQL_DECIMAL:
{
break;
}
case SQL_NUMERIC:
{
break;
}
case SQL_REAL:
{
break;
}
case SQL_FLOAT:
{
type_enum=SQL_C_FLOAT;
format_size=9;
data_columns[i].data_length_indicator=sizeof(float);
break;
}
case SQL_DOUBLE:
{
type_enum=SQL_C_DOUBLE;
data_columns[i].data_length_indicator=sizeof(double);
format_size=16;
break;
}
case SQL_DATE:
{
break;
}
case SQL_TIME:
{
break;
}
case SQL_TYPE_TIMESTAMP:
{
type_enum=SQL_C_TYPE_TIMESTAMP;
format_size=4;
data_columns[i].data_length_indicator=sizeof(SQL_TIMESTAMP_STRUCT);
break;
}
case SQL_BINARY:
{
break;
}
case SQL_VARBINARY:
{
break;
}
case SQL_LONGVARBINARY:
{
break;
}
default:
{
break;
}
}
rcode = SQLBindParameter
(
statement_handle,
parameter_count,
SQL_PARAM_INPUT,
type_enum,
data_columns[i].column_type,
data_columns[i].data_length_indicator,
format_size,
data_columns[i].column_buffer,
data_columns[i].column_buffer_length,
&data_columns[i].data_length_indicator
);
if(rcode!=SQL_SUCCESS)
{
//Show state
connection.last_message+="\n[DBBindUpdateParameters] error executing \
SQLBindParameter at columns!\n";
connection.last_message+=DBGetErrorMsg(statement_handle,SQL_HANDLE_STMT);
//cout << connection.last_message << endl;
return false;
}
}
for(i=0;i<total_primary_keys;i++)
{
parameter_count++;
switch(primary_keys[i].column_type)
{
case SQL_BIT:
{
break;
}
case SQL_CHAR:
{
type_enum=SQL_C_CHAR;
primary_keys[i].data_length_indicator=sizeof(char);
break;
}
case SQL_VARCHAR:
{
type_enum=SQL_C_CHAR;
primary_keys[i].data_length_indicator=SQL_NTS;
break;
}
case SQL_LONGVARCHAR:
{
break;
}
case SQL_WCHAR:
{
break;
}
case SQL_WVARCHAR:
{
break;
}
case SQL_WLONGVARCHAR:
{
break;
}
case SQL_TINYINT:
{
type_enum=SQL_C_TINYINT;
primary_keys[i].data_length_indicator=sizeof(unsigned char);
break;
}
case SQL_SMALLINT:
{
type_enum=SQL_C_SHORT;
primary_keys[i].data_length_indicator=sizeof(short);
break;
}
case SQL_INTEGER:
{
type_enum=SQL_C_LONG;
primary_keys[i].data_length_indicator=sizeof(int);
break;
}
case SQL_BIGINT:
{
type_enum=SQL_C_SBIGINT;
primary_keys[i].data_length_indicator=sizeof(long);
break;
}
case SQL_DECIMAL:
{
break;
}
case SQL_NUMERIC:
{
break;
}
case SQL_REAL:
{
break;
}
case SQL_FLOAT:
{
type_enum=SQL_C_FLOAT;
format_size=9;
primary_keys[i].data_length_indicator=sizeof(float);
break;
}
case SQL_DOUBLE:
{
type_enum=SQL_C_DOUBLE;
primary_keys[i].data_length_indicator=sizeof(double);
format_size=16;
break;
}
case SQL_DATE:
{
break;
}
case SQL_TIME:
{
break;
}
case SQL_TYPE_TIMESTAMP:
{
type_enum=SQL_C_TYPE_TIMESTAMP;
format_size=4;
primary_keys[i].data_length_indicator=sizeof(SQL_TIMESTAMP_STRUCT);
break;
}
case SQL_BINARY:
{
break;
}
case SQL_VARBINARY:
{
break;
}
case SQL_LONGVARBINARY:
{
break;
}
default:
{
break;
}
}
rcode = SQLBindParameter
(
statement_handle,
parameter_count,
SQL_PARAM_INPUT,
type_enum,
primary_keys[i].column_type,
primary_keys[i].data_length_indicator,
format_size,
primary_keys[i].column_buffer,
primary_keys[i].column_buffer_length,
&primary_keys[i].data_length_indicator
);
if(rcode!=SQL_SUCCESS)
{
//Show state
connection.last_message+="\n[DBBindUpdateParameters] error executing \
SQLBindParameter at primary keys!\n";
connection.last_message+=DBGetErrorMsg(statement_handle,SQL_HANDLE_STMT);
//cout << connection.last_message << endl;
return false;
}
}
return true;
}
bool DBBindDeleteParameters
(
DBConnection& connection,
SQLHSTMT& statement_handle,
const short& total_primary_keys,
DBColumn*& primary_keys
)
{
SQLRETURN rcode;
SQLSMALLINT type_enum;
SQLSMALLINT format_size=0;
short i;
short parameter_count=0;
for(i=0;i<total_primary_keys;i++)
{
parameter_count++;
switch(primary_keys[i].column_type)
{
case SQL_BIT:
{
break;
}
case SQL_CHAR:
{
type_enum=SQL_C_CHAR;
primary_keys[i].data_length_indicator=sizeof(char);
break;
}
case SQL_VARCHAR:
{
type_enum=SQL_C_CHAR;
primary_keys[i].data_length_indicator=SQL_NTS;
break;
}
case SQL_LONGVARCHAR:
{
break;
}
case SQL_WCHAR:
{
break;
}
case SQL_WVARCHAR:
{
break;
}
case SQL_WLONGVARCHAR:
{
break;
}
case SQL_TINYINT:
{
type_enum=SQL_C_TINYINT;
primary_keys[i].data_length_indicator=sizeof(unsigned char);
break;
}
case SQL_SMALLINT:
{
type_enum=SQL_C_SHORT;
primary_keys[i].data_length_indicator=sizeof(short);
break;
}
case SQL_INTEGER:
{
type_enum=SQL_C_LONG;
primary_keys[i].data_length_indicator=sizeof(int);
break;
}
case SQL_BIGINT:
{
type_enum=SQL_C_SBIGINT;
primary_keys[i].data_length_indicator=sizeof(long);
break;
}
case SQL_DECIMAL:
{
break;
}
case SQL_NUMERIC:
{
break;
}
case SQL_REAL:
{
break;
}
case SQL_FLOAT:
{
type_enum=SQL_C_FLOAT;
format_size=9;
primary_keys[i].data_length_indicator=sizeof(float);
break;
}
case SQL_DOUBLE:
{
type_enum=SQL_C_DOUBLE;
primary_keys[i].data_length_indicator=sizeof(double);
format_size=16;
break;
}
case SQL_DATE:
{
break;
}
case SQL_TIME:
{
break;
}
case SQL_TYPE_TIMESTAMP:
{
type_enum=SQL_C_TYPE_TIMESTAMP;
format_size=4;
primary_keys[i].data_length_indicator=sizeof(SQL_TIMESTAMP_STRUCT);
break;
}
case SQL_BINARY:
{
break;
}
case SQL_VARBINARY:
{
break;
}
case SQL_LONGVARBINARY:
{
break;
}
default:
{
break;
}
}
rcode = SQLBindParameter
(
statement_handle,
parameter_count,
SQL_PARAM_INPUT,
type_enum,
primary_keys[i].column_type,
primary_keys[i].data_length_indicator,
format_size,
primary_keys[i].column_buffer,
primary_keys[i].column_buffer_length,
&primary_keys[i].data_length_indicator
);
if(rcode!=SQL_SUCCESS)
{
//Show state
connection.last_message+="\n[DBBindDeleteParameters] error executing \
SQLBindParameter at primary keys!\n";
connection.last_message+=DBGetErrorMsg(statement_handle,SQL_HANDLE_STMT);
//cout << connection.last_message << endl;
return false;
}
}
return true;
}
bool DBPrepareSelect
(
DBConnection& connection,
SQLHSTMT& statement_handle,
const std::string& sqlcmd
)
{
SQLRETURN rcode;
//Allocate statement handle
rcode=SQLAllocHandle
(
SQL_HANDLE_STMT,
connection.database_connection_handle,
&statement_handle
);
if(rcode!=SQL_SUCCESS && rcode!=SQL_SUCCESS_WITH_INFO)
{
connection.last_message="\n[DBPrepareSelect] Can't allocate statement handle!";
connection.last_message+=DBGetErrorMsg(statement_handle,SQL_HANDLE_STMT);
return false;
}
//Set cursor statement attribute
rcode=SQLSetStmtAttr
(
statement_handle,
SQL_ATTR_CURSOR_TYPE,
(SQLPOINTER)SQL_CURSOR_FORWARD_ONLY,
0
);
if(rcode!=SQL_SUCCESS && rcode!=SQL_SUCCESS_WITH_INFO)
{
connection.last_message="\n[DBPrepareSelect] Can't set cursor attribute!";
connection.last_message+=DBGetErrorMsg(statement_handle,SQL_HANDLE_STMT);
return false;
}
//Set cursor row size statement attribute
rcode=SQLSetStmtAttr
(
statement_handle,
SQL_ATTR_ROW_ARRAY_SIZE,
(SQLPOINTER)1,
SQL_IS_UINTEGER
);
if(rcode!=SQL_SUCCESS && rcode!=SQL_SUCCESS_WITH_INFO)
{
connection.last_message="\n[DBPrepareSelect] Can't set cursor size attribute!";
connection.last_message+=DBGetErrorMsg(statement_handle,SQL_HANDLE_STMT);
return false;
}
//Set concurrency statement attribute
rcode=SQLSetStmtAttr
(
statement_handle,
SQL_ATTR_CONCURRENCY,
(SQLPOINTER)SQL_CONCUR_READ_ONLY,
0
);
if(rcode!=SQL_SUCCESS && rcode!=SQL_SUCCESS_WITH_INFO)
{
connection.last_message="\n[DBPrepareSelect] Can't set concurrency attribute!";
connection.last_message+=DBGetErrorMsg(statement_handle,SQL_HANDLE_STMT);
return false;
}
//Prepare SQl command
rcode=SQLPrepare
(
statement_handle,
(PSQLCHAR)sqlcmd.c_str(),
(SQLINTEGER)strlen(sqlcmd.c_str())
);
if(rcode!=SQL_SUCCESS && rcode!=SQL_SUCCESS_WITH_INFO)
{
connection.sql_command_prepared=false;
connection.last_message="\n[DBPrepareSelect] Can't prepare SQL statement!";
connection.last_message+=DBGetErrorMsg(statement_handle,SQL_HANDLE_STMT);
return false;
}
connection.sql_command_prepared=true;
//THE ASYNCHRONOUS SUPPORT FOR NOW IS NOT USED GIVEN THAT DM (DRIVER MANAGER)
//IS A TOO OLD VERSION THAT NOT SUPPORT ASKING FOR ASYNCHRONOUS TASKS TO FINISH
//FOR NOW THIS PROBLEM CANNOT BE HANDLED
//Set asynchronous support statement attribute
//rcode=SQLSetStmtAttr(connection.statement_handle,SQL_ATTR_ASYNC_ENABLE,(SQLPOINTER)SQL_ASYNC_ENABLE_ON,0);
//if(rcode!=SQL_SUCCESS && rcode!=SQL_SUCCESS_WITH_INFO)
//{
// connection.last_message="\n[DBPrepareStatement]Can't set asynchronous support attribute!";
// connection.last_message+="";
// connection.last_message+=DBGetErrorMsg(connection,SQL_HANDLE_STMT);
// return false;
//}
return true;
}
bool DBPrepareInsert
(
DBConnection& connection,
SQLHSTMT& statement_handle,
const std::string& sqlcmd
)
{
SQLRETURN rcode;
//Allocate statement handle
rcode=SQLAllocHandle
(
SQL_HANDLE_STMT,
connection.database_connection_handle,
&statement_handle
);
if(rcode!=SQL_SUCCESS && rcode!=SQL_SUCCESS_WITH_INFO)
{
connection.last_message="\n[DBPrepareInsert] Can't allocate statement handle!";
connection.last_message+=DBGetErrorMsg(statement_handle,SQL_HANDLE_STMT);
return false;
}
//Set cursor statement attribute
rcode=SQLSetStmtAttr
(
statement_handle,
SQL_ATTR_CURSOR_TYPE,
(SQLPOINTER)SQL_CURSOR_FORWARD_ONLY,
0
);
if(rcode!=SQL_SUCCESS && rcode!=SQL_SUCCESS_WITH_INFO)
{
connection.last_message="\n[DBPrepareInsert] Can't set cursor attribute!";
connection.last_message+=DBGetErrorMsg(statement_handle,SQL_HANDLE_STMT);
return false;
}
//Set cursor row size statement attribute
rcode=SQLSetStmtAttr
(
statement_handle,
SQL_ATTR_ROW_ARRAY_SIZE,
(SQLPOINTER)1,
SQL_IS_UINTEGER
);
if(rcode!=SQL_SUCCESS && rcode!=SQL_SUCCESS_WITH_INFO)
{
connection.last_message="\n[DBPrepareInsert] Can't set cursor size attribute!";
connection.last_message+=DBGetErrorMsg(statement_handle,SQL_HANDLE_STMT);
return false;
}
//Set concurrency statement attribute
rcode=SQLSetStmtAttr
(
statement_handle,
SQL_ATTR_CONCURRENCY,
(SQLPOINTER)SQL_CONCUR_DEFAULT,
0
);
if(rcode!=SQL_SUCCESS && rcode!=SQL_SUCCESS_WITH_INFO)
{
connection.last_message="\n[DBPrepareInsert] Can't set concurrency attribute!";
connection.last_message+=DBGetErrorMsg(statement_handle,SQL_HANDLE_STMT);
return false;
}
//To indicate column binding
rcode=SQLSetStmtAttr
(
statement_handle,
SQL_ATTR_PARAM_BIND_TYPE,
SQL_PARAM_BIND_BY_COLUMN,
0
);
if(rcode!=SQL_SUCCESS && rcode!=SQL_SUCCESS_WITH_INFO)
{
connection.last_message="\n[DBPrepareInsert] Can't set parameter binding type \
attribute!";
connection.last_message+=DBGetErrorMsg(statement_handle,SQL_HANDLE_STMT);
return false;
}
//To indicate the number of parameters to bind
SQLUSMALLINT total_parameters;
size_t n=std::count(sqlcmd.begin(), sqlcmd.end(),'?');
if(n>0)
{
total_parameters=(SQLUSMALLINT)n;
}
else
{
connection.last_message="\n[DBPrepareInsert] Bad SQL command!";
connection.last_message+=DBGetErrorMsg(statement_handle,SQL_HANDLE_STMT);
return false;
}
rcode=SQLSetStmtAttr
(
statement_handle,
SQL_ATTR_PARAMSET_SIZE,
(SQLPOINTER)(&total_parameters),
0
);
if(rcode!=SQL_SUCCESS && rcode!=SQL_SUCCESS_WITH_INFO)
{
connection.last_message="\n[DBPrepareInsert] Can't set the number of parameters \
binding attribute!";
connection.last_message+=DBGetErrorMsg(statement_handle,SQL_HANDLE_STMT);
return false;
}
//To indicate the rows per parameter set
rcode=SQLSetStmtAttr
(
statement_handle,
SQL_ATTR_PARAMSET_SIZE,
(SQLPOINTER)1,
0
);
if(rcode!=SQL_SUCCESS && rcode!=SQL_SUCCESS_WITH_INFO)
{
connection.last_message="\n[DBPrepareInsert] Can't set parameter binding type \
attribute!";
connection.last_message+=DBGetErrorMsg(statement_handle,SQL_HANDLE_STMT);
return false;
}
// //Prepare SQl command
// rcode=SQLPrepare(connection.statement_handle,(PSQLCHAR)sqlcmd.c_str(),
// (SQLINTEGER)strlen(sqlcmd.c_str()));
// if(rcode!=SQL_SUCCESS && rcode!=SQL_SUCCESS_WITH_INFO)
// {
// connection.sql_command_prepared=false;
// connection.last_message="\n[DBPrepareInsert] Can't prepare SQL statement!";
// connection.last_message+="";
// connection.last_message+=DBGetErrorMsg(connection,SQL_HANDLE_STMT);
// return false;
// }
// connection.sql_command_prepared=true;
return true;
}
bool DBPrepareUpdate
(
DBConnection& connection,
SQLHSTMT& statement_handle,
const std::string& sqlcmd
)
{
SQLRETURN rcode;
//Allocate statement handle
rcode=SQLAllocHandle
(
SQL_HANDLE_STMT,
connection.database_connection_handle,
&statement_handle
);
if(rcode!=SQL_SUCCESS && rcode!=SQL_SUCCESS_WITH_INFO)
{
connection.last_message="\n[DBPrepareUpdate] Can't allocate statement handle!";
connection.last_message+=DBGetErrorMsg(statement_handle,SQL_HANDLE_STMT);
return false;
}
//Set cursor statement attribute
rcode=SQLSetStmtAttr
(
statement_handle,
SQL_ATTR_CURSOR_TYPE,
(SQLPOINTER)SQL_CURSOR_FORWARD_ONLY,
0
);
if(rcode!=SQL_SUCCESS && rcode!=SQL_SUCCESS_WITH_INFO)
{
connection.last_message="\n[DBPrepareUpdate] Can't set cursor attribute!";
connection.last_message+=DBGetErrorMsg(statement_handle,SQL_HANDLE_STMT);
return false;
}
//Set cursor row size statement attribute
rcode=SQLSetStmtAttr
(
statement_handle,
SQL_ATTR_ROW_ARRAY_SIZE,
(SQLPOINTER)1,
SQL_IS_UINTEGER
);
if(rcode!=SQL_SUCCESS && rcode!=SQL_SUCCESS_WITH_INFO)
{
connection.last_message="\n[DBPrepareUpdate] Can't set cursor size attribute!";
connection.last_message+=DBGetErrorMsg(statement_handle,SQL_HANDLE_STMT);
return false;
}
//Set concurrency statement attribute
rcode=SQLSetStmtAttr
(
statement_handle,
SQL_ATTR_CONCURRENCY,
(SQLPOINTER)SQL_CONCUR_DEFAULT,
0
);
if(rcode!=SQL_SUCCESS && rcode!=SQL_SUCCESS_WITH_INFO)
{
connection.last_message="\n[DBPrepareUpdate] Can't set concurrency attribute!";
connection.last_message+=DBGetErrorMsg(statement_handle,SQL_HANDLE_STMT);
return false;
}
//To indicate column binding
rcode=SQLSetStmtAttr
(
statement_handle,
SQL_ATTR_PARAM_BIND_TYPE,
SQL_PARAM_BIND_BY_COLUMN,
0
);
if(rcode!=SQL_SUCCESS && rcode!=SQL_SUCCESS_WITH_INFO)
{
connection.last_message="\n[DBPrepareUpdate] Can't set parameter binding type \
attribute!";
connection.last_message+=DBGetErrorMsg(statement_handle,SQL_HANDLE_STMT);
return false;
}
return true;
}
bool DBPrepareDelete
(
DBConnection& connection,
SQLHSTMT& statement_handle,
const std::string& sqlcmd
)
{
SQLRETURN rcode;
//Allocate statement handle
rcode=SQLAllocHandle
(
SQL_HANDLE_STMT,
connection.database_connection_handle,
&statement_handle
);
if(rcode!=SQL_SUCCESS && rcode!=SQL_SUCCESS_WITH_INFO)
{
connection.last_message="\n[DBPrepareDelete] Can't allocate statement handle!";
connection.last_message+=DBGetErrorMsg(statement_handle,SQL_HANDLE_STMT);
return false;
}
//Set cursor statement attribute
rcode=SQLSetStmtAttr
(
statement_handle,
SQL_ATTR_CURSOR_TYPE,
(SQLPOINTER)SQL_CURSOR_FORWARD_ONLY,
0
);
if(rcode!=SQL_SUCCESS && rcode!=SQL_SUCCESS_WITH_INFO)
{
connection.last_message="\n[DBPrepareDelete] Can't set cursor attribute!";
connection.last_message+=DBGetErrorMsg(statement_handle,SQL_HANDLE_STMT);
return false;
}
//Set cursor row size statement attribute
rcode=SQLSetStmtAttr
(
statement_handle,
SQL_ATTR_ROW_ARRAY_SIZE,
(SQLPOINTER)1,
SQL_IS_UINTEGER
);
if(rcode!=SQL_SUCCESS && rcode!=SQL_SUCCESS_WITH_INFO)
{
connection.last_message="\n[DBPrepareDelete] Can't set cursor size attribute!";
connection.last_message+=DBGetErrorMsg(statement_handle,SQL_HANDLE_STMT);
return false;
}
//Set concurrency statement attribute
rcode=SQLSetStmtAttr
(
statement_handle,
SQL_ATTR_CONCURRENCY,
(SQLPOINTER)SQL_CONCUR_DEFAULT,
0
);
if(rcode!=SQL_SUCCESS && rcode!=SQL_SUCCESS_WITH_INFO)
{
connection.last_message="\n[DBPrepareDelete] Can't set concurrency attribute!";
connection.last_message+=DBGetErrorMsg(statement_handle,SQL_HANDLE_STMT);
return false;
}
//To indicate column binding
rcode=SQLSetStmtAttr
(
statement_handle,
SQL_ATTR_PARAM_BIND_TYPE,
SQL_PARAM_BIND_BY_COLUMN,
0
);
if(rcode!=SQL_SUCCESS && rcode!=SQL_SUCCESS_WITH_INFO)
{
connection.last_message="\n[DBPrepareDelete] Can't set parameter binding type \
attribute!";
connection.last_message+=DBGetErrorMsg(statement_handle,SQL_HANDLE_STMT);
return false;
}
return true;
}
}//odbc_database_operations namespace
}//databases namespace