summaryrefslogtreecommitdiff
path: root/odb-tests/common/section/basics/test.hxx
diff options
context:
space:
mode:
Diffstat (limited to 'odb-tests/common/section/basics/test.hxx')
-rw-r--r--odb-tests/common/section/basics/test.hxx628
1 files changed, 628 insertions, 0 deletions
diff --git a/odb-tests/common/section/basics/test.hxx b/odb-tests/common/section/basics/test.hxx
new file mode 100644
index 0000000..702ef8b
--- /dev/null
+++ b/odb-tests/common/section/basics/test.hxx
@@ -0,0 +1,628 @@
+// file : common/section/basics/test.hxx
+// license : GNU GPL v2; see accompanying LICENSE file
+
+#ifndef TEST_HXX
+#define TEST_HXX
+
+#include <string>
+#include <vector>
+
+#include <odb/core.hxx>
+#include <odb/section.hxx>
+#include <odb/vector.hxx>
+
+#ifdef ODB_COMPILER
+# if defined(ODB_DATABASE_PGSQL)
+# define BLOB_TYPE "BYTEA"
+# elif defined(ODB_DATABASE_MSSQL)
+# define BLOB_TYPE "VARBINARY(max)"
+# else
+# define BLOB_TYPE "BLOB"
+# endif
+#endif
+
+// Test lazy-loaded, always-updated section.
+//
+#pragma db namespace table("t1_")
+namespace test1
+{
+ #pragma db object
+ struct object
+ {
+ object (int n_ = 999, const std::string& s_ = "xxx")
+ : sn (n_), n (n_), ss (s_) {sv.push_back (n_);}
+
+ #pragma db id auto
+ unsigned long id;
+
+ #pragma db load(lazy)
+ odb::section s;
+
+ #pragma db section(s)
+ int sn;
+
+ int n;
+
+ #pragma db section(s)
+ std::string ss;
+
+ #pragma db section(s)
+ std::vector<int> sv;
+ };
+}
+
+// Test lazy-loaded, change-updated section.
+//
+#pragma db namespace table("t2_")
+namespace test2
+{
+ #pragma db object
+ struct object
+ {
+ object (int n_ = 999, const std::string& s_ = "xxx")
+ : sn (n_), n (n_), ss (s_) {sv.push_back (n_);}
+
+ #pragma db id auto
+ unsigned long id;
+
+ #pragma db load(lazy) update(change)
+ odb::section s;
+
+ #pragma db section(s)
+ int sn;
+
+ int n;
+
+ #pragma db section(s)
+ std::string ss;
+
+ #pragma db section(s)
+ std::vector<int> sv;
+ };
+}
+
+// Test lazy-loaded, manually-updated section.
+//
+#pragma db namespace table("t3_")
+namespace test3
+{
+ #pragma db object
+ struct object
+ {
+ object (int n_ = 999, const std::string& s_ = "xxx")
+ : sn (n_), n (n_), ss (s_) {sv.push_back (n_);}
+
+ #pragma db id auto
+ unsigned long id;
+
+ #pragma db load(lazy) update(manual)
+ odb::section s;
+
+ #pragma db section(s)
+ int sn;
+
+ int n;
+
+ #pragma db section(s)
+ std::string ss;
+
+ #pragma db section(s)
+ std::vector<int> sv;
+ };
+}
+
+// Test eager-loaded, change-updated section.
+//
+#pragma db namespace table("t4_")
+namespace test4
+{
+ #pragma db object
+ struct object
+ {
+ object (int n_ = 999, const std::string& s_ = "xxx")
+ : sn (n_), n (n_), ss (s_) {sv.push_back (n_);}
+
+ #pragma db id auto
+ unsigned long id;
+
+ #pragma db section(s)
+ int sn;
+
+ #pragma db update(change)
+ odb::section s;
+
+ int n;
+
+ #pragma db section(s)
+ std::string ss;
+
+ #pragma db section(s)
+ std::vector<int> sv;
+ };
+}
+
+// Test eager-loaded, manually-updated section.
+//
+#pragma db namespace table("t5_")
+namespace test5
+{
+ #pragma db object
+ struct object
+ {
+ object (int n_ = 999, const std::string& s_ = "xxx")
+ : sn (n_), n (n_), ss (s_) {sv.push_back (n_);}
+
+ #pragma db id auto
+ unsigned long id;
+
+ #pragma db section(s)
+ int sn;
+
+ #pragma db update(manual)
+ odb::section s;
+
+ int n;
+
+ #pragma db section(s)
+ std::string ss;
+
+ #pragma db section(s)
+ std::vector<int> sv;
+ };
+}
+
+// Test value-only and container-only section. Also multiple sections
+// in an object.
+//
+#pragma db namespace table("t6_")
+namespace test6
+{
+ #pragma db object
+ struct object
+ {
+ object (int n_ = 999, const std::string& s_ = "xxx")
+ : n (n_), sn (n_), ss (s_) {sv.push_back (n_);}
+
+ #pragma db id auto
+ unsigned long id;
+
+ int n;
+
+ #pragma db load(lazy)
+ odb::section s1;
+
+ #pragma db load(lazy)
+ odb::section s2;
+
+ #pragma db section(s1)
+ int sn;
+
+ #pragma db section(s1)
+ std::string ss;
+
+ #pragma db section(s2)
+ std::vector<int> sv;
+ };
+}
+
+// Test sections and reuse inheritance.
+//
+#pragma db namespace table("t7_")
+namespace test7
+{
+ #pragma db object abstract
+ struct base
+ {
+ #pragma db id auto
+ unsigned long id;
+
+ #pragma db load(lazy)
+ odb::section s1; // Empty section.
+
+ #pragma db load(lazy)
+ odb::section s2;
+
+ #pragma db section(s2)
+ int sn2;
+ };
+
+ #pragma db object abstract
+ struct interm: base
+ {
+ // Section s1 is still empty.
+
+ #pragma db section(s2)
+ std::string ss2;
+ };
+
+ #pragma db object
+ struct derived: interm
+ {
+ #pragma db section(s1)
+ int sn1;
+ };
+
+ #pragma db object
+ struct object: derived
+ {
+ object (int n = 999, const std::string& s = "xxx", bool b = false)
+ {
+ sn1 = sn2 = n;
+ ss1 = ss2 = s;
+ sb2 = b;
+ }
+
+ #pragma db section(s1)
+ std::string ss1;
+
+ #pragma db section(s2)
+ bool sb2;
+ };
+}
+
+// Test readonly and inverse section members.
+//
+#pragma db namespace table("t8_")
+namespace test8
+{
+ struct object1;
+
+ #pragma db object session
+ struct object
+ {
+ object (int n_ = 999, const std::string& s_ = "xxx", object1* p_ = 0)
+ : n (n_), sn (n_), ss (s_), sp (p_) {}
+
+ #pragma db id auto
+ unsigned long id;
+
+ int n;
+
+ #pragma db load(lazy)
+ odb::section s;
+
+ #pragma db section(s) readonly
+ int sn;
+
+ #pragma db section(s)
+ std::string ss;
+
+ #pragma db inverse(p) section(s)
+ object1* sp;
+ };
+
+ #pragma db object session
+ struct object1
+ {
+ object1 (object* p_ = 0): p (p_) {}
+ ~object1 () {delete p;}
+
+ #pragma db id auto
+ unsigned long id;
+
+ object* p;
+ };
+}
+
+// Test object without any columns to load or update.
+//
+#pragma db namespace table("t9_")
+namespace test9
+{
+ #pragma db object
+ struct object
+ {
+ object (int n_ = 999, const std::string& s_ = "xxx"): sn (n_), ss (s_) {}
+
+ #pragma db id auto
+ unsigned long id;
+
+ #pragma db load(lazy) update(manual)
+ odb::section s;
+
+ #pragma db section(s)
+ int sn;
+
+ #pragma db section(s)
+ std::string ss;
+ };
+}
+
+// Test section without any columns or containers to update.
+//
+#pragma db namespace table("t10_")
+namespace test10
+{
+ #pragma db object
+ struct object
+ {
+ object (int n_ = 999): n (n_), sn (n_) {}
+
+ #pragma db id auto
+ unsigned long id;
+
+ int n;
+
+ #pragma db load(lazy)
+ odb::section s;
+
+ #pragma db section(s) readonly
+ int sn;
+ };
+}
+
+// Test section with composite member.
+//
+#pragma db namespace table("t11_")
+namespace test11
+{
+ #pragma db value
+ struct comp
+ {
+ comp (int n_, const std::string& s_): s (s_) {v.push_back (n_);}
+
+ std::string s;
+ std::vector<int> v;
+ };
+
+ #pragma db object
+ struct object
+ {
+ object (int n_ = 999, const std::string& s_ = "xxx")
+ : n (n_), sn (n_), sc (n_, s_) {}
+
+ #pragma db id auto
+ unsigned long id;
+
+ int n;
+
+ #pragma db load(lazy)
+ odb::section s;
+
+ #pragma db section(s)
+ int sn;
+
+ #pragma db section(s)
+ comp sc;
+ };
+}
+
+// Test change state restoration on transaction rollback.
+//
+#pragma db namespace table("t12_")
+namespace test12
+{
+ #pragma db object
+ struct object
+ {
+ object (int n_ = 999, const std::string& s_ = "xxx")
+ : sn (n_), n (n_), ss (s_) {}
+
+ #pragma db id auto
+ unsigned long id;
+
+ #pragma db load(lazy) update(change)
+ odb::section s;
+
+ #pragma db section(s)
+ int sn;
+
+ int n;
+
+ #pragma db section(s)
+ std::string ss;
+ };
+}
+
+// Test section accessor/modifier.
+//
+#pragma db namespace table("t13_")
+namespace test13
+{
+ #pragma db object
+ struct object
+ {
+ object (int n_ = 999, const std::string& s_ = "xxx")
+ : n (n_), sn (n_), ss (s_) {}
+
+ #pragma db id auto
+ unsigned long id;
+
+ int n;
+
+ #pragma db section(s_)
+ int sn;
+
+ #pragma db section(s_)
+ std::string ss;
+
+ public:
+ const odb::section&
+ s () const {return s_;}
+
+ odb::section&
+ rw_s () {return s_;}
+
+ private:
+ #pragma db load(lazy) update(manual)
+ odb::section s_;
+ };
+}
+
+// Test LOB in section streaming, column re-ordering.
+//
+#pragma db namespace table("t14_")
+namespace test14
+{
+ #pragma db object
+ struct object
+ {
+ object (unsigned long id_ = 0, int n_ = 999, const std::string& s_ = "xxx")
+ : id (id_), sb (s_.begin (), s_.end ()), sn (n_), n (n_) {}
+
+ #pragma db id
+ unsigned long id;
+
+ #pragma db load(lazy)
+ odb::section s;
+
+ #pragma db section(s) type(BLOB_TYPE)
+ std::vector<char> sb; // Comes before sn.
+
+ #pragma db section(s)
+ int sn;
+
+ int n;
+ };
+}
+
+// Test sections and optimistic concurrency.
+//
+#pragma db namespace table("t15_")
+namespace test15
+{
+ #pragma db object optimistic
+ struct object
+ {
+ object (int n_ = 999, const std::string& s_ = "xxx")
+ : sn (n_), n (n_), ss (s_) {sv.push_back (n_);}
+
+ #pragma db id auto
+ unsigned long id;
+
+ #pragma db version mssql:type("ROWVERSION")
+ unsigned long long v;
+
+ #pragma db load(lazy)
+ odb::section s;
+
+ #pragma db section(s)
+ int sn;
+
+ int n;
+
+ #pragma db section(s)
+ std::string ss;
+
+ #pragma db section(s)
+ std::vector<int> sv;
+ };
+}
+
+// Test container-only sections and optimistic concurrency.
+//
+#pragma db namespace table("t16_")
+namespace test16
+{
+ #pragma db object optimistic
+ struct object
+ {
+ object (int n = 999) {sv.push_back (n);}
+
+ #pragma db id auto
+ unsigned long id;
+
+ #pragma db version // mssql:type("ROWVERSION")
+ unsigned long long v;
+
+ #pragma db load(lazy)
+ odb::section s;
+
+ #pragma db section(s)
+ std::vector<int> sv;
+ };
+}
+
+// Test reuse-inheritance, sections, and optimistic concurrency.
+//
+#pragma db namespace table("t17_")
+namespace test17
+{
+ #pragma db object optimistic sectionable abstract
+ struct root
+ {
+ #pragma db id auto
+ unsigned long id;
+
+ #pragma db version
+ unsigned long long v;
+ };
+
+ #pragma db object
+ struct base: root
+ {
+ };
+
+ #pragma db object
+ struct object: base
+ {
+ object (int n = 999): s1n (n) {s2v.push_back (n);}
+
+ #pragma db load(lazy)
+ odb::section s1;
+
+ #pragma db section(s1)
+ int s1n;
+
+ #pragma db load(lazy)
+ odb::section s2;
+
+ #pragma db section(s2)
+ std::vector<int> s2v;
+ };
+}
+
+// Test change-updated section and change-tracking container.
+//
+#pragma db namespace table("t18_")
+namespace test18
+{
+ #pragma db object
+ struct object
+ {
+ object (int n = 999): sn (n) {sv.push_back (n);}
+
+ #pragma db id auto
+ unsigned long id;
+
+ #pragma db load(lazy) update(change)
+ odb::section s;
+
+ #pragma db section(s)
+ int sn;
+
+ #pragma db section(s)
+ odb::vector<int> sv;
+ };
+}
+
+// Regression: BLOB in a value type used as a map value that is in a section.
+//
+#include <map>
+#include <vector>
+
+#pragma db namespace table("t19_")
+namespace test19
+{
+ #pragma db value
+ struct value
+ {
+ #pragma db type(BLOB_TYPE)
+ std::vector<char> b;
+ };
+
+ #pragma db object
+ struct object
+ {
+ #pragma db id auto
+ unsigned long id;
+
+ #pragma db load(lazy) update(always)
+ odb::section s;
+
+ #pragma db section(s)
+ std::map<int, value> m;
+ };
+}
+
+#endif // TEST_HXX