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 : * SQLSetDescField()
25 : * CLI Compliance: ISO 92
26 : **********************************************************************/
27 :
28 : #include "ODBCGlobal.h"
29 : #include "ODBCStmt.h"
30 : #include "ODBCUtil.h"
31 :
32 : SQLRETURN
33 30 : MNDBSetDescField(ODBCDesc *desc,
34 : SQLSMALLINT RecNumber,
35 : SQLSMALLINT FieldIdentifier,
36 : SQLPOINTER ValuePtr,
37 : SQLINTEGER BufferLength)
38 : {
39 30 : ODBCDescRec *rec;
40 30 : struct sql_types *tp;
41 :
42 30 : if (isAD(desc))
43 : tp = ODBC_c_types;
44 : else
45 9 : tp = ODBC_sql_types;
46 :
47 30 : switch (FieldIdentifier) {
48 0 : case SQL_DESC_ALLOC_TYPE: /* SQLSMALLINT */
49 : /* Invalid descriptor field identifier */
50 0 : addDescError(desc, "HY091", NULL, 0);
51 0 : return SQL_ERROR;
52 0 : case SQL_DESC_ARRAY_SIZE: /* SQLULEN */
53 0 : if ((SQLULEN) (uintptr_t) ValuePtr == 0) {
54 : /* Invalid attribute/option identifier */
55 0 : addDescError(desc, "HY092", NULL, 0);
56 0 : return SQL_ERROR;
57 : }
58 0 : if (isAD(desc)) {
59 : /* limit size to protect against bugs */
60 0 : if ((SQLULEN) (uintptr_t) ValuePtr > 10000) {
61 : /* Driver does not support this function */
62 0 : addDescError(desc, "IM001", NULL, 0);
63 0 : return SQL_ERROR;
64 : }
65 0 : desc->sql_desc_array_size = (SQLULEN) (uintptr_t) ValuePtr;
66 : }
67 : return SQL_SUCCESS;
68 0 : case SQL_DESC_ARRAY_STATUS_PTR: /* SQLUSMALLINT * */
69 0 : desc->sql_desc_array_status_ptr = (SQLUSMALLINT *) ValuePtr;
70 0 : return SQL_SUCCESS;
71 0 : case SQL_DESC_BIND_OFFSET_PTR: /* SQLLEN * */
72 0 : if (isAD(desc))
73 0 : desc->sql_desc_bind_offset_ptr = (SQLLEN *) ValuePtr;
74 : return SQL_SUCCESS;
75 0 : case SQL_DESC_BIND_TYPE: /* SQLINTEGER */
76 0 : if (isAD(desc))
77 0 : desc->sql_desc_bind_type = (SQLINTEGER) (intptr_t) ValuePtr;
78 : return SQL_SUCCESS;
79 0 : case SQL_DESC_COUNT: /* SQLSMALLINT */
80 0 : if (isIRD(desc)) {
81 : /* Invalid descriptor field identifier */
82 0 : addDescError(desc, "HY091", NULL, 0);
83 0 : return SQL_ERROR;
84 : }
85 0 : setODBCDescRecCount(desc, (int) (SQLSMALLINT) (intptr_t) ValuePtr);
86 0 : return SQL_SUCCESS;
87 0 : case SQL_DESC_ROWS_PROCESSED_PTR: /* SQLULEN * */
88 0 : if (desc->Stmt)
89 0 : desc->sql_desc_rows_processed_ptr = (SQLULEN *) ValuePtr;
90 : return SQL_SUCCESS;
91 : }
92 :
93 30 : if (RecNumber <= 0) {
94 : /* Invalid descriptor index */
95 0 : addDescError(desc, "07009", NULL, 0);
96 0 : return SQL_ERROR;
97 : }
98 30 : if (RecNumber > desc->sql_desc_count)
99 : return SQL_NO_DATA;
100 :
101 30 : if (isIRD(desc)) {
102 : /* the Implementation Row Descriptor is read-only */
103 : /* Invalid descriptor field identifier */
104 0 : addDescError(desc, "HY091", NULL, 0);
105 0 : return SQL_ERROR;
106 : }
107 :
108 30 : rec = &desc->descRec[RecNumber];
109 :
110 : /* break for read-only fields since the error is the same as
111 : unknown FieldIdentifier */
112 30 : switch (FieldIdentifier) {
113 : case SQL_DESC_AUTO_UNIQUE_VALUE: /* SQLINTEGER */
114 : case SQL_DESC_BASE_COLUMN_NAME: /* SQLCHAR * */
115 : case SQL_DESC_BASE_TABLE_NAME: /* SQLCHAR * */
116 : case SQL_DESC_CASE_SENSITIVE: /* SQLINTEGER */
117 : case SQL_DESC_CATALOG_NAME: /* SQLCHAR * */
118 : case SQL_DESC_DISPLAY_SIZE: /* SQLLEN */
119 : case SQL_DESC_FIXED_PREC_SCALE: /* SQLSMALLINT */
120 : case SQL_DESC_LABEL: /* SQLCHAR * */
121 : case SQL_DESC_LITERAL_PREFIX: /* SQLCHAR * */
122 : case SQL_DESC_LITERAL_SUFFIX: /* SQLCHAR * */
123 : case SQL_DESC_LOCAL_TYPE_NAME: /* SQLCHAR * */
124 : case SQL_DESC_NULLABLE: /* SQLSMALLINT */
125 : case SQL_DESC_ROWVER: /* SQLSMALLINT */
126 : case SQL_DESC_SCHEMA_NAME: /* SQLCHAR * */
127 : case SQL_DESC_SEARCHABLE: /* SQLSMALLINT */
128 : case SQL_DESC_TABLE_NAME: /* SQLCHAR * */
129 : case SQL_DESC_TYPE_NAME: /* SQLCHAR * */
130 : case SQL_DESC_UNSIGNED: /* SQLSMALLINT */
131 : case SQL_DESC_UPDATABLE: /* SQLSMALLINT */
132 : break; /* read-only or unused */
133 : case SQL_DESC_CONCISE_TYPE: /* SQLSMALLINT */
134 368 : while (tp->concise_type != 0) {
135 368 : if ((intptr_t) tp->concise_type == (intptr_t) ValuePtr) {
136 30 : if (tp->concise_type == SQL_HUGEINT)
137 0 : desc->Dbc->allow_hugeint = true;
138 30 : rec->sql_desc_concise_type = tp->concise_type;
139 30 : rec->sql_desc_type = tp->type;
140 30 : rec->sql_desc_datetime_interval_code = tp->code;
141 30 : if (tp->precision != UNAFFECTED)
142 15 : rec->sql_desc_precision = tp->precision;
143 30 : if (tp->datetime_interval_precision != UNAFFECTED)
144 0 : rec->sql_desc_datetime_interval_precision = tp->datetime_interval_precision;
145 30 : if (tp->length != UNAFFECTED)
146 3 : rec->sql_desc_length = tp->length;
147 30 : if (tp->scale != UNAFFECTED)
148 0 : rec->sql_desc_scale = tp->scale;
149 30 : rec->sql_desc_fixed_prec_scale = tp->fixed;
150 30 : rec->sql_desc_num_prec_radix = tp->radix;
151 30 : return SQL_SUCCESS;
152 : }
153 338 : tp++;
154 : }
155 : /* Invalid attribute/option identifier */
156 0 : addDescError(desc, "HY092", NULL, 0);
157 0 : return SQL_ERROR;
158 0 : case SQL_DESC_DATA_PTR: /* SQLPOINTER */
159 : /* TODO: consistency check */
160 0 : rec->sql_desc_data_ptr = ValuePtr;
161 0 : return SQL_SUCCESS;
162 : case SQL_DESC_DATETIME_INTERVAL_CODE: /* SQLSMALLINT */
163 0 : while (tp->concise_type != 0) {
164 0 : if ((intptr_t) tp->code == (intptr_t) ValuePtr &&
165 0 : tp->type == rec->sql_desc_type) {
166 0 : rec->sql_desc_concise_type = tp->concise_type;
167 0 : rec->sql_desc_type = tp->type;
168 0 : rec->sql_desc_datetime_interval_code = tp->code;
169 0 : if (tp->precision != UNAFFECTED)
170 0 : rec->sql_desc_precision = tp->precision;
171 0 : if (tp->datetime_interval_precision != UNAFFECTED)
172 0 : rec->sql_desc_datetime_interval_precision = tp->datetime_interval_precision;
173 0 : if (tp->length != UNAFFECTED)
174 0 : rec->sql_desc_length = tp->length;
175 0 : if (tp->scale != UNAFFECTED)
176 0 : rec->sql_desc_scale = tp->scale;
177 0 : rec->sql_desc_fixed_prec_scale = tp->fixed;
178 0 : rec->sql_desc_num_prec_radix = tp->radix;
179 0 : return SQL_SUCCESS;
180 : }
181 0 : tp++;
182 : }
183 : /* Inconsistent descriptor information */
184 0 : addDescError(desc, "HY021", NULL, 0);
185 0 : return SQL_ERROR;
186 0 : case SQL_DESC_DATETIME_INTERVAL_PRECISION: /* SQLINTEGER */
187 0 : rec->sql_desc_datetime_interval_precision = (SQLINTEGER) (intptr_t) ValuePtr;
188 0 : return SQL_SUCCESS;
189 0 : case SQL_DESC_INDICATOR_PTR: /* SQLLEN * */
190 0 : if (isAD(desc))
191 0 : rec->sql_desc_indicator_ptr = (SQLLEN *) ValuePtr;
192 : return SQL_SUCCESS;
193 0 : case SQL_DESC_LENGTH: /* SQLULEN */
194 0 : rec->sql_desc_length = (SQLULEN) (uintptr_t) ValuePtr;
195 0 : return SQL_SUCCESS;
196 0 : case SQL_DESC_NAME: /* SQLCHAR * */
197 0 : if (isID(desc)) {
198 0 : fixODBCstring(ValuePtr, BufferLength, SQLINTEGER,
199 : addDescError, desc, return SQL_ERROR);
200 0 : if (rec->sql_desc_name != NULL)
201 0 : free(rec->sql_desc_name);
202 0 : rec->sql_desc_name = (SQLCHAR *) dupODBCstring((SQLCHAR *) ValuePtr, (size_t) BufferLength);
203 0 : if (rec->sql_desc_name == NULL) {
204 : /* Memory allocation error */
205 0 : addDescError(desc, "HY001", NULL, 0);
206 0 : return SQL_ERROR;
207 : }
208 0 : rec->sql_desc_unnamed = *rec->sql_desc_name ? SQL_NAMED : SQL_UNNAMED;
209 : }
210 : return SQL_SUCCESS;
211 0 : case SQL_DESC_NUM_PREC_RADIX:
212 0 : rec->sql_desc_num_prec_radix = (SQLINTEGER) (intptr_t) ValuePtr;
213 0 : return SQL_SUCCESS;
214 0 : case SQL_DESC_OCTET_LENGTH: /* SQLLEN */
215 0 : rec->sql_desc_octet_length = (SQLLEN) (intptr_t) ValuePtr;
216 0 : return SQL_SUCCESS;
217 0 : case SQL_DESC_OCTET_LENGTH_PTR: /* SQLLEN * */
218 0 : if (isAD(desc))
219 0 : rec->sql_desc_octet_length_ptr = (SQLLEN *) ValuePtr;
220 : return SQL_SUCCESS;
221 0 : case SQL_DESC_PARAMETER_TYPE: /* SQLSMALLINT */
222 0 : switch ((SQLSMALLINT) (intptr_t) ValuePtr) {
223 : case SQL_PARAM_INPUT:
224 0 : break;
225 0 : case SQL_PARAM_INPUT_OUTPUT:
226 : case SQL_PARAM_OUTPUT:
227 : /* Driver does not support this function */
228 0 : addDescError(desc, "IM001", NULL, 0);
229 0 : return SQL_ERROR;
230 0 : default:
231 : /* Invalid attribute/option identifier */
232 0 : addDescError(desc, "HY092", NULL, 0);
233 0 : return SQL_ERROR;
234 : }
235 0 : if (isIPD(desc))
236 0 : rec->sql_desc_parameter_type = (SQLSMALLINT) (intptr_t) ValuePtr;
237 : return SQL_SUCCESS;
238 0 : case SQL_DESC_PRECISION: /* SQLSMALLINT */
239 0 : rec->sql_desc_precision = (SQLSMALLINT) (intptr_t) ValuePtr;
240 0 : return SQL_SUCCESS;
241 0 : case SQL_DESC_SCALE: /* SQLSMALLINT */
242 0 : rec->sql_desc_scale = (SQLSMALLINT) (intptr_t) ValuePtr;
243 0 : return SQL_SUCCESS;
244 : case SQL_DESC_TYPE: /* SQLSMALLINT */
245 0 : while (tp->concise_type != 0) {
246 0 : if ((SQLSMALLINT) (intptr_t) ValuePtr == tp->type &&
247 0 : (((SQLSMALLINT) (intptr_t) ValuePtr != SQL_DATETIME &&
248 0 : (SQLSMALLINT) (intptr_t) ValuePtr != SQL_INTERVAL) ||
249 0 : tp->code == rec->sql_desc_datetime_interval_code)) {
250 0 : if (tp->concise_type == SQL_HUGEINT)
251 0 : desc->Dbc->allow_hugeint = true;
252 0 : rec->sql_desc_concise_type = tp->concise_type;
253 0 : rec->sql_desc_type = tp->type;
254 0 : rec->sql_desc_datetime_interval_code = tp->code;
255 0 : if (tp->precision != UNAFFECTED)
256 0 : rec->sql_desc_precision = tp->precision;
257 0 : if (tp->datetime_interval_precision != UNAFFECTED)
258 0 : rec->sql_desc_datetime_interval_precision = tp->datetime_interval_precision;
259 0 : if (tp->length != UNAFFECTED)
260 0 : rec->sql_desc_length = tp->length;
261 0 : if (tp->scale != UNAFFECTED)
262 0 : rec->sql_desc_scale = tp->scale;
263 0 : rec->sql_desc_fixed_prec_scale = tp->fixed;
264 0 : rec->sql_desc_num_prec_radix = tp->radix;
265 0 : return SQL_SUCCESS;
266 : }
267 0 : tp++;
268 : }
269 : /* Inconsistent descriptor information */
270 0 : addDescError(desc, "HY021", NULL, 0);
271 0 : return SQL_ERROR;
272 0 : case SQL_DESC_UNNAMED: /* SQLSMALLINT */
273 0 : if ((SQLSMALLINT) (intptr_t) ValuePtr == SQL_NAMED) {
274 : /* Invalid descriptor field identifier */
275 0 : addDescError(desc, "HY091", NULL, 0);
276 0 : return SQL_ERROR;
277 0 : } else if ((SQLSMALLINT) (intptr_t) ValuePtr == SQL_UNNAMED && isIPD(desc)) {
278 0 : rec->sql_desc_unnamed = SQL_UNNAMED;
279 0 : if (rec->sql_desc_name)
280 0 : free(rec->sql_desc_name);
281 0 : rec->sql_desc_name = NULL;
282 0 : return SQL_SUCCESS;
283 : }
284 : /* Inconsistent descriptor information */
285 0 : addDescError(desc, "HY021", NULL, 0);
286 0 : return SQL_ERROR;
287 : }
288 :
289 : /* Invalid descriptor field identifier */
290 0 : addDescError(desc, "HY091", NULL, 0);
291 0 : return SQL_ERROR;
292 : }
293 :
294 : SQLRETURN SQL_API
295 : SQLSetDescField(SQLHDESC DescriptorHandle,
296 : SQLSMALLINT RecNumber,
297 : SQLSMALLINT FieldIdentifier,
298 : SQLPOINTER ValuePtr,
299 : SQLINTEGER BufferLength)
300 : {
301 : #ifdef ODBCDEBUG
302 0 : ODBCLOG("SQLSetDescField %p %d %s %p %d\n",
303 : DescriptorHandle, (int) RecNumber,
304 : translateFieldIdentifier(FieldIdentifier),
305 : ValuePtr, (int) BufferLength);
306 : #endif
307 :
308 0 : if (!isValidDesc((ODBCDesc *) DescriptorHandle))
309 : return SQL_INVALID_HANDLE;
310 :
311 0 : clearDescErrors((ODBCDesc *) DescriptorHandle);
312 :
313 0 : return MNDBSetDescField((ODBCDesc *) DescriptorHandle, RecNumber, FieldIdentifier, ValuePtr, BufferLength);
314 : }
315 :
316 : SQLRETURN SQL_API
317 : SQLSetDescFieldW(SQLHDESC DescriptorHandle,
318 : SQLSMALLINT RecNumber,
319 : SQLSMALLINT FieldIdentifier,
320 : SQLPOINTER ValuePtr,
321 : SQLINTEGER BufferLength)
322 : {
323 0 : ODBCDesc *desc = (ODBCDesc *) DescriptorHandle;
324 0 : SQLRETURN rc;
325 0 : SQLPOINTER ptr;
326 0 : SQLINTEGER n;
327 :
328 : #ifdef ODBCDEBUG
329 0 : ODBCLOG("SQLSetDescFieldW %p %d %s %p %d\n",
330 : DescriptorHandle, (int) RecNumber,
331 : translateFieldIdentifier(FieldIdentifier),
332 : ValuePtr, (int) BufferLength);
333 : #endif
334 :
335 0 : if (!isValidDesc(desc))
336 : return SQL_INVALID_HANDLE;
337 :
338 0 : clearDescErrors(desc);
339 :
340 0 : switch (FieldIdentifier) {
341 0 : case SQL_DESC_NAME:
342 0 : if (BufferLength > 0) /* convert from bytes to characters */
343 0 : BufferLength /= 2;
344 0 : fixWcharIn(ValuePtr, BufferLength, SQLCHAR, ptr,
345 : addDescError, desc, return SQL_ERROR);
346 0 : n = SQL_NTS;
347 0 : break;
348 : default:
349 : ptr = ValuePtr;
350 : n = BufferLength;
351 : break;
352 : }
353 :
354 0 : rc = MNDBSetDescField(desc, RecNumber, FieldIdentifier, ptr, n);
355 :
356 0 : if (ptr && ptr != ValuePtr)
357 0 : free(ptr);
358 :
359 : return rc;
360 : }
|