// Connection.h: interface for the CConnection class.
//
//////////////////////////////////////////////////////////////////////
#if !defined(AFX_CONNECTION_H__035ED1A8_ECAE_4A7F_8CFE_44F22F9A2FDA__INCLUDED_)
#define AFX_CONNECTION_H__035ED1A8_ECAE_4A7F_8CFE_44F22F9A2FDA__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
namespace scdriver
{
///
/// Supported ScimoreDB transaction isolation levels
///
enum TRAN_ISOLATION_LEVEL
{
READ_COMMITTED = 0, /// Read only committed data. This level is the default.
READ_REPEATABLE = 1, /// Read repeatable isolation level. The data view will not change, and the current transaction will always see the database in the state after the transaction has been started.
SERIALIZE = 3 /// Serialize all transactions and execute on at the time
};
///
/// Query language type
///
enum CONNECTION_LANG
{
LANG_DQL = 0, /// Interpet the command text as DQL statements
LANG_SQL = 1, /// Interpet the command text as SQL statements
};
///
/// Connection callback events
///
enum CONNECTION_EVENT
{
CONN_BROKEN = 1, /// Fire when connections has been terminated.
CONN_ALTER = 2, /// Fire when DB cluster configuration has been altered.
QUERY_DONE = 3, /// Fire when the query has been completed, usually used when query is executed asychronuosously.
READ_SCHEMA = 4, /// Reserved for internal use. Do not set this event it will lead to crash!
READ_PARAMETERS = 5 /// Read output parameter value.
};
// forward declaration
class CConnection;
class CRecordset;
class CFieldStream;
class CCommand;
class c_connector;
///
/// Callback routine that will be fired when specified connection state event occurs.
///
/// Connection instance pointer that fires the event
/// User key, specified in SetConnectionCallback function
typedef void (__stdcall CONNECTION_STATE_CALLBACK) (CConnection *conn, void *context);
///
/// Manage connection, transaction,
/// query execution and state callbacks
///
#ifdef DELPHI
class CConnection : public CAbstractConnection
#else
class __declspec( dllexport ) CConnection
#endif
{
public:
CConnection();
virtual ~CConnection();
///
/// Connects with TCP to the database server. The client uses internal connection pool. It will re-use
/// released connection or establish new one. Connection becomes release after Close() call & can be reused.
///
/// Host name or IP address
/// The port, the databse is listening
/// The parameter is used when connecting to distributed database.
/// All Servers in the cluster has an unique instance id that can be acquired from system metadata:
/// SELECT * from system.sysinstances.
/// Default value -1, i.e. client will connect to the random server.
/// If method fails, the node_exception exception, containing the error message, will be thrown
void Connect(const char *host,const int port, const long inst_id = -1);
///
/// Connects, using named pipes protocol (shared memory), to the embedded database engine.
/// The embedded database can be loaded into client's process as dll or started in a separate
/// process (rundll32).
///
/// Host name or IP address
/// True if database is loaded in host process
/// If method fails, the ServerException, containing the error message, will be thrown
void Connect(const char *embdb_id,const bool &in_process);
///
/// If connection executes asynchronuos query, you can cancel it
/// by calling Cancel method.
///
/// If method fails, the node_exception exception, containing the error message, will be thrown
void Cancel();
///
/// Close connection and release it to the poll of
/// the available connections. If you need to query
/// the database, call Connect() again.
///
/// If method fails, the node_exception exception, containing the error message, will be thrown
void Close();
///
/// The function call will block until database
/// responded executed query status. If database returns an error
/// the [node_exception] exception with an error message
/// will be thrown. Otherwise, if defined, query events/callbacks will be
/// fired. The callback event is set with SetConnectionStateCallback
/// function.
/// The GetCompletionStatus(), must always be called right after
/// CConnection: Execute, CCommand::Execute/Open or CRecordset::Open,
/// unless, the query is asynchronuos - in this case, call the function
/// after completion event has been fired.
///
/// If server sends back to the client the error, node_exception exception, containing the error message, will be thrown
void GetCompletionStatus();
///
/// Return number of deleted, inserted or updated rows in the current transaction scope
///
__int64 GetAffectedRows();
///
/// Start new transaction scope and sets AutoCommit to false. Followed data changes will be visible
/// only by the current connection, until, Commit() is executed. Executing Rollback() will undo
/// all changes that was made after begin current transaction. The behaviour is similiar to BEGIN TRANSACTION
/// SQL statememnt.
///
/// Set transaction supported isolation level. The default - read committed.
/// If server sends back to the client the error, node_exception exception, containing the error message, will be thrown
void BeginTransaction(const TRAN_ISOLATION_LEVEL iso_level = READ_COMMITTED);
///
/// Abort/Rollback current transaction. The transaction must be started
/// using BeginTransaction() function.
///
/// If server sends back to the client the error, node_exception exception, containing the error message, will be thrown
void AbortTransaction();
///
/// Commit current transaction's changes. The transaction must be started
/// using BeginTransaction() function.
///
/// If server sends back to the client the error, node_exception exception, containing the error message, will be thrown
void CommitTransaction();
///
/// Execute SQL or DQL command.
/// The command will set affected rows and receive the new values
/// for the output parameter(s).
///
/// SQL or DQL statement. By default, database interpret text as SQL, unless, SetLanguage function had set it to DQL.
/// Reserved for internal use.
/// Reserved for internal use.
/// If server sends back to the client the error, node_exception exception with the error message, will be thrown
void Execute(const char *cmd, byte *_recv = 0, const int _irecv = 8192);
///
/// Return generated DQL statement from SQL.
///
/// SQL statement.
/// Pointer to the buffer that receives DQL
/// Size of the DQL buffer. The DQL can be maximum 8KB
/// If server sends back to the client the error, node_exception exception with the error message, will be thrown
void ShowDQL(const char *sql,char *dql, int idql);
///
/// Set query timeout value in seconds. If query being executed longer than
/// timeout seconds, it will be cancelled. The timeout is only used for synchronuos
/// queries. Asynchrounuos queries can be executed with ScimoreCommand::ExecuteAsynchronous
/// method and cancelled using ScimoreCommand::Cancel. Default value is - 0xffffffff, i.e. the query
/// never timeouts.
///
void SetTimeout(const long Seconds);
///
/// Set which language to execute. ScimoreDB supports SQL and DQL. DQL is text-based execution plan and used in rare cases,
/// for example, if SQL optimizer generates incorrect or slow DQL plan. By default, Language is SQL.
///
/// CONNECTION_LANG enum value specifying the language
void SetLanguage(const CONNECTION_LANG tlang);
///
/// Set callback function to be fired for the specified connection state.
/// The callback routine must not use any DB functions, e.g. execute, read rows, etc..,
/// it should do a quick operation like SetEvent()...
/// NOTE: do not call GetCompletionStatus() inside any callback functions.
///
/// Set QUERY_DONE event, which will be fired, when
/// asynchronuos query completed
/// Events callback routine address
/// User defined key/value that will be passed to callback routine.
void SetConnectionStateCallback(const CONNECTION_EVENT etype, CONNECTION_STATE_CALLBACK *pcallback, void *usercontext = 0);
///
/// If you set callback routines, you need to reset them as well.
/// Reset it in the inside callback routines or when you done with the query.
///
/// Callback events type.
void ResetConnectionStateCallback(const CONNECTION_EVENT etype);
/**************************************
*
* function: get_class_size
*
**************************************
*
* Functional description
*
* return the size of the class
**************************************/
static int get_class_size();
friend class CRecordset;
friend class CFieldStream;
friend class CCommand;
friend class CBulkExport;
friend class CBulkImport;
friend class c_connector;
protected:
/**************************************
*
* function: F i r e E v e n t
*
**************************************
*
* Functional description
*
* call users callback functions
**************************************/
void FireEvent(const CONNECTION_EVENT &etype);
/**************************************
*
* function: g e t _ r e t u r n
*
**************************************
*
* Functional description
*
**************************************/
byte *get_return();
/**************************************
*
* function: g e t _ d r i v e r
*
**************************************
*
* Functional description
*
**************************************/
c_connector *get_driver();
private:
/**************************************
*
* function: E x e c u t e S Q L
*
**************************************
*
* Functional description
*
* execute SQL
**************************************/
void ExecuteSQL(const char *sql, const int &isql, byte *recv);
/**************************************
*
* function: E x e c u t e D Q L
*
**************************************
*
* Functional description
*
* execute DQL
**************************************/
void ExecuteDQL(const char *dql, byte *recv);
/**************************************
*
* function: b a t c h _ s q l
*
**************************************
*
* Functional description
*
* split SQL into max 8kb chunk.
* Batching is allowed when SQL statement
* ends with ';'
* Return: true - if there is more than one batch
* isql - size of sql block
* sql updated pointer to the next sql batch begining
**************************************/
bool batch_sql(const char *cmd, char *sql, int &isql);
/**************************************
*
* function: r e s e t _ t r a n _ s c o p e
*
**************************************
*
* Functional description
*
* when auto_commit == false and transaction fails
* the server will rollback all changes made
* by transaction's scope. And the client does not need to call
* AbortTransaction anymore.The auto_commit flag will be reset
* to TRUE as well
**************************************/
void reset_tran_scope();
private:
c_connector *m_driver; // connection enpoint instance used to communicate with the DB servers
__int64 m_affected_rows;// number of affected rows by current executed command
bool m_auto_commit; // auto commit flag: true - each succesfully executed command will commit data, false - modified data will not be committed until implicitly call conn->CommitTransactio()
long m_timeout; // in seconds to wait for the qurty to complete
CONNECTION_LANG m_language; // 1 - SQL or 0 - DQL command statement
byte m_recv[8192];
protected:
int m_irecv;
private:
// registered callback functions for each connection
// state change event [CONNECTION_EVENT]
CONNECTION_STATE_CALLBACK *m_pconn_broken;
CONNECTION_STATE_CALLBACK *m_pconn_alter;
CONNECTION_STATE_CALLBACK *m_pquery_done;
CONNECTION_STATE_CALLBACK *m_pread_schema;
CONNECTION_STATE_CALLBACK *m_pread_params;
// user data ptr, which will be passed in callback function
void *m_pconn_broken_context;
void *m_pconn_alter_context;
void *m_pquery_done_context;
void *m_pread_schema_context;
void *m_pread_params_context;
};
}
#endif // !defined(AFX_CONNECTION_H__035ED1A8_ECAE_4A7F_8CFE_44F22F9A2FDA__INCLUDED_)