Commit 3ffae1ab authored by jan.koester's avatar jan.koester
Browse files

test

parent be280c79
Loading
Loading
Loading
Loading
+74 −35
Original line number Diff line number Diff line
@@ -28,6 +28,7 @@
#include <iostream>
#include <atomic>
#include <stdexcept>
#include <memory>

#include <sqlite3.h>

@@ -35,6 +36,25 @@

std::atomic<bool> sqllock(false);

namespace {

class SqlSpinGuard {
public:
    SqlSpinGuard() {
        while (sqllock.exchange(true, std::memory_order_acquire)) {
        }
    }

    ~SqlSpinGuard() {
        sqllock.store(false, std::memory_order_release);
    }

    SqlSpinGuard(const SqlSpinGuard &) = delete;
    SqlSpinGuard &operator=(const SqlSpinGuard &) = delete;
};

} // namespace

static std::string quoteDoubleIdentifier(const std::string &identifier) {
    std::string result;
    result.reserve(identifier.size() + 2);
@@ -52,78 +72,97 @@ static std::string quoteDoubleIdentifier(const std::string &identifier) {


dbpp::SQLite::SQLite(const char *constr){
    while( sqllock.exchange(true, std::memory_order_acquire) );
    SqlSpinGuard lock;
    int status=sqlite3_open(constr,&_dbconn);
    if (status != SQLITE_OK ){
        std::string err = _dbconn ? sqlite3_errmsg(_dbconn) : "sqlite3_open failed";
        if (_dbconn)
            sqlite3_close(_dbconn);
        throw  std::runtime_error(sqlite3_errmsg(_dbconn));
        _dbconn = nullptr;
        throw std::runtime_error(err);
    }
    sqllock.store(false);

}

dbpp::SQLite::~SQLite(){
    if (_dbconn)
        sqlite3_close(_dbconn);
}

int dbpp::SQLite::exec(const SQL &sql,DBResult &res){
    while( sqllock.exchange(true, std::memory_order_acquire) );
    char *ssql;
    ssql=new char[sql.size()];
    memcpy(ssql,sql.c_str(),sql.size());
    sqlite3_stmt *prep;
    SqlSpinGuard lock;
    std::unique_ptr<char[]> ssql(new char[sql.size()]);
    memcpy(ssql.get(),sql.c_str(),sql.size());
    int rcount = 0;

    res.clear();

    DBResult::Data *lastdat;
    DBResult::Data *lastdat = nullptr;

    const char *cssql=ssql;
    const char *cssql = ssql.get();
    const char *end = ssql.get() + strlen(ssql.get());

    do{
        const char *sqlptr = nullptr;
        int pstate=sqlite3_prepare_v3(_dbconn,cssql,sql.size(),0,&prep,&sqlptr);
        sqlite3_stmt *prep = nullptr;
        int pstate = sqlite3_prepare_v3(_dbconn, cssql, -1, 0, &prep, &sqlptr);

        if (pstate != SQLITE_OK) {
            throw std::runtime_error(sqlite3_errmsg(_dbconn));
        }

        cssql = sqlptr;

        if(pstate == SQLITE_ERROR) {
            std::cerr << sqlite3_errmsg(_dbconn) << std::endl;
            continue;
        if(!prep) {
            if (cssql == nullptr) {
                throw std::runtime_error("sqlite prepare returned null tail pointer");
            }

        if(!prep)
            continue;
        }

        int pcode;

        while( ( pcode = sqlite3_step(prep) ) !=SQLITE_DONE ) {

            if(pcode==SQLITE_ERROR){
                delete[] ssql;
                sqllock.store(false);
                throw std::runtime_error(sqlite3_errmsg(_dbconn));
        while (true) {
            pcode = sqlite3_step(prep);
            if (pcode == SQLITE_DONE) {
                break;
            }

            if (pcode == SQLITE_ROW) {
                int i;
                for(i=0; i < sqlite3_column_count(prep); ++i){
                    const unsigned char *txt = sqlite3_column_text(prep, i);
                    const char *val = txt ? reinterpret_cast<const char *>(txt) : "";
                    int len = sqlite3_column_bytes(prep, i);
                    if(!res.firstRow){
                        res.firstRow = new DBResult::Data(rcount,i,(const char*)sqlite3_column_text(prep,i),sqlite3_column_bytes(prep,i));
                        res.firstRow = new DBResult::Data(rcount, i, val, len);
                        lastdat = res.firstRow;
                    } else {
                        lastdat->nextData=new DBResult::Data(rcount,i,(const char*)sqlite3_column_text(prep,i),sqlite3_column_bytes(prep,i));
                        lastdat->nextData = new DBResult::Data(rcount, i, val, len);
                        lastdat = lastdat->nextData;
                    }
                }
                ++rcount;
                continue;
            }

            if (pcode == SQLITE_BUSY || pcode == SQLITE_LOCKED) {
                sqlite3_finalize(prep);
                throw std::runtime_error("sqlite database is busy/locked: " + std::string(sqlite3_errmsg(_dbconn)));
            }

            if(pcode == SQLITE_ERROR || pcode == SQLITE_MISUSE) {
                sqlite3_finalize(prep);
                throw std::runtime_error(sqlite3_errmsg(_dbconn));
            }

            sqlite3_finalize(prep);
            throw std::runtime_error("sqlite step failed with code " + std::to_string(pcode) + ": " + std::string(sqlite3_errmsg(_dbconn)));
        }

        sqlite3_finalize(prep);
    }while(cssql != ssql+strlen(ssql));
    } while (cssql != end);

    sqllock.store(false);
    delete[] ssql;
    return rcount;
};