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 : * SQLBindParameter()
25 : * CLI Compliance: ODBC (Microsoft)
26 : *
27 : * Note: this function does not yet support Output parameters, only SQL_PARAM_INPUT.
28 : *
29 : * Author: Martin van Dinther, Sjoerd Mullender
30 : * Date : 30 Aug 2002
31 : *
32 : **********************************************************************/
33 :
34 : #include "ODBCGlobal.h"
35 : #include "ODBCStmt.h"
36 :
37 : SQLRETURN
38 9 : MNDBBindParameter(ODBCStmt *stmt,
39 : SQLUSMALLINT ParameterNumber,
40 : SQLSMALLINT InputOutputType,
41 : SQLSMALLINT ValueType,
42 : SQLSMALLINT ParameterType,
43 : SQLULEN ColumnSize,
44 : SQLSMALLINT DecimalDigits,
45 : SQLPOINTER ParameterValuePtr,
46 : SQLLEN BufferLength,
47 : SQLLEN *StrLen_or_IndPtr)
48 : {
49 9 : ODBCDesc *apd, *ipd;
50 9 : ODBCDescRec *apdrec, *ipdrec;
51 9 : SQLRETURN rc;
52 :
53 9 : if (!isValidStmt(stmt))
54 : return SQL_INVALID_HANDLE;
55 :
56 9 : clearStmtErrors(stmt);
57 :
58 : /* check input parameters */
59 9 : if (ParameterNumber <= 0) {
60 : /* Invalid descriptor index */
61 0 : addStmtError(stmt, "07009", NULL, 0);
62 0 : return SQL_ERROR;
63 : }
64 : /* For safety: limit the maximum number of columns to bind */
65 9 : if (ParameterNumber > MONETDB_MAX_BIND_COLS) {
66 : /* General error */
67 0 : addStmtError(stmt, "HY000", "Maximum number of bind columns (8192) exceeded", 0);
68 0 : return SQL_ERROR;
69 : }
70 :
71 9 : switch (InputOutputType) {
72 : case SQL_PARAM_INPUT:
73 9 : break;
74 0 : case SQL_PARAM_INPUT_OUTPUT:
75 : case SQL_PARAM_OUTPUT:
76 : /* Optional feature not implemented */
77 0 : addStmtError(stmt, "HYC00", "Output parameters are not supported", 0);
78 0 : return SQL_ERROR;
79 0 : default:
80 : /* Invalid parameter type */
81 0 : addStmtError(stmt, "HY105", NULL, 0);
82 0 : return SQL_ERROR;
83 : }
84 :
85 9 : if (ParameterValuePtr == NULL && StrLen_or_IndPtr == NULL
86 : /* && InputOutputType != SQL_PARAM_OUTPUT */ ) {
87 : /* Invalid use of null pointer */
88 0 : addStmtError(stmt, "HY009", NULL, 0);
89 0 : return SQL_ERROR;
90 : }
91 :
92 9 : if (BufferLength < 0) {
93 : /* Invalid string or buffer length */
94 0 : addStmtError(stmt, "HY090", NULL, 0);
95 0 : return SQL_ERROR;
96 : }
97 :
98 : /* can't let SQLSetDescField below do this check since it
99 : returns the wrong error code if the type is incorrect */
100 9 : switch (ValueType) {
101 : case SQL_C_CHAR:
102 : case SQL_C_WCHAR:
103 : case SQL_C_BINARY:
104 : case SQL_C_BIT:
105 : case SQL_C_STINYINT:
106 : case SQL_C_UTINYINT:
107 : case SQL_C_TINYINT:
108 : case SQL_C_SSHORT:
109 : case SQL_C_USHORT:
110 : case SQL_C_SHORT:
111 : case SQL_C_SLONG:
112 : case SQL_C_ULONG:
113 : case SQL_C_LONG:
114 : case SQL_C_SBIGINT:
115 : case SQL_C_UBIGINT:
116 : case SQL_C_NUMERIC:
117 : case SQL_C_FLOAT:
118 : case SQL_C_DOUBLE:
119 : case SQL_C_TYPE_DATE:
120 : case SQL_C_TYPE_TIME:
121 : case SQL_C_TYPE_TIMESTAMP:
122 : case SQL_C_INTERVAL_YEAR:
123 : case SQL_C_INTERVAL_MONTH:
124 : case SQL_C_INTERVAL_YEAR_TO_MONTH:
125 : case SQL_C_INTERVAL_DAY:
126 : case SQL_C_INTERVAL_HOUR:
127 : case SQL_C_INTERVAL_MINUTE:
128 : case SQL_C_INTERVAL_SECOND:
129 : case SQL_C_INTERVAL_DAY_TO_HOUR:
130 : case SQL_C_INTERVAL_DAY_TO_MINUTE:
131 : case SQL_C_INTERVAL_DAY_TO_SECOND:
132 : case SQL_C_INTERVAL_HOUR_TO_MINUTE:
133 : case SQL_C_INTERVAL_HOUR_TO_SECOND:
134 : case SQL_C_INTERVAL_MINUTE_TO_SECOND:
135 : case SQL_C_GUID:
136 : case SQL_C_DEFAULT:
137 9 : break;
138 0 : default:
139 : /* Invalid application buffer type */
140 0 : addStmtError(stmt, "HY003", NULL, 0);
141 0 : return SQL_ERROR;
142 : }
143 :
144 9 : apd = stmt->ApplParamDescr;
145 9 : ipd = stmt->ImplParamDescr;
146 :
147 9 : apdrec = addODBCDescRec(apd, ParameterNumber);
148 9 : ipdrec = addODBCDescRec(ipd, ParameterNumber);
149 :
150 : /* we disallow types not supported by the server */
151 9 : switch (ParameterType) {
152 1 : case SQL_CHAR:
153 : case SQL_VARCHAR:
154 : case SQL_LONGVARCHAR:
155 : /* case SQL_BINARY: */
156 : case SQL_VARBINARY:
157 : case SQL_LONGVARBINARY:
158 : case SQL_TYPE_DATE:
159 : case SQL_INTERVAL_MONTH:
160 : /* case SQL_INTERVAL_YEAR: */
161 : /* case SQL_INTERVAL_YEAR_TO_MONTH: */
162 : /* case SQL_INTERVAL_DAY: */
163 : /* case SQL_INTERVAL_HOUR: */
164 : /* case SQL_INTERVAL_MINUTE: */
165 : /* case SQL_INTERVAL_DAY_TO_HOUR: */
166 : /* case SQL_INTERVAL_DAY_TO_MINUTE: */
167 : /* case SQL_INTERVAL_HOUR_TO_MINUTE: */
168 1 : ipdrec->sql_desc_length = ColumnSize;
169 1 : break;
170 1 : case SQL_TYPE_TIME:
171 : case SQL_TYPE_TIMESTAMP:
172 : case SQL_INTERVAL_SECOND:
173 : /* case SQL_INTERVAL_DAY_TO_SECOND: */
174 : /* case SQL_INTERVAL_HOUR_TO_SECOND: */
175 : /* case SQL_INTERVAL_MINUTE_TO_SECOND: */
176 1 : ipdrec->sql_desc_precision = DecimalDigits;
177 1 : ipdrec->sql_desc_length = ColumnSize;
178 1 : break;
179 0 : case SQL_DECIMAL:
180 : case SQL_NUMERIC:
181 0 : ipdrec->sql_desc_precision = (SQLSMALLINT) ColumnSize;
182 0 : ipdrec->sql_desc_scale = DecimalDigits;
183 0 : break;
184 1 : case SQL_FLOAT:
185 : case SQL_REAL:
186 : case SQL_DOUBLE:
187 1 : ipdrec->sql_desc_precision = (SQLSMALLINT) ColumnSize;
188 1 : break;
189 : case SQL_WCHAR:
190 : case SQL_WVARCHAR:
191 : case SQL_WLONGVARCHAR:
192 : case SQL_BIT:
193 : case SQL_TINYINT:
194 : case SQL_SMALLINT:
195 : case SQL_INTEGER:
196 : case SQL_BIGINT:
197 : case SQL_HUGEINT:
198 : case SQL_GUID:
199 : break;
200 0 : default:
201 : /* Invalid SQL data type */
202 0 : addStmtError(stmt, "HY004", NULL, 0);
203 0 : return SQL_ERROR;
204 :
205 : /* these types are not allowed by the server */
206 0 : case SQL_BINARY:
207 : case SQL_INTERVAL_YEAR:
208 : case SQL_INTERVAL_YEAR_TO_MONTH:
209 : case SQL_INTERVAL_DAY:
210 : case SQL_INTERVAL_HOUR:
211 : case SQL_INTERVAL_MINUTE:
212 : case SQL_INTERVAL_DAY_TO_HOUR:
213 : case SQL_INTERVAL_DAY_TO_MINUTE:
214 : case SQL_INTERVAL_HOUR_TO_MINUTE:
215 : case SQL_INTERVAL_DAY_TO_SECOND:
216 : case SQL_INTERVAL_HOUR_TO_SECOND:
217 : case SQL_INTERVAL_MINUTE_TO_SECOND:
218 : /* Optional feature not implemented */
219 0 : addStmtError(stmt, "HYC00", NULL, 0);
220 0 : return SQL_ERROR;
221 : }
222 :
223 9 : rc = MNDBSetDescField(apd, ParameterNumber, SQL_DESC_CONCISE_TYPE, (SQLPOINTER) (intptr_t) ValueType, 0);
224 9 : if (!SQL_SUCCEEDED(rc))
225 : return rc;
226 9 : rc = MNDBSetDescField(ipd, ParameterNumber, SQL_DESC_CONCISE_TYPE, (SQLPOINTER) (intptr_t) ParameterType, 0);
227 9 : if (!SQL_SUCCEEDED(rc))
228 : return rc;
229 9 : ipdrec->sql_desc_parameter_type = InputOutputType;
230 9 : apdrec->sql_desc_data_ptr = ParameterValuePtr;
231 9 : apdrec->sql_desc_octet_length = BufferLength;
232 9 : apdrec->sql_desc_indicator_ptr = StrLen_or_IndPtr;
233 9 : apdrec->sql_desc_octet_length_ptr = StrLen_or_IndPtr;
234 :
235 9 : return SQL_SUCCESS;
236 : }
237 :
238 : SQLRETURN SQL_API
239 : SQLBindParameter(SQLHSTMT StatementHandle,
240 : SQLUSMALLINT ParameterNumber,
241 : SQLSMALLINT InputOutputType,
242 : SQLSMALLINT ValueType,
243 : SQLSMALLINT ParameterType,
244 : SQLULEN ColumnSize,
245 : SQLSMALLINT DecimalDigits,
246 : SQLPOINTER ParameterValuePtr,
247 : SQLLEN BufferLength,
248 : SQLLEN *StrLen_or_IndPtr)
249 : {
250 : #ifdef ODBCDEBUG
251 9 : ODBCLOG("SQLBindParameter %p %u %d %s %s " ULENFMT " %d %p " LENFMT " %p\n",
252 : StatementHandle, (unsigned int) ParameterNumber,
253 : (int) InputOutputType, translateCType(ValueType),
254 : translateSQLType(ParameterType),
255 : ULENCAST ColumnSize, (int) DecimalDigits,
256 : ParameterValuePtr, LENCAST BufferLength,
257 : StrLen_or_IndPtr);
258 : #endif
259 :
260 9 : return MNDBBindParameter((ODBCStmt *) StatementHandle, ParameterNumber,
261 : InputOutputType, ValueType, ParameterType,
262 : ColumnSize, DecimalDigits, ParameterValuePtr,
263 : BufferLength, StrLen_or_IndPtr);
264 : }
|