Chapter 2. Class overview
Prev |  | Next

## Chapter 2. Class overview

To work with libpqxx™, you need to be aware of at least the following classes. These are all introduced in a dedicated namespace, `pqxx`:

- `connection` represents a connection from your program to a PostgreSQL™ back-end server. Naturally your program may open multiple connections, simultaneous or not, to any number of databases.

- `work`, actually a typedef for the `transaction` class template, represents a transaction being executed in the context of a `connection`. This is a unit of work that must be completed as a whole by the database backend. If execution fails, everything done within that `transaction` is undone by the backend as if it had never happened. [2] You may execute any number of transactions consecutively on a single `connection`, but only one at a time.

  I recommend that you do not set up your own `transaction`s however, but have them managed for you by a `transactor` instead (see below).

- A `result` is a container holding the resulting data coming out of a query or command executed in a `transaction`. It behaves just like a standard C++ container as found in the STL, although its contents are not modifiable. The tuples held in the result in turn behave much like (non-modifiable) containers themselves.

I would also like to use this opportunity to plug the invaluable `esc` function, which you should use whenever you want to include a variable as a string in your SQL (eg. insert it into a text field in a table). See below.

There are other classes that may be of interest to you; these are either not essential to writing a simple program using libpqxx™, or are used in such a way that knowledge of them is not immediately necessary. You will probably want to look them up at some point when it becomes necessary to understand complex compiler warnings. Unfortunately C++ compilers are not yet very good at unravelling template-related errors and making them readable, so you may find some long and strange names when they happen.

Some of the classes you may become interested in fairly quickly are:

- `broken_connection` is an exception class that is thrown if libpqxx™ loses its connection to the back-end. It is derived from the standard C++ exception `std::runtime_error`, and can generally be treated as such.

- `sql_error` is an exception class that is thrown if a query to the back-end fails. Like `broken_connection` it is derived from `std::runtime_error`, but it also carries information about the failed query. This may be useful for debugging.

- `icursorstream` is a way of iterating over a query result using an SQL cursor. This can be useful for selectively retrieving parts of a query, or for retrieving and processing results in chunks so your program can do useful work on one chunk while the next is still coming in over a network connection. Or you may want to use this to give progress reports to the user between chunk transfers.

- `in_doubt_error` is an exception class to indicate a rare and difficult error condition. Explaining this is a bit painful, since it invalidates some of what was said above (and is commonly said in the database world).

  In theory, a "transaction" is an integral, atomic unit of work that either fails or succeeds. This is a beautiful idea, but in practice there is nothing that cannot be broken. In practice there is a tiny risk that, like Schroedinger's Cat, the transaction ends up in a third, indeterminate state. This happens when the connection to the backend is lost just when you were waiting for confirmation after completing your transaction. Your transaction may have succeeded (in fact it probably has), but if the connection is lost during just this small time window, it has no way to confirm this to your application.

  When this happens, libpqxx throws an `in_doubt_error` on the client side, which you may want to `catch` as a special case. If you do, make sure all alarm bells go off!

  See also the description for `robusttransaction`, which sacrifices some performance to minimize this risk.

- `nontransaction` is just like a regular `transaction` as far your code is concerned (except that it's not a template). The big difference is that where the latter opens a back-end transaction to keep your view and modifications of the database atomic, the former does nothing to maintain integrity. It just passes your queries directly to the database, with no enclosing transaction. This difference is expressed by the fact that the other transaction classes are derived from `dbtransaction`, an abstract class that expresses the presence of a real backend transaction, whereas `nontransaction` is not.

  This may give you better performance if your transaction does not modify the database, but if it does, may have unforeseen implications if you expect certain levels of consistency in the database--especially if other programs (perhaps even other instances of your own) may be modifying the database at the same time. You'll probably only want to use this in the following cases:

  - If you only want to read from the database, not modify it, and you know that the data is not going to be updated while your program is running.

  - If you are interested in always getting the very latest information out of your database, even if that means that you may not get a temporally consistent view of the database.

  - When making changes to the database schema; some operations may not be supported by the backend inside backend transactions.

- `robusttransaction` (a template just like `transaction`) is essentially the same as a `transaction`, ie. an atomic unit of work, except that it works harder to prevent `in_doubt_error`s from happening. This comes at the cost of some performance, which is one reason why this behaviour isn't the default. It also creates some extra tables in your database to keep track of what's happening.

  Use this class instead of plain old `transaction` if you get `in_doubt_error`s in your application--but only after thoroughly inspecting your code for bugs that might be causing the problem, or you'll only be hiding glitches that should be fixed instead.

- `tablestream` provides simple, relatively direct access to a table for either reading (through its child class `tablereader`) or writing (through child class `tablewriter`) using PostgreSQL™'s `COPY` command. This is typically much faster than issuing `SELECT` or `UPDATE` queries.

- `transaction_base` defines the common public interface for the `transaction`-like classes: `nontransaction`, `robusttransaction`, and `transaction` itself. To look up methods available in these classes, see the definition (or documentation) for `transaction_base` instead.

  You'll usually want to refer to the default `transaction` type as `work`, a typedef that means "`transaction` with default (read-committed) isolation level."

- `transactor<>` provides a framework that makes it easier for you to write correct, robust transaction code to be executed in a transaction. You should generally try to write your code as a class derived from `transactor<>`, but this is not required.

  A `transactor`-derived class may select its own "quality of service" in transactional integrity by choosing a transaction type as its template argument, e.g. `transactor<robusttransaction<> >`. The default `transactor<>` is equivalent to `transactor<work>`. Within your class you can refer to the transaction type used as `argument_type`.

- `trigger` is an instance of the Observer design pattern. Any code connected to a backend may flag an event using the PostgreSQL™ `NOTIFY` command. Frontends connected to that same backend database may be listening for an event of that name to occur. A frontend using libpqxx™ does this by registering an observer object derived from `trigger`, which will be invoked by libpqxx™ to handle the event when it occurs.

  What every programmer using triggers in PostgreSQL should know, by the way, is that trigger notifications are not delivered to your program while it is inside a back-end transaction. Nor are they sent until the notifying process has committed the transaction, if any, that the notification was done from. This makes sense from a correctness point of view (otherwise your processing of the event might get rolled back just because the transaction you're in happens to fail), but may be a little confusing to the unaware programmer.

- `result::tuple` is a nested class defined within `result`. It refers to a tuple of data within a `result` object.

- `result::field`, also nested within `result`, refers to one field within a `tuple`. A `field` contains one retrieved value such as a number or a string, and can be read into variables of various types such as `int`s or `string`s.

- `result::const_iterator` allows you to enumerate the `tuple`s in a `result` in a similar way to the iterators defined by any standard C++ container.

- `result::tuple::const_iterator` similarly iterates over the `field`s in a `tuple`.

Finally, there are also some functions that you may want to know about, that live alone in the `pqxx` namespace without being part of any class:

- `esc`, found in the transaction classes, is the canonical way to use strings in your SQL. This function escapes any quotes, backslashes, and other characters in your input string that would otherwise cause syntax errors (or worse, security holes) in your queries when included directly.

  Use these functions whenever you want to have a variable string in your SQL queries. If you don't, you'll be left with annoying bugs or possibly even security holes in your program. Use this function, use this function, use this function. Please. Make me proud.

- `to_string` knows how to render many types of values as strings. This is used internally by `libpqxx` to convert values coming out of or going into the backend, and doesn't respect locale settings.

- `from_string` is the inverse of `to_string`. It is used by eg. `result::field::to()` to convert the incoming field data (which is in text format) to the desired C++ type.

[2] Actually libpqxx™ provides three classes doing this at various levels of reliability, called `nontransaction`, `transaction`, and `robusttransaction` for no, standard, and best reliability respectively.

Prev |  | Next
Chapter 1. Why another C++ SQL library? | Home | Chapter 3. Tutorial