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