From a87c149915fa5a262bd797df1c2a4e756420d413 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Mon, 21 Jun 2021 12:52:18 +0200 Subject: Add support for bulk operations in PostgreSQL 14 --- odb/pragma.cxx | 2 -- odb/relational/pgsql/context.cxx | 2 +- odb/relational/pgsql/header.cxx | 14 ++++++++++ odb/relational/pgsql/source.cxx | 6 ++-- odb/relational/source.cxx | 59 ++++++++++++++++++++++++++++++---------- 5 files changed, 62 insertions(+), 21 deletions(-) (limited to 'odb') diff --git a/odb/pragma.cxx b/odb/pragma.cxx index bd1d848..6668733 100644 --- a/odb/pragma.cxx +++ b/odb/pragma.cxx @@ -1643,8 +1643,6 @@ handle_pragma (cxx_lexer& l, return; } - // base - // if (l.next (tl, &tn) != CPP_NUMBER || TREE_CODE (tn) != INTEGER_CST) { error (l) << "unsigned integer expected as batch size" << endl; diff --git a/odb/relational/pgsql/context.cxx b/odb/relational/pgsql/context.cxx index a9f34dd..7f99f5d 100644 --- a/odb/relational/pgsql/context.cxx +++ b/odb/relational/pgsql/context.cxx @@ -85,7 +85,7 @@ namespace relational insert_send_auto_id = false; delay_freeing_statement_result = false; need_image_clone = false; - generate_bulk = false; + generate_bulk = true; global_index = true; global_fkey = false; data_->bind_vector_ = "pgsql::bind*"; diff --git a/odb/relational/pgsql/header.cxx b/odb/relational/pgsql/header.cxx index ff00eaa..c3efc3e 100644 --- a/odb/relational/pgsql/header.cxx +++ b/odb/relational/pgsql/header.cxx @@ -87,6 +87,20 @@ namespace relational } os << endl; + + if (poly_derived) + return; + + // Bulk operations batch size. + // + { + unsigned long long b (c.count ("bulk") + ? c.get ("bulk") + : 1); + + os << "static const std::size_t batch = " << b << "UL;" + << endl; + } } virtual void diff --git a/odb/relational/pgsql/source.cxx b/odb/relational/pgsql/source.cxx index 580103d..b881e48 100644 --- a/odb/relational/pgsql/source.cxx +++ b/odb/relational/pgsql/source.cxx @@ -203,7 +203,7 @@ namespace relational traverse_numeric (member_info& mi) { os << b << ".type = pgsql::bind::numeric;" - << b << ".buffer = " << arg << "." << mi.var << "value.data ();" + << b << ".buffer = " << arg << "." << mi.var << "value.data_ptr ();" << b << ".capacity = " << arg << "." << mi.var << "value.capacity ();" << b << ".size = &" << arg << "." << mi.var << "size;" @@ -224,7 +224,7 @@ namespace relational { os << b << ".type = " << char_bin_buffer_types[mi.st->type - sql_type::CHAR] << ";" - << b << ".buffer = " << arg << "." << mi.var << "value.data ();" + << b << ".buffer = " << arg << "." << mi.var << "value.data_ptr ();" << b << ".capacity = " << arg << "." << mi.var << "value.capacity ();" << b << ".size = &" << arg << "." << mi.var << "size;" @@ -245,7 +245,7 @@ namespace relational traverse_varbit (member_info& mi) { os << b << ".type = pgsql::bind::varbit;" - << b << ".buffer = " << arg << "." << mi.var << "value.data ();" + << b << ".buffer = " << arg << "." << mi.var << "value.data_ptr ();" << b << ".capacity = " << arg << "." << mi.var << "value.capacity ();" << b << ".size = &" << arg << "." << mi.var << "size;" diff --git a/odb/relational/source.cxx b/odb/relational/source.cxx index d35a827..e00626a 100644 --- a/odb/relational/source.cxx +++ b/odb/relational/source.cxx @@ -1172,10 +1172,10 @@ traverse_object (type& c) << "{"; if (poly) - os << "ODB_POTENTIALLY_UNUSED (top);"; + os << "ODB_POTENTIALLY_UNUSED (top);" + << endl; - os << endl - << "using namespace " << db << ";" + os << "using namespace " << db << ";" << endl; if (poly) @@ -1461,13 +1461,25 @@ traverse_object (type& c) << "{" << "const object_type& obj (*objs[i]);" << "callback (db, obj, callback_event::pre_persist);" - //@@ assumption: generate_grow is false + //@@ assumption: generate_grow is false or it only affects select (like + // in pgsql) so all we have to do is to increment image + // version if it grew. //@@ assumption: insert_send_auto_id is false - << "init (sts.image (i), obj, statement_insert" << - (versioned ? ", svm" : "") << ");" + << "image_type& im (sts.image (i));"; + + if (generate_grow) + os << "if ("; + + os << "init (im, obj, statement_insert" << (versioned ? ", svm" : "") << ")"; + + if (generate_grow) + os << " && i == 0)" << endl + << "im.version++"; + + os << ";" << "}"; - //@@ assumption: generate_grow is false + //@@ assumption: generate_grow: as above os << "binding& imb (sts.insert_image_binding ());" << "if (imb.version == 0)" << "{" @@ -1483,7 +1495,7 @@ traverse_object (type& c) if (bv || auto_id) { os << "binding& idb (sts.id_image_binding ());" - //@@ assumption: generate_grow is false + //@@ assumption: generate_grow: as above << "if (idb.version == 0)" << "{" << "bind (idb.bind, sts.id_image ());" @@ -2212,9 +2224,24 @@ traverse_object (type& c) if (opt != 0) os << "const version_type& v (version (obj));"; - os << "init (sts.id_image (i), id (obj)" << (opt != 0 ? ", &v" : "") << ");" - //@@ assumption: generate_grow false - << "init (sts.image (i), obj, statement_update);" + os << "init (sts.id_image (i), id (obj)" << (opt != 0 ? ", &v" : "") << ");"; + + //@@ assumption: generate_grow is false or it only affects select (like + // in pgsql) so all we have to do is to increment image + // version if it grew. + + os << "image_type& im (sts.image (i));"; + + if (generate_grow) + os << "if ("; + + os << "init (im, obj, statement_update" << (versioned ? ", svm" : "") << ")"; + + if (generate_grow) + os << " && i == 0)" << endl + << "im.version++"; + + os << ";" << "}"; // Update bindings. @@ -2223,7 +2250,7 @@ traverse_object (type& c) << "binding& imb (sts.update_image_binding ());" << endl; - //@@ assumption: generate_grow false + //@@ assumption: generate_grow: as above // os << "bool u (false);" // Avoid incrementing version twice. << "if (imb.version == 0)" @@ -2234,7 +2261,7 @@ traverse_object (type& c) << "u = true;" << "}"; - //@@ assumption: generate_grow false + //@@ assumption: generate_grow: as above // os << "if (idb.version == 0)" << "{" @@ -2452,7 +2479,8 @@ traverse_object (type& c) << "init (sts.id_image (i), *ids[i]);" << endl << "binding& idb (sts.id_image_binding ());" - //@@ assumption: generate_grow false + //@@ assumption: generate_grow is false or it only affects select (like + // in pgsql). << "if (idb.version == 0)" << "{" << "bind (idb.bind, sts.id_image ());" @@ -2836,7 +2864,8 @@ traverse_object (type& c) << "}"; os << "binding& idb (sts.id_image_binding ());" - //@@ assumption: generate_grow false + //@@ assumption: generate_grow is false or it only affects select + // (like in pgsql). << "if (idb.version == 0)" << "{" << "bind (idb.bind, sts.id_image ());" -- cgit v1.1