diff options
author | Boris Kolpackov <boris@codesynthesis.com> | 2013-04-25 07:35:45 +0200 |
---|---|---|
committer | Boris Kolpackov <boris@codesynthesis.com> | 2013-04-25 07:35:45 +0200 |
commit | 596281268a8602eec39956a12ff519e5d35f3acc (patch) | |
tree | 499827577fb4fc099dfc00dc6cfeb8f457d9069a | |
parent | 5793218aa39d188719d531593fe6fb4ab6cdb805 (diff) |
Add support for schema version table
-rw-r--r-- | odb/oracle/database.cxx | 102 | ||||
-rw-r--r-- | odb/oracle/database.hxx | 6 |
2 files changed, 107 insertions, 1 deletions
diff --git a/odb/oracle/database.cxx b/odb/oracle/database.cxx index 6b2a1e2..60dc4f4 100644 --- a/odb/oracle/database.cxx +++ b/odb/oracle/database.cxx @@ -6,7 +6,10 @@ #include <sstream> +#include <odb/oracle/traits.hxx> #include <odb/oracle/database.hxx> +#include <odb/oracle/statement.hxx> +#include <odb/oracle/transaction.hxx> #include <odb/oracle/exceptions.hxx> #include <odb/oracle/error.hxx> @@ -220,7 +223,7 @@ namespace odb } void database:: - print_usage (std::ostream& os) + print_usage (ostream& os) { details::options::print_usage (os); } @@ -242,5 +245,102 @@ namespace odb connection_ptr c (factory_->connect ()); return c.release (); } + + const database::schema_version_info& database:: + load_schema_version (const string& name) const + { + schema_version_info& svi (schema_version_map_[name]); + + // Construct the SELECT statement text. + // + string text ("SELECT \"version\", \"migration\" FROM "); + + if (!svi.version_table.empty ()) + text += svi.version_table; // Already quoted. + else if (!schema_version_table_.empty ()) + text += schema_version_table_; // Already quoted. + else + text += "\"schema_version\""; + + text += " WHERE \"name\" = :1"; + + // Bind parameters and results. If the schema name is empty, replace + // it with a single space to workaround the VARCHAR2 empty/NULL issue. + // + string n (name.empty () ? string (" ") : name); + ub2 psize[1] = {static_cast<ub2> (n.size ())}; + sb2 pind[1] = {0}; + bind pbind[1] = {{bind::string, + const_cast<char*> (n.c_str ()), + &psize[0], + psize[0], + &pind[0], + 0}}; + binding param (pbind, 1); + param.version++; + + char version[12]; + unsigned int migration; + ub2 rsize[1]; + sb2 rind[2]; + bind rbind[2] = { + {bind::number, + version, + &rsize[0], + static_cast<ub4> (sizeof (version)), + &rind[0], + 0}, + + {bind::uinteger, &migration, 0, 4, &rind[1], 0} + }; + binding result (rbind, 2); + result.version++; + + // If we are not in transaction, then OCI will start an implicit one + // but only if we try to modify anything. Since our statement is read- + // only, we can run without a transaction. + // + connection_ptr cp; + if (!transaction::has_current ()) + cp = factory_->connect (); + + oracle::connection& c ( + cp != 0 ? *cp : transaction::current ().connection ()); + + try + { + select_statement st (c, text, param, result); + st.execute (); + auto_result ar (st); + + switch (st.fetch ()) + { + case select_statement::success: + { + value_traits<unsigned long long, id_big_int>::set_value ( + svi.version, version, rsize[0], rind[0] == -1); + svi.migration = migration != 0; + assert (st.fetch () == select_statement::no_data); + break; + } + case select_statement::no_data: + { + svi.version = 0; // No schema. + break; + } + } + } + catch (const database_exception& e) + { + // Detect the case where there is no version table. + // + if (e.size () != 0 && e.begin ()->error () == 942) + svi.version = 0; // No schema. + else + throw; + } + + return svi; + } } } diff --git a/odb/oracle/database.hxx b/odb/oracle/database.hxx index e9cac18..c29453b 100644 --- a/odb/oracle/database.hxx +++ b/odb/oracle/database.hxx @@ -378,6 +378,12 @@ namespace odb using odb::database::tracer; + // Database schema version. + // + protected: + virtual const schema_version_info& + load_schema_version (const std::string& schema_name) const; + public: // Database id constant (useful for meta-programming). // |