Flora license update
[apps/osp/Home.git] / src / HmGenericDatabaseManager.cpp
1 //
2 // Copyright (c) 2012 Samsung Electronics Co., Ltd.
3 //
4 // Licensed under the Flora License, Version 1.1 (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://floralicense.org/license/
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 /**
18  * @file        HmGenericDatabaseManager.cpp
19  * @brief       Keeps the Implementation of GenericDatabaseManager and related interfaces
20  * declaration of the various functions which may be needed for various database operations
21  */
22
23 #include <cstdlib>
24 #include "HmGenericDatabaseManager.h"
25 #include "HmTypes.h"
26
27 using namespace Tizen::Base;
28 using namespace Tizen::Base::Collection;
29 using namespace Tizen::Io;
30
31 GenericDatabaseManager* GenericDatabaseManager::__pDatabaseManager = null;
32
33 void
34 GenericDatabaseManager::DestroyInstance(void)
35 {
36         if (__pDatabaseManager != null)
37         {
38                 delete __pDatabaseManager;
39                 __pDatabaseManager = null;
40         }
41 }
42
43 GenericDatabaseManager*
44 GenericDatabaseManager::GetInstance(void)
45 {
46         if (__pDatabaseManager == null)
47         {
48                 CreateInstance();
49         }
50         return __pDatabaseManager;
51 }
52
53 result
54 GenericDatabaseManager::CreateDataBase(const String& databaseName)
55 {
56         result r = E_INVALID_ARG;
57         String folderName(databaseName);
58         int indexOfDirectory = 0;
59         //Santiy test
60         TryReturn(!databaseName.IsEmpty(), r, "Invalid argument passed");
61
62         if (__pDatabase != null)
63         {
64                 if (__pDatabase->GetName().Equals(databaseName, true))
65                 {
66                         return E_SUCCESS;
67                 }
68                 else
69                 {
70                         delete __pDatabase;
71                         __pDatabase = null;
72                 }
73         }
74
75         folderName.LastIndexOf(L'/', databaseName.GetLength() - 1, indexOfDirectory);
76         folderName.Remove(indexOfDirectory, (folderName.GetLength() - indexOfDirectory));
77         Directory::Create(folderName, true);
78         __pDatabase = new (std::nothrow) Database();
79         TryReturn(__pDatabase != null, E_OUT_OF_MEMORY, "unable to allocate memory for Database");
80         r = __pDatabase->Construct(databaseName, "a+");
81         TryCatch(r == E_SUCCESS, , "__pDatabase->Construct(databaseName, a+) failed with error %s", GetErrorMessage(r));
82
83         return r;
84
85 CATCH:
86
87         if (__pDatabase != null)
88         {
89                 delete __pDatabase;
90                 __pDatabase = null;
91         }
92
93         return r;
94 }
95
96 result
97 GenericDatabaseManager::CreateTable(const String& tableName, ArrayList* pColumnNames, ArrayList* pColumnTypes)
98 {
99         result r = E_INVALID_ARG;
100
101         TryReturn((!tableName.IsEmpty() || pColumnNames != null || pColumnTypes != null), r, "Invalid arguments");
102
103         if (__pDatabase != null)
104         {
105                 String queryText(CREATE_TABLE);
106                 queryText.Append(tableName);
107                 queryText.Append(L"(");
108
109                 for (int paramCount = 0; paramCount < pColumnNames->GetCount(); paramCount++)
110                 {
111                         String* name = static_cast<String*>(pColumnNames->GetAt(paramCount));
112                         String* type = static_cast<String*>(pColumnTypes->GetAt(paramCount));
113
114                         queryText.Append(*name);
115                         queryText.Append(L" ");
116                         queryText.Append(*type);
117
118                         if (paramCount == pColumnNames->GetCount() - 1)
119                         {
120                                 queryText.Append(L")");
121                         }
122                         else
123                         {
124                                 queryText.Append(L",");
125                         }
126                 }
127
128                 r = __pDatabase->BeginTransaction();
129
130                 if (r == E_SUCCESS)
131                 {
132                         r = __pDatabase->ExecuteSql(queryText, true);
133
134                         if (IsFailed(r))
135                         {
136                                 __pDatabase->RollbackTransaction();
137                         }
138                         TryReturn(r == E_SUCCESS, r,
139                                           "__pDatabase->ExecuteSql(queryStr, true) failed %s", GetErrorMessage(r));
140                         r = __pDatabase->CommitTransaction();
141                         TryReturn(r == E_SUCCESS, r,
142                                           "__pDatabase->CommitTransaction() failed %s", GetErrorMessage(r));
143                 }
144         }
145         return r;
146 }
147
148 result
149 GenericDatabaseManager::DeleteFromTable(const String& tableName, const String& whereCondition)
150 {
151         result r = E_INVALID_ARG;
152         //sanity test
153         TryReturn(!tableName.IsEmpty() || !whereCondition.IsEmpty(), r, "Invalid argument passed");
154         String query(DELETE_TABLE);
155         query.Append(tableName);
156         query.Append(L" ");
157         query.Append(L"WHERE ");
158         query.Append(whereCondition);
159
160         if (__pDatabase != null)
161         {
162                 __pDatabase->BeginTransaction();
163                 r = __pDatabase->ExecuteSql(query, true);
164
165                 if (IsFailed(r))
166                 {
167                         AppLogException("__pDatabase->ExecuteSql(query,true); returned with %s", GetErrorMessage(r));
168                         __pDatabase->RollbackTransaction();
169                 }
170                 else
171                 {
172                         __pDatabase->CommitTransaction();
173                 }
174         }
175         return r;
176 }
177
178 result
179 GenericDatabaseManager::GetDataRowFromTable(const String& tableName, const String& whereCondition, Collection::HashMap& rowDataHashMap)
180 {
181         result r = E_SUCCESS;
182         // Prepare Column info
183         DbEnumerator* pDbEnumerator = null;
184         String query = SELECT_TABLE;
185
186         query.Append(tableName);
187         query.Append(L" ");
188         query.Append(L"WHERE ");
189         query.Append(whereCondition);
190         pDbEnumerator = __pDatabase->QueryN(query);
191
192         if (pDbEnumerator == null)
193         {
194                 AppLogException("GetDataRowFromTable returning error %s", GetErrorMessage(GetLastResult()));
195                 return GetLastResult();
196         }
197
198         pDbEnumerator->MoveNext();
199
200         for (int paramCount = 0; paramCount < pDbEnumerator->GetColumnCount(); paramCount++)
201         {
202                 Object* pValue = null;
203                 DbColumnType columnType = pDbEnumerator->GetColumnType(paramCount);
204                 String* pColumnName = null;
205
206                 if (columnType == DB_COLUMNTYPE_INT)
207                 {
208                         int tempIntVal = 0;
209                         r = pDbEnumerator->GetIntAt(paramCount, tempIntVal);
210 //                      TryContinue(retVal, pValue,
211 //                                      "pDbEnumerator->GetIntAt failed with error %s",GetErrorMessage(retVal));
212                         pValue = new (std::nothrow) Integer(tempIntVal);
213
214                         if (pValue == null)
215                         {
216                                 continue;
217                         }
218                 }
219                 else if (columnType == DB_COLUMNTYPE_INT64)
220                 {
221                         long long tempLongVal = 0;
222                         r = pDbEnumerator->GetInt64At(paramCount, tempLongVal);
223 //                      TryContinue(retVal, pLongValue,
224 //                                      "pDbEnumerator->GetInt64At failed with error %s",GetErrorMessage(retVal));
225                         pValue = new (std::nothrow) LongLong(tempLongVal);
226
227                         if (pValue == null)
228                         {
229                                 continue;
230                         }
231                 }
232                 else if (columnType == DB_COLUMNTYPE_DOUBLE)
233                 {
234                         double tempDoubleVal;
235                         r = pDbEnumerator->GetDoubleAt(paramCount, tempDoubleVal);
236 //                      TryContinue(retVal, pDoubleValue,
237 //                                      "pDbEnumerator->GetDoubleAt failed with error %s",GetErrorMessage(retVal));
238                         pValue = new (std::nothrow) Double(tempDoubleVal);
239
240                         if (pValue == null)
241                         {
242                                 continue;
243                         }
244
245                 }
246                 else if (columnType == DB_COLUMNTYPE_TEXT)
247                 {
248                         String* pTextValue = new (std::nothrow) String();
249
250                         if (pTextValue == null)
251                         {
252                                 continue;
253                         }
254                         r = pDbEnumerator->GetStringAt(paramCount, *pTextValue);
255
256                         if (IsFailed(r))
257                         {
258                                 delete pTextValue;
259                                 pTextValue = null;
260                                 continue;
261                         }
262                         pValue = pTextValue;
263                 }
264                 else if (columnType == DB_COLUMNTYPE_BLOB)
265                 {
266                         ByteBuffer* pBlobValue = new (std::nothrow) ByteBuffer();
267
268                         if (pBlobValue == null)
269                         {
270                                 continue;
271                         }
272
273                         r = pDbEnumerator->GetBlobAt(paramCount, *pBlobValue);
274
275                         if (IsFailed(r))
276                         {
277                                 delete pBlobValue;
278                                 pBlobValue = null;
279                                 continue;
280                         }
281
282                         pValue = pBlobValue;
283                 }
284
285                 if (pValue != null)
286                 {
287                         pColumnName = new (std::nothrow) String(pDbEnumerator->GetColumnName(paramCount));
288
289                         if (pColumnName == null)
290                         {
291                                 delete pValue;
292                                 pValue = null;
293                                 r = E_OUT_OF_MEMORY;
294                                 continue;
295                         }
296
297                         r = rowDataHashMap.Add(pColumnName, pValue);
298                 }
299         }
300
301         delete pDbEnumerator;
302         pDbEnumerator = null;
303
304         return r;
305 }
306
307 int
308 GenericDatabaseManager::GetLastAddedRowID(const String& tableName)
309 {
310         int rowId = -1;
311         TryReturn(!tableName.IsEmpty(), E_INVALID_ARG, "Invalid arguments");
312
313         if (__pDatabase != null)
314         {
315                 String query = GET_LAST_RECORD_ID;
316                 DbEnumerator* pDbEnumerator = null;
317                 query.Append(tableName);
318                 pDbEnumerator = __pDatabase->QueryN(query);
319
320                 if (pDbEnumerator != null)
321                 {
322                         while (pDbEnumerator->MoveNext() == E_SUCCESS)
323                         {
324                                 for (int paramCount = 0; paramCount < pDbEnumerator->GetColumnCount(); paramCount++)
325                                 {
326                                         DbColumnType columnType = pDbEnumerator->GetColumnType(paramCount);
327
328                                         if (columnType == DB_COLUMNTYPE_INT)
329                                         {
330                                                 pDbEnumerator->GetIntAt(paramCount, rowId);
331                                                 break;
332                                         }
333                                 }
334                         }
335
336                         delete pDbEnumerator;
337                         pDbEnumerator = null;
338                 }
339         }
340
341         return rowId;
342 }
343
344 result
345 GenericDatabaseManager::InsertToTable(const String& tableName, ArrayList* pColumnNames, ArrayList* pColumnTypes, ArrayList* pColumnValues)
346 {
347         result r = E_SUCCESS;
348         TryReturn((!tableName.IsEmpty() || pColumnNames != null || pColumnValues != null), E_INVALID_ARG, "Invalid arguments");
349
350         if (__pDatabase != null)
351         {
352                 DbEnumerator* pDbEnum = null;
353                 DbStatement* pDbStatement = null;
354                 String query(INSERT_TABLE);
355                 query.Append(tableName);
356                 query.Append(L"(");
357                 //Prepare Transaction
358                 r = __pDatabase->BeginTransaction();
359
360                 if (r == E_SUCCESS)
361                 {
362                         for (int paramCount = 0; paramCount < pColumnNames->GetCount(); paramCount++)
363                         {
364                                 String* name = static_cast<String*>(pColumnNames->GetAt(paramCount));
365                                 query.Append(*name);
366
367                                 if (paramCount == pColumnNames->GetCount() - 1)
368                                 {
369                                         query.Append(L")");
370                                 }
371                                 else
372                                 {
373                                         query.Append(L",");
374                                 }
375                         }
376
377                         query.Append(L" ");
378                         query.Append(L"VALUES");
379                         query.Append(L" (");
380
381                         for (int paramCount = 0; paramCount < pColumnValues->GetCount(); paramCount++)
382                         {
383                                 query.Append(L" ? ");
384
385                                 if (paramCount == pColumnNames->GetCount() - 1)
386                                 {
387                                         query.Append(L")");
388                                 }
389                                 else
390                                 {
391                                         query.Append(L",");
392                                 }
393                         }
394
395                         pDbStatement = __pDatabase->CreateStatementN(query);
396
397                         if (pDbStatement != null)
398                         {
399                                 for (int colIndex = 0; colIndex < pColumnValues->GetCount(); colIndex++)
400                                 {
401
402                                         Integer* columnInttype = static_cast<Integer*>(pColumnTypes->GetAt(colIndex));
403
404                                         DbColumnType columnType = (DbColumnType) columnInttype->ToInt();
405
406                                         if (columnType == DB_COLUMNTYPE_INT)
407                                         {
408                                                 Integer* pIntValue = static_cast<Integer*>(pColumnValues->GetAt(colIndex));
409
410                                                 if (pIntValue != null && pIntValue->ToInt() == -1)
411                                                 {
412                                                         pDbStatement->BindNull(colIndex);
413                                                 }
414                                                 else
415                                                 {
416                                                         pDbStatement->BindInt(colIndex, pIntValue->ToInt());
417                                                 }
418                                         }
419                                         else if (columnType == DB_COLUMNTYPE_INT64)
420                                         {
421                                                 LongLong* pLongValue = static_cast<LongLong*>(pColumnValues->GetAt(colIndex));
422                                                 pDbStatement->BindInt64(colIndex, pLongValue->ToLong());
423                                         }
424                                         else if (columnType == DB_COLUMNTYPE_DOUBLE)
425                                         {
426                                                 Double* pDoubleValue = static_cast<Double*>(pColumnValues->GetAt(colIndex));
427                                                 pDbStatement->BindDouble(colIndex, pDoubleValue->ToDouble());
428                                         }
429                                         else if (columnType == DB_COLUMNTYPE_TEXT)
430                                         {
431                                                 String* pTextValue = static_cast<String*>(pColumnValues->GetAt(colIndex));
432                                                 pDbStatement->BindString(colIndex, *pTextValue);
433                                         }
434                                         else if (columnType == DB_COLUMNTYPE_BLOB)
435                                         {
436                                                 ByteBuffer* pBlobValue = static_cast<ByteBuffer*>(pColumnValues->GetAt(colIndex));
437                                                 pDbStatement->BindBlob(colIndex, *pBlobValue);
438                                         }
439                                         else
440                                         {
441                                                 continue;
442                                         }
443                                 }
444
445                                 pDbEnum = __pDatabase->ExecuteStatementN(*pDbStatement);
446
447                                 if (GetLastResult() == E_SUCCESS)
448                                 {
449                                         r = __pDatabase->CommitTransaction();
450                                 }
451                                 else
452                                 {
453                                         r = __pDatabase->RollbackTransaction();
454                                 }
455
456                                 if (IsFailed(r))
457                                 {
458                                         AppLogDebug("__pDatabase->CommitTransaction() failed result = %s", GetErrorMessage(r));
459                                         __pDatabase->RollbackTransaction();
460                                 }
461
462                                 if (pDbStatement != null)
463                                 {
464                                         delete pDbStatement;
465                                         pDbStatement = null;
466                                 }
467
468
469                                 if (pDbEnum != null)
470                                 {
471                                         delete pDbEnum;
472                                         pDbEnum = null;
473                                 }
474                         }
475                         else
476                         {
477                                 r = __pDatabase->RollbackTransaction();
478                         }
479                 }
480                 else
481                 {
482                         r = __pDatabase->RollbackTransaction();
483                 }
484         }
485         return r;
486
487 }
488
489 result
490 GenericDatabaseManager::UpdateTable(const String& tableName, ArrayList* pColumnsToModify, ArrayList* pColumnTypes, ArrayList* pColumnsNewData, const String* pWhereCondition)
491 {
492         TryReturn((!tableName.IsEmpty() || pColumnsToModify != null || pColumnsNewData != null || pWhereCondition != null), E_INVALID_ARG,
493                           "Invalid arguments");
494
495         result r = E_SUCCESS;
496         String query = UPDATE_TABLE;
497         query.Append(tableName);
498         query.Append(L" SET ");
499
500         for (int columnNumber = 0; columnNumber < pColumnsToModify->GetCount(); columnNumber++)
501         {
502                 String* pColName = static_cast<String*>(pColumnsToModify->GetAt(columnNumber));
503                 query.Append(*pColName);
504                 query.Append(L" = ");
505                 query.Append(L"?");
506
507                 if (columnNumber == pColumnsToModify->GetCount() - 1)
508                 {
509                         query.Append(L" ");
510                 }
511                 else
512                 {
513                         query.Append(L",");
514                 }
515         }
516
517         query.Append(L"WHERE ");
518         query.Append(*pWhereCondition);
519
520         if (__pDatabase != null)
521         {
522                 DbStatement* pDbStatement = null;
523
524                 r = __pDatabase->BeginTransaction();
525                 pDbStatement = __pDatabase->CreateStatementN(query);
526
527                 if (pDbStatement != null)
528                 {
529                         DbEnumerator* pDbEnum = null;
530
531                         for (int colIndex = 0; colIndex < pColumnsNewData->GetCount(); colIndex++)
532                         {
533                                 Integer* columnInttype = static_cast<Integer*>(pColumnTypes->GetAt(colIndex));
534
535                                 DbColumnType columnType = (DbColumnType) columnInttype->ToInt();
536
537
538                                 if (columnType == DB_COLUMNTYPE_INT)
539                                 {
540                                         Integer* pIntValue = static_cast<Integer*>(pColumnsNewData->GetAt(colIndex));
541                                         pDbStatement->BindInt(colIndex, pIntValue->ToInt());
542                                 }
543                                 else if (columnType == DB_COLUMNTYPE_INT64)
544                                 {
545                                         LongLong* pLongValue = static_cast<LongLong*>(pColumnsNewData->GetAt(colIndex));
546                                         pDbStatement->BindInt64(colIndex, pLongValue->ToLong());
547                                 }
548                                 else if (columnType == DB_COLUMNTYPE_DOUBLE)
549                                 {
550                                         Double* pDoubleValue = static_cast<Double*>(pColumnsNewData->GetAt(colIndex));
551                                         pDbStatement->BindDouble(colIndex, pDoubleValue->ToDouble());
552                                 }
553                                 else if (columnType == DB_COLUMNTYPE_TEXT)
554                                 {
555                                         String* pTextValue = static_cast<String*>(pColumnsNewData->GetAt(colIndex));
556                                         if (pTextValue != null)
557                                         {
558                                                 if (pTextValue->IsEmpty())
559                                                 {
560                                                         pDbStatement->BindNull(colIndex);
561                                                 }
562                                                 else
563                                                 {
564                                                         pDbStatement->BindString(colIndex, *pTextValue);
565                                                 }
566                                         }
567                                 }
568                                 else if (columnType == DB_COLUMNTYPE_BLOB)
569                                 {
570                                         ByteBuffer* pBlobValue = static_cast<ByteBuffer*>(pColumnsNewData->GetAt(colIndex));
571                                         pDbStatement->BindBlob(colIndex, *pBlobValue);
572                                 }
573                                 else
574                                 {
575                                         continue;
576                                 }
577                         }
578
579                         pDbEnum = __pDatabase->ExecuteStatementN(*pDbStatement);
580
581                         if (pDbEnum == null)
582                         {
583                                 r = GetLastResult();
584                                 AppLogException("__pDatabase->ExecuteStatementN returned error %s", GetErrorMessage(r));
585                         }
586
587                         if (!IsFailed(r))
588                         {
589                                 r = __pDatabase->CommitTransaction();
590                         }
591
592                         if (pDbEnum != null)
593                         {
594                                 if (pDbEnum->GetColumnCount() < 1)
595                                 {
596                                         r = E_SUCCESS;
597                                 }
598                                 delete pDbEnum;
599                                 pDbEnum = null;
600                         }
601                         if (pDbStatement != null)
602                         {
603                                 delete pDbStatement;
604                                 pDbStatement = null;
605                         }
606                 }
607                 else
608                 {
609                         r = GetLastResult();
610                         AppLogException("Create statement failed with error %s", GetErrorMessage(r));
611                         __pDatabase->RollbackTransaction();
612                 }
613
614
615         }
616         return r;
617 }
618
619 GenericDatabaseManager::GenericDatabaseManager(void)
620         : __pDatabase(null)
621 {
622         //no implementation required
623 }
624
625 GenericDatabaseManager::~GenericDatabaseManager(void)
626 {
627         if (__pDatabase != null)
628         {
629                 delete __pDatabase;
630         }
631 }
632
633 void
634 GenericDatabaseManager::CreateInstance(void)
635 {
636         __pDatabaseManager = new (std::nothrow) GenericDatabaseManager();
637
638         if (__pDatabaseManager != null)
639         {
640                 std::atexit(DestroyInstance);
641         }
642 }
643
644 DbColumnType
645 GenericDatabaseManager::GetColumnType(DbEnumerator* dbEnumerator, String* pColumnName)
646 {
647         TryReturn(dbEnumerator != null || pColumnName != null, DB_COLUMNTYPE_UNDEFINED, "Invalid parameters passed");
648
649         for (int columnNumber = 0; columnNumber < dbEnumerator->GetColumnCount(); columnNumber++)
650         {
651                 String colName = dbEnumerator->GetColumnName(columnNumber);
652
653                 if (pColumnName->Equals(colName, false))
654                 {
655                         return dbEnumerator->GetColumnType(columnNumber);
656                 }
657         }
658
659         return DB_COLUMNTYPE_UNDEFINED;
660 }
661
662 int
663 GenericDatabaseManager::GetColumnIndex(DbEnumerator* dbEnumerator, String* pColumnName)
664 {
665         TryReturn(dbEnumerator != null || pColumnName != null, -1, "Invalid parameters passed");
666
667         for (int columnNumber = 0; columnNumber < dbEnumerator->GetColumnCount(); columnNumber++)
668         {
669                 String columnName = dbEnumerator->GetColumnName(columnNumber);
670
671                 if (pColumnName->Equals(columnName, false))
672                 {
673                         return columnNumber;
674                 }
675         }
676
677         return -1;
678
679 }