Qore Programming Language 1.19.1
Loading...
Searching...
No Matches
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 - 2023 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
44typedef std::set<QoreSQLStatement*> stmt_set_t;
45
46hashdecl qore_ds_private {
47 // mutex
48 mutable QoreThreadLock m;
49
50 Datasource* ds;
51
52 bool in_transaction = false;
53 bool active_transaction = false;
54 bool isopen = false;
55 bool autocommit = false;
56 bool connection_aborted = false;
57 bool keep_lock = false;
58
59 mutable DBIDriver* dsl;
60 const QoreEncoding* qorecharset = QCS_DEFAULT;
61 void* private_data = nullptr; // 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 = 0; // 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 = 0; // port number (0 = default port)
78
79 // options per connection
80 QoreHashNode* opt;
81 // DBI event queue
82 Queue* event_queue = nullptr;
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),
90 dsl(ndsl), opt(new QoreHashNode(autoTypeInfo)), dsh(dsh) {
91 }
92
93 DLLLOCAL qore_ds_private(const qore_ds_private& old, Datasource* n_ds, DatasourceStatementHelper* dsh) :
94 ds(n_ds), autocommit(old.autocommit), dsl(old.dsl),
95 p_username(old.p_username), p_password(old.p_password),
96 p_dbname(old.p_dbname), p_db_encoding(old.p_db_encoding),
97 p_hostname(old.p_hostname), p_port(old.p_port),
98 //opt(old.opt->copy()) {
99 opt(old.getCurrentOptionHash(true)),
100 event_queue(old.event_queue ? old.event_queue->queueRefSelf() : nullptr),
101 event_arg(old.event_arg.refSelf()),
102 dsh(dsh) {
103 }
104
105 DLLLOCAL ~qore_ds_private() {
106 assert(!private_data);
107 assert(stmt_set.empty());
108 ExceptionSink xsink;
109 if (opt) {
110 opt->deref(&xsink);
111 }
112 event_arg.discard(&xsink);
113 if (event_queue) {
114 event_queue->deref(&xsink);
115 }
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#ifdef DEBUG
203 // issue #4117: get backtrace if connectionLost() called while the connection is closed
204 if (!isopen) {
205 qore_machine_backtrace();
206 }
207#endif
208 assert(isopen);
209 // close statements but do not clear datasource or statements in the datasource
210 transactionDone(false, false, xsink);
211 }
212
213 DLLLOCAL void connectionRecovered(ExceptionSink* xsink) {
214 assert(isopen);
215 // close all statements, clear private data, leave datasource allocation
216 transactionDone(false, true, xsink);
217 }
218
219 // @param clear if true then clears the statements' datasource ptrs and the stmt_set, if false, does not
220 DLLLOCAL void transactionDone(bool clear, bool close, ExceptionSink* xsink) {
221 AutoLocker al(m);
222 for (stmt_set_t::iterator i = stmt_set.begin(), e = stmt_set.end(); i != e; ++i) {
223 //printd(5, "qore_ds_private::transactionDone() this: %p stmt: %p clear: %d close: %d\n", this, *i, clear, close);
224 (*i)->transactionDone(clear, close, xsink);
225 }
226 if (clear)
227 stmt_set.clear();
228 }
229
230 DLLLOCAL int commitIntern(ExceptionSink* xsink) {
231 //printd(5, "qore_ds_private::commitIntern() this: %p in_transaction: %d active_transaction: %d\n", this, in_transaction, active_transaction);
232 assert(isopen);
233 in_transaction = false;
234 active_transaction = false;
235 return qore_dbi_private::get(*dsl)->commit(ds, xsink);
236 }
237
238 DLLLOCAL int rollbackIntern(ExceptionSink* xsink) {
239 //printd(5, "qore_ds_private::rollbackIntern() this: %p in_transaction: %d active_transaction: %d\n", this, in_transaction, active_transaction);
240 assert(isopen);
241 in_transaction = false;
242 active_transaction = false;
243 return qore_dbi_private::get(*dsl)->rollback(ds, xsink);
244 }
245
246 DLLLOCAL int commit(ExceptionSink* xsink) {
247 int rc = commitIntern(xsink);
248 transactionDone(true, true, xsink);
249 return rc;
250 }
251
252 DLLLOCAL int rollback(ExceptionSink* xsink) {
253 int rc = rollbackIntern(xsink);
254 transactionDone(true, true, xsink);
255 return rc;
256 }
257
258 DLLLOCAL int close() {
259 if (isopen) {
260 //printd(5, "qore_ds_private::close() this: %p in_transaction: %d active_transaction: %d\n", this, in_transaction, active_transaction);
261 qore_dbi_private::get(*dsl)->close(ds);
262 isopen = false;
263 in_transaction = false;
264 active_transaction = false;
265 return 0;
266 }
267 return -1;
268 }
269
270 DLLLOCAL void setStatementKeepLock(QoreSQLStatement* stmt) {
271 assert(!keep_lock);
272 keep_lock = true;
273 if (!in_transaction)
274 in_transaction = true;
275 if (!active_transaction)
276 active_transaction = true;
277
278 addStatement(stmt);
279 }
280
281 DLLLOCAL bool keepLock() {
282 bool rv = keep_lock;
283 if (keep_lock)
284 keep_lock = false;
285 return rv;
286 }
287
288 DLLLOCAL static qore_ds_private* get(Datasource& ds) {
289 return ds.priv;
290 }
291
292private:
293 // set of active SQLStatements on this datasource
294 stmt_set_t stmt_set;
295};
296
297#endif
DLLEXPORT const QoreEncoding * QCS_DEFAULT
the default encoding for the Qore library
DLLEXPORT void deref(ExceptionSink *xsink)
decrements the reference count and calls derefImpl() if there_can_be_only_one is false,...
provides a safe and exception-safe way to hold locks in Qore, only to be used on the stack,...
Definition: QoreThreadLock.h:136
this class provides the internal link to the database driver for Qore's DBI layer
Definition: DBI.h:367
the base class for accessing databases in Qore through a Qore DBI driver
Definition: Datasource.h:55
container for holding Qore-language exception information and also for registering a "thread_exit" ca...
Definition: ExceptionSink.h:50
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 int setKeyValue(const char *key, QoreValue value, ExceptionSink *xsink)
sets the value of "key" to "value"
DLLEXPORT QoreHashNode * hashRefSelf() const
returns "this" with an incremented reference count
Qore's string value type, reference counted, dynamically-allocated only.
Definition: QoreStringNode.h:50
provides a mutually-exclusive thread lock
Definition: QoreThreadLock.h:49
The main value class in Qore, designed to be passed by value.
Definition: QoreValue.h:276
DLLEXPORT void discard(ExceptionSink *xsink)
dereferences any contained AbstractQoreNode pointer and sets to 0; does not modify other values
DLLEXPORT QoreValue refSelf() const
references the contained value if type == QV_Node, returns itself