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: SQLPrepareW.c,v 1.8 2009/02/18 17:59:08 lurcher Exp $
31 *
32 * $Log: SQLPrepareW.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 2008/08/29 08:01:39 lurcher
37 * Alter the way W functions are passed to the driver
38 *
39 * Revision 1.6 2007/02/28 15:37:48 lurcher
40 * deal with drivers that call internal W functions and end up in the driver manager. controlled by the --enable-handlemap configure arg
41 *
42 * Revision 1.5 2003/10/30 18:20:46 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.4 2002/12/05 17:44:31 lurcher
50 *
51 * Display unknown return values in return logging
52 *
53 * Revision 1.3 2002/08/23 09:42:37 lurcher
54 *
55 * Fix some build warnings with casts, and a AIX linker mod, to include
56 * deplib's on the link line, but not the libtool generated ones
57 *
58 * Revision 1.2 2002/07/24 08:49:52 lurcher
59 *
60 * Alter UNICODE support to use iconv for UNICODE-ANSI conversion
61 *
62 * Revision 1.1.1.1 2001/10/17 16:40:06 lurcher
63 *
64 * First upload to SourceForge
65 *
66 * Revision 1.2 2001/04/12 17:43:36 nick
67 *
68 * Change logging and added autotest to odbctest
69 *
70 * Revision 1.1 2000/12/31 20:30:54 nick
71 *
72 * Add UNICODE support
73 *
74 *
75 **********************************************************************/
76
77#include <config.h>
78#include "drivermanager.h"
79
80static char const rcsid[]= "$RCSfile: SQLPrepareW.c,v $";
81
82SQLRETURN SQLPrepareW( SQLHSTMT statement_handle,
83 SQLWCHAR *statement_text,
84 SQLINTEGER text_length )
85{
86 DMHSTMT statement = (DMHSTMT) statement_handle;
87 SQLRETURN ret;
88 SQLCHAR *s1;
89 SQLCHAR s2[ 100 + LOG_MESSAGE_LEN ];
90
91 /*
92 * check statement
93 */
94
95 if ( !__validate_stmt( statement ))
96 {
97 dm_log_write( __FILE__,
98 __LINE__,
99 LOG_INFO,
100 LOG_INFO,
101 "Error: SQL_INVALID_HANDLE" );
102
103#ifdef WITH_HANDLE_REDIRECT
104 {
105 DMHSTMT parent_statement;
106
107 parent_statement = find_parent_handle( statement, SQL_HANDLE_STMT );
108
109 if ( parent_statement ) {
110 dm_log_write( __FILE__,
111 __LINE__,
112 LOG_INFO,
113 LOG_INFO,
114 "Info: found parent handle" );
115
116 if ( CHECK_SQLPREPAREW( parent_statement -> connection ))
117 {
118 dm_log_write( __FILE__,
119 __LINE__,
120 LOG_INFO,
121 LOG_INFO,
122 "Info: calling redirected driver function" );
123
124 return SQLPREPAREW( parent_statement -> connection,
125 statement_handle,
126 statement_text,
127 text_length );
128 }
129 }
130 }
131#endif
132 return SQL_INVALID_HANDLE;
133 }
134
135 function_entry( statement );
136
137 if ( log_info.log_flag )
138 {
139 /*
140 * allocate some space for the buffer
141 */
142
143 if ( statement_text && text_length == SQL_NTS )
144 {
145 s1 = malloc( wide_strlen( statement_text ) + 100 );
146 }
147 else if ( statement_text )
148 {
149 s1 = malloc( text_length + 100 );
150 }
151 else
152 {
153 s1 = malloc( 101 );
154 }
155
156 sprintf( statement -> msg, "\n\t\tEntry:\
157\n\t\t\tStatement = %p\
158\n\t\t\tSQL = %s",
159 statement,
160 __wstring_with_length( s1, statement_text, text_length ));
161
162 free( s1 );
163
164 dm_log_write( __FILE__,
165 __LINE__,
166 LOG_INFO,
167 LOG_INFO,
168 statement -> msg );
169 }
170
171 thread_protect( SQL_HANDLE_STMT, statement );
172
173 if ( !statement_text )
174 {
175 dm_log_write( __FILE__,
176 __LINE__,
177 LOG_INFO,
178 LOG_INFO,
179 "Error: HY009" );
180
181 __post_internal_error( &statement -> error,
182 ERROR_HY009, NULL,
183 statement -> connection -> environment -> requested_version );
184
185 return function_return_nodrv( SQL_HANDLE_STMT, statement, SQL_ERROR );
186 }
187
188 if ( text_length <= 0 && text_length != SQL_NTS )
189 {
190 dm_log_write( __FILE__,
191 __LINE__,
192 LOG_INFO,
193 LOG_INFO,
194 "Error: HY090" );
195
196 __post_internal_error( &statement -> error,
197 ERROR_HY090, NULL,
198 statement -> connection -> environment -> requested_version );
199
200 return function_return_nodrv( SQL_HANDLE_STMT, statement, SQL_ERROR );
201 }
202
203 /*
204 * check states
205 */
206#ifdef NR_PROBE
207 if ( statement -> state == STATE_S5 ||
208 statement -> state == STATE_S6 ||
209 statement -> state == STATE_S7 )
210#else
211 if (( statement -> state == STATE_S6 && statement -> eod == 0 ) ||
212 statement -> state == STATE_S7 )
213#endif
214 {
215 dm_log_write( __FILE__,
216 __LINE__,
217 LOG_INFO,
218 LOG_INFO,
219 "Error: 24000" );
220
221 __post_internal_error( &statement -> error,
222 ERROR_24000, NULL,
223 statement -> connection -> environment -> requested_version );
224
225 return function_return_nodrv( SQL_HANDLE_STMT, statement, SQL_ERROR );
226 }
227 else if ( statement -> state == STATE_S8 ||
228 statement -> state == STATE_S9 ||
229 statement -> state == STATE_S10 ||
230 statement -> state == STATE_S13 ||
231 statement -> state == STATE_S14 ||
232 statement -> state == STATE_S15 )
233 {
234 dm_log_write( __FILE__,
235 __LINE__,
236 LOG_INFO,
237 LOG_INFO,
238 "Error: HY010" );
239
240 __post_internal_error( &statement -> error,
241 ERROR_HY010, NULL,
242 statement -> connection -> environment -> requested_version );
243
244 return function_return_nodrv( SQL_HANDLE_STMT, statement, SQL_ERROR );
245 }
246
247 if ( statement -> state == STATE_S11 ||
248 statement -> state == STATE_S12 )
249 {
250 if ( statement -> interupted_func != SQL_API_SQLPREPARE )
251 {
252 dm_log_write( __FILE__,
253 __LINE__,
254 LOG_INFO,
255 LOG_INFO,
256 "Error: HY010" );
257
258 __post_internal_error( &statement -> error,
259 ERROR_HY010, NULL,
260 statement -> connection -> environment -> requested_version );
261
262 return function_return_nodrv( SQL_HANDLE_STMT, statement, SQL_ERROR );
263 }
264 }
265
266 if ( statement -> connection -> unicode_driver ||
267 CHECK_SQLPREPAREW( statement -> connection ))
268 {
269 if ( !CHECK_SQLPREPAREW( statement -> connection ))
270 {
271 dm_log_write( __FILE__,
272 __LINE__,
273 LOG_INFO,
274 LOG_INFO,
275 "Error: IM001" );
276
277 __post_internal_error( &statement -> error,
278 ERROR_IM001, NULL,
279 statement -> connection -> environment -> requested_version );
280
281 return function_return_nodrv( SQL_HANDLE_STMT, statement, SQL_ERROR );
282 }
283
284 ret = SQLPREPAREW( statement -> connection ,
285 statement -> driver_stmt,
286 statement_text,
287 text_length );
288 }
289 else
290 {
291 SQLCHAR *as1;
292 int clen;
293
294 if ( !CHECK_SQLPREPARE( statement -> connection ))
295 {
296 dm_log_write( __FILE__,
297 __LINE__,
298 LOG_INFO,
299 LOG_INFO,
300 "Error: IM001" );
301
302 __post_internal_error( &statement -> error,
303 ERROR_IM001, NULL,
304 statement -> connection -> environment -> requested_version );
305
306 return function_return_nodrv( SQL_HANDLE_STMT, statement, SQL_ERROR );
307 }
308
309 as1 = (SQLCHAR*) unicode_to_ansi_alloc( statement_text, text_length, statement -> connection, &clen );
310
311 text_length = clen;
312
313 ret = SQLPREPARE( statement -> connection ,
314 statement -> driver_stmt,
315 as1,
316 text_length );
317
318 if ( as1 ) free( as1 );
319 }
320
321 if ( SQL_SUCCEEDED( ret ))
322 {
323 statement -> hascols = 0;
324 statement -> state = STATE_S3;
325 statement -> prepared = 1;
326 }
327 else if ( ret == SQL_STILL_EXECUTING )
328 {
329 statement -> interupted_func = SQL_API_SQLPREPARE;
330 if ( statement -> state != STATE_S11 &&
331 statement -> state != STATE_S12 )
332 statement -> state = STATE_S11;
333 }
334 else
335 {
336 statement -> state = STATE_S1;
337 }
338
339 if ( log_info.log_flag )
340 {
341 sprintf( statement -> msg,
342 "\n\t\tExit:[%s]",
343 __get_return_status( ret, s2 ));
344
345 dm_log_write( __FILE__,
346 __LINE__,
347 LOG_INFO,
348 LOG_INFO,
349 statement -> msg );
350 }
351
352 return function_return( SQL_HANDLE_STMT, statement, ret );
353}
354