Qore Programming Language  0.9.4.6
qore_ds_private.h
1 /* -*- mode: c++; indent-tabs-mode: nil -*- */
2 /*
3  qore_ds_private.h
4 
5  Qore Programming Language
6 
7  Copyright (C) 2003 - 2020 Qore Technologies, s.r.o.
8 
9  The Datasource class provides the low-level interface to Qore DBI drivers.
10 
11  Permission is hereby granted, free of charge, to any person obtaining a
12  copy of this software and associated documentation files (the "Software"),
13  to deal in the Software without restriction, including without limitation
14  the rights to use, copy, modify, merge, publish, distribute, sublicense,
15  and/or sell copies of the Software, and to permit persons to whom the
16  Software is furnished to do so, subject to the following conditions:
17 
18  The above copyright notice and this permission notice shall be included in
19  all copies or substantial portions of the Software.
20 
21  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
27  DEALINGS IN THE SOFTWARE.
28 
29  Note that the Qore library is released under a choice of three open-source
30  licenses: MIT (as above), LGPL 2+, or GPL 2+; see README-LICENSE for more
31  information.
32 */
33 
34 #ifndef _QORE_DS_PRIVATE_H
35 
36 #define _QORE_DS_PRIVATE_H
37 
38 #include "qore/intern/qore_dbi_private.h"
39 #include "qore/intern/QoreSQLStatement.h"
40 #include "qore/intern/DatasourceStatementHelper.h"
41 
42 #include <set>
43 
44 typedef std::set<QoreSQLStatement*> stmt_set_t;
45 
46 hashdecl qore_ds_private {
47  // mutex
48  mutable QoreThreadLock m;
49 
50  Datasource* ds;
51 
52  bool in_transaction;
53  bool active_transaction;
54  bool isopen;
55  bool autocommit;
56  bool connection_aborted;
57  bool keep_lock = false;
58 
59  mutable DBIDriver* dsl;
60  const QoreEncoding* qorecharset;
61  void* private_data; // driver private data per connection
62 
63  // for pending connection values
64  std::string p_username,
65  p_password,
66  p_dbname,
67  p_db_encoding, // database-specific name for the encoding for the connection
68  p_hostname;
69  int p_port; // pending port number (0 = default port)
70 
71  // actual connection values set by init() before the datasource is opened
72  std::string username,
73  password,
74  db_encoding, // database-specific name for the encoding for the connection
75  dbname,
76  hostname;
77  int port; // port number (0 = default port)
78 
79  // options per connection
80  QoreHashNode* opt;
81  // DBI event queue
82  Queue* event_queue;
83  // DBI Event queue argument
84  QoreValue event_arg;
85 
86  // interface for the parent class
87  DatasourceStatementHelper* dsh;
88 
89  DLLLOCAL qore_ds_private(Datasource* n_ds, DBIDriver* ndsl, DatasourceStatementHelper* dsh) : ds(n_ds), in_transaction(false), active_transaction(false), isopen(false), autocommit(false), connection_aborted(false), dsl(ndsl), qorecharset(QCS_DEFAULT), private_data(nullptr), p_port(0), port(0), opt(new QoreHashNode(autoTypeInfo)), event_queue(nullptr), dsh(dsh) {
90  }
91 
92  DLLLOCAL qore_ds_private(const qore_ds_private& old, Datasource* n_ds, DatasourceStatementHelper* dsh) :
93  ds(n_ds), in_transaction(false), active_transaction(false), isopen(false),
94  autocommit(old.autocommit), connection_aborted(false), dsl(old.dsl),
95  qorecharset(QCS_DEFAULT), private_data(0),
96  p_username(old.p_username), p_password(old.p_password),
97  p_dbname(old.p_dbname), p_db_encoding(old.p_db_encoding),
98  p_hostname(old.p_hostname), p_port(old.p_port),
99  port(0),
100  //opt(old.opt->copy()) {
101  opt(old.getCurrentOptionHash(true)),
102  event_queue(old.event_queue ? old.event_queue->queueRefSelf() : nullptr),
103  event_arg(old.event_arg.refSelf()),
104  dsh(dsh) {
105  }
106 
107  DLLLOCAL ~qore_ds_private() {
108  assert(!private_data);
109  assert(stmt_set.empty());
110  ExceptionSink xsink;
111  if (opt)
112  opt->deref(&xsink);
113  event_arg.discard(&xsink);
114  if (event_queue)
115  event_queue->deref(&xsink);
116  }
117 
118  DLLLOCAL void setPendingConnectionValues(const qore_ds_private *other) {
119  p_username = other->p_username;
120  p_password = other->p_password;
121  p_dbname = other->p_dbname;
122  p_hostname = other->p_hostname;
123  p_db_encoding = other->p_db_encoding;
124  autocommit = other->autocommit;
125  p_port = other->p_port;
126  }
127 
128  DLLLOCAL void setConnectionValues() {
129  dbname = p_dbname;
130  username = p_username;
131  password = p_password;
132  hostname = p_hostname;
133  db_encoding = p_db_encoding;
134  port = p_port;
135  }
136 
137  DLLLOCAL void statementExecuted(int rc);
138 
139  DLLLOCAL void copyOptions(const Datasource* ods);
140 
141  DLLLOCAL void setOption(const char* name, QoreValue v, ExceptionSink* xsink) {
142  opt->setKeyValue(name, v.refSelf(), xsink);
143  }
144 
145  DLLLOCAL QoreHashNode* getOptionHash() const {
146  return private_data ? qore_dbi_private::get(*dsl)->getOptionHash(ds) : opt->hashRefSelf();
147  }
148 
149  DLLLOCAL QoreHashNode* getCurrentOptionHash(bool ensure_hash = false) const;
150 
151  DLLLOCAL QoreHashNode* getConfigHash() const;
152 
153  DLLLOCAL QoreStringNode* getConfigString() const;
154 
155  DLLLOCAL void setEventQueue(Queue* q, QoreValue arg, ExceptionSink* xsink) {
156  if (event_queue)
157  event_queue->deref(xsink);
158  event_arg.discard(xsink);
159  event_queue = q;
160  event_arg = arg;
161  }
162 
163  DLLLOCAL QoreHashNode* getEventQueueHash(Queue*& q, int event_code) const {
164  q = event_queue;
165  if (!q)
166  return nullptr;
167  QoreHashNode* h = new QoreHashNode(autoTypeInfo);
168  if (!username.empty())
169  h->setKeyValue("user", new QoreStringNode(username), 0);
170  if (!dbname.empty())
171  h->setKeyValue("db", new QoreStringNode(dbname), 0);
172  h->setKeyValue("eventtype", event_code, 0);
173  if (event_arg)
174  h->setKeyValue("arg", event_arg.refSelf(), 0);
175  return h;
176  }
177 
178  DLLLOCAL void addStatement(QoreSQLStatement* stmt) {
179  AutoLocker al(m);
180  assert(stmt_set.find(stmt) == stmt_set.end());
181  stmt_set.insert(stmt);
182  }
183 
184  DLLLOCAL void removeStatement(QoreSQLStatement* stmt) {
185  AutoLocker al(m);
186  stmt_set_t::iterator i = stmt_set.find(stmt);
187  if (i != stmt_set.end())
188  stmt_set.erase(i);
189  }
190 
191  DLLLOCAL void connectionAborted(ExceptionSink* xsink) {
192  assert(isopen);
193  // close all statements and clear private data, leave datasource allocated
194  transactionDone(false, true, xsink);
195  // mark connection aborted
196  connection_aborted = true;
197  // close the datasource
198  close();
199  }
200 
201  DLLLOCAL void connectionLost(ExceptionSink* xsink) {
202  assert(isopen);
203  // close statements but do not clear datasource or statements in the datasource
204  transactionDone(false, false, xsink);
205  }
206 
207  DLLLOCAL void connectionRecovered(ExceptionSink* xsink) {
208  assert(isopen);
209  // close all statements, clear private data, leave datasource allocation
210  transactionDone(false, true, xsink);
211  }
212 
213  // @param clear if true then clears the statements' datasource ptrs and the stmt_set, if false, does not
214  DLLLOCAL void transactionDone(bool clear, bool close, ExceptionSink* xsink) {
215  AutoLocker al(m);
216  for (stmt_set_t::iterator i = stmt_set.begin(), e = stmt_set.end(); i != e; ++i) {
217  //printd(5, "qore_ds_private::transactionDone() this: %p stmt: %p clear: %d close: %d\n", this, *i, clear, close);
218  (*i)->transactionDone(clear, close, xsink);
219  }
220  if (clear)
221  stmt_set.clear();
222  }
223 
224  DLLLOCAL int commitIntern(ExceptionSink* xsink) {
225  //printd(5, "qore_ds_private::commitIntern() this: %p in_transaction: %d active_transaction: %d\n", this, in_transaction, active_transaction);
226  assert(isopen);
227  in_transaction = false;
228  active_transaction = false;
229  return qore_dbi_private::get(*dsl)->commit(ds, xsink);
230  }
231 
232  DLLLOCAL int rollbackIntern(ExceptionSink* xsink) {
233  //printd(5, "qore_ds_private::rollbackIntern() this: %p in_transaction: %d active_transaction: %d\n", this, in_transaction, active_transaction);
234  assert(isopen);
235  in_transaction = false;
236  active_transaction = false;
237  return qore_dbi_private::get(*dsl)->rollback(ds, xsink);
238  }
239 
240  DLLLOCAL int commit(ExceptionSink* xsink) {
241  int rc = commitIntern(xsink);
242  transactionDone(true, true, xsink);
243  return rc;
244  }
245 
246  DLLLOCAL int rollback(ExceptionSink* xsink) {
247  int rc = rollbackIntern(xsink);
248  transactionDone(true, true, xsink);
249  return rc;
250  }
251 
252  DLLLOCAL int close() {
253  if (isopen) {
254  //printd(5, "qore_ds_private::close() this: %p in_transaction: %d active_transaction: %d\n", this, in_transaction, active_transaction);
255  qore_dbi_private::get(*dsl)->close(ds);
256  isopen = false;
257  in_transaction = false;
258  active_transaction = false;
259  return 0;
260  }
261  return -1;
262  }
263 
264  DLLLOCAL void setStatementKeepLock(QoreSQLStatement* stmt) {
265  assert(!keep_lock);
266  keep_lock = true;
267  if (!in_transaction)
268  in_transaction = true;
269  if (!active_transaction)
270  active_transaction = true;
271 
272  addStatement(stmt);
273  }
274 
275  DLLLOCAL bool keepLock() {
276  bool rv = keep_lock;
277  if (keep_lock)
278  keep_lock = false;
279  return rv;
280  }
281 
282  DLLLOCAL static qore_ds_private* get(Datasource& ds) {
283  return ds.priv;
284  }
285 
286 private:
287  // set of active SQLStatements on this datasource
288  stmt_set_t stmt_set;
289 };
290 
291 #endif
defines string encoding functions in Qore
Definition: QoreEncoding.h:83
This is the hash or associative list container type in Qore, dynamically allocated only...
Definition: QoreHashNode.h:50
DLLEXPORT const QoreEncoding * QCS_DEFAULT
the default encoding for the Qore library
DLLEXPORT int setKeyValue(const char *key, QoreValue value, ExceptionSink *xsink)
sets the value of "key" to "value"
this class provides the internal link to the database driver for Qore&#39;s DBI layer ...
Definition: DBI.h:350
DLLEXPORT QoreHashNode * hashRefSelf() const
returns "this" with an incremented reference count
Qore&#39;s string value type, reference counted, dynamically-allocated only.
Definition: QoreStringNode.h:50
provides a safe and exception-safe way to hold locks in Qore, only to be used on the stack...
Definition: QoreThreadLock.h:128
the base class for accessing databases in Qore through a Qore DBI driver
Definition: Datasource.h:55
The main value class in Qore, designed to be passed by value.
Definition: QoreValue.h:262
container for holding Qore-language exception information and also for registering a "thread_exit" ca...
Definition: ExceptionSink.h:46
DLLEXPORT void deref(ExceptionSink *xsink)
decrements the reference count and calls derefImpl() if there_can_be_only_one is false, otherwise does nothing
provides a mutually-exclusive thread lock
Definition: QoreThreadLock.h:47
DLLEXPORT QoreValue refSelf() const
references the contained value if type == QV_Node, returns itself
DLLEXPORT void discard(ExceptionSink *xsink)
dereferences any contained AbstractQoreNode pointer and sets to 0; does not modify other values ...