Line data Source code
1 : /******************************************************************************
2 : *
3 : * Project: OGR ODBC Driver
4 : * Purpose: Declarations for ODBC Access Cover API.
5 : * Author: Frank Warmerdam, warmerdam@pobox.com
6 : *
7 : ******************************************************************************
8 : * Copyright (c) 2003, Frank Warmerdam
9 : *
10 : * SPDX-License-Identifier: MIT
11 : ****************************************************************************/
12 :
13 : #ifndef CPL_ODBC_H_INCLUDED
14 : #define CPL_ODBC_H_INCLUDED
15 :
16 : #include "cpl_port.h"
17 :
18 : #ifdef _WIN32
19 : #include <windows.h>
20 : #endif
21 :
22 : #include <sql.h>
23 : #include <sqlext.h>
24 : #include <odbcinst.h>
25 : #include "cpl_string.h"
26 :
27 : /*! @cond Doxygen_Suppress */
28 : #ifdef PATH_MAX
29 : #define ODBC_FILENAME_MAX PATH_MAX
30 : #else
31 : #define ODBC_FILENAME_MAX (255 + 1) /* Max path length */
32 : #endif
33 : /*! @endcond */
34 :
35 : /**
36 : * \file cpl_odbc.h
37 : *
38 : * ODBC Abstraction Layer (C++).
39 : */
40 :
41 : /**
42 : * A class providing functions to install or remove ODBC driver.
43 : */
44 : class CPL_DLL CPLODBCDriverInstaller
45 : {
46 : char m_szPathOut[ODBC_FILENAME_MAX];
47 : char m_szError[SQL_MAX_MESSAGE_LENGTH];
48 : DWORD m_nErrorCode;
49 : DWORD m_nUsageCount;
50 :
51 : static bool FindMdbToolsDriverLib(CPLString &osDriverFile);
52 : static bool LibraryExists(const char *pszLibPath);
53 :
54 : public:
55 : // Default constructor.
56 : CPLODBCDriverInstaller();
57 :
58 : /**
59 : * Installs ODBC driver or updates definition of already installed driver.
60 : * Internally, it calls ODBC's SQLInstallDriverEx function.
61 : *
62 : * @param pszDriver - The driver definition as a list of keyword-value
63 : * pairs describing the driver (See ODBC API Reference).
64 : *
65 : * @param pszPathIn - Full path of the target directory of the installation,
66 : * or a null pointer (for unixODBC, NULL is passed).
67 : *
68 : * @param fRequest - The fRequest argument must contain one of
69 : * the following values:
70 : * ODBC_INSTALL_COMPLETE - (default) complete the installation request
71 : * ODBC_INSTALL_INQUIRY - inquire about where a driver can be installed
72 : *
73 : * @return TRUE indicates success, FALSE if it fails.
74 : */
75 : int InstallDriver(const char *pszDriver, const char *pszPathIn,
76 : WORD fRequest = ODBC_INSTALL_COMPLETE);
77 :
78 : /**
79 : * Attempts to install the MDB Tools driver for Microsoft Access databases.
80 : *
81 : * This is only supported on non-Windows platforms.
82 : *
83 : * @since GDAL 3.4
84 : */
85 : static void InstallMdbToolsDriver();
86 :
87 : /**
88 : * Removes or changes information about the driver from
89 : * the Odbcinst.ini entry in the system information.
90 : *
91 : * @param pszDriverName - The name of the driver as registered in
92 : * the Odbcinst.ini key of the system information.
93 : *
94 : * @param fRemoveDSN - TRUE: Remove DSNs associated with the driver
95 : * specified in lpszDriver. FALSE: Do not remove DSNs associated
96 : * with the driver specified in lpszDriver.
97 : *
98 : * @return The function returns TRUE if it is successful,
99 : * FALSE if it fails. If no entry exists in the system information
100 : * when this function is called, the function returns FALSE.
101 : * In order to obtain usage count value, call GetUsageCount().
102 : */
103 : int RemoveDriver(const char *pszDriverName, int fRemoveDSN = FALSE);
104 :
105 : /** The usage count of the driver after this function has been called */
106 : int GetUsageCount() const
107 : {
108 : return m_nUsageCount;
109 : }
110 :
111 : /** Path of the target directory where the driver should be installed.
112 : * For details, see ODBC API Reference and lpszPathOut
113 : * parameter of SQLInstallDriverEx
114 : */
115 : const char *GetPathOut() const
116 : {
117 : return m_szPathOut;
118 : }
119 :
120 : /** If InstallDriver returns FALSE, then GetLastError then
121 : * error message can be obtained by calling this function.
122 : * Internally, it calls ODBC's SQLInstallerError function.
123 : */
124 0 : const char *GetLastError() const
125 : {
126 0 : return m_szError;
127 : }
128 :
129 : /** If InstallDriver returns FALSE, then GetLastErrorCode then
130 : * error code can be obtained by calling this function.
131 : * Internally, it calls ODBC's SQLInstallerError function.
132 : * See ODBC API Reference for possible error flags.
133 : */
134 : DWORD GetLastErrorCode() const
135 : {
136 : return m_nErrorCode;
137 : }
138 : };
139 :
140 : class CPLODBCStatement;
141 :
142 : /* On MSVC SQLULEN is missing in some cases (i.e. VC6)
143 : ** but it is always a #define so test this way. On Unix
144 : ** it is a typedef so we can't always do this.
145 : */
146 : #if defined(_MSC_VER) && !defined(SQLULEN) && !defined(_WIN64)
147 : #define MISSING_SQLULEN
148 : #endif
149 :
150 : /*! @cond Doxygen_Suppress */
151 : #if !defined(MISSING_SQLULEN)
152 : /* ODBC types to support 64 bit compilation */
153 : #define CPL_SQLULEN SQLULEN
154 : #define CPL_SQLLEN SQLLEN
155 : #else
156 : #define CPL_SQLULEN SQLUINTEGER
157 : #define CPL_SQLLEN SQLINTEGER
158 : #endif /* ifdef SQLULEN */
159 : /*! @endcond */
160 :
161 : /**
162 : * A class representing an ODBC database session.
163 : *
164 : * Includes error collection services.
165 : */
166 :
167 : class CPL_DLL CPLODBCSession
168 : {
169 :
170 : CPL_DISALLOW_COPY_ASSIGN(CPLODBCSession)
171 :
172 : /*! @cond Doxygen_Suppress */
173 : protected:
174 : CPLString m_osLastError{};
175 : HENV m_hEnv = nullptr;
176 : HDBC m_hDBC = nullptr;
177 : int m_bInTransaction = false;
178 : int m_bAutoCommit = true;
179 : /*! @endcond */
180 :
181 : public:
182 : CPLODBCSession();
183 : ~CPLODBCSession();
184 :
185 : int EstablishSession(const char *pszDSN, const char *pszUserid,
186 : const char *pszPassword);
187 : const char *GetLastError();
188 :
189 : // Transaction handling
190 :
191 : int ClearTransaction();
192 : int BeginTransaction();
193 : int CommitTransaction();
194 : int RollbackTransaction();
195 :
196 : /** Returns whether a transaction is active */
197 9 : int IsInTransaction()
198 : {
199 9 : return m_bInTransaction;
200 : }
201 :
202 : // Essentially internal.
203 :
204 : int CloseSession();
205 :
206 : int Failed(int, HSTMT = nullptr);
207 :
208 : /** Return connection handle */
209 0 : HDBC GetConnection()
210 : {
211 0 : return m_hDBC;
212 : }
213 :
214 : /** Return GetEnvironment handle */
215 : HENV GetEnvironment()
216 : {
217 : return m_hEnv;
218 : }
219 :
220 : bool ConnectToMsAccess(const char *pszName,
221 : const char *pszDSNStringTemplate);
222 : };
223 :
224 : /**
225 : * Abstraction for statement, and resultset.
226 : *
227 : * Includes methods for executing an SQL statement, and for accessing the
228 : * resultset from that statement. Also provides for executing other ODBC
229 : * requests that produce results sets such as SQLColumns() and SQLTables()
230 : * requests.
231 : */
232 :
233 : class CPL_DLL CPLODBCStatement
234 : {
235 :
236 : CPL_DISALLOW_COPY_ASSIGN(CPLODBCStatement)
237 :
238 : /*! @cond Doxygen_Suppress */
239 : protected:
240 : int m_nFlags = 0;
241 :
242 : CPLODBCSession *m_poSession = nullptr;
243 : HSTMT m_hStmt = nullptr;
244 :
245 : SQLSMALLINT m_nColCount = 0;
246 : char **m_papszColNames = nullptr;
247 : SQLSMALLINT *m_panColType = nullptr;
248 : char **m_papszColTypeNames = nullptr;
249 : CPL_SQLULEN *m_panColSize = nullptr;
250 : SQLSMALLINT *m_panColPrecision = nullptr;
251 : SQLSMALLINT *m_panColNullable = nullptr;
252 : char **m_papszColColumnDef = nullptr;
253 :
254 : char **m_papszColValues = nullptr;
255 : CPL_SQLLEN *m_panColValueLengths = nullptr;
256 : double *m_padColValuesAsDouble = nullptr;
257 :
258 : int Failed(int);
259 :
260 : char *m_pszStatement = nullptr;
261 : size_t m_nStatementMax = 0;
262 : size_t m_nStatementLen = 0;
263 : /*! @endcond */
264 :
265 : public:
266 : /**
267 : * Flags which control ODBC statement behavior.
268 : */
269 : enum Flag
270 : {
271 : /**
272 : * Numeric column values should be retrieved as doubles, using either
273 : * the SQL_C_DOUBLE or SQL_C_FLOAT types.
274 : *
275 : * By default numeric column values are retrieved as characters.
276 : * Retrieving as character is the safest behavior, but can risk loss of
277 : * precision.
278 : *
279 : * If set, GetColDataAsDouble should be used for numeric columns instead
280 : * of GetColData.
281 : *
282 : * Warning: this flag can expose issues in particular ODBC drivers on
283 : * different platforms. Use with caution.
284 : */
285 : RetrieveNumericColumnsAsDouble = 1 << 0,
286 : };
287 :
288 : explicit CPLODBCStatement(CPLODBCSession *, int flags = 0);
289 : ~CPLODBCStatement();
290 :
291 : /** Return statement handle */
292 0 : HSTMT GetStatement()
293 : {
294 0 : return m_hStmt;
295 : }
296 :
297 : /**
298 : * Returns statement flags.
299 : */
300 0 : int Flags() const
301 : {
302 0 : return m_nFlags;
303 : }
304 :
305 : // Command buffer related.
306 : void Clear();
307 : void AppendEscaped(const char *);
308 : void Append(const char *);
309 : void Append(const std::string &);
310 : // cppcheck-suppress functionStatic
311 : void Append(int);
312 : void Append(double);
313 : int Appendf(CPL_FORMAT_STRING(const char *), ...)
314 : CPL_PRINT_FUNC_FORMAT(2, 3);
315 :
316 : /** Return statement string */
317 0 : const char *GetCommand()
318 : {
319 0 : return m_pszStatement;
320 : }
321 :
322 : int ExecuteSQL(const char * = nullptr);
323 :
324 : // Results fetching
325 : int Fetch(int nOrientation = SQL_FETCH_NEXT, int nOffset = 0);
326 : void ClearColumnData();
327 :
328 : int GetColCount();
329 : const char *GetColName(int);
330 : short GetColType(int);
331 : const char *GetColTypeName(int);
332 : short GetColSize(int);
333 : short GetColPrecision(int);
334 : short GetColNullable(int);
335 : const char *GetColColumnDef(int);
336 :
337 : int GetColId(const char *) const;
338 : const char *GetColData(int, const char * = nullptr);
339 : const char *GetColData(const char *, const char * = nullptr);
340 : int GetColDataLength(int);
341 :
342 : double GetColDataAsDouble(int) const;
343 : double GetColDataAsDouble(const char *) const;
344 :
345 : int GetRowCountAffected();
346 :
347 : // Fetch special metadata.
348 : int GetColumns(const char *pszTable, const char *pszCatalog = nullptr,
349 : const char *pszSchema = nullptr);
350 : int GetPrimaryKeys(const char *pszTable, const char *pszCatalog = nullptr,
351 : const char *pszSchema = nullptr);
352 :
353 : int GetTables(const char *pszCatalog = nullptr,
354 : const char *pszSchema = nullptr);
355 :
356 : void DumpResult(FILE *fp, int bShowSchema = FALSE);
357 :
358 : static CPLString GetTypeName(int);
359 : static SQLSMALLINT GetTypeMapping(SQLSMALLINT);
360 :
361 : int CollectResultsInfo();
362 : };
363 :
364 : #endif
|