<commit_before>/*
 * This file is a part of Xpiks - cross platform application for
 * keywording and uploading images for microstocks
 * Copyright (C) 2014-2017 <NAME> <<EMAIL>>
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

#ifndef DATABASE_H
#define DATABASE_H

#include <QByteArray>
#include <QReadWriteLock>
#include <QDataStream>
#include <QAtomicInt>
#include <QMutex>
#include <QHash>
#include <QString>
#include <QVector>
#include <QPair>
#include <vector>
#include <memory>
#include <functional>
#include "asynccoordinator.h"
#include "../Common/defines.h"

struct sqlite3;
struct sqlite3_stmt;

namespace Helpers {
    template<class TValue>
    void restoreFailedItems(QHash<QString, TValue> &hash, QVector<QPair<QByteArray, QByteArray> > &keyValuesList, const QVector<int> &failedIndices) {
        for (auto &index: failedIndices) {
            auto &keyValuePair = keyValuesList[index];
            QString key = QString::fromUtf8(keyValuePair.first);

            TValue value;
            QByteArray &rawData = keyValuePair.second;
            QDataStream ds(&rawData, QIODevice::ReadOnly);
            ds >> value;

            hash.insert(key, value);
        }
    }

    // super simple wrapper over sqlite
    // to make it look like a key-value storage
    class Database {
    public:
        Database(int id, AsyncCoordinator *finalizeCoordinator);
        virtual ~Database();

    private:
        class Transaction {
        public:
            Transaction(sqlite3 *database);
            virtual ~Transaction();

        private:
            sqlite3 *m_Database;
            bool m_Started;
        };

    public:
        class Table {
        public:
            Table(sqlite3 *database, const QString &tableName);

        public:
            bool initialize();
            void finalize();

        public:
            bool tryGetValue(const QByteArray &key, QByteArray &value);
            bool trySetValue(const QByteArray &key, const QByteArray &value);
            bool tryAddValue(const QByteArray &key, const QByteArray &value);
            bool trySetMany(const QVector<QPair<QByteArray, QByteArray> > &keyValueList, QVector<int> &failedIndices);
            int tryAddMany(const QVector<QPair<QByteArray, QByteArray> > &keyValueList);
            bool tryDeleteRecord(const QByteArray &key);
            bool tryDeleteMany(const QVector<QByteArray> &keysList);
            void foreachRow(std::function<bool (QByteArray &, QByteArray &)> action);

        private:
            QString m_TableName;
            sqlite3 *m_Database;
            sqlite3_stmt *m_GetStatement;
            sqlite3_stmt *m_SetStatement;
            sqlite3_stmt *m_AddStatement;
            sqlite3_stmt *m_DelStatement;
            sqlite3_stmt *m_AllStatement;
        };

    public:
        bool open(const char *fullDbPath);
        void close();
        bool initialize();
        void finalize();
        void sync();
        std::shared_ptr<Table> getTable(const QString &name);

    private:
        void doClose();
        bool executeStatement(const char *stmt);

    private:<commit_msg>cosmetic fixes [ci skip]<commit_after>/*
 * This file is a part of Xpiks - cross platform application for
 * keywording and uploading images for microstocks
 * Copyright (C) 2014-2017 <NAME> <<EMAIL>>
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

#ifndef DATABASE_H
#define DATABASE_H

#include <QByteArray>
#include <QReadWriteLock>
#include <QDataStream>
#include <QAtomicInt>
#include <QMutex>
#include <QHash>
#include <QString>
#include <QVector>
#include <QPair>
#include <vector>
#include <memory>
#include <functional>
#include "asynccoordinator.h"
#include "../Common/defines.h"

struct sqlite3;
struct sqlite3_stmt;

namespace Helpers {
    template<class TValue>
    void restoreFailedItems(QHash<QString, TValue> &hash, QVector<QPair<QByteArray, QByteArray> > &keyValuesList, const QVector<int> &failedIndices) {
        for (auto &index: failedIndices) {
            auto &keyValuePair = keyValuesList[index];
            QString key = QString::fromUtf8(keyValuePair.first);

            TValue value;
            QByteArray &rawData = keyValuePair.second;
            QDataStream ds(&rawData, QIODevice::ReadOnly);
            ds >> value;

            hash.insert(key, value);
        }
    }

    // super simple wrapper over sqlite
    // to make it look like a key-value storage
    class Database {
    public:
        Database(int id, AsyncCoordinator *finalizeCoordinator);
        virtual ~Database();

    private:
        class Transaction {
        public:
            Transaction(sqlite3 *database);
            virtual ~Transaction();

        private:
            sqlite3 *m_Database;
            bool m_Started;
        };

    public:
        class Table {
        public:
            Table(sqlite3 *database, const QString &tableName);

        public:
            bool initialize();
            void finalize();

        public:
            bool tryGetValue(const QByteArray &key, QByteArray &value);
            bool trySetValue(const QByteArray &key, const QByteArray &value);
            bool tryAddValue(const QByteArray &key, const QByteArray &value);
            bool trySetMany(const QVector<QPair<QByteArray, QByteArray> > &keyValueList, QVector<int> &failedIndices);
            int tryAddMany(const QVector<QPair<QByteArray, QByteArray> > &keyValueList);
            bool tryDeleteRecord(const QByteArray &key);
            bool tryDeleteMany(const QVector<QByteArray> &keysList);
            void foreachRow(const std::function<bool (QByteArray &, QByteArray &)> &action);

        private:
            QString m_TableName;
            sqlite3 *m_Database;
            sqlite3_stmt *m_GetStatement;
            sqlite3_stmt *m_SetStatement;
            sqlite3_stmt *m_AddStatement;
            sqlite3_stmt *m_DelStatement;
            sqlite3_stmt *m_AllStatement;
        };

    public:
        bool open(const char *fullDbPath);
        void close();
        bool initialize();
        void finalize();
        void sync();
        std::shared_ptr<Table> getTable(const QString &name);

    private:
        void doClose();
        bool executeStatement(const char *stmt);

    private:
{'fraction_non_alphanumeric': 0.09531772575250837, 'fraction_numerical': 0.007297050775311645, 'mean_word_length': 2.5736013036393266, 'pattern_counts': {'":': 0, '<': 59, '<?xml version=': 0, '>': 63, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7126970', 'n_tokens_mistral': 1937, 'n_tokens_neox': 1888, 'n_words': 531}