Connection.h
1/* Copyright (C) 2006-2026 by Tommi Maekitalo
2 Copyright (C) 2006-2026 by Marc Boris Duerner
3 SPDX-License-Identifier: LGPL-2.1-or-later WITH mif-exception
4*/
5
6#ifndef PT_DB_CONNECTION_H
7#define PT_DB_CONNECTION_H
8
9#include <Pt/Db/Api.h>
10#include <Pt/SmartPtr.h>
11#include <Pt/Db/IConnection.h>
12#include <Pt/Db/Statement.h>
13#include <Pt/Db/Result.h>
14#include <Pt/Db/Row.h>
15#include <Pt/Db/Value.h>
16#include <Pt/Signal.h>
17#include <string>
18
19#if __cplusplus >= 202002L
20#include <Pt/Slot.h>
21#include <Pt/Coroutine.h>
22#endif
23
24namespace Pt {
25
26namespace System {
27class EventLoop;
28}
29
30namespace Db {
31
32class Result;
33class Row;
34class Value;
35class Statement;
36class Transaction;
37
38#if __cplusplus >= 202002L
39class AsyncOpen;
40class AsyncClose;
41class AsyncExecute;
42class AsyncSelect;
43class AsyncPing;
44class ConnectionAwaiter;
45#endif
46
96class PT_DB_API Connection
97{
98 public:
99 typedef std::size_t size_type;
100
107 explicit Connection(const std::string& driver);
108
111 explicit Connection(IConnection* conn);
112
116
120
123 void cancel();
124
127 bool ping();
128
131 void beginPing();
132
137 bool endPing();
138
142
148 long long lastInsertId(const std::string& name = std::string());
149
152 bool isIdle() const;
153
156 bool hasTransaction() const;
157
158 public:
161 bool isOpen() const;
162
165 bool operator!() const;
166
169 void open(const std::string& connStr);
170
173 void close();
174
180
183 void endClose();
184
188
191 void beginOpen(const std::string& connStr);
192
195 void endOpen();
196
200
201 public:
204 size_type execute(const std::string& query);
205
208 void beginExecute(const std::string& sql);
209
214 size_type endExecute();
215
219
220 public:
223 Result select(const std::string& query);
224
227 void beginSelect(const std::string& sql);
228
234
238
239 public:
242 Statement prepare(const std::string& query);
243
246 Statement prepareCached(const std::string& query);
247
251
252 public:
255 void beginPrepare(const std::string& query);
256
262
266
269 void beginPrepareCached(const std::string& query);
270
276
280
281 private:
282 friend class Transaction;
283
284#if __cplusplus >= 202002L
285 friend class ConnectionAwaiter;
286
287 void attachAwaiter(ConnectionAwaiter& awaiter);
288
289 void detachAwaiter(ConnectionAwaiter& awaiter);
290#endif
291
292 void startTransaction(const char* sql = nullptr);
293
294 void commitTransaction(const char* sql = nullptr);
295
296 void rollbackTransaction(const char* sql = nullptr);
297
298 void beginStartTransaction(Transaction& txn, const char* sql);
299
300 void endStartTransaction();
301
302 void beginCommitTransaction(Transaction& txn, const char* sql);
303
304 void endCommitTransaction();
305
306 void beginRollbackTransaction(Transaction& txn, const char* sql);
307
308 void endRollbackTransaction();
309
310#if __cplusplus >= 202002L
311 public:
314 AsyncOpen openAsync(const std::string& connStr);
315
319
324 AsyncExecute executeAsync(const std::string& sql);
325
330 AsyncSelect selectAsync(const std::string& sql);
331
337#endif
338
339 public:
343
346 const IConnection* impl() const;
347
348 private:
349 Connection(const Connection&) = delete;
350
351 Connection& operator=(const Connection&) = delete;
352
353 typedef SmartPtr<IConnection,
354 InternalRefCounted<IConnection> > ConnectionImplPtr;
355
356 ConnectionImplPtr _connection;
357
358#if __cplusplus >= 202002L
359 ConnectionAwaiter* _awaiter = nullptr;
360#endif
361};
362
363#if __cplusplus >= 202002L
364
369class ConnectionAwaiter : public Pt::Awaiter
370 , public Pt::Connectable
371{
372 public:
373 explicit ConnectionAwaiter(Connection& conn)
374 : _conn(&conn)
375 {
376 _conn->attachAwaiter(*this); ;
377 }
378
379 ~ConnectionAwaiter()
380 {
381 if(_conn)
382 {
383 _conn->cancel();
384 _conn->detachAwaiter(*this);
385 _conn = nullptr;
386 }
387 }
388
389 virtual void onDetach()
390 {
391 if(_conn)
392 _conn->detachAwaiter(*this);
393
394 _conn = nullptr;
395 _handle = nullptr;
396 }
397
398 protected:
399 Connection& connection()
400 {
401 if( ! _conn )
402 throw std::logic_error("invalid connection");
403
404 return *_conn;
405 }
406
407 void onCancel() override
408 {
409 if(_conn)
410 _conn->cancel();
411 }
412
413 private:
414 Connection* _conn;
415};
416
421class AsyncOpen : public ConnectionAwaiter
422{
423 public:
424 AsyncOpen(Connection& conn, const std::string& connStr)
425 : ConnectionAwaiter(conn)
426 , _connStr(connStr)
427 {}
428
429 void await_resume()
430 {
431 connection().endOpen();
432 }
433
434 private:
435 void onBegin() override
436 {
437 Connection& conn = connection();
438 conn.openFinished() += slot(*this, &AsyncOpen::setReady);
439 conn.beginOpen(_connStr);
440 }
441
442 std::string _connStr;
443};
444
449class AsyncClose : public ConnectionAwaiter
450{
451 public:
452 AsyncClose(Connection& conn)
453 : ConnectionAwaiter(conn)
454 {}
455
456 void await_resume()
457 { connection().endClose(); }
458
459 private:
460 void onBegin() override
461 {
462 Connection& conn = connection();
463 conn.closeFinished() += slot(*this, &AsyncClose::setReady);
464 conn.beginClose();
465 }
466};
467
468
473class AsyncExecute : public ConnectionAwaiter
474{
475 public:
476 AsyncExecute(Connection& conn, const std::string& sql)
477 : ConnectionAwaiter(conn)
478 , _sql(sql)
479 {}
480
481 Connection::size_type await_resume()
482 { return connection().endExecute(); }
483
484 private:
485 void onBegin() override
486 {
487 Connection& conn = connection();
489 conn.beginExecute(_sql);
490 }
491
492 std::string _sql;
493};
494
495
500class AsyncSelect : public ConnectionAwaiter
501{
502 public:
503 AsyncSelect(Connection& conn, const std::string& sql)
504 : ConnectionAwaiter(conn)
505 , _sql(sql)
506 {}
507
508 Result await_resume()
509 { return connection().endSelect(); }
510
511 private:
512 void onBegin() override
513 {
514 Connection& conn = connection();
515 conn.selectFinished() += slot(*this, &AsyncSelect::setReady);
516 conn.beginSelect(_sql);
517 }
518
519 std::string _sql;
520};
521
522
527class AsyncPing : public ConnectionAwaiter
528{
529 public:
530 AsyncPing(Connection& conn)
531 : ConnectionAwaiter(conn)
532 {}
533
534 bool await_resume()
535 {
536 return connection().endPing();
537 }
538
539 private:
540 void onBegin() override
541 {
542 Connection& conn = connection();
543 conn.pingFinished() += slot(*this, &AsyncPing::setReady);
544 conn.beginPing();
545 }
546};
547
548#endif // __cplusplus >= 202002L
549
550} // namespace Db
551
552} // namespace Pt
553
554#endif // PT_DB_CONNECTION_H
Provides the base class for I/O-driven co_await-able operations.
Definition Coroutine.h:126
void setReady()
Resumes the waiting coroutine.
Definition Coroutine.h:162
Connection Management for Signal and Slot Objects.
Definition Connectable.h:50
Awaitable for asynchronous close.
Definition Connection.h:450
Awaitable for asynchronous execute.
Definition Connection.h:474
Awaitable for asynchronous open.
Definition Connection.h:422
Awaitable for asynchronous ping.
Definition Connection.h:528
Awaitable for asynchronous select.
Definition Connection.h:501
void onCancel() override
Aborts the in-flight operation.
Definition Connection.h:407
Database session for a registered driver.
Definition Connection.h:97
bool isOpen() const
Returns true if the database is open.
void beginPrepareCached(const std::string &query)
Starts asynchronous compile and cache of query.
void cancel()
Cancels any pending async operation.
Pt::Signal & selectFinished()
Signal emitted when an asynchronous select completes.
void beginExecute(const std::string &sql)
Starts asynchronous execution of sql.
long long lastInsertId(const std::string &name=std::string())
Returns the last generated row id.
void setActive(Pt::System::EventLoop &loop)
Attaches loop for asynchronous operations.
bool ping()
Returns true if the backend still answers.
const IConnection * impl() const
Returns the backend implementation.
Pt::Signal & prepareCachedFinished()
Signal emitted when asynchronous prepareCached completes.
Pt::Signal & openFinished()
Signal emitted when an asynchronous open completes.
void endOpen()
Completes an asynchronous open.
Result select(const std::string &query)
Executes query and returns a buffered result.
Result endSelect()
Completes an asynchronous select.
void beginPrepare(const std::string &query)
Starts asynchronous compile of query.
bool endPing()
Completes an asynchronous ping.
Pt::Signal & pingFinished()
Signal emitted when an asynchronous ping completes.
void beginOpen(const std::string &connStr)
Starts an asynchronous open with connStr.
Pt::Signal & executeFinished()
Signal emitted when asynchronous execution completes.
AsyncExecute executeAsync(const std::string &sql)
Returns an awaitable that executes sql.
void close()
Closes the database connection.
bool operator!() const
Returns true if the database is not open.
AsyncOpen openAsync(const std::string &connStr)
Returns an awaitable that opens the database with connStr.
~Connection()
Cancels a pending async operation and destroys the connection.
Statement endPrepareCached()
Completes asynchronous prepareCached.
bool isIdle() const
Returns true if no asynchronous operation is pending.
Connection(IConnection *conn)
Takes ownership of the backend conn.
bool hasTransaction() const
Returns true if a transaction is active.
Pt::Signal & prepareFinished()
Signal emitted when asynchronous prepare completes.
void open(const std::string &connStr)
Opens the database with connStr.
size_type endExecute()
Completes asynchronous execution.
Statement endPrepare()
Completes asynchronous compile.
size_type execute(const std::string &query)
Executes query and returns the number of rows changed.
Connection(const std::string &driver)
Creates a connection for driver.
Pt::Signal & closeFinished()
Signal emitted when an asynchronous close completes.
void clearStatementCache()
Clears the prepared-statement cache.
IConnection * impl()
Returns the backend implementation.
void beginClose()
Starts an asynchronous close.
void beginPing()
Starts an asynchronous ping.
AsyncSelect selectAsync(const std::string &sql)
Returns an awaitable that selects sql.
AsyncClose closeAsync()
Returns an awaitable that closes the database.
Statement prepare(const std::string &query)
Compiles query into a prepared statement.
Statement prepareCached(const std::string &query)
Compiles query and caches the prepared statement.
void endClose()
Completes an asynchronous close.
AsyncPing pingAsync()
Returns an awaitable that pings the database.
void beginSelect(const std::string &sql)
Starts an asynchronous select of sql.
Database connection backend.
Definition IConnection.h:44
Buffered query result with random-access rows.
Definition Result.h:42
Prepared SQL statement with named host variables.
Definition Statement.h:65
Multicast Signal to call multiple slots.
Definition Signal.h:190
ConstMethodSlot< R, ClassT, As... > slot(ClassT &object, R(BaseT::*method)(As...) const)
Returns a slot object for the given object/member pair.
Definition ConstMethod.h:172
Policy based smart pointer.
Definition SmartPtr.h:462
Event loop of a thread or process.
Definition EventLoop.h:83
Portable SQL database access.
System programming
Definition Connection.h:26
Core module.
Definition Allocator.h:33