]> granicus.if.org Git - postgresql/blob - src/interfaces/odbc/execute.c
Provide some initial support for building the ODBC driver for
[postgresql] / src / interfaces / odbc / execute.c
1 /*-------
2  * Module:                      execute.c
3  *
4  * Description:         This module contains routines related to
5  *                                      preparing and executing an SQL statement.
6  *
7  * Classes:                     n/a
8  *
9  * API functions:       SQLPrepare, SQLExecute, SQLExecDirect, SQLTransact,
10  *                                      SQLCancel, SQLNativeSql, SQLParamData, SQLPutData
11  *
12  * Comments:            See "notice.txt" for copyright and license information.
13  *-------
14  */
15
16 #include "psqlodbc.h"
17
18 #include <stdio.h>
19 #include <string.h>
20
21 #include "connection.h"
22 #include "statement.h"
23 #include "qresult.h"
24 #include "convert.h"
25 #include "bind.h"
26 #include "pgtypes.h"
27 #include "lobj.h"
28 #include "pgapifunc.h"
29
30 /*extern GLOBAL_VALUES globals;*/
31
32
33 /*              Perform a Prepare on the SQL statement */
34 RETCODE SQL_API
35 PGAPI_Prepare(HSTMT hstmt,
36                    UCHAR FAR *szSqlStr,
37                    SDWORD cbSqlStr)
38 {
39         static char *func = "PGAPI_Prepare";
40         StatementClass *self = (StatementClass *) hstmt;
41
42         mylog("%s: entering...\n", func);
43
44         if (!self)
45         {
46                 SC_log_error(func, "", NULL);
47                 return SQL_INVALID_HANDLE;
48         }
49
50         /*
51          * According to the ODBC specs it is valid to call SQLPrepare mulitple
52          * times. In that case, the bound SQL statement is replaced by the new
53          * one
54          */
55
56         switch (self->status)
57         {
58                 case STMT_PREMATURE:
59                         mylog("**** PGAPI_Prepare: STMT_PREMATURE, recycle\n");
60                         SC_recycle_statement(self); /* recycle the statement, but do
61                                                                                  * not remove parameter bindings */
62                         break;
63
64                 case STMT_FINISHED:
65                         mylog("**** PGAPI_Prepare: STMT_FINISHED, recycle\n");
66                         SC_recycle_statement(self); /* recycle the statement, but do
67                                                                                  * not remove parameter bindings */
68                         break;
69
70                 case STMT_ALLOCATED:
71                         mylog("**** PGAPI_Prepare: STMT_ALLOCATED, copy\n");
72                         self->status = STMT_READY;
73                         break;
74
75                 case STMT_READY:
76                         mylog("**** PGAPI_Prepare: STMT_READY, change SQL\n");
77                         break;
78
79                 case STMT_EXECUTING:
80                         mylog("**** PGAPI_Prepare: STMT_EXECUTING, error!\n");
81
82                         self->errornumber = STMT_SEQUENCE_ERROR;
83                         self->errormsg = "PGAPI_Prepare(): The handle does not point to a statement that is ready to be executed";
84                         SC_log_error(func, "", self);
85
86                         return SQL_ERROR;
87
88                 default:
89                         self->errornumber = STMT_INTERNAL_ERROR;
90                         self->errormsg = "An Internal Error has occured -- Unknown statement status.";
91                         SC_log_error(func, "", self);
92                         return SQL_ERROR;
93         }
94
95         if (self->statement)
96                 free(self->statement);
97
98         self->statement = make_string(szSqlStr, cbSqlStr, NULL);
99         if (!self->statement)
100         {
101                 self->errornumber = STMT_NO_MEMORY_ERROR;
102                 self->errormsg = "No memory available to store statement";
103                 SC_log_error(func, "", self);
104                 return SQL_ERROR;
105         }
106
107         self->prepare = TRUE;
108         self->statement_type = statement_type(self->statement);
109
110         /* Check if connection is onlyread (only selects are allowed) */
111         if (CC_is_onlyread(self->hdbc) && STMT_UPDATE(self))
112         {
113                 self->errornumber = STMT_EXEC_ERROR;
114                 self->errormsg = "Connection is readonly, only select statements are allowed.";
115                 SC_log_error(func, "", self);
116                 return SQL_ERROR;
117         }
118
119         return SQL_SUCCESS;
120 }
121
122
123 /*              Performs the equivalent of SQLPrepare, followed by SQLExecute. */
124 RETCODE SQL_API
125 PGAPI_ExecDirect(
126                           HSTMT hstmt,
127                           UCHAR FAR *szSqlStr,
128                           SDWORD cbSqlStr)
129 {
130         StatementClass *stmt = (StatementClass *) hstmt;
131         RETCODE         result;
132         static char *func = "PGAPI_ExecDirect";
133
134         mylog("%s: entering...\n", func);
135
136         if (!stmt)
137         {
138                 SC_log_error(func, "", NULL);
139                 return SQL_INVALID_HANDLE;
140         }
141
142         if (stmt->statement)
143                 free(stmt->statement);
144
145         /*
146          * keep a copy of the un-parametrized statement, in case they try to
147          * execute this statement again
148          */
149         stmt->statement = make_string(szSqlStr, cbSqlStr, NULL);
150         if (!stmt->statement)
151         {
152                 stmt->errornumber = STMT_NO_MEMORY_ERROR;
153                 stmt->errormsg = "No memory available to store statement";
154                 SC_log_error(func, "", stmt);
155                 return SQL_ERROR;
156         }
157
158         mylog("**** %s: hstmt=%u, statement='%s'\n", func, hstmt, stmt->statement);
159
160         stmt->prepare = FALSE;
161
162         /*
163          * If an SQLPrepare was performed prior to this, but was left in the
164          * premature state because an error occurred prior to SQLExecute then
165          * set the statement to finished so it can be recycled.
166          */
167         if (stmt->status == STMT_PREMATURE)
168                 stmt->status = STMT_FINISHED;
169
170         stmt->statement_type = statement_type(stmt->statement);
171
172         /* Check if connection is onlyread (only selects are allowed) */
173         if (CC_is_onlyread(stmt->hdbc) && STMT_UPDATE(stmt))
174         {
175                 stmt->errornumber = STMT_EXEC_ERROR;
176                 stmt->errormsg = "Connection is readonly, only select statements are allowed.";
177                 SC_log_error(func, "", stmt);
178                 return SQL_ERROR;
179         }
180
181         mylog("%s: calling PGAPI_Execute...\n", func);
182
183         result = PGAPI_Execute(hstmt);
184
185         mylog("%s: returned %hd from PGAPI_Execute\n", func, result);
186         return result;
187 }
188
189
190 /*      Execute a prepared SQL statement */
191 RETCODE SQL_API
192 PGAPI_Execute(
193                    HSTMT hstmt)
194 {
195         static char *func = "PGAPI_Execute";
196         StatementClass *stmt = (StatementClass *) hstmt;
197         ConnectionClass *conn;
198         int                     i,
199                                 retval;
200
201         mylog("%s: entering...\n", func);
202
203         if (!stmt)
204         {
205                 SC_log_error(func, "", NULL);
206                 mylog("%s: NULL statement so return SQL_INVALID_HANDLE\n", func);
207                 return SQL_INVALID_HANDLE;
208         }
209
210         /*
211          * If the statement is premature, it means we already executed it from
212          * an SQLPrepare/SQLDescribeCol type of scenario.  So just return
213          * success.
214          */
215         if (stmt->prepare && stmt->status == STMT_PREMATURE)
216         {
217                 if (stmt->inaccurate_result)
218                         SC_recycle_statement(stmt);
219                 else
220                 {
221                         stmt->status = STMT_FINISHED;
222                         if (stmt->errormsg == NULL)
223                         {
224                                 mylog("%s: premature statement but return SQL_SUCCESS\n", func);
225                                 return SQL_SUCCESS;
226                         }
227                         else
228                         {
229                                 SC_log_error(func, "", stmt);
230                                 mylog("%s: premature statement so return SQL_ERROR\n", func);
231                                 return SQL_ERROR;
232                         }
233                 }
234         }
235
236         mylog("%s: clear errors...\n", func);
237
238         SC_clear_error(stmt);
239
240         conn = SC_get_conn(stmt);
241         if (conn->status == CONN_EXECUTING)
242         {
243                 stmt->errormsg = "Connection is already in use.";
244                 stmt->errornumber = STMT_SEQUENCE_ERROR;
245                 SC_log_error(func, "", stmt);
246                 mylog("%s: problem with connection\n", func);
247                 return SQL_ERROR;
248         }
249
250         if (!stmt->statement)
251         {
252                 stmt->errornumber = STMT_NO_STMTSTRING;
253                 stmt->errormsg = "This handle does not have a SQL statement stored in it";
254                 SC_log_error(func, "", stmt);
255                 mylog("%s: problem with handle\n", func);
256                 return SQL_ERROR;
257         }
258
259         /*
260          * If SQLExecute is being called again, recycle the statement. Note
261          * this should have been done by the application in a call to
262          * SQLFreeStmt(SQL_CLOSE) or SQLCancel.
263          */
264         if (stmt->status == STMT_FINISHED)
265         {
266                 mylog("%s: recycling statement (should have been done by app)...\n", func);
267                 SC_recycle_statement(stmt);
268         }
269
270         /* Check if the statement is in the correct state */
271         if ((stmt->prepare && stmt->status != STMT_READY) ||
272                 (stmt->status != STMT_ALLOCATED && stmt->status != STMT_READY))
273         {
274                 stmt->errornumber = STMT_STATUS_ERROR;
275                 stmt->errormsg = "The handle does not point to a statement that is ready to be executed";
276                 SC_log_error(func, "", stmt);
277                 mylog("%s: problem with statement\n", func);
278                 return SQL_ERROR;
279         }
280
281         /*
282          * Check if statement has any data-at-execute parameters when it is
283          * not in SC_pre_execute.
284          */
285         if (!stmt->pre_executing)
286         {
287
288                 /*
289                  * The bound parameters could have possibly changed since the last
290                  * execute of this statement?  Therefore check for params and
291                  * re-copy.
292                  */
293                 stmt->data_at_exec = -1;
294                 for (i = 0; i < stmt->parameters_allocated; i++)
295                 {
296                         Int4       *pcVal = stmt->parameters[i].used;
297
298                         if (pcVal && (*pcVal == SQL_DATA_AT_EXEC || *pcVal <= SQL_LEN_DATA_AT_EXEC_OFFSET))
299                                 stmt->parameters[i].data_at_exec = TRUE;
300                         else
301                                 stmt->parameters[i].data_at_exec = FALSE;
302                         /* Check for data at execution parameters */
303                         if (stmt->parameters[i].data_at_exec == TRUE)
304                         {
305                                 if (stmt->data_at_exec < 0)
306                                         stmt->data_at_exec = 1;
307                                 else
308                                         stmt->data_at_exec++;
309                         }
310                 }
311
312                 /*
313                  * If there are some data at execution parameters, return need
314                  * data
315                  */
316
317                 /*
318                  * SQLParamData and SQLPutData will be used to send params and
319                  * execute the statement.
320                  */
321                 if (stmt->data_at_exec > 0)
322                         return SQL_NEED_DATA;
323
324         }
325
326
327         mylog("%s: copying statement params: trans_status=%d, len=%d, stmt='%s'\n", func, conn->transact_status, strlen(stmt->statement), stmt->statement);
328
329         /* Create the statement with parameters substituted. */
330         retval = copy_statement_with_parameters(stmt);
331         if (retval != SQL_SUCCESS)
332                 /* error msg passed from above */
333                 return retval;
334
335         mylog("   stmt_with_params = '%s'\n", stmt->stmt_with_params);
336         /*
337          *      Get the field info for the prepared
338          *      query using dummy backward fetch.
339          */
340         if (stmt->inaccurate_result && conn->connInfo.disallow_premature)
341         {
342                 if (SC_is_pre_executable(stmt))
343                 {
344                         BOOL    in_trans = CC_is_in_trans(conn);
345                         BOOL    issued_begin = FALSE, begin_included = FALSE;
346                         QResultClass    *res;
347
348                         if (strnicmp(stmt->stmt_with_params, "BEGIN;", 6) == 0)
349                                 begin_included = TRUE;
350                         else if (!in_trans)
351                         {
352                                 res = CC_send_query(conn, "BEGIN", NULL);
353                                 if (res && !QR_aborted(res))
354                                         issued_begin = TRUE;
355                                 if (res)
356                                         QR_Destructor(res);
357                                 if (!issued_begin)
358                                 {
359                                         stmt->errornumber = STMT_EXEC_ERROR;
360                                         stmt->errormsg = "Handle prepare error";
361                                         return SQL_ERROR;
362                                 }
363                         }
364                         /* we are now in a transaction */
365                         CC_set_in_trans(conn);
366                         stmt->result = res = CC_send_query(conn, stmt->stmt_with_params, NULL);
367                         if (!res || QR_aborted(res))
368                         {
369                                 CC_abort(conn);
370                                 stmt->errornumber = STMT_EXEC_ERROR;
371                                 stmt->errormsg = "Handle prepare error";
372                                 return SQL_ERROR;
373                         }
374                         else
375                         {
376                                 if (CC_is_in_autocommit(conn))
377                                 {
378                                         if (issued_begin)
379                                         {
380                                                 res = CC_send_query(conn, "COMMIT", NULL);
381                                                 CC_set_no_trans(conn);
382                                                 if (res)
383                                                         QR_Destructor(res);
384                                         }
385                                         else if (!in_trans && begin_included)
386                                                 CC_set_no_trans(conn);
387                                 }       
388                                 stmt->status =STMT_FINISHED;
389                                 return SQL_SUCCESS;
390                         }
391                 }
392                 else
393                         return SQL_SUCCESS;
394         }
395
396         return SC_execute(stmt);
397 }
398
399
400 RETCODE SQL_API
401 PGAPI_Transact(
402                         HENV henv,
403                         HDBC hdbc,
404                         UWORD fType)
405 {
406         static char *func = "PGAPI_Transact";
407         extern ConnectionClass *conns[];
408         ConnectionClass *conn;
409         QResultClass *res;
410         char            ok,
411                            *stmt_string;
412         int                     lf;
413
414         mylog("entering %s: hdbc=%u, henv=%u\n", func, hdbc, henv);
415
416         if (hdbc == SQL_NULL_HDBC && henv == SQL_NULL_HENV)
417         {
418                 CC_log_error(func, "", NULL);
419                 return SQL_INVALID_HANDLE;
420         }
421
422         /*
423          * If hdbc is null and henv is valid, it means transact all
424          * connections on that henv.
425          */
426         if (hdbc == SQL_NULL_HDBC && henv != SQL_NULL_HENV)
427         {
428                 for (lf = 0; lf < MAX_CONNECTIONS; lf++)
429                 {
430                         conn = conns[lf];
431
432                         if (conn && conn->henv == henv)
433                                 if (PGAPI_Transact(henv, (HDBC) conn, fType) != SQL_SUCCESS)
434                                         return SQL_ERROR;
435                 }
436                 return SQL_SUCCESS;
437         }
438
439         conn = (ConnectionClass *) hdbc;
440
441         if (fType == SQL_COMMIT)
442                 stmt_string = "COMMIT";
443         else if (fType == SQL_ROLLBACK)
444                 stmt_string = "ROLLBACK";
445         else
446         {
447                 conn->errornumber = CONN_INVALID_ARGUMENT_NO;
448                 conn->errormsg = "PGAPI_Transact can only be called with SQL_COMMIT or SQL_ROLLBACK as parameter";
449                 CC_log_error(func, "", conn);
450                 return SQL_ERROR;
451         }
452
453         /* If manual commit and in transaction, then proceed. */
454         if (!CC_is_in_autocommit(conn) && CC_is_in_trans(conn))
455         {
456                 mylog("PGAPI_Transact: sending on conn %d '%s'\n", conn, stmt_string);
457
458                 res = CC_send_query(conn, stmt_string, NULL);
459                 CC_set_no_trans(conn);
460
461                 if (!res)
462                 {
463                         /* error msg will be in the connection */
464                         CC_log_error(func, "", conn);
465                         return SQL_ERROR;
466                 }
467
468                 ok = QR_command_successful(res);
469                 QR_Destructor(res);
470
471                 if (!ok)
472                 {
473                         CC_log_error(func, "", conn);
474                         return SQL_ERROR;
475                 }
476         }
477         return SQL_SUCCESS;
478 }
479
480
481 RETCODE SQL_API
482 PGAPI_Cancel(
483                   HSTMT hstmt)                  /* Statement to cancel. */
484 {
485         static char *func = "PGAPI_Cancel";
486         StatementClass *stmt = (StatementClass *) hstmt;
487         RETCODE         result;
488         ConnInfo *ci;
489
490 #ifdef WIN32
491         HMODULE         hmodule;
492         FARPROC         addr;
493
494 #endif
495
496         mylog("%s: entering...\n", func);
497
498         /* Check if this can handle canceling in the middle of a SQLPutData? */
499         if (!stmt)
500         {
501                 SC_log_error(func, "", NULL);
502                 return SQL_INVALID_HANDLE;
503         }
504         ci = &(SC_get_conn(stmt)->connInfo);
505
506         /*
507          * Not in the middle of SQLParamData/SQLPutData so cancel like a
508          * close.
509          */
510         if (stmt->data_at_exec < 0)
511         {
512
513                 /*
514                  * MAJOR HACK for Windows to reset the driver manager's cursor
515                  * state: Because of what seems like a bug in the Odbc driver
516                  * manager, SQLCancel does not act like a SQLFreeStmt(CLOSE), as
517                  * many applications depend on this behavior.  So, this brute
518                  * force method calls the driver manager's function on behalf of
519                  * the application.
520                  */
521
522 #ifdef WIN32
523                 if (ci->drivers.cancel_as_freestmt)
524                 {
525                         hmodule = GetModuleHandle("ODBC32");
526                         addr = GetProcAddress(hmodule, "SQLFreeStmt");
527                         result = addr((char *) (stmt->phstmt) - 96, SQL_CLOSE);
528                 }
529                 else
530                         result = PGAPI_FreeStmt(hstmt, SQL_CLOSE);
531 #else
532                 result = PGAPI_FreeStmt(hstmt, SQL_CLOSE);
533 #endif
534
535                 mylog("PGAPI_Cancel:  PGAPI_FreeStmt returned %d\n", result);
536
537                 SC_clear_error(hstmt);
538                 return SQL_SUCCESS;
539         }
540
541         /* In the middle of SQLParamData/SQLPutData, so cancel that. */
542
543         /*
544          * Note, any previous data-at-exec buffers will be freed in the
545          * recycle
546          */
547         /* if they call SQLExecDirect or SQLExecute again. */
548
549         stmt->data_at_exec = -1;
550         stmt->current_exec_param = -1;
551         stmt->put_data = FALSE;
552
553         return SQL_SUCCESS;
554 }
555
556
557 /*
558  *      Returns the SQL string as modified by the driver.
559  *      Currently, just copy the input string without modification
560  *      observing buffer limits and truncation.
561  */
562 RETCODE SQL_API
563 PGAPI_NativeSql(
564                          HDBC hdbc,
565                          UCHAR FAR *szSqlStrIn,
566                          SDWORD cbSqlStrIn,
567                          UCHAR FAR *szSqlStr,
568                          SDWORD cbSqlStrMax,
569                          SDWORD FAR *pcbSqlStr)
570 {
571         static char *func = "PGAPI_NativeSql";
572         int                     len = 0;
573         char       *ptr;
574         ConnectionClass *conn = (ConnectionClass *) hdbc;
575         RETCODE         result;
576
577         mylog("%s: entering...cbSqlStrIn=%d\n", func, cbSqlStrIn);
578
579         ptr = (cbSqlStrIn == 0) ? "" : make_string(szSqlStrIn, cbSqlStrIn, NULL);
580         if (!ptr)
581         {
582                 conn->errornumber = CONN_NO_MEMORY_ERROR;
583                 conn->errormsg = "No memory available to store native sql string";
584                 CC_log_error(func, "", conn);
585                 return SQL_ERROR;
586         }
587
588         result = SQL_SUCCESS;
589         len = strlen(ptr);
590
591         if (szSqlStr)
592         {
593                 strncpy_null(szSqlStr, ptr, cbSqlStrMax);
594
595                 if (len >= cbSqlStrMax)
596                 {
597                         result = SQL_SUCCESS_WITH_INFO;
598                         conn->errornumber = STMT_TRUNCATED;
599                         conn->errormsg = "The buffer was too small for the NativeSQL.";
600                 }
601         }
602
603         if (pcbSqlStr)
604                 *pcbSqlStr = len;
605
606         if (cbSqlStrIn)
607                 free(ptr);
608
609         return result;
610 }
611
612
613 /*
614  *      Supplies parameter data at execution time.
615  *      Used in conjuction with SQLPutData.
616  */
617 RETCODE SQL_API
618 PGAPI_ParamData(
619                          HSTMT hstmt,
620                          PTR FAR *prgbValue)
621 {
622         static char *func = "PGAPI_ParamData";
623         StatementClass *stmt = (StatementClass *) hstmt;
624         int                     i,
625                                 retval;
626         ConnInfo *ci;
627
628         mylog("%s: entering...\n", func);
629
630         if (!stmt)
631         {
632                 SC_log_error(func, "", NULL);
633                 return SQL_INVALID_HANDLE;
634         }
635         ci = &(SC_get_conn(stmt)->connInfo);
636
637         mylog("%s: data_at_exec=%d, params_alloc=%d\n", func, stmt->data_at_exec, stmt->parameters_allocated);
638
639         if (stmt->data_at_exec < 0)
640         {
641                 stmt->errornumber = STMT_SEQUENCE_ERROR;
642                 stmt->errormsg = "No execution-time parameters for this statement";
643                 SC_log_error(func, "", stmt);
644                 return SQL_ERROR;
645         }
646
647         if (stmt->data_at_exec > stmt->parameters_allocated)
648         {
649                 stmt->errornumber = STMT_SEQUENCE_ERROR;
650                 stmt->errormsg = "Too many execution-time parameters were present";
651                 SC_log_error(func, "", stmt);
652                 return SQL_ERROR;
653         }
654
655         /* close the large object */
656         if (stmt->lobj_fd >= 0)
657         {
658                 lo_close(stmt->hdbc, stmt->lobj_fd);
659
660                 /* commit transaction if needed */
661                 if (!ci->drivers.use_declarefetch && CC_is_in_autocommit(stmt->hdbc))
662                 {
663                         QResultClass *res;
664                         char            ok;
665
666                         res = CC_send_query(stmt->hdbc, "COMMIT", NULL);
667                         if (!res)
668                         {
669                                 stmt->errormsg = "Could not commit (in-line) a transaction";
670                                 stmt->errornumber = STMT_EXEC_ERROR;
671                                 SC_log_error(func, "", stmt);
672                                 return SQL_ERROR;
673                         }
674                         ok = QR_command_successful(res);
675                         CC_set_no_trans(stmt->hdbc);
676                         QR_Destructor(res);
677                         if (!ok)
678                         {
679                                 stmt->errormsg = "Could not commit (in-line) a transaction";
680                                 stmt->errornumber = STMT_EXEC_ERROR;
681                                 SC_log_error(func, "", stmt);
682                                 return SQL_ERROR;
683                         }
684                 }
685                 stmt->lobj_fd = -1;
686         }
687
688         /* Done, now copy the params and then execute the statement */
689         if (stmt->data_at_exec == 0)
690         {
691                 retval = copy_statement_with_parameters(stmt);
692                 if (retval != SQL_SUCCESS)
693                         return retval;
694
695                 stmt->current_exec_param = -1;
696
697                 return SC_execute(stmt);
698         }
699
700         /*
701          * Set beginning param;  if first time SQLParamData is called , start
702          * at 0. Otherwise, start at the last parameter + 1.
703          */
704         i = stmt->current_exec_param >= 0 ? stmt->current_exec_param + 1 : 0;
705
706         /* At least 1 data at execution parameter, so Fill in the token value */
707         for (; i < stmt->parameters_allocated; i++)
708         {
709                 if (stmt->parameters[i].data_at_exec == TRUE)
710                 {
711                         stmt->data_at_exec--;
712                         stmt->current_exec_param = i;
713                         stmt->put_data = FALSE;
714                         *prgbValue = stmt->parameters[i].buffer;        /* token */
715                         break;
716                 }
717         }
718
719         return SQL_NEED_DATA;
720 }
721
722
723 /*
724  *      Supplies parameter data at execution time.
725  *      Used in conjunction with SQLParamData.
726  */
727 RETCODE SQL_API
728 PGAPI_PutData(
729                    HSTMT hstmt,
730                    PTR rgbValue,
731                    SDWORD cbValue)
732 {
733         static char *func = "PGAPI_PutData";
734         StatementClass *stmt = (StatementClass *) hstmt;
735         int                     old_pos,
736                                 retval;
737         ParameterInfoClass *current_param;
738         char       *buffer;
739
740         mylog("%s: entering...\n", func);
741
742         if (!stmt)
743         {
744                 SC_log_error(func, "", NULL);
745                 return SQL_INVALID_HANDLE;
746         }
747
748         if (stmt->current_exec_param < 0)
749         {
750                 stmt->errornumber = STMT_SEQUENCE_ERROR;
751                 stmt->errormsg = "Previous call was not SQLPutData or SQLParamData";
752                 SC_log_error(func, "", stmt);
753                 return SQL_ERROR;
754         }
755
756         current_param = &(stmt->parameters[stmt->current_exec_param]);
757
758         if (!stmt->put_data)
759         {                                                       /* first call */
760                 mylog("PGAPI_PutData: (1) cbValue = %d\n", cbValue);
761
762                 stmt->put_data = TRUE;
763
764                 current_param->EXEC_used = (SDWORD *) malloc(sizeof(SDWORD));
765                 if (!current_param->EXEC_used)
766                 {
767                         stmt->errornumber = STMT_NO_MEMORY_ERROR;
768                         stmt->errormsg = "Out of memory in PGAPI_PutData (1)";
769                         SC_log_error(func, "", stmt);
770                         return SQL_ERROR;
771                 }
772
773                 *current_param->EXEC_used = cbValue;
774
775                 if (cbValue == SQL_NULL_DATA)
776                         return SQL_SUCCESS;
777
778                 /* Handle Long Var Binary with Large Objects */
779                 if (current_param->SQLType == SQL_LONGVARBINARY)
780                 {
781                         /* begin transaction if needed */
782                         if (!CC_is_in_trans(stmt->hdbc))
783                         {
784                                 QResultClass *res;
785                                 char            ok;
786
787                                 res = CC_send_query(stmt->hdbc, "BEGIN", NULL);
788                                 if (!res)
789                                 {
790                                         stmt->errormsg = "Could not begin (in-line) a transaction";
791                                         stmt->errornumber = STMT_EXEC_ERROR;
792                                         SC_log_error(func, "", stmt);
793                                         return SQL_ERROR;
794                                 }
795                                 ok = QR_command_successful(res);
796                                 QR_Destructor(res);
797                                 if (!ok)
798                                 {
799                                         stmt->errormsg = "Could not begin (in-line) a transaction";
800                                         stmt->errornumber = STMT_EXEC_ERROR;
801                                         SC_log_error(func, "", stmt);
802                                         return SQL_ERROR;
803                                 }
804
805                                 CC_set_in_trans(stmt->hdbc);
806                         }
807
808                         /* store the oid */
809                         current_param->lobj_oid = lo_creat(stmt->hdbc, INV_READ | INV_WRITE);
810                         if (current_param->lobj_oid == 0)
811                         {
812                                 stmt->errornumber = STMT_EXEC_ERROR;
813                                 stmt->errormsg = "Couldnt create large object.";
814                                 SC_log_error(func, "", stmt);
815                                 return SQL_ERROR;
816                         }
817
818                         /*
819                          * major hack -- to allow convert to see somethings there have
820                          * to modify convert to handle this better
821                          */
822                         current_param->EXEC_buffer = (char *) &current_param->lobj_oid;
823
824                         /* store the fd */
825                         stmt->lobj_fd = lo_open(stmt->hdbc, current_param->lobj_oid, INV_WRITE);
826                         if (stmt->lobj_fd < 0)
827                         {
828                                 stmt->errornumber = STMT_EXEC_ERROR;
829                                 stmt->errormsg = "Couldnt open large object for writing.";
830                                 SC_log_error(func, "", stmt);
831                                 return SQL_ERROR;
832                         }
833
834                         retval = lo_write(stmt->hdbc, stmt->lobj_fd, rgbValue, cbValue);
835                         mylog("lo_write: cbValue=%d, wrote %d bytes\n", cbValue, retval);
836                 }
837                 else
838                 {
839                         /* for handling fields */
840                         if (cbValue == SQL_NTS)
841                         {
842                                 current_param->EXEC_buffer = strdup(rgbValue);
843                                 if (!current_param->EXEC_buffer)
844                                 {
845                                         stmt->errornumber = STMT_NO_MEMORY_ERROR;
846                                         stmt->errormsg = "Out of memory in PGAPI_PutData (2)";
847                                         SC_log_error(func, "", stmt);
848                                         return SQL_ERROR;
849                                 }
850                         }
851                         else
852                         {
853                                 Int2            ctype = current_param->CType;
854
855                                 if (ctype == SQL_C_DEFAULT)
856                                         ctype = sqltype_to_default_ctype(current_param->SQLType);
857                                 if (ctype == SQL_C_CHAR || ctype == SQL_C_BINARY)
858                                 {
859                                         current_param->EXEC_buffer = malloc(cbValue + 1);
860                                         if (!current_param->EXEC_buffer)
861                                         {
862                                                 stmt->errornumber = STMT_NO_MEMORY_ERROR;
863                                                 stmt->errormsg = "Out of memory in PGAPI_PutData (2)";
864                                                 SC_log_error(func, "", stmt);
865                                                 return SQL_ERROR;
866                                         }
867                                         memcpy(current_param->EXEC_buffer, rgbValue, cbValue);
868                                         current_param->EXEC_buffer[cbValue] = '\0';
869                                 }
870                                 else
871                                 {
872                                         Int4            used = ctype_length(ctype);
873
874                                         current_param->EXEC_buffer = malloc(used);
875                                         if (!current_param->EXEC_buffer)
876                                         {
877                                                 stmt->errornumber = STMT_NO_MEMORY_ERROR;
878                                                 stmt->errormsg = "Out of memory in PGAPI_PutData (2)";
879                                                 SC_log_error(func, "", stmt);
880                                                 return SQL_ERROR;
881                                         }
882                                         memcpy(current_param->EXEC_buffer, rgbValue, used);
883                                 }
884                         }
885                 }
886         }
887         else
888         {
889                 /* calling SQLPutData more than once */
890                 mylog("PGAPI_PutData: (>1) cbValue = %d\n", cbValue);
891
892                 if (current_param->SQLType == SQL_LONGVARBINARY)
893                 {
894                         /* the large object fd is in EXEC_buffer */
895                         retval = lo_write(stmt->hdbc, stmt->lobj_fd, rgbValue, cbValue);
896                         mylog("lo_write(2): cbValue = %d, wrote %d bytes\n", cbValue, retval);
897
898                         *current_param->EXEC_used += cbValue;
899                 }
900                 else
901                 {
902                         buffer = current_param->EXEC_buffer;
903
904                         if (cbValue == SQL_NTS)
905                         {
906                                 buffer = realloc(buffer, strlen(buffer) + strlen(rgbValue) + 1);
907                                 if (!buffer)
908                                 {
909                                         stmt->errornumber = STMT_NO_MEMORY_ERROR;
910                                         stmt->errormsg = "Out of memory in PGAPI_PutData (3)";
911                                         SC_log_error(func, "", stmt);
912                                         return SQL_ERROR;
913                                 }
914                                 strcat(buffer, rgbValue);
915
916                                 mylog("       cbValue = SQL_NTS: strlen(buffer) = %d\n", strlen(buffer));
917
918                                 *current_param->EXEC_used = cbValue;
919
920                                 /* reassign buffer incase realloc moved it */
921                                 current_param->EXEC_buffer = buffer;
922                         }
923                         else if (cbValue > 0)
924                         {
925                                 old_pos = *current_param->EXEC_used;
926
927                                 *current_param->EXEC_used += cbValue;
928
929                                 mylog("        cbValue = %d, old_pos = %d, *used = %d\n", cbValue, old_pos, *current_param->EXEC_used);
930
931                                 /* dont lose the old pointer in case out of memory */
932                                 buffer = realloc(current_param->EXEC_buffer, *current_param->EXEC_used + 1);
933                                 if (!buffer)
934                                 {
935                                         stmt->errornumber = STMT_NO_MEMORY_ERROR;
936                                         stmt->errormsg = "Out of memory in PGAPI_PutData (3)";
937                                         SC_log_error(func, "", stmt);
938                                         return SQL_ERROR;
939                                 }
940
941                                 memcpy(&buffer[old_pos], rgbValue, cbValue);
942                                 buffer[*current_param->EXEC_used] = '\0';
943
944                                 /* reassign buffer incase realloc moved it */
945                                 current_param->EXEC_buffer = buffer;
946                         }
947                         else
948                         {
949                                 SC_log_error(func, "bad cbValue", stmt);
950                                 return SQL_ERROR;
951                         }
952                 }
953         }
954
955         return SQL_SUCCESS;
956 }