Commit fb16f53a authored by jan.koester's avatar jan.koester
Browse files

new api

parent 96c11754
Loading
Loading
Loading
Loading

backends/backend.cpp

0 → 100644
+73 −0
Original line number Diff line number Diff line
/*******************************************************************************
 * Copyright (c) 2023, Jan Koester jan.koester@gmx.net
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 * Redistributions of source code must retain the above copyright
 *      notice, this list of conditions and the following disclaimer.
 * Redistributions in binary form must reproduce the above copyright
 *      notice, this list of conditions and the following disclaimer in the
 *      documentation and/or other materials provided with the distribution.
 * Neither the name of the <organization> nor the
 *      names of its contributors may be used to endorse or promote products
 *      derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *******************************************************************************/

#include <database.h>

#include "pgsql.h"
#include "sqlite.h"

dbpp::Database::Database(int dbdriver,const char* connstr){
    switch(dbdriver){
        case DBDriver::pgsql:
            _DBApi= new Postgresql(connstr);
            break;
        case DBDriver::sqlite:
            _DBApi = new SQLite(connstr);
            break;
        default:
            break;
    }
}

dbpp::Database::~Database(){
    delete _DBApi;
}

int dbpp::Database::exec(const dbpp::SQL &sql,DBResult &res){
    return _DBApi->exec(sql,res);
}

const char *dbpp::Database::getDriverName(){
    return _DBApi->getDriverName();
}

const dbpp::SQL &dbpp::Database::autoincrement(dbpp::SQL &sql){
    return _DBApi->autoincrement(sql);
}

const dbpp::SQL &dbpp::Database::getUUIDType(dbpp::SQL &sql){
    return _DBApi->getUUIDType(sql);
}

bool dbpp::Database::isConnected(){
    return _DBApi->isConnected();

}

void dbpp::Database::reset(){
    _DBApi->reset();
}

backends/duck.h

0 → 100644
+0 −0

Empty file added.

backends/pgsql.h

0 → 100644
+117 −0
Original line number Diff line number Diff line
/*******************************************************************************
 * Copyright (c) 2023, Jan Koester jan.koester@gmx.net
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 * Redistributions of source code must retain the above copyright
 *      notice, this list of conditions and the following disclaimer.
 * Redistributions in binary form must reproduce the above copyright
 *      notice, this list of conditions and the following disclaimer in the
 *      documentation and/or other materials provided with the distribution.
 * Neither the name of the <organization> nor the
 *      names of its contributors may be used to endorse or promote products
 *      derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *******************************************************************************/

#include <mutex>

#include <httppp/exception.h>

#include <libpq-fe.h>

#include <database.h>

namespace dbpp {

    std::mutex g_lock_mutex;

    class Postgresql : public DatabaseApi{
    public:
        Postgresql(const char *constr) {
            _dbconn = PQconnectdb(constr);
            if (PQstatus(_dbconn) != CONNECTION_OK){
                libhttppp::HTTPException exp;
                exp[libhttppp::HTTPException::Critical] << PQerrorMessage(_dbconn);
                PQfinish(_dbconn);
                throw exp;
            }
        }

        ~Postgresql(){
            PQfinish(_dbconn);
        }

        int exec(const SQL &sql,DBResult &res) override{
            PGresult *pres = PQexec(_dbconn,sql.c_str());
            int pstate=PQresultStatus(pres);

            if(pstate==PGRES_FATAL_ERROR || pstate==PGRES_BAD_RESPONSE) {
                 libhttppp::HTTPException exp;
                 exp[libhttppp::HTTPException::Critical] << PQerrorMessage(_dbconn);
                 PQclear(pres);
                 throw exp;
            }

            res.clear();

            DBResult::Data *lastdat=nullptr;

            int rcount=PQntuples(pres);

            for(int i = 0; i < rcount; ++i ){
                for(int ii=0; ii < PQnfields(pres); ++ii){
                    if(!res.firstRow){
                       res.firstRow = new DBResult::Data(i,ii,PQgetvalue(pres,i,ii),PQgetlength(pres,i,ii));
                       lastdat=res.firstRow;
                    }else{
                       lastdat->nextData=new DBResult::Data(i,ii,PQgetvalue(pres,i,ii),PQgetlength(pres,i,ii));
                       lastdat=lastdat->nextData;
                    }
                }
            }

            PQclear(pres);

            return rcount;
        };

        const char *getDriverName() override{
            return "pgsql";
        };

        const SQL &autoincrement(SQL &sql) override{
            return (sql << "GENERATED BY DEFAULT AS IDENTITY");
        }

        const SQL &getUUIDType(SQL &sql) override {
            return (sql << "UUID");
        }

        bool isConnected() override{
            const std::lock_guard<std::mutex> lock(g_lock_mutex);
            if(PQstatus(_dbconn)==CONNECTION_OK)
                return true;
            return false;
        }

        void reset() override{
            const std::lock_guard<std::mutex> lock(g_lock_mutex);
            PQreset(_dbconn);
        }

    private:
        PGconn      *_dbconn;
    };
}

backends/sqlite.h

0 → 100644
+153 −0
Original line number Diff line number Diff line
/*******************************************************************************
 * Copyright (c) 2023, Jan Koester jan.koester@gmx.net
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 * Redistributions of source code must retain the above copyright
 *      notice, this list of conditions and the following disclaimer.
 * Redistributions in binary form must reproduce the above copyright
 *      notice, this list of conditions and the following disclaimer in the
 *      documentation and/or other materials provided with the distribution.
 * Neither the name of the <organization> nor the
 *      names of its contributors may be used to endorse or promote products
 *      derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *******************************************************************************/

#include <iostream>
#include <atomic>

#include <httppp/exception.h>

#include <sqlite3.h>

#include <database.h>

namespace dbpp {

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

    class SQLite : public DatabaseApi{
    public:
        SQLite(const char *constr){
            while( sqllock.exchange(true, std::memory_order_acquire) );
            int status=sqlite3_open(constr,&_dbconn);
            if (status != SQLITE_OK ){
                libhttppp::HTTPException exp;
                exp[libhttppp::HTTPException::Critical] << sqlite3_errmsg(_dbconn);
                sqlite3_close(_dbconn);
                throw exp;
            }
            sqllock.store(false);

        }

        ~SQLite(){
            sqlite3_close(_dbconn);
        }

        int exec(const SQL &sql,DBResult &res) override{
            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;
            int rcount = 0;

            res.clear();

            DBResult::Data *lastdat;

            const char *cssql=ssql;

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

                cssql=sqlptr;

                if(pstate == SQLITE_ERROR) {
                    std::cerr << sqlite3_errmsg(_dbconn) << std::endl;
                    continue;
                }

                if(!prep)
                    continue;

                int pcode;

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

                   if(pcode==SQLITE_ERROR){
                        libhttppp::HTTPException exp;
                        exp[libhttppp::HTTPException::Critical] << sqlite3_errmsg(_dbconn);
                        delete[] ssql;
                        sqllock.store(false);
                        throw exp;
                    }

                    if(pcode==SQLITE_ROW){
                         int i;
                         for(i=0; i < sqlite3_column_count(prep); ++i){
                            if(!res.firstRow){
                                res.firstRow = new DBResult::Data(rcount,i,(const char*)sqlite3_column_text(prep,i),sqlite3_column_bytes(prep,i));
                                lastdat=res.firstRow;
                            }else{
                                lastdat->nextData=new DBResult::Data(rcount,i,(const char*)sqlite3_column_text(prep,i),sqlite3_column_bytes(prep,i));
                                lastdat=lastdat->nextData;
                            }
                        }
                        ++rcount;
                    }
          
                } 
                sqlite3_finalize(prep);
            }while(cssql != ssql+sql.size());

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

        const char *getDriverName() override{
            return "sqlite";
        };

        const SQL &autoincrement(SQL &sql) override{
            return (sql <<"AUTOINCREMENT");
        }


        const SQL &getUUIDType(SQL &sql) override{
            return (sql << "Binary()");
        }

        bool isConnected() override{
            int current,high;
            if(sqlite3_db_status(_dbconn,0,&current,&high,0)==SQLITE_OK)
                return true;
            return false;
        }

        void reset() override{
            int current,high;
            sqlite3_db_status(_dbconn,0,&current,&high,1);
        }

    private:

        sqlite3  *_dbconn;
    };
}