auto-handle.hxx   auto-handle.hxx 
skipping to change at line 75 skipping to change at line 75
} }
H* H*
release () release ()
{ {
H* h (h_); H* h (h_);
h_ = 0; h_ = 0;
return h; return h;
} }
operator H* () operator H* () const
{ {
return h_; return h_;
} }
private: private:
auto_handle (const auto_handle&); auto_handle (const auto_handle&);
auto_handle& operator= (const auto_handle&); auto_handle& operator= (const auto_handle&);
private: private:
H* h_; H* h_;
 End of changes. 1 change blocks. 
1 lines changed or deleted 1 lines changed or added


 connection.hxx   connection.hxx 
// file : odb/pgsql/connection.hxx // file : odb/pgsql/connection.hxx
// author : Constantin Michael <constantin@codesynthesis.com> // author : Constantin Michael <constantin@codesynthesis.com>
// copyright : Copyright (c) 2005-2011 Code Synthesis Tools CC // copyright : Copyright (c) 2005-2011 Code Synthesis Tools CC
// license : GNU GPL v2; see accompanying LICENSE file // license : GNU GPL v2; see accompanying LICENSE file
#ifndef ODB_PGSQL_CONNECTION_HXX #ifndef ODB_PGSQL_CONNECTION_HXX
#define ODB_PGSQL_CONNECTION_HXX #define ODB_PGSQL_CONNECTION_HXX
#include <odb/pre.hxx> #include <odb/pre.hxx>
#include <vector>
#include <memory> // std::auto_ptr #include <memory> // std::auto_ptr
#include <odb/forward.hxx> #include <odb/forward.hxx>
#include <odb/connection.hxx> #include <odb/connection.hxx>
#include <odb/details/shared-ptr.hxx> #include <odb/details/shared-ptr.hxx>
#include <odb/pgsql/version.hxx> #include <odb/pgsql/version.hxx>
#include <odb/pgsql/forward.hxx> #include <odb/pgsql/forward.hxx>
#include <odb/pgsql/tracer.hxx>
#include <odb/pgsql/transaction-impl.hxx> #include <odb/pgsql/transaction-impl.hxx>
#include <odb/pgsql/auto-handle.hxx> #include <odb/pgsql/auto-handle.hxx>
#include <odb/pgsql/pgsql-fwd.hxx> // PGconn #include <odb/pgsql/pgsql-fwd.hxx> // PGconn
#include <odb/pgsql/details/export.hxx> #include <odb/pgsql/details/export.hxx>
namespace odb namespace odb
{ {
namespace pgsql namespace pgsql
{ {
class statement;
class statement_cache; class statement_cache;
class connection; class connection;
typedef details::shared_ptr<connection> connection_ptr; typedef details::shared_ptr<connection> connection_ptr;
class LIBODB_PGSQL_EXPORT connection: public odb::connection class LIBODB_PGSQL_EXPORT connection: public odb::connection
{ {
public: public:
typedef pgsql::statement_cache statement_cache_type; typedef pgsql::statement_cache statement_cache_type;
typedef pgsql::database database_type; typedef pgsql::database database_type;
skipping to change at line 65 skipping to change at line 64
public: public:
virtual transaction_impl* virtual transaction_impl*
begin (); begin ();
public: public:
using odb::connection::execute; using odb::connection::execute;
virtual unsigned long long virtual unsigned long long
execute (const char* statement, std::size_t length); execute (const char* statement, std::size_t length);
// SQL statement tracing.
//
public:
typedef pgsql::tracer tracer_type;
void
tracer (tracer_type& t)
{
odb::connection::tracer (t);
}
void
tracer (tracer_type* t)
{
odb::connection::tracer (t);
}
using odb::connection::tracer;
public:
bool
failed () const
{
return failed_;
}
void
mark_failed ()
{
failed_ = true;
}
public: public:
PGconn* PGconn*
handle () handle ()
{ {
return handle_; return handle_;
} }
statement_cache_type& statement_cache_type&
statement_cache () statement_cache ()
{ {
skipping to change at line 93 skipping to change at line 124
void void
init (); init ();
private: private:
// Needed to break the circular connection-database dependency // Needed to break the circular connection-database dependency
// (odb::connection has the odb::database member). // (odb::connection has the odb::database member).
// //
database_type& db_; database_type& db_;
auto_handle<PGconn> handle_; auto_handle<PGconn> handle_;
bool failed_;
// Keep statement_cache_ after handle_ so that it is destroyed before // Keep statement_cache_ after handle_ so that it is destroyed before
// the connection is closed. // the connection is closed.
// //
std::auto_ptr<statement_cache_type> statement_cache_; std::auto_ptr<statement_cache_type> statement_cache_;
}; };
} }
} }
#include <odb/post.hxx> #include <odb/post.hxx>
 End of changes. 5 change blocks. 
2 lines changed or deleted 34 lines changed or added


 container-statements.hxx   container-statements.hxx 
skipping to change at line 190 skipping to change at line 190
if (insert_one_ == 0) if (insert_one_ == 0)
{ {
insert_one_.reset ( insert_one_.reset (
new (details::shared) insert_statement_type ( new (details::shared) insert_statement_type (
conn_, conn_,
insert_one_name_, insert_one_name_,
insert_one_text_, insert_one_text_,
insert_one_types_, insert_one_types_,
insert_one_count_, insert_one_count_,
data_image_binding_, data_image_binding_,
data_image_native_binding_)); data_image_native_binding_,
false,
false));
} }
return *insert_one_; return *insert_one_;
} }
select_statement_type& select_statement_type&
select_all_statement () select_all_statement ()
{ {
if (select_all_ == 0) if (select_all_ == 0)
{ {
select_all_.reset ( select_all_.reset (
new (details::shared) select_statement_type ( new (details::shared) select_statement_type (
conn_, conn_,
select_all_name_, select_all_name_,
select_all_text_, select_all_text_,
select_all_types_, select_all_types_,
select_all_count_, select_all_count_,
cond_image_binding_, cond_image_binding_,
cond_image_native_binding_, cond_image_native_binding_,
data_image_binding_)); data_image_binding_,
false));
} }
return *select_all_; return *select_all_;
} }
delete_statement_type& delete_statement_type&
delete_all_statement () delete_all_statement ()
{ {
if (delete_all_ == 0) if (delete_all_ == 0)
{ {
delete_all_.reset ( delete_all_.reset (
new (details::shared) delete_statement_type ( new (details::shared) delete_statement_type (
conn_, conn_,
delete_all_name_, delete_all_name_,
delete_all_text_, delete_all_text_,
delete_all_types_, delete_all_types_,
delete_all_count_, delete_all_count_,
cond_image_binding_, cond_image_binding_,
cond_image_native_binding_)); cond_image_native_binding_,
false));
} }
return *delete_all_; return *delete_all_;
} }
private: private:
container_statements (const container_statements&); container_statements (const container_statements&);
container_statements& operator= (const container_statements&); container_statements& operator= (const container_statements&);
protected: protected:
 End of changes. 3 change blocks. 
3 lines changed or deleted 7 lines changed or added


 database.hxx   database.hxx 
skipping to change at line 17 skipping to change at line 17
#define ODB_PGSQL_DATABASE_HXX #define ODB_PGSQL_DATABASE_HXX
#include <odb/pre.hxx> #include <odb/pre.hxx>
#include <string> #include <string>
#include <memory> // std::auto_ptr #include <memory> // std::auto_ptr
#include <iosfwd> // std::ostream #include <iosfwd> // std::ostream
#include <odb/database.hxx> #include <odb/database.hxx>
#include <odb/details/shared-ptr.hxx>
#include <odb/pgsql/version.hxx> #include <odb/pgsql/version.hxx>
#include <odb/pgsql/forward.hxx> #include <odb/pgsql/forward.hxx>
#include <odb/pgsql/tracer.hxx>
#include <odb/pgsql/connection.hxx> #include <odb/pgsql/connection.hxx>
#include <odb/pgsql/connection-factory.hxx> #include <odb/pgsql/connection-factory.hxx>
#include <odb/pgsql/details/export.hxx> #include <odb/pgsql/details/export.hxx>
namespace odb namespace odb
{ {
namespace pgsql namespace pgsql
{ {
class transaction_impl; class transaction_impl;
skipping to change at line 101 skipping to change at line 100
connection (); connection ();
public: public:
virtual virtual
~database (); ~database ();
protected: protected:
virtual odb::connection* virtual odb::connection*
connection_ (); connection_ ();
// SQL statement tracing.
//
public:
typedef pgsql::tracer tracer_type;
void
tracer (tracer_type& t)
{
odb::database::tracer (t);
}
void
tracer (tracer_type* t)
{
odb::database::tracer (t);
}
using odb::database::tracer;
public: public:
const std::string& const std::string&
user () const user () const
{ {
return user_; return user_;
} }
const std::string& const std::string&
password () const password () const
{ {
 End of changes. 3 change blocks. 
2 lines changed or deleted 20 lines changed or added


 error.hxx   error.hxx 
// file : odb/pgsql/errors.hxx // file : odb/pgsql/error.hxx
// author : Constantin Michael <constantin@codesynthesis.com> // author : Constantin Michael <constantin@codesynthesis.com>
// copyright : Copyright (c) 2005-2011 Code Synthesis Tools CC // copyright : Copyright (c) 2005-2011 Code Synthesis Tools CC
// license : GNU GPL v2; see accompanying LICENSE file // license : GNU GPL v2; see accompanying LICENSE file
#ifndef ODB_PGSQL_ERRORS_HXX #ifndef ODB_PGSQL_ERROR_HXX
#define ODB_PGSQL_ERRORS_HXX #define ODB_PGSQL_ERROR_HXX
#include <odb/pre.hxx> #include <odb/pre.hxx>
#include <libpq-fe.h> #include <libpq-fe.h>
#include <odb/pgsql/version.hxx> #include <odb/pgsql/version.hxx>
#include <odb/pgsql/forward.hxx> // connection
#include <odb/pgsql/details/export.hxx> #include <odb/pgsql/details/export.hxx>
namespace odb namespace odb
{ {
namespace pgsql namespace pgsql
{ {
class connection;
LIBODB_PGSQL_EXPORT void
translate_error (connection&);
// Translate an error condition involving a PGresult*. If r is null, it is // Translate an error condition involving a PGresult*. If r is null, it is
// assumed that the error was caused due to a bad connection or a memor y // assumed that the error was caused due to a bad connection or a memor y
// allocation error. // allocation error.
// //
LIBODB_PGSQL_EXPORT void LIBODB_PGSQL_EXPORT void
translate_error (connection& c, PGresult* r); translate_error (connection& c, PGresult* r);
// Return true if the PGresult is in an error state. If both s and r ar e // Return true if the PGresult is in an error state. If both s and r ar e
// non-null, the pointed to value will be populated with the result sta tus. // non-null, the pointed to value will be populated with the result sta tus.
// Otherwise, s is ignored. // Otherwise, s is ignored.
// //
LIBODB_PGSQL_EXPORT bool LIBODB_PGSQL_EXPORT bool
is_good_result (PGresult* r, ExecStatusType* s = 0); is_good_result (PGresult* r, ExecStatusType* s = 0);
} }
} }
#include <odb/pgsql/error.ixx> #include <odb/pgsql/error.ixx>
#include <odb/post.hxx> #include <odb/post.hxx>
#endif // ODB_PGSQL_ERRORS_HXX #endif // ODB_PGSQL_ERROR_HXX
 End of changes. 5 change blocks. 
8 lines changed or deleted 4 lines changed or added


 forward.hxx   forward.hxx 
skipping to change at line 21 skipping to change at line 21
#include <odb/forward.hxx> #include <odb/forward.hxx>
namespace odb namespace odb
{ {
namespace pgsql namespace pgsql
{ {
class database; class database;
class connection; class connection;
typedef details::shared_ptr<connection> connection_ptr; typedef details::shared_ptr<connection> connection_ptr;
class connection_factory; class connection_factory;
class statement;
class transaction; class transaction;
class tracer;
class query; class query;
// Implementation details. // Implementation details.
// //
enum statement_kind
{
statement_select,
statement_insert,
statement_update
};
class binding; class binding;
class select_statement; class select_statement;
template <typename T> template <typename T>
class object_statements; class object_statements;
template <typename T> template <typename T>
class object_statements_no_id;
template <typename T>
class view_statements; class view_statements;
template <typename T> template <typename T>
class container_statements; class container_statements;
} }
namespace details namespace details
{ {
template <> template <>
struct counter_type<pgsql::connection> struct counter_type<pgsql::connection>
 End of changes. 4 change blocks. 
0 lines changed or deleted 12 lines changed or added


 object-result.hxx   object-result.hxx 
skipping to change at line 25 skipping to change at line 25
#include <odb/pgsql/version.hxx> #include <odb/pgsql/version.hxx>
#include <odb/pgsql/forward.hxx> // query, object_statements #include <odb/pgsql/forward.hxx> // query, object_statements
#include <odb/pgsql/result.hxx> #include <odb/pgsql/result.hxx>
#include <odb/pgsql/statement.hxx> #include <odb/pgsql/statement.hxx>
namespace odb namespace odb
{ {
namespace pgsql namespace pgsql
{ {
template <typename T> template <typename T>
class result_impl<T, class_object>: class object_result_impl: public odb::object_result_impl<T>
public odb::result_impl<T, class_object>
{ {
public: public:
typedef odb::result_impl<T, class_object> base_type; typedef odb::object_result_impl<T> base_type;
typedef typename base_type::object_type object_type; typedef typename base_type::object_type object_type;
typedef typename base_type::object_traits object_traits; typedef typename base_type::object_traits object_traits;
typedef typename base_type::id_type id_type; typedef typename base_type::id_type id_type;
typedef typename base_type::pointer_type pointer_type; typedef typename base_type::pointer_type pointer_type;
typedef typename base_type::pointer_traits pointer_traits; typedef typename base_type::pointer_traits pointer_traits;
virtual virtual
~result_impl (); ~object_result_impl ();
result_impl (const query&, object_result_impl (const query&,
details::shared_ptr<select_statement>, details::shared_ptr<select_statement>,
object_statements<object_type>&); object_statements<object_type>&);
virtual void virtual void
load (object_type&); load (object_type&, bool fetch);
virtual id_type virtual id_type
load_id (); load_id ();
virtual void virtual void
next (); next ();
virtual void virtual void
cache (); cache ();
skipping to change at line 70 skipping to change at line 69
using base_type::current; using base_type::current;
private: private:
void void
load_image (); load_image ();
private: private:
details::shared_ptr<select_statement> statement_; details::shared_ptr<select_statement> statement_;
object_statements<object_type>& statements_; object_statements<object_type>& statements_;
}; };
template <typename T>
class object_result_impl_no_id: public odb::object_result_impl_no_id<T>
{
public:
typedef odb::object_result_impl_no_id<T> base_type;
typedef typename base_type::object_type object_type;
typedef typename base_type::object_traits object_traits;
typedef typename base_type::pointer_type pointer_type;
typedef typename base_type::pointer_traits pointer_traits;
virtual
~object_result_impl_no_id ();
object_result_impl_no_id (const query&,
details::shared_ptr<select_statement>,
object_statements_no_id<object_type>&);
virtual void
load (object_type&);
virtual void
next ();
virtual void
cache ();
virtual std::size_t
size ();
using base_type::current;
private:
details::shared_ptr<select_statement> statement_;
object_statements_no_id<object_type>& statements_;
};
} }
} }
#include <odb/pgsql/object-result.txx> #include <odb/pgsql/object-result.txx>
#include <odb/post.hxx> #include <odb/post.hxx>
#endif // ODB_PGSQL_OBJECT_RESULT_HXX #endif // ODB_PGSQL_OBJECT_RESULT_HXX
 End of changes. 6 change blocks. 
8 lines changed or deleted 45 lines changed or added


 object-result.txx   object-result.txx 
skipping to change at line 14 skipping to change at line 14
// license : GNU GPL v2; see accompanying LICENSE file // license : GNU GPL v2; see accompanying LICENSE file
#include <odb/callback.hxx> #include <odb/callback.hxx>
#include <odb/pgsql/object-statements.hxx> #include <odb/pgsql/object-statements.hxx>
namespace odb namespace odb
{ {
namespace pgsql namespace pgsql
{ {
//
// object_result_impl
//
template <typename T> template <typename T>
result_impl<T, class_object>:: object_result_impl<T>::
~result_impl () ~object_result_impl ()
{ {
} }
template <typename T> template <typename T>
result_impl<T, class_object>:: object_result_impl<T>::
result_impl (const query&, object_result_impl (const query&,
details::shared_ptr<select_statement> statement, details::shared_ptr<select_statement> statement,
object_statements<object_type>& statements) object_statements<object_type>& statements)
: base_type (statements.connection ().database ()), : base_type (statements.connection ().database ()),
statement_ (statement), statement_ (statement),
statements_ (statements) statements_ (statements)
{ {
} }
template <typename T> template <typename T>
void result_impl<T, class_object>:: void object_result_impl<T>::
load (object_type& obj) load (object_type& obj, bool fetch)
{ {
load_image (); if (fetch)
load_image ();
// This is a top-level call so the statements cannot be locked. // This is a top-level call so the statements cannot be locked.
// //
assert (!statements_.locked ()); assert (!statements_.locked ());
typename object_statements<object_type>::auto_lock l (statements_); typename object_statements<object_type>::auto_lock l (statements_);
odb::database& db (this->database ()); odb::database& db (this->database ());
object_traits::callback (db, obj, callback_event::pre_load); object_traits::callback (db, obj, callback_event::pre_load);
typename object_traits::image_type& i (statements_.image ()); typename object_traits::image_type& i (statements_.image ());
skipping to change at line 69 skipping to change at line 74
idb.version++; idb.version++;
} }
object_traits::load_ (statements_, obj); object_traits::load_ (statements_, obj);
statements_.load_delayed (); statements_.load_delayed ();
l.unlock (); l.unlock ();
object_traits::callback (db, obj, callback_event::post_load); object_traits::callback (db, obj, callback_event::post_load);
} }
template <typename T> template <typename T>
typename result_impl<T, class_object>::id_type typename object_result_impl<T>::id_type
result_impl<T, class_object>:: object_result_impl<T>::
load_id () load_id ()
{ {
load_image (); load_image ();
return object_traits::id (statements_.image ()); return object_traits::id (statements_.image ());
} }
template <typename T> template <typename T>
void result_impl<T, class_object>:: void object_result_impl<T>::
next () next ()
{ {
this->current (pointer_type ()); this->current (pointer_type ());
if (!statement_->next ()) if (!statement_->next ())
this->end_ = true; this->end_ = true;
} }
template <typename T> template <typename T>
void result_impl<T, class_object>:: void object_result_impl<T>::
load_image () load_image ()
{ {
// The image can grow between calls to load() as a result of other // The image can grow between calls to load() as a result of other
// statements execution. // statements execution.
// //
typename object_traits::image_type& im (statements_.image ()); typename object_traits::image_type& im (statements_.image ());
if (im.version != statements_.out_image_version ()) if (im.version != statements_.select_image_version ())
{ {
binding& b (statements_.out_image_binding ()); binding& b (statements_.select_image_binding ());
object_traits::bind (b.bind, im, true); object_traits::bind (b.bind, im, statement_select);
statements_.out_image_version (im.version); statements_.select_image_version (im.version);
b.version++; b.version++;
} }
select_statement::result r (statement_->load ()); select_statement::result r (statement_->load ());
if (r == select_statement::truncated) if (r == select_statement::truncated)
{ {
if (object_traits::grow (im, statements_.out_image_truncated ())) if (object_traits::grow (im, statements_.select_image_truncated ()) )
im.version++; im.version++;
if (im.version != statements_.out_image_version ()) if (im.version != statements_.select_image_version ())
{ {
binding& b (statements_.out_image_binding ()); binding& b (statements_.select_image_binding ());
object_traits::bind (b.bind, im, true); object_traits::bind (b.bind, im, statement_select);
statements_.out_image_version (im.version); statements_.select_image_version (im.version);
b.version++; b.version++;
statement_->reload (); statement_->reload ();
} }
} }
} }
template <typename T> template <typename T>
void result_impl<T, class_object>:: void object_result_impl<T>::
cache ()
{
}
template <typename T>
std::size_t object_result_impl<T>::
size ()
{
return statement_->result_size ();
}
//
// object_result_impl_no_id
//
template <typename T>
object_result_impl_no_id<T>::
~object_result_impl_no_id ()
{
}
template <typename T>
object_result_impl_no_id<T>::
object_result_impl_no_id (const query&,
details::shared_ptr<select_statement> stateme
nt,
object_statements_no_id<object_type>& stateme
nts)
: base_type (statements.connection ().database ()),
statement_ (statement),
statements_ (statements)
{
}
template <typename T>
void object_result_impl_no_id<T>::
load (object_type& obj)
{
// The image can grow between calls to load() as a result of other
// statements execution.
//
typename object_traits::image_type& im (statements_.image ());
if (im.version != statements_.select_image_version ())
{
binding& b (statements_.select_image_binding ());
object_traits::bind (b.bind, im, statement_select);
statements_.select_image_version (im.version);
b.version++;
}
select_statement::result r (statement_->load ());
if (r == select_statement::truncated)
{
if (object_traits::grow (im, statements_.select_image_truncated ())
)
im.version++;
if (im.version != statements_.select_image_version ())
{
binding& b (statements_.select_image_binding ());
object_traits::bind (b.bind, im, statement_select);
statements_.select_image_version (im.version);
b.version++;
statement_->reload ();
}
}
odb::database& db (this->database ());
object_traits::callback (db, obj, callback_event::pre_load);
object_traits::init (obj, im, db);
object_traits::callback (db, obj, callback_event::post_load);
}
template <typename T>
void object_result_impl_no_id<T>::
next ()
{
this->current (pointer_type ());
if (!statement_->next ())
this->end_ = true;
}
template <typename T>
void object_result_impl_no_id<T>::
cache () cache ()
{ {
} }
template <typename T> template <typename T>
std::size_t result_impl<T, class_object>:: std::size_t object_result_impl_no_id<T>::
size () size ()
{ {
return statement_->result_size (); return statement_->result_size ();
} }
} }
} }
 End of changes. 15 change blocks. 
24 lines changed or deleted 117 lines changed or added


 object-statements.hxx   object-statements.hxx 
skipping to change at line 32 skipping to change at line 32
#include <odb/pgsql/binding.hxx> #include <odb/pgsql/binding.hxx>
#include <odb/pgsql/statement.hxx> #include <odb/pgsql/statement.hxx>
#include <odb/pgsql/statements-base.hxx> #include <odb/pgsql/statements-base.hxx>
#include <odb/pgsql/details/export.hxx> #include <odb/pgsql/details/export.hxx>
namespace odb namespace odb
{ {
namespace pgsql namespace pgsql
{ {
template <typename T>
class object_statements;
template <typename T>
class object_statements_no_id;
template <typename T, typename ID = typename object_traits<T>::id_type>
struct object_statements_selector
{
typedef object_statements<T> type;
};
template <typename T>
struct object_statements_selector<T, void>
{
typedef object_statements_no_id<T> type;
};
//
// Implementation for objects with object id.
//
class LIBODB_PGSQL_EXPORT object_statements_base: public statements_bas e class LIBODB_PGSQL_EXPORT object_statements_base: public statements_bas e
{ {
public: public:
// Locking. // Locking.
// //
void void
lock () lock ()
{ {
assert (!locked_); assert (!locked_);
locked_ = true; locked_ = true;
skipping to change at line 87 skipping to change at line 109
auto_unlock& operator= (const auto_unlock&); auto_unlock& operator= (const auto_unlock&);
private: private:
object_statements_base& s_; object_statements_base& s_;
}; };
protected: protected:
bool locked_; bool locked_;
}; };
template <typename T, bool optimistic>
struct optimistic_data;
template <typename T>
struct optimistic_data<T, true>
{
typedef T object_type;
typedef odb::object_traits<object_type> object_traits;
optimistic_data (bind*, char** nv, int* nl, int* nf);
// The id + optimistic column binding.
//
std::size_t id_image_version_;
binding id_image_binding_;
native_binding id_image_native_binding_;
details::shared_ptr<delete_statement> erase_;
};
template <typename T>
struct optimistic_data<T, false>
{
optimistic_data (bind*, char**, int*, int*) {}
};
template <typename T> template <typename T>
class object_statements: public object_statements_base class object_statements: public object_statements_base
{ {
public: public:
typedef T object_type; typedef T object_type;
typedef odb::object_traits<object_type> object_traits; typedef odb::object_traits<object_type> object_traits;
typedef typename object_traits::id_type id_type; typedef typename object_traits::id_type id_type;
typedef typename object_traits::pointer_type pointer_type; typedef typename object_traits::pointer_type pointer_type;
typedef typename object_traits::image_type image_type; typedef typename object_traits::image_type image_type;
typedef typename object_traits::id_image_type id_image_type; typedef typename object_traits::id_image_type id_image_type;
typedef pointer_cache_traits<pointer_type> object_cache_traits; typedef pointer_cache_traits<pointer_type> object_cache_traits;
typedef typedef
typename object_traits::container_statement_cache_type typename object_traits::container_statement_cache_type
container_statement_cache_type; container_statement_cache_type;
typedef pgsql::insert_statement persist_statement_type; typedef pgsql::insert_statement insert_statement_type;
typedef pgsql::select_statement find_statement_type; typedef pgsql::select_statement select_statement_type;
typedef pgsql::update_statement update_statement_type; typedef pgsql::update_statement update_statement_type;
typedef pgsql::delete_statement erase_statement_type; typedef pgsql::delete_statement delete_statement_type;
// Automatic lock. // Automatic lock.
// //
struct auto_lock struct auto_lock
{ {
// Lock the statements unless they are already locked in which // Lock the statements unless they are already locked in which
// case subsequent calls to locked() will return false. // case subsequent calls to locked() will return false.
// //
auto_lock (object_statements&); auto_lock (object_statements&);
skipping to change at line 179 skipping to change at line 227
void void
clear_delayed () clear_delayed ()
{ {
if (!delayed_.empty ()) if (!delayed_.empty ())
clear_delayed_ (); clear_delayed_ ();
} }
// Object image. // Object image.
// //
image_type& image_type&
image () image () {return image_;}
{
return image_;
}
// Insert binding.
//
std::size_t std::size_t
in_image_version () const insert_image_version () const { return insert_image_version_;}
{
return in_image_version_; void
} insert_image_version (std::size_t v) {insert_image_version_ = v;}
binding&
insert_image_binding () {return insert_image_binding_;}
// Update binding.
//
std::size_t std::size_t
out_image_version () const update_image_version () const { return update_image_version_;}
{
return out_image_version_;
}
void void
in_image_version (std::size_t v) update_image_version (std::size_t v) {update_image_version_ = v;}
{
in_image_version_ = v; std::size_t
} update_id_image_version () const { return update_id_image_version_;}
void void
out_image_version (std::size_t v) update_id_image_version (std::size_t v) {update_id_image_version_ = v
{ ;}
out_image_version_ = v;
}
binding& binding&
in_image_binding () update_image_binding () {return update_image_binding_;}
{
return in_image_binding_; // Select binding.
} //
std::size_t
select_image_version () const { return select_image_version_;}
void
select_image_version (std::size_t v) {select_image_version_ = v;}
binding& binding&
out_image_binding () select_image_binding () {return select_image_binding_;}
{
return out_image_binding_;
}
bool* bool*
out_image_truncated () select_image_truncated () {return select_image_truncated_;}
{
return out_image_truncated_;
}
// Object id image. // Object id image and binding.
// //
id_image_type& id_image_type&
id_image () id_image () {return id_image_;}
{
return id_image_;
}
std::size_t std::size_t
id_image_version () const id_image_version () const {return id_image_version_;}
{
return id_image_version_;
}
void void
id_image_version (std::size_t v) id_image_version (std::size_t v) {id_image_version_ = v;}
{
id_image_version_ = v;
}
binding& binding&
id_image_binding () id_image_binding () {return id_image_binding_;}
{
return id_image_binding_; // Optimistic id + managed column image binding.
} //
std::size_t
optimistic_id_image_version () const {return od_.id_image_version_;}
void
optimistic_id_image_version (std::size_t v) {od_.id_image_version_ =
v;}
binding&
optimistic_id_image_binding () {return od_.id_image_binding_;}
// Statements. // Statements.
// //
persist_statement_type& insert_statement_type&
persist_statement () persist_statement ()
{ {
if (persist_ == 0) if (persist_ == 0)
{ {
persist_.reset ( persist_.reset (
new (details::shared) persist_statement_type ( new (details::shared) insert_statement_type (
conn_, conn_,
object_traits::persist_statement_name, object_traits::persist_statement_name,
object_traits::persist_statement, object_traits::persist_statement,
object_traits::persist_statement_types, object_traits::persist_statement_types,
object_traits::in_column_count, insert_column_count,
in_image_binding_, insert_image_binding_,
in_image_native_binding_)); insert_image_native_binding_,
object_traits::auto_id,
false));
} }
return *persist_; return *persist_;
} }
find_statement_type& select_statement_type&
find_statement () find_statement ()
{ {
if (find_ == 0) if (find_ == 0)
{ {
find_.reset ( find_.reset (
new (details::shared) find_statement_type ( new (details::shared) select_statement_type (
conn_, conn_,
object_traits::find_statement_name, object_traits::find_statement_name,
object_traits::find_statement, object_traits::find_statement,
object_traits::find_statement_types, object_traits::find_statement_types,
1, id_column_count,
id_image_binding_, id_image_binding_,
id_image_native_binding_, id_image_native_binding_,
out_image_binding_)); select_image_binding_,
false));
} }
return *find_; return *find_;
} }
update_statement_type& update_statement_type&
update_statement () update_statement ()
{ {
if (update_ == 0) if (update_ == 0)
{ {
update_.reset ( update_.reset (
new (details::shared) update_statement_type ( new (details::shared) update_statement_type (
conn_, conn_,
object_traits::update_statement_name, object_traits::update_statement_name,
object_traits::update_statement, object_traits::update_statement,
object_traits::update_statement_types, object_traits::update_statement_types,
object_traits::in_column_count + 1, update_column_count + id_column_count,
id_image_binding_, update_image_binding_,
id_image_native_binding_, update_image_native_binding_,
in_image_binding_, false));
in_image_native_binding_));
} }
return *update_; return *update_;
} }
erase_statement_type& delete_statement_type&
erase_statement () erase_statement ()
{ {
if (erase_ == 0) if (erase_ == 0)
{ {
erase_.reset ( erase_.reset (
new (details::shared) erase_statement_type ( new (details::shared) delete_statement_type (
conn_, conn_,
object_traits::erase_statement_name, object_traits::erase_statement_name,
object_traits::erase_statement, object_traits::erase_statement,
object_traits::erase_statement_types, object_traits::erase_statement_types,
1, id_column_count,
id_image_binding_, id_image_binding_,
id_image_native_binding_)); id_image_native_binding_,
false));
} }
return *erase_; return *erase_;
} }
delete_statement_type&
optimistic_erase_statement ()
{
if (od_.erase_ == 0)
{
od_.erase_.reset (
new (details::shared) delete_statement_type (
conn_,
object_traits::optimistic_erase_statement_name,
object_traits::optimistic_erase_statement,
object_traits::optimistic_erase_statement_types,
id_column_count + managed_optimistic_column_count,
od_.id_image_binding_,
od_.id_image_native_binding_,
false));
}
return *od_.erase_;
}
// Container statement cache. // Container statement cache.
// //
container_statement_cache_type& container_statement_cache_type&
container_statment_cache () container_statment_cache ()
{ {
return container_statement_cache_; return container_statement_cache_;
} }
private: private:
object_statements (const object_statements&); object_statements (const object_statements&);
object_statements& operator= (const object_statements&); object_statements& operator= (const object_statements&);
private: private:
void void
load_delayed_ (); load_delayed_ ();
void void
clear_delayed_ (); clear_delayed_ ();
private: private:
// select = total
// insert = total - inverse - managed_optimistic
// update = total - inverse - managed_optimistic - id - readonly
//
static const std::size_t select_column_count =
object_traits::column_count;
static const std::size_t insert_column_count =
object_traits::column_count - object_traits::inverse_column_count -
object_traits::managed_optimistic_column_count;
static const std::size_t update_column_count = insert_column_count -
object_traits::id_column_count - object_traits::readonly_column_cou
nt;
static const std::size_t id_column_count =
object_traits::id_column_count;
static const std::size_t managed_optimistic_column_count =
object_traits::managed_optimistic_column_count;
private:
container_statement_cache_type container_statement_cache_; container_statement_cache_type container_statement_cache_;
image_type image_; image_type image_;
// In (send) binding. The last element is the id parameter. // Select binding.
// //
std::size_t in_image_version_; std::size_t select_image_version_;
binding in_image_binding_; binding select_image_binding_;
bind in_image_bind_[object_traits::in_column_count + 1]; bind select_image_bind_[select_column_count];
native_binding in_image_native_binding_; bool select_image_truncated_[select_column_count];
char* in_image_values_[object_traits::in_column_count + 1];
int in_image_lengths_[object_traits::in_column_count + 1]; // Insert binding.
int in_image_formats_[object_traits::in_column_count + 1]; //
std::size_t insert_image_version_;
// Out (receive) binding. binding insert_image_binding_;
// bind insert_image_bind_[insert_column_count];
std::size_t out_image_version_; native_binding insert_image_native_binding_;
binding out_image_binding_; char* insert_image_values_[insert_column_count];
bind out_image_bind_[object_traits::out_column_count]; int insert_image_lengths_[insert_column_count];
bool out_image_truncated_[object_traits::out_column_count]; int insert_image_formats_[insert_column_count];
// Update binding. Note that the id suffix is bound to id_image_
// below instead of image_ which makes this binding effectively
// bound to two images. As a result, we have to track versions
// for both of them. If this object uses optimistic concurrency,
// then the binding for the managed column (version, timestamp,
// etc) comes after the id and the image for such a column is
// stored as part of the id image.
//
std::size_t update_image_version_;
std::size_t update_id_image_version_;
binding update_image_binding_;
bind update_image_bind_[update_column_count + id_column_count +
managed_optimistic_column_count];
native_binding update_image_native_binding_;
char* update_image_values_[update_column_count + id_column_count +
managed_optimistic_column_count];
int update_image_lengths_[update_column_count + id_column_count +
managed_optimistic_column_count];
int update_image_formats_[update_column_count + id_column_count +
managed_optimistic_column_count];
// Id image binding (only in). // Id image binding (only used as a parameter). Uses the suffix in
// the update bind.
// //
id_image_type id_image_; id_image_type id_image_;
std::size_t id_image_version_; std::size_t id_image_version_;
binding id_image_binding_; binding id_image_binding_;
native_binding id_image_native_binding_; native_binding id_image_native_binding_;
details::shared_ptr<persist_statement_type> persist_; // Extra data for objects with optimistic concurrency support.
details::shared_ptr<find_statement_type> find_; //
optimistic_data<T, managed_optimistic_column_count != 0> od_;
details::shared_ptr<insert_statement_type> persist_;
details::shared_ptr<select_statement_type> find_;
details::shared_ptr<update_statement_type> update_; details::shared_ptr<update_statement_type> update_;
details::shared_ptr<erase_statement_type> erase_; details::shared_ptr<delete_statement_type> erase_;
// Delayed loading. // Delayed loading.
// //
struct delayed_load struct delayed_load
{ {
typedef typename object_cache_traits::position_type position_type; typedef typename object_cache_traits::position_type position_type;
delayed_load () {} delayed_load () {}
delayed_load (const id_type& i, object_type& o, const position_type & p) delayed_load (const id_type& i, object_type& o, const position_type & p)
: id (i), obj (&o), pos (p) : id (i), obj (&o), pos (p)
skipping to change at line 428 skipping to change at line 542
{ {
os_.clear_delayed (); os_.clear_delayed ();
dl_.swap (os_.delayed_); dl_.swap (os_.delayed_);
} }
private: private:
object_statements& os_; object_statements& os_;
delayed_loads& dl_; delayed_loads& dl_;
}; };
}; };
//
// Implementation for objects without object id.
//
template <typename T>
class object_statements_no_id: public statements_base
{
public:
typedef T object_type;
typedef odb::object_traits<object_type> object_traits;
typedef typename object_traits::pointer_type pointer_type;
typedef typename object_traits::image_type image_type;
typedef pgsql::insert_statement insert_statement_type;
public:
object_statements_no_id (connection_type&);
virtual
~object_statements_no_id ();
// Object image.
//
image_type&
image () {return image_;}
// Insert binding.
//
std::size_t
insert_image_version () const { return insert_image_version_;}
void
insert_image_version (std::size_t v) {insert_image_version_ = v;}
binding&
insert_image_binding () {return insert_image_binding_;}
// Select binding (needed for query support).
//
std::size_t
select_image_version () const { return select_image_version_;}
void
select_image_version (std::size_t v) {select_image_version_ = v;}
binding&
select_image_binding () {return select_image_binding_;}
bool*
select_image_truncated () {return select_image_truncated_;}
// Statements.
//
insert_statement_type&
persist_statement ()
{
if (persist_ == 0)
{
persist_.reset (
new (details::shared) insert_statement_type (
conn_,
object_traits::persist_statement_name,
object_traits::persist_statement,
object_traits::persist_statement_types,
insert_column_count,
insert_image_binding_,
insert_image_native_binding_,
false,
false));
}
return *persist_;
}
private:
object_statements_no_id (const object_statements_no_id&);
object_statements_no_id& operator= (const object_statements_no_id&);
private:
// select = total
// insert = total - inverse; inverse == 0 for object without id
//
static const std::size_t insert_column_count =
object_traits::column_count;
static const std::size_t select_column_count =
object_traits::column_count;
private:
image_type image_;
// Select binding.
//
std::size_t select_image_version_;
binding select_image_binding_;
bind select_image_bind_[select_column_count];
bool select_image_truncated_[select_column_count];
// Insert binding.
//
std::size_t insert_image_version_;
binding insert_image_binding_;
bind insert_image_bind_[insert_column_count];
native_binding insert_image_native_binding_;
char* insert_image_values_[insert_column_count];
int insert_image_lengths_[insert_column_count];
int insert_image_formats_[insert_column_count];
details::shared_ptr<insert_statement_type> persist_;
};
} }
} }
#include <odb/pgsql/object-statements.ixx> #include <odb/pgsql/object-statements.ixx>
#include <odb/pgsql/object-statements.txx> #include <odb/pgsql/object-statements.txx>
#include <odb/post.hxx> #include <odb/post.hxx>
#endif // ODB_PGSQL_OBJECT_STATEMENTS_HXX #endif // ODB_PGSQL_OBJECT_STATEMENTS_HXX
 End of changes. 39 change blocks. 
89 lines changed or deleted 317 lines changed or added


 object-statements.txx   object-statements.txx 
skipping to change at line 19 skipping to change at line 19
#include <odb/session.hxx> #include <odb/session.hxx>
#include <odb/callback.hxx> #include <odb/callback.hxx>
#include <odb/exceptions.hxx> #include <odb/exceptions.hxx>
#include <odb/pgsql/connection.hxx> #include <odb/pgsql/connection.hxx>
namespace odb namespace odb
{ {
namespace pgsql namespace pgsql
{ {
//
// optimistic_data
//
template <typename T>
optimistic_data<T, true>::
optimistic_data (bind* b, char** nv, int* nl, int* nf)
: id_image_binding_ (
b,
object_traits::id_column_count +
object_traits::managed_optimistic_column_count),
id_image_native_binding_ (
nv, nl, nf,
object_traits::id_column_count +
object_traits::managed_optimistic_column_count)
{
id_image_version_ = 0;
}
//
// object_statements
//
template <typename T> template <typename T>
object_statements<T>:: object_statements<T>::
~object_statements () ~object_statements ()
{ {
} }
template <typename T> template <typename T>
object_statements<T>:: object_statements<T>::
object_statements (connection_type& conn) object_statements (connection_type& conn)
: object_statements_base (conn), : object_statements_base (conn),
container_statement_cache_ (conn), container_statement_cache_ (conn),
in_image_binding_ (in_image_bind_, object_traits::in_column_count // select
), select_image_binding_ (select_image_bind_, select_column_count),
in_image_native_binding_ (in_image_values_, // insert
in_image_lengths_, insert_image_binding_ (insert_image_bind_, insert_column_count),
in_image_formats_, insert_image_native_binding_ (insert_image_values_,
object_traits::in_column_count), insert_image_lengths_,
out_image_binding_ (out_image_bind_, insert_image_formats_,
object_traits::out_column_count), insert_column_count),
id_image_binding_ (in_image_bind_ + object_traits::in_column_coun // update
t, update_image_binding_ (update_image_bind_,
1), update_column_count + id_column_count +
managed_optimistic_column_count),
update_image_native_binding_ (update_image_values_,
update_image_lengths_,
update_image_formats_,
update_column_count + id_column_cou
nt +
managed_optimistic_column_count),
// id
id_image_binding_ (update_image_bind_ + update_column_count,
id_column_count),
id_image_native_binding_ ( id_image_native_binding_ (
in_image_values_ + object_traits::in_column_count, update_image_values_ + update_column_count,
in_image_lengths_ + object_traits::in_column_count, update_image_lengths_ + update_column_count,
in_image_formats_ + object_traits::in_column_count, 1) update_image_formats_ + update_column_count,
id_column_count),
// optimistic data
od_ (update_image_bind_ + update_column_count,
update_image_values_ + update_column_count,
update_image_lengths_ + update_column_count,
update_image_formats_ + update_column_count)
{ {
image_.version = 0; image_.version = 0;
in_image_version_ = 0; select_image_version_ = 0;
out_image_version_ = 0; insert_image_version_ = 0;
update_image_version_ = 0;
update_id_image_version_ = 0;
id_image_.version = 0; id_image_.version = 0;
id_image_version_ = 0; id_image_version_ = 0;
std::memset (in_image_bind_, 0, sizeof (in_image_bind_)); std::memset (insert_image_bind_, 0, sizeof (insert_image_bind_));
std::memset (out_image_bind_, 0, sizeof (out_image_bind_)); std::memset (update_image_bind_, 0, sizeof (update_image_bind_));
std::memset (out_image_truncated_, 0, sizeof (out_image_truncated_)); std::memset (select_image_bind_, 0, sizeof (select_image_bind_));
std::memset (
select_image_truncated_, 0, sizeof (select_image_truncated_));
for (std::size_t i (0); i < object_traits::out_column_count; ++i) for (std::size_t i (0); i < select_column_count; ++i)
out_image_bind_[i].truncated = out_image_truncated_ + i; select_image_bind_[i].truncated = select_image_truncated_ + i;
} }
template <typename T> template <typename T>
void object_statements<T>:: void object_statements<T>::
load_delayed_ () load_delayed_ ()
{ {
database& db (connection ().database ()); database& db (connection ().database ());
delayed_loads dls; delayed_loads dls;
swap_guard sg (*this, dls); swap_guard sg (*this, dls);
skipping to change at line 123 skipping to change at line 167
{ {
for (typename delayed_loads::iterator i (delayed_.begin ()), for (typename delayed_loads::iterator i (delayed_.begin ()),
e (delayed_.end ()); i != e; ++i) e (delayed_.end ()); i != e; ++i)
{ {
object_cache_traits::erase (i->pos); object_cache_traits::erase (i->pos);
} }
} }
delayed_.clear (); delayed_.clear ();
} }
//
// object_statements_no_id
//
template <typename T>
object_statements_no_id<T>::
~object_statements_no_id ()
{
}
template <typename T>
object_statements_no_id<T>::
object_statements_no_id (connection_type& conn)
: statements_base (conn),
// select
select_image_binding_ (select_image_bind_, select_column_count),
// insert
insert_image_binding_ (insert_image_bind_, insert_column_count),
insert_image_native_binding_ (insert_image_values_,
insert_image_lengths_,
insert_image_formats_,
insert_column_count)
{
image_.version = 0;
select_image_version_ = 0;
insert_image_version_ = 0;
std::memset (insert_image_bind_, 0, sizeof (insert_image_bind_));
std::memset (select_image_bind_, 0, sizeof (select_image_bind_));
std::memset (
select_image_truncated_, 0, sizeof (select_image_truncated_));
for (std::size_t i (0); i < select_column_count; ++i)
select_image_bind_[i].truncated = select_image_truncated_ + i;
}
} }
} }
 End of changes. 7 change blocks. 
21 lines changed or deleted 100 lines changed or added


 result.hxx   result.hxx 
skipping to change at line 17 skipping to change at line 17
#define ODB_PGSQL_RESULT_HXX #define ODB_PGSQL_RESULT_HXX
#include <odb/pre.hxx> #include <odb/pre.hxx>
#include <odb/traits.hxx> #include <odb/traits.hxx>
#include <odb/result.hxx> #include <odb/result.hxx>
#include <odb/pgsql/version.hxx> #include <odb/pgsql/version.hxx>
#include <odb/pgsql/forward.hxx> #include <odb/pgsql/forward.hxx>
namespace odb
{
namespace pgsql
{
template <typename T, class_kind kind>
class result_impl;
}
}
#include <odb/post.hxx> #include <odb/post.hxx>
#endif // ODB_PGSQL_RESULT_HXX #endif // ODB_PGSQL_RESULT_HXX
// Include result specializations so that the user code only needs // Include result specializations so that the user code only needs
// to include this header. // to include this header.
// //
#include <odb/pgsql/object-result.hxx> #include <odb/pgsql/object-result.hxx>
#include <odb/pgsql/view-result.hxx> #include <odb/pgsql/view-result.hxx>
 End of changes. 1 change blocks. 
9 lines changed or deleted 0 lines changed or added


 statement-cache.hxx   statement-cache.hxx 
skipping to change at line 41 skipping to change at line 41
class LIBODB_PGSQL_EXPORT statement_cache class LIBODB_PGSQL_EXPORT statement_cache
{ {
public: public:
statement_cache (connection& conn) statement_cache (connection& conn)
: conn_ (conn) : conn_ (conn)
{ {
} }
template <typename T> template <typename T>
object_statements<T>& typename object_statements_selector<T>::type&
find_object () find_object ()
{ {
typedef typename object_statements_selector<T>::type object_stateme
nts;
map::iterator i (map_.find (&typeid (T))); map::iterator i (map_.find (&typeid (T)));
if (i != map_.end ()) if (i != map_.end ())
return static_cast<object_statements<T>&amp;> (*i->second); return static_cast<object_statements&> (*i->second);
details::shared_ptr<object_statements<T> > p ( details::shared_ptr<object_statements> p (
new (details::shared) object_statements<T> (conn_)); new (details::shared) object_statements (conn_));
map_.insert (map::value_type (&typeid (T), p)); map_.insert (map::value_type (&typeid (T), p));
return *p; return *p;
} }
template <typename T> template <typename T>
view_statements<T>& view_statements<T>&
find_view () find_view ()
{ {
map::iterator i (map_.find (&typeid (T))); map::iterator i (map_.find (&typeid (T)));
 End of changes. 4 change blocks. 
4 lines changed or deleted 7 lines changed or added


 statement.hxx   statement.hxx 
skipping to change at line 14 skipping to change at line 14
// license : GNU GPL v2; see accompanying LICENSE file // license : GNU GPL v2; see accompanying LICENSE file
#ifndef ODB_PGSQL_STATEMENT_HXX #ifndef ODB_PGSQL_STATEMENT_HXX
#define ODB_PGSQL_STATEMENT_HXX #define ODB_PGSQL_STATEMENT_HXX
#include <odb/pre.hxx> #include <odb/pre.hxx>
#include <string> #include <string>
#include <cstddef> // std::size_t #include <cstddef> // std::size_t
#include <odb/details/shared-ptr.hxx> #include <odb/forward.hxx>
#include <odb/statement.hxx>
#include <odb/pgsql/version.hxx> #include <odb/pgsql/version.hxx>
#include <odb/pgsql/binding.hxx> #include <odb/pgsql/binding.hxx>
#include <odb/pgsql/pgsql-fwd.hxx> // PGresult #include <odb/pgsql/pgsql-fwd.hxx> // PGresult
#include <odb/pgsql/auto-handle.hxx> #include <odb/pgsql/auto-handle.hxx>
#include <odb/pgsql/details/export.hxx> #include <odb/pgsql/details/export.hxx>
namespace odb namespace odb
{ {
namespace pgsql namespace pgsql
{ {
class connection; class connection;
class LIBODB_PGSQL_EXPORT statement: public details::shared_base class LIBODB_PGSQL_EXPORT statement: public odb::statement
{ {
public: public:
virtual virtual
~statement () = 0; ~statement () = 0;
const char*
name () const
{
return name_;
}
virtual const char*
text () const;
void void
deallocate (); deallocate ();
// Adapt an ODB binding to a native PostgreSQL parameter binding. // Adapt an ODB binding to a native PostgreSQL parameter binding.
// //
static void static void
bind_param (native_binding&, const binding&); bind_param (native_binding&, const binding&);
// Populate an ODB binding given a PostgreSQL result. If the truncate d // Populate an ODB binding given a PostgreSQL result. If the truncate d
// argument is true, then only truncated columns are extracted. Retur n // argument is true, then only truncated columns are extracted. Retur n
skipping to change at line 58 skipping to change at line 68
static bool static bool
bind_result (bind*, bind_result (bind*,
std::size_t count, std::size_t count,
PGresult*, PGresult*,
std::size_t row, std::size_t row,
bool truncated = false); bool truncated = false);
protected: protected:
statement (connection&, statement (connection&,
const std::string& name, const std::string& name,
const std::string& stmt, const std::string& text,
const Oid* types,
std::size_t types_count);
statement (connection&,
const char* name,
const char* text,
bool copy_name_text,
const Oid* types, const Oid* types,
std::size_t types_count); std::size_t types_count);
private:
void
init (const Oid* types, std::size_t types_count);
protected: protected:
connection& conn_; connection& conn_;
std::string name_;
std::string name_copy_;
const char* name_;
std::string text_copy_;
const char* text_;
private: private:
bool deallocated_; bool deallocated_;
}; };
class LIBODB_PGSQL_EXPORT select_statement: public statement class LIBODB_PGSQL_EXPORT select_statement: public statement
{ {
public: public:
virtual virtual
~select_statement (); ~select_statement ();
select_statement (connection& conn, select_statement (connection& conn,
const std::string& name, const std::string& name,
const std::string& stmt, const std::string& text,
const Oid* types, const Oid* types,
std::size_t types_count, std::size_t types_count,
binding& cond, binding& param,
native_binding& native_cond, native_binding& native_param,
binding& data); binding& result);
select_statement (connection& conn, select_statement (connection& conn,
const std::string& name, const char* name,
const std::string& stmt, const char* stmt,
const Oid* types, const Oid* types,
std::size_t types_count, std::size_t types_count,
native_binding& native_cond, binding& param,
binding& data); native_binding& native_param,
binding& result,
bool copy_name_text = true);
select_statement (connection& conn, select_statement (connection& conn,
const std::string& name, const std::string& name,
const std::string& stmt, const std::string& text,
binding& data); binding& result);
select_statement (connection& conn,
const char* name,
const char* text,
binding& result,
bool copy_name_text = true);
select_statement (connection& conn,
const std::string& name,
const std::string& text,
const Oid* types,
std::size_t types_count,
native_binding& native_param,
binding& result);
// Common select interface expected by the generated code. // Common select interface expected by the generated code.
// //
public: public:
enum result enum result
{ {
success, success,
no_data, no_data,
truncated truncated
}; };
skipping to change at line 161 skipping to change at line 203
load (); load ();
void void
reload (); reload ();
private: private:
select_statement (const select_statement&); select_statement (const select_statement&);
select_statement& operator= (const select_statement&); select_statement& operator= (const select_statement&);
private: private:
binding* cond_; binding* param_;
native_binding* native_cond_; native_binding* native_param_;
binding& data_; binding& result_;
auto_handle<PGresult> result_; auto_handle<PGresult> handle_;
std::size_t row_count_; std::size_t row_count_;
std::size_t current_row_; std::size_t current_row_;
}; };
class LIBODB_PGSQL_EXPORT insert_statement: public statement class LIBODB_PGSQL_EXPORT insert_statement: public statement
{ {
public: public:
virtual virtual
~insert_statement (); ~insert_statement ();
insert_statement (connection& conn, insert_statement (connection& conn,
const std::string& name, const std::string& name,
const std::string& stmt, const std::string& text,
const Oid* types,
std::size_t types_count,
binding& param,
native_binding& native_param,
bool returning);
insert_statement (connection& conn,
const char* name,
const char* text,
const Oid* types, const Oid* types,
std::size_t types_count, std::size_t types_count,
binding& data, binding& param,
native_binding& native_data); native_binding& native_param,
bool returning,
bool copy_name_text = true);
// Return true if successful and false if the row is a duplicate. // Return true if successful and false if the row is a duplicate.
// All other errors are reported by throwing exceptions. // All other errors are reported by throwing exceptions.
// //
bool bool
execute (); execute ();
unsigned long long unsigned long long
id (); id ()
{
return id_;
}
private: private:
insert_statement (const insert_statement&); insert_statement (const insert_statement&);
insert_statement& operator= (const insert_statement&); insert_statement& operator= (const insert_statement&);
private: private:
binding& data_; binding& param_;
native_binding& native_data_; native_binding& native_param_;
bool id_cached_; bool returning_;
unsigned long long id_; unsigned long long id_;
}; };
class LIBODB_PGSQL_EXPORT update_statement: public statement class LIBODB_PGSQL_EXPORT update_statement: public statement
{ {
public: public:
virtual virtual
~update_statement (); ~update_statement ();
// Asssumes that cond.values, cond.lengths, and cond.formats are
// suffixes of data.values, data.lengths, and data.formats
// respectively.
//
update_statement (connection& conn, update_statement (connection& conn,
const std::string& name, const std::string& name,
const std::string& stmt, const std::string& text,
const Oid* types, const Oid* types,
std::size_t types_count, std::size_t types_count,
binding& cond, binding& param,
native_binding& native_cond, native_binding& native_param);
binding& data,
native_binding& native_data);
void update_statement (connection& conn,
const char* name,
const char* text,
const Oid* types,
std::size_t types_count,
binding& param,
native_binding& native_param,
bool copy_name_text = true);
unsigned long long
execute (); execute ();
private: private:
update_statement (const update_statement&); update_statement (const update_statement&);
update_statement& operator= (const update_statement&); update_statement& operator= (const update_statement&);
private: private:
binding& cond_; binding& param_;
native_binding& native_cond_; native_binding& native_param_;
binding& data_;
native_binding& native_data_;
}; };
class LIBODB_PGSQL_EXPORT delete_statement: public statement class LIBODB_PGSQL_EXPORT delete_statement: public statement
{ {
public: public:
virtual virtual
~delete_statement (); ~delete_statement ();
delete_statement (connection& conn, delete_statement (connection& conn,
const std::string& name, const std::string& name,
const std::string& stmt, const std::string& text,
const Oid* types,
std::size_t types_count,
binding& param,
native_binding& native_param);
delete_statement (connection& conn,
const char* name,
const char* text,
const Oid* types, const Oid* types,
std::size_t types_count, std::size_t types_count,
binding& cond, binding& param,
native_binding& native_cond); native_binding& native_param,
bool copy_name_text = true);
delete_statement (connection& conn, delete_statement (connection& conn,
const std::string& name, const std::string& name,
const std::string& stmt, const std::string& text,
const Oid* types, const Oid* types,
std::size_t types_count, std::size_t types_count,
native_binding& native_cond); native_binding& native_param);
unsigned long long unsigned long long
execute (); execute ();
private: private:
delete_statement (const delete_statement&); delete_statement (const delete_statement&);
delete_statement& operator= (const delete_statement&); delete_statement& operator= (const delete_statement&);
private: private:
binding* cond_; binding* param_;
native_binding& native_cond_; native_binding& native_param_;
}; };
} }
} }
#include <odb/post.hxx> #include <odb/post.hxx>
#endif // ODB_PGSQL_STATEMENT_HXX #endif // ODB_PGSQL_STATEMENT_HXX
 End of changes. 29 change blocks. 
47 lines changed or deleted 112 lines changed or added


 traits.hxx   traits.hxx 
skipping to change at line 14 skipping to change at line 14
// license : GNU GPL v2; see accompanying LICENSE file // license : GNU GPL v2; see accompanying LICENSE file
#ifndef ODB_PGSQL_TRAITS_HXX #ifndef ODB_PGSQL_TRAITS_HXX
#define ODB_PGSQL_TRAITS_HXX #define ODB_PGSQL_TRAITS_HXX
#include <odb/pre.hxx> #include <odb/pre.hxx>
#include <string> #include <string>
#include <vector> #include <vector>
#include <cstddef> // std::size_t #include <cstddef> // std::size_t
#include <cstring> // std::memcpy, std::memset, std::strlen
#include <odb/traits.hxx> #include <odb/traits.hxx>
#include <odb/wrapper-traits.hxx> #include <odb/wrapper-traits.hxx>
#include <odb/details/buffer.hxx> #include <odb/details/buffer.hxx>
#include <odb/details/wrapper-p.hxx> #include <odb/details/wrapper-p.hxx>
#include <odb/pgsql/version.hxx> #include <odb/pgsql/version.hxx>
#include <odb/pgsql/pgsql-types.hxx> #include <odb/pgsql/pgsql-types.hxx>
skipping to change at line 149 skipping to change at line 150
}; };
// The wrapped_value_traits specializations should be able to handle // The wrapped_value_traits specializations should be able to handle
// any value type which means we have to have every possible signature // any value type which means we have to have every possible signature
// of the set_value() and set_image() functions. // of the set_value() and set_image() functions.
// //
template <typename W, database_type_id ID> template <typename W, database_type_id ID>
struct wrapped_value_traits<W, ID, false> struct wrapped_value_traits<W, ID, false>
{ {
typedef wrapper_traits<W> wtraits; typedef wrapper_traits<W> wtraits;
typedef typename wtraits::wrapped_type wrapped_type; typedef typename wtraits::unrestricted_wrapped_type wrapped_type;
typedef W value_type; typedef W value_type;
typedef wrapped_type query_type; typedef wrapped_type query_type;
typedef typename image_traits<ID>::image_type image_type; typedef typename image_traits<ID>::image_type image_type;
typedef value_traits<wrapped_type, ID> vtraits; typedef value_traits<wrapped_type, ID> vtraits;
static void static void
set_value (W& v, const image_type& i, bool is_null) set_value (W& v, const image_type& i, bool is_null)
{ {
skipping to change at line 210 skipping to change at line 211
// VARBIT. // VARBIT.
// //
static void static void
set_value (W& v, const details::ubuffer& b, std::size_t n, bool is_nu ll) set_value (W& v, const details::ubuffer& b, std::size_t n, bool is_nu ll)
{ {
vtraits::set_value (wtraits::set_ref (v), b, n, is_null); vtraits::set_value (wtraits::set_ref (v), b, n, is_null);
} }
static void static void
set_image (details::ubuffer& b, std::size_t& n, bool& is_null, const set_image (details::ubuffer& b,
W& v) std::size_t& n,
bool& is_null,
const W& v)
{ {
vtraits::set_image (b, n, is_null, wtraits::get_ref (v)); vtraits::set_image (b, n, is_null, wtraits::get_ref (v));
} }
// UUID. // UUID.
// //
static void static void
set_value (W& v, const unsigned char* i, bool is_null) set_value (W& v, const unsigned char* i, bool is_null)
{ {
vtraits::set_value (wtraits::set_ref (v), i, is_null); vtraits::set_value (wtraits::set_ref (v), i, is_null);
skipping to change at line 234 skipping to change at line 238
set_image (unsigned char* i, bool& is_null, const W& v) set_image (unsigned char* i, bool& is_null, const W& v)
{ {
vtraits::set_image (i, is_null, wtraits::get_ref (v)); vtraits::set_image (i, is_null, wtraits::get_ref (v));
} }
}; };
template <typename W, database_type_id ID> template <typename W, database_type_id ID>
struct wrapped_value_traits<W, ID, true> struct wrapped_value_traits<W, ID, true>
{ {
typedef wrapper_traits<W> wtraits; typedef wrapper_traits<W> wtraits;
typedef typename wtraits::wrapped_type wrapped_type; typedef typename wtraits::unrestricted_wrapped_type wrapped_type;
typedef W value_type; typedef W value_type;
typedef wrapped_type query_type; typedef wrapped_type query_type;
typedef typename image_traits<ID>::image_type image_type; typedef typename image_traits<ID>::image_type image_type;
typedef value_traits<wrapped_type, ID> vtraits; typedef value_traits<wrapped_type, ID> vtraits;
static void static void
set_value (W& v, const image_type& i, bool is_null) set_value (W& v, const image_type& i, bool is_null)
{ {
skipping to change at line 466 skipping to change at line 470
template <std::size_t n> template <std::size_t n>
struct default_value_traits<const char[n], id_string>: struct default_value_traits<const char[n], id_string>:
c_string_value_traits c_string_value_traits
{ {
}; };
// std::vector<char> (buffer) specialization. // std::vector<char> (buffer) specialization.
// //
template <> template <>
struct LIBODB_PGSQL_EXPORT default_value_traits<std::vector<char>, id_b struct LIBODB_PGSQL_EXPORT default_value_traits<
ytea> std::vector<char>, id_bytea>
{ {
public: public:
typedef std::vector<char> value_type; typedef std::vector<char> value_type;
typedef std::vector<char> query_type; typedef std::vector<char> query_type;
typedef details::buffer image_type; typedef details::buffer image_type;
static void static void
set_value (value_type& v, set_value (value_type& v,
const details::buffer& b, const details::buffer& b,
std::size_t n, std::size_t n,
skipping to change at line 492 skipping to change at line 497
v.clear (); v.clear ();
} }
static void static void
set_image (details::buffer&, set_image (details::buffer&,
std::size_t& n, std::size_t& n,
bool& is_null, bool& is_null,
const value_type&); const value_type&);
}; };
// std::vector<unsigned char> (buffer) specialization.
//
template <>
struct LIBODB_PGSQL_EXPORT default_value_traits<
std::vector<unsigned char>, id_bytea>
{
public:
typedef std::vector<unsigned char> value_type;
typedef std::vector<unsigned char> query_type;
typedef details::buffer image_type;
static void
set_value (value_type& v,
const details::buffer& b,
std::size_t n,
bool is_null)
{
if (!is_null)
{
const unsigned char* d (
reinterpret_cast<const unsigned char*> (b.data ()));
v.assign (d, d + n);
}
else
v.clear ();
}
static void
set_image (details::buffer&,
std::size_t& n,
bool& is_null,
const value_type&);
};
// char[n] (buffer) specialization.
//
template <std::size_t N>
struct default_value_traits<char[N], id_bytea>
{
public:
typedef char* value_type;
typedef const char* query_type;
typedef details::buffer image_type;
static void
set_value (char* const& v,
const details::buffer& b,
std::size_t n,
bool is_null)
{
if (!is_null)
std::memcpy (v, b.data (), (n < N ? n : N));
else
std::memset (v, 0, N);
}
static void
set_image (details::buffer& b,
std::size_t& n,
bool& is_null,
const char* v)
{
is_null = false;
n = N;
if (n > b.capacity ())
b.capacity (n);
std::memcpy (b.data (), v, n);
}
};
// unsigned char[n] (buffer) specialization.
//
template <std::size_t N>
struct default_value_traits<unsigned char[N], id_bytea>
{
public:
typedef unsigned char* value_type;
typedef const unsigned char* query_type;
typedef details::buffer image_type;
static void
set_value (unsigned char* const& v,
const details::buffer& b,
std::size_t n,
bool is_null)
{
if (!is_null)
std::memcpy (v, b.data (), (n < N ? n : N));
else
std::memset (v, 0, N);
}
static void
set_image (details::buffer& b,
std::size_t& n,
bool& is_null,
const unsigned char* v)
{
is_null = false;
n = N;
if (n > b.capacity ())
b.capacity (n);
std::memcpy (b.data (), v, n);
}
};
// //
// type_traits // type_traits
// //
template <typename T> template <typename T>
struct default_type_traits; struct default_type_traits;
template <typename T> template <typename T>
class type_traits: public default_type_traits<T> class type_traits: public default_type_traits<T>
{ {
 End of changes. 6 change blocks. 
6 lines changed or deleted 119 lines changed or added


 transaction-impl.hxx   transaction-impl.hxx 
skipping to change at line 16 skipping to change at line 16
#ifndef ODB_PGSQL_TRANSACTION_IMPL_HXX #ifndef ODB_PGSQL_TRANSACTION_IMPL_HXX
#define ODB_PGSQL_TRANSACTION_IMPL_HXX #define ODB_PGSQL_TRANSACTION_IMPL_HXX
#include <odb/pre.hxx> #include <odb/pre.hxx>
#include <odb/transaction.hxx> #include <odb/transaction.hxx>
#include <odb/pgsql/version.hxx> #include <odb/pgsql/version.hxx>
#include <odb/pgsql/forward.hxx> #include <odb/pgsql/forward.hxx>
#include <odb/details/shared-ptr.hxx>
#include <odb/pgsql/details/export.hxx> #include <odb/pgsql/details/export.hxx>
namespace odb namespace odb
{ {
namespace pgsql namespace pgsql
{ {
class LIBODB_PGSQL_EXPORT transaction_impl: public odb::transaction_imp l class LIBODB_PGSQL_EXPORT transaction_impl: public odb::transaction_imp l
{ {
public: public:
typedef pgsql::database database_type; typedef pgsql::database database_type;
 End of changes. 1 change blocks. 
2 lines changed or deleted 0 lines changed or added


 transaction.hxx   transaction.hxx 
skipping to change at line 15 skipping to change at line 15
#ifndef ODB_PGSQL_TRANSACTION_HXX #ifndef ODB_PGSQL_TRANSACTION_HXX
#define ODB_PGSQL_TRANSACTION_HXX #define ODB_PGSQL_TRANSACTION_HXX
#include <odb/pre.hxx> #include <odb/pre.hxx>
#include <odb/transaction.hxx> #include <odb/transaction.hxx>
#include <odb/pgsql/version.hxx> #include <odb/pgsql/version.hxx>
#include <odb/pgsql/forward.hxx> #include <odb/pgsql/forward.hxx>
#include <odb/pgsql/tracer.hxx>
#include <odb/pgsql/details/export.hxx> #include <odb/pgsql/details/export.hxx>
namespace odb namespace odb
{ {
namespace pgsql namespace pgsql
{ {
class transaction_impl; class transaction_impl;
class LIBODB_PGSQL_EXPORT transaction: public odb::transaction class LIBODB_PGSQL_EXPORT transaction: public odb::transaction
skipping to change at line 54 skipping to change at line 55
// in effect. // in effect.
// //
static transaction& static transaction&
current (); current ();
// Set the current thread's transaction. // Set the current thread's transaction.
// //
static void static void
current (transaction&); current (transaction&);
// SQL statement tracing.
//
public:
typedef pgsql::tracer tracer_type;
void
tracer (tracer_type& t)
{
odb::transaction::tracer (t);
}
void
tracer (tracer_type* t)
{
odb::transaction::tracer (t);
}
using odb::transaction::tracer;
public: public:
transaction_impl& transaction_impl&
implementation (); implementation ();
}; };
} }
} }
#include <odb/pgsql/transaction.ixx> #include <odb/pgsql/transaction.ixx>
#include <odb/post.hxx> #include <odb/post.hxx>
 End of changes. 2 change blocks. 
0 lines changed or deleted 20 lines changed or added


 version.hxx   version.hxx 
skipping to change at line 33 skipping to change at line 33
// Version AABBCCDD // Version AABBCCDD
// 2.0.0 02000000 // 2.0.0 02000000
// 2.1.0 02010000 // 2.1.0 02010000
// 2.1.1 02010100 // 2.1.1 02010100
// 2.2.0.a1 02019901 // 2.2.0.a1 02019901
// 3.0.0.b2 02999952 // 3.0.0.b2 02999952
// //
// Check that we have compatible ODB version. // Check that we have compatible ODB version.
// //
#if ODB_VERSION != 10600 #if ODB_VERSION != 10700
# error incompatible odb interface version detected # error incompatible odb interface version detected
#endif #endif
// libodb-pgsql version: odb interface version plus the bugfix // libodb-pgsql version: odb interface version plus the bugfix
// version. // version.
// //
#define LIBODB_PGSQL_VERSION 1060000 #define LIBODB_PGSQL_VERSION 1070000
#define LIBODB_PGSQL_VERSION_STR "1.6.0" #define LIBODB_PGSQL_VERSION_STR "1.7.0"
#include <odb/post.hxx> #include <odb/post.hxx>
#endif // ODB_PGSQL_VERSION_HXX #endif // ODB_PGSQL_VERSION_HXX
 End of changes. 2 change blocks. 
3 lines changed or deleted 3 lines changed or added


 view-result.hxx   view-result.hxx 
skipping to change at line 25 skipping to change at line 25
#include <odb/pgsql/version.hxx> #include <odb/pgsql/version.hxx>
#include <odb/pgsql/forward.hxx> // query, view_statements #include <odb/pgsql/forward.hxx> // query, view_statements
#include <odb/pgsql/result.hxx> #include <odb/pgsql/result.hxx>
#include <odb/pgsql/statement.hxx> #include <odb/pgsql/statement.hxx>
namespace odb namespace odb
{ {
namespace pgsql namespace pgsql
{ {
template <typename T> template <typename T>
class result_impl<T, class_view>: class view_result_impl: public odb::view_result_impl<T>
public odb::result_impl<T, class_view>
{ {
public: public:
typedef odb::result_impl<T, class_view> base_type; typedef odb::view_result_impl<T> base_type;
typedef typename base_type::view_type view_type; typedef typename base_type::view_type view_type;
typedef typename base_type::view_traits view_traits; typedef typename base_type::view_traits view_traits;
typedef typename base_type::pointer_type pointer_type; typedef typename base_type::pointer_type pointer_type;
typedef typename base_type::pointer_traits pointer_traits; typedef typename base_type::pointer_traits pointer_traits;
virtual virtual
~result_impl (); ~view_result_impl ();
result_impl (const query&, view_result_impl (const query&,
details::shared_ptr<select_statement>, details::shared_ptr<select_statement>,
view_statements<view_type>&); view_statements<view_type>&);
virtual void virtual void
load (view_type&); load (view_type&);
virtual void virtual void
next (); next ();
virtual void virtual void
cache (); cache ();
 End of changes. 4 change blocks. 
7 lines changed or deleted 6 lines changed or added


 view-result.txx   view-result.txx 
skipping to change at line 15 skipping to change at line 15
#include <odb/callback.hxx> #include <odb/callback.hxx>
#include <odb/pgsql/view-statements.hxx> #include <odb/pgsql/view-statements.hxx>
namespace odb namespace odb
{ {
namespace pgsql namespace pgsql
{ {
template <typename T> template <typename T>
result_impl<T, class_view>:: view_result_impl<T>::
~result_impl () ~view_result_impl ()
{ {
} }
template <typename T> template <typename T>
result_impl<T, class_view>:: view_result_impl<T>::
result_impl (const query&, view_result_impl (const query&,
details::shared_ptr<select_statement> statement, details::shared_ptr<select_statement> statement,
view_statements<view_type>& statements) view_statements<view_type>& statements)
: base_type (statements.connection ().database ()), : base_type (statements.connection ().database ()),
statement_ (statement), statement_ (statement),
statements_ (statements) statements_ (statements)
{ {
} }
template <typename T> template <typename T>
void result_impl<T, class_view>:: void view_result_impl<T>::
load (view_type& view) load (view_type& view)
{ {
// The image can grow between calls to load() as a result of other // The image can grow between calls to load() as a result of other
// statements execution. // statements execution.
// //
typename view_traits::image_type& im (statements_.image ()); typename view_traits::image_type& im (statements_.image ());
if (im.version != statements_.image_version ()) if (im.version != statements_.image_version ())
{ {
binding& b (statements_.image_binding ()); binding& b (statements_.image_binding ());
skipping to change at line 73 skipping to change at line 73
} }
odb::database& db (this->database ()); odb::database& db (this->database ());
view_traits::callback (db, view, callback_event::pre_load); view_traits::callback (db, view, callback_event::pre_load);
view_traits::init (view, im, db); view_traits::init (view, im, db);
view_traits::callback (db, view, callback_event::post_load); view_traits::callback (db, view, callback_event::post_load);
} }
template <typename T> template <typename T>
void result_impl<T, class_view>:: void view_result_impl<T>::
next () next ()
{ {
this->current (pointer_type ()); this->current (pointer_type ());
if (!statement_->next ()) if (!statement_->next ())
this->end_ = true; this->end_ = true;
} }
template <typename T> template <typename T>
void result_impl<T, class_view>:: void view_result_impl<T>::
cache () cache ()
{ {
} }
template <typename T> template <typename T>
std::size_t result_impl<T, class_view>:: std::size_t view_result_impl<T>::
size () size ()
{ {
return statement_->result_size (); return statement_->result_size ();
} }
} }
} }
 End of changes. 6 change blocks. 
10 lines changed or deleted 10 lines changed or added


 view-statements.hxx   view-statements.hxx 
skipping to change at line 16 skipping to change at line 16
#ifndef ODB_PGSQL_VIEW_STATEMENTS_HXX #ifndef ODB_PGSQL_VIEW_STATEMENTS_HXX
#define ODB_PGSQL_VIEW_STATEMENTS_HXX #define ODB_PGSQL_VIEW_STATEMENTS_HXX
#include <odb/pre.hxx> #include <odb/pre.hxx>
#include <cstddef> // std::size_t #include <cstddef> // std::size_t
#include <odb/forward.hxx> #include <odb/forward.hxx>
#include <odb/traits.hxx> #include <odb/traits.hxx>
#include <odb/details/shared-ptr.hxx>
#include <odb/pgsql/version.hxx> #include <odb/pgsql/version.hxx>
#include <odb/pgsql/binding.hxx> #include <odb/pgsql/binding.hxx>
#include <odb/pgsql/statement.hxx> #include <odb/pgsql/statement.hxx>
#include <odb/pgsql/statements-base.hxx> #include <odb/pgsql/statements-base.hxx>
namespace odb namespace odb
{ {
namespace pgsql namespace pgsql
{ {
template <typename T> template <typename T>
 End of changes. 1 change blocks. 
2 lines changed or deleted 0 lines changed or added

This html diff was produced by rfcdiff 1.41. The latest version is available from http://tools.ietf.org/tools/rfcdiff/