21cb34a7e7717991f34a03867552258a6b3d800f
[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         } else if (err != 0) {
450                 MSG_FATAL("pthread_mutex_timedlock error [%d]", errno);
451                 return;
452         }
453
454         MSG_END();
455 }
456
457 void MsgDbHandler::shm_mutex_unlock()
458 {
459         MSG_BEGIN();
460         if(!mmapMx) {
461                 MSG_DEBUG("mmapMx not initd");
462                 return;
463         }
464
465         pthread_mutex_unlock(mmapMx);
466         MSG_END();
467 }
468
469 msg_error_t MsgDbHandler::beginTrans()
470 {
471         int ret = 0;
472
473         if(connect() != MSG_SUCCESS)
474                 return MSG_ERR_DB_DISCONNECT;
475
476 #if 0
477         if (!mmapMx) {
478                 getMmapMutex(SHM_FILE_FOR_DB_LOCK);
479         }
480         shm_mutex_timedlock(2);
481 #endif
482         ret = sqlite3_exec(handle, "BEGIN IMMEDIATE TRANSACTION;", 0, 0, NULL);
483
484         if (ret == SQLITE_OK) {
485                 MSG_DEBUG("Begin Transaction Success");
486                 in_trans = true;
487                 return MSG_SUCCESS;
488         } else {
489                 MSG_DEBUG("Begin Transaction Fail [%d]", ret);
490                 return MSG_ERR_DB_EXEC;
491         }
492
493         return MSG_SUCCESS;
494 }
495
496
497 msg_error_t MsgDbHandler::endTrans(bool Success)
498 {
499         int ret = 0;
500
501         if(connect() != MSG_SUCCESS)
502                 return MSG_ERR_DB_DISCONNECT;
503
504
505         if (Success) {
506                 ret = sqlite3_exec(handle, "COMMIT TRANSACTION;", 0, 0, NULL);
507         } else {
508                 ret = sqlite3_exec(handle, "ROLLBACK TRANSACTION;", 0, 0, NULL);
509         }
510 #if 0
511         shm_mutex_unlock();
512 #endif
513         if (ret == SQLITE_OK) {
514                 MSG_DEBUG("End Transaction Success");
515                 in_trans = false;
516                 disconnect();
517                 return MSG_SUCCESS;
518         } else {
519                 MSG_DEBUG("End Transaction Fail [%d]", ret);
520                 if (Success) endTrans(false);
521                 return MSG_ERR_DB_EXEC;
522         }
523
524         return MSG_SUCCESS;
525 }
526
527
528 int MsgDbHandler::getColumnToInt(int RowIndex)
529 {
530         char* pTemp = result[RowIndex];
531
532         int nTemp = 0;
533
534         if (pTemp == NULL) {
535                 return nTemp;
536         }
537
538         nTemp = (int)strtol(pTemp, (char**)NULL, 10);
539
540         return nTemp;
541 }
542
543
544 char MsgDbHandler::getColumnToChar(int RowIndex)
545 {
546         char* pTemp = result[RowIndex];
547
548         if (pTemp == NULL) {
549                 return '\0';
550         }
551
552         return *pTemp;
553 }
554
555
556 char *MsgDbHandler::getColumnToString(int RowIndex)
557 {
558         char* pTemp = result[RowIndex];
559
560         if (pTemp == NULL) {
561                 return NULL;
562         }
563
564         return pTemp;
565 }
566
567
568 void MsgDbHandler::getColumnToString(int RowIndex, int Length, char *pString)
569 {
570         char* pTemp = result[RowIndex];
571
572         if (pTemp == NULL) {
573                 return;
574         }
575
576         strncpy(pString, pTemp, Length);
577 }
578
579
580 msg_error_t MsgDbHandler::getRowId(const char *pTableName, unsigned int *pRowId)
581 {
582         int ret = 0, nRowId = 0, nRowCnt = 0;
583         char strQuery[256];
584
585         if (pTableName == NULL || pRowId == NULL)
586                 return MSG_ERR_INVALID_PARAMETER;
587
588         MSG_SEC_DEBUG("Table Name [%s]", pTableName);
589
590         memset(strQuery, 0x00, sizeof(strQuery));
591         snprintf(strQuery, sizeof(strQuery), "select max(rowid) from %s", pTableName);
592
593         ret = getTable(strQuery, &nRowCnt, NULL);
594
595         if (ret == SQLITE_OK) {
596                 nRowId = getColumnToInt(1);
597
598                 if ((nRowCnt <= 1) && (nRowId == 0))
599                         *pRowId = 1;
600                 else
601                         *pRowId = nRowId + 1;
602         } else {
603                 MSG_DEBUG("MsgGetRowId failed");
604                 *pRowId = 0;
605                 freeTable();
606                 return MSG_ERR_DB_GETTABLE;
607         }
608
609         freeTable();
610
611         MSG_DEBUG("Row ID [%d]", *pRowId);
612
613         return MSG_SUCCESS;
614 }
615
616
617 void MsgReleaseMemoryDB()
618 {
619         int freeSize = 0;
620
621         freeSize = sqlite3_release_memory(-1);
622
623         MSG_DEBUG("freed memory size (bytes) : [%d]", freeSize);
624 }
625
626
627 msg_error_t MsgConvertStrWithEscape(const char *input, char **output)
628 {
629         if (input == NULL || output == NULL || strlen(input) == 0) {
630                 MSG_DEBUG("MSG_ERR_INVALID_PARAMETER");
631                 return MSG_ERR_INVALID_PARAMETER;
632         }
633
634         int inputSize = 0;
635         int i = 0;
636         int j = 0;
637
638         inputSize = strlen(input);
639         MSG_DEBUG("Size of input string [%d]", inputSize);
640
641         char tmpStr[(inputSize*2)+3];
642         memset(tmpStr, 0x00, sizeof(tmpStr));
643
644         tmpStr[j++] = '%';
645
646         for(i = 0; i < inputSize; i++) {
647                 if (input[i] == '\'' || input[i] == '_' || input[i] == '%' || input[i] == '\\') {
648                         tmpStr[j++] = MSGFW_DB_ESCAPE_CHAR;
649                 }
650                 tmpStr[j++] = input[i];
651         }
652         tmpStr[j++] = '%';
653         tmpStr[j] = '\0';
654
655         *output = strdup(tmpStr);
656
657         return MSG_SUCCESS;
658 }
659
660 typedef std::map<pthread_t, MsgDbHandler*> dbMap_t;
661 dbMap_t gDbHandles;
662 MsgMutex mu;
663
664 MsgDbHandler *getDbHandle()
665 {
666         pthread_t self = pthread_self();
667         MsgDbHandler *tmp = NULL;
668
669         dbMap_t::iterator it = gDbHandles.find(self);
670         if (it == gDbHandles.end()) {
671                 MSG_DEBUG("New DB handle added.");
672                 MsgMutexLocker locker(mu);
673                 tmp = new MsgDbHandler();
674                 gDbHandles.insert(std::pair<pthread_t, MsgDbHandler*>(self, tmp));
675
676         } else {
677                 tmp = it->second;
678         }
679
680         return tmp;
681 }
682
683 void removeDbHandle()
684 {
685         pthread_t self = pthread_self();
686         MsgDbHandler *tmp = NULL;
687
688         dbMap_t::iterator it = gDbHandles.find(self);
689         if (it != gDbHandles.end()) {
690                 MsgMutexLocker locker(mu);
691                 tmp = it->second;
692                 delete tmp;
693                 gDbHandles.erase(it);
694         }
695 }
696
697
698 static int __msg_db_util_busyhandler(void *pData, int count)
699 {
700         if(20 - count > 0) {
701                 struct timespec time = {0, };
702                 time.tv_sec = 0;
703                 time.tv_nsec = (count + 1) * 50 * 1000 * 1000;
704
705                 MSG_DEBUG("Busy Handler Called! : PID(%d) / CNT(%d)\n", getpid(), count+1);
706                 nanosleep(&time, NULL);
707                 return 1;
708         } else {
709                 MSG_WARN("Busy Handler will be returned SQLITE_BUSY error : PID(%d) \n", getpid());
710                 return 0;
711         }
712 }
713
714 int __msg_db_util_open(const char *pszFilePath, sqlite3 **ppDB, int flags, const char *zVfs)
715 {
716         if((pszFilePath == NULL) || (ppDB == NULL)) {
717                 MSG_WARN("sqlite3 handle null error");
718                 return SQLITE_ERROR;
719         }
720
721         if((geteuid() != 0) && (access(pszFilePath, R_OK))) {
722                 if(errno == EACCES) {
723                         MSG_ERR("file access permission error");
724                         return SQLITE_PERM;
725                 }
726         }
727
728         /* Open DB */
729         int rc = sqlite3_open_v2(pszFilePath, ppDB, flags, zVfs);
730         if (SQLITE_OK != rc) {
731                 MSG_ERR("sqlite3_open_v2 error(%d)", rc);
732                 return rc;
733         }
734
735         rc = sqlite3_busy_handler(*ppDB, __msg_db_util_busyhandler, NULL);
736         if (SQLITE_OK != rc) {
737                 MSG_WARN("Fail to register busy handler\n");
738                 sqlite3_close(*ppDB);
739         }
740
741         return rc;
742 }
743
744
745 int __msg_db_util_close(sqlite3 *pDB)
746 {
747         if (pDB == NULL) {
748                 MSG_WARN("sqlite3 handle null error");
749                 return SQLITE_ERROR;
750         }
751
752         /* Close DB */
753         int rc = sqlite3_close(pDB);
754         MSG_INFO("sqlite3_close error [%d]", rc);
755
756         if (rc == SQLITE_BUSY) {
757                 __clear_db_handle(pDB);
758                 rc = sqlite3_close(pDB);
759         }
760
761         if (SQLITE_OK != rc) {
762                 MSG_ERR("sqlite3_close error [%d]", rc);
763                 return rc;
764         }
765
766         return 0;
767 }
768
769
770 void __clear_db_handle(sqlite3 *pDB)
771 {
772         if (pDB == NULL) {
773                 MSG_WARN("sqlite3 handle null error");
774                 return;
775         }
776
777         int rc = 0;
778
779         sqlite3_stmt *pStmt;
780         while ((pStmt = sqlite3_next_stmt(pDB, NULL)) != NULL) {
781                 MSG_INFO("sqlite3_next_stmt [%s]", sqlite3_sql(pStmt));
782                 rc = sqlite3_finalize(pStmt);
783                 MSG_INFO("sqlite3_finalize [%d]", rc);
784         }
785 }