#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(row_table_owner); table_owner=row_table_owner; //row_index=new_row_index; row_data=RowData(table.total_columns); for(short i=0;itable_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(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(value.buffer); static unsigned char value7; value7=(unsigned char)(*data7); return &value7; } case SQL_SMALLINT: { short* data8=reinterpret_cast(value.buffer); static short value8; value8=(short)(*data8); return &value8; } case SQL_INTEGER: { int* data9=reinterpret_cast(value.buffer); static int value9; value9=(int)(*data9); return &value9; break; } case SQL_BIGINT: { long* data10=reinterpret_cast(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(value.buffer); static float value14; value14=float(*data14); return &value14; } case SQL_DOUBLE: { double* data15=reinterpret_cast(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(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(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;isql_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;itable_columns[i]=rhs.table_columns[i]; } for(short i=0;iprimary_key_columns[i]=rhs.primary_key_columns[i]; } for(short i=0;iforeign_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(this),0); return new_row; } DBRow DBTable::getRow(const UINT& row_index) const { DBRow row=DBRow(reinterpret_cast(this),row_index); for(short i=0;i(value.buffer); static unsigned char value7; value7=(unsigned char)(*data7); return &value7; } case SQL_SMALLINT: { short* data8=reinterpret_cast(value.buffer); static short value8; value8=(short)(*data8); return &value8; } case SQL_INTEGER: { int* data9=reinterpret_cast(value.buffer); static int value9; value9=(int)(*data9); return &value9; break; } case SQL_BIGINT: { long* data10=reinterpret_cast(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(value.buffer); static float value14; value14=float(*data14); return &value14; } case SQL_DOUBLE: { double* data15=reinterpret_cast(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(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(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(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(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(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(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(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(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(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(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(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(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=(long)len) { match=std::strstr(reinterpret_cast(cell.buffer),pattern); if(match) { if((match-reinterpret_cast(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=(long)len) { match=std::strstr(reinterpret_cast(cell.buffer),pattern); if(match) { if((match-reinterpret_cast(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;i0) { 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::iterator DBDataSet::begin() { return data_tables.begin(); } std::vector::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 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_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;iMAX_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;i0) { 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