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.
Перевод :
Функция 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 запросов"? Можно пример, пожалуйста, для понимания.
При выполнении запроса ( SELECT ) с помощью DatabasePrepare() в справке показано как проводить работу. DatabaseRead() позволяет обращаться к данным через хендл запроса.
При выполнении запроса ( SELECT ) с помощью DatabaseExecute() хендл запроса не создается (работа в справке не показана ). Каким образом обратиться к данным через DatabaseRead() без хендла запроса ( или получить данные без DatabaseRead() ?
Пример задачи : получить количество записей в таблице по определенному признаку ( или максимальное/минимальное значение). Результат работы запроса - одна запись. Обращение к запросу - единоразовое. Как получить результат запроса при использовании DatabaseExecute() ?
Вот детальная статья по использованию SQLite в MQL5: SQLite: нативная работа с базами данных на SQL в MQL5
Используйте поиск, пожалуйста.
- www.mql5.com
`
Каким образом должен выглядеть запрос, и какова должна быть подготовка к запросу, для получения ответа на вопрос : находится ли указанная прямая внутри тел баров на указанном промежутке времени для указанного периода?
`
Получилось. Работает.
Промежуточный знАчимый результат запроса :
"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/
- www.sqlitetutorial.net
- Бесплатные приложения для трейдинга
- 8 000+ сигналов для копирования
- Экономические новости для анализа финансовых рынков
Вы принимаете политику сайта и условия использования
DatabaseFinalize() - что нужно знать о финализации?
Что смотреть кроме документации : https://www.mql5.com/ru/docs/database/databasefinalize ?