KiCad PCB EDA Suite
Loading...
Searching...
No Matches
ODBC_BACKEND Class Reference

Reads a database through an ODBC data source or connection string. More...

#include <odbc_backend.h>

Inheritance diagram for ODBC_BACKEND:
DATABASE_BACKEND

Classes

struct  COLUMN_INFO
 ODBC description of a column, so a lookup key can be bound with the type the driver expects. More...
 
struct  DATA_SOURCE
 A data source configured in the ODBC driver manager. More...
 
struct  KEY_PARAMETER
 How ReadRow describes its key parameter to the driver. More...
 
struct  SELECTOR
 The keyword ODBC uses to choose where a connection string connects. More...
 

Public Types

using DSN_LOOKUP = std::function<std::optional<std::string>( const std::string& )>
 Resolves a data source name to its driver, or nullopt if it is unknown.
 

Public Member Functions

 ODBC_BACKEND (std::string aDsn, std::string aUser, std::string aPass, std::string aConnectionString, long aTimeout)
 
 ~ODBC_BACKEND () override
 
bool Connect () override
 
void Disconnect () override
 
bool IsConnected () const override
 
bool ListTables (std::vector< std::string > &aTables) override
 Lists the tables and views, sorted by name.
 
std::optional< DB_TABLE_INFO > DescribeTable (const std::string &aTable) override
 
bool ListColumns (const std::string &aTable, std::vector< std::string > &aColumns) override
 Lists the column names of a table as the catalog reports them, empty if it has none, false if the catalog failed.
 
bool ReadTable (const DB_TABLE_INFO &aTable, const std::vector< std::string > &aColumns, size_t aMaxRows, std::vector< std::string > &aLabels, const DB_ROW_SINK &aSink) override
 Reads rows of a table, handing each to aSink.
 
std::optional< bool > ReadRow (const DB_TABLE_INFO &aTable, const std::vector< std::string > &aColumns, const std::string &aKeyColumn, const std::string &aKey, std::vector< std::string > &aLabels, std::vector< DB_VALUE > &aRow) override
 Runs a prepared query whose key parameter is described with the key column's catalog type.
 
std::string GetLastError () const override
 
DB_FAILURE GetLastFailure () const override
 
virtual bool ReadAllRows (const DB_TABLE_INFO &aTable, const std::vector< std::string > &aColumns, std::vector< std::string > &aLabels, const DB_ROW_SINK &aSink, const DB_RESTART_SINK &aRestart)
 Reads every row of a table for a caller that keeps them, handing each to aSink.
 
virtual void BeginLoadCycle (const DB_STOP_CHECK &aStopped)
 Brackets a load cycle, in which the caller reads each table once.
 
virtual void EndLoadCycle ()
 

Static Public Member Functions

static std::vector< DATA_SOURCE > ListDataSourceDetails ()
 
static std::vector< std::string > ListDrivers ()
 
static SELECTOR FirstSelector (const std::string &aConnectionString)
 
static bool NeedsDriverLock (const std::string &aDsn, const std::string &aConnectionString, const DSN_LOOKUP &aLookup)
 Decides whether connecting must be serialized because the effective driver is, or may be, the Microsoft Access driver.
 
static bool IsAccessDriver (const std::string &aDriverName)
 
static bool IsAccessFileInUse (const std::string &aLowerMessage)
 
static DB_FAILURE ClassifyFailure (const std::string &aState, const std::string &aMessage)
 Classifies a driver error from its SQLSTATE, falling back to its text since drivers disagree on states.
 
static KEY_PARAMETER DescribeKeyParameter (int aColumnType, long aColumnSize, short aColumnScale, const std::string &aKey)
 Chooses the parameter description for a lookup key from its column's cached ODBC description.
 
static DB_BACKEND_RESULT Create (const DATABASE_SOURCE &aSource, const wxString &aBasePath)
 Builds the backend for a source.
 

Static Public Attributes

static constexpr size_t ALL_ROWS = std::numeric_limits<size_t>::max()
 Passed as ReadTable()'s row limit to read every row.
 

Private Member Functions

bool getQuoteChar ()
 
bool takeAccessDriverLock (std::unique_lock< std::timed_mutex > &aLock)
 Takes the lock that keeps the Access driver from initializing or unloading on two threads at once.
 
void disconnectLocked ()
 Closes the connection with the driver lock held by the caller.
 
std::string quoted (const std::string &aIdentifier) const
 Wraps an identifier in the driver's quote character, doubling any it contains.
 
std::string escapePattern (const std::string &aName) const
 Escapes catalog search pattern characters so a name matches only itself.
 
std::string columnList (const std::vector< std::string > &aColumns) const
 

Private Attributes

std::unique_ptr< nanodbc::connection > m_conn
 
std::string m_dsn
 
std::string m_user
 
std::string m_pass
 
std::string m_connectionString
 
bool m_accessDriver = false
 
std::optional< std::chrono::steady_clock::time_point > m_engineDeadline
 When the wait for the Access driver lock ends, fixed by the first step that finds the lock busy and never renewed, so it stays spent until the next Connect.
 
std::string m_lastError
 
DB_FAILURE m_lastFailure = DB_FAILURE::UNKNOWN
 
std::map< std::string, std::map< std::string, COLUMN_INFO > > m_columnInfo
 Map of table -> map of column name -> column description.
 
long m_timeout
 
char m_quoteChar = '"'
 
std::string m_patternEscape
 

Detailed Description

Reads a database through an ODBC data source or connection string.

Definition at line 43 of file odbc_backend.h.

Member Typedef Documentation

◆ DSN_LOOKUP

using ODBC_BACKEND::DSN_LOOKUP = std::function<std::optional<std::string>( const std::string& )>

Resolves a data source name to its driver, or nullopt if it is unknown.

Definition at line 112 of file odbc_backend.h.

Constructor & Destructor Documentation

◆ ODBC_BACKEND()

ODBC_BACKEND::ODBC_BACKEND ( std::string aDsn,
std::string aUser,
std::string aPass,
std::string aConnectionString,
long aTimeout )
Parameters
aDsnthe data source name, ignored when aConnectionString is set
aConnectionStringa full ODBC connection string, or empty to use the data source name
aTimeoutthe login timeout and query timeout in seconds

Definition at line 141 of file odbc_backend.cpp.

References ListDataSourceDetails(), m_accessDriver, m_connectionString, m_dsn, m_pass, m_timeout, m_user, move, NeedsDriverLock(), and source.

◆ ~ODBC_BACKEND()

ODBC_BACKEND::~ODBC_BACKEND ( )
override

Member Function Documentation

◆ BeginLoadCycle()

virtual void DATABASE_BACKEND::BeginLoadCycle ( const DB_STOP_CHECK & aStopped)
inlinevirtualinherited

Brackets a load cycle, in which the caller reads each table once.

A backend may keep what it opens for the cycle's reads until the cycle ends. Cycles may nest, and only the outermost begin and end count. Nesting is backend-wide and may cross threads, as when a lookup on one thread reads a table while a refresh on another has a cycle open. The nested read keeps the stop check and sessions of the outermost cycle.

Parameters
aStoppedmay be empty; a backend that retries a read gives up when it returns true

Reimplemented in ACE_BACKEND.

Definition at line 161 of file database_backend.h.

◆ ClassifyFailure()

DB_FAILURE ODBC_BACKEND::ClassifyFailure ( const std::string & aState,
const std::string & aMessage )
static

Classifies a driver error from its SQLSTATE, falling back to its text since drivers disagree on states.

Definition at line 993 of file odbc_backend.cpp.

References FILE_IN_USE, IsAccessFileInUse(), LOGIN, message, NO_DRIVER, NO_DSN, TIMEOUT, UNKNOWN, and UNREACHABLE.

Referenced by Connect().

◆ columnList()

std::string ODBC_BACKEND::columnList ( const std::vector< std::string > & aColumns) const
private
Returns
the quoted column list for a SELECT, or * when there are no columns

Definition at line 602 of file odbc_backend.cpp.

References quoted().

Referenced by ReadRow(), and ReadTable().

◆ Connect()

◆ Create()

DB_BACKEND_RESULT DATABASE_BACKEND::Create ( const DATABASE_SOURCE & aSource,
const wxString & aBasePath )
staticinherited

Builds the backend for a source.

Parameters
aSourcethe source as configured; ${CWD} is expanded in its connection string and path
aBasePaththe directory ${CWD} stands for
Returns
the backend, or a null backend with the failure and a message naming the problem

Definition at line 34 of file database_backend.cpp.

References _, ACCESS, DATABASE_SOURCE::Expanded(), INVALID, INVALID_TYPE, ACE_BACKEND::MISSING, NOT_SUPPORTED_ON_PLATFORM, ODBC, PROVIDER_MISSING, ACE_BACKEND::ProviderMissingMessage(), ACE_BACKEND::ProviderState(), source, SQLITE, UNKNOWN, and utf8().

Referenced by SCH_IO_DATABASE::connectOnce(), and SCH_IO_DATABASE::CreateConnection().

◆ DescribeKeyParameter()

ODBC_BACKEND::KEY_PARAMETER ODBC_BACKEND::DescribeKeyParameter ( int aColumnType,
long aColumnSize,
short aColumnScale,
const std::string & aKey )
static

Chooses the parameter description for a lookup key from its column's cached ODBC description.

Strict drivers (Microsoft Access) reject a key whose type does not match the column.

Parameters
aColumnTypeis the ODBC SQL data type of the key column
aColumnSizeis its character length or numeric precision, zero or negative when unknown
aColumnScaleis its number of digits right of the decimal point
aKeyis the key text

Definition at line 626 of file odbc_backend.cpp.

References DEFAULT_KEY_CHAR_SIZE, DEFAULT_KEY_DECIMAL_SIZE, DEFAULT_KEY_INTEGER_SIZE, end, and MAX_KEY_CHAR_SIZE.

Referenced by ReadRow().

◆ DescribeTable()

std::optional< DB_TABLE_INFO > ODBC_BACKEND::DescribeTable ( const std::string & aTable)
overridevirtual
Returns
the table's columns in catalog order, or nullopt if it was not found or the catalog failed

Implements DATABASE_BACKEND.

Definition at line 457 of file odbc_backend.cpp.

References escapePattern(), fromUTF8(), info, m_columnInfo, m_conn, m_lastError, m_lastFailure, name, toUTF8(), traceDatabase, and UNKNOWN.

◆ Disconnect()

void ODBC_BACKEND::Disconnect ( )
overridevirtual

◆ disconnectLocked()

void ODBC_BACKEND::disconnectLocked ( )
private

Closes the connection with the driver lock held by the caller.

Definition at line 435 of file odbc_backend.cpp.

References m_conn, and traceDatabase.

Referenced by Disconnect(), and ~ODBC_BACKEND().

◆ EndLoadCycle()

virtual void DATABASE_BACKEND::EndLoadCycle ( )
inlinevirtualinherited

Reimplemented in ACE_BACKEND.

Definition at line 163 of file database_backend.h.

◆ escapePattern()

std::string ODBC_BACKEND::escapePattern ( const std::string & aName) const
private

Escapes catalog search pattern characters so a name matches only itself.

Definition at line 582 of file odbc_backend.cpp.

References m_patternEscape.

Referenced by DescribeTable(), ListColumns(), and ListTables().

◆ FirstSelector()

ODBC_BACKEND::SELECTOR ODBC_BACKEND::FirstSelector ( const std::string & aConnectionString)
static
Returns
the first DSN, FILEDSN or DRIVER keyword of a connection string, which ODBC honours over later ones

Definition at line 238 of file odbc_backend.cpp.

References ODBC_BACKEND::SELECTOR::DRIVER, ODBC_BACKEND::SELECTOR::DSN, end, and ODBC_BACKEND::SELECTOR::FILE_DSN.

Referenced by NeedsDriverLock().

◆ GetLastError()

std::string ODBC_BACKEND::GetLastError ( ) const
inlineoverridevirtual

Implements DATABASE_BACKEND.

Definition at line 76 of file odbc_backend.h.

References m_lastError.

◆ GetLastFailure()

DB_FAILURE ODBC_BACKEND::GetLastFailure ( ) const
inlineoverridevirtual

Implements DATABASE_BACKEND.

Definition at line 78 of file odbc_backend.h.

References m_lastFailure.

◆ getQuoteChar()

bool ODBC_BACKEND::getQuoteChar ( )
private

Definition at line 544 of file odbc_backend.cpp.

References m_conn, m_lastError, m_quoteChar, toUTF8(), and traceDatabase.

Referenced by Connect().

◆ IsAccessDriver()

bool ODBC_BACKEND::IsAccessDriver ( const std::string & aDriverName)
static
Returns
true for the Microsoft Access ODBC drivers, which must not initialize on two threads at once

Definition at line 344 of file odbc_backend.cpp.

Referenced by NeedsDriverLock().

◆ IsAccessFileInUse()

bool ODBC_BACKEND::IsAccessFileInUse ( const std::string & aLowerMessage)
static
Returns
true when a lowercase driver message is one of the Access driver's own locked-file messages

Definition at line 968 of file odbc_backend.cpp.

Referenced by ClassifyFailure().

◆ IsConnected()

bool ODBC_BACKEND::IsConnected ( ) const
overridevirtual

Implements DATABASE_BACKEND.

Definition at line 448 of file odbc_backend.cpp.

References m_conn.

Referenced by Connect().

◆ ListColumns()

bool ODBC_BACKEND::ListColumns ( const std::string & aTable,
std::vector< std::string > & aColumns )
overridevirtual

Lists the column names of a table as the catalog reports them, empty if it has none, false if the catalog failed.

Reimplemented from DATABASE_BACKEND.

Definition at line 517 of file odbc_backend.cpp.

References escapePattern(), fromUTF8(), m_conn, m_lastError, toUTF8(), and traceDatabase.

◆ ListDataSourceDetails()

std::vector< ODBC_BACKEND::DATA_SOURCE > ODBC_BACKEND::ListDataSourceDetails ( )
static
Returns
the data sources configured in the ODBC driver manager, with the driver each one uses

Definition at line 932 of file odbc_backend.cpp.

References source, toUTF8(), and traceDatabase.

Referenced by DIALOG_DATABASE_LIB_SETTINGS::loadDataSources(), and ODBC_BACKEND().

◆ ListDrivers()

std::vector< std::string > ODBC_BACKEND::ListDrivers ( )
static
Returns
the driver names installed in the ODBC driver manager

Definition at line 950 of file odbc_backend.cpp.

References toUTF8(), and traceDatabase.

Referenced by DIALOG_DATABASE_LIB_SETTINGS::TransferDataToWindow().

◆ ListTables()

bool ODBC_BACKEND::ListTables ( std::vector< std::string > & aTables)
overridevirtual

Lists the tables and views, sorted by name.

Implements DATABASE_BACKEND.

Definition at line 880 of file odbc_backend.cpp.

References escapePattern(), fromUTF8(), m_conn, m_lastError, toUTF8(), and traceDatabase.

◆ NeedsDriverLock()

bool ODBC_BACKEND::NeedsDriverLock ( const std::string & aDsn,
const std::string & aConnectionString,
const DSN_LOOKUP & aLookup )
static

Decides whether connecting must be serialized because the effective driver is, or may be, the Microsoft Access driver.

Anything that cannot be resolved without loading a driver is serialized.

Parameters
aDsnis the data source name, used when the connection string is empty
aLookupresolves a data source name to its driver

Definition at line 314 of file odbc_backend.cpp.

References ODBC_BACKEND::SELECTOR::DRIVER, ODBC_BACKEND::SELECTOR::DSN, ODBC_BACKEND::SELECTOR::FILE_DSN, FirstSelector(), IsAccessDriver(), and ODBC_BACKEND::SELECTOR::NONE.

Referenced by ODBC_BACKEND().

◆ quoted()

std::string ODBC_BACKEND::quoted ( const std::string & aIdentifier) const
private

Wraps an identifier in the driver's quote character, doubling any it contains.

Definition at line 571 of file odbc_backend.cpp.

References m_quoteChar.

Referenced by columnList(), ReadRow(), and ReadTable().

◆ ReadAllRows()

virtual bool DATABASE_BACKEND::ReadAllRows ( const DB_TABLE_INFO & aTable,
const std::vector< std::string > & aColumns,
std::vector< std::string > & aLabels,
const DB_ROW_SINK & aSink,
const DB_RESTART_SINK & aRestart )
inlinevirtualinherited

Reads every row of a table for a caller that keeps them, handing each to aSink.

A backend that checks one read against another may deliver the table more than once, and calls aRestart before every delivery after the first, so the caller drops the rows it already took. The default reads once.

Parameters
aLabelsis filled with the result-column labels before each delivery's first call to aSink
Returns
false on failure, in which case the caller discards any rows already delivered

Reimplemented in ACE_BACKEND.

Definition at line 146 of file database_backend.h.

References ALL_ROWS, and ReadTable().

◆ ReadRow()

std::optional< bool > ODBC_BACKEND::ReadRow ( const DB_TABLE_INFO & aTable,
const std::vector< std::string > & aColumns,
const std::string & aKeyColumn,
const std::string & aKey,
std::vector< std::string > & aLabels,
std::vector< DB_VALUE > & aRow )
overridevirtual

◆ ReadTable()

bool ODBC_BACKEND::ReadTable ( const DB_TABLE_INFO & aTable,
const std::vector< std::string > & aColumns,
size_t aMaxRows,
std::vector< std::string > & aLabels,
const DB_ROW_SINK & aSink )
overridevirtual

Reads rows of a table, handing each to aSink.

Parameters
aColumnsthe columns to read; empty reads all of them
aMaxRowsstops after this many rows; zero fills aLabels and fetches no rows. A bounded read is ordered by the first column where the backend can.
aLabelsis filled with the result-column labels as the source spells them, before the first call to aSink
Returns
false on failure, in which case the caller discards any rows already delivered

Implements DATABASE_BACKEND.

Definition at line 795 of file odbc_backend.cpp.

References DATABASE_BACKEND::ALL_ROWS, columnList(), decodeRow(), Disconnect(), fromUTF8(), m_conn, m_lastError, m_timeout, PROF_TIMER::msecs(), DB_TABLE_INFO::name, quoted(), resultColumns(), rows, PROF_TIMER::Stop(), and traceDatabase.

◆ takeAccessDriverLock()

bool ODBC_BACKEND::takeAccessDriverLock ( std::unique_lock< std::timed_mutex > & aLock)
private

Takes the lock that keeps the Access driver from initializing or unloading on two threads at once.

The lock is not taken for any other driver, and never off Windows. Connect, Disconnect and destruction share one deadline while the lock stays out of reach, so a stalled Access worker costs one wait.

Returns
false if the lock was needed and could not be taken before the deadline

Definition at line 210 of file odbc_backend.cpp.

References AccessEngineMutex(), DB_WORKER_THREAD::CallerBound(), LockAccessEngine(), m_accessDriver, m_engineDeadline, m_timeout, and traceDatabase.

Referenced by Connect(), Disconnect(), and ~ODBC_BACKEND().

Member Data Documentation

◆ ALL_ROWS

size_t DATABASE_BACKEND::ALL_ROWS = std::numeric_limits<size_t>::max()
staticconstexprinherited

Passed as ReadTable()'s row limit to read every row.

Definition at line 106 of file database_backend.h.

Referenced by ReadAllRows(), ACE_BACKEND::ReadTable(), ODBC_BACKEND::ReadTable(), SQLITE_BACKEND::ReadTable(), and ACE_BACKEND::readVerified().

◆ m_accessDriver

bool ODBC_BACKEND::m_accessDriver = false
private

Definition at line 186 of file odbc_backend.h.

Referenced by ODBC_BACKEND(), and takeAccessDriverLock().

◆ m_columnInfo

std::map<std::string, std::map<std::string, COLUMN_INFO> > ODBC_BACKEND::m_columnInfo
private

Map of table -> map of column name -> column description.

Definition at line 204 of file odbc_backend.h.

Referenced by DescribeTable(), and ReadRow().

◆ m_conn

std::unique_ptr<nanodbc::connection> ODBC_BACKEND::m_conn
private

◆ m_connectionString

std::string ODBC_BACKEND::m_connectionString
private

Definition at line 184 of file odbc_backend.h.

Referenced by Connect(), and ODBC_BACKEND().

◆ m_dsn

std::string ODBC_BACKEND::m_dsn
private

Definition at line 181 of file odbc_backend.h.

Referenced by Connect(), and ODBC_BACKEND().

◆ m_engineDeadline

std::optional<std::chrono::steady_clock::time_point> ODBC_BACKEND::m_engineDeadline
private

When the wait for the Access driver lock ends, fixed by the first step that finds the lock busy and never renewed, so it stays spent until the next Connect.

Definition at line 190 of file odbc_backend.h.

Referenced by Connect(), and takeAccessDriverLock().

◆ m_lastError

std::string ODBC_BACKEND::m_lastError
private

◆ m_lastFailure

DB_FAILURE ODBC_BACKEND::m_lastFailure = DB_FAILURE::UNKNOWN
private

Definition at line 193 of file odbc_backend.h.

Referenced by Connect(), DescribeTable(), Disconnect(), and GetLastFailure().

◆ m_pass

std::string ODBC_BACKEND::m_pass
private

Definition at line 183 of file odbc_backend.h.

Referenced by Connect(), and ODBC_BACKEND().

◆ m_patternEscape

std::string ODBC_BACKEND::m_patternEscape
private

Definition at line 210 of file odbc_backend.h.

Referenced by Connect(), and escapePattern().

◆ m_quoteChar

char ODBC_BACKEND::m_quoteChar = '"'
private

Definition at line 208 of file odbc_backend.h.

Referenced by getQuoteChar(), and quoted().

◆ m_timeout

long ODBC_BACKEND::m_timeout
private

Definition at line 206 of file odbc_backend.h.

Referenced by Connect(), ODBC_BACKEND(), ReadTable(), and takeAccessDriverLock().

◆ m_user

std::string ODBC_BACKEND::m_user
private

Definition at line 182 of file odbc_backend.h.

Referenced by Connect(), and ODBC_BACKEND().


The documentation for this class was generated from the following files: