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#include <config.h>
31#include "drivermanager.h"
32
33static char const rcsid[]= "$RCSfile: SQLCancel.c,v $ $Revision: 1.4 $";
34
35SQLRETURN SQLCancelHandle( SQLSMALLINT HandleType, SQLHANDLE Handle )
36{
37 SQLRETURN ret;
38 SQLCHAR s1[ 100 + LOG_MESSAGE_LEN ];
39
40 switch ( HandleType ) {
41 case SQL_HANDLE_STMT:
42 {
43 DMHSTMT statement = (DMHSTMT) Handle;
44 /*
45 * check statement
46 */
47 if ( !__validate_stmt( statement ))
48 {
49 dm_log_write( __FILE__,
50 __LINE__,
51 LOG_INFO,
52 LOG_INFO,
53 "Error: SQL_INVALID_HANDLE" );
54
55 return SQL_INVALID_HANDLE;
56 }
57
58 function_entry( statement );
59
60 if ( log_info.log_flag )
61 {
62 sprintf( statement -> msg, "\n\t\tEntry:\n\t\t\tStatement = %p",
63 statement );
64
65 dm_log_write( __FILE__,
66 __LINE__,
67 LOG_INFO,
68 LOG_INFO,
69 statement -> msg );
70 }
71
72#if defined( HAVE_LIBPTH ) || defined( HAVE_LIBPTHREAD ) || defined( HAVE_LIBTHREAD )
73 /*
74 * Allow this past the thread checks if the driver is at all thread safe, as SQLCancel can
75 * be called across threads
76 */
77 if ( statement -> connection -> protection_level == 3 )
78 {
79 thread_protect( SQL_HANDLE_STMT, statement );
80 }
81#endif
82
83 /*
84 * check states
85 */
86
87 if ( !CHECK_SQLCANCEL( statement -> connection ))
88 {
89 dm_log_write( __FILE__,
90 __LINE__,
91 LOG_INFO,
92 LOG_INFO,
93 "Error: IM001" );
94
95 __post_internal_error( &statement -> error,
96 ERROR_IM001, NULL,
97 statement -> connection -> environment -> requested_version );
98
99#if defined( HAVE_LIBPTH ) || defined( HAVE_LIBPTHREAD ) || defined( HAVE_LIBTHREAD )
100 if ( statement -> connection -> protection_level == 3 )
101 {
102 return function_return_nodrv( SQL_HANDLE_STMT, statement, SQL_ERROR );
103 }
104 else
105 {
106 return function_return_nodrv( IGNORE_THREAD, statement, SQL_ERROR );
107 }
108#else
109 return function_return_nodrv( IGNORE_THREAD, statement, SQL_ERROR );
110#endif
111 }
112
113 ret = SQLCANCEL( statement -> connection,
114 statement -> driver_stmt );
115
116 if ( SQL_SUCCEEDED( ret ))
117 {
118 if ( statement -> state == STATE_S8 ||
119 statement -> state == STATE_S9 ||
120 statement -> state == STATE_S10 ||
121 statement -> state == STATE_S13 ||
122 statement -> state == STATE_S14 ||
123 statement -> state == STATE_S10 )
124 {
125 if ( statement -> interupted_func == SQL_API_SQLEXECDIRECT )
126 {
127 statement -> state = STATE_S1;
128 }
129 else if ( statement -> interupted_func == SQL_API_SQLEXECUTE )
130 {
131 if ( statement -> hascols )
132 {
133 statement -> state = STATE_S3;
134 }
135 else
136 {
137 statement -> state = STATE_S2;
138 }
139 }
140 else if ( statement -> interupted_func ==
141 SQL_API_SQLBULKOPERATIONS )
142 {
143 if ( statement -> interupted_state == STATE_S5 ||
144 statement -> interupted_state == STATE_S6 ||
145 statement -> interupted_state == STATE_S7 )
146 {
147 statement -> state = STATE_S6;
148 statement -> eod = 0;
149 }
150 else
151 {
152 statement -> state = STATE_S6;
153 statement -> eod = 0;
154 }
155 }
156 else if ( statement -> interupted_func ==
157 SQL_API_SQLSETPOS )
158 {
159 if ( statement -> interupted_state == STATE_S5 ||
160 statement -> interupted_state == STATE_S6 )
161 {
162 statement -> state = STATE_S6;
163 statement -> eod = 0;
164 }
165 else if ( statement -> interupted_state == STATE_S7 )
166 {
167 statement -> state = STATE_S7;
168 }
169 }
170 }
171 else if ( statement -> state == STATE_S11 ||
172 statement -> state == STATE_S12 )
173 {
174 statement -> state = STATE_S12;
175 }
176 else { /* Same action as SQLFreeStmt( SQL_CLOSE ) */
177 if ( statement -> state == STATE_S4 )
178 {
179 if ( statement -> prepared )
180 statement -> state = STATE_S2;
181 else
182 statement -> state = STATE_S1;
183 }
184 else
185 {
186 if ( statement -> prepared )
187 statement -> state = STATE_S3;
188 else
189 statement -> state = STATE_S1;
190 }
191 statement -> hascols = 0;
192 }
193 }
194
195 if ( log_info.log_flag )
196 {
197 sprintf( statement -> msg,
198 "\n\t\tExit:[%s]",
199 __get_return_status( ret, s1 ));
200
201 dm_log_write( __FILE__,
202 __LINE__,
203 LOG_INFO,
204 LOG_INFO,
205 statement -> msg );
206 }
207
208#if defined( HAVE_LIBPTH ) || defined( HAVE_LIBPTHREAD ) || defined( HAVE_LIBTHREAD )
209 if ( statement -> connection -> protection_level == 3 )
210 {
211 return function_return( SQL_HANDLE_STMT, statement, SQL_ERROR );
212 }
213 else
214 {
215 return function_return( IGNORE_THREAD, statement, ret );
216 }
217#else
218 return function_return( IGNORE_THREAD, statement, ret );
219#endif
220 }
221 break;
222
223 case SQL_HANDLE_DBC:
224 {
225 DMHDBC connection = (DMHDBC) Handle;
226 /*
227 * check connection
228 */
229
230 if ( !__validate_dbc( connection ))
231 {
232 dm_log_write( __FILE__,
233 __LINE__,
234 LOG_INFO,
235 LOG_INFO,
236 "Error: SQL_INVALID_HANDLE" );
237
238 return SQL_INVALID_HANDLE;
239 }
240
241 function_entry( connection );
242
243 if ( log_info.log_flag )
244 {
245 sprintf( connection -> msg, "\n\t\tEntry:\n\t\t\tConnection = %p",
246 connection );
247
248 dm_log_write( __FILE__,
249 __LINE__,
250 LOG_INFO,
251 LOG_INFO,
252 connection -> msg );
253 }
254
255 /*
256 * check states
257 */
258
259 if ( !CHECK_SQLCANCELHANDLE( connection ))
260 {
261 dm_log_write( __FILE__,
262 __LINE__,
263 LOG_INFO,
264 LOG_INFO,
265 "Error: IM001" );
266
267 __post_internal_error( &connection -> error,
268 ERROR_IM001, NULL,
269 connection -> environment -> requested_version );
270
271 return function_return_nodrv( IGNORE_THREAD, connection, SQL_ERROR );
272 }
273
274 ret = SQLCANCELHANDLE( connection, SQL_HANDLE_DBC,
275 connection -> driver_dbc );
276
277 /*
278 * The effect this has on connection states is not defined AFAIKS
279 */
280
281 if ( log_info.log_flag )
282 {
283 sprintf( connection -> msg,
284 "\n\t\tExit:[%s]",
285 __get_return_status( ret, s1 ));
286
287 dm_log_write( __FILE__,
288 __LINE__,
289 LOG_INFO,
290 LOG_INFO,
291 connection -> msg );
292 }
293
294 return function_return( IGNORE_THREAD, connection, ret );
295 }
296 break;
297
298 default:
299 return SQL_INVALID_HANDLE;
300 break;
301 }
302}
303