Common ODB Runtime Library
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
prepared-query.hxx
Go to the documentation of this file.
1 // file : odb/prepared-query.hxx
2 // copyright : Copyright (c) 2009-2013 Code Synthesis Tools CC
3 // license : GNU GPL v2; see accompanying LICENSE file
4 
5 #ifndef ODB_PREPARED_QUERY_HXX
6 #define ODB_PREPARED_QUERY_HXX
7 
8 #include <odb/pre.hxx>
9 
10 #include <odb/forward.hxx> // odb::core
11 #include <odb/traits.hxx>
12 #include <odb/result.hxx>
13 #include <odb/statement.hxx>
14 
15 #include <odb/details/export.hxx>
16 #include <odb/details/shared-ptr.hxx>
17 
18 namespace odb
19 {
20  class LIBODB_EXPORT prepared_query_impl: public details::shared_base
21  {
22  public:
23  virtual
25 
27 
28  bool cached;
30  const char* name;
31  details::shared_ptr<statement> stmt;
32  details::shared_ptr<result_impl> (*execute) (prepared_query_impl&);
33 
34  private:
36  prepared_query_impl& operator= (const prepared_query_impl&);
37 
38  // Doubly-linked list of results.
39  //
40  // prev_ == 0 means we are the first element.
41  // next_ == 0 means we are the last element.
42  // next_ == this means we are not on the list.
43  //
44  protected:
45  friend class connection;
46 
47  void
48  list_remove ();
49 
52  };
53 
54  template <typename T>
56  {
57  // Cached version.
58  //
59  explicit
60  prepared_query (prepared_query_impl* impl = 0): impl_ (impl) {}
61 
62  // Uncached version.
63  //
64  explicit
65  prepared_query (const details::shared_ptr<prepared_query_impl>& impl)
66  : impl_ (impl.get ())
67  {
68  impl_->_inc_ref ();
69  }
70 
71  result<T>
72  execute (bool cache = true)
73  {
74  typedef
75  typename result_base<T, class_traits<T>::kind>::result_impl_type
76  derived_type;
77 
78  details::shared_ptr<result_impl> ri (impl_->execute (*impl_));
79  result<T> r (
80  details::shared_ptr<derived_type> (
81  static_cast<derived_type*> (ri.release ())));
82 
83  if (cache)
84  r.cache ();
85 
86  return r;
87  }
88 
89  const char*
90  name () const
91  {
92  return impl_->name;
93  }
94 
96 
98  statement () const
99  {
100  return *impl_->stmt;
101  }
102 
104  operator unspecified_bool_type () const
105  {
106  return impl_ ? &prepared_query::impl_ : 0;
107  }
108 
109  public:
111  {
112  if (impl_ != 0 && !impl_->cached && impl_->_dec_ref ())
113  delete impl_;
114  }
115 
117  : impl_ (x.impl_)
118  {
119  if (!impl_->cached)
120  impl_->_inc_ref ();
121  }
122 
125  {
126  if (impl_ != x.impl_)
127  {
128  if (impl_ != 0 && !impl_->cached && impl_->_dec_ref ())
129  delete impl_;
130 
131  impl_ = x.impl_;
132 
133  if (!impl_->cached)
134  impl_->_inc_ref ();
135  }
136 
137  return *this;
138  }
139 
140  private:
141  // Ideally, we would just use shared_ptr to manage the impl object.
142  // However, there is a problem if the prepared query is cached on
143  // the connection and the connection is released early when the
144  // transaction is committed or rolled back. In this case, the
145  // prepared_query object might still be around pointing to impl. If
146  // this connection and the prepared query are then used by another
147  // thread while we release the impl object, then we have a race
148  // condition.
149  //
150  // To work around this problem we will simply "reference" the impl
151  // object without counting if the prepared query is cached. For
152  // transition from pointer to reference, see cache_query_() in
153  // connection.cxx.
154  //
155  // You may also observe that in order to know whether this is a
156  // cached prepared query or not, we have to read the cached data
157  // member in the impl object. This does not cause a race because,
158  // unlike the reference count, this member is immutable once set
159  // to true.
160  //
161  friend class connection;
162  prepared_query_impl* impl_;
163  };
164 
165  namespace common
166  {
167  using odb::prepared_query;
168  }
169 }
170 
171 #include <odb/post.hxx>
172 
173 #endif // ODB_PREPARED_QUERY_HXX
const char * name
Definition: prepared-query.hxx:30
Definition: statement.hxx:20
prepared_query_impl *prepared_query::* unspecified_bool_type
Definition: prepared-query.hxx:103
Definition: prepared-query.hxx:20
connection & conn
Definition: prepared-query.hxx:29
const char * name() const
Definition: prepared-query.hxx:90
void cache()
Definition: result.hxx:187
prepared_query_impl * next_
Definition: prepared-query.hxx:51
result< T > execute(bool cache=true)
Definition: prepared-query.hxx:72
Definition: result.hxx:53
Definition: prepared-query.hxx:55
odb::statement statement_type
Definition: prepared-query.hxx:95
details::shared_ptr< result_impl >(* execute)(prepared_query_impl &)
Definition: prepared-query.hxx:32
details::shared_ptr< statement > stmt
Definition: prepared-query.hxx:31
prepared_query(const prepared_query &x)
Definition: prepared-query.hxx:116
prepared_query_impl * prev_
Definition: prepared-query.hxx:50
Definition: connection.hxx:33
prepared_query & operator=(const prepared_query &x)
Definition: prepared-query.hxx:124
prepared_query(const details::shared_ptr< prepared_query_impl > &impl)
Definition: prepared-query.hxx:65
~prepared_query()
Definition: prepared-query.hxx:110
Definition: result.hxx:75
bool cached
Definition: prepared-query.hxx:28
prepared_query(prepared_query_impl *impl=0)
Definition: prepared-query.hxx:60
statement_type & statement() const
Definition: prepared-query.hxx:98