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: SQLParamData.c,v 1.7 2009/02/18 17:59:08 lurcher Exp $
31 *
32 * $Log: SQLParamData.c,v $
33 * Revision 1.7 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.6 2007/05/25 16:42:32 lurcher
37 * Sync up
38 *
39 * Revision 1.5 2005/11/21 17:25:43 lurcher
40 * A few DM fixes for Oracle's ODBC driver
41 *
42 * Revision 1.4 2004/05/07 09:53:13 lurcher
43 *
44 *
45 * Fix potential problrm in stats if creating a semaphore fails
46 * Alter state after SQLParamData from S4 to S5
47 *
48 * Revision 1.3 2003/10/30 18:20:46 lurcher
49 *
50 * Fix broken thread protection
51 * Remove SQLNumResultCols after execute, lease S4/S% to driver
52 * Fix string overrun in SQLDriverConnect
53 * Add initial support for Interix
54 *
55 * Revision 1.2 2002/12/05 17:44:31 lurcher
56 *
57 * Display unknown return values in return logging
58 *
59 * Revision 1.1.1.1 2001/10/17 16:40:06 lurcher
60 *
61 * First upload to SourceForge
62 *
63 * Revision 1.2 2001/04/12 17:43:36 nick
64 *
65 * Change logging and added autotest to odbctest
66 *
67 * Revision 1.1.1.1 2000/09/04 16:42:52 nick
68 * Imported Sources
69 *
70 * Revision 1.10 2000/06/20 12:44:00 ngorham
71 *
72 * Fix bug that caused a success with info message from SQLExecute or
73 * SQLExecDirect to be lost if used with a ODBC 3 driver and the application
74 * called SQLGetDiagRec
75 *
76 * Revision 1.9 2000/06/16 16:52:18 ngorham
77 *
78 * Stop info messages being lost when calling SQLExecute etc on ODBC 3
79 * drivers, the SQLNumResultCols were clearing the error before
80 * function return had a chance to get to them
81 *
82 * Revision 1.8 2000/05/21 21:49:19 ngorham
83 *
84 * Assorted fixes
85 *
86 * Revision 1.7 1999/11/13 23:41:00 ngorham
87 *
88 * Alter the way DM logging works
89 * Upgrade the Postgres driver to 6.4.6
90 *
91 * Revision 1.6 1999/10/24 23:54:18 ngorham
92 *
93 * First part of the changes to the error reporting
94 *
95 * Revision 1.5 1999/09/21 22:34:25 ngorham
96 *
97 * Improve performance by removing unneeded logging calls when logging is
98 * disabled
99 *
100 * Revision 1.4 1999/07/10 21:10:16 ngorham
101 *
102 * Adjust error sqlstate from driver manager, depending on requested
103 * version (ODBC2/3)
104 *
105 * Revision 1.3 1999/07/04 21:05:08 ngorham
106 *
107 * Add LGPL Headers to code
108 *
109 * Revision 1.2 1999/06/30 23:56:55 ngorham
110 *
111 * Add initial thread safety code
112 *
113 * Revision 1.1.1.1 1999/05/29 13:41:08 sShandyb
114 * first go at it
115 *
116 * Revision 1.1.1.1 1999/05/27 18:23:18 pharvey
117 * Imported sources
118 *
119 * Revision 1.2 1999/05/04 22:41:12 nick
120 * and another night ends
121 *
122 * Revision 1.1 1999/04/25 23:06:11 nick
123 * Initial revision
124 *
125 *
126 **********************************************************************/
127
128#include <config.h>
129#include "drivermanager.h"
130
131static char const rcsid[]= "$RCSfile: SQLParamData.c,v $ $Revision: 1.7 $";
132
133SQLRETURN SQLParamData( SQLHSTMT statement_handle,
134 SQLPOINTER *value )
135{
136 DMHSTMT statement = (DMHSTMT) statement_handle;
137 SQLRETURN ret;
138 SQLCHAR s1[ 100 + LOG_MESSAGE_LEN ];
139
140 /*
141 * check statement
142 */
143
144 if ( !__validate_stmt( statement ))
145 {
146 dm_log_write( __FILE__,
147 __LINE__,
148 LOG_INFO,
149 LOG_INFO,
150 "Error: SQL_INVALID_HANDLE" );
151
152 return SQL_INVALID_HANDLE;
153 }
154
155 function_entry( statement );
156
157 if ( log_info.log_flag )
158 {
159 sprintf( statement -> msg, "\n\t\tEntry:\
160\n\t\t\tStatement = %p\
161\n\t\t\tValue = %p",
162 statement,
163 value );
164
165 dm_log_write( __FILE__,
166 __LINE__,
167 LOG_INFO,
168 LOG_INFO,
169 statement -> msg );
170 }
171
172 thread_protect( SQL_HANDLE_STMT, statement );
173
174 /*
175 * check states
176 */
177
178 if ( statement -> state == STATE_S1 ||
179 statement -> state == STATE_S2 ||
180 statement -> state == STATE_S3 ||
181 statement -> state == STATE_S4 ||
182 statement -> state == STATE_S5 ||
183 statement -> state == STATE_S6 ||
184 statement -> state == STATE_S7 ||
185 statement -> state == STATE_S9 ||
186 statement -> state == STATE_S14 )
187 {
188 dm_log_write( __FILE__,
189 __LINE__,
190 LOG_INFO,
191 LOG_INFO,
192 "Error: HY010" );
193
194 __post_internal_error( &statement -> error,
195 ERROR_HY010, NULL,
196 statement -> connection -> environment -> requested_version );
197
198 return function_return_nodrv( SQL_HANDLE_STMT, statement, SQL_ERROR );
199 }
200
201 if ( statement -> state == STATE_S11 ||
202 statement -> state == STATE_S12 )
203 {
204 if ( statement -> interupted_func != SQL_API_SQLPARAMDATA )
205 {
206 dm_log_write( __FILE__,
207 __LINE__,
208 LOG_INFO,
209 LOG_INFO,
210 "Error: HY010" );
211
212 __post_internal_error( &statement -> error,
213 ERROR_HY010, NULL,
214 statement -> connection -> environment -> requested_version );
215
216 return function_return_nodrv( SQL_HANDLE_STMT, statement, SQL_ERROR );
217 }
218 }
219
220 if ( !CHECK_SQLPARAMDATA( statement -> connection ))
221 {
222 dm_log_write( __FILE__,
223 __LINE__,
224 LOG_INFO,
225 LOG_INFO,
226 "Error: IM001" );
227
228 __post_internal_error( &statement -> error,
229 ERROR_IM001, NULL,
230 statement -> connection -> environment -> requested_version );
231
232 return function_return_nodrv( SQL_HANDLE_STMT, statement, SQL_ERROR );
233 }
234
235 /*
236 * When a NULL is passed, driver tries to access this memory and dumps core,
237 * so pass a vaild pointer to the driver. This mirrors what the MS DM does
238 */
239
240
241 if (!value)
242 {
243 statement -> valueptr = NULL;
244 value = &statement -> valueptr;
245 }
246
247 ret = SQLPARAMDATA( statement -> connection,
248 statement -> driver_stmt,
249 value );
250
251 if ( ret == SQL_STILL_EXECUTING )
252 {
253 statement -> interupted_func = SQL_API_SQLPARAMDATA;
254 if ( statement -> state != STATE_S11 &&
255 statement -> state != STATE_S12 )
256 statement -> state = STATE_S11;
257 }
258 else if ( SQL_SUCCEEDED( ret ))
259 {
260 if ( statement -> interupted_func == SQL_API_SQLEXECDIRECT ||
261 statement -> interupted_func == SQL_API_SQLEXECUTE ||
262 statement -> interupted_func == SQL_API_SQLMORERESULTS )
263 {
264#ifdef NR_PROBE
265 SQLRETURN local_ret;
266
267 /*
268 * grab any errors
269 */
270
271 if ( ret == SQL_SUCCESS_WITH_INFO )
272 {
273 function_return_ex( IGNORE_THREAD, statement, ret, TRUE );
274 }
275
276 local_ret = SQLNUMRESULTCOLS( statement -> connection,
277 statement -> driver_stmt, &statement -> hascols );
278
279 if ( statement -> hascols > 0 )
280 statement -> state = STATE_S5;
281 else
282 statement -> state = STATE_S4;
283#else
284 statement -> hascols = 1;
285 statement -> state = STATE_S5;
286#endif
287 }
288 else if ( statement -> interupted_func ==
289 SQL_API_SQLSETPOS &&
290 statement -> interupted_state == STATE_S7 )
291 {
292 statement -> state = STATE_S7;
293 }
294 else if ( statement -> interupted_func ==
295 SQL_API_SQLBULKOPERATIONS &&
296 statement -> interupted_state == STATE_S5 )
297 {
298 statement -> state = STATE_S5;
299 }
300 else
301 {
302 statement -> state = STATE_S6;
303 statement -> eod = 0;
304 }
305 }
306 else if ( ret == SQL_NEED_DATA )
307 {
308 statement -> state = STATE_S9;
309 }
310 else if ( ret == SQL_PARAM_DATA_AVAILABLE )
311 {
312 statement -> state = STATE_S14;
313 }
314 else if ( ret == SQL_NO_DATA )
315 {
316 statement -> interupted_func = 0;
317 statement -> state = STATE_S4;
318 }
319 else
320 {
321 if ( statement -> interupted_func == SQL_API_SQLEXECDIRECT )
322 {
323 statement -> state = STATE_S1;
324 }
325 else if ( statement -> interupted_func == SQL_API_SQLEXECUTE &&
326 statement -> hascols )
327 {
328 statement -> state = STATE_S3;
329 }
330 else if ( statement -> interupted_func == SQL_API_SQLEXECUTE )
331 {
332 statement -> state = STATE_S2;
333 }
334 else if ( statement -> interupted_func ==
335 SQL_API_SQLBULKOPERATIONS &&
336 statement -> interupted_state == STATE_S5 )
337 {
338 statement -> state = STATE_S5;
339 }
340 else if ( statement -> interupted_func ==
341 SQL_API_SQLSETPOS &&
342 statement -> interupted_state == STATE_S7 )
343 {
344 statement -> state = STATE_S7;
345 }
346 else
347 {
348 statement -> state = STATE_S6;
349 statement -> eod = 0;
350 }
351 }
352
353 if ( log_info.log_flag )
354 {
355 sprintf( statement -> msg,
356 "\n\t\tExit:[%s]\
357\n\t\t\tValue = %p",
358 __get_return_status( ret, s1 ),
359 *value );
360
361 dm_log_write( __FILE__,
362 __LINE__,
363 LOG_INFO,
364 LOG_INFO,
365 statement -> msg );
366 }
367
368 return function_return( SQL_HANDLE_STMT, statement, ret );
369}
370