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 void onDetach()
390 {
391 _conn = nullptr;
392 _handle = nullptr;
393 }
394
395 protected:
396 Connection& connection()
397 {
398 if( ! _conn )
399 throw std::logic_error("invalid connection");
400
401 return *_conn;
402 }
403
404 void onCancel() override
405 {
406 if(_conn)
407 _conn->cancel();
408 }
409
410 private:
411 Connection* _conn;
412};
413
418class AsyncOpen : public ConnectionAwaiter
419{
420 public:
421 AsyncOpen(Connection& conn, const std::string& connStr)
422 : ConnectionAwaiter(conn)
423 , _connStr(connStr)
424 {}
425
426 void await_resume()
427 {
428 connection().endOpen();
429 }
430
431 private:
432 void onBegin() override
433 {
434 Connection& conn = connection();
435 conn.openFinished() += slot(*this, &AsyncOpen::setReady);
436 conn.beginOpen(_connStr);
437 }
438
439 std::string _connStr;
440};
441
446class AsyncClose : public ConnectionAwaiter
447{
448 public:
449 AsyncClose(Connection& conn)
450 : ConnectionAwaiter(conn)
451 {}
452
453 void await_resume()
454 { connection().endClose(); }
455
456 private:
457 void onBegin() override
458 {
459 Connection& conn = connection();
460 conn.closeFinished() += slot(*this, &AsyncClose::setReady);
461 conn.beginClose();
462 }
463};
464
465
470class AsyncExecute : public ConnectionAwaiter
471{
472 public:
473 AsyncExecute(Connection& conn, const std::string& sql)
474 : ConnectionAwaiter(conn)
475 , _sql(sql)
476 {}
477
478 Connection::size_type await_resume()
479 { return connection().endExecute(); }
480
481 private:
482 void onBegin() override
483 {
484 Connection& conn = connection();
486 conn.beginExecute(_sql);
487 }
488
489 std::string _sql;
490};
491
492
497class AsyncSelect : public ConnectionAwaiter
498{
499 public:
500 AsyncSelect(Connection& conn, const std::string& sql)
501 : ConnectionAwaiter(conn)
502 , _sql(sql)
503 {}
504
505 Result await_resume()
506 { return connection().endSelect(); }
507
508 private:
509 void onBegin() override
510 {
511 Connection& conn = connection();
512 conn.selectFinished() += slot(*this, &AsyncSelect::setReady);
513 conn.beginSelect(_sql);
514 }
515
516 std::string _sql;
517};
518
519
524class AsyncPing : public ConnectionAwaiter
525{
526 public:
527 AsyncPing(Connection& conn)
528 : ConnectionAwaiter(conn)
529 {}
530
531 bool await_resume()
532 {
533 return connection().endPing();
534 }
535
536 private:
537 void onBegin() override
538 {
539 Connection& conn = connection();
540 conn.pingFinished() += slot(*this, &AsyncPing::setReady);
541 conn.beginPing();
542 }
543};
544
545#endif // __cplusplus >= 202002L
546
547} // namespace Db
548
549} // namespace Pt
550
551#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:447
Awaitable for asynchronous execute.
Definition Connection.h:471
Awaitable for asynchronous open.
Definition Connection.h:419
Awaitable for asynchronous ping.
Definition Connection.h:525
Awaitable for asynchronous select.
Definition Connection.h:498
void onCancel() override
Aborts the in-flight operation.
Definition Connection.h:404
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