Giter Site home page Giter Site logo

soci / soci Goto Github PK

View Code? Open in Web Editor NEW
1.3K 94.0 468.0 59.48 MB

Official repository of the SOCI - The C++ Database Access Library

Home Page: http://soci.sourceforge.net/

License: Boost Software License 1.0

Shell 1.97% C++ 88.84% HTML 0.92% CMake 4.18% C 0.32% Ada 3.53% CSS 0.04% PowerShell 0.12% Batchfile 0.08%
cplusplus database-library postgresql mysql odbc db2 firebird sqlite3 boost oracle

soci's Introduction

SOCI - The C++ Database Access Library

GitHub release GitHub commits

Website SourceForge

Gitter Mailing Lists StackExchange

Build Status

Branches GitHub Actions AppVeyor-CI Documentation Coverity Scan
master Build Status Build status Docs Status Coverage
release/4.0 Build Status Build status Docs Status

History

Originally, SOCI was developed by Maciej Sobczak at CERN as abstraction layer for Oracle, a Simple Oracle Call Interface. Later, several database backends have been developed for SOCI, thus the long name has lost its practicality. Currently, if you like, SOCI may stand for Simple Open (Database) Call Interface or something similar.

"CERN is also a user of the SOCI library, which serves as a database access layer in some of the control system components."

-- Maciej Sobczak at Inspirel

License

SOCI library is distributed under the terms of the Boost Software License.

Requirements

Core:

  • Compile with C++14 support (please use 4.0 series for C++98 support) or MSVS 2015 or later.
  • Optionally: Boost C++ Libraries (header-only and Boost.DateTime).

Backend specific client libraries for:

  • DB2
  • Firebird
  • MySQL
  • ODBC with specific database driver
  • Oracle
  • PostgreSQL
  • SQLite 3

See documentation at soci.sourceforge.net for details

BSL © Maciej Sobczak and contributors.

soci's People

Contributors

alex-vol-sv avatar alexott avatar arnaudd-fr avatar astrinus avatar avg-i avatar cavaler avatar ccosminsls avatar cstiborg avatar da115115 avatar hobu avatar hrabe avatar juliantaylor avatar krzmbrzl avatar lebdron avatar mloskot avatar msobczak avatar nobodyxu avatar onidaito avatar pbondo avatar pfedor avatar ricardofandrade avatar snikulov avatar soyersoyer avatar thesiv avatar tomay3000 avatar toonen avatar tt4g avatar vadz avatar vnaydionov avatar zann1x avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

soci's Issues

Server-side memory leak in PostgreSQL

I try use SOCI in my project. But after some time I found, that SQL server (postgresql-8.4, 9.1, and 9.2) has eat all memory and killed by oom-killer. After some investigations I update library to recent master (today). But problem not fixed yet.

get_affected_rows() returns -1 for bulk operations

Any attempt to call statement::get_affected_rows() after a bulk operation results in -1.
It happens because postgresql statement class clears its result_ member variable after each iteration.
You can't rely on the number of inputs as a way to deduce this information (specially for DELETE and UPDATE).
Accumulating the number of affected rows seems to be a reasonable solution.

I didn't tested other backends. If this is really considered a bug, I can help with a patch.

Unexpected behavior in rowset::begin()

This ticket is related to old report posted to soci-users in Unexpected behavior in rowset begin():


rowset<row>::const_iterator i = rs.begin();
    for (i=rs.begin(); i != rs.end(); ++i)
    {
       // do something
    }

The calls to rs.begin() increment the row counter in backend fetch for each call. The first begin returns the first row, the subsequent begin call increments the row counter and returns the next row, not the first row.


First, by design, the rowset iterator is of category of input iterator, so it is not guaranteed that it is possible to pass through the same input iterator twice.

In this situation, however, there are two distinct iterators acquired from the subsequent calls to begin(). The problem here is that all the iterators share the same source, they walk through he same rowset, so they share all the side effects caused by the iteration.

Thus, additional restrictions apply to the rowset iterator. It's similar to istream_iterator- you can't have two iterators walking over the same range of input stream.

So, short answer is that the current behaviour is by design. It is not a bug.

Long answer, I reckon is that it should be possible to change the current implementation, so each iterator will manage its own distinct descriptor of rowset range. It is important to avoid copying of rowset. In fact, it may be impossible to make deep copy of rowset.

If anyone is interested in implementing it, that would be great.
I'm leaving this as a task for future work.

Add common tests to DB2

@akashihi it would be good to try to run the common tests against DB2 backend.

I've tried to run the common tests against DB2 and I there is problem with prepared statements. Perhaps there is some kind of limitation. Basically, common_tests::test6() is failing on repeated statement::execute calls with use object re-used:

statement st = (sql.prepare << "insert into soci_test(id) values(:id)", use(i));
 i = 5;
 st.execute(true);
 i = 6;
 st.execute(true);

At the second call to st.execute throws error:

SQLMESSAGE: [IBM][CLI Driver] CLI0100E  Wrong number of parameters. SQLSTATE=07001

I'm going to submit pull request with basic framework for these tests ready.

postgresql backend leaks a PGResult* when an exception is thrown

According to the libpq documentation at http://www.postgresql.org/docs/9.2/static/libpq-exec.html:

PQclear
Frees the storage associated with a PGresult. Every command result should be freed via PQclear when it is no longer needed. ... You can keep a PGresult object around for as long as you need it; it does not go away when you issue a new command, nor even if you close the connection. To get rid of it, you must call PQclear. Failure to do this will result in memory leaks in your application.

In src/backends/postgresql/error.cpp, soci::details::postgresql::throw_postgresql_soci_error accepts a PGresult* as input, but never calls PQclear before throwing an exception:

void soci::details::postgresql::throw_postgresql_soci_error(PGresult *res)
{
    std::string msg;
    std::string sqlstate;

    get_error_details(res, msg, sqlstate);
    throw postgresql_soci_error(msg, sqlstate.c_str());
}   

I don't see any place where the PGresult* is freed after the exception is thrown (e.g. in an exception handler somewhere up the call stack). I think the fix is to call PQclear before throwing the exception:

void soci::details::postgresql::throw_postgresql_soci_error(PGresult *res)
{
    std::string msg;
    std::string sqlstate;

    get_error_details(res, msg, sqlstate);
    PQclear(res); // <- add this
    throw postgresql_soci_error(msg, sqlstate.c_str());
}   

I verified the leak and the fix using valgrind's memcheck tool. Here's what valgrind said before implementing the fix:

==11046== 2,248 (200 direct, 2,048 indirect) bytes in 1 blocks are definitely lost in loss record 36 of 38
==11046==    at 0x4C2B6CD: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==11046==    by 0x4E41A33: PQmakeEmptyPGresult (in /usr/lib/libpq.so.5.4)
==11046==    by 0x4E4A417: ??? (in /usr/lib/libpq.so.5.4)
==11046==    by 0x4E4B217: ??? (in /usr/lib/libpq.so.5.4)
==11046==    by 0x4E4384F: PQgetResult (in /usr/lib/libpq.so.5.4)
==11046==    by 0x4E43BA7: ??? (in /usr/lib/libpq.so.5.4)
==11046==    by 0x456A71: soci::postgresql_statement_backend::prepare(std::string const&, soci::details::statement_type) (statement.cpp:168)
==11046==    by 0x434493: soci::details::statement_impl::prepare(std::string const&, soci::details::statement_type) (statement.cpp:231)
==11046==    by 0x43389A: soci::details::statement_impl::statement_impl(soci::details::prepare_temp_type const&) (statement.cpp:60)
==11046==    by 0x40E442: soci::statement::statement(soci::details::prepare_temp_type const&) (in ...)
==11046==    by 0x40FD6C: soci::details::rowset_impl<SupportIssue>::rowset_impl(soci::details::prepare_temp_type const&) (rowset.h:120)

To reproduce the problem, force the postgresql backend to throw an exception about an error reported by libpq. Here is a simple test case:

try {
    rowset<string> rs = (sql.prepare << "select column_that_does_not_exist from table");
} catch(...) {
    // memory leak!
}

Throw if truncation happens but no indicators was provided

Currently if a select statement results in a null value and no indicator is defined for the corresponding output parameter, a "Null value fetched and no indicator defined." exception is thrown. However when the same happens with truncation, it is silently ignored if there is no indicator (if there is one, the truncation is reported via it). This is inconsistent and actually dangerous as the data can be silently corrupted, so we should throw an exception when this happens instead of just ignoring it.

As this would be a backwards incompatible change, it should only be done in 4.0 and not in any of 3.x releases.

Update code examples

Some of the code examples in docs use old API names.
For example, in the Exchange chapter:

template<>
struct TypeConversion<Person>

should read:

template<>
struct type_conversion<Person>

Binding procedure IN/OUT parameter has no out effect

The following step in Oracle test7 is failing:

    // test procedure with user-defined type as in-out parameter
    {
        in_out_procedure_creator procedureCreator(sql);

        string_holder sh("test");
        procedure proc = (sql.prepare << "soci_test(:s)", use(sh));
        proc.execute(1);
        assert(sh.get() == "testtest");
    }

I noticed that a few days ago while testing Oracle backend built with VS2012 and InstantClient 11g, and I e-mailed Maciej asking for some background on previous design of IN/OUT parameters binding for procedures.

@vnaydionov also pointed at this problem and proposed some (temporary?) fix in his pull request #75 (specific commit SHA: vnaydionov/soci@3d6ccd1). The comment there suggests the problem sneaked with optimisation made by @vadz in SHA: 22e740a

I'm hesitant to merge @vnaydionov commit, not because it's incorrect, but because I'd prefer to clarify how the bindings was originally designed to work in this case, then review all following changes related to the original implementation. Otherwise, we will be chasing our own tails overwriting fix on fix muddying root of the real problem.

Meanwhile, I'm closing #75 as other commits there has been cherry-picked already.
All new commits related to this particular bug shall be submitted separately.

Apply Git workflow: GitFlow

This task discusses Git workflow that is aimed to be applied before releasing next SOCI , either bugfix release for 3.1.0, or new features release SOCI 4.0.0.

At the moment, SOCI development history is flat and there is no easy way to apply bug fixes to existing releases, thus no easy way to issue bug fix releases.

There are two popular Git workflows:

In GitHub Flow article, Scott Chacon says:

For teams that have to do formal releases on a longer term interval (a few weeks to a few
months between releases), and be able to do hot-fixes and maintenance branches and
other things that arise from shipping so infrequently, git-flow makes sense and I would
highly advocate it’s use.

For teams that have set up a culture of shipping, who push to production every day, who are constantly
testing and deploying, I would advocate picking something simpler like GitHub Flow.

I think, git-flow is the right choice for SOCI. It is simple and based on use of two branches only: master and develop, where in fact, on daily basis, only develop branch is used.


What I look for is a dead simple, clear, safe,well structured Git workflow with the following features:

  1. Easy for continuous development and integration of features, patches, pull request
  2. Easy to mark every major release (tags)
  3. Easy to mark every bugfix release (tags)
  4. Easy to maintain what has been released (branches)
    • apply bug fixes
    • issue bugfix release
  5. Repository at github.com/SOCI/soci
    • is the only upstream repository with SOCI source code
    • is a complete history of SOCI (commits, and all milestones and snapshots too)
    • has clear structure of public only stuff, no private branches, no feature brunches
    • must provide access to every release of SOCI, as there were no downloads at SF.net

I also requested for comments on soci-users in Apply Git branching model thread.

Please, feel encouraged to post your comments on this topic.

Clean compiler warnings

Currently, all supported compilers throw variety of warnings. We should address them, preferably add pedantic and strict flags, especially for those potentially buggy issues.

Re-enable g++ testing on travis-ci

As result of adding clang in #92, I effectivelly switched to clang and disabled g++ due to problem with concurrent access to common Oracle database.

Looking for solution to setup both toolsets to run tests using each of them but against different Oracle user/scheme.

Update documentation for 3.2.0 release

The upcoming 3.2.0 will deliver changes in existing features and addition of new features. So, documentation review and update before release is necessary.

error processing table with two fieldnames one of which is part of the other

table persons with two fields

passwd      VARCHAR(20),
passwd_klar VARCHAR(20),

This version works:

db << "INSERT INTO persons(passwd,passwd_klar) VALUES(:passwd, :passwd_klar)", soci::use(p);

This version does not work:

db << "INSERT INTO persons(passwd_klar,passwd) VALUES(:passwd_klar, :passwd)", soci::use(p);

Error is caused by:
file: statement.cpp
Method:

void statement_impl::bind(values & values)

       std::size_t const pos = query_.find(placeholder); 
        --> when searching for placeholder ":passwd" finds position of ":passwd_klar"
                      with nextChar = '_'.

    Thus the following condition does not hold
     if (nextChar == ' ' || nextChar == ',' ||
         nextChar == '\0' || nextChar == ')')
     {
     -->     ":passwd" is added to  values.add_unused

and is consequently not bound to the prepared statement (which in my case results in an "persons.passwd may not be NULL" error).

Add query transformation callback feature

I have received feature request to add support for user-defined last minute query transformation applied just before the query execution:

a) Add ITransformer interface with method ostringstream transform(ostringstream& str) = 0;
b) Add method register_transformer(ITransformer& tr); to session class.
c) Apply the transformation just before the query execution, in method session::get_query_stream()

Presumably, they want to perform something that is equivalent to this:

sql << my_transformer(my_query) ...

but, presumably, the actual code operating on the sql object does not have any knmowledge of my_transformer:

sql.register_filter(my_transformer);
some_other_module::foo(sql);

This is an interesting idea.


A few modifications to the original idea discussed below:

1. Simple approach

Uses plain function pointer interface.

namespace soci {
typedef std::string (*query_transformer_t)(const std::string & query);
}
void soci::session::set_query_transformer(query_transformer_t t);

then, somewhere just before call to prepare(), in final_action(), the transformer could be applied:

if (query_transformer_)
{
    query = query_transformer_(query);
}

This might not be the best option if one wants to manage transformation state easily.

2. Simple and flexible approach

It supports both free functions and function objects.
Note, the code below is just an illustration and does not map 1:1 with SOCI interface.

#include <functional>
#include <string>

// Prototype of additions in SOCI code
namespace soci {
    namespace detail {

        // TODO: use std::unary_function<const std::string&, std::string>
        struct query_transformation_function : public std::unary_function<std::string, std::string>
        {
            virtual ~query_transformation_function() {}
            virtual result_type operator()(argument_type a) const = 0;
        };

        template <typename T>
        struct query_transformation : public query_transformation_function
        {
            query_transformation(T cb) : cb_(cb) {}
            result_type operator()(argument_type a) const
            {
                return cb_(a);
            }
        private:
            T cb_;
        };
    }

    struct session
    {
        template <typename T>
        void set_query_transformation(T cb)
        {
            delete query_transformation_;
            query_transformation_= new detail::query_transformation<T>(cb);
        }

        // This represents the original chain of calls: final_action, get_query_stream, execute
        void execute(std::string s)
        {
            query_ = s;
            if (query_transformation_)
            {
                query_ = query_transformation_->operator()(query_);
            }
            // backEnd_->execute(query_);
        }

        session() : query_transformation_(0) {}
        ~session() { delete query_transformation_; }

    private:
        std::string query_;
        detail::query_transformation_function* query_transformation_;
    };
}

// Usage example
std::string transform_x(std::string query)
{
    return query + " WHERE id = 1";
}

struct TransformX : std::unary_function<std::string, std::string>
{
    result_type operator()(argument_type query) const
    {
        return query + " WHERE name = 'John'";
    }
};

std::string query = "SELECT * FROM x";
soci::session s;
s.set_query_transformation(transform_x);
s.execute(query);
s.set_query_transformation(TransformX());
s.execute(query);

Likely, the option 2. will be implemented.

Add CMake configuration for Firebird

@vnaydionov has done some testing with Firebird for the recent Git master, applied fixes in code and Makefile.basic (see pull #56)) and confirmed it basically works.
So, it would be nice to have Firebird back and released in SOCI 3.2.0.

Before, Firebird needs to be configured for CMake:

  1. Is there FindFirebird.cmake module provided by CMake 2.8.10+? If not, we need to find/create custom one in src/cmake/modules
  2. Add src/cmake/dependencies/Firebird.cmake module and call find_package for Firebird.
  3. Add Firebird to list of searched dependencies in src/cmake/SociDependencies.cmake. (BTW, a separate task, this should be reimplemented to automatically look for files in src/cmake/dependencies/)
  4. Create simple src/backends/firebird/CMakeLists.txt and call soci_backend macro.
  5. Create simple src/backends/firebird/test/CMakeLists.txt and call soci_backend_test macro.

0001-Added-reset-facilities-for-statements.patch from Henning Basold

In the old thread Resetting prepared statements on soci-users, Henning Basold attached 0001-Added-reset-facilities-for-statements.patch file.
The patch has been forgotten, never reviewed or applied

This ticket is to preserve this contribution from Henning.
At least, it may be worth to review it.

I'm going to create branch in my clone at https://github.com/mloskot/soci dedicated for this patch, then manually apply the patch to the current SOCI master.

Anyone interested in this work? Feel free to review it.

Premature deallocation of prepared statement

Fixed prepared statement leak submitted recently in 02bb841b adds clean-up which leads to problems with repeated execution of prepared statements I discuss in unnamed prepared statement does not exist:

session sql(postgresql , "dbname=mydb");
sql << "create table soci_test(id integer)";
int i;
statement st = (sql.prepare << "insert into soci_test(id) values(:id)", use(i));
i = 5;
st.execute(true);
i = 6;
st.execute(true); // ERROR: unnamed prepared statement does not exist

~~Simple fix would be to change the condition to:

if (stType_ != st_repeatable_query && statementName_.empty() == false)

but then, how to detect final execution after which statement deallocation should occur?~~

BTW, playing with GitHub a bit , added line comment to statement.cpp

Run time error: what(): Malformed connection string.

Hello All,

I hope that you can help me. I've installed SOCI on a 64-bit fedora 17 using a g++ 4.7 compiler.

Everything has compiled and linked. Unfortunately I'm getting a runtime error. I've created the mysql DB. I'm not sure what is wrong. Can you help me?

Output:
login=service=my_db user=root password=password

Error
terminate called after throwing an instance of 'soci::soci_error'
  what():  Malformed connection string.

Program received signal SIGABRT, Aborted.
[Switching to Thread 0x7ffff746d700 (LWP 16784)]
0x0000003c25635925 in raise () from /lib64/libc.so.6
Missing separate debuginfos, use: debuginfo-install glibc-2.15-57.fc17.x86_64 keyutils-libs-1.5.5-2.fc17.x86_64 krb5-libs-1.10.2-6.fc17.x86_64 libcom_err-1.42.3-3.fc17.x86_64 libgcc-4.7.2-2.fc17.x86_64 libselinux-2.1.10-3.fc17.x86_64 libstdc++-4.7.2-2.fc17.x86_64 mysql-libs-5.5.28-1.fc17.x86_64 openssl-1.0.0j-2.fc17.x86_64 soci-3.1.0-3.fc17.x86_64 zlib-1.2.5-7.fc17.x86_64
(gdb) up
#1  0x0000003c256370d8 in abort () from /lib64/libc.so.6
(gdb) up
#2  0x0000003c31260dad in __gnu_cxx::__verbose_terminate_handler() ()
   from /lib64/libstdc++.so.6
(gdb) up
#3  0x0000003c3125eea6 in ?? () from /lib64/libstdc++.so.6
(gdb) up
#4  0x0000003c3125eed3 in std::terminate() () from /lib64/libstdc++.so.6
(gdb) up
#5  0x0000003c3125f0fe in __cxa_throw () from /lib64/libstdc++.so.6
(gdb) up
#6  0x00007ffff7b882af in (anonymous namespace)::parse_connect_string(std::string const&, std::string*, bool*, std::string*, bool*, std::string*, bool*, std::string*, bool*, std::string*, bool*, int*, bool*) () from /lib64/libsoci_mysql.so.3.1
(gdb) up
#7  0x00007ffff7b8849c in soci::mysql_session_backend::mysql_session_backend(std::string const&) () from /lib64/libsoci_mysql.so.3.1
(gdb) up
#8  0x00007ffff7b97aeb in soci::mysql_backend_factory::make_session(std::string const&) const () from /lib64/libsoci_mysql.so.3.1
(gdb) up
#9  0x00007ffff7ddbeb6 in soci::session::session(soci::backend_factory const&, std::string const&) () from /lib64/libsoci_core.so.3.1
(gdb) up
#10 0x00000000004203ab in txInsertSQL (this=0x698d30, rsIndex=0, msg=
    "010418:16:5123800") at main.cpp:458
458       session sql1(mysql, login);
(gdb) 

Regards,

Mike

Placeholder at the last position of statement causing crash

(This is bug report with patch I received from Daniel Beaudoin (Optel Vision) on 23/07/2012)

I installed SOCI today and I had problem running one example that is found at thw website: http://soci.sourceforge.net/doc/exchange.html in the Object-relational mapping section.

The statement I had problem with was:

sql << "update person set first_name = :FIRST_NAME "
       "where id = :ID", use(p);

This statement was crashing on my machine, I tried to alter the statement by adding a ";" at the end, there was no crash but it was also not working. I digged a bit in the SOCI source code and found the problem in the statement class. The crash and the failure to work with ";" when the placeholder was at the last position of the statement were two different bug. In attachment you will find the fix for these issues. Is there a more official way to submit bug fixes?

I'm going to submit pull rquest with updated Daniel's patch.

UTF8 MsSql

It seems that MsSql does not use UTF8 encoding so strings that are not latin may not be parsed correctly

Documentation for specializing type_conversion<> doesn't fully explain indicators

I am not sure if this is a bug or just unclear documentation on http://soci.sourceforge.net/doc/exchange.html, so I'll start with some questions:

  1. When specializing type_conversion<>, is the to_base method required to set the indicator equal to some value? The example in the documentation sets ind = i_ok, but I want to know if setting the indicator is required or not.
  2. Is the indicator in to_base an input and output variable, or only an output variable?
  3. If the indicator is only an output variable, then when client code calls soci::use(myType, i_null) won't the i_null be ignored if the user-defined type doesn't represent a null value?

I will try to illustrate the problem implied in question 3 using the following code:

namespace soci
{
    template <>
    struct type_conversion<MyInt>
    {
        typedef int base_type;

        static void from_base(int i, indicator ind, MyInt & mi)
        {
            // ... not important
        }

        static void to_base(const MyInt & mi, int & i, indicator & ind)
        {
            i = mi.get();
            ind = i_ok;
        }
    };
}

Code that wants to store MyInt in the database:

MyInt myInt(1);
soci::indicator ind = soci::i_null;
soci::session db;
db << "INSERT INTO foo (i) VALUES (:myInt)", soci::use(myInt, ind);

In the above code, what is the expected behavior? Should "NULL" be inserted, or should "1"? Currently, the above code results in "1" being inserted, even though the indicator was set to i_null. This is caused by the fact that to_base always sets the indicator to i_ok, even when it was explicitly set to i_null by the calling code.

One way to fix this issue would be to check ind in to_base to make sure the client code didn't set it to i_null:

        static void to_base(const MyInt & mi, int & i, indicator & ind)
        {
            if (ind != i_null) {
                i = mi.get();
                ind = i_ok;
            }
        }

This works fine, until the client code doesn't use an indicator:

MyInt myInt(1);
soci::session db;
db << "INSERT INTO foo (i) VALUES (:myInt)", soci::use(myInt);

Now, you will get undefined behavior because the indicator passed to to_base can come from soci::conversion_use_type::ind_, which is referencing soci::conversion_use_type::ownInd_, which was doesn't appear to be explicitly set when the client code used soci::use(T) instead of soci::use(T, indicator). This means that ownInd_ might be uninitialized. I see in my program that sometimes it is i_null and other times it is i_ok, which causes the exact same piece of client code to behave in different ways depending on which garbage value ownInd_ gets initialized to.

oracle backend doesn't really support prepared statements with vector<string> parameter

oracle_vector_use_type_backend::prepare_for_bind requires that a vector parameter is populated with the actual data. At the same time oracle_vector_use_type_backend::pre_use is a NOP for that parameter.
This is unlike all other types of parameters.

Because of this it is not possible to re-use such a prepared statement with different data in the parameter.

One possibility of resolving this is to use an approach similar to vector of long long.
That is require that the bind-time vector size corresponds to the maximum size of the data. And also require that, for example, the first element in a vector contains a string with a size that corresponds to the maximum string length in the actual data.

A better solution, could be to use either OCI_DATA_AT_EXEC mode with OCIBindByPos/OCIBindByName or to use OCIBindDynamic.

More OCI details could be found here:
http://docs.oracle.com/cd/B10500_01/appdev.920/a96584/oci05bnd.htm#427755

Incorrect assertion in postgresql::get_error_details

This is bug report I received from Fedor Trushkin on 22/10/2012:


Today I hit a bug in SOCI PostgreSQL backend. I thought that it would be nice to make a bug report, but can't find that option on SOCI SourceForge.

Actually, the bug is trivial:

void soci::details::postgresql::get_error_details(PGresult *res,
    std::string &msg, std::string &sqlstate)
{
   msg = PQresultErrorMessage(res);
   const char *sqlst = PQresultErrorField(res, PG_DIAG_SQLSTATE);
   assert(sqlst);  <----- HERE
   assert(std::strlen(sqlst) == 5);
   sqlstate.assign(sqlst, 5);
}

That assertment is not valid, since NULL may be actually returned (see
http://www.postgresql.org/docs/8.3/static/libpq-exec.html). That happens in my case
when connection to server is broken. As a quick solution I would suggest to write:

   const char* blank_sql_state = \"     \";
   if ( ! sqlst ) {
      sqlst = blank_sql_state;
   }
   assert(sqlst && std::strlen(sqlst) == 5);
   sqlstate.assign(sqlst, 5);

Thanks to Fedor for the report.

FindMySQL.cmake update for custom mysqlclient location

@pfedor reported that CMake has troubles finding MySQL libraries if installed in custom non-standard location. Even specifying full path to libraries doesn't seem to work.

The FindMySQL.cmake module we use at the moment is very basic, so it may be lacking.
I'm aiming to update it according to better implementation from KDE.

unexpected behavior in soci::row::get for unsigned and long types

Hey guys,

Is there any special reason to force all unsigned types to be long long while getting a value from a row?

I expected unsigned char, unsigned short to be an int and unsigned int to be long long.

Besides that, there's no type traits support for neither long nor unsigned long.

I saw how you select types for exchange and long is there, including the support for both 4-byte and 8-byte long variations.

Do you see any problem in changing/improving that?

Thanks,
Ricardo

make install - Fedora 17

Hello All,

I wanted to let you know that the "make install" doesn't seem to be working all the way. It load the core and empty files into the /usr/lib64/, but not the libsoci_mysql.so-3.1.0.

I had to copy over the lib files that was missing and created the 2 symbolic links (libsoci_mysql.so, libsoci_mysql.so-3.1,) that were generate from the make.

Regards,

Mike

Build failure with Oracle Instant Client 11.2.0.3.0

Hello, I'm writing on behalf of the MacPorts package management system. We are trying to update our port of Oracle Instant Client from 10.2.0.4.0 to 11.2.0.3.0, but doing this causes soci to fail to build with Oracle support. I tested version 3.1.0 and 176805b from git with the same result. This is the error message:

ld: can't link with bundle (MH_BUNDLE) only dylibs (MH_DYLIB) for architecture x86_64

We get the same error when trying to build TOra 2.1.3 with Oracle support.

Here is the full build log. I'm on OS X 10.8.2 compiling with Xcode 4.6's version of clang ("Apple LLVM version 4.2 (clang-425.0.24) (based on LLVM 3.2svn)").

No rows affected after UPDATE command

This is still a little bit mysterious issue, so investigation is in progress. Here is related soci-users thread get_affected_rows() after UPDATE.

The problem is leaking in SOCI/soci/builds/2986243 as:

 /home/travis/builds/SOCI/soci/src/backends/sqlite3/test/test-sqlite3.cpp:290:
    void test6(): Assertion `st1.get_affected_rows() == 10' failed.

I've briefly tracked down the problem and it looks that for UPDATE SQL command, the relevant sequence is this:

  1. satement_impl::execute(false) executing equivalent of this:
int num = 0;
statement_backend::exec_fetch_result res = backEnd_->execute(num);
  1. sqlite3_statement_backend::execute(number=0)
  2. sqlite3_statement_backend::load_rowset(totalRows=0) in sqlite3/statement.cpp:87
  3. totalRows leads to empty dataCache_.resize(totalRows); in sqlite3/statement.cpp:100
  4. For empty dataCache_, no SQL command is executed
  5. Result: UPDATE SQL with prepared statement has no effect

The bug is definitely fixable, but what puzzles me is

  • has it never worked?
  • if it worked, when it's got broken,

since the implementation of execute/load_rowset hasn't changed since the beginning of time:

As I haven't touched many places in SOCI for ages, before I try to fix
something, I'd rather prefer to understand if/when it's got broken.

FindODBC.cmake deviates from soci_backend() conventions

FindODBC.cmake sets ODBC_INCLUDE_DIRECTORIES variable, but soci_backend() macro handles only ${${DEPU}_INCLUDE_DIR} and ${${DEPU}_INCLUDE_DIRS} variables.
So I think that the name should be changed to ODBC_INCLUDE_DIRS.

Includes are wrong with make-install on Linux Mint

Just FYI when you do a make install on linux mint 14 32 bit the mysql back end header includes the soci_core header but does not take into account the path. The include should be:

include "../soci_core.h"

Currently it is

include "soci_core.h"

I realize if I configured my project to have the location of both headers as include directories this would solve the issue but that seems a little silly to me. Nothing serious, just saying! Thanks for the great lib btw.

Patch with DB2 backend

This is another patch I've found while digging through old archives of SOCI e-mails:


On Wed, 9 Feb 2011 16:49:41 +0200 Denis Chapligin [email protected] wrote:

Here is the patch, that add a DB2 backed to the SOCI. It is based on odbc backend,
as ODBC call and DB2 CLI calls are almost the same. BLOBs aren't supported yet,
but i have plans to implement them.


Here is gist with 0001-Added-DB2-backend.patch

This is an old patch based on pre-SOCI 3.1.0, so it already includes CMake support.
Obviously, the patch needs to be updated, reviewed and tested.

If anyone is interested in helping, feel free to take it over.

Undefined behaviour when use unitialized indicator

This is code from official example:

string name;
indicator ind;

sql << "select name from person where id = 7", into(name, ind);

Mostly this code runs fine (because possibility of ind == i_ok is very very low)...
But, if you change code (this is possible, when use one indicator for few DB calls) to:

string name;
indicator ind = i_ok;

sql << "select name from person where id = 7", into(name, ind);

Then this code always will return i_ok in case of row not found!

To fix it you are need to add initialization of indicator to the constructor (or other place - I do not use prepared statements more than once) of class standard_indicator_type (may be vector_indicator_type also required to be modified, because user may pass non-empty vector of indicators).

Add script templates to simplify CMake configuration

This is extension to idea based on scripts suggested in #4 pull request.

Simply, it would be convenient if there are .bat/.sh helper scripts (templates) to proxy CMake execution. Such scripts would simply consists of list of SOCI-specific variables left to users to uncomment and fill with location of dependencies, ON/OFF switches, etc.

Buried headers and includes cleanup

Long time ago, there was discussion on soci-users about cleaning up structure of SOCI headers and install headers buried in dedicated folder(s). Here is the original discussion soci-users: includes cleanup

It resulted in patch from @juliantaylor (patch/16 in tracker at SourceForge).
Then, @denisarnaud created branch to maintain the buried headers and submitted two pull requests:

Julian also seems to maintain his patch in a branche at https://github.com/juliantaylor/soci

The buried headers subject has been forgotten since. It would be a good idea to pick it up and release with SOCI 4.0.0, so let's discuss it and make the work happen.

New thread related to this ticket at soci-users: Buried headers and includes cleanup


Related ideas

  • This may be a good opportunity to switch headers extension from .h to .hpp and replace - with _ in all file names.

Add ODBC support to Travis-CI configuration

Update .travis.yml to install and configure ODBC for Linux, so the ODBC backend is built by CI machine.

It may also be worth to request CMake to configure ODBC tests, so we have minimal test coverage for this backend.

Add testing against clang on travis-ci

I added clang compiler to .travis.yml (SHA: d3a203b),
but Oracle backend is not building as reported by build 205.2

/usr/bin/ld: warning: libstdc++.so.5, needed by 
    /usr/lib/oracle/xe/app/oracle/product/10.2.0/client/lib/libocci.so, 
    not found (try using -rpath or -rpath-link)

Allocated statement backend memory leaks on exception

My e-mail inbox archived this old report sent by Evgeny Barabanov on 16 December 2012:


Our team is using soci as database connection framework, and I've revealed a
memory leak in case of using sqlite3 backend.
More accurate, the memory leak is not in sqlite3 backend, it is in soci
core, but it is caused by sqlite3 backend implementation.

Here is a flow:

Trying to execute select query with invalid table name:

soci::rowset<soci::row> rs = (m_session.prepare << query);

Arriving to statement_impl constructor in core/statement.cpp

  • Allocating new backend by make_statement_backend method
//Here an unreleased memory is allocated
backEnd_ = session_.make_statement_backend();

...constructor's code

  • Trying to prepare the statement by executing this code:
prepare(query_);
  • Things happens:
    • Arriving to sqlite3_statement_backend::prepare in backends/sqlite3/statement.cpp
    • Getting an sqlite error (because the name of the table is invalid)
    • Throwing a soci_error exception
    • Returning up in the call stack

Exiting from statement_impl constructor without perform clean_up before.

Suggested fix

Place try catch block in constructor, like this:

backEnd_ = session_.make_statement_backend();
ref_counted_prepare_info * prepInfo = prep.get_prepare_info();
// take all bind/define info
intos_.swap(prepInfo->intos_);
uses_.swap(prepInfo->uses_);
// allocate handle
alloc();
// prepare the statement
query_ = prepInfo->get_query();
try
{
    prepare(query_);
}
catch(...)
{
    clean_up();
    throw;
}
define_and_bind();

or consider to change sqlite3_backend implementation.

Our team will appreciate you if you will include this fix in the next
version, please contact us for any questions about this.


Mark Makefile.basic as deprecated

Due to lack of maintainer or active user of the build configuration based on the set of Makefile.basic files who would be willing to submit update, I'm deprecating this build configuration.

In SOCI 3.2.0, they will be marked as obsolete in documentation (SHA: 3af4c03).

In future releases, I'm going to remove these Makefiles, unless they receive update.

Anyone interested in maintaining the basic Makefiles, feel free to submit pull request.

MySQL IEEE floating point representation

It seems that the MySQL backend does not handle special floating points
correct. When NAN or INF is passed to a statement it will return with an
error like this:
Unknown column 'nan' in 'field list'

In my opinion these special floating points must be handled in a special
way. Maybe an SOCI exception?

The following snippet demonstrates the misbehaviour:

#include <iostream>
#include <cmath>

#include <soci.h>
#include <mysql/soci-mysql.h>

using namespace std;

int main(int argc, char **argv) {
  soci::session sql;
  try {
    sql.open(soci::mysql, "host=localhost dbname=test user=test password=test";);
  } catch (std::exception const & e) {
    cerr << "SOCI connect error: " << e.what() << endl;
    return 1;
  }


  double test = NAN;
  soci::statement st = (sql.prepare << "SELECT :test", soci::use(test, "test") );

  try {
    st.execute(true);
  } catch(soci::mysql_soci_error const &e) {
    cerr << e.what() << endl;
    cerr << e.err_num_ << endl;
  }

  return 0;
}

Additional informations about this stuff can be found here http://stackoverflow.com/questions/570669/checking-if-a-double-or-float-is-nan-in-c

Add CMake option SOCI_STATIC

This task involves:

  • Add SOCI_STATIC=ON|OFF option that allows to control build of static libraries (default=ON)
  • Update scripts to test this option and build static targets only if SOCI_STATIC=ON

This will also speed up building and testing on travis-ci cutting the time circa by half.

warning: comparing floating point with == or != is unsafe

Correct the tests using at least comparison with epsilon.

This is split of the large pull request #4 where some of these warnings were cleared.

I'm going to fix it using this formula taken from CATCH suggested by Richard Harris (http://accu.org):

inline bool equal_approx(double const a, double const b)
{
    double const epsilon(std::numeric_limits<float>::epsilon() * 100);
    double const scale(1.0);
    return std::fabs(a - b) < epsilon * (scale + (std::max)(std::fabs(a), std::fabs(b)));
}

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.