KiCad PCB EDA Suite
Loading...
Searching...
No Matches
odbc_backend.h
Go to the documentation of this file.
1/*
2 * This program source code file is part of KiCad, a free EDA CAD application.
3 *
4 * Copyright (C) 2022 Jon Evans <[email protected]>
5 * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
6 *
7 * This program is free software: you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation, either version 3 of the License, or (at your
10 * option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <https://www.gnu.org/licenses/>.
19 */
20
21#ifndef KICAD_ODBC_BACKEND_H
22#define KICAD_ODBC_BACKEND_H
23
24#include <chrono>
25#include <cstdint>
26#include <functional>
27#include <map>
28#include <memory>
29#include <mutex>
30#include <optional>
31#include <string>
32#include <vector>
33
35
36namespace nanodbc
37{
38class connection;
39}
40
41
44{
45public:
51 ODBC_BACKEND( std::string aDsn, std::string aUser, std::string aPass, std::string aConnectionString,
52 long aTimeout );
53
54 ~ODBC_BACKEND() override;
55
56 bool Connect() override;
57
58 void Disconnect() override;
59
60 bool IsConnected() const override;
61
62 bool ListTables( std::vector<std::string>& aTables ) override;
63
64 std::optional<DB_TABLE_INFO> DescribeTable( const std::string& aTable ) override;
65
66 bool ListColumns( const std::string& aTable, std::vector<std::string>& aColumns ) override;
67
68 bool ReadTable( const DB_TABLE_INFO& aTable, const std::vector<std::string>& aColumns, size_t aMaxRows,
69 std::vector<std::string>& aLabels, const DB_ROW_SINK& aSink ) override;
70
72 std::optional<bool> ReadRow( const DB_TABLE_INFO& aTable, const std::vector<std::string>& aColumns,
73 const std::string& aKeyColumn, const std::string& aKey,
74 std::vector<std::string>& aLabels, std::vector<DB_VALUE>& aRow ) override;
75
76 std::string GetLastError() const override { return m_lastError; }
77
78 DB_FAILURE GetLastFailure() const override { return m_lastFailure; }
79
82 {
83 std::string name;
84 std::string driver;
85 };
86
88 static std::vector<DATA_SOURCE> ListDataSourceDetails();
89
91 static std::vector<std::string> ListDrivers();
92
94 struct SELECTOR
95 {
96 enum class KIND
97 {
102 };
103
105 std::string value;
106 };
107
109 static SELECTOR FirstSelector( const std::string& aConnectionString );
110
112 using DSN_LOOKUP = std::function<std::optional<std::string>( const std::string& )>;
113
121 static bool NeedsDriverLock( const std::string& aDsn, const std::string& aConnectionString,
122 const DSN_LOOKUP& aLookup );
123
125 static bool IsAccessDriver( const std::string& aDriverName );
126
128 static bool IsAccessFileInUse( const std::string& aLowerMessage );
129
131 static DB_FAILURE ClassifyFailure( const std::string& aState, const std::string& aMessage );
132
135 {
136 short type = 0;
137 unsigned long size = 0;
138 short scale = 0;
139 bool asInteger = false;
140 int64_t integerValue = 0;
141 };
142
152 static KEY_PARAMETER DescribeKeyParameter( int aColumnType, long aColumnSize, short aColumnScale,
153 const std::string& aKey );
154
155private:
156 bool getQuoteChar();
157
165 bool takeAccessDriverLock( std::unique_lock<std::timed_mutex>& aLock );
166
168 void disconnectLocked();
169
171 std::string quoted( const std::string& aIdentifier ) const;
172
174 std::string escapePattern( const std::string& aName ) const;
175
177 std::string columnList( const std::vector<std::string>& aColumns ) const;
178
179 std::unique_ptr<nanodbc::connection> m_conn;
180
181 std::string m_dsn;
182 std::string m_user;
183 std::string m_pass;
185
186 bool m_accessDriver = false;
187
190 std::optional<std::chrono::steady_clock::time_point> m_engineDeadline;
191
192 std::string m_lastError;
194
197 {
198 int type = 0;
199 long size = 0;
200 short scale = 0;
201 };
202
204 std::map<std::string, std::map<std::string, COLUMN_INFO>> m_columnInfo;
205
207
208 char m_quoteChar = '"';
209
210 std::string m_patternEscape;
211};
212
213#endif // KICAD_ODBC_BACKEND_H
A read-only source of tables.
std::function< std::optional< std::string >(const std::string &)> DSN_LOOKUP
Resolves a data source name to its driver, or nullopt if it is unknown.
std::string GetLastError() const override
std::optional< DB_TABLE_INFO > DescribeTable(const std::string &aTable) override
DB_FAILURE GetLastFailure() const override
std::map< std::string, std::map< std::string, COLUMN_INFO > > m_columnInfo
Map of table -> map of column name -> column description.
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 n...
static std::vector< std::string > ListDrivers()
std::string m_dsn
std::string m_pass
void Disconnect() override
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::string m_user
std::string m_patternEscape
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.
std::string quoted(const std::string &aIdentifier) const
Wraps an identifier in the driver's quote character, doubling any it contains.
static bool IsAccessDriver(const std::string &aDriverName)
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 state...
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.
void disconnectLocked()
Closes the connection with the driver lock held by the caller.
bool ListTables(std::vector< std::string > &aTables) override
Lists the tables and views, sorted by name.
bool Connect() override
ODBC_BACKEND(std::string aDsn, std::string aUser, std::string aPass, std::string aConnectionString, long aTimeout)
std::string m_lastError
static bool IsAccessFileInUse(const std::string &aLowerMessage)
std::string m_connectionString
bool IsConnected() const override
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,...
static SELECTOR FirstSelector(const std::string &aConnectionString)
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 escapePattern(const std::string &aName) const
Escapes catalog search pattern characters so a name matches only itself.
std::unique_ptr< nanodbc::connection > m_conn
DB_FAILURE m_lastFailure
~ODBC_BACKEND() 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,...
static std::vector< DATA_SOURCE > ListDataSourceDetails()
std::string columnList(const std::vector< std::string > &aColumns) const
std::function< void(std::vector< DB_VALUE > &&)> DB_ROW_SINK
Receives one row at a time, in the order of the labels the read produced.
DB_FAILURE
Why a connection attempt failed, as far as the backend's report tells.
This source file implements export and import capabilities to the specctra dsn file format.
Definition specctra.cpp:60
ODBC description of a column, so a lookup key can be bound with the type the driver expects.
short scale
Digits right of the decimal point.
int type
SQL data type.
long size
Character length or numeric precision, zero or negative when unknown.
A data source configured in the ODBC driver manager.
How ReadRow describes its key parameter to the driver.
short type
ODBC SQL data type.
int64_t integerValue
The key as a number, set when asInteger is true.
bool asInteger
Bind integerValue as a 64-bit integer instead of the key text.
short scale
Digits right of the decimal point.
unsigned long size
Column size or precision.
The keyword ODBC uses to choose where a connection string connects.
std::string value
The keyword's value without braces.