Skip to contents

A database connection manager that handles connections to various database systems including Microsoft SQL Server and PostgreSQL. This class provides connection management, authentication, and automatic reconnection.

Details

The DBConnection_v9 class holds the database connection logic and provides a consistent interface to different database systems. It supports both trusted connections and user/password authentication. It handles connection failures, and it reconnects automatically.

Key features:

  • Support for multiple database systems (SQL Server, PostgreSQL).

  • Automatic connection management with retry logic.

  • Secure credential handling.

  • Connection status monitoring.

  • Graceful error handling and recovery.

  • A connection is never shared with another process.

Fork safety

A connection belongs to the process that opened it. After a fork, the child holds a copy of this object and a copy of the parent's connection. Both processes then use one socket. PostgreSQL can return wrong results and report no error. Measured against the NorSySS server on 2026-08-14. A child asked for select 4 and read 3. The parent asked for select 999 and read 2. DBI::dbIsValid() reports TRUE on such a handle, so nothing else detects it.

This class records the process that opens each connection. It drops any connection whose recorded process is not the current one. is_connected() then returns FALSE, connection returns NULL, and autoconnection opens a new connection for the current process. disconnect() closes nothing, because the handle belongs to the other process.

The object never closes an inherited handle, and it keeps a reference to it. Both parts are needed. A close, by DBI::dbDisconnect() or by the garbage collector, would close the other process's socket.

PostgreSQL loads

DBTable_v9$insert_data(), $upsert_data() and insert_data_many send rows to PostgreSQL as JSON text over this connection. csdb starts no client, so a load makes no new login. One statement sends at most 500,000 rows, and every statement of one load runs in one transaction.

csdb finds the failure class in the English error text of the server. Each new connection warns once when the lc_messages of the server is not C, POSIX or English. A failed load is csdb_load_ambiguous unless its ROLLBACK succeeded and the connection then answered SELECT 1. Only then can a known English text give csdb_load_duplicate_key or csdb_load_transient. Any other text gives csdb_load_other. The COMMIT and a broken connection also give csdb_load_ambiguous.

Three more rules apply:

  • A statement that runs past load_timeout stops on the server, which stores no row. The error has class csdb_load_other.

  • A statement that stores fewer rows than csdb sent stops the load before the commit. The error has class csdb_load_other, and the server stores no row.

  • A connection that cannot open before the load gives csdb_load_transient, with the error of connect() in its message.

A row with more than 900 MB of JSON text stops the load before csdb sends it. PostgreSQL refuses a value of 1 GB or more. The error has class csdb_load_other.

PostgreSQL double precision

The field type DOUBLE creates a double precision column. Until 2026.10.16 it created real, which keeps about 7 significant digits.

DBTable_v9$create_table() changes each real column that a table declares DOUBLE to double precision with one ALTER TABLE, and the table keeps its rows. PostgreSQL rewrites the table and its indexes, and blocks every other access to the table until the rewrite ends. The ALTER waits at most 60 s for its lock, and then stops with an error. The table then stays as it was.

See also

The introduction vignette, vignette("csdb", package = "csdb"), which creates one of these, connects, and disconnects again. csdb_set_auth_hook registers the function that connect() calls after its first failed attempt.

Other database classes: DBTable_v9

Public fields

config

Configuration details of the database.

Active bindings

connection

Database connection. NULL when another process opened it.

autoconnection

Database connection that automatically connects if possible. After a fork it opens a connection for the current process.

Methods


DBConnection_v9$new()

Create a new DBConnection_v9 object.

Usage

DBConnection_v9$new(
  driver = NULL,
  server = NULL,
  port = NULL,
  db = NULL,
  schema = NULL,
  user = NULL,
  password = NULL,
  trusted_connection = NULL,
  sslmode = NULL,
  role_create_table = NULL
)

Arguments

driver

Driver.

server

Server.

port

Port.

db

DB.

schema

Schema (e.g. "dbo").

user

User.

password

Password.

trusted_connection

NULL or "yes".

sslmode

NULL or "require".

role_create_table

NULL or the role to take when creating tables.

Returns

A new `DBConnection_v9` object.


DBConnection_v9$is_connected()

Is the DB schema connected?

A connection that another process opened does not count. The method drops that connection first, and then reports FALSE.

Usage

DBConnection_v9$is_connected()

Returns

TRUE/FALSE.


DBConnection_v9$print()

Class-specific print function.

Usage

DBConnection_v9$print(...)

Arguments

...

Not used.


DBConnection_v9$connect()

Connect to the database.

The method drops a connection that another process opened, and then opens a connection for the current process.

The method tries again after any error, until it has made attempts attempts. It waits 2 s before attempt 2 and 10 s before each later attempt, as a bcp or a JSON load does. Each failed attempt emits a message with its number, the wait and the error.

Usage

DBConnection_v9$connect(attempts = 3)

Arguments

attempts

The number of attempts to connect.


DBConnection_v9$disconnect()

Disconnect from the database.

The method closes only a connection that this process opened. A connection that another process opened stays open.

Usage

DBConnection_v9$disconnect()


DBConnection_v9$clone()

The objects of this class are cloneable with this method.

Usage

DBConnection_v9$clone(deep = FALSE)

Arguments

deep

Whether to make a deep clone.

Examples

# Creating the object stores the settings. It opens no connection,
# so this runs without a database server.
db <- DBConnection_v9$new(
  driver = "PostgreSQL Unicode",
  server = "localhost",
  port = 5432,
  db = "mydb",
  user = "myuser",
  password = "mypass"
)
db$is_connected()
#> [1] FALSE
db
#> (disconnected)
#> 
#> Driver:              PostgreSQL Unicode 
#> Server:              localhost 
#> Port:                5432 
#> DB:                  mydb 
#> User:                myuser 
#> Password:            ****** 
#> SSL mode:            x 
#> 

# \donttest{
# The full cycle, on SQLite. SQLite needs no server, so this block runs
# anywhere. Only the driver and the db argument change for a server.
# vignette("backends", package = "csdb") puts the two configurations
# side by side.
sqlite_db <- DBConnection_v9$new(
  driver = "SQLite",
  db = tempfile(fileext = ".sqlite")
)

sqlite_db$connect()
sqlite_db$is_connected()
#> [1] TRUE
DBI::dbListTables(sqlite_db$connection)
#> character(0)

sqlite_db$disconnect()
sqlite_db$is_connected()
#> [1] FALSE

# $autoconnection opens the file again, so a read after a disconnect
# still works.
DBI::dbListTables(sqlite_db$autoconnection)
#> character(0)
sqlite_db$disconnect()
# }