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