#ifndef DBQOP_H
#define DBQOP_H
//FOR LINUX OPERATIVE SYSTEM
#ifdef __linux__
#ifdef BUILD_DBQOP
#define DBQOP_ATTRS extern __attribute__((visibility("default")))
#define DBQOP_STRUCT_EXPORT __attribute__((visibility("default")))
#define DBQOP_DTS_ATTRS
#else
#define DBQOP_ATTRS extern
#define DBQOP_STRUCT_EXPORT
#define DBQOP_DTS_ATTRS
#endif // BUILD_DBQOP
#endif // __linux__
//FOR WINDOWS OPERATIVE SYSTEM
#ifdef __windows__
#ifdef BUILD_DBQOP
#define DBQOP_ATTRS extern __declspec(dllexport)
#define DBQOP_STRUCT_EXPORT __declspec(dllexport)
#define DBQOP_DTS_ATTRS STDCALL
#else
#define DBQOP_ATTRS extern __declspec(dllimport)
#define DBQOP_STRUCT_EXPORT __declspec(dllimport)
#define DBQOP_DTS_ATTRS STDCALL
#endif // BUILD_DBQOP
#include <windows.h>
#include <windef.h>
#endif // __windows__
//THE ORDER OF THESE INCLUDES MATTER
#include <iostream>
#include <cstring>
#include <vector>
#include <ctime>
#include <typeinfo>
#include <string>
#include <sql.h>
#include <sqltypes.h>
#include <sqlext.h>
#include <algorithm>
#include "interop.h"
#include "binrw.h"
#define MAX_COL_TYPE_NAME_LENGTH 64
#define MAX_TYPE_LENGTH sizeof(LONGLONG)
#define MAX_COMMAND_LENGTH 1048576//1024*1024
#define MAX_ERROR_MESSAGES 1024
using namespace canonbit_definitions::interoperatibility;
using namespace canonbit_algorithms::binary_reader_writer;
namespace brw=canonbit_algorithms::binary_reader_writer;
typedef SQLCHAR* PSQLCHAR;
typedef SQLWCHAR* PSQLWCHAR;
typedef SQLSMALLINT* PSQLSMALLINT;
typedef SQLUSMALLINT* PSQLUSMALLINT;
typedef SQLINTEGER* PSQLINTEGER;
typedef SQLLEN* PSQLLEN;
typedef SQL_TIMESTAMP_STRUCT* PTIMESTAMP;
typedef struct DataBuffer
{
SQLLEN buffer_size;
PSQLCHAR buffer;
} CellData;
typedef std::vector<CellData> RowData;
typedef std::vector<RowData> TableData;//Collections of row buffers pointers
namespace canonbit_databases{
namespace odbc_database_operations{
enum TABLE_COLUMN_TYPES
{
PRIMARY_KEY=0,
FOREIGN_KEY,
DATA_COLUMN
};
//Database connection parameters and values
struct DBQOP_STRUCT_EXPORT DBConnection
{
DBConnection();
DBConnection(const DBConnection& other);
~DBConnection();
DBConnection& operator=(const DBConnection& rhs);
SQLHENV environment_handle;//Environment handle
SQLHDBC database_connection_handle;//Database connection handle
bool environment_handle_allocated;
bool connection_handle_allocated;
bool sql_command_prepared;
bool asynch_support;
bool is_connected;
bool is_open;
int flag;
std::string connection_string;
std::string output_connection_string;
std::string server_string;
std::string user_string;
std::string password_string;
std::string last_message;
};
struct DBQOP_STRUCT_EXPORT DBColumn
{
DBColumn();
~DBColumn();
explicit DBColumn(const short& new_column_type,const long& buffer_length);
DBColumn(const DBColumn& other);
DBColumn& operator=(const DBColumn& rhs);
brw::Archive& operator&(brw::Archive& ar);
uintptr_t table_owner;
short column_type;
short catalog_name_length;
short schema_name_length;
short table_name_length;
short column_name_length;
short column_type_name_length;
long data_length_indicator;
long column_buffer_length;//Max byte length of the column
SQLCHAR catalog_name[SQL_MAX_CATALOG_NAME_LEN];
SQLCHAR schema_name[SQL_MAX_SCHEMA_NAME_LEN];
SQLCHAR table_name[SQL_MAX_TABLE_NAME_LEN];
SQLCHAR column_name[SQL_MAX_COLUMN_NAME_LEN];
SQLCHAR column_type_name[MAX_COL_TYPE_NAME_LENGTH];
PSQLCHAR column_buffer;
};
struct DBKeyColumn
{
SQLCHAR key_catalog_name[SQL_MAX_CATALOG_NAME_LEN];
SQLCHAR key_schema_name[SQL_MAX_SCHEMA_NAME_LEN];
SQLCHAR key_table_name[SQL_MAX_TABLE_NAME_LEN];
SQLCHAR key_column_name[SQL_MAX_COLUMN_NAME_LEN];
SQLSMALLINT key_ordinal;
SQLCHAR key_name[SQL_MAX_COLUMN_NAME_LEN];
SQLSMALLINT key_catalog_name_length;
SQLSMALLINT key_schema_name_length;
SQLSMALLINT key_table_name_length;
SQLSMALLINT key_column_name_length;
SQLSMALLINT key_name_length;
};
struct DBQOP_STRUCT_EXPORT DBRow
{
public:
DBRow();
DBRow(const DBRow& other);
explicit DBRow(const uintptr_t& row_table_owner,const UINT& new_row_index);
DBRow& operator=(const DBRow& rhs);
~DBRow();
uintptr_t table_owner;
UINT row_index;
void* getValue(const short& column_index) const;
void getValue(const short& column_index,CellData& value) const;
void setValue(const short& column_index,void* value) const;
void setValue(const short& column_index,const CellData& value);
DBRow cloneRow() const;
private:
RowData row_data;
};
struct DBQOP_STRUCT_EXPORT DBTable
{
public:
DBTable();
~DBTable();
explicit DBTable(const short& new_total_columns,DBColumn* new_table_columns);
DBTable(const DBTable& other);
DBTable& operator=(const DBTable& rhs);
brw::Archive& operator&(brw::Archive& ar);
std::string sql_statement;
std::string database_name;
std::string catalog_name;
std::string schema_name;
std::string table_name;
short total_columns;
short total_primary_key_columns;
short total_foreign_key_columns;
short* primary_key_columns;//Ordinals in zero based index
short* foreign_key_columns;//Ordinals in zero based index
UINT total_rows;
DBColumn* table_columns;
DBRow newRow() const;
DBRow getRow(const UINT& row_index) const;
void addRow(UINT& new_row_index);
void addRow(const DBRow& new_row);
void* getValue(const UINT& row_index,const short& column_index) const;
void getValue
(
const UINT& row_index,
const short& column_index,
CellData& value
) const;
void setValue
(
const UINT& row_index,
const short& column_index,
void* value,
const long& value_length=1
);
void setValue
(
const UINT& row_index,
const short& column_index,
const CellData& value
);
template<typename T>
T getValue(const UINT& row_index,const short& column_index)
{
T value;
T* value_ptr=reinterpret_cast<T*>(getValue(row_index,column_index));
if(value_ptr)
{
value=*value_ptr;
}
return value;
}
bool findRow
(
const short& key_column_index,
const CellData& value,
const UINT& starting_row_index,
DBRow& row
);/*Binary search for a complete match value*/
bool findRowPattern
(
const short& key_column_index,
const std::string& value,
const UINT& starting_row_index,
DBRow& row
) const;/*String search with pattern*/
bool getPrimaryKeys
(
short*& primary_keys,
short& total_primary_keys,
std::string& message
);
bool getForeignKeys
(
short*& foreign_keys,
short& total_foreign_keys,
std::string& message
);
DBTable cloneTable();//Clone table schema and data
DBTable cloneSchema();//Just for cloning table schema
DBTable getSubTable
(
const short columns_indices[],
const short& total_sub_columns
);
void splitPKFKDC
(
DBTable& primary_keys,
DBTable& foreign_keys,
DBTable& data_columns,
bool& has_primary_keys,
bool& has_foreign_keys
);
friend SQLHSTMT& getStatementHandle(DBTable& table);
friend void setStatementHandle(DBTable& table,const SQLHSTMT handle);
private:
SQLHSTMT statement_handle;//Statement handle
TableData table_data;
bool is_primary_keys_set;
bool is_foreign_keys_set;
};
struct DBQOP_STRUCT_EXPORT DBDataSet
{
DBDataSet();
explicit DBDataSet
(
const std::string& sql_statement,
const std::string& driver,
const std::string& server,
const std::string& user,
const std::string& password
);
~DBDataSet();
DBConnection data_connection;
std::vector<DBTable> data_tables;
std::vector<DBTable>::iterator begin();
std::vector<DBTable>::iterator end();
int total_data_tables;
};
struct DBDataRelation
{
DBTable* table;
short column_ordinal;
};
//METHODS THE CONNECTION ARGUMENT WILL HOLD THE OUTPUT MESSAGE IN CASE
//OF ERROR OR WARNING
DBQOP_ATTRS
bool DBConnect
(
DBConnection& connection,
const std::string& driver,
const std::string& server,
const std::string& user,
const std::string& password
);
DBQOP_ATTRS
bool DBDisconnect(DBConnection& connection);
DBQOP_ATTRS
VECSTR DBGetDrivers(DBConnection& connection);
DBQOP_ATTRS
VECSTR DBGetDataSources(DBConnection& connection);
DBQOP_ATTRS
bool DBSelect
(
DBConnection& connection,
const std::string& sqlcmd,
DBTable& select_table
);
DBQOP_ATTRS
bool DBInsert
(
DBConnection& connection,
const std::string& sqlcmd,
const DBTable& rows_to_insert,
DBTable& rows_rejected
);
DBQOP_ATTRS
bool DBUpdate
(
DBConnection& connection,
const std::string& sqlcmd,
const DBTable& rows_to_update,
const DBTable& primary_keys_values,
DBTable& rows_rejected
);
DBQOP_ATTRS
bool DBDelete
(
DBConnection& connection,
const std::string& sqlcmd,
const DBTable& primary_keys_values,
DBTable& rows_rejected
);
DBQOP_ATTRS
bool DBGetPrimaryKeys
(
DBTable& table,
DBKeyColumn*& primary_keys,
short& total_primary_keys,
std::string& message
);
DBQOP_ATTRS
bool DBGetForeignKeys
(
DBTable& table,
DBKeyColumn*& foreign_keys,
short& total_foreign_keys,
std::string& message
);
DBQOP_ATTRS
bool DBTransaction(const std::string& sqlcmd,std::string& message);
DBQOP_ATTRS
short DBGetNumberOfColumns(SQLHSTMT& statement_handle);//Statement handle must be prepared or executed
DBQOP_ATTRS
UINT DBGetNumberOfRows(SQLHSTMT& statement_handle);//Statement handle must be prepared or executed
DBQOP_ATTRS
std::string DBGetErrorMsg(SQLHANDLE handle,SQLSMALLINT handle_type);
DBQOP_ATTRS
std::string GetSQLTypeName(const short sql_type_id,bool& is_type_variable);
//==========================================================================================
//METHODS FOR INTEROPERABILITY WITH EXCEL AND LIBREOFFICE MACROS
DBQOP_ATTRS DBQOP_DTS_ATTRS
bool DTSDBConnect
(
const char*& driver,
const char*& server,
const char*& user,
const char*& password
);
DBQOP_ATTRS DBQOP_DTS_ATTRS
bool DTSDBDisconnect();
DBQOP_ATTRS DBQOP_DTS_ATTRS
bool DTSDBSelect(const char*& sqlcmd);
DBQOP_ATTRS DBQOP_DTS_ATTRS
bool DTSDBInsert(const char*& sqlcmd);
DBQOP_ATTRS DBQOP_DTS_ATTRS
bool DTSDBUpdate(const char*& sqlcmd);
DBQOP_ATTRS DBQOP_DTS_ATTRS
bool DTSDBDelete(const char*& sqlcmd);
DBQOP_ATTRS DBQOP_DTS_ATTRS
void DTSDBSetColumnIndex(const short& index);
DBQOP_ATTRS DBQOP_DTS_ATTRS
int DTSDBGetColumnType(const short& index);
#ifdef BUILD_DBQOP
//==========================================================================================
//VERY IMPORTANT VARIABLES THAT ARE GOING TO BE USED AS A BUFFER
//TO HOLD VARIABLE DATA ON FETCHING
static RowData sql_cmd_buffer;
//==========================================================================================
//==========================================================================================
//VERY IMPORTANT VARIABLES THAT ARE GOING TO BE USED WITH DATASHEET APPLICATIONS
static DBConnection dts_connection;
static DBTable dts_select_table;
static DBTable dts_rows_to_insert;
static DBTable dts_rows_to_update;
static DBTable dts_primary_keys_values;
static DBTable dts_rows_rejected;
static short dts_current_column_index;
//==========================================================================================
static
bool DBGetColumnsAndBind
(
DBConnection& connection,
SQLHSTMT& statement_handle,
const short& total_columns,
DBColumn*& columns
);
static
bool DBBindInsertParameters
(
DBConnection& connection,
SQLHSTMT& statement_handle,
const short& total_columns,
DBColumn*& columns
);
static
bool DBBindUpdateParameters
(
DBConnection& connection,
SQLHSTMT& statement_handle,
const short& total_data_columns,
const short& total_primary_keys,
DBColumn*& data_columns,
DBColumn*& primary_keys
);
static
bool DBBindDeleteParameters
(
DBConnection& connection,
SQLHSTMT& statement_handle,
const short& total_primary_keys,
DBColumn*& primary_keys
);
static
bool DBPrepareSelect
(
DBConnection& connection,
SQLHSTMT& statement_handle,
const std::string& sqlcmd
);
static
bool DBPrepareInsert
(
DBConnection& connection,
SQLHSTMT& statement_handle,
const std::string& sqlcmd
);
static
bool DBPrepareUpdate
(
DBConnection& connection,
SQLHSTMT& statement_handle,
const std::string& sqlcmd
);
static
bool DBPrepareDelete
(
DBConnection& connection,
SQLHSTMT& statement_handle,
const std::string& sqlcmd
);
#endif // BUILD_DBQOP
}//odbc_database_operations namespace
}//canonbit_databases namespace
#endif // DBQOP_H