Commit 1f441d9b authored by Lukas Appelhans's avatar Lukas Appelhans
Browse files

Start with optimizations

parent 87a3009c
......@@ -25,6 +25,7 @@ akabeivalidatorrunnable_p.cpp
md5.c
SQLiteConnection.cpp
PolKitSQLiteConnection.cpp
SQLInterface.cpp
libarchive++/archivehandler.cpp
libarchive++/polkitarchivehandler.cpp
)
......
......@@ -50,7 +50,8 @@ public:
};
PolKitSQLiteConnection::PolKitSQLiteConnection(QString const& name, bool readonly)
: d(new Private())
: SQLInterface(),
d(new Private())
{
connectToDB(name, readonly);
}
......@@ -77,11 +78,11 @@ void PolKitSQLiteConnection::connectToDB(QString const& name, bool readonly)
d->setupDbusDatabase = false;
}
SQLiteResource PolKitSQLiteConnection::query(const QString &q)
QList<Row> PolKitSQLiteConnection::rowQuery(const QString &q)
{
if ((d->access.testFlag(Akabei::Helpers::ReadWritePermission)) || ((d->access.testFlag(Akabei::Helpers::ReadPermission)) && q.startsWith("SELECT"))) {
d->lastQueryDBus = false;
return d->connection->query(q);
return d->connection->rowQuery(q);
}
if (Akabei::Helpers::checkAuthorizationSync("org.chakraproject.akabeicorehelper.sqlite.query")) {
......@@ -92,22 +93,22 @@ SQLiteResource PolKitSQLiteConnection::query(const QString &q)
if (!mes.arguments().isEmpty()) {
const QDBusArgument arg = mes.arguments().first().value<QDBusArgument>();
if (arg.currentType() == QDBusArgument::UnknownType)
return SQLiteResource(QList<Row>());
return QList<Row>();
QList<QVariantMap> list;
arg >> list;
return SQLiteResource(list);
return list;
}
} else {
Akabei::ErrorQueue::instance()->appendError(
Akabei::Error(Akabei::Error::PermissionError, PolkitQt1::Authority::instance()->errorDetails()));
}
return SQLiteResource(QList<Row>());
return QList<Row>();
}
void PolKitSQLiteConnection::query(const QString &q, const QVariantMap &bindings)
void PolKitSQLiteConnection::multipleQuery(const QString &q, const QVariantMap &bindings)
{
if ((d->access.testFlag(Akabei::Helpers::ReadWritePermission)) || ((d->access.testFlag(Akabei::Helpers::ReadPermission)) && q.startsWith("SELECT"))) {
d->connection->query(q, bindings);
d->connection->multipleQuery(q, bindings);
d->lastQueryDBus = false;
return;
}
......
/* This file is part of the Chakra project
Copyright (C) 2012 Lukas Appelhans <boom1992@chakra-project.org>
Copyright (C) 2012 - 2013 Lukas Appelhans <boom1992@chakra-project.org>
Copyright (C) 2011 Lisa Vitolo <shainer@chakra-project.org>
This program is free software; you can redistribute it and/or
......@@ -14,6 +14,7 @@
#include <QVariantMap>
#include <QString>
#include <SQLiteConnection.h>
#include "SQLInterface.h"
/**
* @class SQLiteConnection
......@@ -21,11 +22,8 @@
*
* This class is not thread-safe.
*/
class PolKitSQLiteConnection
class PolKitSQLiteConnection : public SQLInterface
{
typedef QVariant Value;
typedef QVariantMap Row;
public:
/**
* Constructs an object and establishes the connection
......@@ -48,7 +46,7 @@ public:
* @param name the database filename
* @param readonly true if read-only access, false for read-write
*/
void connectToDB(QString const&, bool);
virtual void connectToDB(QString const&, bool);
/**
* Executes a query on the database
......@@ -56,7 +54,7 @@ public:
* @param q the query string
* @returns a SQLiteResource object with the result, if present
*/
SQLiteResource query(const QString &q);
virtual QList<Row> rowQuery(const QString &q);
/**
* Executes multiple queries on the database
......@@ -65,22 +63,22 @@ public:
* @param bindings the bindings we're going to use
* this is pair of values, the key is a string determining the binding name, the value is a stringlist which contains all the values
*/
void query(const QString &q, const QVariantMap &bindings);
virtual void multipleQuery(const QString &q, const QVariantMap &bindings);
/**
* If the table interested by the last query as an autoincremented primary key,
* gets the last value assigned to the key
*/
qint64 getLastRowId();
virtual qint64 getLastRowId();
/**
* Creates a "macro" (fake name) that maps into an integer, a QString, or a QByteArray
* The next query can contain the defined macros in place of the actual values.
* @note All bindings stay valid only for the subsequent call of query().
*/
void bind(QString const&, int);
void bind(QString const&, QString const&);
void bind(QString const&, QByteArray const&);
virtual void bind(QString const&, int);
virtual void bind(QString const&, QString const&);
virtual void bind(QString const&, QByteArray const&);
private:
// Disable copy constructor and default constructor
......@@ -90,6 +88,4 @@ private:
Private *d;
};
Q_DECLARE_METATYPE(QList<Row>);
#endif
/* This file is part of the Chakra project
Copyright (C) 2013 Lukas Appelhans <boom1992@chakra-project.org>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
*/
#include "SQLInterface.h"
#include <QMutexLocker>
class SQLResource::Private : public QSharedData
{
public:
Private(const QList<Row> &t) : table(t) {}
Private(const Private &p) : QSharedData(p), table(p.table) {}
~Private() {}
QList<Row> table;
QMutex mutex;
};
/********** SQLResource **************/
SQLResource::SQLResource(QList<Row> table)
: d(new Private(table))
{}
SQLResource::SQLResource(const SQLResource& other)
: d(other.d)
{}
SQLResource::~SQLResource()
{}
SQLResource& SQLResource::operator=(const SQLResource& other)
{
d = other.d;
return *this;
}
QList<QVariant> SQLResource::getColumn(const QString& columnName)
{
QMutexLocker locker(&d->mutex);
QList<QVariant> data;
for (QList<QVariantMap>::const_iterator it = d->table.begin(); it < d->table.end(); it++) {
QVariantMap map( *it );
if (map.count(columnName) == 0) {
throw SQLException("Unexistent column in table");
}
data.append(map[columnName]);
}
return data;
}
QVariant SQLResource::getDataAt(int rowNumber, const QString& columnName)
{
QMutexLocker locker(&d->mutex);
if (d->table.isEmpty() || rowNumber >= d->table.size() || d->table[rowNumber].count(columnName) == 0) {
std::string error = QString("Access to non-existent data. Trying to access %1.").arg(columnName).toStdString();
throw SQLException(error.c_str());
}
return d->table[rowNumber][columnName];
}
int SQLResource::getRowsCount()
{
QMutexLocker locker(&d->mutex);
return d->table.size();
}
/** SQLInterface */
SQLInterface::SQLInterface()
{
}
SQLInterface::~SQLInterface()
{
}
SQLResource SQLInterface::query(const QString& q)
{
return SQLResource(rowQuery(q));
}
/* This file is part of the Chakra project
Copyright (C) 2013 Lukas Appelhans <boom1992@chakra-project.org>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
*/
#ifndef SQLINTERFACE_H
#define SQLINTERFACE_H
#include <QVariantMap>
#include <QSharedDataPointer>
#include <sqlite3.h>//FIXME: Replace the error handling (SQLITE_OK, SQLITE_ABORT) with something custom, to not harddepend on sqlite3.h here
typedef QVariantMap Row;
/**
* @class SQLResource
* @brief Used by SQLInterface to store the result of a query
*/
class SQLResource
{
typedef QVariant Value;
public:
SQLResource(QList<Row>);
SQLResource(const SQLResource &other);
~SQLResource();
/**
* @param rowNumber the row number in the result table
* @param columnName the column name
* @returns the value of the specified cell
*/
QVariant getDataAt(int, QString const&);
/**
* @param columnName the column name
* @returns a list of values of that column
*/
QList<QVariant> getColumn(QString const&);
/**
* @returns the number of rows in this table
*/
int getRowsCount();
SQLResource &operator=(const SQLResource &other);
private:
class Private;
QSharedDataPointer<Private> d;
};
/**
* @class SQLInterface
* @brief manages a connection with a database using the sqlite C library
*
* This class is not thread-safe.
*/
class SQLInterface
{
public:
typedef QVariant Value;
typedef QVariantMap Row;
virtual ~SQLInterface();
/**
* Establishes a new connection with a database
*
* @param name the database filename
* @param readonly true if read-only access, false for read-write
*/
virtual void connectToDB(QString const&, bool) = 0;
/**
* Executes a query on the database
*
* @param q the query string
* @returns a SQLiteResource object with the result, if present
*/
SQLResource query(const QString &q);
/**
* Executes multiple queries on the database
*
* @param q the query
* @param bindings the bindings we're going to use
* this is pair of values, the key is a string determining the binding name, the value is a stringlist which contains all the values
*/
virtual void multipleQuery(const QString &q, const QVariantMap &bindings) = 0;
/**
* Executes a query on the database
*
* @param q the query string
* @returns a QList<Row> object with the result, if present
*/
virtual QList<Row> rowQuery(const QString &q) = 0;
/**
* If the table interested by the last query as an autoincremented primary key,
* gets the last value assigned to the key
*/
virtual qint64 getLastRowId() = 0;
/**
* Creates a "macro" (fake name) that maps into an integer, a QString, or a QByteArray
* The next query can contain the defined macros in place of the actual values.
* @note All bindings stay valid only for the subsequent call of query().
*/
virtual void bind(QString const&, int) = 0;
virtual void bind(QString const&, QString const&) = 0;
virtual void bind(QString const&, QByteArray const&) = 0;
protected:
SQLInterface();
private:
// Disable copy constructor and default constructor
SQLInterface(SQLInterface const&) {}
class Private;
Private *d;
};
class SQLException : public std::exception
{
public:
SQLException(const char *m) : message(m) {}
virtual const char *what() const throw() {
return message;
}
private:
const char *message;
};
Q_DECLARE_METATYPE(QList<Row>);
#endif
......@@ -73,7 +73,8 @@ public:
* Establish a connection with dbName
*/
SQLiteConnection::SQLiteConnection(QString const& dbName, bool readonly)
: d(new Private())
: SQLInterface(),
d(new Private())
{
connectToDB(dbName, readonly);
}
......@@ -94,7 +95,7 @@ SQLiteConnection::~SQLiteConnection()
void SQLiteConnection::connectToDB(QString const& dbName, bool readonly)
{
if (d->isConnected) {
throw SQLiteException("Object already connected to database");
throw SQLException("Object already connected to database");
}
int flags(readonly ? SQLITE_OPEN_READONLY : SQLITE_OPEN_READWRITE);
......@@ -119,7 +120,7 @@ QList<Row> SQLiteConnection::rowQuery(const QString &q)
d->rows.clear();
if (!d->isConnected) {
throw SQLiteException("Object is not connected to database");
throw SQLException("Object is not connected to database");
}
/*
......@@ -163,20 +164,14 @@ QList<Row> SQLiteConnection::rowQuery(const QString &q)
if (retvalue != SQLITE_DONE && retvalue != SQLITE_OK) {
sqlite3_clear_bindings(d->statement);
sqlite3_finalize(d->statement);
throw SQLiteException(sqlite3_errmsg(d->dbHandle));
throw SQLException(sqlite3_errmsg(d->dbHandle));
}
d->checkForErrors(sqlite3_finalize(d->statement));
return d->rows;
}
SQLiteResource SQLiteConnection::query(const QString &q)
{
SQLiteResource table(rowQuery(q));
return table;
}
void SQLiteConnection::query(const QString &q, const QVariantMap &bindings)
void SQLiteConnection::multipleQuery(const QString &q, const QVariantMap &bindings)
{
if (bindings.isEmpty()) {
rowQuery(q);
......@@ -247,7 +242,7 @@ qint64 SQLiteConnection::getLastRowId()
QMutexLocker locker(&d->mutex);
if (!d->isConnected) {
throw SQLiteException("Object is not connected to database");
throw SQLException("Object is not connected to database");
}
sqlite3_int64 id = sqlite3_last_insert_rowid(d->dbHandle);
......@@ -262,7 +257,7 @@ void SQLiteConnection::bind(const QString& name, int value)
QMutexLocker locker(&d->mutex);
if (!d->isConnected) {
throw SQLiteException("Object is not connected to database");
throw SQLException("Object is not connected to database");
}
if (d->intBindings.contains(name) || d->stringBindings.contains(name)) {
......@@ -272,12 +267,12 @@ void SQLiteConnection::bind(const QString& name, int value)
d->intBindings.insert(name, value);
}
void SQLiteConnection::bind(const QString& name, QString value)
void SQLiteConnection::bind(const QString& name, const QString& value)
{
QMutexLocker locker(&d->mutex);
if (!d->isConnected) {
throw SQLiteException("Object is not connected to database");
throw SQLException("Object is not connected to database");
}
if (d->intBindings.contains(name) || d->stringBindings.contains(name)) {
......@@ -287,12 +282,12 @@ void SQLiteConnection::bind(const QString& name, QString value)
d->stringBindings.insert(name, value);
}
void SQLiteConnection::bind(const QString& name, QByteArray value)
void SQLiteConnection::bind(const QString& name, const QByteArray& value)
{
QMutexLocker locker(&d->mutex);
if (!d->isConnected) {
throw SQLiteException("Object is not connected to database");
throw SQLException("Object is not connected to database");
}
if (d->intBindings.contains(name) || d->stringBindings.contains(name)) {
......@@ -307,71 +302,6 @@ void SQLiteConnection::Private::checkForErrors(int r)
if (r != SQLITE_OK) {
const char *mess( sqlite3_errmsg(dbHandle) );
sqlite3_finalize(statement);
throw SQLiteException(mess);
throw SQLException(mess);
}
}
class SQLiteResource::Private : public QSharedData
{
public:
Private(const QList<Row> &t) : table(t) {}
Private(const Private &p) : QSharedData(p), table(p.table) {}
~Private() {}
QList<Row> table;
QMutex mutex;
};
/********** SQLiteResource **************/
SQLiteResource::SQLiteResource(QList<Row> table)
: d(new Private(table))
{}
SQLiteResource::SQLiteResource(const SQLiteResource& other)
: d(other.d)
{}
SQLiteResource::~SQLiteResource()
{}
SQLiteResource& SQLiteResource::operator=(const SQLiteResource& other)
{
d = other.d;
return *this;
}
QList<QVariant> SQLiteResource::getColumn(const QString& columnName)
{
QMutexLocker locker(&d->mutex);
QList<QVariant> data;
for (QList<QVariantMap>::const_iterator it = d->table.begin(); it < d->table.end(); it++) {
QVariantMap map( *it );
if (map.count(columnName) == 0) {
throw SQLiteException("Unexistent column in table");
}
data.append(map[columnName]);
}
return data;
}
QVariant SQLiteResource::getDataAt(int rowNumber, const QString& columnName)
{
QMutexLocker locker(&d->mutex);
if (d->table.isEmpty() || rowNumber >= d->table.size() || d->table[rowNumber].count(columnName) == 0) {
std::string error = QString("Access to non-existent data. Trying to access %1.").arg(columnName).toStdString();
throw SQLiteException(error.c_str());
}
return d->table[rowNumber][columnName];
}
int SQLiteResource::getRowsCount()
{
QMutexLocker locker(&d->mutex);
return d->table.size();
}
......@@ -12,6 +12,7 @@
#ifndef _SQLITE_CONNECTION_H
#define _SQLITE_CONNECTION_H
#include "SQLInterface.h"
/*
* If there's a God of programming somewhere,
* please forgive these sinners, for they have lost the way
......@@ -30,57 +31,14 @@
#include <exception>
#include <QSharedDataPointer>
typedef QVariantMap Row;
/**
* @class SQLiteResource
* @brief Used by SQLiteConnection to store the result of a query
*/
class SQLiteResource
{
typedef QVariant Value;
public:
SQLiteResource(QList<Row>);
SQLiteResource(const SQLiteResource &other);
~SQLiteResource();
/**
* @param rowNumber the row number in the result table
* @param columnName the column name
* @returns the value of the specified cell
*/
QVariant getDataAt(int, QString const&);
/**
* @param columnName the column name
* @returns a list of values of that column
*/
QList<QVariant> getColumn(QString const&);
/**
* @returns the number of rows in this table
*/
int getRowsCount();
SQLiteResource &operator=(const SQLiteResource &other);
private:
class Private;
QSharedDataPointer<Private> d;
};
/**
* @class SQLiteConnection
* @brief manages a connection with a database using the sqlite C library
*
* This class is not thread-safe.
*/
class SQLiteConnection
class SQLiteConnection : public SQLInterface
{
typedef QVariant Value;
typedef QVariantMap Row;
public:
/**
* Constructs an object and establishes the connection
......@@ -103,15 +61,7 @@ public:
* @param name the database filename