Line data Source code
1 : /*
2 : * SPDX-License-Identifier: MPL-2.0
3 : *
4 : * This Source Code Form is subject to the terms of the Mozilla Public
5 : * License, v. 2.0. If a copy of the MPL was not distributed with this
6 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
7 : *
8 : * Copyright 2024 MonetDB Foundation;
9 : * Copyright August 2008 - 2023 MonetDB B.V.;
10 : * Copyright 1997 - July 2008 CWI.
11 : */
12 :
13 : /*
14 : * This code was created by Peter Harvey (mostly during Christmas 98/99).
15 : * This code is LGPL. Please ensure that this message remains in future
16 : * distributions and uses of this code (thats about all I get out of it).
17 : * - Peter Harvey pharvey@codebydesign.com
18 : *
19 : * This file has been modified for the MonetDB project. See the file
20 : * Copyright in this directory for more information.
21 : */
22 :
23 : /**********************************************************************
24 : * SQLGetDiagRec()
25 : * CLI Compliance: ISO 92
26 : *
27 : * Author: Martin van Dinther, Sjoerd Mullender
28 : * Date : 30 aug 2002
29 : *
30 : **********************************************************************/
31 :
32 : #include "ODBCGlobal.h"
33 : #include "ODBCEnv.h"
34 : #include "ODBCDbc.h"
35 : #include "ODBCStmt.h"
36 : #include "ODBCError.h"
37 : #include "ODBCUtil.h"
38 :
39 : SQLRETURN
40 48 : MNDBGetDiagRec(SQLSMALLINT HandleType,
41 : SQLHANDLE Handle,
42 : SQLSMALLINT RecNumber,
43 : SQLCHAR *SQLState,
44 : SQLINTEGER *NativeErrorPtr,
45 : SQLCHAR *MessageText,
46 : SQLSMALLINT BufferLength,
47 : SQLSMALLINT *TextLengthPtr)
48 : {
49 48 : ODBCError *err;
50 48 : ODBCDbc *dbc = NULL;
51 48 : char *msg;
52 48 : SQLSMALLINT msgLen;
53 :
54 48 : switch (HandleType) {
55 0 : case SQL_HANDLE_ENV:
56 : /* Check if this struct is still valid/alive */
57 0 : if (!isValidEnv((ODBCEnv *) Handle))
58 : return SQL_INVALID_HANDLE;
59 0 : err = getEnvError((ODBCEnv *) Handle);
60 0 : break;
61 1 : case SQL_HANDLE_DBC:
62 : /* Check if this struct is still valid/alive */
63 1 : dbc = (ODBCDbc *) Handle;
64 1 : if (!isValidDbc(dbc))
65 : return SQL_INVALID_HANDLE;
66 1 : err = getDbcError(dbc);
67 1 : break;
68 47 : case SQL_HANDLE_STMT:
69 : /* Check if this struct is still valid/alive */
70 47 : if (!isValidStmt((ODBCStmt *) Handle))
71 : return SQL_INVALID_HANDLE;
72 47 : err = getStmtError((ODBCStmt *) Handle);
73 47 : dbc = ((ODBCStmt *) Handle)->Dbc;
74 47 : break;
75 0 : case SQL_HANDLE_DESC:
76 : /* Check if this struct is still valid/alive */
77 0 : if (!isValidDesc((ODBCDesc *) Handle))
78 : return SQL_INVALID_HANDLE;
79 0 : err = getDescError((ODBCDesc *) Handle);
80 0 : dbc = ((ODBCDesc *) Handle)->Dbc;
81 0 : break;
82 : default:
83 : return SQL_INVALID_HANDLE;
84 : }
85 :
86 : /* Note: BufferLength may be 0 !! */
87 48 : if (BufferLength < 0)
88 : return SQL_ERROR;
89 :
90 48 : if (RecNumber <= 0)
91 : return SQL_ERROR;
92 :
93 47 : err = getErrorRec(err, RecNumber);
94 : /* Check the error object from the handle, it may be NULL when
95 : * no (more) errors are available
96 : */
97 47 : if (err == NULL)
98 : return SQL_NO_DATA;
99 :
100 : /* Now fill the output parameters where possible */
101 31 : if (SQLState) {
102 31 : char *state = getSqlState(err);
103 :
104 31 : assert(state);
105 : /* copy only the first SQL_SQLSTATE_SIZE (5) chars in
106 : * the buffer and make it null terminated
107 : */
108 31 : strcpy_len((char *) SQLState, state, SQL_SQLSTATE_SIZE + 1);
109 : }
110 :
111 31 : if (NativeErrorPtr)
112 31 : *NativeErrorPtr = getNativeErrorCode(err);
113 :
114 31 : msg = getMessage(err);
115 :
116 : /* first write the error message prefix text:
117 : * [MonetDB][ODBC driver VERSION][DSN]
118 : * this is required by the ODBC spec:
119 : * https://docs.microsoft.com/en-us/sql/odbc/reference/develop-app/diagnostic-messages
120 : * and used to determine where the error originated
121 : */
122 31 : if (dbc && dbc->dsn)
123 31 : msgLen = (SQLSMALLINT) strconcat_len((char *) MessageText, BufferLength, ODBCErrorMsgPrefix, "[", dbc->dsn, "]", msg, NULL);
124 : else
125 0 : msgLen = (SQLSMALLINT) strconcat_len((char *) MessageText, BufferLength, ODBCErrorMsgPrefix, msg, NULL);
126 :
127 31 : if (TextLengthPtr)
128 31 : *TextLengthPtr = msgLen;
129 :
130 31 : if (MessageText == NULL || msgLen >= BufferLength) {
131 : /* it didn't fit */
132 0 : return SQL_SUCCESS_WITH_INFO;
133 : }
134 : return SQL_SUCCESS;
135 : }
136 :
137 : SQLRETURN SQL_API
138 : SQLGetDiagRec(SQLSMALLINT HandleType,
139 : SQLHANDLE Handle,
140 : SQLSMALLINT RecNumber,
141 : SQLCHAR *SQLState,
142 : SQLINTEGER *NativeErrorPtr,
143 : SQLCHAR *MessageText,
144 : SQLSMALLINT BufferLength,
145 : SQLSMALLINT *TextLengthPtr)
146 : {
147 : #ifdef ODBCDEBUG
148 15 : ODBCLOG("SQLGetDiagRec %s %p %d %d\n",
149 : HandleType == SQL_HANDLE_ENV ? "Env" : HandleType == SQL_HANDLE_DBC ? "Dbc" : HandleType == SQL_HANDLE_STMT ? "Stmt" : "Desc",
150 : Handle, (int) RecNumber, (int) BufferLength);
151 : #endif
152 :
153 15 : return MNDBGetDiagRec(HandleType,
154 : Handle,
155 : RecNumber,
156 : SQLState,
157 : NativeErrorPtr,
158 : MessageText,
159 : BufferLength,
160 : TextLengthPtr);
161 : }
162 :
163 : SQLRETURN SQL_API
164 : SQLGetDiagRecA(SQLSMALLINT HandleType,
165 : SQLHANDLE Handle,
166 : SQLSMALLINT RecNumber,
167 : SQLCHAR *SQLState,
168 : SQLINTEGER *NativeErrorPtr,
169 : SQLCHAR *MessageText,
170 : SQLSMALLINT BufferLength,
171 : SQLSMALLINT *TextLengthPtr)
172 : {
173 0 : return SQLGetDiagRec(HandleType,
174 : Handle,
175 : RecNumber,
176 : SQLState,
177 : NativeErrorPtr,
178 : MessageText,
179 : BufferLength,
180 : TextLengthPtr);
181 : }
182 :
183 : SQLRETURN SQL_API
184 : SQLGetDiagRecW(SQLSMALLINT HandleType,
185 : SQLHANDLE Handle,
186 : SQLSMALLINT RecNumber,
187 : SQLWCHAR *SQLState,
188 : SQLINTEGER *NativeErrorPtr,
189 : SQLWCHAR *MessageText,
190 : SQLSMALLINT BufferLength,
191 : SQLSMALLINT *TextLengthPtr)
192 : {
193 32 : SQLRETURN rc;
194 32 : SQLCHAR state[6];
195 32 : SQLCHAR msg[512];
196 32 : SQLSMALLINT n;
197 :
198 : #ifdef ODBCDEBUG
199 32 : ODBCLOG("SQLGetDiagRecW %s %p %d %d\n",
200 : HandleType == SQL_HANDLE_ENV ? "Env" : HandleType == SQL_HANDLE_DBC ? "Dbc" : HandleType == SQL_HANDLE_STMT ? "Stmt" : "Desc",
201 : Handle, (int) RecNumber, (int) BufferLength);
202 : #endif
203 :
204 :
205 32 : rc = MNDBGetDiagRec(HandleType, Handle, RecNumber, state,
206 : NativeErrorPtr, msg, (SQLSMALLINT) sizeof(msg), &n);
207 : #ifdef ODBCDEBUG
208 32 : ODBCLOG("SQLGetDiagRecW: %s\n", SQL_SUCCEEDED(rc) ? (char *) msg : rc == SQL_NO_DATA ? "no error" : "failed");
209 : #endif
210 :
211 32 : if (SQL_SUCCEEDED(rc)) {
212 16 : const char *e = ODBCutf82wchar(state, 5, SQLState, 6, NULL,
213 : NULL);
214 :
215 16 : if (e)
216 : rc = SQL_ERROR;
217 : }
218 :
219 16 : if (SQL_SUCCEEDED(rc)) {
220 16 : const char *e = ODBCutf82wchar(msg, n, MessageText,
221 : BufferLength, &n, NULL);
222 :
223 16 : if (e)
224 0 : rc = SQL_ERROR;
225 16 : if (TextLengthPtr)
226 16 : *TextLengthPtr = n;
227 : }
228 :
229 32 : return rc;
230 : }
|