aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2013-04-25 07:35:45 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2013-04-25 07:35:45 +0200
commit596281268a8602eec39956a12ff519e5d35f3acc (patch)
tree499827577fb4fc099dfc00dc6cfeb8f457d9069a
parent5793218aa39d188719d531593fe6fb4ab6cdb805 (diff)
Add support for schema version table
-rw-r--r--odb/oracle/database.cxx102
-rw-r--r--odb/oracle/database.hxx6
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).
//