aboutsummaryrefslogtreecommitdiff
path: root/section/driver.cxx
blob: b01454e8bd0ef9a26b9dd9f239b7dee58bd49732 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
// file      : section/driver.cxx
// copyright : not copyrighted - public domain

#include <memory>   // std::auto_ptr
#include <iostream>

#include <odb/database.hxx>
#include <odb/transaction.hxx>

#include "database.hxx" // create_database

#include "person.hxx"
#include "person-odb.hxx"

using namespace std;
using namespace odb::core;

int
main (int argc, char* argv[])
{
  try
  {
    auto_ptr<database> db (create_database (argc, argv));

    unsigned long id;

    // Create a persistent person object.
    //
    {
      person joe ("Joe", "Dirt");
      joe.bio ("Joe Dirt is a very strange man indeed...");
      joe.nicknames ().push_back ("JD");

      // At this point the state of a section is undefined since the
      // object is transient.

      transaction t (db->begin ());
      id = db->persist (joe);
      t.commit ();

      // Now, since the object is persistent, the state of the section
      // is loaded and unchanged.
    }

    // Load the object and print what we've got. Then update the bio.
    //
    {
      transaction t (db->begin ());
      auto_ptr<person> p (db->load<person> (id));

      // Now, while the object is loaded, the section is not. If (and
      // when) we need to access the section data members, we have to
      // load them explicitly.

      cout << p->first () << " " << p->last () << endl;

      db->load (*p, p->extras_section ());

      // Now the section is loaded and unchanged.

      cout << "  " << p->bio () << endl
           << "  " << p->nicknames ().size () << " nickname(s)" << endl;

      // Update the bio.
      //
      p->bio ("Joe Dirt is a very clean man indeed...");

      // Now, the section is marked changed by the bio() modifier.
      // Because of that, the following object update will also
      // update the section.
      //
      db->update (*p);

      t.commit ();
    }

    // Add a new nickname.
    //
    {
      transaction t (db->begin ());

      auto_ptr<person> p (db->load<person> (id));
      db->load (*p, p->extras_section ());

      // Add a new nickname. The nicknames container is now marked
      // changed.
      //
      p->nicknames ().push_back ("Squeaky Clean");

      // While the section hasn't been marked as changed, a change-
      // tracking container that belongs to it has been. As a result,
      // the following object update call will automatically mark the
      // section as changed and update its state in the database.
      //
      db->update (*p);

      t.commit ();
    }

    // We can also update just the section if we know the rest of
    // the object hasn't changed.
    //
    {
      transaction t (db->begin ());

      auto_ptr<person> p (db->load<person> (id));
      db->load (*p, p->extras_section ());

      p->nicknames ().push_back ("Dirty Joe");
      db->update (*p, p->extras_section ());

      t.commit ();
    }

    // Load and print the updated object.
    //
    {
      transaction t (db->begin ());
      auto_ptr<person> p (db->load<person> (id));
      db->load (*p, p->extras_section ());
      t.commit ();

      cout << p->first () << " " << p->last () << endl
           << "  " << p->bio () << endl
           << "  " << p->nicknames ().size () << " nickname(s)" << endl;
    }
  }
  catch (const odb::exception& e)
  {
    cerr << e.what () << endl;
    return 1;
  }
}