Coverity issue resolved resource_leak
[platform/core/messaging/msg-service.git] / utils / MsgSqliteWrapper.cpp
1 /*
2  * Copyright (c) 2014 Samsung Electronics Co., Ltd. All rights reserved
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15 */
16
17 #include <stdio.h>
18 #include <stddef.h>
19 #include <unistd.h>
20 #include <string.h>
21 #include <stdlib.h>
22 #include <map>
23 #include <sys/mman.h>
24 #include <fcntl.h>
25 #include <errno.h>
26 #include <pthread.h>
27 #include <sqlite3.h>
28
29 #include "MsgDebug.h"
30 #include "MsgSqliteWrapper.h"
31
32 int __msg_db_util_open(const char *pszFilePath, sqlite3 **ppDB, int flags, const char *zVfs);
33 int __msg_db_util_close(sqlite3 *pDB);
34 void __clear_db_handle(sqlite3 *pDB);
35
36 /*==================================================================================================
37                                      VARIABLES
38 ==================================================================================================*/
39 #if 0
40 __thread sqlite3 *handle = NULL;
41 __thread sqlite3_stmt *stmt = NULL;
42 #endif
43
44 /*==================================================================================================
45                                      IMPLEMENTATION OF MsgDbHandler - Member Functions
46 ==================================================================================================*/
47 MsgDbHandler::MsgDbHandler()
48 {
49         result = NULL;
50         handle = NULL;
51         stmt   = NULL;
52         mmapMx = NULL;
53         shm_fd = -1;
54         in_trans = false;
55 }
56
57
58 MsgDbHandler::~MsgDbHandler()
59 {
60         freeTable();
61         finalizeQuery();
62         if (disconnect() != MSG_SUCCESS)
63                 MSG_DEBUG("DB disconnect is failed.");
64 }
65
66 msg_error_t MsgDbHandler::connect()
67 {
68         int ret = 0;
69
70         if (handle == NULL) {
71                 char strDBName[64];
72
73                 memset(strDBName, 0x00, sizeof(strDBName));
74                 snprintf(strDBName, 64, "%s", MSGFW_DB_NAME);
75
76                 ret = __msg_db_util_open(strDBName, &handle, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, NULL);
77
78                 if (ret == SQLITE_OK) {
79                         MSG_DEBUG("DB Connect Success : [%p]", handle);
80                         return MSG_SUCCESS;
81                 } else if (ret == SQLITE_PERM){
82                         MSG_DEBUG("DB Connect Fail [%d]", ret);
83                         disconnect();
84                         return MSG_ERR_PERMISSION_DENIED;
85                 } else {
86                         MSG_DEBUG("DB Connect Fail [%d]", ret);
87                         disconnect();
88                         return MSG_ERR_DB_CONNECT;
89                 }
90         } else {
91                 MSG_DEBUG("DB Connect exist : [%p]", handle);
92         }
93
94         return MSG_SUCCESS;
95 }
96
97 /* Use only in app side */
98 msg_error_t MsgDbHandler::connectReadOnly()
99 {
100         int ret = 0;
101
102         if (handle == NULL) {
103                 char strDBName[64];
104
105                 memset(strDBName, 0x00, sizeof(strDBName));
106                 snprintf(strDBName, 64, "%s", MSGFW_DB_NAME);
107
108                 MSG_DEBUG("db_util_open_with_options SQLITE_OPEN_READONLY");
109                 ret = __msg_db_util_open(strDBName, &handle, SQLITE_OPEN_READONLY, NULL);
110
111                 if (ret == SQLITE_OK) {
112                         MSG_DEBUG("DB Connect Success : [%p]", handle);
113                         return MSG_SUCCESS;
114                 } else if (ret == SQLITE_PERM){
115                         MSG_DEBUG("DB Connect Fail [%d]", ret);
116                         return MSG_ERR_PERMISSION_DENIED;
117                 } else {
118                         MSG_DEBUG("DB Connect Fail [%d]", ret);
119                         return MSG_ERR_DB_CONNECT;
120                 }
121         } else {
122                 MSG_DEBUG("DB Connect exist : [%p]", handle);
123         }
124
125         return MSG_SUCCESS;
126 }
127
128
129 msg_error_t MsgDbHandler::disconnect()
130 {
131         int ret = 0;
132
133         if (handle != NULL) {
134                 ret = __msg_db_util_close(handle);
135
136                 if (ret == SQLITE_OK) {
137                         handle = NULL;
138                         MSG_DEBUG("DB Disconnect Success");
139                         return MSG_SUCCESS;
140                 } else {
141                         MSG_DEBUG("DB Disconnect Fail [%d]", ret);
142                         return MSG_ERR_DB_DISCONNECT;
143                 }
144         }
145
146         return MSG_SUCCESS;
147 }
148
149
150 bool MsgDbHandler::checkTableExist(const char *pTableName)
151 {
152         char strQuery[256];
153         int nRowCnt = 0, nResult = 0;
154
155         /* Formulate the Query */
156         memset(strQuery, 0x00, sizeof(strQuery));
157         snprintf(strQuery, sizeof(strQuery), "select count(name) from sqlite_master where name='%s'", pTableName);
158
159         if (getTable(strQuery, &nRowCnt, NULL) != MSG_SUCCESS) {
160                 freeTable();
161                 return false;
162         }
163
164         nResult = getColumnToInt(1);
165         MSG_DEBUG("Result [%d]", nResult);
166
167         freeTable();
168
169         if (nResult > 0)
170                 return true;
171         else
172                 return false;
173 }
174
175
176 msg_error_t MsgDbHandler::execQuery(const char *pQuery)
177 {
178         if (!pQuery)
179                 return MSG_ERR_INVALID_PARAMETER;
180
181         if(connect() != MSG_SUCCESS)
182                 return MSG_ERR_DB_DISCONNECT;
183
184         if (prepareQuery(pQuery) != MSG_SUCCESS) {
185                 MSG_DEBUG("Fail to prepareQuery.");
186                 return MSG_ERR_DB_EXEC;
187         }
188
189         if (stepQuery() == MSG_ERR_DB_STEP) {
190                 MSG_DEBUG("Fail to stepQuery.");
191                 finalizeQuery();
192                 return MSG_ERR_DB_EXEC;
193         }
194
195         finalizeQuery();
196
197         return MSG_SUCCESS;
198 }
199
200
201 msg_error_t MsgDbHandler::getTable(const char *pQuery, int *pRowCnt, int *pColumnCnt)
202 {
203         int ret = 0;
204
205         *pRowCnt = 0;
206         if (pColumnCnt)
207                 *pColumnCnt = 0;
208
209         if(connect() != MSG_SUCCESS)
210                 return MSG_ERR_DB_DISCONNECT;
211
212         freeTable();
213         MSG_DEBUG("[%s]", pQuery);
214         ret = sqlite3_get_table(handle, pQuery, &result, pRowCnt, pColumnCnt, NULL);
215
216         if (ret == SQLITE_OK) {
217                 if (*pRowCnt == 0) { /* when the no record return 'MSG_ERR_DB_NORECORD' */
218                         MSG_DEBUG("No Query Result");
219                         return MSG_ERR_DB_NORECORD;
220                 }
221
222                 MSG_DEBUG("Get Table Success");
223                 return MSG_SUCCESS;
224         } else if (ret == SQLITE_BUSY) {
225                 MSG_DEBUG("The database file is locked [%d]", ret);
226                 return MSG_ERR_DB_BUSY;
227         } else {
228                 MSG_DEBUG("Get Table Fail [%d]", ret);
229                 return MSG_ERR_DB_GETTABLE;
230         }
231
232         return MSG_SUCCESS;
233 }
234
235
236 msg_error_t MsgDbHandler::getTableWithResult(const char *pQuery, char ***res, int *pRowCnt, int *pColumnCnt)
237 {
238         int ret = 0;
239
240         *pRowCnt = 0;
241         if (pColumnCnt)
242                 *pColumnCnt = 0;
243
244         MSG_DEBUG("[%s]", pQuery);
245         ret = sqlite3_get_table(handle, pQuery, res, pRowCnt, pColumnCnt, NULL);
246
247         if (ret == SQLITE_OK) {
248                 if (*pRowCnt == 0) { /* when the no record return 'MSG_ERR_DB_NORECORD' */
249                         MSG_DEBUG("No Query Result");
250                         return MSG_ERR_DB_NORECORD;
251                 }
252
253                 MSG_DEBUG("Get Table Success");
254                 return MSG_SUCCESS;
255         } else if (ret == SQLITE_BUSY) {
256                 MSG_DEBUG("The database file is locked [%d]", ret);
257                 return MSG_ERR_DB_BUSY;
258         } else {
259                 MSG_DEBUG("Get Table Fail [%d]", ret);
260                 return MSG_ERR_DB_GETTABLE;
261         }
262
263         return MSG_SUCCESS;
264 }
265
266 void MsgDbHandler::freeTable()
267 {
268         if (result) {
269                 sqlite3_free_table(result);
270                 result = NULL;
271         }
272 }
273
274 void MsgDbHandler::freeTable(char **db_res)
275 {
276         if (db_res) {
277                 sqlite3_free_table(db_res);
278                 db_res = NULL;
279         }
280 }
281
282 msg_error_t MsgDbHandler::bindText(const char *pBindStr, int index)
283 {
284         int ret = 0;
285
286         if (pBindStr != NULL)
287                 ret = sqlite3_bind_text(stmt, index, pBindStr, (strlen(pBindStr) + sizeof(unsigned char)), SQLITE_STATIC);
288
289         return ret;
290 }
291
292
293 msg_error_t MsgDbHandler::bindInt(const int pBindint, int index)
294 {
295         int ret = 0;
296
297         ret = sqlite3_bind_int(stmt, index, pBindint);
298
299         return ret;
300 }
301
302
303 msg_error_t MsgDbHandler::bindBlob(const void * pBindBlob, int size, int index)
304 {
305         int ret = 0;
306
307         ret = sqlite3_bind_blob(stmt, index, pBindBlob, size, SQLITE_STATIC);
308
309         return ret;
310 }
311
312
313 msg_error_t MsgDbHandler::prepareQuery(const char *pQuery)
314 {
315         int ret = 0;
316
317         stmt = NULL;
318
319         if(connect() != MSG_SUCCESS)
320                 return MSG_ERR_DB_DISCONNECT;
321
322         ret = sqlite3_prepare_v2(handle, pQuery, strlen(pQuery), &stmt, NULL);
323
324         if (ret == SQLITE_BUSY) {
325                 __clear_db_handle(handle);
326                 ret = sqlite3_prepare_v2(handle, pQuery, strlen(pQuery), &stmt, NULL);
327         }
328
329         if (ret == SQLITE_OK) {
330                 MSG_DEBUG("Prepare Query Success [%p]", stmt);
331                 return MSG_SUCCESS;
332         } else {
333                 MSG_ERR("Prepare Query Fail [%d]", ret);
334                 finalizeQuery();
335                 return MSG_ERR_DB_PREPARE;
336         }
337
338         return MSG_SUCCESS;
339 }
340
341
342 msg_error_t MsgDbHandler::stepQuery()
343 {
344         int ret = 0;
345
346         MSG_DEBUG("stepQuery for [%p]", stmt);
347         ret = sqlite3_step(stmt);
348
349         if (ret == SQLITE_ROW) {
350                 MSG_DEBUG("MsgStepQuery() SQLITE_ROW");
351                 return MSG_ERR_DB_ROW;
352         } else if (ret == SQLITE_DONE) {
353                 MSG_DEBUG("MsgStepQuery() SQLITE_DONE");
354                 return MSG_ERR_DB_DONE;
355         } else {
356                 MSG_ERR("MsgStepQuery() Fail [%d]", ret);
357                 finalizeQuery();
358                 return MSG_ERR_DB_STEP;
359         }
360
361         return MSG_SUCCESS;
362 }
363
364
365 void MsgDbHandler::resetQuery()
366 {
367         if (stmt) {
368                 sqlite3_clear_bindings(stmt);
369                 sqlite3_reset(stmt);
370         }
371 }
372
373
374 void MsgDbHandler::finalizeQuery()
375 {
376         if(stmt != NULL) {
377                 resetQuery();
378                 int ret = sqlite3_finalize(stmt);
379                 MSG_DEBUG("sqlite3_finalize = [%d]", ret);
380
381                 __clear_db_handle(handle);
382         }
383
384         stmt = NULL;
385
386         if (in_trans == false)
387                 disconnect();
388 }
389
390
391 int MsgDbHandler::columnInt(int ColumnIndex)
392 {
393         return sqlite3_column_int(stmt, ColumnIndex);
394 }
395
396
397 const unsigned char* MsgDbHandler::columnText(int ColumnIndex)
398 {
399         return sqlite3_column_text(stmt, ColumnIndex);
400 }
401
402
403 const void* MsgDbHandler::columnBlob(int ColumnIndex)
404 {
405         return sqlite3_column_blob(stmt, ColumnIndex);
406 }
407
408 void MsgDbHandler::getMmapMutex(const char *shm_file_name)
409 {
410         MSG_BEGIN();
411
412         if(!shm_file_name) {
413                 MSG_FATAL("NULL INPUT_PARAM");
414                 return;
415         }
416
417         MSG_DEBUG("** mapping begin **");
418
419          /*  open shm_file_name at first. Otherwise, the num of files in /proc/pid/fd will be increasing  */
420         shm_fd = shm_open(shm_file_name, O_RDWR, 0);
421         if (shm_fd == -1) {
422                 MSG_FATAL("shm_open error [%d]", errno);
423                 return;
424         }
425
426         pthread_mutex_t *tmp = (pthread_mutex_t *)mmap(NULL, sizeof(pthread_mutex_t), PROT_READ|PROT_WRITE, MAP_SHARED, shm_fd, 0);
427         if (tmp == MAP_FAILED) {
428                 MSG_FATAL("mmap error [%d]", errno);
429                 return;
430         }
431         mmapMx = tmp;
432 }
433
434 void MsgDbHandler::shm_mutex_timedlock(int sec)
435 {
436         MSG_BEGIN();
437         if (!mmapMx) {
438                 MSG_DEBUG("mmapMx not initd");
439                 return;
440         }
441
442         struct timespec abs_time;
443         clock_gettime(CLOCK_REALTIME, &abs_time);
444         abs_time.tv_sec += sec;
445
446         int err = pthread_mutex_timedlock(mmapMx, &abs_time);
447
448         if (err == EOWNERDEAD) {
449                 err = pthread_mutex_consistent(mmapMx);
450                 MSG_DEBUG("Previous owner is dead with lock. Fix mutex");
451         } else if (err != 0) {
452                 MSG_FATAL("pthread_mutex_timedlock error [%d]", errno);
453                 return;
454         }
455
456         MSG_END();
457 }
458
459 void MsgDbHandler::shm_mutex_unlock()
460 {
461         MSG_BEGIN();
462         if(!mmapMx) {
463                 MSG_DEBUG("mmapMx not initd");
464                 return;
465         }
466
467         pthread_mutex_unlock(mmapMx);
468         MSG_END();
469 }
470
471 msg_error_t MsgDbHandler::beginTrans()
472 {
473         int ret = 0;
474
475         if(connect() != MSG_SUCCESS)
476                 return MSG_ERR_DB_DISCONNECT;
477
478 #if 0
479         if (!mmapMx) {
480                 getMmapMutex(SHM_FILE_FOR_DB_LOCK);
481         }
482         shm_mutex_timedlock(2);
483 #endif
484         ret = sqlite3_exec(handle, "BEGIN IMMEDIATE TRANSACTION;", 0, 0, NULL);
485
486         if (ret == SQLITE_OK) {
487                 MSG_DEBUG("Begin Transaction Success");
488                 in_trans = true;
489                 return MSG_SUCCESS;
490         } else {
491                 MSG_DEBUG("Begin Transaction Fail [%d]", ret);
492                 return MSG_ERR_DB_EXEC;
493         }
494
495         return MSG_SUCCESS;
496 }
497
498
499 msg_error_t MsgDbHandler::endTrans(bool Success)
500 {
501         int ret = 0;
502
503         if(connect() != MSG_SUCCESS)
504                 return MSG_ERR_DB_DISCONNECT;
505
506
507         if (Success) {
508                 ret = sqlite3_exec(handle, "COMMIT TRANSACTION;", 0, 0, NULL);
509         } else {
510                 ret = sqlite3_exec(handle, "ROLLBACK TRANSACTION;", 0, 0, NULL);
511         }
512 #if 0
513         shm_mutex_unlock();
514 #endif
515         if (ret == SQLITE_OK) {
516                 MSG_DEBUG("End Transaction Success");
517                 in_trans = false;
518                 disconnect();
519                 return MSG_SUCCESS;
520         } else {
521                 MSG_DEBUG("End Transaction Fail [%d]", ret);
522                 if (Success) endTrans(false);
523                 return MSG_ERR_DB_EXEC;
524         }
525
526         return MSG_SUCCESS;
527 }
528
529
530 int MsgDbHandler::getColumnToInt(int RowIndex)
531 {
532         char* pTemp = result[RowIndex];
533
534         int nTemp = 0;
535
536         if (pTemp == NULL) {
537                 return nTemp;
538         }
539
540         nTemp = (int)strtol(pTemp, (char**)NULL, 10);
541
542         return nTemp;
543 }
544
545
546 char MsgDbHandler::getColumnToChar(int RowIndex)
547 {
548         char* pTemp = result[RowIndex];
549
550         if (pTemp == NULL) {
551                 return '\0';
552         }
553
554         return *pTemp;
555 }
556
557
558 char *MsgDbHandler::getColumnToString(int RowIndex)
559 {
560         char* pTemp = result[RowIndex];
561
562         if (pTemp == NULL) {
563                 return NULL;
564         }
565
566         return pTemp;
567 }
568
569
570 void MsgDbHandler::getColumnToString(int RowIndex, int Length, char *pString)
571 {
572         char* pTemp = result[RowIndex];
573
574         if (pTemp == NULL) {
575                 return;
576         }
577
578         strncpy(pString, pTemp, Length);
579 }
580
581
582 msg_error_t MsgDbHandler::getRowId(const char *pTableName, unsigned int *pRowId)
583 {
584         int ret = 0, nRowId = 0, nRowCnt = 0;
585         char strQuery[256];
586
587         if (pTableName == NULL || pRowId == NULL)
588                 return MSG_ERR_INVALID_PARAMETER;
589
590         MSG_SEC_DEBUG("Table Name [%s]", pTableName);
591
592         memset(strQuery, 0x00, sizeof(strQuery));
593         snprintf(strQuery, sizeof(strQuery), "select max(rowid) from %s", pTableName);
594
595         ret = getTable(strQuery, &nRowCnt, NULL);
596
597         if (ret == SQLITE_OK) {
598                 nRowId = getColumnToInt(1);
599
600                 if ((nRowCnt <= 1) && (nRowId == 0))
601                         *pRowId = 1;
602                 else
603                         *pRowId = nRowId + 1;
604         } else {
605                 MSG_DEBUG("MsgGetRowId failed");
606                 *pRowId = 0;
607                 freeTable();
608                 return MSG_ERR_DB_GETTABLE;
609         }
610
611         freeTable();
612
613         MSG_DEBUG("Row ID [%d]", *pRowId);
614
615         return MSG_SUCCESS;
616 }
617
618
619 void MsgReleaseMemoryDB()
620 {
621         int freeSize = 0;
622
623         freeSize = sqlite3_release_memory(-1);
624
625         MSG_DEBUG("freed memory size (bytes) : [%d]", freeSize);
626 }
627
628
629 msg_error_t MsgConvertStrWithEscape(const char *input, char **output)
630 {
631         if (input == NULL || output == NULL || strlen(input) == 0) {
632                 MSG_DEBUG("MSG_ERR_INVALID_PARAMETER");
633                 return MSG_ERR_INVALID_PARAMETER;
634         }
635
636         int inputSize = 0;
637         int i = 0;
638         int j = 0;
639
640         inputSize = strlen(input);
641         MSG_DEBUG("Size of input string [%d]", inputSize);
642
643         char tmpStr[(inputSize*2)+3];
644         memset(tmpStr, 0x00, sizeof(tmpStr));
645
646         tmpStr[j++] = '%';
647
648         for(i = 0; i < inputSize; i++) {
649                 if (input[i] == '\'' || input[i] == '_' || input[i] == '%' || input[i] == '\\') {
650                         tmpStr[j++] = MSGFW_DB_ESCAPE_CHAR;
651                 }
652                 tmpStr[j++] = input[i];
653         }
654         tmpStr[j++] = '%';
655         tmpStr[j] = '\0';
656
657         *output = strdup(tmpStr);
658
659         return MSG_SUCCESS;
660 }
661
662 typedef std::map<pthread_t, MsgDbHandler*> dbMap_t;
663 dbMap_t gDbHandles;
664 MsgMutex mu;
665
666 MsgDbHandler *getDbHandle()
667 {
668         pthread_t self = pthread_self();
669         MsgDbHandler *tmp = NULL;
670
671         dbMap_t::iterator it = gDbHandles.find(self);
672         if (it == gDbHandles.end()) {
673                 MSG_DEBUG("New DB handle added.");
674                 MsgMutexLocker locker(mu);
675                 tmp = new MsgDbHandler();
676                 gDbHandles.insert(std::pair<pthread_t, MsgDbHandler*>(self, tmp));
677
678         } else {
679                 tmp = it->second;
680         }
681
682         return tmp;
683 }
684
685 void removeDbHandle()
686 {
687         pthread_t self = pthread_self();
688         MsgDbHandler *tmp = NULL;
689
690         dbMap_t::iterator it = gDbHandles.find(self);
691         if (it != gDbHandles.end()) {
692                 MsgMutexLocker locker(mu);
693                 tmp = it->second;
694                 delete tmp;
695                 gDbHandles.erase(it);
696         }
697 }
698
699
700 static int __msg_db_util_busyhandler(void *pData, int count)
701 {
702         if(20 - count > 0) {
703                 struct timespec time = {0, };
704                 time.tv_sec = 0;
705                 time.tv_nsec = (count + 1) * 50 * 1000 * 1000;
706
707                 MSG_DEBUG("Busy Handler Called! : PID(%d) / CNT(%d)\n", getpid(), count+1);
708                 nanosleep(&time, NULL);
709                 return 1;
710         } else {
711                 MSG_WARN("Busy Handler will be returned SQLITE_BUSY error : PID(%d) \n", getpid());
712                 return 0;
713         }
714 }
715
716 int __msg_db_util_open(const char *pszFilePath, sqlite3 **ppDB, int flags, const char *zVfs)
717 {
718         if((pszFilePath == NULL) || (ppDB == NULL)) {
719                 MSG_WARN("sqlite3 handle null error");
720                 return SQLITE_ERROR;
721         }
722
723         if((geteuid() != 0) && (access(pszFilePath, R_OK))) {
724                 if(errno == EACCES) {
725                         MSG_ERR("file access permission error");
726                         return SQLITE_PERM;
727                 }
728         }
729
730         /* Open DB */
731         int rc = sqlite3_open_v2(pszFilePath, ppDB, flags, zVfs);
732         if (SQLITE_OK != rc) {
733                 MSG_ERR("sqlite3_open_v2 error(%d)", rc);
734                 return rc;
735         }
736
737         rc = sqlite3_busy_handler(*ppDB, __msg_db_util_busyhandler, NULL);
738         if (SQLITE_OK != rc) {
739                 MSG_WARN("Fail to register busy handler\n");
740                 sqlite3_close(*ppDB);
741         }
742
743         return rc;
744 }
745
746
747 int __msg_db_util_close(sqlite3 *pDB)
748 {
749         if (pDB == NULL) {
750                 MSG_WARN("sqlite3 handle null error");
751                 return SQLITE_ERROR;
752         }
753
754         /* Close DB */
755         int rc = sqlite3_close(pDB);
756         MSG_INFO("sqlite3_close error [%d]", rc);
757
758         if (rc == SQLITE_BUSY) {
759                 __clear_db_handle(pDB);
760                 rc = sqlite3_close(pDB);
761         }
762
763         if (SQLITE_OK != rc) {
764                 MSG_ERR("sqlite3_close error [%d]", rc);
765                 return rc;
766         }
767
768         return 0;
769 }
770
771
772 void __clear_db_handle(sqlite3 *pDB)
773 {
774         if (pDB == NULL) {
775                 MSG_WARN("sqlite3 handle null error");
776                 return;
777         }
778
779         int rc = 0;
780
781         sqlite3_stmt *pStmt;
782         while ((pStmt = sqlite3_next_stmt(pDB, NULL)) != NULL) {
783                 MSG_INFO("sqlite3_next_stmt [%s]", sqlite3_sql(pStmt));
784                 rc = sqlite3_finalize(pStmt);
785                 MSG_INFO("sqlite3_finalize [%d]", rc);
786         }
787 }