Switch to sqlcipher library
[platform/core/security/key-manager.git] / src / manager / dpl / db / src / sql_connection.cpp
1 /*
2  * Copyright (c) 2014-2020 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  * @file        sql_connection.cpp
18  * @author      Przemyslaw Dobrowolski (p.dobrowolsk@samsung.com)
19  * @version     1.0
20  * @brief       This file is the implementation file of SQL connection
21  */
22 #pragma GCC diagnostic push
23 #pragma GCC diagnostic warning "-Wdeprecated-declarations"
24
25 #include <stddef.h>
26 #include <dpl/db/sql_connection.h>
27 #include <dpl/db/naive_synchronization_object.h>
28 #include <dpl/scoped_ptr.h>
29 #include <unistd.h>
30 #include <cassert>
31 #include <cstdio>
32 #include <cstdarg>
33 #include <memory>
34 #include <noncopyable.h>
35
36
37 namespace {
38 const int MAX_RETRY = 10;
39 }
40
41 namespace CKM {
42 namespace DB {
43 namespace { // anonymous
44 class ScopedNotifyAll {
45 private:
46         SqlConnection::SynchronizationObject *m_synchronizationObject;
47
48 public:
49         NONCOPYABLE(ScopedNotifyAll)
50
51         explicit ScopedNotifyAll(
52                 SqlConnection::SynchronizationObject *synchronizationObject) :
53                 m_synchronizationObject(synchronizationObject)
54         {
55         }
56
57         ~ScopedNotifyAll()
58         {
59                 if (!m_synchronizationObject)
60                         return;
61
62                 LogPedantic("Notifying after successful synchronize");
63                 m_synchronizationObject->NotifyAll();
64         }
65 };
66 } // namespace anonymous
67
68 SqlConnection::DataCommand::DataCommand(SqlConnection *connection,
69                                                                                 const char *buffer) :
70         m_masterConnection(connection),
71         m_stmt(NULL)
72 {
73         assert(connection != NULL);
74
75         // Notify all after potentially synchronized database connection access
76         ScopedNotifyAll notifyAll(connection->m_synchronizationObject.get());
77
78         for (int i = 0; i < MAX_RETRY; i++) {
79                 int ret = sqlite3_prepare_v2(connection->m_connection,
80                                                                                 buffer, strlen(buffer),
81                                                                                 &m_stmt, NULL);
82
83                 if (ret == SQLITE_OK) {
84                         LogPedantic("Prepared data command: " << buffer);
85
86                         // Increment stored data command count
87                         ++m_masterConnection->m_dataCommandsCount;
88                         return;
89                 } else if (ret == SQLITE_BUSY) {
90                         LogPedantic("Collision occurred while preparing SQL command");
91
92                         // Synchronize if synchronization object is available
93                         if (connection->m_synchronizationObject) {
94                                 LogPedantic("Performing synchronization");
95                                 connection->m_synchronizationObject->Synchronize();
96                                 continue;
97                         }
98
99                         // No synchronization object defined. Fail.
100                 }
101
102                 // Fatal error
103                 const char *error = sqlite3_errmsg(m_masterConnection->m_connection);
104
105                 LogError("SQL prepare data command failed");
106                 LogError("    Statement: " << buffer);
107                 LogError("    Error: " << error);
108
109                 ThrowMsg(Exception::SyntaxError, error);
110         }
111
112         LogError("sqlite in the state of possible infinite loop");
113         ThrowMsg(Exception::InternalError, "sqlite permanently busy");
114 }
115
116 SqlConnection::DataCommand::~DataCommand()
117 {
118         LogPedantic("SQL data command finalizing");
119
120         if (sqlite3_finalize(m_stmt) != SQLITE_OK)
121                 LogError("Failed to finalize data command");
122
123         // Decrement stored data command count
124         --m_masterConnection->m_dataCommandsCount;
125 }
126
127 void SqlConnection::DataCommand::CheckBindResult(int result)
128 {
129         if (result != SQLITE_OK) {
130                 const char *error = sqlite3_errmsg(
131                                                                 m_masterConnection->m_connection);
132
133                 LogError("Failed to bind SQL statement parameter");
134                 LogError("    Error: " << error);
135
136                 ThrowMsg(Exception::SyntaxError, error);
137         }
138 }
139
140 //LCOV_EXCL_START
141 void SqlConnection::DataCommand::BindNull(
142         SqlConnection::ArgumentIndex position)
143 {
144         CheckBindResult(sqlite3_bind_null(m_stmt, position));
145         LogPedantic("SQL data command bind null: ["
146                                 << position << "]");
147 }
148 //LCOV_EXCL_STOP
149
150 void SqlConnection::DataCommand::BindInteger(
151         SqlConnection::ArgumentIndex position,
152         int value)
153 {
154         CheckBindResult(sqlite3_bind_int(m_stmt, position, value));
155         LogPedantic("SQL data command bind integer: ["
156                                 << position << "] -> " << value);
157 }
158
159 //LCOV_EXCL_START
160 void SqlConnection::DataCommand::BindInt8(
161         SqlConnection::ArgumentIndex position,
162         int8_t value)
163 {
164         CheckBindResult(sqlite3_bind_int(m_stmt, position,
165                                                                                 static_cast<int>(value)));
166         LogPedantic("SQL data command bind int8: ["
167                                 << position << "] -> " << value);
168 }
169
170 void SqlConnection::DataCommand::BindInt16(
171         SqlConnection::ArgumentIndex position,
172         int16_t value)
173 {
174         CheckBindResult(sqlite3_bind_int(m_stmt, position,
175                                                                                 static_cast<int>(value)));
176         LogPedantic("SQL data command bind int16: ["
177                                 << position << "] -> " << value);
178 }
179
180 void SqlConnection::DataCommand::BindInt32(
181         SqlConnection::ArgumentIndex position,
182         int32_t value)
183 {
184         CheckBindResult(sqlite3_bind_int(m_stmt, position,
185                                                                                 static_cast<int>(value)));
186         LogPedantic("SQL data command bind int32: ["
187                                 << position << "] -> " << value);
188 }
189
190 void SqlConnection::DataCommand::BindInt64(
191         SqlConnection::ArgumentIndex position,
192         int64_t value)
193 {
194         CheckBindResult(sqlite3_bind_int64(m_stmt, position,
195                                                                                   static_cast<sqlite3_int64>(value)));
196         LogPedantic("SQL data command bind int64: ["
197                                 << position << "] -> " << value);
198 }
199
200 void SqlConnection::DataCommand::BindFloat(
201         SqlConnection::ArgumentIndex position,
202         float value)
203 {
204         CheckBindResult(sqlite3_bind_double(m_stmt, position,
205                                                                                    static_cast<double>(value)));
206         LogPedantic("SQL data command bind float: ["
207                                 << position << "] -> " << value);
208 }
209
210 void SqlConnection::DataCommand::BindDouble(
211         SqlConnection::ArgumentIndex position,
212         double value)
213 {
214         CheckBindResult(sqlite3_bind_double(m_stmt, position, value));
215         LogPedantic("SQL data command bind double: ["
216                                 << position << "] -> " << value);
217 }
218 //LCOV_EXCL_STOP
219
220 void SqlConnection::DataCommand::BindString(
221         SqlConnection::ArgumentIndex position,
222         const char *value)
223 {
224         if (!value) {
225                 BindNull(position);
226                 return;
227         }
228
229         // Assume that text may disappear
230         CheckBindResult(sqlite3_bind_text(m_stmt, position,
231                                                                                  value, strlen(value),
232                                                                                  SQLITE_TRANSIENT));
233
234         LogPedantic("SQL data command bind string: ["
235                                 << position << "] -> " << value);
236 }
237
238 void SqlConnection::DataCommand::BindBlob(
239         SqlConnection::ArgumentIndex position,
240         const RawBuffer &raw)
241 {
242         if (raw.size() == 0) {
243                 BindNull(position);
244                 return;
245         }
246
247         // Assume that blob may dissappear
248         CheckBindResult(sqlite3_bind_blob(m_stmt, position,
249                                                                                  raw.data(), raw.size(),
250                                                                                  SQLITE_TRANSIENT));
251         LogPedantic("SQL data command bind blob of size: ["
252                                 << position << "] -> " << raw.size());
253 }
254
255 //LCOV_EXCL_START
256 void SqlConnection::DataCommand::BindInteger(
257         SqlConnection::ArgumentIndex position,
258         const boost::optional<int> &value)
259 {
260         if (!value)
261                 BindNull(position);
262         else
263                 BindInteger(position, *value);
264 }
265
266 void SqlConnection::DataCommand::BindInt8(
267         SqlConnection::ArgumentIndex position,
268         const boost::optional<int8_t> &value)
269 {
270         if (!value)
271                 BindNull(position);
272         else
273                 BindInt8(position, *value);
274 }
275
276 void SqlConnection::DataCommand::BindInt16(
277         SqlConnection::ArgumentIndex position,
278         const boost::optional<int16_t> &value)
279 {
280         if (!value)
281                 BindNull(position);
282         else
283                 BindInt16(position, *value);
284 }
285
286 void SqlConnection::DataCommand::BindInt32(
287         SqlConnection::ArgumentIndex position,
288         const boost::optional<int32_t> &value)
289 {
290         if (!value)
291                 BindNull(position);
292         else
293                 BindInt32(position, *value);
294 }
295
296 void SqlConnection::DataCommand::BindInt64(
297         SqlConnection::ArgumentIndex position,
298         const boost::optional<int64_t> &value)
299 {
300         if (!value)
301                 BindNull(position);
302         else
303                 BindInt64(position, *value);
304 }
305
306 void SqlConnection::DataCommand::BindFloat(
307         SqlConnection::ArgumentIndex position,
308         const boost::optional<float> &value)
309 {
310         if (!value)
311                 BindNull(position);
312         else
313                 BindFloat(position, *value);
314 }
315
316 void SqlConnection::DataCommand::BindDouble(
317         SqlConnection::ArgumentIndex position,
318         const boost::optional<double> &value)
319 {
320         if (!value)
321                 BindNull(position);
322         else
323                 BindDouble(position, *value);
324 }
325
326 void SqlConnection::DataCommand::BindBlob(
327         SqlConnection::ArgumentIndex position,
328         const boost::optional<RawBuffer> &value)
329 {
330         if (!!value)
331                 BindBlob(position, *value);
332         else
333                 BindNull(position);
334 }
335 //LCOV_EXCL_STOP
336
337 bool SqlConnection::DataCommand::Step()
338 {
339         // Notify all after potentially synchronized database connection access
340         ScopedNotifyAll notifyAll(
341                 m_masterConnection->m_synchronizationObject.get());
342
343         for (int i = 0; i < MAX_RETRY; i++) {
344                 int ret = sqlite3_step(m_stmt);
345
346                 if (ret == SQLITE_ROW) {
347                         LogPedantic("SQL data command step ROW");
348                         return true;
349                 } else if (ret == SQLITE_DONE) {
350                         LogPedantic("SQL data command step DONE");
351                         return false;
352                 } else if (ret == SQLITE_BUSY) {
353                         LogPedantic("Collision occurred while executing SQL command");
354
355                         // Synchronize if synchronization object is available
356                         if (m_masterConnection->m_synchronizationObject) {
357                                 LogPedantic("Performing synchronization");
358
359                                 m_masterConnection->
360                                 m_synchronizationObject->Synchronize();
361
362                                 continue;
363                         }
364
365                         // No synchronization object defined. Fail.
366                 }
367
368                 // Fatal error
369                 const char *error = sqlite3_errmsg(m_masterConnection->m_connection);
370
371                 LogError("SQL step data command failed");
372                 LogError("    Error: " << error);
373
374                 ThrowMsg(Exception::InternalError, error);
375         }
376
377         LogError("sqlite in the state of possible infinite loop");
378         ThrowMsg(Exception::InternalError, "sqlite permanently busy");
379 }
380
381 void SqlConnection::DataCommand::Reset()
382 {
383         /*
384          * According to:
385          * http://www.sqllite.org/c3ref/stmt.html
386          *
387          * if last sqlite3_step command on this stmt returned an error,
388          * then sqlite3_reset will return that error, althought it is not an error.
389          * So sqlite3_reset allways succedes.
390          */
391         sqlite3_reset(m_stmt);
392
393         LogPedantic("SQL data command reset");
394 }
395
396 void SqlConnection::DataCommand::CheckColumnIndex(
397         SqlConnection::ColumnIndex column)
398 {
399         if (column < 0 || column >= sqlite3_column_count(m_stmt))
400                 ThrowMsg(Exception::InvalidColumn, "Column index is out of bounds");
401 }
402
403 //LCOV_EXCL_START
404 bool SqlConnection::DataCommand::IsColumnNull(
405         SqlConnection::ColumnIndex column)
406 {
407         LogPedantic("SQL data command get column type: [" << column << "]");
408         CheckColumnIndex(column);
409         return sqlite3_column_type(m_stmt, column) == SQLITE_NULL;
410 }
411 //LCOV_EXCL_STOP
412
413 int SqlConnection::DataCommand::GetColumnInteger(
414         SqlConnection::ColumnIndex column)
415 {
416         LogPedantic("SQL data command get column integer: [" << column << "]");
417         CheckColumnIndex(column);
418         int value = sqlite3_column_int(m_stmt, column);
419         LogPedantic("    Value: " << value);
420         return value;
421 }
422
423 //LCOV_EXCL_START
424 int8_t SqlConnection::DataCommand::GetColumnInt8(
425         SqlConnection::ColumnIndex column)
426 {
427         LogPedantic("SQL data command get column int8: [" << column << "]");
428         CheckColumnIndex(column);
429         int8_t value = static_cast<int8_t>(sqlite3_column_int(m_stmt, column));
430         LogPedantic("    Value: " << value);
431         return value;
432 }
433
434 int16_t SqlConnection::DataCommand::GetColumnInt16(
435         SqlConnection::ColumnIndex column)
436 {
437         LogPedantic("SQL data command get column int16: [" << column << "]");
438         CheckColumnIndex(column);
439         int16_t value = static_cast<int16_t>(sqlite3_column_int(m_stmt, column));
440         LogPedantic("    Value: " << value);
441         return value;
442 }
443
444 int32_t SqlConnection::DataCommand::GetColumnInt32(
445         SqlConnection::ColumnIndex column)
446 {
447         LogPedantic("SQL data command get column int32: [" << column << "]");
448         CheckColumnIndex(column);
449         int32_t value = static_cast<int32_t>(sqlite3_column_int(m_stmt, column));
450         LogPedantic("    Value: " << value);
451         return value;
452 }
453
454 int64_t SqlConnection::DataCommand::GetColumnInt64(
455         SqlConnection::ColumnIndex column)
456 {
457         LogPedantic("SQL data command get column int64: [" << column << "]");
458         CheckColumnIndex(column);
459         int64_t value = static_cast<int64_t>(sqlite3_column_int64(m_stmt, column));
460         LogPedantic("    Value: " << value);
461         return value;
462 }
463
464 float SqlConnection::DataCommand::GetColumnFloat(
465         SqlConnection::ColumnIndex column)
466 {
467         LogPedantic("SQL data command get column float: [" << column << "]");
468         CheckColumnIndex(column);
469         float value = static_cast<float>(sqlite3_column_double(m_stmt, column));
470         LogPedantic("    Value: " << value);
471         return value;
472 }
473
474 double SqlConnection::DataCommand::GetColumnDouble(
475         SqlConnection::ColumnIndex column)
476 {
477         LogPedantic("SQL data command get column double: [" << column << "]");
478         CheckColumnIndex(column);
479         double value = sqlite3_column_double(m_stmt, column);
480         LogPedantic("    Value: " << value);
481         return value;
482 }
483 //LCOV_EXCL_STOP
484
485 std::string SqlConnection::DataCommand::GetColumnString(
486         SqlConnection::ColumnIndex column)
487 {
488         LogPedantic("SQL data command get column string: [" << column << "]");
489         CheckColumnIndex(column);
490
491         const char *value = reinterpret_cast<const char *>(
492                                                         sqlite3_column_text(m_stmt, column));
493
494         LogPedantic("Value: " << (value ? value : "NULL"));
495
496         if (value == NULL)
497                 return std::string();
498
499         return std::string(value);
500 }
501
502 RawBuffer SqlConnection::DataCommand::GetColumnBlob(
503         SqlConnection::ColumnIndex column)
504 {
505         LogPedantic("SQL data command get column blog: [" << column << "]");
506         CheckColumnIndex(column);
507
508         const unsigned char *value = reinterpret_cast<const unsigned char *>(
509                                                                          sqlite3_column_blob(m_stmt, column));
510
511         if (value == NULL)
512                 return RawBuffer();
513
514         int length = sqlite3_column_bytes(m_stmt, column);
515         LogPedantic("Got blob of length: " << length);
516
517         return RawBuffer(value, value + length);
518 }
519
520 //LCOV_EXCL_START
521 boost::optional<int> SqlConnection::DataCommand::GetColumnOptionalInteger(
522         SqlConnection::ColumnIndex column)
523 {
524         LogPedantic("SQL data command get column optional integer: ["
525                                 << column << "]");
526         CheckColumnIndex(column);
527
528         if (sqlite3_column_type(m_stmt, column) == SQLITE_NULL)
529                 return boost::optional<int>();
530
531         int value = sqlite3_column_int(m_stmt, column);
532         LogPedantic("    Value: " << value);
533         return boost::optional<int>(value);
534 }
535
536 boost::optional<int8_t> SqlConnection::DataCommand::GetColumnOptionalInt8(
537         SqlConnection::ColumnIndex column)
538 {
539         LogPedantic("SQL data command get column optional int8: ["
540                                 << column << "]");
541         CheckColumnIndex(column);
542
543         if (sqlite3_column_type(m_stmt, column) == SQLITE_NULL)
544                 return boost::optional<int8_t>();
545
546         int8_t value = static_cast<int8_t>(sqlite3_column_int(m_stmt, column));
547         LogPedantic("    Value: " << value);
548         return boost::optional<int8_t>(value);
549 }
550
551 boost::optional<int16_t> SqlConnection::DataCommand::GetColumnOptionalInt16(
552         SqlConnection::ColumnIndex column)
553 {
554         LogPedantic("SQL data command get column optional int16: ["
555                                 << column << "]");
556         CheckColumnIndex(column);
557
558         if (sqlite3_column_type(m_stmt, column) == SQLITE_NULL)
559                 return boost::optional<int16_t>();
560
561         int16_t value = static_cast<int16_t>(sqlite3_column_int(m_stmt, column));
562         LogPedantic("    Value: " << value);
563         return boost::optional<int16_t>(value);
564 }
565
566 boost::optional<int32_t> SqlConnection::DataCommand::GetColumnOptionalInt32(
567         SqlConnection::ColumnIndex column)
568 {
569         LogPedantic("SQL data command get column optional int32: ["
570                                 << column << "]");
571         CheckColumnIndex(column);
572
573         if (sqlite3_column_type(m_stmt, column) == SQLITE_NULL)
574                 return boost::optional<int32_t>();
575
576         int32_t value = static_cast<int32_t>(sqlite3_column_int(m_stmt, column));
577         LogPedantic("    Value: " << value);
578         return boost::optional<int32_t>(value);
579 }
580
581 boost::optional<int64_t> SqlConnection::DataCommand::GetColumnOptionalInt64(
582         SqlConnection::ColumnIndex column)
583 {
584         LogPedantic("SQL data command get column optional int64: ["
585                                 << column << "]");
586         CheckColumnIndex(column);
587
588         if (sqlite3_column_type(m_stmt, column) == SQLITE_NULL)
589                 return boost::optional<int64_t>();
590
591         int64_t value = static_cast<int64_t>(sqlite3_column_int64(m_stmt, column));
592         LogPedantic("    Value: " << value);
593         return boost::optional<int64_t>(value);
594 }
595
596 boost::optional<float> SqlConnection::DataCommand::GetColumnOptionalFloat(
597         SqlConnection::ColumnIndex column)
598 {
599         LogPedantic("SQL data command get column optional float: ["
600                                 << column << "]");
601         CheckColumnIndex(column);
602
603         if (sqlite3_column_type(m_stmt, column) == SQLITE_NULL)
604                 return boost::optional<float>();
605
606         float value = static_cast<float>(sqlite3_column_double(m_stmt, column));
607         LogPedantic("    Value: " << value);
608         return boost::optional<float>(value);
609 }
610
611 boost::optional<double> SqlConnection::DataCommand::GetColumnOptionalDouble(
612         SqlConnection::ColumnIndex column)
613 {
614         LogPedantic("SQL data command get column optional double: ["
615                                 << column << "]");
616         CheckColumnIndex(column);
617
618         if (sqlite3_column_type(m_stmt, column) == SQLITE_NULL)
619                 return boost::optional<double>();
620
621         double value = sqlite3_column_double(m_stmt, column);
622         LogPedantic("    Value: " << value);
623         return boost::optional<double>(value);
624 }
625
626 boost::optional<RawBuffer> SqlConnection::DataCommand::GetColumnOptionalBlob(
627         SqlConnection::ColumnIndex column)
628 {
629         LogPedantic("SQL data command get column blog: [" << column << "]");
630         CheckColumnIndex(column);
631
632         if (sqlite3_column_type(m_stmt, column) == SQLITE_NULL)
633                 return boost::optional<RawBuffer>();
634
635         const unsigned char *value = reinterpret_cast<const unsigned char *>(
636                                                                          sqlite3_column_blob(m_stmt, column));
637
638         int length = sqlite3_column_bytes(m_stmt, column);
639         LogPedantic("Got blob of length: " << length);
640
641         RawBuffer temp(value, value + length);
642         return boost::optional<RawBuffer>(temp);
643 }
644 //LCOV_EXCL_STOP
645
646 void SqlConnection::Connect(const std::string &address,
647                                                         Flag::Option flag)
648 {
649         if (m_connection != NULL) {
650                 LogPedantic("Already connected.");
651                 return;
652         }
653
654         LogPedantic("Connecting to DB: " << address << "...");
655
656         // Connect to database
657         int result;
658         result = sqlite3_open_v2(
659                                  address.c_str(),
660                                  &m_connection,
661                                  flag,
662                                  NULL);
663
664         if (result == SQLITE_OK) {
665                 LogPedantic("Connected to DB");
666         } else {
667                 LogError("Failed to connect to DB!");
668                 ThrowMsg(Exception::ConnectionBroken, address);
669         }
670
671         // Enable foreign keys
672         TurnOnForeignKeys();
673 }
674
675 const std::string SQLITE_RAW_PREFIX = "x'";
676 const std::string SQLITE_RAW_SUFIX = "'";
677 const std::size_t SQLITE_RAW_DATA_SIZE = 32;
678
679 RawBuffer rawToHexString(const RawBuffer &raw)
680 {
681         return hexDump<RawBuffer, true>(raw);
682 }
683
684 RawBuffer createHexPass(const RawBuffer &rawPass)
685 {
686         // We are required to pass 64byte long hex password made out of 32byte raw
687         // binary data
688         RawBuffer output;
689         std::copy(SQLITE_RAW_PREFIX.begin(), SQLITE_RAW_PREFIX.end(),
690                           std::back_inserter(output));
691
692         RawBuffer password = rawToHexString(rawPass);
693
694         std::copy(password.begin(), password.end(),
695                           std::back_inserter(output));
696
697         std::copy(SQLITE_RAW_SUFIX.begin(), SQLITE_RAW_SUFIX.end(),
698                           std::back_inserter(output));
699
700         return output;
701 }
702
703 void SqlConnection::SetKey(const RawBuffer &rawPass)
704 {
705         if (m_connection == NULL) {
706                 LogPedantic("Cannot set key. No connection to DB!");
707                 return;
708         }
709
710         if (rawPass.size() != SQLITE_RAW_DATA_SIZE)
711                 ThrowMsg(Exception::InvalidArguments,
712                                  "Binary data for raw password should be 32 bytes long.");
713
714         RawBuffer pass = createHexPass(rawPass);
715         int result = sqlite3_key(m_connection, pass.data(), pass.size());
716
717         if (result == SQLITE_OK) {
718                 LogPedantic("Set key on DB");
719         } else {
720                 //sqlite3_key fails only when m_connection == NULL || key == NULL ||
721                 //                            key length == 0
722                 LogError("Failed to set key on DB");
723                 ThrowMsg(Exception::InvalidArguments, result);
724         }
725
726         m_isKeySet = true;
727 };
728
729 //LCOV_EXCL_START
730 void SqlConnection::ResetKey(const RawBuffer &rawPassOld,
731                                                          const RawBuffer &rawPassNew)
732 {
733         if (m_connection == NULL) {
734                 LogPedantic("Cannot reset key. No connection to DB!");
735                 return;
736         }
737
738         // Binary data for raw password should be 32 bytes long.
739         assert(rawPassOld.size() == SQLITE_RAW_DATA_SIZE &&
740                rawPassNew.size() == SQLITE_RAW_DATA_SIZE);
741
742         // sqlite3_rekey requires for key to be already set
743         if (!m_isKeySet)
744                 SetKey(rawPassOld);
745
746         RawBuffer pass = createHexPass(rawPassNew);
747         int result = sqlite3_rekey(m_connection, pass.data(), pass.size());
748
749         if (result == SQLITE_OK) {
750                 LogPedantic("Reset key on DB");
751         } else {
752                 //sqlite3_rekey fails only when m_connection == NULL || key == NULL ||
753                 //                              key length == 0
754                 LogError("Failed to reset key on DB");
755                 ThrowMsg(Exception::InvalidArguments, result);
756         }
757 }
758 //LCOV_EXCL_STOP
759
760 void SqlConnection::Disconnect()
761 {
762         if (m_connection == NULL) {
763                 LogPedantic("Already disconnected.");
764                 return;
765         }
766
767         LogPedantic("Disconnecting from DB...");
768
769         // All stored data commands must be deleted before disconnect
770         assert(m_dataCommandsCount == 0);
771
772         int result;
773
774         result = sqlite3_close(m_connection);
775
776         if (result != SQLITE_OK) {
777                 const char *error = sqlite3_errmsg(m_connection);
778                 LogError("SQL close failed");
779                 LogError("    Error: " << error);
780                 Throw(Exception::InternalError);
781         }
782
783         m_connection = NULL;
784
785         LogPedantic("Disconnected from DB");
786 }
787
788 bool SqlConnection::CheckTableExist(const char *tableName)
789 {
790         if (m_connection == NULL) {
791                 LogPedantic("Cannot execute command. Not connected to DB!");
792                 return false;
793         }
794
795         DataCommandUniquePtr command =
796                 PrepareDataCommand("select tbl_name from sqlite_master where name=?;");
797
798         command->BindString(1, tableName);
799
800         if (!command->Step()) {
801                 LogPedantic("No matching records in table");
802                 return false;
803         }
804
805         return command->GetColumnString(0) == tableName;
806 }
807
808 SqlConnection::SqlConnection(const std::string &address,
809                                                          Flag::Option option,
810                                                          SynchronizationObject *synchronizationObject) :
811         m_connection(NULL),
812         m_dataCommandsCount(0),
813         m_synchronizationObject(synchronizationObject),
814         m_isKeySet(false)
815 {
816         LogPedantic("Opening database connection to: " << address);
817
818         // Connect to DB
819         SqlConnection::Connect(address, option);
820
821         if (!m_synchronizationObject)
822                 LogPedantic("No synchronization object defined");
823 }
824
825 SqlConnection::~SqlConnection()
826 {
827         LogPedantic("Closing database connection");
828
829         // Disconnect from DB
830         try {
831                 SqlConnection::Disconnect();
832         } catch (const Exception::Base &) {
833                 LogError("Failed to disconnect from database");
834         }
835 }
836
837 //LCOV_EXCL_START
838 int SqlConnection::Output::Callback(void *param, int columns, char **values,
839                                                                         char **names)
840 {
841         if (param)
842                 static_cast<Output *>(param)->SetResults(columns, values, names);
843
844         return 0;
845 }
846
847 void SqlConnection::Output::SetResults(int columns, char **values, char **names)
848 {
849         if (m_names.empty()) {
850                 for (int i = 0; i < columns; i++)
851                         m_names.push_back(names[i] ? names[i] : "NULL");
852         }
853
854         Row row;
855
856         for (int i = 0; i < columns; i++)
857                 row.push_back(values[i] ? values[i] : "NULL");
858
859         m_values.push_back(std::move(row));
860 }
861 //LCOV_EXCL_STOP
862
863 void SqlConnection::ExecCommandHelper(Output *out, const char *format,
864                                                                           va_list args)
865 {
866         if (m_connection == NULL) {
867                 LogError("Cannot execute command. Not connected to DB!");
868                 return;
869         }
870
871         if (format == NULL) {
872                 LogError("Null query!");
873                 ThrowMsg(Exception::SyntaxError, "Null statement");
874         }
875
876         char *query;
877
878         if (vasprintf(&query, format, args) == -1) {
879                 LogError("Failed to allocate statement string");
880                 return;
881         }
882
883         CharUniquePtr queryPtr(query);
884
885         LogPedantic("Executing SQL command: " << queryPtr.get());
886
887         // Notify all after potentially synchronized database connection access
888         ScopedNotifyAll notifyAll(m_synchronizationObject.get());
889
890         for (int i = 0; i < MAX_RETRY; i++) {
891                 char *errorBuffer;
892                 int ret = sqlite3_exec(m_connection,
893                                                                   queryPtr.get(),
894                                                                   out ? &Output::Callback : NULL,
895                                                                   out,
896                                                                   &errorBuffer);
897
898                 std::string errorMsg;
899
900                 // Take allocated error buffer
901                 if (errorBuffer != NULL) {
902                         errorMsg = errorBuffer;
903                         sqlite3_free(errorBuffer);
904                 }
905
906                 if (ret == SQLITE_OK)
907                         return;
908
909                 if (ret == SQLITE_BUSY) {
910                         LogPedantic("Collision occurred while executing SQL command");
911
912                         // Synchronize if synchronization object is available
913                         if (m_synchronizationObject) {
914                                 LogPedantic("Performing synchronization");
915                                 m_synchronizationObject->Synchronize();
916                                 continue;
917                         }
918
919                         // No synchronization object defined. Fail.
920                 }
921
922                 // Fatal error
923                 LogError("Failed to execute SQL command. Error: " << errorMsg);
924                 ThrowMsg(Exception::SyntaxError, errorMsg);
925         }
926
927         LogError("sqlite in the state of possible infinite loop");
928         ThrowMsg(Exception::InternalError, "sqlite permanently busy");
929 }
930
931 //LCOV_EXCL_START
932 void SqlConnection::ExecCommand(Output *out, const char *format, ...)
933 {
934         va_list args;
935         va_start(args, format);
936         try {
937                 ExecCommandHelper(out, format, args);
938         } catch (...) {
939                 va_end(args);
940                 throw;
941         }
942         va_end(args);
943 }
944 //LCOV_EXCL_STOP
945
946 void SqlConnection::ExecCommand(const char *format, ...)
947 {
948         va_list args;
949         va_start(args, format);
950         try {
951                 ExecCommandHelper(NULL, format, args);
952         } catch (...) {
953                 va_end(args);
954                 throw;
955         }
956         va_end(args);
957 }
958
959 SqlConnection::DataCommandUniquePtr SqlConnection::PrepareDataCommand(
960         const char *format,
961         ...)
962 {
963         if (m_connection == NULL) {
964                 LogError("Cannot execute data command. Not connected to DB!");
965                 return DataCommandUniquePtr();
966         }
967
968         char *rawBuffer;
969
970         va_list args;
971         va_start(args, format);
972
973         if (vasprintf(&rawBuffer, format, args) == -1)
974                 rawBuffer = NULL;
975
976         va_end(args);
977
978         CharUniquePtr buffer(rawBuffer);
979
980         if (!buffer) {
981                 LogError("Failed to allocate statement string");
982                 return DataCommandUniquePtr();
983         }
984
985         LogPedantic("Executing SQL data command: " << buffer.get());
986
987         return DataCommandUniquePtr(new DataCommand(this, buffer.get()));
988 }
989
990 //LCOV_EXCL_START
991 SqlConnection::RowID SqlConnection::GetLastInsertRowID() const
992 {
993         return static_cast<RowID>(sqlite3_last_insert_rowid(m_connection));
994 }
995 //LCOV_EXCL_STOP
996
997 void SqlConnection::TurnOnForeignKeys()
998 {
999         ExecCommand("PRAGMA foreign_keys = ON;");
1000 }
1001
1002 void SqlConnection::BeginTransaction()
1003 {
1004         ExecCommand("BEGIN;");
1005 }
1006
1007 void SqlConnection::RollbackTransaction()
1008 {
1009         ExecCommand("ROLLBACK;");
1010 }
1011
1012 void SqlConnection::CommitTransaction()
1013 {
1014         ExecCommand("COMMIT;");
1015 }
1016
1017 SqlConnection::SynchronizationObject *
1018 SqlConnection::AllocDefaultSynchronizationObject()
1019 {
1020         return new NaiveSynchronizationObject();
1021 }
1022 } // namespace DB
1023 } // namespace CKM
1024
1025 #pragma GCC diagnostic pop