Krita Source Code Documentation
Loading...
Searching...
No Matches
KisSqlQueryLoader Class Reference

#include <KisSqlQueryLoader.h>

Classes

struct  FileException
 
struct  single_statement_mode_t
 
struct  SQLException
 

Public Member Functions

void exec ()
 
 KisSqlQueryLoader (const QString &fileName)
 
 KisSqlQueryLoader (const QString &fileName, single_statement_mode_t)
 
 KisSqlQueryLoader (const QString &scriptName, const QString &script)
 
 KisSqlQueryLoader (const QString &scriptName, const QString &script, single_statement_mode_t)
 
QSqlQuery & query ()
 
 ~KisSqlQueryLoader ()
 

Static Public Attributes

static constexpr single_statement_mode_t single_statement_mode {}
 

Private Member Functions

void init (const QString &fileName, QString entireScript, bool singleStatementMode)
 

Private Attributes

QString m_fileName
 
QSqlQuery m_query
 
bool m_singleStatementMode {false}
 
QStringList m_statements
 

Detailed Description

A utility class to load an SQL query from a file and execute it.

The class reports all the errors in a form of exceptions, making it much easier to write code with multiple steps. The class can also be used in tandem with KisDatabaseTransactionLock to handle the transactions properly.

Usage:

Query provided inline:

 \code{.cpp}

 try {

     /// Start the transaction
     KisDatabaseTransactionLock transactionLock(database);

     // load the query, instead of the filename pass a fake filename that
     // starts with `inline://` prefix
     KisSqlQueryLoader loader("inline://enable_foreign_keys",
                              QString("PRAGMA foreign_keys = %1")
                                  .arg(isEnabled ? "on" : "off"));
     // execute the query
     loader.exec();

     // commit the transaction
     transactionLock.commit();

 } catch (const KisSqlQueryLoader::SQLException &e) {
     // in case of an error an exception will be raised, which can be
     // handled gracefully; please note that the transaction will be
     // automatically rolled back by KisDatabaseTransactionLock

     qWarning().noquote() << "ERROR: failed to execute query:" << e.message;
     qWarning().noquote() << "       file:" << e.filePath;
     qWarning().noquote() << "       statement:" << e.statementIndex;
     qWarning().noquote() << "       error:" << e.sqlError.text();

     return false;
 }

 \endcode

Query loaded from the file:

 \code{.cpp}

 try {

     /// Start the transaction
     KisDatabaseTransactionLock transactionLock(database);

     // load the query, just pass the filename in a form acceptable
     // by QFile
     KisSqlQueryLoader loader(":/create_index_metadata_key.sql");
     // execute the query
     loader.exec();

     // commit the transaction
     transactionLock.commit();

 } catch (const KisSqlQueryLoader::SQLException &e) {
     // in case of an error an exception will be raised, which can be
     // handled gracefully; please note that the transaction will be
     // automatically rolled back by KisDatabaseTransactionLock

     qWarning().noquote() << "ERROR: failed to execute query:" << e.message;
     qWarning().noquote() << "       file:" << e.filePath;
     qWarning().noquote() << "       statement:" << e.statementIndex;
     qWarning().noquote() << "       error:" << e.sqlError.text();

     return false;
 } catch (const KisSqlQueryLoader::FileException &e) {
     // for file-related errors there will be another type of an exception,
     // please don't forget to handle it as well

     qWarning().noquote() << "ERROR: failed to execute query:" << message;
     qWarning().noquote() << "       error" << e.message;
     qWarning().noquote() << "       file:" << e.filePath;
     qWarning().noquote() << "       file-error:" << e.fileErrorString;
     return false;
 }

 \endcode

Definition at line 105 of file KisSqlQueryLoader.h.

Constructor & Destructor Documentation

◆ KisSqlQueryLoader() [1/4]

KisSqlQueryLoader::KisSqlQueryLoader ( const QString & fileName)

Load the query from a file fileName. This form of the constructor does not try prepare the query. It means that:

1) The query is allowed to have multiple statements. All these statements will be executed in the exec() stage.

2) One cannot bind any values to the query.

Definition at line 61 of file KisSqlQueryLoader.cpp.

62{
63 QFile file(fileName);
64 if (file.open(QFile::ReadOnly)) {
65 init(fileName, file.readAll(), false);
66 } else {
67 throw FileException("Could not load SQL script file", fileName, file.errorString());
68 }
69}
void init(const QString &fileName, QString entireScript, bool singleStatementMode)

References init().

◆ KisSqlQueryLoader() [2/4]

KisSqlQueryLoader::KisSqlQueryLoader ( const QString & fileName,
single_statement_mode_t  )

Load the query from a file fileName in a "single statement mode". In this mode the loader immediately prepares the query, which means you can bind any values to the query before calling exec().

Definition at line 71 of file KisSqlQueryLoader.cpp.

72{
73 QFile file(fileName);
74 if (file.open(QFile::ReadOnly)) {
75 init(fileName, file.readAll(), true);
76 } else {
77 throw FileException("Could not load SQL script file", fileName, file.errorString());
78 }
79}

References init().

◆ KisSqlQueryLoader() [3/4]

KisSqlQueryLoader::KisSqlQueryLoader ( const QString & scriptName,
const QString & script )

Load the script from an explicit string script. scriptName is the fake "file name" of the script, which is used for logging and error reporting. Please add prefix inline:// to these script names to be consistent.

This form of the constructor loads the script in a multi-statement more, i.e. it doesn't prepare the query and does not allow value binding.

Definition at line 81 of file KisSqlQueryLoader.cpp.

82{
83 init(scriptName, script, false);
84}

References init().

◆ KisSqlQueryLoader() [4/4]

KisSqlQueryLoader::KisSqlQueryLoader ( const QString & scriptName,
const QString & script,
single_statement_mode_t  )

Load the script from an explicit string script. scriptName is the fake "file name" of the script, which is used for logging and error reporting. Please add prefix inline:// to these script names to be consistent.

This form of the constructor loads the script in a single-statement mode, which prepares the query immediately and allows value binding.

Definition at line 86 of file KisSqlQueryLoader.cpp.

87{
88 init(scriptName, script, true);
89}

References init().

◆ ~KisSqlQueryLoader()

KisSqlQueryLoader::~KisSqlQueryLoader ( )

Definition at line 91 of file KisSqlQueryLoader.cpp.

92{
93}

Member Function Documentation

◆ exec()

void KisSqlQueryLoader::exec ( )

Execute all statements of the query

In single-statement mode, the values can be bound to the query before calling exec().

Definition at line 100 of file KisSqlQueryLoader.cpp.

101{
103 if (!m_query.exec()) {
104 throw SQLException(
105 "Failed to execute sql from file",
107 0,
108 m_query.lastError());
109 }
110 } else {
111 for (int i = 0; i < m_statements.size(); i++) {
112 const QString &statement = m_statements[i];
113 if (!m_query.exec(statement)) {
114 throw SQLException(
115 "Failed to execute sql from file",
117 i,
118 m_query.lastError());
119 }
120 }
121 }
122}

References m_fileName, m_query, m_singleStatementMode, and m_statements.

◆ init()

void KisSqlQueryLoader::init ( const QString & fileName,
QString entireScript,
bool singleStatementMode )
private

Definition at line 21 of file KisSqlQueryLoader.cpp.

22{
23 m_singleStatementMode = singleStatementMode;
24 m_fileName = fileName;
25
26 QTextStream stream(&entireScript);
27
28 // remove comments by splitting into lines
29 QRegularExpression regexp("^--.*$");
30 while (!stream.atEnd()) {
31 const QString statement = stream.readLine().trimmed();
32 if (!regexp.match(statement).hasMatch()) {
33 m_statements.append(statement);
34 }
35 }
36
37 // split lines into actual statements
38 m_statements = m_statements.join(' ').split(';');
39
40 // trim the statements
41 std::transform(m_statements.begin(), m_statements.end(),
42 m_statements.begin(), [] (const QString &x) { return x.trimmed(); });
43
44 // remove empty statements
45 m_statements.erase(std::remove_if(m_statements.begin(), m_statements.end(),
46 kismpl::mem_equal_to(&QString::isEmpty, true)),
47 m_statements.end());
48
51 if (!m_query.prepare(m_statements.first())) {
52 throw SQLException(
53 "Failed to prepare an sql query from file",
55 0,
56 m_query.lastError());
57 }
58 }
59}
#define KIS_SAFE_ASSERT_RECOVER_RETURN(cond)
Definition kis_assert.h:128
auto mem_equal_to(MemTypeNoRef Class::*ptr, MemType &&value)
mem_equal_to is an unary functor that compares a member of the object to a given value
Definition KisMpl.h:233

References KIS_SAFE_ASSERT_RECOVER_RETURN, m_fileName, m_query, m_singleStatementMode, m_statements, and kismpl::mem_equal_to().

◆ query()

QSqlQuery & KisSqlQueryLoader::query ( )

Definition at line 95 of file KisSqlQueryLoader.cpp.

96{
97 return m_query;
98}

References m_query.

Member Data Documentation

◆ m_fileName

QString KisSqlQueryLoader::m_fileName
private

Definition at line 204 of file KisSqlQueryLoader.h.

◆ m_query

QSqlQuery KisSqlQueryLoader::m_query
private

Definition at line 201 of file KisSqlQueryLoader.h.

◆ m_singleStatementMode

bool KisSqlQueryLoader::m_singleStatementMode {false}
private

Definition at line 203 of file KisSqlQueryLoader.h.

203{false};

◆ m_statements

QStringList KisSqlQueryLoader::m_statements
private

Definition at line 202 of file KisSqlQueryLoader.h.

◆ single_statement_mode

constexpr single_statement_mode_t KisSqlQueryLoader::single_statement_mode {}
staticconstexpr

Definition at line 109 of file KisSqlQueryLoader.h.

109{};

The documentation for this class was generated from the following files: