Index: bind.c
===================================================================
RCS file: /usr/local/src/cvsroot/psqlodbc/bind.c,v
retrieving revision 1.1.1.3
retrieving revision 1.1.1.3.2.2
diff -c -r1.1.1.3 -r1.1.1.3.2.2
*** bind.c	2001/03/24 08:14:27	1.1.1.3
--- bind.c	2001/03/24 17:08:26	1.1.1.3.2.2
***************
*** 144,153 ****
  	}
  
  	/* Data at exec macro only valid for C char/binary data */
! 	if ((fSqlType == SQL_LONGVARBINARY || fSqlType == SQL_LONGVARCHAR) && pcbValue && *pcbValue <= SQL_LEN_DATA_AT_EXEC_OFFSET)
  		stmt->parameters[ipar].data_at_exec = TRUE;
  	else
  		stmt->parameters[ipar].data_at_exec = FALSE;
  
  	mylog("SQLBindParamater: ipar=%d, paramType=%d, fCType=%d, fSqlType=%d, cbColDef=%d, ibScale=%d, rgbValue=%d, *pcbValue = %d, data_at_exec = %d\n", ipar, fParamType, fCType, fSqlType, cbColDef, ibScale, rgbValue, pcbValue ? *pcbValue : -777, stmt->parameters[ipar].data_at_exec);
  
--- 144,158 ----
  	}
  
  	/* Data at exec macro only valid for C char/binary data */
! 	if (pcbValue && (*pcbValue == SQL_DATA_AT_EXEC || *pcbValue <= SQL_LEN_DATA_AT_EXEC_OFFSET))
  		stmt->parameters[ipar].data_at_exec = TRUE;
  	else
  		stmt->parameters[ipar].data_at_exec = FALSE;
+ 
+ 	/* Clear premature result */
+ 	if (stmt->status == STMT_PREMATURE)
+ 		SC_recycle_statement(stmt);
  
  	mylog("SQLBindParamater: ipar=%d, paramType=%d, fCType=%d, fSqlType=%d, cbColDef=%d, ibScale=%d, rgbValue=%d, *pcbValue = %d, data_at_exec = %d\n", ipar, fParamType, fCType, fSqlType, cbColDef, ibScale, rgbValue, pcbValue ? *pcbValue : -777, stmt->parameters[ipar].data_at_exec);
  
Index: convert.c
===================================================================
RCS file: /usr/local/src/cvsroot/psqlodbc/convert.c,v
retrieving revision 1.1.1.3
retrieving revision 1.1.1.3.2.1
diff -c -r1.1.1.3 -r1.1.1.3.2.1
*** convert.c	2001/03/24 08:14:31	1.1.1.3
--- convert.c	2001/03/24 15:35:10	1.1.1.3.2.1
***************
*** 838,844 ****
  		param_number++;
  
  		if (param_number >= stmt->parameters_allocated)
! 			break;
  
  		/* Assign correct buffers based on data at exec param or not */
  		if (stmt->parameters[param_number].data_at_exec)
--- 838,857 ----
  		param_number++;
  
  		if (param_number >= stmt->parameters_allocated)
! 		{
! 			if (stmt->pre_executing)
! 			{
! 				strcpy(&new_statement[npos], "NULL");
! 				npos += 4;
! 				stmt->inaccurate_result = TRUE;
! 				continue;
! 			}
! 			else
! 			{
! 				new_statement[npos++] = '?';
! 				continue;
! 			}
! 		}
  
  		/* Assign correct buffers based on data at exec param or not */
  		if (stmt->parameters[param_number].data_at_exec)
***************
*** 866,873 ****
  		 */
  		if (!buffer)
  		{
! 			new_statement[npos++] = '?';
! 			continue;
  		}
  
  		param_ctype = stmt->parameters[param_number].CType;
--- 879,896 ----
  		 */
  		if (!buffer)
  		{
! 			if (stmt->pre_executing)
! 			{
! 				strcpy(&new_statement[npos], "NULL");
! 				npos += 4;
! 				stmt->inaccurate_result = TRUE;
! 				continue;
! 			}
! 			else
! 			{
! 				new_statement[npos++] = '?';
! 				continue;
! 			}
  		}
  
  		param_ctype = stmt->parameters[param_number].CType;
Index: execute.c
===================================================================
RCS file: /usr/local/src/cvsroot/psqlodbc/execute.c,v
retrieving revision 1.1.1.3
retrieving revision 1.1.1.3.2.2
diff -c -r1.1.1.3 -r1.1.1.3.2.2
*** execute.c	2001/03/24 08:14:35	1.1.1.3
--- execute.c	2001/03/24 16:40:47	1.1.1.3.2.2
***************
*** 34,39 ****
--- 34,40 ----
  #include "qresult.h"
  #include "convert.h"
  #include "bind.h"
+ #include "pgtypes.h"
  #include "lobj.h"
  
  extern GLOBAL_VALUES globals;
***************
*** 223,239 ****
  	 */
  	if (stmt->prepare && stmt->status == STMT_PREMATURE)
  	{
! 		stmt->status = STMT_FINISHED;
! 		if (stmt->errormsg == NULL)
! 		{
! 			mylog("%s: premature statement but return SQL_SUCCESS\n", func);
! 			return SQL_SUCCESS;
! 		}
  		else
  		{
! 			SC_log_error(func, "", stmt);
! 			mylog("%s: premature statement so return SQL_ERROR\n", func);
! 			return SQL_ERROR;
  		}
  	}
  
--- 224,245 ----
  	 */
  	if (stmt->prepare && stmt->status == STMT_PREMATURE)
  	{
! 		if (stmt->inaccurate_result)
! 			SC_recycle_statement(stmt);
  		else
  		{
! 			stmt->status = STMT_FINISHED;
! 			if (stmt->errormsg == NULL)
! 			{
! 				mylog("%s: premature statement but return SQL_SUCCESS\n", func);
! 				return SQL_SUCCESS;
! 			}
! 			else
! 			{
! 				SC_log_error(func, "", stmt);
! 				mylog("%s: premature statement so return SQL_ERROR\n", func);
! 				return SQL_ERROR;
! 			}
  		}
  	}
  
***************
*** 284,314 ****
  	}
  
  
! 	/*
! 	 * The bound parameters could have possibly changed since the last
! 	 * execute of this statement?  Therefore check for params and re-copy.
! 	 */
! 	stmt->data_at_exec = -1;
! 	for (i = 0; i < stmt->parameters_allocated; i++)
  	{
! 		/* Check for data at execution parameters */
! 		if (stmt->parameters[i].data_at_exec == TRUE)
  		{
! 			if (stmt->data_at_exec < 0)
! 				stmt->data_at_exec = 1;
! 			else
! 				stmt->data_at_exec++;
  		}
! 	}
! 	/* If there are some data at execution parameters, return need data */
  
! 	/*
! 	 * SQLParamData and SQLPutData will be used to send params and execute
! 	 * the statement.
! 	 */
! 	if (stmt->data_at_exec > 0)
! 		return SQL_NEED_DATA;
  
  
  	mylog("%s: copying statement params: trans_status=%d, len=%d, stmt='%s'\n", func, conn->transact_status, strlen(stmt->statement), stmt->statement);
  
--- 290,326 ----
  	}
  
  
! 	/* Check if statement has any data-at-execute parameters when it is not in SC_pre_execute. */
! 	if (!stmt->pre_executing)
  	{
! 
! 		/*
! 		 * The bound parameters could have possibly changed since the last
! 		 * execute of this statement?  Therefore check for params and re-copy.
! 		 */
! 		stmt->data_at_exec = -1;
! 		for (i = 0; i < stmt->parameters_allocated; i++)
  		{
! 			/* Check for data at execution parameters */
! 			if (stmt->parameters[i].data_at_exec == TRUE)
! 			{
! 				if (stmt->data_at_exec < 0)
! 					stmt->data_at_exec = 1;
! 				else
! 					stmt->data_at_exec++;
! 			}
  		}
! 		/* If there are some data at execution parameters, return need data */
  
! 		/*
! 		 * SQLParamData and SQLPutData will be used to send params and execute
! 		 * the statement.
! 		 */
! 		if (stmt->data_at_exec > 0)
! 			return SQL_NEED_DATA;
  
+ 	}
+ 
  
  	mylog("%s: copying statement params: trans_status=%d, len=%d, stmt='%s'\n", func, conn->transact_status, strlen(stmt->statement), stmt->statement);
  
***************
*** 778,785 ****
  
  		}
  		else
! 		{						/* for handling text fields and small
! 								 * binaries */
  
  			if (cbValue == SQL_NTS)
  			{
--- 790,796 ----
  
  		}
  		else
! 		{						/* for handling fields */
  
  			if (cbValue == SQL_NTS)
  			{
***************
*** 794,809 ****
  			}
  			else
  			{
! 				current_param->EXEC_buffer = malloc(cbValue + 1);
! 				if (!current_param->EXEC_buffer)
  				{
! 					stmt->errornumber = STMT_NO_MEMORY_ERROR;
! 					stmt->errormsg = "Out of memory in SQLPutData (2)";
! 					SC_log_error(func, "", stmt);
! 					return SQL_ERROR;
  				}
- 				memcpy(current_param->EXEC_buffer, rgbValue, cbValue);
- 				current_param->EXEC_buffer[cbValue] = '\0';
  			}
  		}
  	}
--- 805,839 ----
  			}
  			else
  			{
! 				Int2 ctype = current_param->CType;
! 				if (ctype == SQL_C_DEFAULT)
! 					ctype = sqltype_to_default_ctype(current_param->SQLType);
! 				if (ctype == SQL_C_CHAR || ctype == SQL_C_BINARY)
  				{
! 					current_param->EXEC_buffer = malloc(cbValue + 1);
! 					if (!current_param->EXEC_buffer)
! 					{
! 						stmt->errornumber = STMT_NO_MEMORY_ERROR;
! 						stmt->errormsg = "Out of memory in SQLPutData (2)";
! 						SC_log_error(func, "", stmt);
! 						return SQL_ERROR;
! 					}
! 					memcpy(current_param->EXEC_buffer, rgbValue, cbValue);
! 					current_param->EXEC_buffer[cbValue] = '\0';
! 				}
! 				else
! 				{
! 					Int4 used = ctype_length(ctype);
! 					current_param->EXEC_buffer = malloc(used);
! 					if (!current_param->EXEC_buffer)
! 					{
! 						stmt->errornumber = STMT_NO_MEMORY_ERROR;
! 						stmt->errormsg = "Out of memory in SQLPutData (2)";
! 						SC_log_error(func, "", stmt);
! 						return SQL_ERROR;
! 					}
! 					memcpy(current_param->EXEC_buffer, rgbValue, used);
  				}
  			}
  		}
  	}
Index: pgtypes.c
===================================================================
RCS file: /usr/local/src/cvsroot/psqlodbc/pgtypes.c,v
retrieving revision 1.1.1.3
retrieving revision 1.1.1.3.2.2
diff -c -r1.1.1.3 -r1.1.1.3.2.2
*** pgtypes.c	2001/03/24 08:14:46	1.1.1.3
--- pgtypes.c	2001/03/24 16:40:47	1.1.1.3.2.2
***************
*** 956,958 ****
--- 956,1011 ----
  			return SQL_C_CHAR;
  	}
  }
+ 
+ Int4
+ ctype_length(Int2 ctype)
+ {
+ 	switch (ctype)
+ 	{
+ 		case SQL_C_SSHORT:
+ 		case SQL_C_SHORT:
+ 			return sizeof(SWORD);
+ 
+ 		case SQL_C_USHORT:
+ 			return sizeof(UWORD);
+ 
+ 		case SQL_C_SLONG:
+ 		case SQL_C_LONG:
+ 			return sizeof(SDWORD);
+ 
+ 		case SQL_C_ULONG:
+ 			return sizeof(UDWORD);
+ 
+ 		case SQL_C_FLOAT:
+ 			return sizeof(SFLOAT);
+ 
+ 		case SQL_C_DOUBLE:
+ 			return sizeof(SDOUBLE);
+ 
+ 		case SQL_C_BIT:
+ 			return sizeof(UCHAR);
+ 
+ 		case SQL_C_STINYINT:
+ 		case SQL_C_TINYINT:
+ 			return sizeof(SCHAR);
+ 
+ 		case SQL_C_UTINYINT:
+ 			return sizeof(UCHAR);
+ 
+ 		case SQL_C_DATE:
+ 			return sizeof(DATE_STRUCT);
+ 
+ 		case SQL_C_TIME:
+ 			return sizeof(TIME_STRUCT);
+ 
+ 		case SQL_C_TIMESTAMP:
+ 			return sizeof(TIMESTAMP_STRUCT);
+ 
+ 		case SQL_C_BINARY:
+ 		case SQL_C_CHAR:
+ 			return 0;
+ 
+ 		default:				/* should never happen */
+ 			return 0;
+ 	}
+ }
Index: pgtypes.h
===================================================================
RCS file: /usr/local/src/cvsroot/psqlodbc/pgtypes.h,v
retrieving revision 1.1.1.3
retrieving revision 1.1.1.3.2.1
diff -c -r1.1.1.3 -r1.1.1.3.2.1
*** pgtypes.h	2001/03/24 08:14:46	1.1.1.3
--- pgtypes.h	2001/03/24 15:35:12	1.1.1.3.2.1
***************
*** 93,97 ****
--- 93,98 ----
  char	   *pgtype_create_params(StatementClass *stmt, Int4 type);
  
  Int2		sqltype_to_default_ctype(Int2 sqltype);
+ Int4		ctype_length(Int2 ctype);
  
  #endif
Index: statement.c
===================================================================
RCS file: /usr/local/src/cvsroot/psqlodbc/statement.c,v
retrieving revision 1.1.1.3
retrieving revision 1.1.1.3.2.1
diff -c -r1.1.1.3 -r1.1.1.3.2.1
*** statement.c	2001/03/24 08:14:53	1.1.1.3
--- statement.c	2001/03/24 15:35:12	1.1.1.3.2.1
***************
*** 292,297 ****
--- 292,300 ----
  
  		/* Clear Statement Options -- defaults will be set in AllocStmt */
  		memset(&rv->options, 0, sizeof(StatementOptions));
+ 
+ 		rv->pre_executing = FALSE;
+ 		rv->inaccurate_result = FALSE;
  	}
  	return rv;
  }
***************
*** 519,524 ****
--- 522,528 ----
  		QR_Destructor(self->result);
  		self->result = NULL;
  	}
+ 	self->inaccurate_result = FALSE;
  
  	/****************************************************************/
  	/* Reset only parameters that have anything to do with results */
***************
*** 551,568 ****
  void
  SC_pre_execute(StatementClass *self)
  {
- 
  	mylog("SC_pre_execute: status = %d\n", self->status);
  
  	if (self->status == STMT_READY)
  	{
  		mylog("              preprocess: status = READY\n");
  
! 		SQLExecute(self);
  
! 		if (self->status == STMT_FINISHED)
  		{
! 			mylog("              preprocess: after status = FINISHED, so set PREMATURE\n");
  			self->status = STMT_PREMATURE;
  		}
  	}
--- 555,587 ----
  void
  SC_pre_execute(StatementClass *self)
  {
  	mylog("SC_pre_execute: status = %d\n", self->status);
  
  	if (self->status == STMT_READY)
  	{
  		mylog("              preprocess: status = READY\n");
+ 
+ 		if (self->statement_type == STMT_TYPE_SELECT)
+ 		{
+ 			char old_pre_executing = self->pre_executing;
+ 			self->pre_executing = TRUE;
+ 			self->inaccurate_result = FALSE;
  
! 			SQLExecute(self);
  
! 			self->pre_executing = old_pre_executing;
! 
! 			if (self->status == STMT_FINISHED)
! 			{
! 				mylog("              preprocess: after status = FINISHED, so set PREMATURE\n");
! 				self->status = STMT_PREMATURE;
! 			}
! 		}
! 		else
  		{
! 			self->result = QR_Constructor();
! 			QR_set_status(self->result, PGRES_TUPLES_OK);
! 			self->inaccurate_result = TRUE;
  			self->status = STMT_PREMATURE;
  		}
  	}
Index: statement.h
===================================================================
RCS file: /usr/local/src/cvsroot/psqlodbc/statement.h,v
retrieving revision 1.1.1.3
retrieving revision 1.1.1.3.2.1
diff -c -r1.1.1.3 -r1.1.1.3.2.1
*** statement.h	2001/03/24 08:14:54	1.1.1.3
--- statement.h	2001/03/24 15:35:13	1.1.1.3.2.1
***************
*** 213,218 ****
--- 213,221 ----
  														 * parameter
  														 * substitution */
  
+ 	char		pre_executing;	/* This statement is prematurely executing */
+ 	char		inaccurate_result;		/* Current status is PREMATURE
+ 										 * but result is inaccurate */
  };
  
  #define SC_get_conn(a)	  (a->hdbc)
