SQLite in MQL5. Примеры, решения.

 

    

   DatabaseFinalize() - что нужно знать о финализации? 

   Что смотреть кроме документации : https://www.mql5.com/ru/docs/database/databasefinalize   ?  


 

https://www.sqlite.org/c3ref/finalize.html

Destroy A Prepared Statement Object

int sqlite3_finalize(sqlite3_stmt *pStmt);

The sqlite3_finalize() function is called to delete a prepared statement. If the most recent evaluation of the statement encountered no errors or if the statement is never been evaluated, then sqlite3_finalize() returns SQLITE_OK. If the most recent evaluation of statement S failed, then sqlite3_finalize(S) returns the appropriate error code or extended error code.

The sqlite3_finalize(S) routine can be called at any point during the life cycle of prepared statement S: before statement S is ever evaluated, after one or more calls to sqlite3_reset(), or after any call to sqlite3_step() regardless of whether or not the statement has completed execution.

Invoking sqlite3_finalize() on a NULL pointer is a harmless no-op.

The application must finalize every prepared statement in order to avoid resource leaks. It is a grievous error for the application to try to use a prepared statement after it has been finalized. Any use of a prepared statement after it has been finalized can result in undefined and undesirable behavior such as segfaults and heap corruption.

See also lists of Objects, Constants, and Functions.

 

   

  Перевод  : 

Функция sqlite3_finalize() вызывается для удаления подготовленного оператора. Если последнее выполнение оператора не вызвало ошибок или если оператор еще не был выполнен, то sqlite3_finalize() возвращает SQLITE_OK. Если последнее выполнение оператора S завершилось неудачно, то sqlite3_finalize(S) возвращает соответствующий код ошибки или расширенный код ошибки. Процедуру sqlite3_finalize(S) можно вызывать на любом этапе жизненного цикла подготовленного оператора S: до того, как оператор S будет выполнен, после одного или нескольких вызовов sqlite3_reset() или после любого вызова sqlite3_step(), независимо от того, завершено ли выполнение оператора. Вызов sqlite3_finalize() для нулевого указателя не приводит к ошибке. Приложение должно завершать каждый подготовленный оператор, чтобы избежать утечек ресурсов. Попытка использовать подготовленный оператор после его завершения является серьезной ошибкой. Любое использование подготовленного оператора после его завершения может привести к неопределенному и нежелательному поведению, такому как сбои и повреждение кучи. См. также списки объектов, констант и функций.

  Дополнительное уточнение :  

Правильно ли понимать, что первый пример, в этом случае ,  является серьезной ошибкой, а второй пример является правильным использованием финализации? 

1. 

// #########################################################################################################################################
//+------------------------------------------------------------------+
//| объявление запроса, формирование запроса
//+------------------------------------------------------------------+
int que_065 = DatabasePrepare(Handle_db_01, " SELECT * FROM " + Tb_Nm_Q_43  + "     ; ");   //  получить количество записей в таблице для создания массивов
//+------------------------------------------------------------------+//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| обработка запроса
//+------------------------------------------------------------------+

//+------------------------------------------------------------------+
//| формирование запроса
//+------------------------------------------------------------------+
que_065 = DatabasePrepare(Handle_db_01, " SELECT * FROM " + Tb_Nm_Q_43  + "     ; ");   //  получить количество записей в таблице для создания массивов
//+------------------------------------------------------------------+
//| обработка запроса
//+------------------------------------------------------------------+

//+------------------------------------------------------------------+
//| формирование запроса
//+------------------------------------------------------------------+
que_065 = DatabasePrepare(Handle_db_01, " SELECT * FROM " + Tb_Nm_Q_43  + "     ; ");   //  получить количество записей в таблице для создания массивов
//+------------------------------------------------------------------+
//| обработка запроса
//+------------------------------------------------------------------+

DatabaseFinalize(que_065);
// #########################################################################################################################################

2. 

// #########################################################################################################################################
//+------------------------------------------------------------------+
//| объявление запроса, формирование запроса
//+------------------------------------------------------------------+
int que_065 = DatabasePrepare(Handle_db_01, " SELECT * FROM " + Tb_Nm_Q_43  + "     ; ");   //  получить количество записей в таблице для создания массивов
//+------------------------------------------------------------------+//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| обработка запроса
//+------------------------------------------------------------------+
DatabaseFinalize(que_065);
//+------------------------------------------------------------------+
//| объявление запроса, формирование запроса
//+------------------------------------------------------------------+
int que_066 = DatabasePrepare(Handle_db_01, " SELECT * FROM " + Tb_Nm_Q_43  + "     ; ");   //  получить количество записей в таблице для создания массивов
//+------------------------------------------------------------------+
//| обработка запроса
//+------------------------------------------------------------------+
DatabaseFinalize(que_066);
//+------------------------------------------------------------------+
//| объявление запроса, формирование запроса
//+------------------------------------------------------------------+
int que_067 = DatabasePrepare(Handle_db_01, " SELECT * FROM " + Tb_Nm_Q_43  + "     ; ");   //  получить количество записей в таблице для создания массивов
//+------------------------------------------------------------------+
//| обработка запроса
//+------------------------------------------------------------------+
DatabaseFinalize(que_067);
// #########################################################################################################################################// 

  


 

Второй вариант правильный, а первый будет генерировать утечки.

DatabasePrepare используется для случаев, когда один ранее подготовленный стейтмент далее без изменений используется много (сотни и тысячи) раз. Тем самым экономится время парсинга текстового запроса и сразу используется бинарное представление запроса.

Ради 1-2 запросов городить кеширование через DatabasePrepare не имеет никакого смысла.

 

   

  Каким образом сделать правильно, без "кеширования" и "ради 1-2 запросов"?  Можно пример, пожалуйста, для понимания. 

 
DDFedor #:

   

  Каким образом сделать правильно, без "кеширования" и "ради 1-2 запросов"?  Можно пример, пожалуйста, для понимания. 

Используйте напрямую DatabaseExecute и все будет работать просто и без кеширования.
 

   

  При выполнении запроса ( SELECT )  с помощью DatabasePrepare() в справке показано как проводить работу. DatabaseRead() позволяет обращаться к данным через хендл запроса. 

  При выполнении запроса ( SELECT )  с помощью DatabaseExecute() хендл запроса не создается (работа в справке не показана ).  Каким образом обратиться к данным через DatabaseRead() без хендла запроса ( или получить данные без DatabaseRead() ? 

 Пример задачи  :  получить количество записей в таблице по определенному признаку ( или максимальное/минимальное значение). Результат работы запроса - одна запись. Обращение к запросу - единоразовое.  Как получить результат запроса при использовании  DatabaseExecute()  ? 


 

Вот детальная статья по использованию SQLite в MQL5: SQLite: нативная работа с базами данных на SQL в MQL5

Используйте поиск, пожалуйста.

SQLite: нативная работа с базами данных на SQL в MQL5
SQLite: нативная работа с базами данных на SQL в MQL5
  • www.mql5.com
Разработка торговых стратегий связана с обработкой больших объемов данных. Теперь прямо в MQL5 вы можете работать с базами данных с помощью SQL-запросов на основе SQLite. Важным преимуществом данного движка является то, что вся база данных содержится в единственном файле, который находится на компьютере пользователя.
 

 `  

  Каким образом должен выглядеть запрос, и какова должна быть подготовка к запросу,  для получения ответа на вопрос : находится ли указанная прямая внутри тел баров на указанном промежутке времени для указанного периода? 

 

`

Получилось. Работает. 

Промежуточный знАчимый результат запроса  : 

"SELECT TF, BARN, TM, HI, LO, OP, CL, (1693256400) AS TM2, (1.08076) AS PR2, (1693267200) AS TM1, (1.08112) AS PR1, (1693267200) AS TM3,  "
"IIF(OP < CL, OP , CL  ) AS MMIN,     IIF(OP > CL, OP , CL )  AS MMAX   "
"FROM 'BARS_TB'    "
"WHERE (( PR2 - PR1 )/(TM2 - TM1 )*  TM3  + PR1 -( PR2 - PR1 )/(TM2 - TM1 )* TM1 )   "
"BETWEEN MMIN AND MMAX  "


Конечный вариант - с  дополнительными несущественными изменениями. 



 

`

Удачно довелось поработать с сайтом по SQLite :  https://www.sqlitetutorial.net/   

SQLite Tutorial
  • www.sqlitetutorial.net
This SQLite tutorial teaches you everything you need to know to start using SQLite effectively. In this tutorial, you will learn SQLite step by step through extensive hands-on practice. SQLite is an open-source, zero-configuration, self-contained, stand-alone, transaction relational database engine designed to be embedded into an application...