235 lines
12 KiB
Markdown
235 lines
12 KiB
Markdown
# DatabaseTransactionBegin
|
||
|
||
Starts transaction execution.
|
||
|
||
```
|
||
bool DatabaseTransactionBegin(
|
||
int database // database handle received in DatabaseOpen
|
||
);
|
||
|
||
```
|
||
|
||
Parameters
|
||
|
||
database
|
||
|
||
[in] Database handle received in [DatabaseOpen()](/en/docs/database/databaseopen).
|
||
|
||
Return true if successful, otherwise false. To get the error code, use GetLastError(), the possible responses are:
|
||
|
||
- ERR_INTERNAL_ERROR (4001) – critical runtime error;
|
||
- ERR_INVALID_PARAMETER (4003) – sql parameter contains an empty string;
|
||
- ERR_NOT_ENOUGH_MEMORY (4004) – insufficient memory;
|
||
- ERR_WRONG_STRING_PARAMETER (5040) – error converting a request into a UTF-8 string;
|
||
- ERR_DATABASE_INTERNAL (5120) – internal database error;
|
||
- ERR_DATABASE_INVALID_HANDLE (5121) – invalid database handle;
|
||
- ERR_DATABASE_EXECUTE (5124) – request execution error.
|
||
|
||
Note
|
||
|
||
The DatabaseTransactionBegin() function should be called before a transaction execution. Any transaction should start with calling DatabaseTransactionBegin() and end with calling DatabaseTransactionCommit().
|
||
|
||
Example:
|
||
|
||
```
|
||
//+------------------------------------------------------------------+
|
||
//| Script program start function |
|
||
//+------------------------------------------------------------------+
|
||
void OnStart()
|
||
{
|
||
//--- create the file name
|
||
string filename=AccountInfoString(ACCOUNT_SERVER) +"_"+IntegerToString(AccountInfoInteger(ACCOUNT_LOGIN))+".sqlite";
|
||
//--- open/create the database in the common terminal folder
|
||
int db=DatabaseOpen(filename, DATABASE_OPEN_READWRITE | DATABASE_OPEN_CREATE | DATABASE_OPEN_COMMON);
|
||
if(db==INVALID_HANDLE)
|
||
{
|
||
Print("DB: ", filename, " open failed with code ", GetLastError());
|
||
return;
|
||
}
|
||
//--- if the DEALS table already exists, delete it
|
||
if(!DeleteTable(db, "DEALS"))
|
||
{
|
||
DatabaseClose(db);
|
||
return;
|
||
}
|
||
//--- create the DEALS table
|
||
if(!CreateTableDeals(db))
|
||
{
|
||
DatabaseClose(db);
|
||
return;
|
||
}
|
||
//--- request the entire trading history
|
||
datetime from_date=0;
|
||
datetime to_date=TimeCurrent();
|
||
//--- request the history of deals in the specified interval
|
||
HistorySelect(from_date, to_date);
|
||
int deals_total=HistoryDealsTotal();
|
||
PrintFormat("Deals in the trading history: %d ", deals_total);
|
||
|
||
//--- measure the transaction execution speed using DatabaseTransactionBegin/DatabaseTransactionCommit
|
||
ulong start=GetMicrosecondCount();
|
||
bool fast_transactions=true;
|
||
InsertDeals(db, fast_transactions);
|
||
double fast_transactions_time=double(GetMicrosecondCount()-start)/1000;
|
||
PrintFormat("Transations WITH DatabaseTransactionBegin/DatabaseTransactionCommit: time=%.1f milliseconds", fast_transactions_time);
|
||
|
||
//--- delete the DEALS table, and then create it again
|
||
if(!DeleteTable(db, "DEALS"))
|
||
{
|
||
DatabaseClose(db);
|
||
return;
|
||
}
|
||
//--- create a new DEALS table
|
||
if(!CreateTableDeals(db))
|
||
{
|
||
DatabaseClose(db);
|
||
return;
|
||
}
|
||
|
||
//--- test again, this time without using DatabaseTransactionBegin/DatabaseTransactionCommit
|
||
fast_transactions=false;
|
||
start=GetMicrosecondCount();
|
||
InsertDeals(db, fast_transactions);
|
||
double slow_transactions_time=double(GetMicrosecondCount()-start)/1000;
|
||
PrintFormat("Transations WITHOUT DatabaseTransactionBegin/DatabaseTransactionCommit: time=%.1f milliseconds", slow_transactions_time);
|
||
//--- report gain in time
|
||
PrintFormat("Use of DatabaseTransactionBegin/DatabaseTransactionCommit provided acceleration by %.1f times", double(slow_transactions_time)/fast_transactions_time);
|
||
//--- close the database
|
||
DatabaseClose(db);
|
||
}
|
||
/*
|
||
Results:
|
||
Deals in the trading history: 2737
|
||
Transations WITH DatabaseTransactionBegin/DatabaseTransactionCommit: time=48.5 milliseconds
|
||
Transations WITHOUT DatabaseTransactionBegin/DatabaseTransactionCommit: time=25818.9 milliseconds
|
||
Use of DatabaseTransactionBegin/DatabaseTransactionCommit provided acceleration by 532.8 times
|
||
*/
|
||
//+------------------------------------------------------------------+
|
||
//| Deletes a table with the specified name from the database |
|
||
//+------------------------------------------------------------------+
|
||
bool DeleteTable(int database, string table_name)
|
||
{
|
||
if(!DatabaseExecute(database, "DROP TABLE IF EXISTS "+table_name))
|
||
{
|
||
Print("Failed to drop table with code ", GetLastError());
|
||
return(false);
|
||
}
|
||
//--- the table has been successfully deleted
|
||
return(true);
|
||
}
|
||
//+------------------------------------------------------------------+
|
||
//| Creates the DEALS table |
|
||
//+------------------------------------------------------------------+
|
||
bool CreateTableDeals(int database)
|
||
{
|
||
//--- check if the table exists
|
||
if(!DatabaseTableExists(database, "DEALS"))
|
||
//--- create the table
|
||
if(!DatabaseExecute(database, "CREATE TABLE DEALS("
|
||
"ID INT KEY NOT NULL,"
|
||
"ORDER_ID INT NOT NULL,"
|
||
"POSITION_ID INT NOT NULL,"
|
||
"TIME INT NOT NULL,"
|
||
"TYPE INT NOT NULL,"
|
||
"ENTRY INT NOT NULL,"
|
||
"SYMBOL CHAR(10),"
|
||
"VOLUME REAL,"
|
||
"PRICE REAL,"
|
||
"PROFIT REAL,"
|
||
"SWAP REAL,"
|
||
"COMMISSION REAL,"
|
||
"MAGIC INT,"
|
||
"REASON INT );"))
|
||
{
|
||
Print("DB: create the table DEALS failed with code ", GetLastError());
|
||
return(false);
|
||
}
|
||
//--- the table has been successfully created
|
||
return(true);
|
||
}
|
||
//+------------------------------------------------------------------+
|
||
//| Adds deals to the database table |
|
||
//+------------------------------------------------------------------+
|
||
bool InsertDeals(int database, bool begintransaction=true)
|
||
{
|
||
//--- Auxiliary variables
|
||
ulong deal_ticket; // deal ticket
|
||
long order_ticket; // the ticket of the order by which the deal was executed
|
||
long position_ticket; // ID of the position to which the deal belongs
|
||
datetime time; // deal execution time
|
||
long type ; // deal type
|
||
long entry ; // deal direction
|
||
string symbol; // the symbol fro which the deal was executed
|
||
double volume; // operation volume
|
||
double price; // price
|
||
double profit; // financial result
|
||
double swap; // swap
|
||
double commission; // commission
|
||
long magic; // Magic number
|
||
long reason; // deal execution reason or source
|
||
//--- go through all deals and add to the database
|
||
bool failed=false;
|
||
int deals=HistoryDealsTotal();
|
||
//--- if fast transaction performance method is used
|
||
if(begintransaction)
|
||
{
|
||
// --- lock the database before executing transactions
|
||
DatabaseTransactionBegin(database);
|
||
}
|
||
for(int i=0; i<deals; i++)
|
||
{
|
||
deal_ticket= HistoryDealGetTicket(i);
|
||
order_ticket= HistoryDealGetInteger(deal_ticket, DEAL_ORDER);
|
||
position_ticket=HistoryDealGetInteger(deal_ticket, DEAL_POSITION_ID);
|
||
time= (datetime)HistoryDealGetInteger(deal_ticket, DEAL_TIME);
|
||
type= HistoryDealGetInteger(deal_ticket, DEAL_TYPE);
|
||
entry= HistoryDealGetInteger(deal_ticket, DEAL_ENTRY);
|
||
symbol= HistoryDealGetString(deal_ticket, DEAL_SYMBOL);
|
||
volume= HistoryDealGetDouble(deal_ticket, DEAL_VOLUME);
|
||
price= HistoryDealGetDouble(deal_ticket, DEAL_PRICE);
|
||
profit= HistoryDealGetDouble(deal_ticket, DEAL_PROFIT);
|
||
swap= HistoryDealGetDouble(deal_ticket, DEAL_SWAP);
|
||
commission= HistoryDealGetDouble(deal_ticket, DEAL_COMMISSION);
|
||
magic= HistoryDealGetInteger(deal_ticket, DEAL_MAGIC);
|
||
reason= HistoryDealGetInteger(deal_ticket, DEAL_REASON);
|
||
//--- add each deal using the following request
|
||
string request_text=StringFormat("INSERT INTO DEALS (ID,ORDER_ID,POSITION_ID,TIME,TYPE,ENTRY,SYMBOL,VOLUME,PRICE,PROFIT,SWAP,COMMISSION,MAGIC,REASON)"
|
||
"VALUES (%d, %d, %d, %d, %d, %d, '%s', %G, %G, %G, %G, %G, %d, %d)",
|
||
deal_ticket, order_ticket, position_ticket, time, type, entry, symbol, volume, price, profit, swap, commission, magic, reason);
|
||
if(!DatabaseExecute(database, request_text))
|
||
{
|
||
PrintFormat("%s: failed to insert deal #%dwith code %d", __FUNCTION__, deal_ticket, GetLastError());
|
||
PrintFormat("i=%d: deal #%d %s", i, deal_ticket, symbol);
|
||
failed=true;
|
||
break;
|
||
}
|
||
}
|
||
//--- check for transaction execution errors
|
||
if(failed)
|
||
{
|
||
//--- if fast transaction performance method is used
|
||
if(begintransaction)
|
||
{
|
||
//--- roll back all transactions and unlock the database
|
||
DatabaseTransactionRollback(database);
|
||
}
|
||
Print("%s: DatabaseExecute() failed with code ", __FUNCTION__, GetLastError());
|
||
return(false);
|
||
}
|
||
//--- if fast transaction performance method is used
|
||
if(begintransaction)
|
||
{
|
||
//--- all transactions have been performed successfully - record changes and unlock the database
|
||
DatabaseTransactionCommit(database);
|
||
}
|
||
//--- successful completion
|
||
return(true);
|
||
}
|
||
//+------------------------------------------------------------------+
|
||
|
||
```
|
||
|
||
See also
|
||
|
||
[DatabaseExecute](/en/docs/database/databaseexecute),[ DatabasePrepare](/en/docs/database/databaseprepare), [DatabaseTransactionCommit](/en/docs/database/databasetransactioncommit), [DatabaseTransactionRollback](/en/docs/database/databasetransactionrollback)
|