aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2014-08-14 09:37:06 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2014-11-11 10:29:50 +0200
commit0d0e4b23176f0b55d7948ffef9b9ffdad6a95973 (patch)
treeb72d34281441dbd959fe48ec1d60117a17b29e37
parent51a01cfebf933d270bf7b7fadb0fb3ca3b7a4cd5 (diff)
Draft implementation for INSERT
-rw-r--r--bulk/README63
-rw-r--r--bulk/database.hxx94
-rw-r--r--bulk/driver.cxx107
-rw-r--r--bulk/makefile125
-rw-r--r--bulk/mssql/auto/person-odb.cxx578
-rw-r--r--bulk/mssql/auto/person-odb.hxx219
-rw-r--r--bulk/mssql/auto/person-odb.ixx61
-rw-r--r--bulk/mssql/auto/person.sql15
-rw-r--r--bulk/mssql/id/person-odb.cxx569
-rw-r--r--bulk/mssql/id/person-odb.hxx216
-rw-r--r--bulk/mssql/id/person-odb.ixx61
-rw-r--r--bulk/mssql/id/person.sql12
-rw-r--r--bulk/mssql/orig/person-odb.cxx524
-rw-r--r--bulk/mssql/orig/person-odb.hxx214
-rw-r--r--bulk/mssql/orig/person-odb.ixx61
-rw-r--r--bulk/oracle/auto/person-odb.cxx580
-rw-r--r--bulk/oracle/auto/person-odb.hxx221
-rw-r--r--bulk/oracle/auto/person-odb.ixx61
-rw-r--r--bulk/oracle/auto/person.sql33
-rw-r--r--bulk/oracle/orig/person-odb.cxx546
-rw-r--r--bulk/oracle/orig/person-odb.hxx218
-rw-r--r--bulk/oracle/orig/person-odb.ixx61
-rw-r--r--bulk/person.hxx28
23 files changed, 4667 insertions, 0 deletions
diff --git a/bulk/README b/bulk/README
new file mode 100644
index 0000000..a068898
--- /dev/null
+++ b/bulk/README
@@ -0,0 +1,63 @@
+This is a "Hello World" example that shows how to use ODB to perform basic
+database operations, such as making objects persistent, loading, updating
+and deleting persistent objects, as well as querying the database for
+objects matching a certain criteria. It also includes an example of a
+simple view.
+
+The example consists of the following files:
+
+person.hxx
+ Header file defining the 'person' persistent class as well as the
+ 'person_stat' view.
+
+person-odb.hxx
+person-odb.ixx
+person-odb.cxx
+person.sql
+ The first three files contain the database support code and the last file
+ contains the database schema for the person.hxx header.
+
+ These files are generated by the ODB compiler from person.hxx using the
+ following command line:
+
+ odb -d <database> --generate-query --generate-schema person.hxx
+
+ Where <database> stands for the database system we are using, for example,
+ 'mysql'.
+
+database.hxx
+ Contains the create_database() function which instantiates the concrete
+ database class corresponding to the database system we are using.
+
+driver.cxx
+ Driver for the example. It includes the person.hxx and person-odb.hxx
+ headers to gain access to the persistent classes and their database support
+ code. It also includes database.hxx for the create_database() function
+ declaration.
+
+ In main() the driver first calls create_database() to obtain the database
+ instance. Then it executes a number of database transactions on persistent
+ objects.
+
+To compile and link the example manually from the command line we can use
+the following commands (using MySQL as an example; replace 'c++' with your
+C++ compiler name):
+
+c++ -c person-odb.cxx
+c++ -DDATABASE_MYSQL -c driver.cxx
+c++ -o driver driver.o person-odb.o -lodb-mysql -lodb
+
+To run the example we may first need to create the database schema (for some
+database systems, such as SQLite, the schema is embedded into the generated
+code which makes this step unnecessary). Using MySQL as an example, this
+can be achieved with the following command:
+
+mysql --user=odb_test --database=odb_test < person.sql
+
+Here we use 'odb_test' as the database login and also 'odb_test' as the
+database name.
+
+Once the database schema is ready, we can run the example (using MySQL as
+the database):
+
+./driver --user odb_test --database odb_test
diff --git a/bulk/database.hxx b/bulk/database.hxx
new file mode 100644
index 0000000..283f5cb
--- /dev/null
+++ b/bulk/database.hxx
@@ -0,0 +1,94 @@
+// file : hello/database.hxx
+// copyright : not copyrighted - public domain
+
+//
+// Create concrete database instance based on the DATABASE_* macros.
+//
+
+#ifndef DATABASE_HXX
+#define DATABASE_HXX
+
+#include <string>
+#include <memory> // std::auto_ptr
+#include <cstdlib> // std::exit
+#include <iostream>
+
+#include <odb/database.hxx>
+
+#if defined(DATABASE_MYSQL)
+# include <odb/mysql/database.hxx>
+#elif defined(DATABASE_SQLITE)
+# include <odb/connection.hxx>
+# include <odb/transaction.hxx>
+# include <odb/schema-catalog.hxx>
+# include <odb/sqlite/database.hxx>
+#elif defined(DATABASE_PGSQL)
+# include <odb/pgsql/database.hxx>
+#elif defined(DATABASE_ORACLE)
+# include <odb/oracle/database.hxx>
+#elif defined(DATABASE_MSSQL)
+# include <odb/mssql/database.hxx>
+#else
+# error unknown database; did you forget to define the DATABASE_* macros?
+#endif
+
+inline std::auto_ptr<odb::database>
+create_database (int& argc, char* argv[])
+{
+ using namespace std;
+ using namespace odb::core;
+
+ if (argc > 1 && argv[1] == string ("--help"))
+ {
+ cout << "Usage: " << argv[0] << " [options]" << endl
+ << "Options:" << endl;
+
+#if defined(DATABASE_MYSQL)
+ odb::mysql::database::print_usage (cout);
+#elif defined(DATABASE_SQLITE)
+ odb::sqlite::database::print_usage (cout);
+#elif defined(DATABASE_PGSQL)
+ odb::pgsql::database::print_usage (cout);
+#elif defined(DATABASE_ORACLE)
+ odb::oracle::database::print_usage (cout);
+#elif defined(DATABASE_MSSQL)
+ odb::mssql::database::print_usage (cout);
+#endif
+
+ exit (0);
+ }
+
+#if defined(DATABASE_MYSQL)
+ auto_ptr<database> db (new odb::mysql::database (argc, argv));
+#elif defined(DATABASE_SQLITE)
+ auto_ptr<database> db (
+ new odb::sqlite::database (
+ argc, argv, false, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE));
+
+ // Create the database schema. Due to bugs in SQLite foreign key
+ // support for DDL statements, we need to temporarily disable
+ // foreign keys.
+ //
+ {
+ connection_ptr c (db->connection ());
+
+ c->execute ("PRAGMA foreign_keys=OFF");
+
+ transaction t (c->begin ());
+ schema_catalog::create_schema (*db);
+ t.commit ();
+
+ c->execute ("PRAGMA foreign_keys=ON");
+ }
+#elif defined(DATABASE_PGSQL)
+ auto_ptr<database> db (new odb::pgsql::database (argc, argv));
+#elif defined(DATABASE_ORACLE)
+ auto_ptr<database> db (new odb::oracle::database (argc, argv));
+#elif defined(DATABASE_MSSQL)
+ auto_ptr<database> db (new odb::mssql::database (argc, argv));
+#endif
+
+ return db;
+}
+
+#endif // DATABASE_HXX
diff --git a/bulk/driver.cxx b/bulk/driver.cxx
new file mode 100644
index 0000000..8632905
--- /dev/null
+++ b/bulk/driver.cxx
@@ -0,0 +1,107 @@
+// file : hello/driver.cxx
+// copyright : not copyrighted - public domain
+
+#include <memory> // std::auto_ptr
+#include <iostream>
+
+#include <odb/database.hxx>
+#include <odb/transaction.hxx>
+
+#include "database.hxx" // create_database
+
+#include "person.hxx"
+#include "person-odb.hxx"
+
+using namespace std;
+using namespace odb::core;
+
+int
+main (int argc, char* argv[])
+{
+ try
+ {
+ auto_ptr<database> db (create_database (argc, argv));
+
+ //person p[3];
+ std::vector<person> p (5, person ());
+
+ p[0].id = 1;
+ p[0].num = 1;
+ p[0].str = "aaa";
+
+ p[1].id = 2;
+ p[1].num = 2;
+ p[1].str = "bbb";
+
+ p[2].id = 3;
+ p[2].num = 3;
+ p[2].str = "ccc";
+
+ p[3].id = 4;
+ p[3].num = 4;
+ p[3].str = "ccc";
+
+ p[4].id = 5;
+ p[4].num = 5;
+ p[4].str = "ccc";
+
+ std::vector<person*> pp (5);
+ pp[0] = &p[0];
+ pp[1] = &p[1];
+ pp[2] = &p[2];
+ pp[3] = &p[3];
+ pp[4] = &p[4];
+
+ {
+ transaction t (db->begin ());
+
+ t.tracer (stderr_tracer);
+
+ //db->persist (p, p + 3);
+ //db->persist (p.begin (), p.end ());
+
+ try
+ {
+ db->persist (pp.begin (), pp.end ());
+ }
+ catch (const odb::multiple_exceptions& e)
+ {
+ if (!e.fatal ())
+ cerr << e.what () << endl;
+ else
+ throw;
+ }
+
+ cerr << pp[0]->id << endl
+ << pp[1]->id << endl
+ << pp[2]->id << endl
+ << pp[3]->id << endl
+ << pp[4]->id << endl;
+
+ t.commit ();
+ }
+
+ {
+ transaction t (db->begin ());
+
+ auto_ptr<person> p1 (db->find<person> (1));
+ auto_ptr<person> p2 (db->find<person> (2));
+ auto_ptr<person> p3 (db->find<person> (3));
+ auto_ptr<person> p4 (db->find<person> (4));
+ auto_ptr<person> p5 (db->find<person> (5));
+
+ if (p1.get ()) cerr << p1->id << " " << p1->num << " " << p1->str << endl;
+ if (p2.get ()) cerr << p2->id << " " << p2->num << " " << p2->str << endl;
+ if (p3.get ()) cerr << p3->id << " " << p3->num << " " << p3->str << endl;
+ if (p4.get ()) cerr << p4->id << " " << p4->num << " " << p4->str << endl;
+ if (p5.get ()) cerr << p5->id << " " << p5->num << " " << p5->str << endl;
+
+ t.commit ();
+ }
+ }
+ catch (const odb::exception& e)
+ {
+ cerr << e.what () << endl;
+ return 1;
+ }
+}
diff --git a/bulk/makefile b/bulk/makefile
new file mode 100644
index 0000000..66c704e
--- /dev/null
+++ b/bulk/makefile
@@ -0,0 +1,125 @@
+# file : hello/makefile
+# copyright : Copyright (c) 2009-2013 Code Synthesis Tools CC
+# license : GNU GPL v2; see accompanying LICENSE file
+
+include $(dir $(lastword $(MAKEFILE_LIST)))../build/bootstrap.make
+
+cxx_tun := driver.cxx
+odb_hdr := person.hxx
+cxx_obj := $(addprefix $(out_base)/,$(cxx_tun:.cxx=.o) $(odb_hdr:.hxx=-odb.o))
+cxx_od := $(cxx_obj:.o=.o.d)
+
+driver := $(out_base)/driver
+dist := $(out_base)/.dist
+test := $(out_base)/.test
+clean := $(out_base)/.clean
+
+# Import.
+#
+$(call import,\
+ $(scf_root)/import/odb/stub.make,\
+ odb: odb,odb-rules: odb_rules)
+
+$(call import,\
+ $(scf_root)/import/libodb/stub.make,\
+ l: odb.l,cpp-options: odb.l.cpp-options)
+
+ifdef db_id
+$(call import,\
+ $(scf_root)/import/libodb-$(db_id)/stub.make,\
+ l: odb_db.l,cpp-options: odb_db.l.cpp-options)
+endif
+
+ifeq ($(odb_db.l.cpp-options),)
+odb_db.l.cpp-options := $(out_base)/.unbuildable
+endif
+
+# Build.
+#
+$(driver): $(cxx_obj) $(odb_db.l) $(odb.l)
+$(cxx_obj) $(cxx_od): cpp_options := -I$(out_base) -I$(src_base) -D$(db_macro)
+$(cxx_obj) $(cxx_od): $(odb.l.cpp-options) $(odb_db.l.cpp-options)
+
+genf := $(addprefix $(odb_hdr:.hxx=-odb),.hxx .ixx .cxx) $(odb_hdr:.hxx=.sql)
+gen := $(addprefix $(out_base)/,$(genf))
+
+$(gen): $(odb)
+$(gen): odb := $(odb)
+$(gen) $(dist): export odb_options += --generate-schema --disabled
+$(gen): cpp_options := -I$(src_base)
+$(gen): $(odb.l.cpp-options)
+
+$(gen): odb_options += --database $(db_id)
+
+$(call include-dep,$(cxx_od),$(cxx_obj),$(gen))
+
+# Alias for default target.
+#
+$(out_base)/: $(driver)
+
+# Dist
+#
+name := $(subst /,-,$(subst $(src_root)/,,$(src_base)))
+
+$(dist): sources := $(cxx_tun)
+$(dist): headers := $(odb_hdr)
+$(dist): export name := $(name)
+$(dist): export odb_header_stem := $(basename $(odb_hdr))
+$(dist): export extra_dist := README $(call vc8projs,$(name)) \
+$(call vc9projs,$(name)) $(call vc10projs,$(name)) $(call vc11projs,$(name)) \
+$(call vc12projs,$(name))
+$(dist):
+ $(call dist-data,$(sources) $(headers) README database.hxx)
+ $(call meta-automake,../template/Makefile.am)
+ $(call meta-vc8projs,../template/template,$(name))
+ $(call meta-vc9projs,../template/template,$(name))
+ $(call meta-vc10projs,../template/template,$(name))
+ $(call meta-vc11projs,../template/template,$(name))
+ $(call meta-vc12projs,../template/template,$(name))
+
+# Test.
+#
+$(test): header := $(odb_hdr)
+$(test): $(driver)
+ $(call schema)
+ $(call message,test $<,$< --options-file $(dcf_root)/$(db_id).options)
+
+# Clean.
+#
+$(clean): \
+ $(driver).o.clean \
+ $(addsuffix .cxx.clean,$(cxx_obj)) \
+ $(addsuffix .cxx.clean,$(cxx_od)) \
+ $(addprefix $(out_base)/,$(odb_hdr:.hxx=-odb.cxx.hxx.clean))
+
+# Generated .gitignore.
+#
+ifeq ($(out_base),$(src_base))
+$(driver): | $(out_base)/.gitignore
+
+$(out_base)/.gitignore: files := driver $(genf)
+$(clean): $(out_base)/.gitignore.clean
+
+$(call include,$(bld_root)/git/gitignore.make)
+endif
+
+# How to.
+#
+$(call include,$(bld_root)/dist.make)
+$(call include,$(bld_root)/meta/vc8proj.make)
+$(call include,$(bld_root)/meta/vc9proj.make)
+$(call include,$(bld_root)/meta/vc10proj.make)
+$(call include,$(bld_root)/meta/vc11proj.make)
+$(call include,$(bld_root)/meta/vc12proj.make)
+$(call include,$(bld_root)/meta/automake.make)
+
+$(call include,$(bld_root)/cxx/standard.make) # cxx_standard
+ifdef cxx_standard
+$(gen): odb_options += --std $(cxx_standard)
+$(call include,$(odb_rules))
+endif
+
+$(call include,$(bld_root)/cxx/cxx-d.make)
+$(call include,$(bld_root)/cxx/cxx-o.make)
+$(call include,$(bld_root)/cxx/o-e.make)
+
diff --git a/bulk/mssql/auto/person-odb.cxx b/bulk/mssql/auto/person-odb.cxx
new file mode 100644
index 0000000..69010a3
--- /dev/null
+++ b/bulk/mssql/auto/person-odb.cxx
@@ -0,0 +1,578 @@
+// This file was generated by ODB, object-relational mapping (ORM)
+// compiler for C++.
+//
+
+#include <odb/pre.hxx>
+
+#include "person-odb.hxx"
+
+#include <cassert>
+#include <cstring> // std::memcpy
+#include <iostream>
+
+#include <odb/mssql/traits.hxx>
+#include <odb/mssql/database.hxx>
+#include <odb/mssql/transaction.hxx>
+#include <odb/mssql/connection.hxx>
+#include <odb/mssql/statement.hxx>
+#include <odb/mssql/statement-cache.hxx>
+#include <odb/mssql/simple-object-statements.hxx>
+#include <odb/mssql/container-statements.hxx>
+#include <odb/mssql/exceptions.hxx>
+
+namespace odb
+{
+ // person
+ //
+
+ struct access::object_traits_impl< ::person, id_mssql >::extra_statement_cache_type
+ {
+ extra_statement_cache_type (
+ mssql::connection&,
+ image_type&,
+ mssql::binding&,
+ mssql::binding&)
+ {
+ }
+ };
+
+ access::object_traits_impl< ::person, id_mssql >::id_type
+ access::object_traits_impl< ::person, id_mssql >::
+ id (const id_image_type& i)
+ {
+ mssql::database* db (0);
+ ODB_POTENTIALLY_UNUSED (db);
+
+ id_type id;
+ {
+ mssql::value_traits<
+ long unsigned int,
+ mssql::id_bigint >::set_value (
+ id,
+ i.id_value,
+ i.id_size_ind == SQL_NULL_DATA);
+ }
+
+ return id;
+ }
+
+ void access::object_traits_impl< ::person, id_mssql >::
+ bind (mssql::bind* b,
+ image_type& i,
+ mssql::statement_kind sk)
+ {
+ ODB_POTENTIALLY_UNUSED (sk);
+
+ using namespace mssql;
+
+ std::size_t n (0);
+
+ // id
+ //
+ if (sk != statement_insert && sk != statement_update)
+ {
+ b[n].type = mssql::bind::bigint;
+ b[n].buffer = &i.id_value;
+ b[n].size_ind = &i.id_size_ind;
+ n++;
+ }
+
+ // num
+ //
+ b[n].type = mssql::bind::int_;
+ b[n].buffer = &i.num_value;
+ b[n].size_ind = &i.num_size_ind;
+ n++;
+
+ // str
+ //
+ b[n].type = mssql::bind::long_string;
+ b[n].buffer = &i.str_callback;
+ b[n].size_ind = &i.str_size_ind;
+ b[n].capacity = 0;
+ n++;
+ }
+
+ void access::object_traits_impl< ::person, id_mssql >::
+ bind (mssql::bind* b, id_image_type& i)
+ {
+ std::size_t n (0);
+ b[n].type = mssql::bind::bigint;
+ b[n].buffer = &i.id_value;
+ b[n].size_ind = &i.id_size_ind;
+ }
+
+ void access::object_traits_impl< ::person, id_mssql >::
+ init (image_type& i,
+ const object_type& o,
+ mssql::statement_kind sk)
+ {
+ ODB_POTENTIALLY_UNUSED (i);
+ ODB_POTENTIALLY_UNUSED (o);
+ ODB_POTENTIALLY_UNUSED (sk);
+
+ using namespace mssql;
+
+
+ // num
+ //
+ {
+ unsigned int const& v =
+ o.num;
+
+ bool is_null (false);
+ mssql::value_traits<
+ unsigned int,
+ mssql::id_int >::set_image (
+ i.num_value, is_null, v);
+ i.num_size_ind = is_null ? SQL_NULL_DATA : 0;
+ }
+
+ // str
+ //
+ {
+ ::std::string const& v =
+ o.str;
+
+ bool is_null (false);
+ mssql::value_traits<
+ ::std::string,
+ mssql::id_long_string >::set_image (
+ i.str_callback.callback.param,
+ i.str_callback.context.param,
+ is_null,
+ v);
+ i.str_size_ind = is_null ? SQL_NULL_DATA : SQL_DATA_AT_EXEC;
+ }
+ }
+
+ void access::object_traits_impl< ::person, id_mssql >::
+ init (object_type& o,
+ const image_type& i,
+ database* db)
+ {
+ ODB_POTENTIALLY_UNUSED (o);
+ ODB_POTENTIALLY_UNUSED (i);
+ ODB_POTENTIALLY_UNUSED (db);
+
+ // id
+ //
+ {
+ long unsigned int& v =
+ o.id;
+
+ mssql::value_traits<
+ long unsigned int,
+ mssql::id_bigint >::set_value (
+ v,
+ i.id_value,
+ i.id_size_ind == SQL_NULL_DATA);
+ }
+
+ // num
+ //
+ {
+ unsigned int& v =
+ o.num;
+
+ mssql::value_traits<
+ unsigned int,
+ mssql::id_int >::set_value (
+ v,
+ i.num_value,
+ i.num_size_ind == SQL_NULL_DATA);
+ }
+
+ // str
+ //
+ {
+ ::std::string& v =
+ o.str;
+
+ mssql::value_traits<
+ ::std::string,
+ mssql::id_long_string >::set_value (
+ v,
+ i.str_callback.callback.result,
+ i.str_callback.context.result);
+ }
+ }
+
+ void access::object_traits_impl< ::person, id_mssql >::
+ init (id_image_type& i, const id_type& id)
+ {
+ {
+ bool is_null (false);
+ mssql::value_traits<
+ long unsigned int,
+ mssql::id_bigint >::set_image (
+ i.id_value, is_null, id);
+ i.id_size_ind = is_null ? SQL_NULL_DATA : 0;
+ }
+ }
+
+ const char access::object_traits_impl< ::person, id_mssql >::persist_statement[] =
+ "INSERT INTO [person] "
+ "([num], "
+ "[str]) "
+ "OUTPUT INSERTED.[id] "
+ "VALUES "
+ "(?, ?)";
+
+ const char access::object_traits_impl< ::person, id_mssql >::find_statement[] =
+ "SELECT "
+ "[person].[id], "
+ "[person].[num], "
+ "[person].[str] "
+ "FROM [person] "
+ "WHERE [person].[id]=?";
+
+ const char access::object_traits_impl< ::person, id_mssql >::update_statement[] =
+ "UPDATE [person] "
+ "SET "
+ "[num]=?, "
+ "[str]=? "
+ "WHERE [id]=?";
+
+ const char access::object_traits_impl< ::person, id_mssql >::erase_statement[] =
+ "DELETE FROM [person] "
+ "WHERE [id]=?";
+
+ void access::object_traits_impl< ::person, id_mssql >::
+ persist (database& db, object_type** objs, std::size_t n,
+ multiple_exceptions* mex)
+ {
+ ODB_POTENTIALLY_UNUSED (db);
+ assert (n <= batch);
+
+ using namespace mssql;
+
+ mssql::connection& conn (
+ mssql::transaction::current ().connection ());
+ statements_type& sts (
+ conn.statement_cache ().find_object<object_type> ());
+
+ for (std::size_t i (0); i != n; ++i)
+ {
+ object_type& obj (*objs[i]);
+
+ callback (db,
+ static_cast<const object_type&> (obj),
+ callback_event::pre_persist);
+
+ init (sts.image (i), obj, statement_insert);
+ }
+
+ image_type& im (sts.image (0));
+ binding& imb (sts.insert_image_binding ());
+
+ if (im.version != sts.insert_image_version () ||
+ imb.version == 0)
+ {
+ bind (imb.bind, im, statement_insert);
+ sts.insert_image_version (im.version);
+ imb.version++;
+ }
+
+ // @@ TMP. Why tmp?
+ bind (sts.id_image_binding ().bind, sts.id_image ());
+
+ insert_statement& st (sts.persist_statement ());
+ n = st.execute (n, mex); // Set to actual number of rows attempted.
+
+ for (std::size_t i (0); i != n; ++i)
+ {
+ bool r (st.result (i)); // Sets current in mex.
+
+ if (mex != 0)
+ {
+ if ((*mex)[i] != 0) // Pending exception.
+ continue;
+
+ if (!r)
+ {
+ mex->insert (i, object_already_persistent ());
+ continue;
+ }
+
+ if (mex->fatal ()) // Don't do any extra work.
+ continue;
+ }
+ else if (!r)
+ throw object_already_persistent ();
+
+ object_type& obj (*objs[i]);
+
+ obj.id = id (sts.id_image (0)); //@@ It is always 0! Can probably live with it.
+
+ callback (db,
+ static_cast<const object_type&> (obj),
+ callback_event::post_persist);
+ }
+ }
+
+ void access::object_traits_impl< ::person, id_mssql >::
+ update (database& db, const object_type& obj)
+ {
+ ODB_POTENTIALLY_UNUSED (db);
+
+ using namespace mssql;
+ using mssql::update_statement;
+
+ callback (db, obj, callback_event::pre_update);
+
+ mssql::transaction& tr (mssql::transaction::current ());
+ mssql::connection& conn (tr.connection ());
+ statements_type& sts (
+ conn.statement_cache ().find_object<object_type> ());
+
+ const id_type& id (
+ obj.id);
+ id_image_type& idi (sts.id_image ());
+ init (idi, id);
+
+ image_type& im (sts.image ());
+ init (im, obj, statement_update);
+
+ bool u (false);
+ binding& imb (sts.update_image_binding ());
+ if (im.version != sts.update_image_version () ||
+ imb.version == 0)
+ {
+ bind (imb.bind, im, statement_update);
+ sts.update_image_version (im.version);
+ imb.version++;
+ u = true;
+ }
+
+ binding& idb (sts.id_image_binding ());
+ if (idi.version != sts.update_id_image_version () ||
+ idb.version == 0)
+ {
+ if (idi.version != sts.id_image_version () ||
+ idb.version == 0)
+ {
+ bind (idb.bind, idi);
+ sts.id_image_version (idi.version);
+ idb.version++;
+ }
+
+ sts.update_id_image_version (idi.version);
+
+ if (!u)
+ imb.version++;
+ }
+
+ update_statement& st (sts.update_statement ());
+ if (st.execute () == 0)
+ throw object_not_persistent ();
+
+ callback (db, obj, callback_event::post_update);
+ pointer_cache_traits::update (db, obj);
+ }
+
+ void access::object_traits_impl< ::person, id_mssql >::
+ erase (database& db, const id_type& id)
+ {
+ using namespace mssql;
+
+ ODB_POTENTIALLY_UNUSED (db);
+
+ mssql::connection& conn (
+ mssql::transaction::current ().connection ());
+ statements_type& sts (
+ conn.statement_cache ().find_object<object_type> ());
+
+ id_image_type& i (sts.id_image ());
+ init (i, id);
+
+ binding& idb (sts.id_image_binding ());
+ if (i.version != sts.id_image_version () || idb.version == 0)
+ {
+ bind (idb.bind, i);
+ sts.id_image_version (i.version);
+ idb.version++;
+ }
+
+ if (sts.erase_statement ().execute () != 1)
+ throw object_not_persistent ();
+
+ pointer_cache_traits::erase (db, id);
+ }
+
+ access::object_traits_impl< ::person, id_mssql >::pointer_type
+ access::object_traits_impl< ::person, id_mssql >::
+ find (database& db, const id_type& id)
+ {
+ using namespace mssql;
+
+ {
+ pointer_type p (pointer_cache_traits::find (db, id));
+
+ if (!pointer_traits::null_ptr (p))
+ return p;
+ }
+
+ mssql::connection& conn (
+ mssql::transaction::current ().connection ());
+ statements_type& sts (
+ conn.statement_cache ().find_object<object_type> ());
+
+ statements_type::auto_lock l (sts);
+ auto_result ar;
+
+ if (l.locked ())
+ {
+ if (!find_ (sts, &id))
+ return pointer_type ();
+
+ ar.set (sts.find_statement ());
+ }
+
+ pointer_type p (
+ access::object_factory<object_type, pointer_type>::create ());
+ pointer_traits::guard pg (p);
+
+ pointer_cache_traits::insert_guard ig (
+ pointer_cache_traits::insert (db, id, p));
+
+ object_type& obj (pointer_traits::get_ref (p));
+
+ if (l.locked ())
+ {
+ select_statement& st (sts.find_statement ());
+ ODB_POTENTIALLY_UNUSED (st);
+
+ callback (db, obj, callback_event::pre_load);
+ init (obj, sts.image (), &db);
+ st.stream_result ();
+ ar.free ();
+ load_ (sts, obj, false);
+ sts.load_delayed (0);
+ l.unlock ();
+ callback (db, obj, callback_event::post_load);
+ pointer_cache_traits::load (ig.position ());
+ }
+ else
+ sts.delay_load (id, obj, ig.position ());
+
+ ig.release ();
+ pg.release ();
+ return p;
+ }
+
+ bool access::object_traits_impl< ::person, id_mssql >::
+ find (database& db, const id_type& id, object_type& obj)
+ {
+ using namespace mssql;
+
+ mssql::connection& conn (
+ mssql::transaction::current ().connection ());
+ statements_type& sts (
+ conn.statement_cache ().find_object<object_type> ());
+
+ statements_type::auto_lock l (sts);
+
+ if (!find_ (sts, &id))
+ return false;
+
+ select_statement& st (sts.find_statement ());
+ ODB_POTENTIALLY_UNUSED (st);
+
+ auto_result ar (st);
+ reference_cache_traits::position_type pos (
+ reference_cache_traits::insert (db, id, obj));
+ reference_cache_traits::insert_guard ig (pos);
+
+ callback (db, obj, callback_event::pre_load);
+ init (obj, sts.image (), &db);
+ st.stream_result ();
+ ar.free ();
+ load_ (sts, obj, false);
+ sts.load_delayed (0);
+ l.unlock ();
+ callback (db, obj, callback_event::post_load);
+ reference_cache_traits::load (pos);
+ ig.release ();
+ return true;
+ }
+
+ bool access::object_traits_impl< ::person, id_mssql >::
+ reload (database& db, object_type& obj)
+ {
+ using namespace mssql;
+
+ mssql::connection& conn (
+ mssql::transaction::current ().connection ());
+ statements_type& sts (
+ conn.statement_cache ().find_object<object_type> ());
+
+ statements_type::auto_lock l (sts);
+
+ const id_type& id (
+ obj.id);
+
+ if (!find_ (sts, &id))
+ return false;
+
+ select_statement& st (sts.find_statement ());
+ ODB_POTENTIALLY_UNUSED (st);
+
+ auto_result ar (st);
+
+ callback (db, obj, callback_event::pre_load);
+ init (obj, sts.image (), &db);
+ st.stream_result ();
+ ar.free ();
+ load_ (sts, obj, true);
+ sts.load_delayed (0);
+ l.unlock ();
+ callback (db, obj, callback_event::post_load);
+ return true;
+ }
+
+ bool access::object_traits_impl< ::person, id_mssql >::
+ find_ (statements_type& sts,
+ const id_type* id)
+ {
+ using namespace mssql;
+
+ id_image_type& i (sts.id_image ());
+ init (i, *id);
+
+ binding& idb (sts.id_image_binding ());
+ if (i.version != sts.id_image_version () || idb.version == 0)
+ {
+ bind (idb.bind, i);
+ sts.id_image_version (i.version);
+ idb.version++;
+ }
+
+ image_type& im (sts.image ());
+ binding& imb (sts.select_image_binding ());
+
+ if (im.version != sts.select_image_version () ||
+ imb.version == 0)
+ {
+ bind (imb.bind, im, statement_select);
+ sts.select_image_version (im.version);
+ imb.version++;
+ }
+
+ select_statement& st (sts.find_statement ());
+
+ st.execute ();
+ auto_result ar (st);
+ select_statement::result r (st.fetch ());
+
+ if (r != select_statement::no_data)
+ {
+ ar.release ();
+ return true;
+ }
+ else
+ return false;
+ }
+}
+
+#include <odb/post.hxx>
diff --git a/bulk/mssql/auto/person-odb.hxx b/bulk/mssql/auto/person-odb.hxx
new file mode 100644
index 0000000..f73d829
--- /dev/null
+++ b/bulk/mssql/auto/person-odb.hxx
@@ -0,0 +1,219 @@
+// This file was generated by ODB, object-relational mapping (ORM)
+// compiler for C++.
+//
+
+#ifndef PERSON_ODB_HXX
+#define PERSON_ODB_HXX
+
+#include <odb/version.hxx>
+
+#if (ODB_VERSION != 20302UL)
+#error ODB runtime version mismatch
+#endif
+
+#include <odb/pre.hxx>
+
+#include "person.hxx"
+
+#include <memory>
+#include <cstddef>
+
+#include <odb/core.hxx>
+#include <odb/traits.hxx>
+#include <odb/callback.hxx>
+#include <odb/wrapper-traits.hxx>
+#include <odb/pointer-traits.hxx>
+#include <odb/container-traits.hxx>
+#include <odb/no-op-cache-traits.hxx>
+
+#include <odb/details/unused.hxx>
+
+namespace odb
+{
+ // person
+ //
+ template <>
+ struct class_traits< ::person >
+ {
+ static const class_kind kind = class_object;
+ };
+
+ template <>
+ class access::object_traits< ::person >
+ {
+ public:
+ typedef ::person object_type;
+ typedef ::person* pointer_type;
+ typedef odb::pointer_traits<pointer_type> pointer_traits;
+
+ static const bool polymorphic = false;
+
+ typedef long unsigned int id_type;
+
+ static const bool auto_id = true;
+
+ static const bool abstract = false;
+
+ static id_type
+ id (const object_type&);
+
+ typedef
+ no_op_pointer_cache_traits<pointer_type>
+ pointer_cache_traits;
+
+ typedef
+ no_op_reference_cache_traits<object_type>
+ reference_cache_traits;
+
+ static void
+ callback (database&, object_type&, callback_event);
+
+ static void
+ callback (database&, const object_type&, callback_event);
+ };
+}
+
+#include <odb/details/buffer.hxx>
+
+#include <odb/mssql/version.hxx>
+#include <odb/mssql/forward.hxx>
+#include <odb/mssql/binding.hxx>
+#include <odb/mssql/mssql-types.hxx>
+
+namespace odb
+{
+ // person
+ //
+ template <>
+ class access::object_traits_impl< ::person, id_mssql >:
+ public access::object_traits< ::person >
+ {
+ public:
+ static const bool rowversion = false;
+
+ static const std::size_t batch = 3UL;
+
+ struct id_image_type
+ {
+ long long id_value;
+ SQLLEN id_size_ind;
+
+ std::size_t version;
+ };
+
+ struct image_type
+ {
+ // id
+ //
+ long long id_value;
+ SQLLEN id_size_ind;
+
+ // num
+ //
+ int num_value;
+ SQLLEN num_size_ind;
+
+ // str
+ //
+ mutable mssql::long_callback str_callback;
+ SQLLEN str_size_ind;
+
+ std::size_t version;
+
+ mssql::change_callback*
+ change_callback ()
+ {
+ return 0;
+ }
+ };
+
+ struct extra_statement_cache_type;
+
+ using object_traits<object_type>::id;
+
+ static id_type
+ id (const id_image_type&);
+
+ static void
+ bind (mssql::bind*,
+ image_type&,
+ mssql::statement_kind);
+
+ static void
+ bind (mssql::bind*, id_image_type&);
+
+ static void
+ init (image_type&,
+ const object_type&,
+ mssql::statement_kind);
+
+ static void
+ init (object_type&,
+ const image_type&,
+ database*);
+
+ static void
+ init (id_image_type&, const id_type&);
+
+ typedef mssql::object_statements<object_type> statements_type;
+
+ static const std::size_t column_count = 3UL;
+ static const std::size_t id_column_count = 1UL;
+ static const std::size_t inverse_column_count = 0UL;
+ static const std::size_t readonly_column_count = 0UL;
+ static const std::size_t managed_optimistic_column_count = 0UL;
+
+ static const std::size_t separate_load_column_count = 0UL;
+ static const std::size_t separate_update_column_count = 0UL;
+
+ static const bool versioned = false;
+
+ static const char persist_statement[];
+ static const char find_statement[];
+ static const char update_statement[];
+ static const char erase_statement[];
+
+ static void
+ persist (database&, object_type**, std::size_t, multiple_exceptions*);
+
+ static pointer_type
+ find (database&, const id_type&);
+
+ static bool
+ find (database&, const id_type&, object_type&);
+
+ static bool
+ reload (database&, object_type&);
+
+ static void
+ update (database&, const object_type&);
+
+ static void
+ erase (database&, const id_type&);
+
+ static void
+ erase (database&, const object_type&);
+
+ public:
+ static bool
+ find_ (statements_type&,
+ const id_type*);
+
+ static void
+ load_ (statements_type&,
+ object_type&,
+ bool reload);
+ };
+
+ template <>
+ class access::object_traits_impl< ::person, id_common >:
+ public access::object_traits_impl< ::person, id_mssql >
+ {
+ };
+}
+
+#include "person-odb.ixx"
+
+#include <odb/post.hxx>
+
+#endif // PERSON_ODB_HXX
diff --git a/bulk/mssql/auto/person-odb.ixx b/bulk/mssql/auto/person-odb.ixx
new file mode 100644
index 0000000..73f62a7
--- /dev/null
+++ b/bulk/mssql/auto/person-odb.ixx
@@ -0,0 +1,61 @@
+// This file was generated by ODB, object-relational mapping (ORM)
+// compiler for C++.
+//
+
+namespace odb
+{
+ // person
+ //
+
+ inline
+ access::object_traits< ::person >::id_type
+ access::object_traits< ::person >::
+ id (const object_type& o)
+ {
+ return o.id;
+ }
+
+ inline
+ void access::object_traits< ::person >::
+ callback (database& db, object_type& x, callback_event e)
+ {
+ ODB_POTENTIALLY_UNUSED (db);
+ ODB_POTENTIALLY_UNUSED (x);
+ ODB_POTENTIALLY_UNUSED (e);
+ }
+
+ inline
+ void access::object_traits< ::person >::
+ callback (database& db, const object_type& x, callback_event e)
+ {
+ ODB_POTENTIALLY_UNUSED (db);
+ ODB_POTENTIALLY_UNUSED (x);
+ ODB_POTENTIALLY_UNUSED (e);
+ }
+}
+
+namespace odb
+{
+ // person
+ //
+
+ inline
+ void access::object_traits_impl< ::person, id_mssql >::
+ erase (database& db, const object_type& obj)
+ {
+ callback (db, obj, callback_event::pre_erase);
+ erase (db, id (obj));
+ callback (db, obj, callback_event::post_erase);
+ }
+
+ inline
+ void access::object_traits_impl< ::person, id_mssql >::
+ load_ (statements_type& sts,
+ object_type& obj,
+ bool)
+ {
+ ODB_POTENTIALLY_UNUSED (sts);
+ ODB_POTENTIALLY_UNUSED (obj);
+ }
+}
+
diff --git a/bulk/mssql/auto/person.sql b/bulk/mssql/auto/person.sql
new file mode 100644
index 0000000..784d449
--- /dev/null
+++ b/bulk/mssql/auto/person.sql
@@ -0,0 +1,15 @@
+/* This file was generated by ODB, object-relational mapping (ORM)
+ * compiler for C++.
+ */
+
+
+IF OBJECT_ID('person', 'U') IS NOT NULL
+ DROP TABLE [person];
+GO
+
+
+CREATE TABLE [person] (
+ [id] BIGINT NOT NULL PRIMARY KEY IDENTITY,
+ [num] INT NOT NULL UNIQUE,
+ [str] VARCHAR(max) NOT NULL);
+GO
diff --git a/bulk/mssql/id/person-odb.cxx b/bulk/mssql/id/person-odb.cxx
new file mode 100644
index 0000000..48d535c
--- /dev/null
+++ b/bulk/mssql/id/person-odb.cxx
@@ -0,0 +1,569 @@
+// This file was generated by ODB, object-relational mapping (ORM)
+// compiler for C++.
+//
+
+#include <odb/pre.hxx>
+
+#include "person-odb.hxx"
+
+#include <cassert>
+#include <cstring> // std::memcpy
+#include <iostream>
+
+#include <odb/mssql/traits.hxx>
+#include <odb/mssql/database.hxx>
+#include <odb/mssql/transaction.hxx>
+#include <odb/mssql/connection.hxx>
+#include <odb/mssql/statement.hxx>
+#include <odb/mssql/statement-cache.hxx>
+#include <odb/mssql/simple-object-statements.hxx>
+#include <odb/mssql/container-statements.hxx>
+#include <odb/mssql/exceptions.hxx>
+
+namespace odb
+{
+ // person
+ //
+
+ struct access::object_traits_impl< ::person, id_mssql >::extra_statement_cache_type
+ {
+ extra_statement_cache_type (
+ mssql::connection&,
+ image_type&,
+ mssql::binding&,
+ mssql::binding&)
+ {
+ }
+ };
+
+ void access::object_traits_impl< ::person, id_mssql >::
+ bind (mssql::bind* b,
+ image_type& i,
+ mssql::statement_kind sk)
+ {
+ ODB_POTENTIALLY_UNUSED (sk);
+
+ using namespace mssql;
+
+ std::size_t n (0);
+
+ // id
+ //
+ if (/*%%sk != statement_insert &&*/ sk != statement_update)
+ {
+ b[n].type = mssql::bind::bigint;
+ b[n].buffer = &i.id_value;
+ b[n].size_ind = &i.id_size_ind;
+ n++;
+ }
+
+ // num
+ //
+ b[n].type = mssql::bind::int_;
+ b[n].buffer = &i.num_value;
+ b[n].size_ind = &i.num_size_ind;
+ n++;
+
+ // str
+ //
+ b[n].type = mssql::bind::long_string;
+ b[n].buffer = &i.str_callback;
+ b[n].size_ind = &i.str_size_ind;
+ b[n].capacity = 0;
+ n++;
+ }
+
+ void access::object_traits_impl< ::person, id_mssql >::
+ bind (mssql::bind* b, id_image_type& i)
+ {
+ std::size_t n (0);
+ b[n].type = mssql::bind::bigint;
+ b[n].buffer = &i.id_value;
+ b[n].size_ind = &i.id_size_ind;
+ }
+
+ void access::object_traits_impl< ::person, id_mssql >::
+ init (image_type& i,
+ const object_type& o,
+ mssql::statement_kind sk)
+ {
+ ODB_POTENTIALLY_UNUSED (i);
+ ODB_POTENTIALLY_UNUSED (o);
+ ODB_POTENTIALLY_UNUSED (sk);
+
+ using namespace mssql;
+
+ // id %%
+ //
+ {
+ long unsigned int const& v =
+ o.id;
+
+ bool is_null (false);
+ mssql::value_traits<
+ long unsigned int,
+ mssql::id_bigint >::set_image (
+ i.id_value, is_null, v);
+ i.id_size_ind = is_null ? SQL_NULL_DATA : 0;
+ }
+
+ // num
+ //
+ {
+ unsigned int const& v =
+ o.num;
+
+ bool is_null (false);
+ mssql::value_traits<
+ unsigned int,
+ mssql::id_int >::set_image (
+ i.num_value, is_null, v);
+ i.num_size_ind = is_null ? SQL_NULL_DATA : 0;
+ }
+
+ // str
+ //
+ {
+ ::std::string const& v =
+ o.str;
+
+ bool is_null (false);
+ mssql::value_traits<
+ ::std::string,
+ mssql::id_long_string >::set_image (
+ i.str_callback.callback.param,
+ i.str_callback.context.param,
+ is_null,
+ v);
+ i.str_size_ind = is_null ? SQL_NULL_DATA : SQL_DATA_AT_EXEC;
+ }
+ }
+
+ void access::object_traits_impl< ::person, id_mssql >::
+ init (object_type& o,
+ const image_type& i,
+ database* db)
+ {
+ ODB_POTENTIALLY_UNUSED (o);
+ ODB_POTENTIALLY_UNUSED (i);
+ ODB_POTENTIALLY_UNUSED (db);
+
+ // id
+ //
+ {
+ long unsigned int& v =
+ o.id;
+
+ mssql::value_traits<
+ long unsigned int,
+ mssql::id_bigint >::set_value (
+ v,
+ i.id_value,
+ i.id_size_ind == SQL_NULL_DATA);
+ }
+
+ // num
+ //
+ {
+ unsigned int& v =
+ o.num;
+
+ mssql::value_traits<
+ unsigned int,
+ mssql::id_int >::set_value (
+ v,
+ i.num_value,
+ i.num_size_ind == SQL_NULL_DATA);
+ }
+
+ // str
+ //
+ {
+ ::std::string& v =
+ o.str;
+
+ mssql::value_traits<
+ ::std::string,
+ mssql::id_long_string >::set_value (
+ v,
+ i.str_callback.callback.result,
+ i.str_callback.context.result);
+ }
+ }
+
+ void access::object_traits_impl< ::person, id_mssql >::
+ init (id_image_type& i, const id_type& id)
+ {
+ {
+ bool is_null (false);
+ mssql::value_traits<
+ long unsigned int,
+ mssql::id_bigint >::set_image (
+ i.id_value, is_null, id);
+ i.id_size_ind = is_null ? SQL_NULL_DATA : 0;
+ }
+ }
+
+ const char access::object_traits_impl< ::person, id_mssql >::persist_statement[] =
+ "INSERT INTO [person] "
+ "([id], " // %%
+ "[num], "
+ "[str]) "
+ //%% "OUTPUT INSERTED.[id] "
+ "VALUES "
+ "(?, ?, ?)"; // %%
+
+ const char access::object_traits_impl< ::person, id_mssql >::find_statement[] =
+ "SELECT "
+ "[person].[id], "
+ "[person].[num], "
+ "[person].[str] "
+ "FROM [person] "
+ "WHERE [person].[id]=?";
+
+ const char access::object_traits_impl< ::person, id_mssql >::update_statement[] =
+ "UPDATE [person] "
+ "SET "
+ "[num]=?, "
+ "[str]=? "
+ "WHERE [id]=?";
+
+ const char access::object_traits_impl< ::person, id_mssql >::erase_statement[] =
+ "DELETE FROM [person] "
+ "WHERE [id]=?";
+
+ void access::object_traits_impl< ::person, id_mssql >::
+ persist (database& db, object_type** objs, std::size_t n,
+ multiple_exceptions* mex)
+ {
+ ODB_POTENTIALLY_UNUSED (db);
+ assert (n <= batch);
+
+ using namespace mssql;
+
+ mssql::connection& conn (
+ mssql::transaction::current ().connection ());
+ statements_type& sts (
+ conn.statement_cache ().find_object<object_type> ());
+
+ for (std::size_t i (0); i != n; ++i)
+ {
+ object_type& obj (*objs[i]);
+
+ callback (db,
+ static_cast<const object_type&> (obj),
+ callback_event::pre_persist);
+
+ init (sts.image (i), obj, statement_insert);
+ }
+
+ image_type& im (sts.image (0));
+ binding& imb (sts.insert_image_binding ());
+
+ if (im.version != sts.insert_image_version () ||
+ imb.version == 0)
+ {
+ bind (imb.bind, im, statement_insert);
+ sts.insert_image_version (im.version);
+ imb.version++;
+ }
+
+ insert_statement& st (sts.persist_statement ());
+ n = st.execute (n, mex); // Set to actual number of rows attempted.
+
+ for (std::size_t i (0); i != n; ++i)
+ {
+ bool r (st.result (i)); // Sets current in mex.
+
+ if (mex != 0)
+ {
+ if ((*mex)[i] != 0) // Pending exception.
+ continue;
+
+ if (!r)
+ {
+ mex->insert (i, object_already_persistent ());
+ continue;
+ }
+
+ if (mex->fatal ()) // Don't do any extra work.
+ continue;
+ }
+ else if (!r)
+ throw object_already_persistent ();
+
+ object_type& obj (*objs[i]);
+
+ //%% obj.id = static_cast< id_type > (st.id ());
+
+ callback (db,
+ static_cast<const object_type&> (obj),
+ callback_event::post_persist);
+ }
+ }
+
+ void access::object_traits_impl< ::person, id_mssql >::
+ update (database& db, const object_type& obj)
+ {
+ ODB_POTENTIALLY_UNUSED (db);
+
+ using namespace mssql;
+ using mssql::update_statement;
+
+ callback (db, obj, callback_event::pre_update);
+
+ mssql::transaction& tr (mssql::transaction::current ());
+ mssql::connection& conn (tr.connection ());
+ statements_type& sts (
+ conn.statement_cache ().find_object<object_type> ());
+
+ const id_type& id (
+ obj.id);
+ id_image_type& idi (sts.id_image ());
+ init (idi, id);
+
+ image_type& im (sts.image ());
+ init (im, obj, statement_update);
+
+ bool u (false);
+ binding& imb (sts.update_image_binding ());
+ if (im.version != sts.update_image_version () ||
+ imb.version == 0)
+ {
+ bind (imb.bind, im, statement_update);
+ sts.update_image_version (im.version);
+ imb.version++;
+ u = true;
+ }
+
+ binding& idb (sts.id_image_binding ());
+ if (idi.version != sts.update_id_image_version () ||
+ idb.version == 0)
+ {
+ if (idi.version != sts.id_image_version () ||
+ idb.version == 0)
+ {
+ bind (idb.bind, idi);
+ sts.id_image_version (idi.version);
+ idb.version++;
+ }
+
+ sts.update_id_image_version (idi.version);
+
+ if (!u)
+ imb.version++;
+ }
+
+ update_statement& st (sts.update_statement ());
+ if (st.execute () == 0)
+ throw object_not_persistent ();
+
+ callback (db, obj, callback_event::post_update);
+ pointer_cache_traits::update (db, obj);
+ }
+
+ void access::object_traits_impl< ::person, id_mssql >::
+ erase (database& db, const id_type& id)
+ {
+ using namespace mssql;
+
+ ODB_POTENTIALLY_UNUSED (db);
+
+ mssql::connection& conn (
+ mssql::transaction::current ().connection ());
+ statements_type& sts (
+ conn.statement_cache ().find_object<object_type> ());
+
+ id_image_type& i (sts.id_image ());
+ init (i, id);
+
+ binding& idb (sts.id_image_binding ());
+ if (i.version != sts.id_image_version () || idb.version == 0)
+ {
+ bind (idb.bind, i);
+ sts.id_image_version (i.version);
+ idb.version++;
+ }
+
+ if (sts.erase_statement ().execute () != 1)
+ throw object_not_persistent ();
+
+ pointer_cache_traits::erase (db, id);
+ }
+
+ access::object_traits_impl< ::person, id_mssql >::pointer_type
+ access::object_traits_impl< ::person, id_mssql >::
+ find (database& db, const id_type& id)
+ {
+ using namespace mssql;
+
+ {
+ pointer_type p (pointer_cache_traits::find (db, id));
+
+ if (!pointer_traits::null_ptr (p))
+ return p;
+ }
+
+ mssql::connection& conn (
+ mssql::transaction::current ().connection ());
+ statements_type& sts (
+ conn.statement_cache ().find_object<object_type> ());
+
+ statements_type::auto_lock l (sts);
+ auto_result ar;
+
+ if (l.locked ())
+ {
+ if (!find_ (sts, &id))
+ return pointer_type ();
+
+ ar.set (sts.find_statement ());
+ }
+
+ pointer_type p (
+ access::object_factory<object_type, pointer_type>::create ());
+ pointer_traits::guard pg (p);
+
+ pointer_cache_traits::insert_guard ig (
+ pointer_cache_traits::insert (db, id, p));
+
+ object_type& obj (pointer_traits::get_ref (p));
+
+ if (l.locked ())
+ {
+ select_statement& st (sts.find_statement ());
+ ODB_POTENTIALLY_UNUSED (st);
+
+ callback (db, obj, callback_event::pre_load);
+ init (obj, sts.image (), &db);
+ st.stream_result ();
+ ar.free ();
+ load_ (sts, obj, false);
+ sts.load_delayed (0);
+ l.unlock ();
+ callback (db, obj, callback_event::post_load);
+ pointer_cache_traits::load (ig.position ());
+ }
+ else
+ sts.delay_load (id, obj, ig.position ());
+
+ ig.release ();
+ pg.release ();
+ return p;
+ }
+
+ bool access::object_traits_impl< ::person, id_mssql >::
+ find (database& db, const id_type& id, object_type& obj)
+ {
+ using namespace mssql;
+
+ mssql::connection& conn (
+ mssql::transaction::current ().connection ());
+ statements_type& sts (
+ conn.statement_cache ().find_object<object_type> ());
+
+ statements_type::auto_lock l (sts);
+
+ if (!find_ (sts, &id))
+ return false;
+
+ select_statement& st (sts.find_statement ());
+ ODB_POTENTIALLY_UNUSED (st);
+
+ auto_result ar (st);
+ reference_cache_traits::position_type pos (
+ reference_cache_traits::insert (db, id, obj));
+ reference_cache_traits::insert_guard ig (pos);
+
+ callback (db, obj, callback_event::pre_load);
+ init (obj, sts.image (), &db);
+ st.stream_result ();
+ ar.free ();
+ load_ (sts, obj, false);
+ sts.load_delayed (0);
+ l.unlock ();
+ callback (db, obj, callback_event::post_load);
+ reference_cache_traits::load (pos);
+ ig.release ();
+ return true;
+ }
+
+ bool access::object_traits_impl< ::person, id_mssql >::
+ reload (database& db, object_type& obj)
+ {
+ using namespace mssql;
+
+ mssql::connection& conn (
+ mssql::transaction::current ().connection ());
+ statements_type& sts (
+ conn.statement_cache ().find_object<object_type> ());
+
+ statements_type::auto_lock l (sts);
+
+ const id_type& id (
+ obj.id);
+
+ if (!find_ (sts, &id))
+ return false;
+
+ select_statement& st (sts.find_statement ());
+ ODB_POTENTIALLY_UNUSED (st);
+
+ auto_result ar (st);
+
+ callback (db, obj, callback_event::pre_load);
+ init (obj, sts.image (), &db);
+ st.stream_result ();
+ ar.free ();
+ load_ (sts, obj, true);
+ sts.load_delayed (0);
+ l.unlock ();
+ callback (db, obj, callback_event::post_load);
+ return true;
+ }
+
+ bool access::object_traits_impl< ::person, id_mssql >::
+ find_ (statements_type& sts,
+ const id_type* id)
+ {
+ using namespace mssql;
+
+ id_image_type& i (sts.id_image ());
+ init (i, *id);
+
+ binding& idb (sts.id_image_binding ());
+ if (i.version != sts.id_image_version () || idb.version == 0)
+ {
+ bind (idb.bind, i);
+ sts.id_image_version (i.version);
+ idb.version++;
+ }
+
+ image_type& im (sts.image ());
+ binding& imb (sts.select_image_binding ());
+
+ if (im.version != sts.select_image_version () ||
+ imb.version == 0)
+ {
+ bind (imb.bind, im, statement_select);
+ sts.select_image_version (im.version);
+ imb.version++;
+ }
+
+ select_statement& st (sts.find_statement ());
+
+ st.execute ();
+ auto_result ar (st);
+ select_statement::result r (st.fetch ());
+
+ if (r != select_statement::no_data)
+ {
+ ar.release ();
+ return true;
+ }
+ else
+ return false;
+ }
+}
+
+#include <odb/post.hxx>
diff --git a/bulk/mssql/id/person-odb.hxx b/bulk/mssql/id/person-odb.hxx
new file mode 100644
index 0000000..53434d6
--- /dev/null
+++ b/bulk/mssql/id/person-odb.hxx
@@ -0,0 +1,216 @@
+// This file was generated by ODB, object-relational mapping (ORM)
+// compiler for C++.
+//
+
+#ifndef PERSON_ODB_HXX
+#define PERSON_ODB_HXX
+
+#include <odb/version.hxx>
+
+#if (ODB_VERSION != 20302UL)
+#error ODB runtime version mismatch
+#endif
+
+#include <odb/pre.hxx>
+
+#include "person.hxx"
+
+#include <memory>
+#include <cstddef>
+
+#include <odb/core.hxx>
+#include <odb/traits.hxx>
+#include <odb/callback.hxx>
+#include <odb/wrapper-traits.hxx>
+#include <odb/pointer-traits.hxx>
+#include <odb/container-traits.hxx>
+#include <odb/no-op-cache-traits.hxx>
+
+#include <odb/details/unused.hxx>
+
+namespace odb
+{
+ // person
+ //
+ template <>
+ struct class_traits< ::person >
+ {
+ static const class_kind kind = class_object;
+ };
+
+ template <>
+ class access::object_traits< ::person >
+ {
+ public:
+ typedef ::person object_type;
+ typedef ::person* pointer_type;
+ typedef odb::pointer_traits<pointer_type> pointer_traits;
+
+ static const bool polymorphic = false;
+
+ typedef long unsigned int id_type;
+
+ static const bool auto_id = false; //%%true;
+
+ static const bool abstract = false;
+
+ static id_type
+ id (const object_type&);
+
+ typedef
+ no_op_pointer_cache_traits<pointer_type>
+ pointer_cache_traits;
+
+ typedef
+ no_op_reference_cache_traits<object_type>
+ reference_cache_traits;
+
+ static void
+ callback (database&, object_type&, callback_event);
+
+ static void
+ callback (database&, const object_type&, callback_event);
+ };
+}
+
+#include <odb/details/buffer.hxx>
+
+#include <odb/mssql/version.hxx>
+#include <odb/mssql/forward.hxx>
+#include <odb/mssql/binding.hxx>
+#include <odb/mssql/mssql-types.hxx>
+
+namespace odb
+{
+ // person
+ //
+ template <>
+ class access::object_traits_impl< ::person, id_mssql >:
+ public access::object_traits< ::person >
+ {
+ public:
+ static const bool rowversion = false;
+
+ static const std::size_t batch = 3UL;
+
+ struct id_image_type
+ {
+ long long id_value;
+ SQLLEN id_size_ind;
+
+ std::size_t version;
+ };
+
+ struct image_type
+ {
+ // id
+ //
+ long long id_value;
+ SQLLEN id_size_ind;
+
+ // num
+ //
+ int num_value;
+ SQLLEN num_size_ind;
+
+ // str
+ //
+ mutable mssql::long_callback str_callback;
+ SQLLEN str_size_ind;
+
+ std::size_t version;
+
+ mssql::change_callback*
+ change_callback ()
+ {
+ return 0;
+ }
+ };
+
+ struct extra_statement_cache_type;
+
+ using object_traits<object_type>::id;
+
+ static void
+ bind (mssql::bind*,
+ image_type&,
+ mssql::statement_kind);
+
+ static void
+ bind (mssql::bind*, id_image_type&);
+
+ static void
+ init (image_type&,
+ const object_type&,
+ mssql::statement_kind);
+
+ static void
+ init (object_type&,
+ const image_type&,
+ database*);
+
+ static void
+ init (id_image_type&, const id_type&);
+
+ typedef mssql::object_statements<object_type> statements_type;
+
+ static const std::size_t column_count = 3UL;
+ static const std::size_t id_column_count = 1UL;
+ static const std::size_t inverse_column_count = 0UL;
+ static const std::size_t readonly_column_count = 0UL;
+ static const std::size_t managed_optimistic_column_count = 0UL;
+
+ static const std::size_t separate_load_column_count = 0UL;
+ static const std::size_t separate_update_column_count = 0UL;
+
+ static const bool versioned = false;
+
+ static const char persist_statement[];
+ static const char find_statement[];
+ static const char update_statement[];
+ static const char erase_statement[];
+
+ static void
+ persist (database&, object_type**, std::size_t, multiple_exceptions*);
+
+ static pointer_type
+ find (database&, const id_type&);
+
+ static bool
+ find (database&, const id_type&, object_type&);
+
+ static bool
+ reload (database&, object_type&);
+
+ static void
+ update (database&, const object_type&);
+
+ static void
+ erase (database&, const id_type&);
+
+ static void
+ erase (database&, const object_type&);
+
+ public:
+ static bool
+ find_ (statements_type&,
+ const id_type*);
+
+ static void
+ load_ (statements_type&,
+ object_type&,
+ bool reload);
+ };
+
+ template <>
+ class access::object_traits_impl< ::person, id_common >:
+ public access::object_traits_impl< ::person, id_mssql >
+ {
+ };
+}
+
+#include "person-odb.ixx"
+
+#include <odb/post.hxx>
+
+#endif // PERSON_ODB_HXX
diff --git a/bulk/mssql/id/person-odb.ixx b/bulk/mssql/id/person-odb.ixx
new file mode 100644
index 0000000..73f62a7
--- /dev/null
+++ b/bulk/mssql/id/person-odb.ixx
@@ -0,0 +1,61 @@
+// This file was generated by ODB, object-relational mapping (ORM)
+// compiler for C++.
+//
+
+namespace odb
+{
+ // person
+ //
+
+ inline
+ access::object_traits< ::person >::id_type
+ access::object_traits< ::person >::
+ id (const object_type& o)
+ {
+ return o.id;
+ }
+
+ inline
+ void access::object_traits< ::person >::
+ callback (database& db, object_type& x, callback_event e)
+ {
+ ODB_POTENTIALLY_UNUSED (db);
+ ODB_POTENTIALLY_UNUSED (x);
+ ODB_POTENTIALLY_UNUSED (e);
+ }
+
+ inline
+ void access::object_traits< ::person >::
+ callback (database& db, const object_type& x, callback_event e)
+ {
+ ODB_POTENTIALLY_UNUSED (db);
+ ODB_POTENTIALLY_UNUSED (x);
+ ODB_POTENTIALLY_UNUSED (e);
+ }
+}
+
+namespace odb
+{
+ // person
+ //
+
+ inline
+ void access::object_traits_impl< ::person, id_mssql >::
+ erase (database& db, const object_type& obj)
+ {
+ callback (db, obj, callback_event::pre_erase);
+ erase (db, id (obj));
+ callback (db, obj, callback_event::post_erase);
+ }
+
+ inline
+ void access::object_traits_impl< ::person, id_mssql >::
+ load_ (statements_type& sts,
+ object_type& obj,
+ bool)
+ {
+ ODB_POTENTIALLY_UNUSED (sts);
+ ODB_POTENTIALLY_UNUSED (obj);
+ }
+}
+
diff --git a/bulk/mssql/id/person.sql b/bulk/mssql/id/person.sql
new file mode 100644
index 0000000..c0d7cae
--- /dev/null
+++ b/bulk/mssql/id/person.sql
@@ -0,0 +1,12 @@
+/* This file was generated by ODB, object-relational mapping (ORM)
+ * compiler for C++.
+ */
+IF OBJECT_ID('person', 'U') IS NOT NULL
+ DROP TABLE [person];
+GO
+
+CREATE TABLE [person] (
+ [id] BIGINT NOT NULL PRIMARY KEY /*%%IDENTITY*/,
+ [num] INT NOT NULL UNIQUE,
+ [str] VARCHAR(max) NOT NULL);
+GO
diff --git a/bulk/mssql/orig/person-odb.cxx b/bulk/mssql/orig/person-odb.cxx
new file mode 100644
index 0000000..6ed2172
--- /dev/null
+++ b/bulk/mssql/orig/person-odb.cxx
@@ -0,0 +1,524 @@
+// This file was generated by ODB, object-relational mapping (ORM)
+// compiler for C++.
+//
+
+#include <odb/pre.hxx>
+
+#include "person-odb.hxx"
+
+#include <cassert>
+#include <cstring> // std::memcpy
+
+
+#include <odb/mssql/traits.hxx>
+#include <odb/mssql/database.hxx>
+#include <odb/mssql/transaction.hxx>
+#include <odb/mssql/connection.hxx>
+#include <odb/mssql/statement.hxx>
+#include <odb/mssql/statement-cache.hxx>
+#include <odb/mssql/simple-object-statements.hxx>
+#include <odb/mssql/container-statements.hxx>
+#include <odb/mssql/exceptions.hxx>
+
+namespace odb
+{
+ // person
+ //
+
+ struct access::object_traits_impl< ::person, id_mssql >::extra_statement_cache_type
+ {
+ extra_statement_cache_type (
+ mssql::connection&,
+ image_type&,
+ mssql::binding&,
+ mssql::binding&)
+ {
+ }
+ };
+
+ void access::object_traits_impl< ::person, id_mssql >::
+ bind (mssql::bind* b,
+ image_type& i,
+ mssql::statement_kind sk)
+ {
+ ODB_POTENTIALLY_UNUSED (sk);
+
+ using namespace mssql;
+
+ std::size_t n (0);
+
+ // id
+ //
+ if (sk != statement_insert && sk != statement_update)
+ {
+ b[n].type = mssql::bind::bigint;
+ b[n].buffer = &i.id_value;
+ b[n].size_ind = &i.id_size_ind;
+ n++;
+ }
+
+ // num
+ //
+ b[n].type = mssql::bind::int_;
+ b[n].buffer = &i.num_value;
+ b[n].size_ind = &i.num_size_ind;
+ n++;
+
+ // str
+ //
+ b[n].type = mssql::bind::long_string;
+ b[n].buffer = &i.str_callback;
+ b[n].size_ind = &i.str_size_ind;
+ b[n].capacity = 0;
+ n++;
+ }
+
+ void access::object_traits_impl< ::person, id_mssql >::
+ bind (mssql::bind* b, id_image_type& i)
+ {
+ std::size_t n (0);
+ b[n].type = mssql::bind::bigint;
+ b[n].buffer = &i.id_value;
+ b[n].size_ind = &i.id_size_ind;
+ }
+
+ void access::object_traits_impl< ::person, id_mssql >::
+ init (image_type& i,
+ const object_type& o,
+ mssql::statement_kind sk)
+ {
+ ODB_POTENTIALLY_UNUSED (i);
+ ODB_POTENTIALLY_UNUSED (o);
+ ODB_POTENTIALLY_UNUSED (sk);
+
+ using namespace mssql;
+
+ // num
+ //
+ {
+ unsigned int const& v =
+ o.num;
+
+ bool is_null (false);
+ mssql::value_traits<
+ unsigned int,
+ mssql::id_int >::set_image (
+ i.num_value, is_null, v);
+ i.num_size_ind = is_null ? SQL_NULL_DATA : 0;
+ }
+
+ // str
+ //
+ {
+ ::std::string const& v =
+ o.str;
+
+ bool is_null (false);
+ mssql::value_traits<
+ ::std::string,
+ mssql::id_long_string >::set_image (
+ i.str_callback.callback.param,
+ i.str_callback.context.param,
+ is_null,
+ v);
+ i.str_size_ind = is_null ? SQL_NULL_DATA : SQL_DATA_AT_EXEC;
+ }
+ }
+
+ void access::object_traits_impl< ::person, id_mssql >::
+ init (object_type& o,
+ const image_type& i,
+ database* db)
+ {
+ ODB_POTENTIALLY_UNUSED (o);
+ ODB_POTENTIALLY_UNUSED (i);
+ ODB_POTENTIALLY_UNUSED (db);
+
+ // id
+ //
+ {
+ long unsigned int& v =
+ o.id;
+
+ mssql::value_traits<
+ long unsigned int,
+ mssql::id_bigint >::set_value (
+ v,
+ i.id_value,
+ i.id_size_ind == SQL_NULL_DATA);
+ }
+
+ // num
+ //
+ {
+ unsigned int& v =
+ o.num;
+
+ mssql::value_traits<
+ unsigned int,
+ mssql::id_int >::set_value (
+ v,
+ i.num_value,
+ i.num_size_ind == SQL_NULL_DATA);
+ }
+
+ // str
+ //
+ {
+ ::std::string& v =
+ o.str;
+
+ mssql::value_traits<
+ ::std::string,
+ mssql::id_long_string >::set_value (
+ v,
+ i.str_callback.callback.result,
+ i.str_callback.context.result);
+ }
+ }
+
+ void access::object_traits_impl< ::person, id_mssql >::
+ init (id_image_type& i, const id_type& id)
+ {
+ {
+ bool is_null (false);
+ mssql::value_traits<
+ long unsigned int,
+ mssql::id_bigint >::set_image (
+ i.id_value, is_null, id);
+ i.id_size_ind = is_null ? SQL_NULL_DATA : 0;
+ }
+ }
+
+ const char access::object_traits_impl< ::person, id_mssql >::persist_statement[] =
+ "INSERT INTO [person] "
+ "([num], "
+ "[str]) "
+ "OUTPUT INSERTED.[id] "
+ "VALUES "
+ "(?, ?)";
+
+ const char access::object_traits_impl< ::person, id_mssql >::find_statement[] =
+ "SELECT "
+ "[person].[id], "
+ "[person].[num], "
+ "[person].[str] "
+ "FROM [person] "
+ "WHERE [person].[id]=?";
+
+ const char access::object_traits_impl< ::person, id_mssql >::update_statement[] =
+ "UPDATE [person] "
+ "SET "
+ "[num]=?, "
+ "[str]=? "
+ "WHERE [id]=?";
+
+ const char access::object_traits_impl< ::person, id_mssql >::erase_statement[] =
+ "DELETE FROM [person] "
+ "WHERE [id]=?";
+
+ void access::object_traits_impl< ::person, id_mssql >::
+ persist (database& db, object_type& obj)
+ {
+ ODB_POTENTIALLY_UNUSED (db);
+
+ using namespace mssql;
+
+ mssql::connection& conn (
+ mssql::transaction::current ().connection ());
+ statements_type& sts (
+ conn.statement_cache ().find_object<object_type> ());
+
+ callback (db,
+ static_cast<const object_type&> (obj),
+ callback_event::pre_persist);
+
+ image_type& im (sts.image ());
+ binding& imb (sts.insert_image_binding ());
+
+ init (im, obj, statement_insert);
+
+ if (im.version != sts.insert_image_version () ||
+ imb.version == 0)
+ {
+ bind (imb.bind, im, statement_insert);
+ sts.insert_image_version (im.version);
+ imb.version++;
+ }
+
+ insert_statement& st (sts.persist_statement ());
+ if (!st.execute ())
+ throw object_already_persistent ();
+
+ obj.id = static_cast< id_type > (st.id ());
+
+ callback (db,
+ static_cast<const object_type&> (obj),
+ callback_event::post_persist);
+ }
+
+ void access::object_traits_impl< ::person, id_mssql >::
+ update (database& db, const object_type& obj)
+ {
+ ODB_POTENTIALLY_UNUSED (db);
+
+ using namespace mssql;
+ using mssql::update_statement;
+
+ callback (db, obj, callback_event::pre_update);
+
+ mssql::transaction& tr (mssql::transaction::current ());
+ mssql::connection& conn (tr.connection ());
+ statements_type& sts (
+ conn.statement_cache ().find_object<object_type> ());
+
+ const id_type& id (
+ obj.id);
+ id_image_type& idi (sts.id_image ());
+ init (idi, id);
+
+ image_type& im (sts.image ());
+ init (im, obj, statement_update);
+
+ bool u (false);
+ binding& imb (sts.update_image_binding ());
+ if (im.version != sts.update_image_version () ||
+ imb.version == 0)
+ {
+ bind (imb.bind, im, statement_update);
+ sts.update_image_version (im.version);
+ imb.version++;
+ u = true;
+ }
+
+ binding& idb (sts.id_image_binding ());
+ if (idi.version != sts.update_id_image_version () ||
+ idb.version == 0)
+ {
+ if (idi.version != sts.id_image_version () ||
+ idb.version == 0)
+ {
+ bind (idb.bind, idi);
+ sts.id_image_version (idi.version);
+ idb.version++;
+ }
+
+ sts.update_id_image_version (idi.version);
+
+ if (!u)
+ imb.version++;
+ }
+
+ update_statement& st (sts.update_statement ());
+ if (st.execute () == 0)
+ throw object_not_persistent ();
+
+ callback (db, obj, callback_event::post_update);
+ pointer_cache_traits::update (db, obj);
+ }
+
+ void access::object_traits_impl< ::person, id_mssql >::
+ erase (database& db, const id_type& id)
+ {
+ using namespace mssql;
+
+ ODB_POTENTIALLY_UNUSED (db);
+
+ mssql::connection& conn (
+ mssql::transaction::current ().connection ());
+ statements_type& sts (
+ conn.statement_cache ().find_object<object_type> ());
+
+ id_image_type& i (sts.id_image ());
+ init (i, id);
+
+ binding& idb (sts.id_image_binding ());
+ if (i.version != sts.id_image_version () || idb.version == 0)
+ {
+ bind (idb.bind, i);
+ sts.id_image_version (i.version);
+ idb.version++;
+ }
+
+ if (sts.erase_statement ().execute () != 1)
+ throw object_not_persistent ();
+
+ pointer_cache_traits::erase (db, id);
+ }
+
+ access::object_traits_impl< ::person, id_mssql >::pointer_type
+ access::object_traits_impl< ::person, id_mssql >::
+ find (database& db, const id_type& id)
+ {
+ using namespace mssql;
+
+ {
+ pointer_type p (pointer_cache_traits::find (db, id));
+
+ if (!pointer_traits::null_ptr (p))
+ return p;
+ }
+
+ mssql::connection& conn (
+ mssql::transaction::current ().connection ());
+ statements_type& sts (
+ conn.statement_cache ().find_object<object_type> ());
+
+ statements_type::auto_lock l (sts);
+ auto_result ar;
+
+ if (l.locked ())
+ {
+ if (!find_ (sts, &id))
+ return pointer_type ();
+
+ ar.set (sts.find_statement ());
+ }
+
+ pointer_type p (
+ access::object_factory<object_type, pointer_type>::create ());
+ pointer_traits::guard pg (p);
+
+ pointer_cache_traits::insert_guard ig (
+ pointer_cache_traits::insert (db, id, p));
+
+ object_type& obj (pointer_traits::get_ref (p));
+
+ if (l.locked ())
+ {
+ select_statement& st (sts.find_statement ());
+ ODB_POTENTIALLY_UNUSED (st);
+
+ callback (db, obj, callback_event::pre_load);
+ init (obj, sts.image (), &db);
+ st.stream_result ();
+ ar.free ();
+ load_ (sts, obj, false);
+ sts.load_delayed (0);
+ l.unlock ();
+ callback (db, obj, callback_event::post_load);
+ pointer_cache_traits::load (ig.position ());
+ }
+ else
+ sts.delay_load (id, obj, ig.position ());
+
+ ig.release ();
+ pg.release ();
+ return p;
+ }
+
+ bool access::object_traits_impl< ::person, id_mssql >::
+ find (database& db, const id_type& id, object_type& obj)
+ {
+ using namespace mssql;
+
+ mssql::connection& conn (
+ mssql::transaction::current ().connection ());
+ statements_type& sts (
+ conn.statement_cache ().find_object<object_type> ());
+
+ statements_type::auto_lock l (sts);
+
+ if (!find_ (sts, &id))
+ return false;
+
+ select_statement& st (sts.find_statement ());
+ ODB_POTENTIALLY_UNUSED (st);
+
+ auto_result ar (st);
+ reference_cache_traits::position_type pos (
+ reference_cache_traits::insert (db, id, obj));
+ reference_cache_traits::insert_guard ig (pos);
+
+ callback (db, obj, callback_event::pre_load);
+ init (obj, sts.image (), &db);
+ st.stream_result ();
+ ar.free ();
+ load_ (sts, obj, false);
+ sts.load_delayed (0);
+ l.unlock ();
+ callback (db, obj, callback_event::post_load);
+ reference_cache_traits::load (pos);
+ ig.release ();
+ return true;
+ }
+
+ bool access::object_traits_impl< ::person, id_mssql >::
+ reload (database& db, object_type& obj)
+ {
+ using namespace mssql;
+
+ mssql::connection& conn (
+ mssql::transaction::current ().connection ());
+ statements_type& sts (
+ conn.statement_cache ().find_object<object_type> ());
+
+ statements_type::auto_lock l (sts);
+
+ const id_type& id (
+ obj.id);
+
+ if (!find_ (sts, &id))
+ return false;
+
+ select_statement& st (sts.find_statement ());
+ ODB_POTENTIALLY_UNUSED (st);
+
+ auto_result ar (st);
+
+ callback (db, obj, callback_event::pre_load);
+ init (obj, sts.image (), &db);
+ st.stream_result ();
+ ar.free ();
+ load_ (sts, obj, true);
+ sts.load_delayed (0);
+ l.unlock ();
+ callback (db, obj, callback_event::post_load);
+ return true;
+ }
+
+ bool access::object_traits_impl< ::person, id_mssql >::
+ find_ (statements_type& sts,
+ const id_type* id)
+ {
+ using namespace mssql;
+
+ id_image_type& i (sts.id_image ());
+ init (i, *id);
+
+ binding& idb (sts.id_image_binding ());
+ if (i.version != sts.id_image_version () || idb.version == 0)
+ {
+ bind (idb.bind, i);
+ sts.id_image_version (i.version);
+ idb.version++;
+ }
+
+ image_type& im (sts.image ());
+ binding& imb (sts.select_image_binding ());
+
+ if (im.version != sts.select_image_version () ||
+ imb.version == 0)
+ {
+ bind (imb.bind, im, statement_select);
+ sts.select_image_version (im.version);
+ imb.version++;
+ }
+
+ select_statement& st (sts.find_statement ());
+
+ st.execute ();
+ auto_result ar (st);
+ select_statement::result r (st.fetch ());
+
+ if (r != select_statement::no_data)
+ {
+ ar.release ();
+ return true;
+ }
+ else
+ return false;
+ }
+}
+
+#include <odb/post.hxx>
diff --git a/bulk/mssql/orig/person-odb.hxx b/bulk/mssql/orig/person-odb.hxx
new file mode 100644
index 0000000..9f395b0
--- /dev/null
+++ b/bulk/mssql/orig/person-odb.hxx
@@ -0,0 +1,214 @@
+// This file was generated by ODB, object-relational mapping (ORM)
+// compiler for C++.
+//
+
+#ifndef PERSON_ODB_HXX
+#define PERSON_ODB_HXX
+
+#include <odb/version.hxx>
+
+#if (ODB_VERSION != 20302UL)
+#error ODB runtime version mismatch
+#endif
+
+#include <odb/pre.hxx>
+
+#include "person.hxx"
+
+#include <memory>
+#include <cstddef>
+
+#include <odb/core.hxx>
+#include <odb/traits.hxx>
+#include <odb/callback.hxx>
+#include <odb/wrapper-traits.hxx>
+#include <odb/pointer-traits.hxx>
+#include <odb/container-traits.hxx>
+#include <odb/no-op-cache-traits.hxx>
+
+#include <odb/details/unused.hxx>
+
+namespace odb
+{
+ // person
+ //
+ template <>
+ struct class_traits< ::person >
+ {
+ static const class_kind kind = class_object;
+ };
+
+ template <>
+ class access::object_traits< ::person >
+ {
+ public:
+ typedef ::person object_type;
+ typedef ::person* pointer_type;
+ typedef odb::pointer_traits<pointer_type> pointer_traits;
+
+ static const bool polymorphic = false;
+
+ typedef long unsigned int id_type;
+
+ static const bool auto_id = true;
+
+ static const bool abstract = false;
+
+ static id_type
+ id (const object_type&);
+
+ typedef
+ no_op_pointer_cache_traits<pointer_type>
+ pointer_cache_traits;
+
+ typedef
+ no_op_reference_cache_traits<object_type>
+ reference_cache_traits;
+
+ static void
+ callback (database&, object_type&, callback_event);
+
+ static void
+ callback (database&, const object_type&, callback_event);
+ };
+}
+
+#include <odb/details/buffer.hxx>
+
+#include <odb/mssql/version.hxx>
+#include <odb/mssql/forward.hxx>
+#include <odb/mssql/binding.hxx>
+#include <odb/mssql/mssql-types.hxx>
+
+namespace odb
+{
+ // person
+ //
+ template <>
+ class access::object_traits_impl< ::person, id_mssql >:
+ public access::object_traits< ::person >
+ {
+ public:
+ static const bool rowversion = false;
+
+ struct id_image_type
+ {
+ long long id_value;
+ SQLLEN id_size_ind;
+
+ std::size_t version;
+ };
+
+ struct image_type
+ {
+ // id
+ //
+ long long id_value;
+ SQLLEN id_size_ind;
+
+ // num
+ //
+ int num_value;
+ SQLLEN num_size_ind;
+
+ // str
+ //
+ mutable mssql::long_callback str_callback;
+ SQLLEN str_size_ind;
+
+ std::size_t version;
+
+ mssql::change_callback*
+ change_callback ()
+ {
+ return 0;
+ }
+ };
+
+ struct extra_statement_cache_type;
+
+ using object_traits<object_type>::id;
+
+ static void
+ bind (mssql::bind*,
+ image_type&,
+ mssql::statement_kind);
+
+ static void
+ bind (mssql::bind*, id_image_type&);
+
+ static void
+ init (image_type&,
+ const object_type&,
+ mssql::statement_kind);
+
+ static void
+ init (object_type&,
+ const image_type&,
+ database*);
+
+ static void
+ init (id_image_type&, const id_type&);
+
+ typedef mssql::object_statements<object_type> statements_type;
+
+ static const std::size_t column_count = 3UL;
+ static const std::size_t id_column_count = 1UL;
+ static const std::size_t inverse_column_count = 0UL;
+ static const std::size_t readonly_column_count = 0UL;
+ static const std::size_t managed_optimistic_column_count = 0UL;
+
+ static const std::size_t separate_load_column_count = 0UL;
+ static const std::size_t separate_update_column_count = 0UL;
+
+ static const bool versioned = false;
+
+ static const char persist_statement[];
+ static const char find_statement[];
+ static const char update_statement[];
+ static const char erase_statement[];
+
+ static void
+ persist (database&, object_type&);
+
+ static pointer_type
+ find (database&, const id_type&);
+
+ static bool
+ find (database&, const id_type&, object_type&);
+
+ static bool
+ reload (database&, object_type&);
+
+ static void
+ update (database&, const object_type&);
+
+ static void
+ erase (database&, const id_type&);
+
+ static void
+ erase (database&, const object_type&);
+
+ public:
+ static bool
+ find_ (statements_type&,
+ const id_type*);
+
+ static void
+ load_ (statements_type&,
+ object_type&,
+ bool reload);
+ };
+
+ template <>
+ class access::object_traits_impl< ::person, id_common >:
+ public access::object_traits_impl< ::person, id_mssql >
+ {
+ };
+}
+
+#include "person-odb.ixx"
+
+#include <odb/post.hxx>
+
+#endif // PERSON_ODB_HXX
diff --git a/bulk/mssql/orig/person-odb.ixx b/bulk/mssql/orig/person-odb.ixx
new file mode 100644
index 0000000..73f62a7
--- /dev/null
+++ b/bulk/mssql/orig/person-odb.ixx
@@ -0,0 +1,61 @@
+// This file was generated by ODB, object-relational mapping (ORM)
+// compiler for C++.
+//
+
+namespace odb
+{
+ // person
+ //
+
+ inline
+ access::object_traits< ::person >::id_type
+ access::object_traits< ::person >::
+ id (const object_type& o)
+ {
+ return o.id;
+ }
+
+ inline
+ void access::object_traits< ::person >::
+ callback (database& db, object_type& x, callback_event e)
+ {
+ ODB_POTENTIALLY_UNUSED (db);
+ ODB_POTENTIALLY_UNUSED (x);
+ ODB_POTENTIALLY_UNUSED (e);
+ }
+
+ inline
+ void access::object_traits< ::person >::
+ callback (database& db, const object_type& x, callback_event e)
+ {
+ ODB_POTENTIALLY_UNUSED (db);
+ ODB_POTENTIALLY_UNUSED (x);
+ ODB_POTENTIALLY_UNUSED (e);
+ }
+}
+
+namespace odb
+{
+ // person
+ //
+
+ inline
+ void access::object_traits_impl< ::person, id_mssql >::
+ erase (database& db, const object_type& obj)
+ {
+ callback (db, obj, callback_event::pre_erase);
+ erase (db, id (obj));
+ callback (db, obj, callback_event::post_erase);
+ }
+
+ inline
+ void access::object_traits_impl< ::person, id_mssql >::
+ load_ (statements_type& sts,
+ object_type& obj,
+ bool)
+ {
+ ODB_POTENTIALLY_UNUSED (sts);
+ ODB_POTENTIALLY_UNUSED (obj);
+ }
+}
+
diff --git a/bulk/oracle/auto/person-odb.cxx b/bulk/oracle/auto/person-odb.cxx
new file mode 100644
index 0000000..360e1b9
--- /dev/null
+++ b/bulk/oracle/auto/person-odb.cxx
@@ -0,0 +1,580 @@
+// This file was generated by ODB, object-relational mapping (ORM)
+// compiler for C++.
+//
+
+#include <odb/pre.hxx>
+
+#include "person-odb.hxx"
+
+#include <cassert>
+#include <cstring> // std::memcpy
+#include <iostream>
+
+
+#include <odb/oracle/traits.hxx>
+#include <odb/oracle/database.hxx>
+#include <odb/oracle/transaction.hxx>
+#include <odb/oracle/connection.hxx>
+#include <odb/oracle/statement.hxx>
+#include <odb/oracle/statement-cache.hxx>
+#include <odb/oracle/simple-object-statements.hxx>
+#include <odb/oracle/container-statements.hxx>
+#include <odb/oracle/exceptions.hxx>
+
+namespace odb
+{
+ // person
+ //
+
+ struct access::object_traits_impl< ::person, id_oracle >::extra_statement_cache_type
+ {
+ extra_statement_cache_type (
+ oracle::connection&,
+ image_type&,
+ oracle::binding&,
+ oracle::binding&)
+ {
+ }
+ };
+
+ access::object_traits_impl< ::person, id_oracle >::id_type
+ access::object_traits_impl< ::person, id_oracle >::
+ id (const id_image_type& i)
+ {
+ oracle::database* db (0);
+ ODB_POTENTIALLY_UNUSED (db);
+
+ id_type id;
+ {
+ oracle::value_traits<
+ long unsigned int,
+ oracle::id_big_int >::set_value (
+ id,
+ i.id_value,
+ i.id_size,
+ i.id_indicator == -1);
+ }
+
+ return id;
+ }
+
+ void access::object_traits_impl< ::person, id_oracle >::
+ bind (oracle::bind* b,
+ image_type& i,
+ oracle::statement_kind sk)
+ {
+ ODB_POTENTIALLY_UNUSED (sk);
+
+ using namespace oracle;
+
+ std::size_t n (0);
+
+ // id
+ //
+ if (sk != statement_insert && sk != statement_update)
+ {
+ b[n].type = oracle::bind::number;
+ b[n].buffer = i.id_value;
+ b[n].capacity = static_cast<ub4> (sizeof (i.id_value));
+ b[n].size = &i.id_size;
+ b[n].indicator = &i.id_indicator;
+ n++;
+ }
+
+ // num
+ //
+ b[n].type = oracle::bind::uinteger;
+ b[n].buffer = &i.num_value;
+ b[n].capacity = 4;
+ b[n].size = 0;
+ b[n].indicator = &i.num_indicator;
+ n++;
+
+ // str
+ //
+ b[n].type = oracle::bind::clob;
+ b[n].buffer = &i.str_lob;
+ b[n].indicator = &i.str_indicator;
+ b[n].callback = &i.str_callback;
+
+ n++;
+ }
+
+ void access::object_traits_impl< ::person, id_oracle >::
+ bind (oracle::bind* b, id_image_type& i)
+ {
+ std::size_t n (0);
+ b[n].type = oracle::bind::number;
+ b[n].buffer = i.id_value;
+ b[n].capacity = static_cast<ub4> (sizeof (i.id_value));
+ b[n].size = &i.id_size;
+ b[n].indicator = &i.id_indicator;
+ }
+
+ void access::object_traits_impl< ::person, id_oracle >::
+ init (image_type& i,
+ const object_type& o,
+ oracle::statement_kind sk)
+ {
+ ODB_POTENTIALLY_UNUSED (i);
+ ODB_POTENTIALLY_UNUSED (o);
+ ODB_POTENTIALLY_UNUSED (sk);
+
+ using namespace oracle;
+
+ // num
+ //
+ {
+ unsigned int const& v =
+ o.num;
+
+ bool is_null (false);
+ oracle::value_traits<
+ unsigned int,
+ oracle::id_int32 >::set_image (
+ i.num_value, is_null, v);
+ i.num_indicator = is_null ? -1 : 0;
+ }
+
+ // str
+ //
+ {
+ ::std::string const& v =
+ o.str;
+
+ bool is_null (false);
+ i.str_lob.position = 0;
+ oracle::value_traits<
+ ::std::string,
+ oracle::id_clob >::set_image (
+ i.str_callback.callback.param,
+ i.str_callback.context.param,
+ is_null,
+ v);
+ i.str_indicator = is_null ? -1 : 0;
+ }
+ }
+
+ void access::object_traits_impl< ::person, id_oracle >::
+ init (object_type& o,
+ const image_type& i,
+ database* db)
+ {
+ ODB_POTENTIALLY_UNUSED (o);
+ ODB_POTENTIALLY_UNUSED (i);
+ ODB_POTENTIALLY_UNUSED (db);
+
+ // id
+ //
+ {
+ long unsigned int& v =
+ o.id;
+
+ oracle::value_traits<
+ long unsigned int,
+ oracle::id_big_int >::set_value (
+ v,
+ i.id_value,
+ i.id_size,
+ i.id_indicator == -1);
+ }
+
+ // num
+ //
+ {
+ unsigned int& v =
+ o.num;
+
+ oracle::value_traits<
+ unsigned int,
+ oracle::id_int32 >::set_value (
+ v,
+ i.num_value,
+ i.num_indicator == -1);
+ }
+
+ // str
+ //
+ {
+ ::std::string& v =
+ o.str;
+
+ oracle::value_traits<
+ ::std::string,
+ oracle::id_clob >::set_value (
+ v,
+ i.str_callback.callback.result,
+ i.str_callback.context.result,
+ i.str_indicator == -1);
+ }
+ }
+
+ void access::object_traits_impl< ::person, id_oracle >::
+ init (id_image_type& i, const id_type& id)
+ {
+ {
+ bool is_null (false);
+ std::size_t size (0);
+ oracle::value_traits<
+ long unsigned int,
+ oracle::id_big_int >::set_image (
+ i.id_value,
+ size,
+ is_null,
+ id);
+ i.id_indicator = is_null ? -1 : 0;
+ i.id_size = static_cast<ub2> (size);
+ }
+ }
+
+ const char access::object_traits_impl< ::person, id_oracle >::persist_statement[] =
+ "INSERT INTO \"person\" "
+ "(\"id\", "
+ "\"num\", "
+ "\"str\") "
+ "VALUES "
+ "(\"person_seq\".nextval, :1, :2) "
+ "RETURNING \"id\" INTO :3";
+
+ const char access::object_traits_impl< ::person, id_oracle >::find_statement[] =
+ "SELECT "
+ "\"person\".\"id\", "
+ "\"person\".\"num\", "
+ "\"person\".\"str\" "
+ "FROM \"person\" "
+ "WHERE \"person\".\"id\"=:1";
+
+ const char access::object_traits_impl< ::person, id_oracle >::update_statement[] =
+ "UPDATE \"person\" "
+ "SET "
+ "\"num\"=:1, "
+ "\"str\"=:2 "
+ "WHERE \"id\"=:3";
+
+ const char access::object_traits_impl< ::person, id_oracle >::erase_statement[] =
+ "DELETE FROM \"person\" "
+ "WHERE \"id\"=:1";
+
+ void access::object_traits_impl< ::person, id_oracle >::
+ persist (database& db, object_type** objs, std::size_t n,
+ multiple_exceptions* mex)
+ {
+ ODB_POTENTIALLY_UNUSED (db);
+ assert (n <= batch);
+
+ using namespace oracle;
+
+ oracle::connection& conn (
+ oracle::transaction::current ().connection ());
+ statements_type& sts (
+ conn.statement_cache ().find_object<object_type> ());
+
+ for (std::size_t i (0); i != n; ++i)
+ {
+ object_type& obj (*objs[i]);
+
+ callback (db,
+ static_cast<const object_type&> (obj),
+ callback_event::pre_persist);
+
+ init (sts.image (i), obj, statement_insert);
+ }
+
+ image_type& im (sts.image (0));
+ binding& imb (sts.insert_image_binding ());
+
+ if (im.version != sts.insert_image_version () ||
+ imb.version == 0)
+ {
+ bind (imb.bind, im, statement_insert);
+ sts.insert_image_version (im.version);
+ imb.version++;
+ }
+
+ // @@ TMP. Why tmp?
+ bind (sts.id_image_binding ().bind, sts.id_image ());
+
+ insert_statement& st (sts.persist_statement ());
+ n = st.execute (n, mex); // Set to actual number of rows attempted.
+
+ for (std::size_t i (0); i != n; ++i)
+ {
+ bool r (st.result (i)); // Sets current in mex.
+
+ if (mex != 0)
+ {
+ if ((*mex)[i] != 0) // Pending exception.
+ continue;
+
+ if (!r)
+ {
+ mex->insert (i, object_already_persistent ());
+ continue;
+ }
+
+ if (mex->fatal ()) // Don't do any extra work.
+ continue;
+ }
+ else if (!r)
+ throw object_already_persistent ();
+
+ object_type& obj (*objs[i]);
+
+ obj.id = id (sts.id_image (i));
+
+ callback (db,
+ static_cast<const object_type&> (obj),
+ callback_event::post_persist);
+ }
+ }
+
+ void access::object_traits_impl< ::person, id_oracle >::
+ update (database& db, const object_type& obj)
+ {
+ ODB_POTENTIALLY_UNUSED (db);
+
+ using namespace oracle;
+ using oracle::update_statement;
+
+ callback (db, obj, callback_event::pre_update);
+
+ oracle::transaction& tr (oracle::transaction::current ());
+ oracle::connection& conn (tr.connection ());
+ statements_type& sts (
+ conn.statement_cache ().find_object<object_type> ());
+
+ const id_type& id (
+ obj.id);
+ id_image_type& idi (sts.id_image ());
+ init (idi, id);
+
+ image_type& im (sts.image ());
+ init (im, obj, statement_update);
+
+ bool u (false);
+ binding& imb (sts.update_image_binding ());
+ if (im.version != sts.update_image_version () ||
+ imb.version == 0)
+ {
+ bind (imb.bind, im, statement_update);
+ sts.update_image_version (im.version);
+ imb.version++;
+ u = true;
+ }
+
+ binding& idb (sts.id_image_binding ());
+ if (idi.version != sts.update_id_image_version () ||
+ idb.version == 0)
+ {
+ if (idi.version != sts.id_image_version () ||
+ idb.version == 0)
+ {
+ bind (idb.bind, idi);
+ sts.id_image_version (idi.version);
+ idb.version++;
+ }
+
+ sts.update_id_image_version (idi.version);
+
+ if (!u)
+ imb.version++;
+ }
+
+ update_statement& st (sts.update_statement ());
+ if (st.execute () == 0)
+ throw object_not_persistent ();
+
+ callback (db, obj, callback_event::post_update);
+ pointer_cache_traits::update (db, obj);
+ }
+
+ void access::object_traits_impl< ::person, id_oracle >::
+ erase (database& db, const id_type& id)
+ {
+ using namespace oracle;
+
+ ODB_POTENTIALLY_UNUSED (db);
+
+ oracle::connection& conn (
+ oracle::transaction::current ().connection ());
+ statements_type& sts (
+ conn.statement_cache ().find_object<object_type> ());
+
+ id_image_type& i (sts.id_image ());
+ init (i, id);
+
+ binding& idb (sts.id_image_binding ());
+ if (i.version != sts.id_image_version () || idb.version == 0)
+ {
+ bind (idb.bind, i);
+ sts.id_image_version (i.version);
+ idb.version++;
+ }
+
+ if (sts.erase_statement ().execute () != 1)
+ throw object_not_persistent ();
+
+ pointer_cache_traits::erase (db, id);
+ }
+
+ access::object_traits_impl< ::person, id_oracle >::pointer_type
+ access::object_traits_impl< ::person, id_oracle >::
+ find (database& db, const id_type& id)
+ {
+ using namespace oracle;
+
+ {
+ pointer_type p (pointer_cache_traits::find (db, id));
+
+ if (!pointer_traits::null_ptr (p))
+ return p;
+ }
+
+ oracle::connection& conn (
+ oracle::transaction::current ().connection ());
+ statements_type& sts (
+ conn.statement_cache ().find_object<object_type> ());
+
+ statements_type::auto_lock l (sts);
+
+ if (l.locked ())
+ {
+ if (!find_ (sts, &id))
+ return pointer_type ();
+ }
+
+ pointer_type p (
+ access::object_factory<object_type, pointer_type>::create ());
+ pointer_traits::guard pg (p);
+
+ pointer_cache_traits::insert_guard ig (
+ pointer_cache_traits::insert (db, id, p));
+
+ object_type& obj (pointer_traits::get_ref (p));
+
+ if (l.locked ())
+ {
+ select_statement& st (sts.find_statement ());
+ ODB_POTENTIALLY_UNUSED (st);
+
+ callback (db, obj, callback_event::pre_load);
+ init (obj, sts.image (), &db);
+ st.stream_result ();
+ load_ (sts, obj, false);
+ sts.load_delayed (0);
+ l.unlock ();
+ callback (db, obj, callback_event::post_load);
+ pointer_cache_traits::load (ig.position ());
+ }
+ else
+ sts.delay_load (id, obj, ig.position ());
+
+ ig.release ();
+ pg.release ();
+ return p;
+ }
+
+ bool access::object_traits_impl< ::person, id_oracle >::
+ find (database& db, const id_type& id, object_type& obj)
+ {
+ using namespace oracle;
+
+ oracle::connection& conn (
+ oracle::transaction::current ().connection ());
+ statements_type& sts (
+ conn.statement_cache ().find_object<object_type> ());
+
+ statements_type::auto_lock l (sts);
+
+ if (!find_ (sts, &id))
+ return false;
+
+ select_statement& st (sts.find_statement ());
+ ODB_POTENTIALLY_UNUSED (st);
+
+ reference_cache_traits::position_type pos (
+ reference_cache_traits::insert (db, id, obj));
+ reference_cache_traits::insert_guard ig (pos);
+
+ callback (db, obj, callback_event::pre_load);
+ init (obj, sts.image (), &db);
+ st.stream_result ();
+ load_ (sts, obj, false);
+ sts.load_delayed (0);
+ l.unlock ();
+ callback (db, obj, callback_event::post_load);
+ reference_cache_traits::load (pos);
+ ig.release ();
+ return true;
+ }
+
+ bool access::object_traits_impl< ::person, id_oracle >::
+ reload (database& db, object_type& obj)
+ {
+ using namespace oracle;
+
+ oracle::connection& conn (
+ oracle::transaction::current ().connection ());
+ statements_type& sts (
+ conn.statement_cache ().find_object<object_type> ());
+
+ statements_type::auto_lock l (sts);
+
+ const id_type& id (
+ obj.id);
+
+ if (!find_ (sts, &id))
+ return false;
+
+ select_statement& st (sts.find_statement ());
+ ODB_POTENTIALLY_UNUSED (st);
+
+ callback (db, obj, callback_event::pre_load);
+ init (obj, sts.image (), &db);
+ st.stream_result ();
+ load_ (sts, obj, true);
+ sts.load_delayed (0);
+ l.unlock ();
+ callback (db, obj, callback_event::post_load);
+ return true;
+ }
+
+ bool access::object_traits_impl< ::person, id_oracle >::
+ find_ (statements_type& sts,
+ const id_type* id)
+ {
+ using namespace oracle;
+
+ id_image_type& i (sts.id_image ());
+ init (i, *id);
+
+ binding& idb (sts.id_image_binding ());
+ if (i.version != sts.id_image_version () || idb.version == 0)
+ {
+ bind (idb.bind, i);
+ sts.id_image_version (i.version);
+ idb.version++;
+ }
+
+ image_type& im (sts.image ());
+ binding& imb (sts.select_image_binding ());
+
+ if (im.version != sts.select_image_version () ||
+ imb.version == 0)
+ {
+ bind (imb.bind, im, statement_select);
+ sts.select_image_version (im.version);
+ imb.version++;
+ }
+
+ select_statement& st (sts.find_statement ());
+
+ st.execute ();
+ auto_result ar (st);
+ select_statement::result r (st.fetch ());
+
+ return r != select_statement::no_data;
+ }
+}
+
+#include <odb/post.hxx>
diff --git a/bulk/oracle/auto/person-odb.hxx b/bulk/oracle/auto/person-odb.hxx
new file mode 100644
index 0000000..fbc84aa
--- /dev/null
+++ b/bulk/oracle/auto/person-odb.hxx
@@ -0,0 +1,221 @@
+// This file was generated by ODB, object-relational mapping (ORM)
+// compiler for C++.
+//
+
+#ifndef PERSON_ODB_HXX
+#define PERSON_ODB_HXX
+
+#include <odb/version.hxx>
+
+#if (ODB_VERSION != 20302UL)
+#error ODB runtime version mismatch
+#endif
+
+#include <odb/pre.hxx>
+
+#include "person.hxx"
+
+#include <memory>
+#include <cstddef>
+
+#include <odb/core.hxx>
+#include <odb/traits.hxx>
+#include <odb/callback.hxx>
+#include <odb/wrapper-traits.hxx>
+#include <odb/pointer-traits.hxx>
+#include <odb/container-traits.hxx>
+#include <odb/no-op-cache-traits.hxx>
+
+#include <odb/details/unused.hxx>
+
+namespace odb
+{
+ // person
+ //
+ template <>
+ struct class_traits< ::person >
+ {
+ static const class_kind kind = class_object;
+ };
+
+ template <>
+ class access::object_traits< ::person >
+ {
+ public:
+ typedef ::person object_type;
+ typedef ::person* pointer_type;
+ typedef odb::pointer_traits<pointer_type> pointer_traits;
+
+ static const bool polymorphic = false;
+
+ typedef long unsigned int id_type;
+
+ static const bool auto_id = true;
+
+ static const bool abstract = false;
+
+ static id_type
+ id (const object_type&);
+
+ typedef
+ no_op_pointer_cache_traits<pointer_type>
+ pointer_cache_traits;
+
+ typedef
+ no_op_reference_cache_traits<object_type>
+ reference_cache_traits;
+
+ static void
+ callback (database&, object_type&, callback_event);
+
+ static void
+ callback (database&, const object_type&, callback_event);
+ };
+}
+
+#include <odb/details/buffer.hxx>
+
+#include <odb/oracle/version.hxx>
+#include <odb/oracle/forward.hxx>
+#include <odb/oracle/binding.hxx>
+#include <odb/oracle/oracle-types.hxx>
+
+namespace odb
+{
+ // person
+ //
+ template <>
+ class access::object_traits_impl< ::person, id_oracle >:
+ public access::object_traits< ::person >
+ {
+ public:
+
+ static const std::size_t batch = 3UL;
+
+ struct id_image_type
+ {
+ char id_value[12];
+ ub2 id_size;
+ sb2 id_indicator;
+
+ std::size_t version;
+ };
+
+ struct image_type
+ {
+ // id
+ //
+ char id_value[12];
+ ub2 id_size;
+ sb2 id_indicator;
+
+ // num
+ //
+ unsigned int num_value;
+ sb2 num_indicator;
+
+ // str
+ //
+ mutable oracle::lob_callback str_callback;
+ sb2 str_indicator;
+ oracle::lob str_lob;
+
+ std::size_t version;
+
+ oracle::change_callback*
+ change_callback ()
+ {
+ return 0;
+ }
+ };
+
+ struct extra_statement_cache_type;
+
+ using object_traits<object_type>::id;
+
+ static id_type
+ id (const id_image_type&);
+
+ static void
+ bind (oracle::bind*,
+ image_type&,
+ oracle::statement_kind);
+
+ static void
+ bind (oracle::bind*, id_image_type&);
+
+ static void
+ init (image_type&,
+ const object_type&,
+ oracle::statement_kind);
+
+ static void
+ init (object_type&,
+ const image_type&,
+ database*);
+
+ static void
+ init (id_image_type&, const id_type&);
+
+ typedef oracle::object_statements<object_type> statements_type;
+
+ static const std::size_t column_count = 3UL;
+ static const std::size_t id_column_count = 1UL;
+ static const std::size_t inverse_column_count = 0UL;
+ static const std::size_t readonly_column_count = 0UL;
+ static const std::size_t managed_optimistic_column_count = 0UL;
+
+ static const std::size_t separate_load_column_count = 0UL;
+ static const std::size_t separate_update_column_count = 0UL;
+
+ static const bool versioned = false;
+
+ static const char persist_statement[];
+ static const char find_statement[];
+ static const char update_statement[];
+ static const char erase_statement[];
+
+ static void
+ persist (database&, object_type**, std::size_t, multiple_exceptions*);
+
+ static pointer_type
+ find (database&, const id_type&);
+
+ static bool
+ find (database&, const id_type&, object_type&);
+
+ static bool
+ reload (database&, object_type&);
+
+ static void
+ update (database&, const object_type&);
+
+ static void
+ erase (database&, const id_type&);
+
+ static void
+ erase (database&, const object_type&);
+
+ public:
+ static bool
+ find_ (statements_type&,
+ const id_type*);
+
+ static void
+ load_ (statements_type&,
+ object_type&,
+ bool reload);
+ };
+
+ template <>
+ class access::object_traits_impl< ::person, id_common >:
+ public access::object_traits_impl< ::person, id_oracle >
+ {
+ };
+}
+
+#include "person-odb.ixx"
+
+#include <odb/post.hxx>
+
+#endif // PERSON_ODB_HXX
diff --git a/bulk/oracle/auto/person-odb.ixx b/bulk/oracle/auto/person-odb.ixx
new file mode 100644
index 0000000..d1763df
--- /dev/null
+++ b/bulk/oracle/auto/person-odb.ixx
@@ -0,0 +1,61 @@
+// This file was generated by ODB, object-relational mapping (ORM)
+// compiler for C++.
+//
+
+namespace odb
+{
+ // person
+ //
+
+ inline
+ access::object_traits< ::person >::id_type
+ access::object_traits< ::person >::
+ id (const object_type& o)
+ {
+ return o.id;
+ }
+
+ inline
+ void access::object_traits< ::person >::
+ callback (database& db, object_type& x, callback_event e)
+ {
+ ODB_POTENTIALLY_UNUSED (db);
+ ODB_POTENTIALLY_UNUSED (x);
+ ODB_POTENTIALLY_UNUSED (e);
+ }
+
+ inline
+ void access::object_traits< ::person >::
+ callback (database& db, const object_type& x, callback_event e)
+ {
+ ODB_POTENTIALLY_UNUSED (db);
+ ODB_POTENTIALLY_UNUSED (x);
+ ODB_POTENTIALLY_UNUSED (e);
+ }
+}
+
+namespace odb
+{
+ // person
+ //
+
+ inline
+ void access::object_traits_impl< ::person, id_oracle >::
+ erase (database& db, const object_type& obj)
+ {
+ callback (db, obj, callback_event::pre_erase);
+ erase (db, id (obj));
+ callback (db, obj, callback_event::post_erase);
+ }
+
+ inline
+ void access::object_traits_impl< ::person, id_oracle >::
+ load_ (statements_type& sts,
+ object_type& obj,
+ bool)
+ {
+ ODB_POTENTIALLY_UNUSED (sts);
+ ODB_POTENTIALLY_UNUSED (obj);
+ }
+}
+
diff --git a/bulk/oracle/auto/person.sql b/bulk/oracle/auto/person.sql
new file mode 100644
index 0000000..7676ef6
--- /dev/null
+++ b/bulk/oracle/auto/person.sql
@@ -0,0 +1,33 @@
+/* This file was generated by ODB, object-relational mapping (ORM)
+ * compiler for C++.
+ */
+
+SET FEEDBACK OFF;
+WHENEVER SQLERROR EXIT FAILURE;
+WHENEVER OSERROR EXIT FAILURE;
+
+BEGIN
+ BEGIN
+ EXECUTE IMMEDIATE 'DROP TABLE "person" CASCADE CONSTRAINTS';
+ EXCEPTION
+ WHEN OTHERS THEN
+ IF SQLCODE != -942 THEN RAISE; END IF;
+ END;
+ BEGIN
+ EXECUTE IMMEDIATE 'DROP SEQUENCE "person_seq"';
+ EXCEPTION
+ WHEN OTHERS THEN
+ IF SQLCODE != -2289 THEN RAISE; END IF;
+ END;
+END;
+/
+
+CREATE TABLE "person" (
+ "id" NUMBER(20) NOT NULL PRIMARY KEY,
+ "num" NUMBER(10) NOT NULL UNIQUE,
+ "str" CLOB NOT NULL);
+
+CREATE SEQUENCE "person_seq"
+ START WITH 1 INCREMENT BY 1;
+
+EXIT;
diff --git a/bulk/oracle/orig/person-odb.cxx b/bulk/oracle/orig/person-odb.cxx
new file mode 100644
index 0000000..e18ffae
--- /dev/null
+++ b/bulk/oracle/orig/person-odb.cxx
@@ -0,0 +1,546 @@
+// This file was generated by ODB, object-relational mapping (ORM)
+// compiler for C++.
+//
+
+#include <odb/pre.hxx>
+
+#include "person-odb.hxx"
+
+#include <cassert>
+#include <cstring> // std::memcpy
+
+
+#include <odb/oracle/traits.hxx>
+#include <odb/oracle/database.hxx>
+#include <odb/oracle/transaction.hxx>
+#include <odb/oracle/connection.hxx>
+#include <odb/oracle/statement.hxx>
+#include <odb/oracle/statement-cache.hxx>
+#include <odb/oracle/simple-object-statements.hxx>
+#include <odb/oracle/container-statements.hxx>
+#include <odb/oracle/exceptions.hxx>
+
+namespace odb
+{
+ // person
+ //
+
+ struct access::object_traits_impl< ::person, id_oracle >::extra_statement_cache_type
+ {
+ extra_statement_cache_type (
+ oracle::connection&,
+ image_type&,
+ oracle::binding&,
+ oracle::binding&)
+ {
+ }
+ };
+
+ access::object_traits_impl< ::person, id_oracle >::id_type
+ access::object_traits_impl< ::person, id_oracle >::
+ id (const id_image_type& i)
+ {
+ oracle::database* db (0);
+ ODB_POTENTIALLY_UNUSED (db);
+
+ id_type id;
+ {
+ oracle::value_traits<
+ long unsigned int,
+ oracle::id_big_int >::set_value (
+ id,
+ i.id_value,
+ i.id_size,
+ i.id_indicator == -1);
+ }
+
+ return id;
+ }
+
+ void access::object_traits_impl< ::person, id_oracle >::
+ bind (oracle::bind* b,
+ image_type& i,
+ oracle::statement_kind sk)
+ {
+ ODB_POTENTIALLY_UNUSED (sk);
+
+ using namespace oracle;
+
+ std::size_t n (0);
+
+ // id
+ //
+ if (sk != statement_insert && sk != statement_update)
+ {
+ b[n].type = oracle::bind::number;
+ b[n].buffer = i.id_value;
+ b[n].capacity = static_cast<ub4> (sizeof (i.id_value));
+ b[n].size = &i.id_size;
+ b[n].indicator = &i.id_indicator;
+ n++;
+ }
+
+ // num
+ //
+ b[n].type = oracle::bind::uinteger;
+ b[n].buffer = &i.num_value;
+ b[n].capacity = 4;
+ b[n].size = 0;
+ b[n].indicator = &i.num_indicator;
+ n++;
+
+ // str
+ //
+ b[n].type = oracle::bind::clob;
+ b[n].buffer = &i.str_lob;
+ b[n].indicator = &i.str_indicator;
+ b[n].callback = &i.str_callback;
+
+ n++;
+ }
+
+ void access::object_traits_impl< ::person, id_oracle >::
+ bind (oracle::bind* b, id_image_type& i)
+ {
+ std::size_t n (0);
+ b[n].type = oracle::bind::number;
+ b[n].buffer = i.id_value;
+ b[n].capacity = static_cast<ub4> (sizeof (i.id_value));
+ b[n].size = &i.id_size;
+ b[n].indicator = &i.id_indicator;
+ }
+
+ void access::object_traits_impl< ::person, id_oracle >::
+ init (image_type& i,
+ const object_type& o,
+ oracle::statement_kind sk)
+ {
+ ODB_POTENTIALLY_UNUSED (i);
+ ODB_POTENTIALLY_UNUSED (o);
+ ODB_POTENTIALLY_UNUSED (sk);
+
+ using namespace oracle;
+
+ // num
+ //
+ {
+ unsigned int const& v =
+ o.num;
+
+ bool is_null (false);
+ oracle::value_traits<
+ unsigned int,
+ oracle::id_int32 >::set_image (
+ i.num_value, is_null, v);
+ i.num_indicator = is_null ? -1 : 0;
+ }
+
+ // str
+ //
+ {
+ ::std::string const& v =
+ o.str;
+
+ bool is_null (false);
+ i.str_lob.position = 0;
+ oracle::value_traits<
+ ::std::string,
+ oracle::id_clob >::set_image (
+ i.str_callback.callback.param,
+ i.str_callback.context.param,
+ is_null,
+ v);
+ i.str_indicator = is_null ? -1 : 0;
+ }
+ }
+
+ void access::object_traits_impl< ::person, id_oracle >::
+ init (object_type& o,
+ const image_type& i,
+ database* db)
+ {
+ ODB_POTENTIALLY_UNUSED (o);
+ ODB_POTENTIALLY_UNUSED (i);
+ ODB_POTENTIALLY_UNUSED (db);
+
+ // id
+ //
+ {
+ long unsigned int& v =
+ o.id;
+
+ oracle::value_traits<
+ long unsigned int,
+ oracle::id_big_int >::set_value (
+ v,
+ i.id_value,
+ i.id_size,
+ i.id_indicator == -1);
+ }
+
+ // num
+ //
+ {
+ unsigned int& v =
+ o.num;
+
+ oracle::value_traits<
+ unsigned int,
+ oracle::id_int32 >::set_value (
+ v,
+ i.num_value,
+ i.num_indicator == -1);
+ }
+
+ // str
+ //
+ {
+ ::std::string& v =
+ o.str;
+
+ oracle::value_traits<
+ ::std::string,
+ oracle::id_clob >::set_value (
+ v,
+ i.str_callback.callback.result,
+ i.str_callback.context.result,
+ i.str_indicator == -1);
+ }
+ }
+
+ void access::object_traits_impl< ::person, id_oracle >::
+ init (id_image_type& i, const id_type& id)
+ {
+ {
+ bool is_null (false);
+ std::size_t size (0);
+ oracle::value_traits<
+ long unsigned int,
+ oracle::id_big_int >::set_image (
+ i.id_value,
+ size,
+ is_null,
+ id);
+ i.id_indicator = is_null ? -1 : 0;
+ i.id_size = static_cast<ub2> (size);
+ }
+ }
+
+ const char access::object_traits_impl< ::person, id_oracle >::persist_statement[] =
+ "INSERT INTO \"person\" "
+ "(\"id\", "
+ "\"num\", "
+ "\"str\") "
+ "VALUES "
+ "(\"person_seq\".nextval, :1, :2) "
+ "RETURNING \"id\" INTO :3";
+
+ const char access::object_traits_impl< ::person, id_oracle >::find_statement[] =
+ "SELECT "
+ "\"person\".\"id\", "
+ "\"person\".\"num\", "
+ "\"person\".\"str\" "
+ "FROM \"person\" "
+ "WHERE \"person\".\"id\"=:1";
+
+ const char access::object_traits_impl< ::person, id_oracle >::update_statement[] =
+ "UPDATE \"person\" "
+ "SET "
+ "\"num\"=:1, "
+ "\"str\"=:2 "
+ "WHERE \"id\"=:3";
+
+ const char access::object_traits_impl< ::person, id_oracle >::erase_statement[] =
+ "DELETE FROM \"person\" "
+ "WHERE \"id\"=:1";
+
+ void access::object_traits_impl< ::person, id_oracle >::
+ persist (database& db, object_type& obj)
+ {
+ ODB_POTENTIALLY_UNUSED (db);
+
+ using namespace oracle;
+
+ oracle::connection& conn (
+ oracle::transaction::current ().connection ());
+ statements_type& sts (
+ conn.statement_cache ().find_object<object_type> ());
+
+ callback (db,
+ static_cast<const object_type&> (obj),
+ callback_event::pre_persist);
+
+ image_type& im (sts.image ());
+ binding& imb (sts.insert_image_binding ());
+
+ init (im, obj, statement_insert);
+
+ if (im.version != sts.insert_image_version () ||
+ imb.version == 0)
+ {
+ bind (imb.bind, im, statement_insert);
+ sts.insert_image_version (im.version);
+ imb.version++;
+ }
+
+ insert_statement& st (sts.persist_statement ());
+ if (!st.execute ())
+ throw object_already_persistent ();
+
+ obj.id = static_cast< id_type > (st.id ());
+
+ callback (db,
+ static_cast<const object_type&> (obj),
+ callback_event::post_persist);
+ }
+
+ void access::object_traits_impl< ::person, id_oracle >::
+ update (database& db, const object_type& obj)
+ {
+ ODB_POTENTIALLY_UNUSED (db);
+
+ using namespace oracle;
+ using oracle::update_statement;
+
+ callback (db, obj, callback_event::pre_update);
+
+ oracle::transaction& tr (oracle::transaction::current ());
+ oracle::connection& conn (tr.connection ());
+ statements_type& sts (
+ conn.statement_cache ().find_object<object_type> ());
+
+ const id_type& id (
+ obj.id);
+ id_image_type& idi (sts.id_image ());
+ init (idi, id);
+
+ image_type& im (sts.image ());
+ init (im, obj, statement_update);
+
+ bool u (false);
+ binding& imb (sts.update_image_binding ());
+ if (im.version != sts.update_image_version () ||
+ imb.version == 0)
+ {
+ bind (imb.bind, im, statement_update);
+ sts.update_image_version (im.version);
+ imb.version++;
+ u = true;
+ }
+
+ binding& idb (sts.id_image_binding ());
+ if (idi.version != sts.update_id_image_version () ||
+ idb.version == 0)
+ {
+ if (idi.version != sts.id_image_version () ||
+ idb.version == 0)
+ {
+ bind (idb.bind, idi);
+ sts.id_image_version (idi.version);
+ idb.version++;
+ }
+
+ sts.update_id_image_version (idi.version);
+
+ if (!u)
+ imb.version++;
+ }
+
+ update_statement& st (sts.update_statement ());
+ if (st.execute () == 0)
+ throw object_not_persistent ();
+
+ callback (db, obj, callback_event::post_update);
+ pointer_cache_traits::update (db, obj);
+ }
+
+ void access::object_traits_impl< ::person, id_oracle >::
+ erase (database& db, const id_type& id)
+ {
+ using namespace oracle;
+
+ ODB_POTENTIALLY_UNUSED (db);
+
+ oracle::connection& conn (
+ oracle::transaction::current ().connection ());
+ statements_type& sts (
+ conn.statement_cache ().find_object<object_type> ());
+
+ id_image_type& i (sts.id_image ());
+ init (i, id);
+
+ binding& idb (sts.id_image_binding ());
+ if (i.version != sts.id_image_version () || idb.version == 0)
+ {
+ bind (idb.bind, i);
+ sts.id_image_version (i.version);
+ idb.version++;
+ }
+
+ if (sts.erase_statement ().execute () != 1)
+ throw object_not_persistent ();
+
+ pointer_cache_traits::erase (db, id);
+ }
+
+ access::object_traits_impl< ::person, id_oracle >::pointer_type
+ access::object_traits_impl< ::person, id_oracle >::
+ find (database& db, const id_type& id)
+ {
+ using namespace oracle;
+
+ {
+ pointer_type p (pointer_cache_traits::find (db, id));
+
+ if (!pointer_traits::null_ptr (p))
+ return p;
+ }
+
+ oracle::connection& conn (
+ oracle::transaction::current ().connection ());
+ statements_type& sts (
+ conn.statement_cache ().find_object<object_type> ());
+
+ statements_type::auto_lock l (sts);
+
+ if (l.locked ())
+ {
+ if (!find_ (sts, &id))
+ return pointer_type ();
+ }
+
+ pointer_type p (
+ access::object_factory<object_type, pointer_type>::create ());
+ pointer_traits::guard pg (p);
+
+ pointer_cache_traits::insert_guard ig (
+ pointer_cache_traits::insert (db, id, p));
+
+ object_type& obj (pointer_traits::get_ref (p));
+
+ if (l.locked ())
+ {
+ select_statement& st (sts.find_statement ());
+ ODB_POTENTIALLY_UNUSED (st);
+
+ callback (db, obj, callback_event::pre_load);
+ init (obj, sts.image (), &db);
+ st.stream_result ();
+ load_ (sts, obj, false);
+ sts.load_delayed (0);
+ l.unlock ();
+ callback (db, obj, callback_event::post_load);
+ pointer_cache_traits::load (ig.position ());
+ }
+ else
+ sts.delay_load (id, obj, ig.position ());
+
+ ig.release ();
+ pg.release ();
+ return p;
+ }
+
+ bool access::object_traits_impl< ::person, id_oracle >::
+ find (database& db, const id_type& id, object_type& obj)
+ {
+ using namespace oracle;
+
+ oracle::connection& conn (
+ oracle::transaction::current ().connection ());
+ statements_type& sts (
+ conn.statement_cache ().find_object<object_type> ());
+
+ statements_type::auto_lock l (sts);
+
+ if (!find_ (sts, &id))
+ return false;
+
+ select_statement& st (sts.find_statement ());
+ ODB_POTENTIALLY_UNUSED (st);
+
+ reference_cache_traits::position_type pos (
+ reference_cache_traits::insert (db, id, obj));
+ reference_cache_traits::insert_guard ig (pos);
+
+ callback (db, obj, callback_event::pre_load);
+ init (obj, sts.image (), &db);
+ st.stream_result ();
+ load_ (sts, obj, false);
+ sts.load_delayed (0);
+ l.unlock ();
+ callback (db, obj, callback_event::post_load);
+ reference_cache_traits::load (pos);
+ ig.release ();
+ return true;
+ }
+
+ bool access::object_traits_impl< ::person, id_oracle >::
+ reload (database& db, object_type& obj)
+ {
+ using namespace oracle;
+
+ oracle::connection& conn (
+ oracle::transaction::current ().connection ());
+ statements_type& sts (
+ conn.statement_cache ().find_object<object_type> ());
+
+ statements_type::auto_lock l (sts);
+
+ const id_type& id (
+ obj.id);
+
+ if (!find_ (sts, &id))
+ return false;
+
+ select_statement& st (sts.find_statement ());
+ ODB_POTENTIALLY_UNUSED (st);
+
+ callback (db, obj, callback_event::pre_load);
+ init (obj, sts.image (), &db);
+ st.stream_result ();
+ load_ (sts, obj, true);
+ sts.load_delayed (0);
+ l.unlock ();
+ callback (db, obj, callback_event::post_load);
+ return true;
+ }
+
+ bool access::object_traits_impl< ::person, id_oracle >::
+ find_ (statements_type& sts,
+ const id_type* id)
+ {
+ using namespace oracle;
+
+ id_image_type& i (sts.id_image ());
+ init (i, *id);
+
+ binding& idb (sts.id_image_binding ());
+ if (i.version != sts.id_image_version () || idb.version == 0)
+ {
+ bind (idb.bind, i);
+ sts.id_image_version (i.version);
+ idb.version++;
+ }
+
+ image_type& im (sts.image ());
+ binding& imb (sts.select_image_binding ());
+
+ if (im.version != sts.select_image_version () ||
+ imb.version == 0)
+ {
+ bind (imb.bind, im, statement_select);
+ sts.select_image_version (im.version);
+ imb.version++;
+ }
+
+ select_statement& st (sts.find_statement ());
+
+ st.execute ();
+ auto_result ar (st);
+ select_statement::result r (st.fetch ());
+
+ return r != select_statement::no_data;
+ }
+}
+
+#include <odb/post.hxx>
diff --git a/bulk/oracle/orig/person-odb.hxx b/bulk/oracle/orig/person-odb.hxx
new file mode 100644
index 0000000..460be54
--- /dev/null
+++ b/bulk/oracle/orig/person-odb.hxx
@@ -0,0 +1,218 @@
+// This file was generated by ODB, object-relational mapping (ORM)
+// compiler for C++.
+//
+
+#ifndef PERSON_ODB_HXX
+#define PERSON_ODB_HXX
+
+#include <odb/version.hxx>
+
+#if (ODB_VERSION != 20302UL)
+#error ODB runtime version mismatch
+#endif
+
+#include <odb/pre.hxx>
+
+#include "person.hxx"
+
+#include <memory>
+#include <cstddef>
+
+#include <odb/core.hxx>
+#include <odb/traits.hxx>
+#include <odb/callback.hxx>
+#include <odb/wrapper-traits.hxx>
+#include <odb/pointer-traits.hxx>
+#include <odb/container-traits.hxx>
+#include <odb/no-op-cache-traits.hxx>
+
+#include <odb/details/unused.hxx>
+
+namespace odb
+{
+ // person
+ //
+ template <>
+ struct class_traits< ::person >
+ {
+ static const class_kind kind = class_object;
+ };
+
+ template <>
+ class access::object_traits< ::person >
+ {
+ public:
+ typedef ::person object_type;
+ typedef ::person* pointer_type;
+ typedef odb::pointer_traits<pointer_type> pointer_traits;
+
+ static const bool polymorphic = false;
+
+ typedef long unsigned int id_type;
+
+ static const bool auto_id = true;
+
+ static const bool abstract = false;
+
+ static id_type
+ id (const object_type&);
+
+ typedef
+ no_op_pointer_cache_traits<pointer_type>
+ pointer_cache_traits;
+
+ typedef
+ no_op_reference_cache_traits<object_type>
+ reference_cache_traits;
+
+ static void
+ callback (database&, object_type&, callback_event);
+
+ static void
+ callback (database&, const object_type&, callback_event);
+ };
+}
+
+#include <odb/details/buffer.hxx>
+
+#include <odb/oracle/version.hxx>
+#include <odb/oracle/forward.hxx>
+#include <odb/oracle/binding.hxx>
+#include <odb/oracle/oracle-types.hxx>
+
+namespace odb
+{
+ // person
+ //
+ template <>
+ class access::object_traits_impl< ::person, id_oracle >:
+ public access::object_traits< ::person >
+ {
+ public:
+ struct id_image_type
+ {
+ char id_value[12];
+ ub2 id_size;
+ sb2 id_indicator;
+
+ std::size_t version;
+ };
+
+ struct image_type
+ {
+ // id
+ //
+ char id_value[12];
+ ub2 id_size;
+ sb2 id_indicator;
+
+ // num
+ //
+ unsigned int num_value;
+ sb2 num_indicator;
+
+ // str
+ //
+ mutable oracle::lob_callback str_callback;
+ sb2 str_indicator;
+ oracle::lob str_lob;
+
+ std::size_t version;
+
+ oracle::change_callback*
+ change_callback ()
+ {
+ return 0;
+ }
+ };
+
+ struct extra_statement_cache_type;
+
+ using object_traits<object_type>::id;
+
+ static id_type
+ id (const id_image_type&);
+
+ static void
+ bind (oracle::bind*,
+ image_type&,
+ oracle::statement_kind);
+
+ static void
+ bind (oracle::bind*, id_image_type&);
+
+ static void
+ init (image_type&,
+ const object_type&,
+ oracle::statement_kind);
+
+ static void
+ init (object_type&,
+ const image_type&,
+ database*);
+
+ static void
+ init (id_image_type&, const id_type&);
+
+ typedef oracle::object_statements<object_type> statements_type;
+
+ static const std::size_t column_count = 3UL;
+ static const std::size_t id_column_count = 1UL;
+ static const std::size_t inverse_column_count = 0UL;
+ static const std::size_t readonly_column_count = 0UL;
+ static const std::size_t managed_optimistic_column_count = 0UL;
+
+ static const std::size_t separate_load_column_count = 0UL;
+ static const std::size_t separate_update_column_count = 0UL;
+
+ static const bool versioned = false;
+
+ static const char persist_statement[];
+ static const char find_statement[];
+ static const char update_statement[];
+ static const char erase_statement[];
+
+ static void
+ persist (database&, object_type&);
+
+ static pointer_type
+ find (database&, const id_type&);
+
+ static bool
+ find (database&, const id_type&, object_type&);
+
+ static bool
+ reload (database&, object_type&);
+
+ static void
+ update (database&, const object_type&);
+
+ static void
+ erase (database&, const id_type&);
+
+ static void
+ erase (database&, const object_type&);
+
+ public:
+ static bool
+ find_ (statements_type&,
+ const id_type*);
+
+ static void
+ load_ (statements_type&,
+ object_type&,
+ bool reload);
+ };
+
+ template <>
+ class access::object_traits_impl< ::person, id_common >:
+ public access::object_traits_impl< ::person, id_oracle >
+ {
+ };
+}
+
+#include "person-odb.ixx"
+
+#include <odb/post.hxx>
+
+#endif // PERSON_ODB_HXX
diff --git a/bulk/oracle/orig/person-odb.ixx b/bulk/oracle/orig/person-odb.ixx
new file mode 100644
index 0000000..d1763df
--- /dev/null
+++ b/bulk/oracle/orig/person-odb.ixx
@@ -0,0 +1,61 @@
+// This file was generated by ODB, object-relational mapping (ORM)
+// compiler for C++.
+//
+
+namespace odb
+{
+ // person
+ //
+
+ inline
+ access::object_traits< ::person >::id_type
+ access::object_traits< ::person >::
+ id (const object_type& o)
+ {
+ return o.id;
+ }
+
+ inline
+ void access::object_traits< ::person >::
+ callback (database& db, object_type& x, callback_event e)
+ {
+ ODB_POTENTIALLY_UNUSED (db);
+ ODB_POTENTIALLY_UNUSED (x);
+ ODB_POTENTIALLY_UNUSED (e);
+ }
+
+ inline
+ void access::object_traits< ::person >::
+ callback (database& db, const object_type& x, callback_event e)
+ {
+ ODB_POTENTIALLY_UNUSED (db);
+ ODB_POTENTIALLY_UNUSED (x);
+ ODB_POTENTIALLY_UNUSED (e);
+ }
+}
+
+namespace odb
+{
+ // person
+ //
+
+ inline
+ void access::object_traits_impl< ::person, id_oracle >::
+ erase (database& db, const object_type& obj)
+ {
+ callback (db, obj, callback_event::pre_erase);
+ erase (db, id (obj));
+ callback (db, obj, callback_event::post_erase);
+ }
+
+ inline
+ void access::object_traits_impl< ::person, id_oracle >::
+ load_ (statements_type& sts,
+ object_type& obj,
+ bool)
+ {
+ ODB_POTENTIALLY_UNUSED (sts);
+ ODB_POTENTIALLY_UNUSED (obj);
+ }
+}
+
diff --git a/bulk/person.hxx b/bulk/person.hxx
new file mode 100644
index 0000000..ac7a66b
--- /dev/null
+++ b/bulk/person.hxx
@@ -0,0 +1,28 @@
+// file : hello/person.hxx
+// copyright : not copyrighted - public domain
+
+#ifndef PERSON_HXX
+#define PERSON_HXX
+
+#include <string>
+
+#include <odb/core.hxx>
+
+#pragma db object
+class person
+{
+public:
+ #pragma db id auto
+ unsigned long id;
+
+ unsigned int num;
+
+#ifdef ODB_DATABASE_MSSQL
+ #pragma db type("VARCHAR(max)")
+#else
+ #pragma db type("CLOB")
+#endif
+ std::string str;
+};
+
+#endif // PERSON_HXX