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