monotone-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Monotone-devel] Re: [PATCH] Updated Typesafe VA_ARGS replacement for da


From: Vinzenz 'evilissimo' Feenstra
Subject: [Monotone-devel] Re: [PATCH] Updated Typesafe VA_ARGS replacement for database::execute/fetch
Date: Thu, 19 Jan 2006 12:15:24 +0100
User-agent: Thunderbird 1.5 (Windows/20051201)

Just removed the nasty ifndef directive which was added for testing purposes

BR
Vinzenz


// -*- mode: C++; c-file-style: "gnu"; indent-tabs-mode: nil -*-
// vim:et:sw=2:sts=2:ts=2:cino=>2s,{s,\:s,+s,t0,g0,^-2,e-2,n-2,p2s,(0,=s:
#ifndef __QUERY_ARGS_HH__
#define __QUERY_ARGS_HH__ 1
// copyright (C) 2006 vinzenz feenstra <address@hidden>
// all rights reserved.
// licensed to the public under the terms of the GNU GPL (>= 2)
// see the file COPYING for details
#include <string>
#include <utility>
struct sqlite3_stmt;
struct sqlite3;

struct query_args
{
    struct blob
    {
        explicit blob( void const * data , size_t size ); 
        explicit blob( char const * data , size_t size ); 
        explicit blob( std::string const & data ); 
        void const * get_data() const; 
        size_t const get_size() const;
    private:
        void const * data_p;
        size_t data_size;
    };

    struct text
    {
        explicit text( char const * str , size_t size ); 
        explicit text( std::string const & str ); 
        char const * get_text() const; 
        size_t const get_size() const;
    private:
        char const * str_p;
        size_t data_size;
    };

    explicit query_args( sqlite3 * db_handle , std::string const & sql_query );
    ~query_args();

    query_args & operator%( blob const & bin );
    query_args & operator%( text const & txt );

    // Retrieving the statement 
    // If release is true we don't care anymore whether 
    // the statement will be cleared anywhere else
    sqlite3_stmt * get_statement(bool release = true);
    std::string const & get_query() const;

private:
    void internal_assert();
protected:
    sqlite3_stmt * stmt;
    int params_needed;
    int last_param_nr;
    std::string query;
    static bool already_instantiated;
};

#endif // __QUERY_ARGS_HH__
// -*- mode: C++; c-file-style: "gnu"; indent-tabs-mode: nil -*-
// vim:et:sw=2:sts=2:ts=2:cino=>2s,{s,\:s,+s,t0,g0,^-2,e-2,n-2,p2s,(0,=s:
// copyright (C) 2006 vinzenz feenstra <address@hidden>
// all rights reserved.
// licensed to the public under the terms of the GNU GPL (>= 2)
// see the file COPYING for details
#include "sqlite3.h"
#include "query_args.hh"

bool query_args::already_instantiated = false;

query_args::blob::blob( void const * data , size_t size )
:data_p(data),data_size(size)
{}

query_args::blob::blob( char const * data , size_t size )
:data_p(data),data_size(size)
{}

query_args::blob::blob( std::string const & data )
:data_p(data.c_str()),data_size(data.size())
{}

void const * query_args::blob::get_data() const
{
    return data_p;
}

size_t const query_args::blob::get_size() const
{   
    return data_size;
}

query_args::text::text( char const * str , size_t size )
:str_p(str),data_size(size)
{}

query_args::text::text( std::string const & str )
:str_p(str.c_str()),data_size(str.size())
{}

char const * query_args::text::get_text() const
{
    return str_p;
}

size_t const query_args::text::get_size() const
{
    return data_size;
}

query_args::query_args( sqlite3 * db_handle , std::string const & sql_query )
:stmt(0),
params_needed(0),
last_param_nr(1),
query(sql_query)
{
    I(!already_instantiated);
    already_instantiated = true;

    char const * tail = 0;
    sqlite3_prepare(db_handle, query.c_str() , -1, &stmt , &tail);
    internal_assert();

    L(F("prepared statement %s\n") % query);

    // no support for multiple statements here
    E(*tail == 0, 
        F("multiple statements in query: %s\n") % query);

    params_needed = sqlite3_bind_parameter_count(stmt);
}

query_args::~query_args()
{
    // if the statement still exists we're cleaning it
    // since the database can't be closed properly if it
    // is still opened
    if(stmt)
    {
        L("Resetting sqlite3_statement");
        sqlite3_reset(stmt);
        L("Finalizing sqlite3_statement");
        sqlite3_finalize(stmt) != SQLITE_OK
    }
    already_instantiated = false;
}

std::string const & query_args::get_query() const
{
    return query;
}

sqlite3_stmt * query_args::get_statement( bool release )
{
    // Ensure that we have all params needed, otherwise 
    I( params_needed == last_param_nr );

    // Retrieving the statement 
    // If release is true we don't care anymore whether 
    // the statement will be cleared anywhere else
    if(release)
    {        
        L("Returning statement and releasing the ownership of the sqlite3_stmt 
pointer");
        sqlite3_stmt * tmp = stmt;
        stmt = 0;
        return tmp;
    }
    // returning the statement and keep ownership of the 
    // statement
    L("Returning statement and keeping the ownership of the sqlite3_stmt 
pointer");
    return stmt;
}

query_args & query_args::operator%( blob const & bin )
{
    L( F("Binding argument %d of %d as BLOB, with Value %s") % last_param_nr % 
params_needed % (char const*)bin.get_data() );
    if(stmt)
    {
        
sqlite3_bind_blob(stmt,last_param_nr++,bin.get_data(),bin.get_size(),SQLITE_TRANSIENT);
        internal_assert();
    }
    return *this;
}
// as TEXT
query_args & query_args::operator%( text const & txt )
{
    L( F("Binding argument %d of %d as TEXT, with Value %s") % last_param_nr % 
params_needed % txt.get_text() );
    if(stmt)
    {
        
sqlite3_bind_text(stmt,last_param_nr++,txt.get_text(),int(txt.get_size()),SQLITE_TRANSIENT);
        internal_assert();
    }    
    return *this;
}

void query_args::internal_assert()
{
    sqlite3 * s = sqlite3_db_handle(stmt);

    int errcode = sqlite3_errcode(s);

    if (errcode == SQLITE_OK) return;

    const char * errmsg = sqlite3_errmsg(s);

    // sometimes sqlite is not very helpful
    // so we keep a table of errors people have gotten and more helpful versions
    if (errcode != SQLITE_OK)
    {
        // first log the code so we can find _out_ what the confusing code
        // was... note that code does not uniquely identify the errmsg, unlike
        // errno's.
        L(F("sqlite error: %d: %s") % errcode % errmsg);
    }
    std::string auxiliary_message = "";
    if (errcode == SQLITE_ERROR)
    {
        auxiliary_message = _("make sure database and containing directory are 
writeable");
    }
    // if the last message is empty, the \n will be stripped off too
    E(errcode == SQLITE_OK,
        // kind of string surgery to avoid ~duplicate strings
        boost::format("%s\n%s")
        % (F("sqlite error: %d: %s") % errcode % errmsg).str()
        % auxiliary_message);
}


reply via email to

[Prev in Thread] Current Thread [Next in Thread]