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