diff options
Diffstat (limited to 'odb-tests/oracle/custom')
-rw-r--r-- | odb-tests/oracle/custom/custom.sql | 53 | ||||
-rw-r--r-- | odb-tests/oracle/custom/driver.cxx | 77 | ||||
-rw-r--r-- | odb-tests/oracle/custom/test.hxx | 40 | ||||
-rw-r--r-- | odb-tests/oracle/custom/traits.hxx | 76 |
4 files changed, 246 insertions, 0 deletions
diff --git a/odb-tests/oracle/custom/custom.sql b/odb-tests/oracle/custom/custom.sql new file mode 100644 index 0000000..6e22903 --- /dev/null +++ b/odb-tests/oracle/custom/custom.sql @@ -0,0 +1,53 @@ +/* This file contains custom type definitions and helper functions. + */ + +/* For some reason CREATE OR REPLACE TYPE does not work on Oracle 10.2. */ +BEGIN + BEGIN + EXECUTE IMMEDIATE 'DROP TYPE Numbers'; + EXCEPTION + WHEN OTHERS THEN + IF SQLCODE != -4043 THEN RAISE; END IF; + END; +END; +/ + +CREATE TYPE Numbers AS VARRAY(100) OF NUMBER(10); +/ + +CREATE OR REPLACE FUNCTION string_to_numbers(in_str IN VARCHAR2) RETURN Numbers +IS + ret Numbers := Numbers(); + s_pos NUMBER := 1; + e_pos NUMBER := 0; +BEGIN + IF in_str IS NOT NULL THEN + LOOP + e_pos := INSTR(in_str, ',', s_pos); + EXIT WHEN e_pos = 0; + ret.extend; + ret(ret.COUNT) := CAST(SUBSTR(in_str, s_pos, e_pos - s_pos) AS NUMBER); + s_pos := e_pos + 1; + END LOOP; + ret.extend; + ret(ret.COUNT) := CAST(SUBSTR(in_str, s_pos) AS NUMBER); + END IF; + RETURN ret; +END; +/ + +CREATE OR REPLACE FUNCTION numbers_to_string(in_nums IN Numbers) RETURN VARCHAR2 +IS + ret VARCHAR2(1500); +BEGIN + IF in_nums.COUNT != 0 THEN + FOR i IN in_nums.FIRST .. in_nums.LAST LOOP + IF i != in_nums.FIRST THEN + ret := ret || ','; + END IF; + ret := ret || in_nums(i); + END LOOP; + END IF; + RETURN ret; +END; +/ diff --git a/odb-tests/oracle/custom/driver.cxx b/odb-tests/oracle/custom/driver.cxx new file mode 100644 index 0000000..45f0a4e --- /dev/null +++ b/odb-tests/oracle/custom/driver.cxx @@ -0,0 +1,77 @@ +// file : oracle/custom/driver.cxx +// license : GNU GPL v2; see accompanying LICENSE file + +// Test custom database type mapping in Oracle. +// + +#include <memory> // std::auto_ptr +#include <cassert> +#include <iostream> + +#include <odb/oracle/database.hxx> +#include <odb/oracle/transaction.hxx> + +#include <common/common.hxx> + +#include "test.hxx" +#include "test-odb.hxx" + +using namespace std; +namespace oracle = odb::oracle; +using namespace oracle; + +int +main (int argc, char* argv[]) +{ + try + { + auto_ptr<database> db (create_specific_database<database> (argc, argv)); + + object o (1); + o.iv.push_back (123); + o.iv.push_back (234); + o.iv.push_back (-345); + + // Persist. + // + { + transaction t (db->begin ()); + db->persist (o); + t.commit (); + } + + // Load. + // + { + transaction t (db->begin ()); + auto_ptr<object> o1 (db->load<object> (1)); + t.commit (); + + assert (o == *o1); + } + + // Update. + // + o.iv[0]++; + o.iv.pop_back (); + + { + transaction t (db->begin ()); + db->update (o); + t.commit (); + } + + { + transaction t (db->begin ()); + auto_ptr<object> o1 (db->load<object> (1)); + t.commit (); + + assert (o == *o1); + } + } + catch (const odb::exception& e) + { + cerr << e.what () << endl; + return 1; + } +} diff --git a/odb-tests/oracle/custom/test.hxx b/odb-tests/oracle/custom/test.hxx new file mode 100644 index 0000000..523d50b --- /dev/null +++ b/odb-tests/oracle/custom/test.hxx @@ -0,0 +1,40 @@ +// file : oracle/custom/test.hxx +// license : GNU GPL v2; see accompanying LICENSE file + +#ifndef TEST_HXX +#define TEST_HXX + +#include <vector> + +#include <odb/core.hxx> + +// Map Numbers VARRAY Oracle type to std::vector<int>. This type is defined +// in the custom.sql file along with two helper functions that convert +// between Numbers and its string representation. The other half of this +// mapping is in traits.hxx (value_traits<std::vector<int>, id_string>). +// +#pragma db map type("Numbers") \ + as("VARCHAR2(1500)") \ + to("CAST(string_to_numbers((?)) AS Numbers)") \ + from("numbers_to_string((?))") + +#pragma db object +struct object +{ + object () {} + object (unsigned long id_) : id (id_) {} + + #pragma db id + unsigned long id; + + #pragma db type("Numbers") + std::vector<int> iv; + + bool + operator== (const object& y) const + { + return id == y.id && iv == y.iv; + } +}; + +#endif // TEST_HXX diff --git a/odb-tests/oracle/custom/traits.hxx b/odb-tests/oracle/custom/traits.hxx new file mode 100644 index 0000000..8df2f91 --- /dev/null +++ b/odb-tests/oracle/custom/traits.hxx @@ -0,0 +1,76 @@ +// file : oracle/types/traits.hxx +// license : GNU GPL v2; see accompanying LICENSE file + +#ifndef TRAITS_HXX +#define TRAITS_HXX + +#include <vector> +#include <sstream> +#include <cstring> // std::memcpy +#include <cassert> // std::memcpy + +#include <odb/oracle/traits.hxx> + +namespace odb +{ + namespace oracle + { + + template <> + class value_traits<std::vector<int>, id_string> + { + public: + typedef std::vector<int> value_type; + typedef value_type query_type; + typedef details::buffer image_type; + + static void + set_value (value_type& v, + const char* b, + std::size_t n, + bool is_null) + { + v.clear (); + + if (!is_null) + { + // Array format is "n1,n2,n3...". + // + std::istringstream is (std::string (b, n)); + + for (char c; !is.eof (); is >> c) + { + v.push_back (int ()); + is >> v.back (); + } + } + } + + static void + set_image (char* b, + std::size_t c, + std::size_t& n, + bool& is_null, + const value_type& v) + { + is_null = false; + std::ostringstream os; + + for (value_type::const_iterator i (v.begin ()), e (v.end ()); i != e;) + { + os << *i; + + if (++i != e) + os << ','; + } + + const std::string& s (os.str ()); + n = s.size (); + assert (n <= c); + std::memcpy (b, s.c_str (), n); + } + }; + } +} + +#endif // TRAITS_HXX |