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 | |
131 | static char const rcsid[]= "$RCSfile: SQLParamData.c,v $ $Revision: 1.7 $" ; |
132 | |
133 | SQLRETURN 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 | |