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: SQLPutData.c,v 1.5 2009/02/18 17:59:08 lurcher Exp $
31  *
32  * $Log: SQLPutData.c,v $
33  * Revision 1.5  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.4  2003/10/30 18:20:46  lurcher
37  *
38  * Fix broken thread protection
39  * Remove SQLNumResultCols after execute, lease S4/S% to driver
40  * Fix string overrun in SQLDriverConnect
41  * Add initial support for Interix
42  *
43  * Revision 1.3  2002/12/05 17:44:31  lurcher
44  *
45  * Display unknown return values in return logging
46  *
47  * Revision 1.2  2001/12/13 13:00:32  lurcher
48  *
49  * Remove most if not all warnings on 64 bit platforms
50  * Add support for new MS 3.52 64 bit changes
51  * Add override to disable the stopping of tracing
52  * Add MAX_ROWS support in postgres driver
53  *
54  * Revision 1.1.1.1  2001/10/17 16:40:06  lurcher
55  *
56  * First upload to SourceForge
57  *
58  * Revision 1.2  2001/04/12 17:43:36  nick
59  *
60  * Change logging and added autotest to odbctest
61  *
62  * Revision 1.1.1.1  2000/09/04 16:42:52  nick
63  * Imported Sources
64  *
65  * Revision 1.7  1999/11/13 23:41:00  ngorham
66  *
67  * Alter the way DM logging works
68  * Upgrade the Postgres driver to 6.4.6
69  *
70  * Revision 1.6  1999/10/24 23:54:18  ngorham
71  *
72  * First part of the changes to the error reporting
73  *
74  * Revision 1.5  1999/09/21 22:34:25  ngorham
75  *
76  * Improve performance by removing unneeded logging calls when logging is
77  * disabled
78  *
79  * Revision 1.4  1999/07/10 21:10:17  ngorham
80  *
81  * Adjust error sqlstate from driver manager, depending on requested
82  * version (ODBC2/3)
83  *
84  * Revision 1.3  1999/07/04 21:05:08  ngorham
85  *
86  * Add LGPL Headers to code
87  *
88  * Revision 1.2  1999/06/30 23:56:55  ngorham
89  *
90  * Add initial thread safety code
91  *
92  * Revision 1.1.1.1  1999/05/29 13:41:08  sShandyb
93  * first go at it
94  *
95  * Revision 1.1.1.1  1999/05/27 18:23:18  pharvey
96  * Imported sources
97  *
98  * Revision 1.2  1999/05/04 22:41:12  nick
99  * and another night ends
100  *
101  * Revision 1.1  1999/04/25 23:06:11  nick
102  * Initial revision
103  *
104  *
105  **********************************************************************/
106 
107 #include <config.h>
108 #include "drivermanager.h"
109 
110 static char const rcsid[]= "$RCSfile: SQLPutData.c,v $ $Revision: 1.5 $";
111 
SQLPutData(SQLHSTMT statement_handle,SQLPOINTER data,SQLLEN strlen_or_ind)112 SQLRETURN SQLPutData( SQLHSTMT statement_handle,
113            SQLPOINTER data,
114            SQLLEN strlen_or_ind )
115 {
116     DMHSTMT statement = (DMHSTMT) statement_handle;
117     SQLRETURN ret;
118     SQLCHAR s1[ 100 + LOG_MESSAGE_LEN ];
119 
120     /*
121      * check statement
122      */
123 
124     if ( !__validate_stmt( statement ))
125     {
126         dm_log_write( __FILE__,
127                     __LINE__,
128                     LOG_INFO,
129                     LOG_INFO,
130                     "Error: SQL_INVALID_HANDLE" );
131 
132         return SQL_INVALID_HANDLE;
133     }
134 
135     function_entry( statement );
136 
137     if ( log_info.log_flag )
138     {
139         sprintf( statement -> msg, "\n\t\tEntry:\
140 \n\t\t\tStatement = %p\
141 \n\t\t\tData = %p\
142 \n\t\t\tStrLen = %d",
143                 statement,
144                 data,
145                 (int)strlen_or_ind );
146 
147         dm_log_write( __FILE__,
148                 __LINE__,
149                 LOG_INFO,
150                 LOG_INFO,
151                 statement -> msg );
152     }
153 
154     thread_protect( SQL_HANDLE_STMT, statement );
155 
156     /*
157      * check states
158      */
159 
160     if ( statement -> state == STATE_S1 ||
161             statement -> state == STATE_S2 ||
162             statement -> state == STATE_S3 ||
163             statement -> state == STATE_S4 ||
164             statement -> state == STATE_S5 ||
165             statement -> state == STATE_S6 ||
166             statement -> state == STATE_S7 ||
167             statement -> state == STATE_S8 ||
168             statement -> state == STATE_S13 )
169     {
170         dm_log_write( __FILE__,
171                 __LINE__,
172                 LOG_INFO,
173                 LOG_INFO,
174                 "Error: HY010" );
175 
176         __post_internal_error( &statement -> error,
177                 ERROR_HY010, NULL,
178                 statement -> connection -> environment -> requested_version );
179 
180         return function_return_nodrv( SQL_HANDLE_STMT, statement, SQL_ERROR );
181     }
182 
183     /*
184      * not the first put for this paramenter and we
185      * try and set a NULL
186      */
187 
188     if ( statement -> state == STATE_S10 &&
189             strlen_or_ind == SQL_NULL_DATA )
190     {
191         dm_log_write( __FILE__,
192                 __LINE__,
193                 LOG_INFO,
194                 LOG_INFO,
195                 "Error: HY011" );
196 
197         __post_internal_error( &statement -> error,
198                 ERROR_HY011, NULL,
199                 statement -> connection -> environment -> requested_version );
200 
201         return function_return_nodrv( SQL_HANDLE_STMT, statement, SQL_ERROR );
202     }
203 
204     if ( statement -> state == STATE_S11 ||
205             statement -> state == STATE_S12 )
206     {
207         if ( statement -> interupted_func != SQL_API_SQLPUTDATA )
208         {
209             dm_log_write( __FILE__,
210                     __LINE__,
211                     LOG_INFO,
212                     LOG_INFO,
213                     "Error: HY010" );
214 
215             __post_internal_error( &statement -> error,
216                     ERROR_HY010, NULL,
217                     statement -> connection -> environment -> requested_version );
218 
219             return function_return_nodrv( SQL_HANDLE_STMT, statement, SQL_ERROR );
220         }
221     }
222 
223     if ( data == NULL && strlen_or_ind != 0 && strlen_or_ind != SQL_DEFAULT_PARAM && strlen_or_ind != SQL_NULL_DATA )
224     {
225         dm_log_write( __FILE__,
226                 __LINE__,
227                 LOG_INFO,
228                 LOG_INFO,
229                 "Error: HY010" );
230 
231         __post_internal_error( &statement -> error,
232                 ERROR_HY009, NULL,
233                 statement -> connection -> environment -> requested_version );
234 
235         return function_return_nodrv( SQL_HANDLE_STMT, statement, SQL_ERROR );
236     }
237 
238     if ( !CHECK_SQLPUTDATA( statement -> connection ))
239     {
240         dm_log_write( __FILE__,
241                 __LINE__,
242                 LOG_INFO,
243                 LOG_INFO,
244                 "Error: IM001" );
245 
246         __post_internal_error( &statement -> error,
247                 ERROR_IM001, NULL,
248                 statement -> connection -> environment -> requested_version );
249 
250         return function_return_nodrv( SQL_HANDLE_STMT, statement, SQL_ERROR );
251     }
252 
253     ret = SQLPUTDATA( statement -> connection,
254             statement -> driver_stmt,
255             data,
256             strlen_or_ind );
257 
258     if ( ret == SQL_STILL_EXECUTING )
259     {
260         statement -> interupted_func = SQL_API_SQLPUTDATA;
261         if ( statement -> state != STATE_S11 &&
262                 statement -> state != STATE_S12 )
263             statement -> state = STATE_S11;
264     }
265     else if ( SQL_SUCCEEDED( ret ))
266     {
267         if ( statement -> state == STATE_S13 ) {
268             statement -> state = STATE_S14;
269         }
270         else {
271             statement -> state = STATE_S10;
272         }
273     }
274     else
275     {
276         if ( statement -> interupted_func == SQL_API_SQLEXECDIRECT )
277         {
278             statement -> state = STATE_S1;
279         }
280         else if ( statement -> interupted_func == SQL_API_SQLEXECUTE &&
281                 statement -> hascols )
282         {
283             statement -> state = STATE_S3;
284         }
285         else if ( statement -> interupted_func == SQL_API_SQLEXECUTE )
286         {
287             statement -> state = STATE_S2;
288         }
289         else if ( statement -> interupted_func ==
290                 SQL_API_SQLBULKOPERATIONS &&
291                 statement -> interupted_state == STATE_S5 )
292         {
293             statement -> state = STATE_S5;
294         }
295         else if ( statement -> interupted_func ==
296                 SQL_API_SQLSETPOS &&
297                 statement -> interupted_state == STATE_S7 )
298         {
299             statement -> state = STATE_S7;
300         }
301         else
302         {
303             statement -> state = STATE_S6;
304             statement -> eod = 0;
305         }
306     }
307 
308     if ( log_info.log_flag )
309     {
310         sprintf( statement -> msg,
311                 "\n\t\tExit:[%s]",
312                     __get_return_status( ret, s1 ));
313 
314         dm_log_write( __FILE__,
315                 __LINE__,
316                 LOG_INFO,
317                 LOG_INFO,
318                 statement -> msg );
319     }
320 
321     return function_return( SQL_HANDLE_STMT, statement, ret, DEFER_R3 );
322 }
323