2 * Copyright (c) 2014-2020 Samsung Electronics Co., Ltd. All rights reserved
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 * @file sql_connection.cpp
18 * @author Przemyslaw Dobrowolski (p.dobrowolsk@samsung.com)
20 * @brief This file is the implementation file of SQL connection
22 #pragma GCC diagnostic push
23 #pragma GCC diagnostic warning "-Wdeprecated-declarations"
26 #include <dpl/db/sql_connection.h>
27 #include <dpl/db/naive_synchronization_object.h>
28 #include <dpl/scoped_ptr.h>
34 #include <noncopyable.h>
38 const int MAX_RETRY = 10;
43 namespace { // anonymous
44 class ScopedNotifyAll {
46 SqlConnection::SynchronizationObject *m_synchronizationObject;
49 NONCOPYABLE(ScopedNotifyAll)
51 explicit ScopedNotifyAll(
52 SqlConnection::SynchronizationObject *synchronizationObject) :
53 m_synchronizationObject(synchronizationObject)
59 if (!m_synchronizationObject)
62 LogPedantic("Notifying after successful synchronize");
63 m_synchronizationObject->NotifyAll();
66 } // namespace anonymous
68 SqlConnection::DataCommand::DataCommand(SqlConnection *connection,
70 m_masterConnection(connection),
73 assert(connection != NULL);
75 // Notify all after potentially synchronized database connection access
76 ScopedNotifyAll notifyAll(connection->m_synchronizationObject.get());
78 for (int i = 0; i < MAX_RETRY; i++) {
79 int ret = sqlite3_prepare_v2(connection->m_connection,
80 buffer, strlen(buffer),
83 if (ret == SQLITE_OK) {
84 LogPedantic("Prepared data command: " << buffer);
86 // Increment stored data command count
87 ++m_masterConnection->m_dataCommandsCount;
89 } else if (ret == SQLITE_BUSY) {
90 LogPedantic("Collision occurred while preparing SQL command");
92 // Synchronize if synchronization object is available
93 if (connection->m_synchronizationObject) {
94 LogPedantic("Performing synchronization");
95 connection->m_synchronizationObject->Synchronize();
99 // No synchronization object defined. Fail.
103 const char *error = sqlite3_errmsg(m_masterConnection->m_connection);
105 LogError("SQL prepare data command failed");
106 LogError(" Statement: " << buffer);
107 LogError(" Error: " << error);
109 ThrowMsg(Exception::SyntaxError, error);
112 LogError("sqlite in the state of possible infinite loop");
113 ThrowMsg(Exception::InternalError, "sqlite permanently busy");
116 SqlConnection::DataCommand::~DataCommand()
118 LogPedantic("SQL data command finalizing");
120 if (sqlite3_finalize(m_stmt) != SQLITE_OK)
121 LogError("Failed to finalize data command");
123 // Decrement stored data command count
124 --m_masterConnection->m_dataCommandsCount;
127 void SqlConnection::DataCommand::CheckBindResult(int result)
129 if (result != SQLITE_OK) {
130 const char *error = sqlite3_errmsg(
131 m_masterConnection->m_connection);
133 LogError("Failed to bind SQL statement parameter");
134 LogError(" Error: " << error);
136 ThrowMsg(Exception::SyntaxError, error);
141 void SqlConnection::DataCommand::BindNull(
142 SqlConnection::ArgumentIndex position)
144 CheckBindResult(sqlite3_bind_null(m_stmt, position));
145 LogPedantic("SQL data command bind null: ["
150 void SqlConnection::DataCommand::BindInteger(
151 SqlConnection::ArgumentIndex position,
154 CheckBindResult(sqlite3_bind_int(m_stmt, position, value));
155 LogPedantic("SQL data command bind integer: ["
156 << position << "] -> " << value);
160 void SqlConnection::DataCommand::BindInt8(
161 SqlConnection::ArgumentIndex position,
164 CheckBindResult(sqlite3_bind_int(m_stmt, position,
165 static_cast<int>(value)));
166 LogPedantic("SQL data command bind int8: ["
167 << position << "] -> " << value);
170 void SqlConnection::DataCommand::BindInt16(
171 SqlConnection::ArgumentIndex position,
174 CheckBindResult(sqlite3_bind_int(m_stmt, position,
175 static_cast<int>(value)));
176 LogPedantic("SQL data command bind int16: ["
177 << position << "] -> " << value);
180 void SqlConnection::DataCommand::BindInt32(
181 SqlConnection::ArgumentIndex position,
184 CheckBindResult(sqlite3_bind_int(m_stmt, position,
185 static_cast<int>(value)));
186 LogPedantic("SQL data command bind int32: ["
187 << position << "] -> " << value);
190 void SqlConnection::DataCommand::BindInt64(
191 SqlConnection::ArgumentIndex position,
194 CheckBindResult(sqlite3_bind_int64(m_stmt, position,
195 static_cast<sqlite3_int64>(value)));
196 LogPedantic("SQL data command bind int64: ["
197 << position << "] -> " << value);
200 void SqlConnection::DataCommand::BindFloat(
201 SqlConnection::ArgumentIndex position,
204 CheckBindResult(sqlite3_bind_double(m_stmt, position,
205 static_cast<double>(value)));
206 LogPedantic("SQL data command bind float: ["
207 << position << "] -> " << value);
210 void SqlConnection::DataCommand::BindDouble(
211 SqlConnection::ArgumentIndex position,
214 CheckBindResult(sqlite3_bind_double(m_stmt, position, value));
215 LogPedantic("SQL data command bind double: ["
216 << position << "] -> " << value);
220 void SqlConnection::DataCommand::BindString(
221 SqlConnection::ArgumentIndex position,
229 // Assume that text may disappear
230 CheckBindResult(sqlite3_bind_text(m_stmt, position,
231 value, strlen(value),
234 LogPedantic("SQL data command bind string: ["
235 << position << "] -> " << value);
238 void SqlConnection::DataCommand::BindBlob(
239 SqlConnection::ArgumentIndex position,
240 const RawBuffer &raw)
242 if (raw.size() == 0) {
247 // Assume that blob may dissappear
248 CheckBindResult(sqlite3_bind_blob(m_stmt, position,
249 raw.data(), raw.size(),
251 LogPedantic("SQL data command bind blob of size: ["
252 << position << "] -> " << raw.size());
256 void SqlConnection::DataCommand::BindInteger(
257 SqlConnection::ArgumentIndex position,
258 const boost::optional<int> &value)
263 BindInteger(position, *value);
266 void SqlConnection::DataCommand::BindInt8(
267 SqlConnection::ArgumentIndex position,
268 const boost::optional<int8_t> &value)
273 BindInt8(position, *value);
276 void SqlConnection::DataCommand::BindInt16(
277 SqlConnection::ArgumentIndex position,
278 const boost::optional<int16_t> &value)
283 BindInt16(position, *value);
286 void SqlConnection::DataCommand::BindInt32(
287 SqlConnection::ArgumentIndex position,
288 const boost::optional<int32_t> &value)
293 BindInt32(position, *value);
296 void SqlConnection::DataCommand::BindInt64(
297 SqlConnection::ArgumentIndex position,
298 const boost::optional<int64_t> &value)
303 BindInt64(position, *value);
306 void SqlConnection::DataCommand::BindFloat(
307 SqlConnection::ArgumentIndex position,
308 const boost::optional<float> &value)
313 BindFloat(position, *value);
316 void SqlConnection::DataCommand::BindDouble(
317 SqlConnection::ArgumentIndex position,
318 const boost::optional<double> &value)
323 BindDouble(position, *value);
326 void SqlConnection::DataCommand::BindBlob(
327 SqlConnection::ArgumentIndex position,
328 const boost::optional<RawBuffer> &value)
331 BindBlob(position, *value);
337 bool SqlConnection::DataCommand::Step()
339 // Notify all after potentially synchronized database connection access
340 ScopedNotifyAll notifyAll(
341 m_masterConnection->m_synchronizationObject.get());
343 for (int i = 0; i < MAX_RETRY; i++) {
344 int ret = sqlite3_step(m_stmt);
346 if (ret == SQLITE_ROW) {
347 LogPedantic("SQL data command step ROW");
349 } else if (ret == SQLITE_DONE) {
350 LogPedantic("SQL data command step DONE");
352 } else if (ret == SQLITE_BUSY) {
353 LogPedantic("Collision occurred while executing SQL command");
355 // Synchronize if synchronization object is available
356 if (m_masterConnection->m_synchronizationObject) {
357 LogPedantic("Performing synchronization");
360 m_synchronizationObject->Synchronize();
365 // No synchronization object defined. Fail.
369 const char *error = sqlite3_errmsg(m_masterConnection->m_connection);
371 LogError("SQL step data command failed");
372 LogError(" Error: " << error);
374 ThrowMsg(Exception::InternalError, error);
377 LogError("sqlite in the state of possible infinite loop");
378 ThrowMsg(Exception::InternalError, "sqlite permanently busy");
381 void SqlConnection::DataCommand::Reset()
385 * http://www.sqllite.org/c3ref/stmt.html
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.
391 sqlite3_reset(m_stmt);
393 LogPedantic("SQL data command reset");
396 void SqlConnection::DataCommand::CheckColumnIndex(
397 SqlConnection::ColumnIndex column)
399 if (column < 0 || column >= sqlite3_column_count(m_stmt))
400 ThrowMsg(Exception::InvalidColumn, "Column index is out of bounds");
404 bool SqlConnection::DataCommand::IsColumnNull(
405 SqlConnection::ColumnIndex column)
407 LogPedantic("SQL data command get column type: [" << column << "]");
408 CheckColumnIndex(column);
409 return sqlite3_column_type(m_stmt, column) == SQLITE_NULL;
413 int SqlConnection::DataCommand::GetColumnInteger(
414 SqlConnection::ColumnIndex column)
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);
424 int8_t SqlConnection::DataCommand::GetColumnInt8(
425 SqlConnection::ColumnIndex column)
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);
434 int16_t SqlConnection::DataCommand::GetColumnInt16(
435 SqlConnection::ColumnIndex column)
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);
444 int32_t SqlConnection::DataCommand::GetColumnInt32(
445 SqlConnection::ColumnIndex column)
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);
454 int64_t SqlConnection::DataCommand::GetColumnInt64(
455 SqlConnection::ColumnIndex column)
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);
464 float SqlConnection::DataCommand::GetColumnFloat(
465 SqlConnection::ColumnIndex column)
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);
474 double SqlConnection::DataCommand::GetColumnDouble(
475 SqlConnection::ColumnIndex column)
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);
485 std::string SqlConnection::DataCommand::GetColumnString(
486 SqlConnection::ColumnIndex column)
488 LogPedantic("SQL data command get column string: [" << column << "]");
489 CheckColumnIndex(column);
491 const char *value = reinterpret_cast<const char *>(
492 sqlite3_column_text(m_stmt, column));
494 LogPedantic("Value: " << (value ? value : "NULL"));
497 return std::string();
499 return std::string(value);
502 RawBuffer SqlConnection::DataCommand::GetColumnBlob(
503 SqlConnection::ColumnIndex column)
505 LogPedantic("SQL data command get column blog: [" << column << "]");
506 CheckColumnIndex(column);
508 const unsigned char *value = reinterpret_cast<const unsigned char *>(
509 sqlite3_column_blob(m_stmt, column));
514 int length = sqlite3_column_bytes(m_stmt, column);
515 LogPedantic("Got blob of length: " << length);
517 return RawBuffer(value, value + length);
521 boost::optional<int> SqlConnection::DataCommand::GetColumnOptionalInteger(
522 SqlConnection::ColumnIndex column)
524 LogPedantic("SQL data command get column optional integer: ["
526 CheckColumnIndex(column);
528 if (sqlite3_column_type(m_stmt, column) == SQLITE_NULL)
529 return boost::optional<int>();
531 int value = sqlite3_column_int(m_stmt, column);
532 LogPedantic(" Value: " << value);
533 return boost::optional<int>(value);
536 boost::optional<int8_t> SqlConnection::DataCommand::GetColumnOptionalInt8(
537 SqlConnection::ColumnIndex column)
539 LogPedantic("SQL data command get column optional int8: ["
541 CheckColumnIndex(column);
543 if (sqlite3_column_type(m_stmt, column) == SQLITE_NULL)
544 return boost::optional<int8_t>();
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);
551 boost::optional<int16_t> SqlConnection::DataCommand::GetColumnOptionalInt16(
552 SqlConnection::ColumnIndex column)
554 LogPedantic("SQL data command get column optional int16: ["
556 CheckColumnIndex(column);
558 if (sqlite3_column_type(m_stmt, column) == SQLITE_NULL)
559 return boost::optional<int16_t>();
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);
566 boost::optional<int32_t> SqlConnection::DataCommand::GetColumnOptionalInt32(
567 SqlConnection::ColumnIndex column)
569 LogPedantic("SQL data command get column optional int32: ["
571 CheckColumnIndex(column);
573 if (sqlite3_column_type(m_stmt, column) == SQLITE_NULL)
574 return boost::optional<int32_t>();
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);
581 boost::optional<int64_t> SqlConnection::DataCommand::GetColumnOptionalInt64(
582 SqlConnection::ColumnIndex column)
584 LogPedantic("SQL data command get column optional int64: ["
586 CheckColumnIndex(column);
588 if (sqlite3_column_type(m_stmt, column) == SQLITE_NULL)
589 return boost::optional<int64_t>();
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);
596 boost::optional<float> SqlConnection::DataCommand::GetColumnOptionalFloat(
597 SqlConnection::ColumnIndex column)
599 LogPedantic("SQL data command get column optional float: ["
601 CheckColumnIndex(column);
603 if (sqlite3_column_type(m_stmt, column) == SQLITE_NULL)
604 return boost::optional<float>();
606 float value = static_cast<float>(sqlite3_column_double(m_stmt, column));
607 LogPedantic(" Value: " << value);
608 return boost::optional<float>(value);
611 boost::optional<double> SqlConnection::DataCommand::GetColumnOptionalDouble(
612 SqlConnection::ColumnIndex column)
614 LogPedantic("SQL data command get column optional double: ["
616 CheckColumnIndex(column);
618 if (sqlite3_column_type(m_stmt, column) == SQLITE_NULL)
619 return boost::optional<double>();
621 double value = sqlite3_column_double(m_stmt, column);
622 LogPedantic(" Value: " << value);
623 return boost::optional<double>(value);
626 boost::optional<RawBuffer> SqlConnection::DataCommand::GetColumnOptionalBlob(
627 SqlConnection::ColumnIndex column)
629 LogPedantic("SQL data command get column blog: [" << column << "]");
630 CheckColumnIndex(column);
632 if (sqlite3_column_type(m_stmt, column) == SQLITE_NULL)
633 return boost::optional<RawBuffer>();
635 const unsigned char *value = reinterpret_cast<const unsigned char *>(
636 sqlite3_column_blob(m_stmt, column));
638 int length = sqlite3_column_bytes(m_stmt, column);
639 LogPedantic("Got blob of length: " << length);
641 RawBuffer temp(value, value + length);
642 return boost::optional<RawBuffer>(temp);
646 void SqlConnection::Connect(const std::string &address,
649 if (m_connection != NULL) {
650 LogPedantic("Already connected.");
654 LogPedantic("Connecting to DB: " << address << "...");
656 // Connect to database
658 result = sqlite3_open_v2(
664 if (result == SQLITE_OK) {
665 LogPedantic("Connected to DB");
667 LogError("Failed to connect to DB!");
668 ThrowMsg(Exception::ConnectionBroken, address);
671 // Enable foreign keys
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;
679 RawBuffer rawToHexString(const RawBuffer &raw)
681 return hexDump<RawBuffer, true>(raw);
684 RawBuffer createHexPass(const RawBuffer &rawPass)
686 // We are required to pass 64byte long hex password made out of 32byte raw
689 std::copy(SQLITE_RAW_PREFIX.begin(), SQLITE_RAW_PREFIX.end(),
690 std::back_inserter(output));
692 RawBuffer password = rawToHexString(rawPass);
694 std::copy(password.begin(), password.end(),
695 std::back_inserter(output));
697 std::copy(SQLITE_RAW_SUFIX.begin(), SQLITE_RAW_SUFIX.end(),
698 std::back_inserter(output));
703 void SqlConnection::SetKey(const RawBuffer &rawPass)
705 if (m_connection == NULL) {
706 LogPedantic("Cannot set key. No connection to DB!");
710 if (rawPass.size() != SQLITE_RAW_DATA_SIZE)
711 ThrowMsg(Exception::InvalidArguments,
712 "Binary data for raw password should be 32 bytes long.");
714 RawBuffer pass = createHexPass(rawPass);
715 int result = sqlite3_key(m_connection, pass.data(), pass.size());
717 if (result == SQLITE_OK) {
718 LogPedantic("Set key on DB");
720 //sqlite3_key fails only when m_connection == NULL || key == NULL ||
722 LogError("Failed to set key on DB");
723 ThrowMsg(Exception::InvalidArguments, result);
730 void SqlConnection::ResetKey(const RawBuffer &rawPassOld,
731 const RawBuffer &rawPassNew)
733 if (m_connection == NULL) {
734 LogPedantic("Cannot reset key. No connection to DB!");
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);
742 // sqlite3_rekey requires for key to be already set
746 RawBuffer pass = createHexPass(rawPassNew);
747 int result = sqlite3_rekey(m_connection, pass.data(), pass.size());
749 if (result == SQLITE_OK) {
750 LogPedantic("Reset key on DB");
752 //sqlite3_rekey fails only when m_connection == NULL || key == NULL ||
754 LogError("Failed to reset key on DB");
755 ThrowMsg(Exception::InvalidArguments, result);
760 void SqlConnection::Disconnect()
762 if (m_connection == NULL) {
763 LogPedantic("Already disconnected.");
767 LogPedantic("Disconnecting from DB...");
769 // All stored data commands must be deleted before disconnect
770 assert(m_dataCommandsCount == 0);
774 result = sqlite3_close(m_connection);
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);
785 LogPedantic("Disconnected from DB");
788 bool SqlConnection::CheckTableExist(const char *tableName)
790 if (m_connection == NULL) {
791 LogPedantic("Cannot execute command. Not connected to DB!");
795 DataCommandUniquePtr command =
796 PrepareDataCommand("select tbl_name from sqlite_master where name=?;");
798 command->BindString(1, tableName);
800 if (!command->Step()) {
801 LogPedantic("No matching records in table");
805 return command->GetColumnString(0) == tableName;
808 SqlConnection::SqlConnection(const std::string &address,
810 SynchronizationObject *synchronizationObject) :
812 m_dataCommandsCount(0),
813 m_synchronizationObject(synchronizationObject),
816 LogPedantic("Opening database connection to: " << address);
819 SqlConnection::Connect(address, option);
821 if (!m_synchronizationObject)
822 LogPedantic("No synchronization object defined");
825 SqlConnection::~SqlConnection()
827 LogPedantic("Closing database connection");
829 // Disconnect from DB
831 SqlConnection::Disconnect();
832 } catch (const Exception::Base &) {
833 LogError("Failed to disconnect from database");
838 int SqlConnection::Output::Callback(void *param, int columns, char **values,
842 static_cast<Output *>(param)->SetResults(columns, values, names);
847 void SqlConnection::Output::SetResults(int columns, char **values, char **names)
849 if (m_names.empty()) {
850 for (int i = 0; i < columns; i++)
851 m_names.push_back(names[i] ? names[i] : "NULL");
856 for (int i = 0; i < columns; i++)
857 row.push_back(values[i] ? values[i] : "NULL");
859 m_values.push_back(std::move(row));
863 void SqlConnection::ExecCommandHelper(Output *out, const char *format,
866 if (m_connection == NULL) {
867 LogError("Cannot execute command. Not connected to DB!");
871 if (format == NULL) {
872 LogError("Null query!");
873 ThrowMsg(Exception::SyntaxError, "Null statement");
878 if (vasprintf(&query, format, args) == -1) {
879 LogError("Failed to allocate statement string");
883 CharUniquePtr queryPtr(query);
885 LogPedantic("Executing SQL command: " << queryPtr.get());
887 // Notify all after potentially synchronized database connection access
888 ScopedNotifyAll notifyAll(m_synchronizationObject.get());
890 for (int i = 0; i < MAX_RETRY; i++) {
892 int ret = sqlite3_exec(m_connection,
894 out ? &Output::Callback : NULL,
898 std::string errorMsg;
900 // Take allocated error buffer
901 if (errorBuffer != NULL) {
902 errorMsg = errorBuffer;
903 sqlite3_free(errorBuffer);
906 if (ret == SQLITE_OK)
909 if (ret == SQLITE_BUSY) {
910 LogPedantic("Collision occurred while executing SQL command");
912 // Synchronize if synchronization object is available
913 if (m_synchronizationObject) {
914 LogPedantic("Performing synchronization");
915 m_synchronizationObject->Synchronize();
919 // No synchronization object defined. Fail.
923 LogError("Failed to execute SQL command. Error: " << errorMsg);
924 ThrowMsg(Exception::SyntaxError, errorMsg);
927 LogError("sqlite in the state of possible infinite loop");
928 ThrowMsg(Exception::InternalError, "sqlite permanently busy");
932 void SqlConnection::ExecCommand(Output *out, const char *format, ...)
935 va_start(args, format);
937 ExecCommandHelper(out, format, args);
946 void SqlConnection::ExecCommand(const char *format, ...)
949 va_start(args, format);
951 ExecCommandHelper(NULL, format, args);
959 SqlConnection::DataCommandUniquePtr SqlConnection::PrepareDataCommand(
963 if (m_connection == NULL) {
964 LogError("Cannot execute data command. Not connected to DB!");
965 return DataCommandUniquePtr();
971 va_start(args, format);
973 if (vasprintf(&rawBuffer, format, args) == -1)
978 CharUniquePtr buffer(rawBuffer);
981 LogError("Failed to allocate statement string");
982 return DataCommandUniquePtr();
985 LogPedantic("Executing SQL data command: " << buffer.get());
987 return DataCommandUniquePtr(new DataCommand(this, buffer.get()));
991 SqlConnection::RowID SqlConnection::GetLastInsertRowID() const
993 return static_cast<RowID>(sqlite3_last_insert_rowid(m_connection));
997 void SqlConnection::TurnOnForeignKeys()
999 ExecCommand("PRAGMA foreign_keys = ON;");
1002 void SqlConnection::BeginTransaction()
1004 ExecCommand("BEGIN;");
1007 void SqlConnection::RollbackTransaction()
1009 ExecCommand("ROLLBACK;");
1012 void SqlConnection::CommitTransaction()
1014 ExecCommand("COMMIT;");
1017 SqlConnection::SynchronizationObject *
1018 SqlConnection::AllocDefaultSynchronizationObject()
1020 return new NaiveSynchronizationObject();
1025 #pragma GCC diagnostic pop