1/*********************************************************************
2 *
3 * This is based on code created by Peter Harvey,
4 * (pharvey@codebydesign.com).
5 *
6 * Modified and extended by Nick Gorham
7 * (nick@lurcher.org).
8 *
9 * Any bugs or problems should be considered the fault of Nick and not
10 * Peter.
11 *
12 * copyright (c) 1999 Nick Gorham
13 *
14 * This library is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU Lesser General Public
16 * License as published by the Free Software Foundation; either
17 * version 2 of the License, or (at your option) any later version.
18 *
19 * This library is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22 * Lesser General Public License for more details.
23 *
24 * You should have received a copy of the GNU Lesser General Public
25 * License along with this library; if not, write to the Free Software
26 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27 *
28 **********************************************************************
29 *
30 * $Id: SQLBindCol.c,v 1.8 2009/02/18 17:59:08 lurcher Exp $
31 *
32 * $Log: SQLBindCol.c,v $
33 * Revision 1.8 2009/02/18 17:59:08 lurcher
34 * Shift to using config.h, the compile lines were making it hard to spot warnings
35 *
36 * Revision 1.7 2007/03/05 09:49:23 lurcher
37 * Get it to build on VMS again
38 *
39 * Revision 1.6 2006/04/11 10:22:56 lurcher
40 * Fix a data type check
41 *
42 * Revision 1.5 2006/03/08 11:22:13 lurcher
43 * Add check for valid C_TYPE
44 *
45 * Revision 1.4 2003/10/30 18:20:45 lurcher
46 *
47 * Fix broken thread protection
48 * Remove SQLNumResultCols after execute, lease S4/S% to driver
49 * Fix string overrun in SQLDriverConnect
50 * Add initial support for Interix
51 *
52 * Revision 1.3 2002/12/05 17:44:30 lurcher
53 *
54 * Display unknown return values in return logging
55 *
56 * Revision 1.2 2001/12/13 13:00:31 lurcher
57 *
58 * Remove most if not all warnings on 64 bit platforms
59 * Add support for new MS 3.52 64 bit changes
60 * Add override to disable the stopping of tracing
61 * Add MAX_ROWS support in postgres driver
62 *
63 * Revision 1.1.1.1 2001/10/17 16:40:05 lurcher
64 *
65 * First upload to SourceForge
66 *
67 * Revision 1.2 2001/04/12 17:43:35 nick
68 *
69 * Change logging and added autotest to odbctest
70 *
71 * Revision 1.1.1.1 2000/09/04 16:42:52 nick
72 * Imported Sources
73 *
74 * Revision 1.9 1999/11/13 23:40:58 ngorham
75 *
76 * Alter the way DM logging works
77 * Upgrade the Postgres driver to 6.4.6
78 *
79 * Revision 1.8 1999/10/24 23:54:17 ngorham
80 *
81 * First part of the changes to the error reporting
82 *
83 * Revision 1.7 1999/10/09 00:56:16 ngorham
84 *
85 * Added Manush's patch to map ODBC 3-2 datetime values
86 *
87 * Revision 1.6 1999/10/09 00:15:58 ngorham
88 *
89 * Add mapping from SQL_TYPE_X to SQL_X and SQL_C_TYPE_X to SQL_C_X
90 * when the driver is a ODBC 2 one
91 *
92 * Revision 1.5 1999/09/21 22:34:23 ngorham
93 *
94 * Improve performance by removing unneeded logging calls when logging is
95 * disabled
96 *
97 * Revision 1.4 1999/07/10 21:10:15 ngorham
98 *
99 * Adjust error sqlstate from driver manager, depending on requested
100 * version (ODBC2/3)
101 *
102 * Revision 1.3 1999/07/04 21:05:06 ngorham
103 *
104 * Add LGPL Headers to code
105 *
106 * Revision 1.2 1999/06/30 23:56:54 ngorham
107 *
108 * Add initial thread safety code
109 *
110 * Revision 1.1.1.1 1999/05/29 13:41:05 sShandyb
111 * first go at it
112 *
113 * Revision 1.1.1.1 1999/05/27 18:23:17 pharvey
114 * Imported sources
115 *
116 * Revision 1.3 1999/04/30 16:22:47 nick
117 * Another checkpoint
118 *
119 * Revision 1.2 1999/04/29 20:47:37 nick
120 * Another checkpoint
121 *
122 * Revision 1.1 1999/04/25 23:02:41 nick
123 * Initial revision
124 *
125 *
126 **********************************************************************/
127
128#include <config.h>
129#include "drivermanager.h"
130
131static char const rcsid[]= "$RCSfile: SQLBindCol.c,v $ $Revision: 1.8 $";
132
133int check_target_type( int c_type, int connection_mode)
134{
135 /*
136 * driver defined types
137 */
138 if ( connection_mode >= SQL_OV_ODBC3_80 && c_type >= 0x4000 && c_type <= 0x7FFF ) {
139 return 1;
140 }
141
142 switch( c_type ) {
143 case SQL_C_CHAR:
144 case SQL_C_LONG:
145 case SQL_C_SHORT:
146 case SQL_C_FLOAT:
147 case SQL_C_NUMERIC:
148 case SQL_C_DEFAULT:
149 case SQL_C_DATE:
150 case SQL_C_TIME:
151 case SQL_C_TIMESTAMP:
152 case SQL_C_TYPE_DATE:
153 case SQL_C_TYPE_TIME:
154 case SQL_C_TYPE_TIMESTAMP:
155 case SQL_C_INTERVAL_YEAR:
156 case SQL_C_INTERVAL_MONTH:
157 case SQL_C_INTERVAL_DAY:
158 case SQL_C_INTERVAL_HOUR:
159 case SQL_C_INTERVAL_MINUTE:
160 case SQL_C_INTERVAL_SECOND:
161 case SQL_C_INTERVAL_YEAR_TO_MONTH:
162 case SQL_C_INTERVAL_DAY_TO_HOUR:
163 case SQL_C_INTERVAL_DAY_TO_MINUTE:
164 case SQL_C_INTERVAL_DAY_TO_SECOND:
165 case SQL_C_INTERVAL_HOUR_TO_MINUTE:
166 case SQL_C_INTERVAL_HOUR_TO_SECOND:
167 case SQL_C_INTERVAL_MINUTE_TO_SECOND:
168 case SQL_C_BINARY:
169 case SQL_C_BIT:
170 case SQL_C_SBIGINT:
171 case SQL_C_UBIGINT:
172 case SQL_C_TINYINT:
173 case SQL_C_SLONG:
174 case SQL_C_SSHORT:
175 case SQL_C_STINYINT:
176 case SQL_C_ULONG:
177 case SQL_C_USHORT:
178 case SQL_C_UTINYINT:
179 case SQL_C_GUID:
180 case SQL_C_WCHAR:
181 case SQL_ARD_TYPE:
182 case SQL_C_DOUBLE:
183 /* case SQL_C_XML: still trying to find what value this is */
184 return 1;
185
186 default:
187 return 0;
188 }
189}
190
191SQLRETURN SQLBindCol( SQLHSTMT statement_handle,
192 SQLUSMALLINT column_number,
193 SQLSMALLINT target_type,
194 SQLPOINTER target_value,
195 SQLLEN buffer_length,
196 SQLLEN *strlen_or_ind )
197{
198 DMHSTMT statement = (DMHSTMT) statement_handle;
199 SQLRETURN ret;
200
201 /*
202 * check statement
203 */
204
205 if ( !__validate_stmt( statement ))
206 {
207 dm_log_write( __FILE__,
208 __LINE__,
209 LOG_INFO,
210 LOG_INFO,
211 "Error: SQL_INVALID_HANDLE" );
212
213 return SQL_INVALID_HANDLE;
214 }
215
216 function_entry( statement );
217
218 if ( log_info.log_flag )
219 {
220 sprintf( statement -> msg, "\n\t\tEntry:\
221\n\t\t\tStatement = %p\
222\n\t\t\tColumn Number = %d\
223\n\t\t\tTarget Type = %d %s\
224\n\t\t\tTarget Value = %p\
225\n\t\t\tBuffer Length = %d\
226\n\t\t\tStrLen Or Ind = %p",
227 statement,
228 column_number,
229 target_type,
230 __sql_as_text( target_type ),
231 target_value,
232 (int)buffer_length,
233 (void*)strlen_or_ind );
234
235 dm_log_write( __FILE__,
236 __LINE__,
237 LOG_INFO,
238 LOG_INFO,
239 statement -> msg );
240 }
241
242 thread_protect( SQL_HANDLE_STMT, statement );
243
244 if ( buffer_length < 0 )
245 {
246 dm_log_write( __FILE__,
247 __LINE__,
248 LOG_INFO,
249 LOG_INFO,
250 "Error: HY090" );
251
252 __post_internal_error( &statement -> error,
253 ERROR_HY090, NULL,
254 statement -> connection -> environment -> requested_version );
255
256 return function_return_nodrv( SQL_HANDLE_STMT, statement, SQL_ERROR );
257 }
258
259 /*
260 * TO_DO
261 * Check the type against a bookmark
262 * check that the length is 4 for a odbc 2 bookmark
263 * remember thats its bound for SQLGetData checks
264 */
265
266 /*
267 * check states
268 */
269
270 if ( statement -> state == STATE_S8 ||
271 statement -> state == STATE_S9 ||
272 statement -> state == STATE_S10 ||
273 statement -> state == STATE_S11 ||
274 statement -> state == STATE_S12 ||
275 statement -> state == STATE_S13 ||
276 statement -> state == STATE_S14 ||
277 statement -> state == STATE_S12 )
278 {
279 dm_log_write( __FILE__,
280 __LINE__,
281 LOG_INFO,
282 LOG_INFO,
283 "Error: HY010" );
284
285 __post_internal_error( &statement -> error,
286 ERROR_HY010, NULL,
287 statement -> connection -> environment -> requested_version );
288
289 return function_return_nodrv( SQL_HANDLE_STMT, statement, SQL_ERROR );
290 }
291
292 /*
293 * check valid C_TYPE
294 * Its possible to call with the indicator and buffer NULL to unbind without setting the type
295 */
296
297 if (( target_value || strlen_or_ind ) && !check_target_type( target_type, statement -> connection -> environment -> requested_version ))
298 {
299 dm_log_write( __FILE__,
300 __LINE__,
301 LOG_INFO,
302 LOG_INFO,
303 "Error: HY003" );
304
305 __post_internal_error( &statement -> error,
306 ERROR_HY003, NULL,
307 statement -> connection -> environment -> requested_version );
308
309 return function_return_nodrv( SQL_HANDLE_STMT, statement, SQL_ERROR );
310 }
311
312 if ( !CHECK_SQLBINDCOL( statement -> connection ))
313 {
314 dm_log_write( __FILE__,
315 __LINE__,
316 LOG_INFO,
317 LOG_INFO,
318 "Error: IM001" );
319
320 __post_internal_error( &statement -> error,
321 ERROR_IM001, NULL,
322 statement -> connection -> environment -> requested_version );
323
324 return function_return_nodrv( SQL_HANDLE_STMT, statement, SQL_ERROR );
325 }
326
327 ret = SQLBINDCOL( statement -> connection ,
328 statement -> driver_stmt,
329 column_number,
330 __map_type(MAP_C_DM2D,statement->connection,target_type),
331 target_value,
332 buffer_length,
333 strlen_or_ind );
334
335 if ( log_info.log_flag )
336 {
337 SQLCHAR buf[ 128 ];
338
339 sprintf( statement -> msg,
340 "\n\t\tExit:[%s]",
341 __get_return_status( ret, buf ));
342
343 dm_log_write( __FILE__,
344 __LINE__,
345 LOG_INFO,
346 LOG_INFO,
347 statement -> msg );
348 }
349
350 return function_return( SQL_HANDLE_STMT, statement, ret );
351}
352