From 19131a419b35e409e6b65fc47ff31f7742ff54f3 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Wed, 7 Mar 2012 10:21:09 +0200 Subject: Use RAII to free select statement results --- odb/relational/context.cxx | 1 + odb/relational/context.hxx | 1 + odb/relational/mssql/context.cxx | 1 + odb/relational/mssql/source.cxx | 18 ------- odb/relational/mysql/context.cxx | 1 + odb/relational/oracle/context.cxx | 1 + odb/relational/pgsql/context.cxx | 1 + odb/relational/source.hxx | 106 +++++++++++++++++++++----------------- odb/relational/sqlite/context.cxx | 1 + 9 files changed, 65 insertions(+), 66 deletions(-) diff --git a/odb/relational/context.cxx b/odb/relational/context.cxx index ae73603..98bbfe4 100644 --- a/odb/relational/context.cxx +++ b/odb/relational/context.cxx @@ -26,6 +26,7 @@ namespace relational generate_grow (current ().generate_grow), need_alias_as (current ().need_alias_as), insert_send_auto_id (current ().insert_send_auto_id), + delay_freeing_statement_result (current ().delay_freeing_statement_result), bind_vector (data_->bind_vector_), truncated_vector (data_->truncated_vector_) { diff --git a/odb/relational/context.hxx b/odb/relational/context.hxx index dddb86e..52cb9c0 100644 --- a/odb/relational/context.hxx +++ b/odb/relational/context.hxx @@ -158,6 +158,7 @@ namespace relational bool generate_grow; bool need_alias_as; bool insert_send_auto_id; + bool delay_freeing_statement_result; string const& bind_vector; string const& truncated_vector; diff --git a/odb/relational/mssql/context.cxx b/odb/relational/mssql/context.cxx index 312cc03..1fddbe9 100644 --- a/odb/relational/mssql/context.cxx +++ b/odb/relational/mssql/context.cxx @@ -84,6 +84,7 @@ namespace relational generate_grow = false; need_alias_as = true; insert_send_auto_id = false; + delay_freeing_statement_result = true; data_->bind_vector_ = "mssql::bind*"; // Populate the C++ type to DB type map. diff --git a/odb/relational/mssql/source.cxx b/odb/relational/mssql/source.cxx index 1b800aa..2d8d41d 100644 --- a/odb/relational/mssql/source.cxx +++ b/odb/relational/mssql/source.cxx @@ -971,24 +971,6 @@ namespace relational } virtual void - free_statement_result_immediate () - { - // Only free the result if there are no rows. Otherwise we - // need to keep the result alive until after we are done - // streaming long data. - // - os << "if (r == select_statement::no_data)" << endl - << "st.free_result ();" - << endl; - } - - virtual void - free_statement_result_delayed () - { - os << "sts.find_statement ().free_result ();"; - } - - virtual void persist_statement_extra (type& c, relational::query_parameters&, persist_position p) diff --git a/odb/relational/mysql/context.cxx b/odb/relational/mysql/context.cxx index ad7236c..5d45934 100644 --- a/odb/relational/mysql/context.cxx +++ b/odb/relational/mysql/context.cxx @@ -80,6 +80,7 @@ namespace relational generate_grow = true; need_alias_as = true; insert_send_auto_id = true; + delay_freeing_statement_result = false; data_->bind_vector_ = "MYSQL_BIND*"; data_->truncated_vector_ = "my_bool*"; diff --git a/odb/relational/oracle/context.cxx b/odb/relational/oracle/context.cxx index dbe61af..2fa566c 100644 --- a/odb/relational/oracle/context.cxx +++ b/odb/relational/oracle/context.cxx @@ -79,6 +79,7 @@ namespace relational generate_grow = false; need_alias_as = false; insert_send_auto_id = true; + delay_freeing_statement_result = false; data_->bind_vector_ = "oracle::bind*"; // Populate the C++ type to DB type map. diff --git a/odb/relational/pgsql/context.cxx b/odb/relational/pgsql/context.cxx index 17ceaaa..9ce333e 100644 --- a/odb/relational/pgsql/context.cxx +++ b/odb/relational/pgsql/context.cxx @@ -80,6 +80,7 @@ namespace relational generate_grow = true; need_alias_as = true; insert_send_auto_id = true; + delay_freeing_statement_result = false; data_->bind_vector_ = "pgsql::bind*"; data_->truncated_vector_ = "bool*"; diff --git a/odb/relational/source.hxx b/odb/relational/source.hxx index a8edcf3..e6ca961 100644 --- a/odb/relational/source.hxx +++ b/odb/relational/source.hxx @@ -2191,7 +2191,6 @@ namespace relational } } - init_value_extra (); // If we are loading an eager pointer, then the call to init @@ -2236,12 +2235,7 @@ namespace relational << "}" << "}"; - os << "if (r == select_statement::no_data)" - << "{" - << "st.free_result ();" - << "return false;" - << "}" - << "return true;" + os << "return r != select_statement::no_data;" << "}"; // delete_all @@ -2315,7 +2309,8 @@ namespace relational << "cb.version++;" << "}" << "select_statement& st (sts.select_all_statement ());" - << "st.execute ();"; + << "st.execute ();" + << "auto_result ar (st);"; // If we are loading eager object pointers, we may need to cache // the result since we will be loading other objects. @@ -2344,9 +2339,6 @@ namespace relational os << "bool more (r != select_statement::no_data);" << endl - << "if (!more)" << endl - << "st.free_result ();" - << endl << "sts.id_binding (id);" << "functions_type& fs (sts.functions ());"; @@ -2809,19 +2801,6 @@ namespace relational { } - // By default we free statement result immediately after fetch. - // - virtual void - free_statement_result_immediate () - { - os << "st.free_result ();"; - } - - virtual void - free_statement_result_delayed () - { - } - virtual void object_query_statement_ctor_args (type&) { @@ -3553,7 +3532,8 @@ namespace relational << "throw object_not_persistent ();" << endl; - free_statement_result_delayed (); + if (delay_freeing_statement_result) + os << "sts.find_statement ().free_result ();"; if (straight_readwrite_containers) os << "binding& idb (sts.id_image_binding ());" @@ -3698,7 +3678,8 @@ namespace relational << "throw object_changed ();" << endl; - free_statement_result_delayed (); + if (delay_freeing_statement_result) + os << "sts.find_statement ().free_result ();"; os << "if (version (sts.image ()) != obj." << optimistic->name () << ")" << endl @@ -3728,13 +3709,22 @@ namespace relational << db << "::transaction::current ().connection ());" << object_statements_type << "& sts (" << endl << "conn.statement_cache ().find_object ());" - << object_statements_type << "::auto_lock l (sts);" - << endl + << object_statements_type << "::auto_lock l (sts);"; + + if (delay_freeing_statement_result) + os << "auto_result ar;"; + + os << endl << "if (l.locked ())" << "{" << "if (!find_ (sts, id))" << endl - << "return pointer_type ();" - << "}" + << "return pointer_type ();"; + + if (delay_freeing_statement_result) + os << endl + << "ar.set (sts.find_statement ());"; + + os << "}" << "pointer_type p (" << endl << "access::object_factory< object_type, pointer_type >::create ());" << "pointer_traits< pointer_type >::guard pg (p);" @@ -3748,7 +3738,9 @@ namespace relational << "init (obj, sts.image (), &db);"; init_value_extra (); - free_statement_result_delayed (); + + if (delay_freeing_statement_result) + os << "ar.free ();"; os << "load_ (sts, obj);" << "sts.load_delayed ();" @@ -3786,15 +3778,21 @@ namespace relational os << "if (!find_ (sts, id))" << endl << "return false;" - << endl - << "reference_cache_traits< object_type >::insert_guard ig (" << endl + << endl; + + if (delay_freeing_statement_result) + os << "auto_result ar (sts.find_statement ());"; + + os << "reference_cache_traits< object_type >::insert_guard ig (" << endl << "reference_cache_traits< object_type >::insert (db, id, obj));" << endl << "callback (db, obj, callback_event::pre_load);" << "init (obj, sts.image (), &db);"; init_value_extra (); - free_statement_result_delayed (); + + if (delay_freeing_statement_result) + os << "ar.free ();"; os << "load_ (sts, obj);" << "sts.load_delayed ();" @@ -3828,23 +3826,24 @@ namespace relational << "return false;" << endl; + if (delay_freeing_statement_result) + os << "auto_result ar (sts.find_statement ());" + << endl; + if (optimistic != 0) { os << "if (version (sts.image ()) == obj." << - optimistic->name () << ")" - << "{"; - - free_statement_result_delayed (); - - os << "return true;" - << "}"; + optimistic->name () << ")" << endl + << "return true;"; } os << "callback (db, obj, callback_event::pre_load);" << "init (obj, sts.image (), &db);"; init_value_extra (); - free_statement_result_delayed (); + + if (delay_freeing_statement_result) + os << "ar.free ();"; os << "load_ (sts, obj);" << "sts.load_delayed ();" @@ -3893,11 +3892,12 @@ namespace relational << "}" << "select_statement& st (sts.find_statement ());" << "st.execute ();" - << "select_statement::result r (st.fetch ());"; + << "auto_result ar (st);" + << "select_statement::result r (st.fetch ());" + << endl; if (grow) - os << endl - << "if (r == select_statement::truncated)" + os << "if (r == select_statement::truncated)" << "{" << "if (grow (im, sts.select_image_truncated ()))" << endl << "im.version++;" @@ -3911,10 +3911,20 @@ namespace relational << "}" << "}"; - free_statement_result_immediate (); + // If we are delaying, only free the result if it is empty. + // + if (delay_freeing_statement_result) + os << "if (r != select_statement::no_data)" + << "{" + << "ar.release ();" + << "return true;" + << "}" + << "else" << endl + << "return false;"; + else + os << "return r != select_statement::no_data;"; - os << "return r != select_statement::no_data;" - << "}"; + os << "}"; } // load_() diff --git a/odb/relational/sqlite/context.cxx b/odb/relational/sqlite/context.cxx index 46689bd..9f25fcc 100644 --- a/odb/relational/sqlite/context.cxx +++ b/odb/relational/sqlite/context.cxx @@ -78,6 +78,7 @@ namespace relational generate_grow = true; need_alias_as = true; insert_send_auto_id = true; + delay_freeing_statement_result = false; data_->bind_vector_ = "sqlite::bind*"; data_->truncated_vector_ = "bool*"; -- cgit v1.1