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 : * SQLGetDescField()
25 : * CLI Compliance: ISO 92
26 : **********************************************************************/
27 :
28 : #include "ODBCGlobal.h"
29 : #include "ODBCStmt.h"
30 : #include "ODBCUtil.h"
31 :
32 : SQLRETURN
33 0 : MNDBGetDescField(ODBCDesc *desc,
34 : SQLSMALLINT RecordNumber,
35 : SQLSMALLINT FieldIdentifier,
36 : SQLPOINTER ValuePtr,
37 : SQLINTEGER BufferLength,
38 : SQLINTEGER *StringLengthPtr)
39 : {
40 0 : ODBCDescRec *rec;
41 :
42 0 : if (isIRD(desc)) {
43 0 : if (desc->Stmt->State == INITED) {
44 : /* Function sequence error */
45 0 : addDescError(desc, "HY010", NULL, 0);
46 0 : return SQL_ERROR;
47 : }
48 0 : if (desc->Stmt->State == EXECUTED0) {
49 : /* Invalid cursor state */
50 0 : addDescError(desc, "24000", NULL, 0);
51 0 : return SQL_ERROR;
52 : }
53 0 : if (desc->Stmt->State == PREPARED0)
54 : return SQL_NO_DATA;
55 : }
56 :
57 : /* header fields ignore RecordNumber */
58 0 : switch (FieldIdentifier) {
59 0 : case SQL_DESC_ALLOC_TYPE: /* SQLSMALLINT */
60 0 : WriteData(ValuePtr, desc->sql_desc_alloc_type, SQLSMALLINT);
61 : return SQL_SUCCESS;
62 0 : case SQL_DESC_ARRAY_SIZE: /* SQLULEN */
63 0 : if (isAD(desc))
64 0 : WriteData(ValuePtr, desc->sql_desc_array_size, SQLULEN);
65 : return SQL_SUCCESS;
66 0 : case SQL_DESC_ARRAY_STATUS_PTR: /* SQLUSMALLINT * */
67 0 : WriteData(ValuePtr, desc->sql_desc_array_status_ptr, SQLUSMALLINT *);
68 : return SQL_SUCCESS;
69 0 : case SQL_DESC_BIND_OFFSET_PTR: /* SQLLEN * */
70 0 : if (isAD(desc))
71 0 : WriteData(ValuePtr, desc->sql_desc_bind_offset_ptr, SQLLEN *);
72 : return SQL_SUCCESS;
73 0 : case SQL_DESC_BIND_TYPE: /* SQLINTEGER */
74 0 : if (isAD(desc))
75 0 : WriteData(ValuePtr, desc->sql_desc_bind_type, SQLINTEGER);
76 : return SQL_SUCCESS;
77 0 : case SQL_DESC_COUNT: /* SQLSMALLINT */
78 0 : WriteData(ValuePtr, desc->sql_desc_count, SQLSMALLINT);
79 : return SQL_SUCCESS;
80 0 : case SQL_DESC_ROWS_PROCESSED_PTR: /* SQLULEN * */
81 0 : if (desc->Stmt)
82 0 : WriteData(ValuePtr, desc->sql_desc_rows_processed_ptr, SQLULEN *);
83 : return SQL_SUCCESS;
84 : }
85 :
86 0 : if (RecordNumber <= 0) {
87 : /* Invalid descriptor index */
88 0 : addDescError(desc, "07009", NULL, 0);
89 0 : return SQL_ERROR;
90 : }
91 0 : if (RecordNumber > desc->sql_desc_count)
92 : return SQL_NO_DATA;
93 :
94 0 : rec = &desc->descRec[RecordNumber];
95 :
96 0 : switch (FieldIdentifier) {
97 0 : case SQL_DESC_AUTO_UNIQUE_VALUE: /* SQLINTEGER */
98 0 : if (isIRD(desc))
99 0 : WriteData(ValuePtr, rec->sql_desc_auto_unique_value, SQLINTEGER);
100 : return SQL_SUCCESS;
101 0 : case SQL_DESC_BASE_COLUMN_NAME: /* SQLCHAR * */
102 0 : if (isIRD(desc))
103 0 : copyString(rec->sql_desc_base_column_name,
104 : strlen((char *) rec->sql_desc_base_column_name),
105 : ValuePtr, BufferLength, StringLengthPtr,
106 : SQLINTEGER, addDescError, desc,
107 : return SQL_ERROR);
108 0 : return desc->Error ? SQL_SUCCESS_WITH_INFO : SQL_SUCCESS;
109 0 : case SQL_DESC_BASE_TABLE_NAME: /* SQLCHAR * */
110 0 : if (isIRD(desc))
111 0 : copyString(rec->sql_desc_base_table_name,
112 : strlen((char *) rec->sql_desc_base_table_name),
113 : ValuePtr, BufferLength, StringLengthPtr,
114 : SQLINTEGER, addDescError, desc,
115 : return SQL_ERROR);
116 0 : return desc->Error ? SQL_SUCCESS_WITH_INFO : SQL_SUCCESS;
117 0 : case SQL_DESC_CASE_SENSITIVE: /* SQLINTEGER */
118 0 : if (isID(desc))
119 0 : WriteData(ValuePtr, rec->sql_desc_case_sensitive, SQLINTEGER);
120 : return SQL_SUCCESS;
121 0 : case SQL_DESC_CATALOG_NAME: /* SQLCHAR * */
122 0 : if (isIRD(desc))
123 0 : copyString(rec->sql_desc_catalog_name,
124 : strlen((char *) rec->sql_desc_catalog_name),
125 : ValuePtr, BufferLength, StringLengthPtr,
126 : SQLINTEGER, addDescError, desc,
127 : return SQL_ERROR);
128 0 : return desc->Error ? SQL_SUCCESS_WITH_INFO : SQL_SUCCESS;
129 0 : case SQL_DESC_CONCISE_TYPE: /* SQLSMALLINT */
130 0 : WriteData(ValuePtr, rec->sql_desc_concise_type, SQLSMALLINT);
131 : return SQL_SUCCESS;
132 0 : case SQL_DESC_DATA_PTR: /* SQLPOINTER */
133 : #ifndef __COVERITY__
134 : /* Coverity doesn't like the debug print in WriteData,
135 : * so we hide this whole thing */
136 0 : if (!isIRD(desc))
137 0 : WriteData(ValuePtr, rec->sql_desc_data_ptr, SQLPOINTER);
138 : #endif
139 : return SQL_SUCCESS;
140 0 : case SQL_DESC_DATETIME_INTERVAL_CODE: /* SQLSMALLINT */
141 0 : WriteData(ValuePtr, rec->sql_desc_datetime_interval_code, SQLSMALLINT);
142 : return SQL_SUCCESS;
143 0 : case SQL_DESC_DATETIME_INTERVAL_PRECISION: /* SQLINTEGER */
144 0 : WriteData(ValuePtr, rec->sql_desc_datetime_interval_precision, SQLINTEGER);
145 : return SQL_SUCCESS;
146 0 : case SQL_DESC_DISPLAY_SIZE: /* SQLLEN */
147 0 : if (isIRD(desc))
148 0 : WriteData(ValuePtr, (SQLINTEGER) rec->sql_desc_display_size, SQLLEN);
149 : return SQL_SUCCESS;
150 0 : case SQL_DESC_FIXED_PREC_SCALE: /* SQLSMALLINT */
151 0 : if (isID(desc))
152 0 : WriteData(ValuePtr, rec->sql_desc_fixed_prec_scale, SQLSMALLINT);
153 : return SQL_SUCCESS;
154 0 : case SQL_DESC_INDICATOR_PTR: /* SQLLEN * */
155 0 : if (isAD(desc))
156 0 : WriteData(ValuePtr, rec->sql_desc_indicator_ptr, SQLLEN *);
157 : return SQL_SUCCESS;
158 0 : case SQL_DESC_LABEL: /* SQLCHAR * */
159 0 : if (isIRD(desc))
160 0 : copyString(rec->sql_desc_label,
161 : strlen((char *) rec->sql_desc_label),
162 : ValuePtr, BufferLength, StringLengthPtr,
163 : SQLINTEGER, addDescError, desc,
164 : return SQL_ERROR);
165 0 : return desc->Error ? SQL_SUCCESS_WITH_INFO : SQL_SUCCESS;
166 0 : case SQL_DESC_LENGTH: /* SQLULEN */
167 0 : WriteData(ValuePtr, (SQLUINTEGER) rec->sql_desc_length, SQLULEN);
168 : return SQL_SUCCESS;
169 0 : case SQL_DESC_LITERAL_PREFIX: /* SQLCHAR * */
170 0 : if (isIRD(desc))
171 0 : copyString(rec->sql_desc_literal_prefix,
172 : strlen((char *) rec->sql_desc_literal_prefix),
173 : ValuePtr, BufferLength, StringLengthPtr,
174 : SQLINTEGER, addDescError, desc,
175 : return SQL_ERROR);
176 0 : return desc->Error ? SQL_SUCCESS_WITH_INFO : SQL_SUCCESS;
177 0 : case SQL_DESC_LITERAL_SUFFIX: /* SQLCHAR * */
178 0 : if (isIRD(desc))
179 0 : copyString(rec->sql_desc_literal_suffix,
180 : strlen((char *) rec->sql_desc_literal_suffix),
181 : ValuePtr, BufferLength, StringLengthPtr,
182 : SQLINTEGER, addDescError, desc,
183 : return SQL_ERROR);
184 0 : return desc->Error ? SQL_SUCCESS_WITH_INFO : SQL_SUCCESS;
185 0 : case SQL_DESC_LOCAL_TYPE_NAME: /* SQLCHAR * */
186 0 : if (isID(desc))
187 0 : copyString(rec->sql_desc_local_type_name,
188 : strlen((char *) rec->sql_desc_local_type_name),
189 : ValuePtr, BufferLength, StringLengthPtr,
190 : SQLINTEGER, addDescError, desc,
191 : return SQL_ERROR);
192 0 : return desc->Error ? SQL_SUCCESS_WITH_INFO : SQL_SUCCESS;
193 0 : case SQL_DESC_NAME: /* SQLCHAR * */
194 0 : if (isID(desc))
195 0 : copyString(rec->sql_desc_name,
196 : strlen((char *) rec->sql_desc_name),
197 : ValuePtr, BufferLength, StringLengthPtr,
198 : SQLINTEGER, addDescError, desc,
199 : return SQL_ERROR);
200 0 : return desc->Error ? SQL_SUCCESS_WITH_INFO : SQL_SUCCESS;
201 0 : case SQL_DESC_NULLABLE: /* SQLSMALLINT */
202 0 : if (isID(desc))
203 0 : WriteData(ValuePtr, rec->sql_desc_nullable, SQLSMALLINT);
204 : return SQL_SUCCESS;
205 0 : case SQL_DESC_NUM_PREC_RADIX: /* SQLINTEGER */
206 0 : WriteData(ValuePtr, rec->sql_desc_num_prec_radix, SQLINTEGER);
207 : return SQL_SUCCESS;
208 0 : case SQL_DESC_OCTET_LENGTH: /* SQLLEN */
209 0 : WriteData(ValuePtr, rec->sql_desc_octet_length, SQLLEN);
210 : return SQL_SUCCESS;
211 0 : case SQL_DESC_OCTET_LENGTH_PTR: /* SQLLEN * */
212 0 : if (isAD(desc))
213 0 : WriteData(ValuePtr, rec->sql_desc_octet_length_ptr, SQLLEN *);
214 : return SQL_SUCCESS;
215 0 : case SQL_DESC_PARAMETER_TYPE: /* SQLSMALLINT */
216 0 : if (isIPD(desc))
217 0 : WriteData(ValuePtr, rec->sql_desc_parameter_type, SQLSMALLINT);
218 : return SQL_SUCCESS;
219 0 : case SQL_DESC_PRECISION: /* SQLSMALLINT */
220 0 : WriteData(ValuePtr, rec->sql_desc_precision, SQLSMALLINT);
221 : return SQL_SUCCESS;
222 0 : case SQL_DESC_ROWVER: /* SQLSMALLINT */
223 0 : if (isID(desc))
224 0 : WriteData(ValuePtr, rec->sql_desc_rowver, SQLSMALLINT);
225 : return SQL_SUCCESS;
226 0 : case SQL_DESC_SCALE: /* SQLSMALLINT */
227 0 : WriteData(ValuePtr, rec->sql_desc_scale, SQLSMALLINT);
228 : return SQL_SUCCESS;
229 0 : case SQL_DESC_SCHEMA_NAME: /* SQLCHAR * */
230 0 : if (isIRD(desc))
231 0 : copyString(rec->sql_desc_schema_name,
232 : strlen((char *) rec->sql_desc_schema_name),
233 : ValuePtr, BufferLength, StringLengthPtr,
234 : SQLINTEGER, addDescError, desc,
235 : return SQL_ERROR);
236 0 : return desc->Error ? SQL_SUCCESS_WITH_INFO : SQL_SUCCESS;
237 0 : case SQL_DESC_SEARCHABLE: /* SQLSMALLINT */
238 0 : if (isIRD(desc))
239 0 : WriteData(ValuePtr, rec->sql_desc_searchable, SQLSMALLINT);
240 : return SQL_SUCCESS;
241 0 : case SQL_DESC_TABLE_NAME: /* SQLCHAR * */
242 0 : if (isIRD(desc))
243 0 : copyString(rec->sql_desc_table_name,
244 : strlen((char *) rec->sql_desc_table_name),
245 : ValuePtr, BufferLength, StringLengthPtr,
246 : SQLINTEGER, addDescError, desc,
247 : return SQL_ERROR);
248 0 : return desc->Error ? SQL_SUCCESS_WITH_INFO : SQL_SUCCESS;
249 0 : case SQL_DESC_TYPE: /* SQLSMALLINT */
250 0 : WriteData(ValuePtr, rec->sql_desc_type, SQLSMALLINT);
251 : return SQL_SUCCESS;
252 0 : case SQL_DESC_TYPE_NAME: /* SQLCHAR * */
253 0 : if (isID(desc))
254 0 : copyString(rec->sql_desc_type_name,
255 : strlen((char *) rec->sql_desc_type_name),
256 : ValuePtr, BufferLength, StringLengthPtr,
257 : SQLINTEGER, addDescError, desc,
258 : return SQL_ERROR);
259 0 : return desc->Error ? SQL_SUCCESS_WITH_INFO : SQL_SUCCESS;
260 0 : case SQL_DESC_UNNAMED: /* SQLSMALLINT */
261 0 : if (isID(desc))
262 0 : WriteData(ValuePtr, rec->sql_desc_unnamed, SQLSMALLINT);
263 : return SQL_SUCCESS;
264 0 : case SQL_DESC_UNSIGNED: /* SQLSMALLINT */
265 0 : if (isID(desc))
266 0 : WriteData(ValuePtr, rec->sql_desc_unsigned, SQLSMALLINT);
267 : return SQL_SUCCESS;
268 0 : case SQL_DESC_UPDATABLE: /* SQLSMALLINT */
269 0 : if (isIRD(desc))
270 0 : WriteData(ValuePtr, rec->sql_desc_updatable, SQLSMALLINT);
271 : return SQL_SUCCESS;
272 : }
273 :
274 : /* Invalid descriptor field identifier */
275 0 : addDescError(desc, "HY091", NULL, 0);
276 0 : return SQL_ERROR;
277 : }
278 :
279 : SQLRETURN SQL_API
280 : SQLGetDescField(SQLHDESC DescriptorHandle,
281 : SQLSMALLINT RecordNumber,
282 : SQLSMALLINT FieldIdentifier,
283 : SQLPOINTER ValuePtr,
284 : SQLINTEGER BufferLength,
285 : SQLINTEGER *StringLengthPtr)
286 : {
287 : #ifdef ODBCDEBUG
288 0 : ODBCLOG("SQLGetDescField %p %d %s %p %d %p\n",
289 : DescriptorHandle, (int) RecordNumber,
290 : translateFieldIdentifier(FieldIdentifier),
291 : ValuePtr, (int) BufferLength,
292 : StringLengthPtr);
293 : #endif
294 :
295 0 : if (!isValidDesc((ODBCDesc *) DescriptorHandle))
296 : return SQL_INVALID_HANDLE;
297 0 : clearDescErrors((ODBCDesc *) DescriptorHandle);
298 :
299 0 : return MNDBGetDescField((ODBCDesc *) DescriptorHandle,
300 : RecordNumber,
301 : FieldIdentifier,
302 : ValuePtr,
303 : BufferLength,
304 : StringLengthPtr);
305 : }
306 :
307 : SQLRETURN SQL_API
308 : SQLGetDescFieldA(SQLHDESC DescriptorHandle,
309 : SQLSMALLINT RecordNumber,
310 : SQLSMALLINT FieldIdentifier,
311 : SQLPOINTER ValuePtr,
312 : SQLINTEGER BufferLength,
313 : SQLINTEGER *StringLengthPtr)
314 : {
315 0 : return SQLGetDescField(DescriptorHandle,
316 : RecordNumber,
317 : FieldIdentifier,
318 : ValuePtr,
319 : BufferLength,
320 : StringLengthPtr);
321 : }
322 :
323 : SQLRETURN SQL_API
324 : SQLGetDescFieldW(SQLHDESC DescriptorHandle,
325 : SQLSMALLINT RecordNumber,
326 : SQLSMALLINT FieldIdentifier,
327 : SQLPOINTER ValuePtr,
328 : SQLINTEGER BufferLength,
329 : SQLINTEGER *StringLengthPtr)
330 : {
331 0 : ODBCDesc *desc = (ODBCDesc *) DescriptorHandle;
332 0 : SQLRETURN rc;
333 0 : SQLPOINTER ptr;
334 0 : SQLINTEGER n;
335 :
336 : #ifdef ODBCDEBUG
337 0 : ODBCLOG("SQLGetDescFieldW %p %d %s %p %d %p\n",
338 : DescriptorHandle, (int) RecordNumber,
339 : translateFieldIdentifier(FieldIdentifier),
340 : ValuePtr, (int) BufferLength,
341 : StringLengthPtr);
342 : #endif
343 :
344 0 : if (!isValidDesc(desc))
345 : return SQL_INVALID_HANDLE;
346 0 : clearDescErrors(desc);
347 :
348 0 : switch (FieldIdentifier) {
349 : /* all string attributes */
350 0 : case SQL_DESC_BASE_COLUMN_NAME:
351 : case SQL_DESC_BASE_TABLE_NAME:
352 : case SQL_DESC_CATALOG_NAME:
353 : case SQL_DESC_LABEL:
354 : case SQL_DESC_LITERAL_PREFIX:
355 : case SQL_DESC_LITERAL_SUFFIX:
356 : case SQL_DESC_LOCAL_TYPE_NAME:
357 : case SQL_DESC_NAME:
358 : case SQL_DESC_SCHEMA_NAME:
359 : case SQL_DESC_TABLE_NAME:
360 : case SQL_DESC_TYPE_NAME:
361 0 : ptr = (SQLPOINTER) malloc(BufferLength);
362 0 : if (ptr == NULL) {
363 : /* Memory allocation error */
364 0 : addDescError(desc, "HY001", NULL, 0);
365 0 : return SQL_ERROR;
366 : }
367 : break;
368 : default:
369 : ptr = ValuePtr;
370 : break;
371 : }
372 :
373 0 : rc = MNDBGetDescField(desc, RecordNumber, FieldIdentifier, ptr,
374 : BufferLength, &n);
375 :
376 0 : if (ptr != ValuePtr) {
377 0 : if (rc == SQL_SUCCESS_WITH_INFO) {
378 0 : clearDescErrors(desc);
379 0 : free(ptr);
380 0 : ptr = malloc(++n); /* add one for NULL byte */
381 0 : if (ptr == NULL) {
382 : /* Memory allocation error */
383 0 : addDescError(desc, "HY001", NULL, 0);
384 0 : return SQL_ERROR;
385 : }
386 0 : rc = MNDBGetDescField(desc, RecordNumber,
387 : FieldIdentifier, ptr, n, &n);
388 : }
389 0 : if (SQL_SUCCEEDED(rc)) {
390 0 : SQLSMALLINT nn = (SQLSMALLINT) n;
391 :
392 0 : fixWcharOut(rc, ptr, nn, ValuePtr, BufferLength,
393 : StringLengthPtr, 2, addDescError, desc);
394 : }
395 0 : free(ptr);
396 0 : } else if (StringLengthPtr)
397 0 : *StringLengthPtr = n;
398 :
399 : return rc;
400 : }
|