示例#1
0
RETCODE		SQL_API
SQLBindCol(HSTMT StatementHandle,
		   SQLUSMALLINT ColumnNumber, SQLSMALLINT TargetType,
		   PTR TargetValue, SQLLEN BufferLength,
		   SQLLEN *StrLen_or_Ind)
{
	RETCODE	ret;
	StatementClass *stmt = (StatementClass *) StatementHandle;

	mylog("[SQLBindCol]");
	ENTER_STMT_CS(stmt);
	SC_clear_error(stmt);
	StartRollbackState(stmt);
	ret = PGAPI_BindCol(StatementHandle, ColumnNumber,
				   TargetType, TargetValue, BufferLength, StrLen_or_Ind);
	ret = DiscardStatementSvp(stmt, ret, FALSE);
	LEAVE_STMT_CS(stmt);
	return ret;
}
示例#2
0
RETCODE		SQL_API
SQLSetPos(
		  HSTMT hstmt,
		  SQLSETPOSIROW irow,
		  SQLUSMALLINT fOption,
		  SQLUSMALLINT fLock)
{
	RETCODE	ret;
	StatementClass *stmt = (StatementClass *) hstmt;

	mylog("[SQLSetPos]");
	ENTER_STMT_CS(stmt);
	SC_clear_error(stmt);
	StartRollbackState(stmt);
	ret = PGAPI_SetPos(hstmt, irow, fOption, fLock);
	ret = DiscardStatementSvp(stmt, ret, FALSE);
	LEAVE_STMT_CS(stmt);
	return ret;
}
示例#3
0
RETCODE SQL_API	SQLSetStmtAttrW(SQLHSTMT hstmt,
		SQLINTEGER	fAttribute,
		PTR		rgbValue,
		SQLINTEGER	cbValueMax)
{
	CSTR func = "SQLSetStmtAttrW";
	RETCODE	ret;
	StatementClass	*stmt = (StatementClass *) hstmt;

	mylog("[%s]", func);
	ENTER_STMT_CS(stmt);
	SC_clear_error(stmt);
	StartRollbackState(stmt);
	ret = PGAPI_SetStmtAttr(hstmt, fAttribute, rgbValue,
		cbValueMax);
	ret = DiscardStatementSvp(stmt, ret, FALSE);
	LEAVE_STMT_CS(stmt);
	return ret;
}
示例#4
0
RETCODE  SQL_API
SQLStatisticsW(HSTMT StatementHandle,
			   SQLWCHAR *CatalogName, SQLSMALLINT NameLength1,
			   SQLWCHAR *SchemaName, SQLSMALLINT NameLength2,
			   SQLWCHAR *TableName, SQLSMALLINT NameLength3,
			   SQLUSMALLINT Unique, SQLUSMALLINT Reserved)
{
	CSTR func = "SQLStatisticsW";
	RETCODE	ret;
	char	*ctName, *scName, *tbName;
	SQLLEN	nmlen1, nmlen2, nmlen3;
	StatementClass *stmt = (StatementClass *) StatementHandle;
	ConnectionClass *conn;
	BOOL lower_id;

	mylog("[%s]", func);
	conn = SC_get_conn(stmt);
	lower_id = SC_is_lower_case(stmt, conn);
	ctName = ucs2_to_utf8(CatalogName, NameLength1, &nmlen1, lower_id);
	scName = ucs2_to_utf8(SchemaName, NameLength2, &nmlen2, lower_id);
	tbName = ucs2_to_utf8(TableName, NameLength3, &nmlen3, lower_id);
	ENTER_STMT_CS(stmt);
	SC_clear_error(stmt);
	StartRollbackState(stmt);
	if (SC_opencheck(stmt, func))
		ret = SQL_ERROR;
	else
		ret = PGAPI_Statistics(StatementHandle,
							   (SQLCHAR *) ctName, (SQLSMALLINT) nmlen1,
							   (SQLCHAR *) scName, (SQLSMALLINT) nmlen2,
							   (SQLCHAR *) tbName, (SQLSMALLINT) nmlen3,
							   Unique, Reserved);
	ret = DiscardStatementSvp(stmt, ret, FALSE);
	LEAVE_STMT_CS(stmt);
	if (ctName)
		free(ctName);
	if (scName)
		free(scName);
	if (tbName)
		free(tbName);
	return ret;
}
示例#5
0
RETCODE SQL_API
SQLGetTypeInfoW(SQLHSTMT	StatementHandle,
				SQLSMALLINT	DataType)
{
	CSTR func = "SQLGetTypeInfoW";
	RETCODE	ret;
	StatementClass * stmt = (StatementClass *) StatementHandle;

	mylog("[%s]", func);
	ENTER_STMT_CS(stmt);
	SC_clear_error(stmt);
	StartRollbackState(stmt);
	if (SC_opencheck(stmt, func))
		ret = SQL_ERROR;
	else
		ret = PGAPI_GetTypeInfo(StatementHandle, DataType);
	ret = DiscardStatementSvp(stmt, ret, FALSE);
	LEAVE_STMT_CS(stmt);
	return ret;
}
RETCODE SQL_API SQLPrimaryKeysW(
    HSTMT           hstmt,
    SQLWCHAR          *szCatalogName,
    SQLSMALLINT        cbCatalogName,
    SQLWCHAR          *szSchemaName,
    SQLSMALLINT        cbSchemaName,
    SQLWCHAR          *szTableName,
    SQLSMALLINT        cbTableName)
{
    CSTR func = "SQLPrimaryKeysW";
    RETCODE ret;
    char    *ctName, *scName, *tbName;
    SQLLEN  nmlen1, nmlen2, nmlen3;
    StatementClass *stmt = (StatementClass *) hstmt;
    ConnectionClass *conn;
    BOOL    lower_id; 

    mylog("[%s]", func);
    conn = SC_get_conn(stmt);
    lower_id = SC_is_lower_case(stmt, conn);
    ctName = ucs2_to_utf8(szCatalogName, cbCatalogName, &nmlen1, lower_id);
    scName = ucs2_to_utf8(szSchemaName, cbSchemaName, &nmlen2, lower_id);
    tbName = ucs2_to_utf8(szTableName, cbTableName, &nmlen3, lower_id);
    ENTER_STMT_CS(stmt);
    SC_clear_error(stmt);
    StartRollbackState(stmt);
    if (SC_opencheck(stmt, func))
        ret = SQL_ERROR;
    else
        ret = PGAPI_PrimaryKeys(hstmt, ctName, (SQLSMALLINT) nmlen1,
            scName, (SQLSMALLINT) nmlen2, tbName, (SQLSMALLINT) nmlen3, 0);
    ret = DiscardStatementSvp(stmt, ret, FALSE);
    LEAVE_STMT_CS(stmt);
    if (ctName)
        free(ctName);
    if (scName)
        free(scName);
    if (tbName)
        free(tbName);
    return ret;
}
示例#7
0
RETCODE		SQL_API
SQLDescribeParam(HSTMT hstmt,
				 SQLUSMALLINT ipar,
				 SQLSMALLINT *pfSqlType,
				 SQLULEN *pcbParamDef,
				 SQLSMALLINT *pibScale,
				 SQLSMALLINT *pfNullable)
{
	RETCODE	ret;
	StatementClass *stmt = (StatementClass *) hstmt;

	mylog("[SQLDescribeParam]");
	ENTER_STMT_CS(stmt);
	SC_clear_error(stmt);
	StartRollbackState(stmt);
	ret = PGAPI_DescribeParam(hstmt, ipar, pfSqlType, pcbParamDef,
							   pibScale, pfNullable);
	ret = DiscardStatementSvp(stmt, ret, FALSE);
	LEAVE_STMT_CS(stmt);
	return ret;
}
示例#8
0
/*	SQLBindParameter/SQLSetParam -> SQLBindParam */
RETCODE		SQL_API
SQLBindParam(HSTMT StatementHandle,
			 SQLUSMALLINT ParameterNumber, SQLSMALLINT ValueType,
			 SQLSMALLINT ParameterType, SQLULEN LengthPrecision,
			 SQLSMALLINT ParameterScale, PTR ParameterValue,
			 SQLLEN *StrLen_or_Ind)
{
	CSTR	func = "SQLBindParam";
	RETCODE			ret;
	StatementClass	*stmt = (StatementClass *) StatementHandle;
	int			BufferLength = 512;		/* Is it OK ? */

	mylog("[[%s]]", func);
	ENTER_STMT_CS(stmt);
	SC_clear_error(stmt);
	StartRollbackState(stmt);
	ret = PGAPI_BindParameter(StatementHandle, ParameterNumber, SQL_PARAM_INPUT, ValueType, ParameterType, LengthPrecision, ParameterScale, ParameterValue, BufferLength, StrLen_or_Ind);
	ret = DiscardStatementSvp(stmt,ret, FALSE);
	LEAVE_STMT_CS(stmt);
	return ret;
}
RETCODE  SQL_API SQLSetCursorNameW(HSTMT StatementHandle,
           SQLWCHAR *CursorName, SQLSMALLINT NameLength)
{
    CSTR func = "SQLSetCursorNameW";
    RETCODE ret;
    StatementClass *stmt = (StatementClass *) StatementHandle;
    char    *crName;
    SQLLEN  nlen;

    mylog("[%s]", func);
    crName = ucs2_to_utf8(CursorName, NameLength, &nlen, FALSE);
    ENTER_STMT_CS(stmt);
    SC_clear_error(stmt);
    StartRollbackState(stmt);
    ret = PGAPI_SetCursorName(StatementHandle, crName, (SQLSMALLINT) nlen);
    ret = DiscardStatementSvp(stmt, ret, FALSE);
    LEAVE_STMT_CS(stmt);
    if (crName)
        free(crName);
    return ret;
}
示例#10
0
RETCODE		SQL_API
SQLDescribeCol(HSTMT StatementHandle,
			   SQLUSMALLINT ColumnNumber, SQLCHAR *ColumnName,
			   SQLSMALLINT BufferLength, SQLSMALLINT *NameLength,
			   SQLSMALLINT *DataType, SQLULEN *ColumnSize,
			   SQLSMALLINT *DecimalDigits, SQLSMALLINT *Nullable)
{
	RETCODE	ret;
	StatementClass *stmt = (StatementClass *) StatementHandle;

	mylog("[SQLDescribeCol]");
	ENTER_STMT_CS(stmt);
	SC_clear_error(stmt);
	StartRollbackState(stmt);
	ret = PGAPI_DescribeCol(StatementHandle, ColumnNumber,
							 ColumnName, BufferLength, NameLength,
						  DataType, ColumnSize, DecimalDigits, Nullable);
	ret = DiscardStatementSvp(stmt, ret, FALSE);
	LEAVE_STMT_CS(stmt);
	return ret;
}
示例#11
0
RETCODE		SQL_API
SQLColAttributes(HSTMT hstmt,
				 SQLUSMALLINT icol,
				 SQLUSMALLINT fDescType,
				 PTR rgbDesc,
				 SQLSMALLINT cbDescMax,
				 SQLSMALLINT *pcbDesc,
				 SQLLEN *pfDesc)
{
	RETCODE	ret;
	StatementClass *stmt = (StatementClass *) hstmt;

	mylog("[SQLColAttributes]");
	ENTER_STMT_CS(stmt);
	SC_clear_error(stmt);
	StartRollbackState(stmt);
	ret = PGAPI_ColAttributes(hstmt, icol, fDescType, rgbDesc,
							   cbDescMax, pcbDesc, pfDesc);
	ret = DiscardStatementSvp(stmt, ret, FALSE);
	LEAVE_STMT_CS(stmt);
	return ret;
}
示例#12
0
RETCODE		SQL_API
SQLPrepare(HSTMT StatementHandle,
		   SQLCHAR *StatementText, SQLINTEGER TextLength)
{
	CSTR func = "SQLPrepare";
	RETCODE	ret;
	StatementClass *stmt = (StatementClass *) StatementHandle;

	mylog("[SQLPrepare]");
	ENTER_STMT_CS(stmt);
	SC_clear_error(stmt);
	if (SC_opencheck(stmt, func))
		ret = SQL_ERROR;
	else
	{
		StartRollbackState(stmt);
		ret = PGAPI_Prepare(StatementHandle, StatementText, TextLength);
		ret = DiscardStatementSvp(stmt, ret, FALSE);
	}
	LEAVE_STMT_CS(stmt);
	return ret;
}
示例#13
0
RETCODE  SQL_API SQLPrepareW(HSTMT StatementHandle,
           SQLWCHAR *StatementText, SQLINTEGER TextLength)
{
    CSTR func = "SQLPrepareW";
    StatementClass *stmt = (StatementClass *) StatementHandle;
    RETCODE ret;
    char    *stxt;
    SQLLEN  slen;

    mylog("[%s]", func);
    stxt = ucs2_to_utf8(StatementText, TextLength, &slen, FALSE);
    ENTER_STMT_CS(stmt);
    SC_clear_error(stmt);
    StartRollbackState(stmt);
    if (SC_opencheck(stmt, func))
        ret = SQL_ERROR;
    else
        ret = PGAPI_Prepare(StatementHandle, stxt, (SQLINTEGER) slen);
    ret = DiscardStatementSvp(stmt, ret, FALSE);
    LEAVE_STMT_CS(stmt);
    if (stxt)
        free(stxt);
    return ret;
}
示例#14
0
RETCODE		SQL_API
SQLExecute(HSTMT StatementHandle)
{
	CSTR func = "SQLExecute";
	RETCODE	ret;
	StatementClass *stmt = (StatementClass *) StatementHandle;
	UWORD	flag = 0;

	mylog("[%s]", func);
	ENTER_STMT_CS(stmt);
	SC_clear_error(stmt);
	if (PG_VERSION_GE(SC_get_conn(stmt), 7.4))
		flag |= PODBC_WITH_HOLD;
	if (SC_opencheck(stmt, func))
		ret = SQL_ERROR;
	else
	{
		StartRollbackState(stmt);
		ret = PGAPI_Execute(StatementHandle, flag);
		ret = DiscardStatementSvp(stmt, ret, FALSE);
	}
	LEAVE_STMT_CS(stmt);
	return ret;
}
示例#15
0
文件: execute.c 项目: vadz/psqlodbc
/*
 *	Supplies parameter data at execution time.
 *	Used in conjuction with SQLPutData.
 */
RETCODE		SQL_API
PGAPI_ParamData(
				HSTMT hstmt,
				PTR FAR * prgbValue)
{
	CSTR func = "PGAPI_ParamData";
	StatementClass *stmt = (StatementClass *) hstmt, *estmt;
	APDFields	*apdopts;
	IPDFields	*ipdopts;
	RETCODE		retval;
	int		i;
	Int2		num_p;
	ConnectionClass	*conn = NULL;

	mylog("%s: entering...\n", func);

	if (!stmt)
	{
		SC_log_error(func, "", NULL);
		retval = SQL_INVALID_HANDLE;
		goto cleanup;
	}
	conn = SC_get_conn(stmt);

	estmt = stmt->execute_delegate ? stmt->execute_delegate : stmt;
	apdopts = SC_get_APDF(estmt);
	mylog("%s: data_at_exec=%d, params_alloc=%d\n", func, estmt->data_at_exec, apdopts->allocated);

#define	return	DONT_CALL_RETURN_FROM_HERE???
	if (SC_AcceptedCancelRequest(stmt))
	{
		SC_set_error(stmt, STMT_OPERATION_CANCELLED, "Cancel the statement, sorry", func);
		retval = SQL_ERROR;
		goto cleanup;
	}
	if (estmt->data_at_exec < 0)
	{
		SC_set_error(stmt, STMT_SEQUENCE_ERROR, "No execution-time parameters for this statement", func);
		retval = SQL_ERROR;
		goto cleanup;
	}

	if (estmt->data_at_exec > apdopts->allocated)
	{
		SC_set_error(stmt, STMT_SEQUENCE_ERROR, "Too many execution-time parameters were present", func);
		retval = SQL_ERROR;
		goto cleanup;
	}

	/* close the large object */
	if (estmt->lobj_fd >= 0)
	{
		odbc_lo_close(conn, estmt->lobj_fd);

		/* commit transaction if needed */
		if (!CC_cursor_count(conn) && CC_does_autocommit(conn))
		{
			if (!CC_commit(conn))
			{
				SC_set_error(stmt, STMT_EXEC_ERROR, "Could not commit (in-line) a transaction", func);
				retval = SQL_ERROR;
				goto cleanup;
			}
		}
		estmt->lobj_fd = -1;
	}

	/* Done, now copy the params and then execute the statement */
	ipdopts = SC_get_IPDF(estmt);
inolog("ipdopts=%p\n", ipdopts);
	if (estmt->data_at_exec == 0)
	{
		BOOL	exec_end;
		UWORD	flag = SC_is_with_hold(stmt) ? PODBC_WITH_HOLD : 0;

		retval = Exec_with_parameters_resolved(estmt, &exec_end);
		if (exec_end)
		{
			/**SC_reset_delegate(retval, stmt);**/
			retval = dequeueNeedDataCallback(retval, stmt);
			goto cleanup;
		}
		if (retval = PGAPI_Execute(estmt, flag), SQL_NEED_DATA != retval)
		{
			goto cleanup;
		}
	}

	/*
	 * Set beginning param;  if first time SQLParamData is called , start
	 * at 0. Otherwise, start at the last parameter + 1.
	 */
	i = estmt->current_exec_param >= 0 ? estmt->current_exec_param + 1 : 0;

	num_p = estmt->num_params;
	if (num_p < 0)
		PGAPI_NumParams(estmt, &num_p);
inolog("i=%d allocated=%d num_p=%d\n", i, apdopts->allocated, num_p);
	if (num_p > apdopts->allocated)
		num_p = apdopts->allocated;
	/* At least 1 data at execution parameter, so Fill in the token value */
	for (; i < num_p; i++)
	{
inolog("i=%d", i);
		if (apdopts->parameters[i].data_at_exec)
		{
inolog(" at exec buffer=%p", apdopts->parameters[i].buffer);
			estmt->data_at_exec--;
			estmt->current_exec_param = i;
			estmt->put_data = FALSE;
			if (prgbValue)
			{
				/* returns token here */
				if (stmt->execute_delegate)
				{
					SQLULEN	offset = apdopts->param_offset_ptr ? *apdopts->param_offset_ptr : 0;
					SQLLEN	perrow = apdopts->param_bind_type > 0 ? apdopts->param_bind_type : apdopts->parameters[i].buflen; 

inolog(" offset=%d perrow=%d", offset, perrow);
					*prgbValue = apdopts->parameters[i].buffer + offset + estmt->exec_current_row * perrow;
				}
				else
					*prgbValue = apdopts->parameters[i].buffer;
			}
			break;
		}
inolog("\n");
	}

	retval = SQL_NEED_DATA;
inolog("return SQL_NEED_DATA\n");
cleanup:
#undef	return
	SC_setInsertedTable(stmt, retval);
	if (stmt->internal)
		retval = DiscardStatementSvp(stmt, retval, FALSE);
	mylog("%s: returning %d\n", func, retval);
	return retval;
}
示例#16
0
RETCODE		SQL_API
SQLProcedures(
			  HSTMT hstmt,
			  SQLCHAR *szCatalogName,
			  SQLSMALLINT cbCatalogName,
			  SQLCHAR *szSchemaName,
			  SQLSMALLINT cbSchemaName,
			  SQLCHAR *szProcName,
			  SQLSMALLINT cbProcName)
{
	CSTR func = "SQLProcedures";
	RETCODE	ret;
	StatementClass *stmt = (StatementClass *) hstmt;
	SQLCHAR	*ctName = szCatalogName, *scName = szSchemaName,
		*prName = szProcName;
	UWORD	flag = 0;

	mylog("[%s]", func);
	ENTER_STMT_CS(stmt);
	SC_clear_error(stmt);
	StartRollbackState(stmt);
#if (ODBCVER >= 0x0300)
	if (stmt->options.metadata_id)
		flag |= PODBC_NOT_SEARCH_PATTERN;
#endif
	if (SC_opencheck(stmt, func))
		ret = SQL_ERROR;
	else
		ret = PGAPI_Procedures(hstmt, ctName, cbCatalogName,
					 scName, cbSchemaName, prName,
					 cbProcName, flag);
	if (SQL_SUCCESS == ret && 0 == QR_get_num_total_tuples(SC_get_Result(stmt))) 
	{
		BOOL	ifallupper = TRUE, reexec = FALSE;
		char *newCt = NULL, *newSc = NULL, *newPr = NULL;
		ConnectionClass *conn = SC_get_conn(stmt);

		if (SC_is_lower_case(stmt, conn)) /* case-insensitive identifier */
			ifallupper = FALSE;
		if (newCt = make_lstring_ifneeded(conn, szCatalogName, cbCatalogName, ifallupper), NULL != newCt)
		{
			ctName = newCt;
			reexec = TRUE;
		}
		if (newSc = make_lstring_ifneeded(conn, szSchemaName, cbSchemaName, ifallupper), NULL != newSc)
		{
			scName = newSc;
			reexec = TRUE;
		}
		if (newPr = make_lstring_ifneeded(conn, szProcName, cbProcName, ifallupper), NULL != newPr)
		{
			prName = newPr;
			reexec = TRUE;
		}
		if (reexec)
		{
			ret = PGAPI_Procedures(hstmt, ctName, cbCatalogName,
					 scName, cbSchemaName, prName, cbProcName, flag);
			if (newCt)
				free(newCt);
			if (newSc)
				free(newSc);
			if (newPr)
				free(newPr);
		}
	}
	ret = DiscardStatementSvp(stmt, ret, FALSE);
	LEAVE_STMT_CS(stmt);
	return ret;
}
示例#17
0
/*
 *	Returns the description of a parameter marker.
 *	This function is listed as not being supported by SQLGetFunctions() because it is
 *	used to describe "parameter markers" (not bound parameters), in which case,
 *	the dbms should return info on the markers.  Since Postgres doesn't support that,
 *	it is best to say this function is not supported and let the application assume a
 *	data type (most likely varchar).
 */
RETCODE		SQL_API
PGAPI_DescribeParam(HSTMT hstmt,
					SQLUSMALLINT ipar,
					SQLSMALLINT FAR * pfSqlType,
					SQLULEN FAR * pcbParamDef,
					SQLSMALLINT FAR * pibScale,
					SQLSMALLINT FAR * pfNullable)
{
	StatementClass *stmt = (StatementClass *) hstmt;
	CSTR func = "PGAPI_DescribeParam";
	IPDFields	*ipdopts;
	RETCODE		ret = SQL_SUCCESS;
	int		num_params;
	OID		pgtype;

	mylog("%s: entering...%d\n", func, ipar);

	if (!stmt)
	{
		SC_log_error(func, "", NULL);
		return SQL_INVALID_HANDLE;
	}
	SC_clear_error(stmt);

	ipdopts = SC_get_IPDF(stmt);
	/*if ((ipar < 1) || (ipar > ipdopts->allocated))*/
	num_params = stmt->num_params;
	if (num_params < 0)
	{
		SQLSMALLINT	num_p;

		PGAPI_NumParams(stmt, &num_p);
		num_params = num_p;
	}
	if ((ipar < 1) || (ipar > num_params))
	{
inolog("num_params=%d\n", stmt->num_params);
		SC_set_error(stmt, STMT_BAD_PARAMETER_NUMBER_ERROR, "Invalid parameter number for PGAPI_DescribeParam.", func);
		return SQL_ERROR;
	}
	extend_iparameter_bindings(ipdopts, stmt->num_params);

#define	return	DONT_CALL_RETURN_FROM_HERE???
	/* StartRollbackState(stmt); */
	if (NOT_YET_PREPARED == stmt->prepared)
	{
		decideHowToPrepare(stmt, FALSE);
inolog("howTo=%d\n", SC_get_prepare_method(stmt));
		switch (SC_get_prepare_method(stmt))
		{
			case NAMED_PARSE_REQUEST:
			case PARSE_TO_EXEC_ONCE:
			case PARSE_REQ_FOR_INFO:
				if (ret = prepareParameters(stmt), SQL_ERROR == ret)
					goto cleanup;
		}
	}

	ipar--;
	pgtype = PIC_get_pgtype(ipdopts->parameters[ipar]);
	/*
	 * This implementation is not very good, since it is supposed to
	 * describe
	 */
	/* parameter markers, not bound parameters.  */
	if (pfSqlType)
	{
inolog("[%d].SQLType=%d .PGType=%d\n", ipar, ipdopts->parameters[ipar].SQLType, pgtype);
		if (ipdopts->parameters[ipar].SQLType)
			*pfSqlType = ipdopts->parameters[ipar].SQLType;
		else if (pgtype)
			*pfSqlType = pgtype_to_concise_type(stmt, pgtype, PG_STATIC);
		else
		{
			ret = SQL_ERROR;
			SC_set_error(stmt, STMT_EXEC_ERROR, "Unfortunatley couldn't get this paramater's info", func);
			goto cleanup;
		}
	}

	if (pcbParamDef)
	{
		*pcbParamDef = 0;
		if (ipdopts->parameters[ipar].SQLType)
			*pcbParamDef = ipdopts->parameters[ipar].column_size;
		if (0 == *pcbParamDef && pgtype)
			*pcbParamDef = pgtype_column_size(stmt, pgtype, PG_STATIC, PG_STATIC);
	}

	if (pibScale)
	{
		*pibScale = 0;
		if (ipdopts->parameters[ipar].SQLType)
			*pibScale = ipdopts->parameters[ipar].decimal_digits;
		else if (pgtype)
			*pibScale = pgtype_scale(stmt, pgtype, -1);
	}

	if (pfNullable)
		*pfNullable = pgtype_nullable(SC_get_conn(stmt), ipdopts->parameters[ipar].paramType);
cleanup:
#undef	return
	if (stmt->internal)
		ret = DiscardStatementSvp(stmt, ret, FALSE);
	return ret;
}
示例#18
0
RETCODE		SQL_API
SQLForeignKeys(
			   HSTMT hstmt,
			   SQLCHAR *szPkCatalogName,
			   SQLSMALLINT cbPkCatalogName,
			   SQLCHAR *szPkSchemaName,
			   SQLSMALLINT cbPkSchemaName,
			   SQLCHAR *szPkTableName,
			   SQLSMALLINT cbPkTableName,
			   SQLCHAR *szFkCatalogName,
			   SQLSMALLINT cbFkCatalogName,
			   SQLCHAR *szFkSchemaName,
			   SQLSMALLINT cbFkSchemaName,
			   SQLCHAR *szFkTableName,
			   SQLSMALLINT cbFkTableName)
{
	CSTR func = "SQLForeignKeys";
	RETCODE	ret;
	StatementClass *stmt = (StatementClass *) hstmt;
	SQLCHAR *pkctName = szPkCatalogName, *pkscName = szPkSchemaName,
		*pktbName = szPkTableName, *fkctName = szFkCatalogName,
		*fkscName = szFkSchemaName, *fktbName = szFkTableName;

	mylog("[%s]", func);
	ENTER_STMT_CS(stmt);
	SC_clear_error(stmt);
	StartRollbackState(stmt);
	if (SC_opencheck(stmt, func))
		ret = SQL_ERROR;
	else
		ret = PGAPI_ForeignKeys(hstmt, pkctName, cbPkCatalogName,
			pkscName, cbPkSchemaName, pktbName, cbPkTableName,
			fkctName, cbFkCatalogName, fkscName, cbFkSchemaName,
			fktbName, cbFkTableName);
	if (SQL_SUCCESS == ret && 0 == QR_get_num_total_tuples(SC_get_Result(stmt))) 
	{
		BOOL	ifallupper = TRUE, reexec = FALSE;
		char *newPkct = NULL, *newPksc = NULL, *newPktb = NULL,
			*newFkct = NULL, *newFksc = NULL, *newFktb = NULL;
		ConnectionClass *conn = SC_get_conn(stmt);

		if (SC_is_lower_case(stmt, conn)) /* case-insensitive identifier */
			ifallupper = FALSE;
		if (newPkct = make_lstring_ifneeded(conn, szPkCatalogName, cbPkCatalogName, ifallupper), NULL != newPkct)
		{
			pkctName = newPkct;
			reexec = TRUE;
		}
		if (newPksc = make_lstring_ifneeded(conn, szPkSchemaName, cbPkSchemaName, ifallupper), NULL != newPksc)
		{
			pkscName = newPksc;
			reexec = TRUE;
		}
		if (newPktb = make_lstring_ifneeded(conn, szPkTableName, cbPkTableName, ifallupper), NULL != newPktb)
		{
			pktbName = newPktb;
			reexec = TRUE;
		}
		if (newFkct = make_lstring_ifneeded(conn, szFkCatalogName, cbFkCatalogName, ifallupper), NULL != newFkct)
		{
			fkctName = newFkct;
			reexec = TRUE;
		}
		if (newFksc = make_lstring_ifneeded(conn, szFkSchemaName, cbFkSchemaName, ifallupper), NULL != newFksc)
		{
			fkscName = newFksc;
			reexec = TRUE;
		}
		if (newFktb = make_lstring_ifneeded(conn, szFkTableName, cbFkTableName, ifallupper), NULL != newFktb)
		{
			fktbName = newFktb;
			reexec = TRUE;
		}
		if (reexec)
		{
			ret = PGAPI_ForeignKeys(hstmt, pkctName, cbPkCatalogName,
			pkscName, cbPkSchemaName, pktbName, cbPkTableName,
			fkctName, cbFkCatalogName, fkscName, cbFkSchemaName,
			fktbName, cbFkTableName);
			if (newPkct)
				free(newPkct);
			if (newPksc)
				free(newPksc);
			if (newPktb)
				free(newPktb);
			if (newFkct)
				free(newFkct);
			if (newFksc)
				free(newFksc);
			if (newFktb)
				free(newFktb);
		}
	}
	ret = DiscardStatementSvp(stmt, ret, FALSE);
	LEAVE_STMT_CS(stmt);
	return ret;
}
示例#19
0
RETCODE		SQL_API
SQLPrimaryKeys(
			   HSTMT hstmt,
			   SQLCHAR *szCatalogName,
			   SQLSMALLINT cbCatalogName,
			   SQLCHAR *szSchemaName,
			   SQLSMALLINT cbSchemaName,
			   SQLCHAR *szTableName,
			   SQLSMALLINT cbTableName)
{
	CSTR func = "SQLPrimaryKeys";
	RETCODE	ret;
	StatementClass *stmt = (StatementClass *) hstmt;
	SQLCHAR	*ctName = szCatalogName, *scName = szSchemaName,
		*tbName = szTableName;

	mylog("[%s]", func);
	ENTER_STMT_CS(stmt);
	SC_clear_error(stmt);
	StartRollbackState(stmt);
	if (SC_opencheck(stmt, func))
		ret = SQL_ERROR;
	else
		ret = PGAPI_PrimaryKeys(hstmt, ctName, cbCatalogName,
			scName, cbSchemaName, tbName, cbTableName, 0);
	if (SQL_SUCCESS == ret && 0 == QR_get_num_total_tuples(SC_get_Result(stmt))) 
	{
		BOOL	ifallupper = TRUE, reexec = FALSE;
		char *newCt = NULL, *newSc = NULL, *newTb = NULL;
		ConnectionClass *conn = SC_get_conn(stmt);

		if (SC_is_lower_case(stmt, conn)) /* case-insensitive identifier */
			ifallupper = FALSE;
		if (newCt = make_lstring_ifneeded(conn, szCatalogName, cbCatalogName, ifallupper), NULL != newCt)
		{
			ctName = newCt;
			reexec = TRUE;
		}
		if (newSc = make_lstring_ifneeded(conn, szSchemaName, cbSchemaName, ifallupper), NULL != newSc)
		{
			scName = newSc;
			reexec = TRUE;
		}
		if (newTb = make_lstring_ifneeded(conn, szTableName, cbTableName, ifallupper), NULL != newTb)
		{
			tbName = newTb;
			reexec = TRUE;
		}
		if (reexec)
		{
			ret = PGAPI_PrimaryKeys(hstmt, ctName, cbCatalogName,
			scName, cbSchemaName, tbName, cbTableName, 0);
			if (newCt)
				free(newCt);
			if (newSc)
				free(newSc);
			if (newTb)
				free(newTb);
		}
	}
	ret = DiscardStatementSvp(stmt, ret, FALSE);
	LEAVE_STMT_CS(stmt);
	return ret;
}
示例#20
0
文件: execute.c 项目: vadz/psqlodbc
/*		Perform a Prepare on the SQL statement */
RETCODE		SQL_API
PGAPI_Prepare(HSTMT hstmt,
			  const SQLCHAR FAR * szSqlStr,
			  SQLINTEGER cbSqlStr)
{
	CSTR func = "PGAPI_Prepare";
	StatementClass *self = (StatementClass *) hstmt;
	RETCODE	retval = SQL_SUCCESS;

	mylog("%s: entering...\n", func);

#define	return	DONT_CALL_RETURN_FROM_HERE???
	/* StartRollbackState(self); */
	if (!self)
	{
		SC_log_error(func, "", NULL);
		retval = SQL_INVALID_HANDLE;
		goto cleanup;
	}

	/*
	 * According to the ODBC specs it is valid to call SQLPrepare multiple
	 * times. In that case, the bound SQL statement is replaced by the new
	 * one
	 */

	SC_set_prepared(self, NOT_YET_PREPARED);
	switch (self->status)
	{
		case STMT_PREMATURE:
			mylog("**** PGAPI_Prepare: STMT_PREMATURE, recycle\n");
			SC_recycle_statement(self); /* recycle the statement, but do
										 * not remove parameter bindings */
			break;

		case STMT_FINISHED:
			mylog("**** PGAPI_Prepare: STMT_FINISHED, recycle\n");
			SC_recycle_statement(self); /* recycle the statement, but do
										 * not remove parameter bindings */
			break;

		case STMT_ALLOCATED:
			mylog("**** PGAPI_Prepare: STMT_ALLOCATED, copy\n");
			self->status = STMT_READY;
			break;

		case STMT_READY:
			mylog("**** PGAPI_Prepare: STMT_READY, change SQL\n");
			break;

		case STMT_EXECUTING:
			mylog("**** PGAPI_Prepare: STMT_EXECUTING, error!\n");

			SC_set_error(self, STMT_SEQUENCE_ERROR, "PGAPI_Prepare(): The handle does not point to a statement that is ready to be executed", func);

			retval = SQL_ERROR;
			goto cleanup;

		default:
			SC_set_error(self, STMT_INTERNAL_ERROR, "An Internal Error has occured -- Unknown statement status.", func);
			retval = SQL_ERROR;
			goto cleanup;
	}

	SC_initialize_stmts(self, TRUE);

	if (!szSqlStr)
	{
		SC_set_error(self, STMT_NO_MEMORY_ERROR, "the query is NULL", func);
		retval = SQL_ERROR;
		goto cleanup;
	}
	if (!szSqlStr[0])
		self->statement = strdup("");
	else
		self->statement = make_string(szSqlStr, cbSqlStr, NULL, 0);
	if (!self->statement)
	{
		SC_set_error(self, STMT_NO_MEMORY_ERROR, "No memory available to store statement", func);
		retval = SQL_ERROR;
		goto cleanup;
	}

	self->prepare = PREPARE_STATEMENT;
	self->statement_type = statement_type(self->statement);

	/* Check if connection is onlyread (only selects are allowed) */
	if (CC_is_onlyread(SC_get_conn(self)) && STMT_UPDATE(self))
	{
		SC_set_error(self, STMT_EXEC_ERROR, "Connection is readonly, only select statements are allowed.", func);
		retval = SQL_ERROR;
		goto cleanup;
	}

cleanup:
#undef	return
inolog("SQLPrepare return=%d\n", retval);
	if (self->internal)
		retval = DiscardStatementSvp(self, retval, FALSE);
	return retval;
}
示例#21
0
文件: execute.c 项目: vadz/psqlodbc
/*	Execute a prepared SQL statement */
RETCODE		SQL_API
PGAPI_Execute(HSTMT hstmt, UWORD flag)
{
	CSTR func = "PGAPI_Execute";
	StatementClass *stmt = (StatementClass *) hstmt;
	RETCODE		retval = SQL_SUCCESS;
	ConnectionClass	*conn;
	APDFields	*apdopts;
	IPDFields	*ipdopts;
	SQLLEN		i, start_row, end_row;
	BOOL	exec_end, recycled = FALSE, recycle = TRUE;
	SQLSMALLINT	num_params;

	mylog("%s: entering...%x\n", func, flag);

	if (!stmt)
	{
		SC_log_error(func, "", NULL);
		mylog("%s: NULL statement so return SQL_INVALID_HANDLE\n", func);
		return SQL_INVALID_HANDLE;
	}

	conn = SC_get_conn(stmt);
	apdopts = SC_get_APDF(stmt);
	/*
	 * If the statement is premature, it means we already executed it from
	 * an SQLPrepare/SQLDescribeCol type of scenario.  So just return
	 * success.
	 */
	if (stmt->prepare && stmt->status == STMT_PREMATURE)
	{
		if (stmt->inaccurate_result)
		{
			stmt->exec_current_row = -1;
			SC_recycle_statement(stmt);
		}
		else
		{
			stmt->status = STMT_FINISHED;
			if (NULL == SC_get_errormsg(stmt))
			{
				mylog("%s: premature statement but return SQL_SUCCESS\n", func);
				retval = SQL_SUCCESS;
				goto cleanup;
			}
			else
			{
				SC_set_error(stmt,STMT_INTERNAL_ERROR, "premature statement so return SQL_ERROR", func);
				retval = SQL_ERROR;
				goto cleanup;
			}
		}
	}

	mylog("%s: clear errors...\n", func);

	SC_clear_error(stmt);
	if (!stmt->statement)
	{
		SC_set_error(stmt, STMT_NO_STMTSTRING, "This handle does not have a SQL statement stored in it", func);
		mylog("%s: problem with handle\n", func);
		return SQL_ERROR;
	}

#define	return	DONT_CALL_RETURN_FROM_HERE???

	if (stmt->exec_current_row > 0)
	{
		/*
		 * executing an array of parameters.
		 * Don't recycle the statement.
		 */
		recycle = FALSE;
	}
	else if (PREPARED_PERMANENTLY == stmt->prepared ||
		 PREPARED_TEMPORARILY == stmt->prepared)
	{
		QResultClass	*res;

		/*
		 * re-executing an prepared statement.
		 * Don't recycle the statement but
		 * discard the old result.
		 */
		recycle = FALSE;
		if (res = SC_get_Result(stmt), res)
        		QR_close_result(res, FALSE);
	}
	/*
	 * If SQLExecute is being called again, recycle the statement. Note
	 * this should have been done by the application in a call to
	 * SQLFreeStmt(SQL_CLOSE) or SQLCancel.
	 */
	else if (stmt->status == STMT_FINISHED)
	{
		mylog("%s: recycling statement (should have been done by app)...\n", func);
/******** Is this really NEEDED ? ******/
		SC_recycle_statement(stmt);
		recycled = TRUE;
	}
	/* Check if the statement is in the correct state */
	else if ((stmt->prepare && stmt->status != STMT_READY) ||
		(stmt->status != STMT_ALLOCATED && stmt->status != STMT_READY))
	{
		SC_set_error(stmt, STMT_STATUS_ERROR, "The handle does not point to a statement that is ready to be executed", func);
		mylog("%s: problem with statement\n", func);
		retval = SQL_ERROR;
		goto cleanup;
	}

	if (start_row = stmt->exec_start_row, start_row < 0)
		start_row = 0; 
	if (end_row = stmt->exec_end_row, end_row < 0)
		end_row = (SQLINTEGER) apdopts->paramset_size - 1; 
	if (stmt->exec_current_row < 0)
		stmt->exec_current_row = start_row;
	ipdopts = SC_get_IPDF(stmt);
	num_params = stmt->num_params;
	if (num_params < 0)
		PGAPI_NumParams(stmt, &num_params);
	if (stmt->exec_current_row == start_row)
	{
		/*
		   We sometimes need to know about the PG type of binding
		   parameters even in case of non-prepared statements.
		 */
		int	nCallParse = doNothing;

		if (NOT_YET_PREPARED == stmt->prepared)
		{
			switch (nCallParse = HowToPrepareBeforeExec(stmt, TRUE))
			{
				case shouldParse:
					if (retval = prepareParameters(stmt, TRUE), SQL_ERROR == retval)
						goto cleanup;
					break;
			}
		}
mylog("prepareParameters was %s called, prepare state:%d\n", shouldParse == nCallParse ? "" : "not", stmt->prepare);

		if (ipdopts->param_processed_ptr)
			*ipdopts->param_processed_ptr = 0;
#if (ODBCVER >= 0x0300)
		/*
	 	 *	Initialize the param_status_ptr 
	 	 */
		if (ipdopts->param_status_ptr)
		{
			for (i = 0; i <= end_row; i++)
				ipdopts->param_status_ptr[i] = SQL_PARAM_UNUSED;
		}
#endif /* ODBCVER */
		if (recycle && !recycled)
			SC_recycle_statement(stmt);
		if (isSqlServr() &&
		    !stmt->internal &&
		    0 != stmt->prepare &&
		    PG_VERSION_LT(conn, 8.4) &&
		    SC_can_parse_statement(stmt))
			parse_sqlsvr(stmt);
	}

	/*
	 * Clear any old result sets before executing. The prepare stage might've
	 * created one.
	 */
	SC_set_Result(stmt, NULL);

next_param_row:
#if (ODBCVER >= 0x0300)
	if (apdopts->param_operation_ptr)
	{
		while (apdopts->param_operation_ptr[stmt->exec_current_row] == SQL_PARAM_IGNORE)
		{
			if (stmt->exec_current_row >= end_row)
			{
				stmt->exec_current_row = -1;
				retval = SQL_SUCCESS;
				goto cleanup;
			}
			++stmt->exec_current_row;
		}
	}
	/*
	 *	Initialize the current row status 
	 */
	if (ipdopts->param_status_ptr)
		ipdopts->param_status_ptr[stmt->exec_current_row] = SQL_PARAM_ERROR;
#endif /* ODBCVER */
	/*
	 * 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.
		 */
		SQLULEN	offset = apdopts->param_offset_ptr ? *apdopts->param_offset_ptr : 0;
		SQLINTEGER	bind_size = apdopts->param_bind_type;
		SQLLEN		current_row = stmt->exec_current_row < 0 ? 0 : stmt->exec_current_row;
		Int4	num_p = num_params < apdopts->allocated ? num_params : apdopts->allocated;

		/*
		 *	Increment the  number of currently processed rows 
		 */
		if (ipdopts->param_processed_ptr)
			(*ipdopts->param_processed_ptr)++;
		stmt->data_at_exec = -1;
		for (i = 0; i < num_p; i++)
		{
			SQLLEN	   *pcVal = apdopts->parameters[i].used;

			apdopts->parameters[i].data_at_exec = FALSE;
			if (pcVal)
			{
				if (bind_size > 0)
					pcVal = LENADDR_SHIFT(pcVal, offset + bind_size * current_row);
				else
					pcVal = LENADDR_SHIFT(pcVal, offset) + current_row;
				if (*pcVal == SQL_DATA_AT_EXEC || *pcVal <= SQL_LEN_DATA_AT_EXEC_OFFSET)
					apdopts->parameters[i].data_at_exec = TRUE;
			}
			/* Check for data at execution parameters */
			if (apdopts->parameters[i].data_at_exec)
			{
				mylog("The %dth parameter of %d-row is data at exec(%d)\n", i, current_row, *pcVal);
				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)
		{
			retval = SQL_NEED_DATA;
			goto cleanup;
		}
	}

	if (0 != (flag & PODBC_WITH_HOLD))
		SC_set_with_hold(stmt);
	retval = Exec_with_parameters_resolved(stmt, &exec_end);
	if (!exec_end)
	{
		stmt->curr_param_result = 0;
		goto next_param_row;
	}
cleanup:
mylog("retval=%d\n", retval);
	SC_setInsertedTable(stmt, retval);
#undef	return
	if (stmt->internal)
		retval = DiscardStatementSvp(stmt, retval, FALSE);
	return retval;
}
示例#22
0
RETCODE		SQL_API
SQLSpecialColumns(HSTMT StatementHandle,
				  SQLUSMALLINT IdentifierType, SQLCHAR *CatalogName,
				  SQLSMALLINT NameLength1, SQLCHAR *SchemaName,
				  SQLSMALLINT NameLength2, SQLCHAR *TableName,
				  SQLSMALLINT NameLength3, SQLUSMALLINT Scope,
				  SQLUSMALLINT Nullable)
{
	CSTR func = "SQLSpecialColumns";
	RETCODE	ret;
	StatementClass *stmt = (StatementClass *) StatementHandle;
	SQLCHAR *ctName = CatalogName, *scName = SchemaName, *tbName = TableName;

	mylog("[%s]", func);
	ENTER_STMT_CS(stmt);
	SC_clear_error(stmt);
	StartRollbackState(stmt);
	if (SC_opencheck(stmt, func))
		ret = SQL_ERROR;
	else
		ret = PGAPI_SpecialColumns(StatementHandle, IdentifierType, ctName,
			NameLength1, scName, NameLength2, tbName, NameLength3,
							Scope, Nullable);
	if (SQL_SUCCESS == ret && 0 == QR_get_num_total_tuples(SC_get_Result(stmt))) 
	{
		BOOL	ifallupper = TRUE, reexec = FALSE;
		char *newCt =NULL, *newSc = NULL, *newTb = NULL;
		ConnectionClass *conn = SC_get_conn(stmt);

		if (SC_is_lower_case(stmt, conn)) /* case-insensitive identifier */
			ifallupper = FALSE;
		if (newCt = make_lstring_ifneeded(conn, CatalogName, NameLength1, ifallupper), NULL != newCt)
		{
			ctName = newCt;
			reexec = TRUE;
		}
		if (newSc = make_lstring_ifneeded(conn, SchemaName, NameLength2, ifallupper), NULL != newSc)
		{
			scName = newSc;
			reexec = TRUE;
		}
		if (newTb = make_lstring_ifneeded(conn, TableName, NameLength3, ifallupper), NULL != newTb)
		{
			tbName = newTb;
			reexec = TRUE;
		}
		if (reexec)
		{
			ret = PGAPI_SpecialColumns(StatementHandle, IdentifierType, ctName,
			NameLength1, scName, NameLength2, tbName, NameLength3,
							Scope, Nullable);
			if (newCt)
				free(newCt);
			if (newSc)
				free(newSc);
			if (newTb)
				free(newTb);
		}
	}
	ret = DiscardStatementSvp(stmt, ret, FALSE);
	LEAVE_STMT_CS(stmt);
	return ret;
}
示例#23
0
/*	Associate a user-supplied buffer with a database column. */
RETCODE		SQL_API
PGAPI_BindCol(HSTMT hstmt,
			  SQLUSMALLINT icol,
			  SQLSMALLINT fCType,
			  PTR rgbValue,
			  SQLLEN cbValueMax,
			  SQLLEN FAR * pcbValue)
{
	StatementClass *stmt = (StatementClass *) hstmt;
	CSTR func = "PGAPI_BindCol";
	ARDFields	*opts;
	GetDataInfo	*gdata_info;
	BindInfoClass	*bookmark;
	RETCODE		ret = SQL_SUCCESS;

	mylog("%s: entering...\n", func);

	mylog("**** PGAPI_BindCol: stmt = %p, icol = %d\n", stmt, icol);
	mylog("**** : fCType=%d rgb=%p valusMax=%d pcb=%p\n", fCType, rgbValue, cbValueMax, pcbValue);

	if (!stmt)
	{
		SC_log_error(func, "", NULL);
		return SQL_INVALID_HANDLE;
	}

	opts = SC_get_ARDF(stmt);
	if (stmt->status == STMT_EXECUTING)
	{
		SC_set_error(stmt, STMT_SEQUENCE_ERROR, "Can't bind columns while statement is still executing.", func);
		return SQL_ERROR;
	}

#define	return	DONT_CALL_RETURN_FROM_HERE ???
	SC_clear_error(stmt);
	/* If the bookmark column is being bound, then just save it */
	if (icol == 0)
	{
		bookmark = opts->bookmark;
		if (rgbValue == NULL)
		{
			if (bookmark)
			{
				bookmark->buffer = NULL;
				bookmark->used =
				bookmark->indicator = NULL;
			}
		}
		else
		{
			/* Make sure it is the bookmark data type */
			switch (fCType)
			{
				case SQL_C_BOOKMARK:
#if (ODBCVER >= 0x0300)
				case SQL_C_VARBOOKMARK:
#endif /* ODBCVER */
					break;
				default:
					SC_set_error(stmt, STMT_PROGRAM_TYPE_OUT_OF_RANGE, "Bind column 0 is not of type SQL_C_BOOKMARK", func);
inolog("Bind column 0 is type %d not of type SQL_C_BOOKMARK", fCType);
					ret = SQL_ERROR;
					goto cleanup;
			}

			bookmark = ARD_AllocBookmark(opts);
			bookmark->buffer = rgbValue;
			bookmark->used =
			bookmark->indicator = pcbValue;
			bookmark->buflen = cbValueMax;
			bookmark->returntype = fCType;
		}
		goto cleanup;
	}

	/*
	 * Allocate enough bindings if not already done. Most likely,
	 * execution of a statement would have setup the necessary bindings.
	 * But some apps call BindCol before any statement is executed.
	 */
	if (icol > opts->allocated)
		extend_column_bindings(opts, icol);
	gdata_info = SC_get_GDTI(stmt);
	if (icol > gdata_info->allocated)
		extend_getdata_info(gdata_info, icol, FALSE);

	/* check to see if the bindings were allocated */
	if (!opts->bindings)
	{
		SC_set_error(stmt, STMT_NO_MEMORY_ERROR, "Could not allocate memory for bindings.", func);
		ret = SQL_ERROR;
		goto cleanup;
	}

	/* use zero based col numbers from here out */
	icol--;

	/* Reset for SQLGetData */
	gdata_info->gdata[icol].data_left = -1;

	if (rgbValue == NULL)
	{
		/* we have to unbind the column */
		opts->bindings[icol].buflen = 0;
		opts->bindings[icol].buffer = NULL;
		opts->bindings[icol].used =
		opts->bindings[icol].indicator = NULL;
		opts->bindings[icol].returntype = SQL_C_CHAR;
		opts->bindings[icol].precision = 0;
		opts->bindings[icol].scale = 0;
		if (gdata_info->gdata[icol].ttlbuf)
			free(gdata_info->gdata[icol].ttlbuf);
		gdata_info->gdata[icol].ttlbuf = NULL;
		gdata_info->gdata[icol].ttlbuflen = 0;
		gdata_info->gdata[icol].ttlbufused = 0;
	}
	else
	{
		/* ok, bind that column */
		opts->bindings[icol].buflen = cbValueMax;
		opts->bindings[icol].buffer = rgbValue;
		opts->bindings[icol].used =
		opts->bindings[icol].indicator = pcbValue;
		opts->bindings[icol].returntype = fCType;
		opts->bindings[icol].precision = 0;
#if (ODBCVER >= 0x0300)
		switch (fCType)
		{
			case SQL_C_NUMERIC:
				opts->bindings[icol].precision = 32;
				break;
			case SQL_C_TIMESTAMP:
			case SQL_C_INTERVAL_DAY_TO_SECOND:
			case SQL_C_INTERVAL_HOUR_TO_SECOND:
			case SQL_C_INTERVAL_MINUTE_TO_SECOND:
			case SQL_C_INTERVAL_SECOND:
				opts->bindings[icol].precision = 6;
				break;
		}
#endif /* ODBCVER */
		opts->bindings[icol].scale = 0;

		mylog("       bound buffer[%d] = %p\n", icol, opts->bindings[icol].buffer);
	}

cleanup:
#undef	return
	if (stmt->internal)
		ret = DiscardStatementSvp(stmt, ret, FALSE);
	return ret;
}
示例#24
0
文件: execute.c 项目: vadz/psqlodbc
RETCODE		SQL_API
PGAPI_Cancel(
			 HSTMT hstmt)		/* Statement to cancel. */
{
	CSTR func = "PGAPI_Cancel";
	StatementClass *stmt = (StatementClass *) hstmt, *estmt;
	ConnectionClass *conn;
	RETCODE		ret = SQL_SUCCESS;
	BOOL	entered_cs = FALSE;

	mylog("%s: entering...\n", func);

	/* Check if this can handle canceling in the middle of a SQLPutData? */
	if (!stmt)
	{
		SC_log_error(func, "", NULL);
		return SQL_INVALID_HANDLE;
	}
	conn = SC_get_conn(stmt);

#define	return	DONT_CALL_RETURN_FROM_HERE???
	/* StartRollbackState(stmt); */

	if (stmt->execute_delegate)
		estmt = stmt->execute_delegate;
	else
		estmt = stmt;
	/*
	 * Not in the middle of SQLParamData/SQLPutData so cancel like a
	 * close.
	 */
	if (estmt->data_at_exec < 0)
	{
		/*
		 * Tell the Backend that we're cancelling this request
		 */
		if (estmt->status == STMT_EXECUTING)
		{
			if (!CC_send_cancel_request(conn))
			{
				ret = SQL_ERROR;
			}
			goto cleanup;
		}
		/*
		 * MAJOR HACK for Windows to reset the driver manager's cursor
		 * state: Because of what seems like a bug in the Odbc driver
		 * manager, SQLCancel does not act like a SQLFreeStmt(CLOSE), as
		 * many applications depend on this behavior.  So, this brute
		 * force method calls the driver manager's function on behalf of
		 * the application.
		 */

		if (conn->driver_version < 0x0350)
		{
#ifdef WIN32
		ConnInfo   *ci = &(conn->connInfo);

		if (ci->drivers.cancel_as_freestmt)
		{
	typedef SQLRETURN (SQL_API *SQLAPIPROC)();
			HMODULE		hmodule;
			SQLAPIPROC	addr;

			hmodule = GetModuleHandle("ODBC32");
			addr = (SQLAPIPROC) GetProcAddress(hmodule, "SQLFreeStmt");
			ret = addr((char *) (stmt->phstmt) - 96, SQL_CLOSE);
		}
		else
#endif /* WIN32 */
		{
			ENTER_STMT_CS(stmt);
			entered_cs = TRUE;
			SC_clear_error(hstmt);
			ret = PGAPI_FreeStmt(hstmt, SQL_CLOSE);
		}

		mylog("PGAPI_Cancel:  PGAPI_FreeStmt returned %d\n", ret);
		}
		goto cleanup;
	}

	/* In the middle of SQLParamData/SQLPutData, so cancel that. */
	/*
	 * Note, any previous data-at-exec buffers will be freed in the
	 * recycle
	 */
	/* if they call SQLExecDirect or SQLExecute again. */

	ENTER_STMT_CS(stmt);
	entered_cs = TRUE;
	SC_clear_error(stmt);
	estmt->data_at_exec = -1;
	estmt->current_exec_param = -1;
	estmt->put_data = FALSE;
	cancelNeedDataState(estmt);

cleanup:
#undef	return
	if (entered_cs)
	{
		if (stmt->internal)
			ret = DiscardStatementSvp(stmt, ret, FALSE);
		LEAVE_STMT_CS(stmt);
	}
	return ret;
}
示例#25
0
SQLRETURN SQL_API SQLColAttributeW(
	SQLHSTMT	hstmt,
	SQLUSMALLINT	iCol,
	SQLUSMALLINT	iField,
	SQLPOINTER	pCharAttr,
	SQLSMALLINT	cbCharAttrMax,	
	SQLSMALLINT	*pcbCharAttr,
#if defined(WITH_UNIXODBC) || (defined(WIN32) && ! defined(_WIN64))
	SQLPOINTER	pNumAttr
#else
	SQLLEN		*pNumAttr
#endif
	)
{
	CSTR func = "SQLColAttributeW";
	RETCODE	ret;
	StatementClass	*stmt = (StatementClass *) hstmt;
	SQLSMALLINT	*rgbL, blen = 0, bMax;
        char    *rgbD = NULL;

	mylog("[%s]", func);
	ENTER_STMT_CS(stmt);
	SC_clear_error(stmt);
	StartRollbackState(stmt);
	switch (iField)
	{ 
		case SQL_DESC_BASE_COLUMN_NAME:
		case SQL_DESC_BASE_TABLE_NAME:
		case SQL_DESC_CATALOG_NAME:
		case SQL_DESC_LABEL:
		case SQL_DESC_LITERAL_PREFIX:
		case SQL_DESC_LITERAL_SUFFIX:
		case SQL_DESC_LOCAL_TYPE_NAME:
		case SQL_DESC_NAME:
		case SQL_DESC_SCHEMA_NAME:
		case SQL_DESC_TABLE_NAME:
		case SQL_DESC_TYPE_NAME:
		case SQL_COLUMN_NAME:
			bMax = cbCharAttrMax * 3 / WCLEN;
			rgbD = malloc(bMax);
			rgbL = &blen;
			for (;; bMax = blen + 1, rgbD = realloc(rgbD, bMax))
			{
				ret = PGAPI_ColAttributes(hstmt, iCol, iField, rgbD,
					bMax, rgbL, pNumAttr);
				if (SQL_SUCCESS_WITH_INFO != ret || blen < bMax)
					break;
			}
			if (SQL_SUCCEEDED(ret))
			{
				blen = (SQLSMALLINT) utf8_to_ucs2(rgbD, blen, (SQLWCHAR *) pCharAttr, cbCharAttrMax / WCLEN);
				if (SQL_SUCCESS == ret && blen * WCLEN >= cbCharAttrMax)
				{
					ret = SQL_SUCCESS_WITH_INFO;
					SC_set_error(stmt, STMT_TRUNCATED, "The buffer was too small for the pCharAttr.", func);
				}
				if (pcbCharAttr)
					*pcbCharAttr = blen * WCLEN;
			}
			if (rgbD)
				free(rgbD);
			break;
		default:
			rgbD = pCharAttr;
			bMax = cbCharAttrMax;
			rgbL = pcbCharAttr;
			ret = PGAPI_ColAttributes(hstmt, iCol, iField, rgbD,
					bMax, rgbL, pNumAttr);
			break;
	}
	ret = DiscardStatementSvp(stmt, ret, FALSE);
	LEAVE_STMT_CS(stmt);

	return ret;
}
示例#26
0
RETCODE SQL_API
SQLForeignKeysW(HSTMT			hstmt,
				SQLWCHAR	   *szPkCatalogName,
				SQLSMALLINT		cbPkCatalogName,
				SQLWCHAR	   *szPkSchemaName,
				SQLSMALLINT		cbPkSchemaName,
				SQLWCHAR	   *szPkTableName,
				SQLSMALLINT		cbPkTableName,
				SQLWCHAR	   *szFkCatalogName,
				SQLSMALLINT		cbFkCatalogName,
				SQLWCHAR	   *szFkSchemaName,
				SQLSMALLINT		cbFkSchemaName,
				SQLWCHAR	   *szFkTableName,
				SQLSMALLINT		cbFkTableName)
{
	CSTR func = "SQLForeignKeysW";
	RETCODE	ret;
	char	*ctName, *scName, *tbName, *fkctName, *fkscName, *fktbName;
	SQLLEN	nmlen1, nmlen2, nmlen3, nmlen4, nmlen5, nmlen6;
	StatementClass *stmt = (StatementClass *) hstmt;
	ConnectionClass *conn;
	BOOL	lower_id;

	mylog("[%s]", func);
	conn = SC_get_conn(stmt);
	lower_id = SC_is_lower_case(stmt, conn);
	ctName = ucs2_to_utf8(szPkCatalogName, cbPkCatalogName, &nmlen1, lower_id);
	scName = ucs2_to_utf8(szPkSchemaName, cbPkSchemaName, &nmlen2, lower_id);
	tbName = ucs2_to_utf8(szPkTableName, cbPkTableName, &nmlen3, lower_id);
	fkctName = ucs2_to_utf8(szFkCatalogName, cbFkCatalogName, &nmlen4, lower_id);
	fkscName = ucs2_to_utf8(szFkSchemaName, cbFkSchemaName, &nmlen5, lower_id);
	fktbName = ucs2_to_utf8(szFkTableName, cbFkTableName, &nmlen6, lower_id);
	ENTER_STMT_CS(stmt);
	SC_clear_error(stmt);
	StartRollbackState(stmt);
	if (SC_opencheck(stmt, func))
		ret = SQL_ERROR;
	else
		ret = PGAPI_ForeignKeys(hstmt,
								(SQLCHAR *) ctName, (SQLSMALLINT) nmlen1,
								(SQLCHAR *) scName, (SQLSMALLINT) nmlen2,
								(SQLCHAR *) tbName, (SQLSMALLINT) nmlen3,
								(SQLCHAR *) fkctName, (SQLSMALLINT) nmlen4,
								(SQLCHAR *) fkscName, (SQLSMALLINT) nmlen5,
								(SQLCHAR *) fktbName, (SQLSMALLINT) nmlen6);
	ret = DiscardStatementSvp(stmt, ret, FALSE);
	LEAVE_STMT_CS(stmt);
	if (ctName)
		free(ctName);
	if (scName)
		free(scName);
	if (tbName)
		free(tbName);
	if (fkctName)
		free(fkctName);
	if (fkscName)
		free(fkscName);
	if (fktbName)
		free(fktbName);
	return ret;
}
示例#27
0
			SQLPOINTER NumericAttribute
#endif
			)
{
	CSTR	func = "SQLColAttribute";
	RETCODE	ret;
	StatementClass	*stmt = (StatementClass *) StatementHandle;

	mylog("[[%s]]", func);
	ENTER_STMT_CS(stmt);
	SC_clear_error(stmt);
	StartRollbackState(stmt);
	ret = PGAPI_ColAttributes(StatementHandle, ColumnNumber,
					   FieldIdentifier, CharacterAttribute, BufferLength,
							   StringLength, NumericAttribute);
	ret = DiscardStatementSvp(stmt,ret, FALSE);
	LEAVE_STMT_CS(stmt);
	return ret;
}

/*	new function */
RETCODE		SQL_API
SQLCopyDesc(SQLHDESC SourceDescHandle,
			SQLHDESC TargetDescHandle)
{
	CSTR	func = "SQLCopyDesc";
	RETCODE	ret;

	mylog("[[%s]]\n", func);
	ret = PGAPI_CopyDesc(SourceDescHandle, TargetDescHandle);
	return ret;
示例#28
0
RETCODE		SQL_API
SQLColumnPrivileges(HSTMT hstmt,
					SQLCHAR *szCatalogName,
					SQLSMALLINT cbCatalogName,
					SQLCHAR *szSchemaName,
					SQLSMALLINT cbSchemaName,
					SQLCHAR *szTableName,
					SQLSMALLINT cbTableName,
					SQLCHAR *szColumnName,
					SQLSMALLINT cbColumnName)
{
	CSTR func = "SQLColumnPrivileges";
	RETCODE	ret;
	StatementClass *stmt = (StatementClass *) hstmt;
	SQLCHAR	*ctName = szCatalogName, *scName = szSchemaName,
		*tbName = szTableName, *clName = szColumnName;
	UWORD	flag = 0;

	mylog("[%s]", func);
	ENTER_STMT_CS(stmt);
	SC_clear_error(stmt);
	StartRollbackState(stmt);
#if (ODBCVER >= 0x0300)
	if (stmt->options.metadata_id)
		flag |= PODBC_NOT_SEARCH_PATTERN;
#endif
	if (SC_opencheck(stmt, func))
		ret = SQL_ERROR;
	else
		ret = PGAPI_ColumnPrivileges(hstmt, ctName, cbCatalogName,
				scName, cbSchemaName, tbName, cbTableName,
						clName, cbColumnName, flag);
	if (SQL_SUCCESS == ret && theResultIsEmpty(stmt))
	{
		BOOL	ifallupper = TRUE, reexec = FALSE;
		SQLCHAR *newCt = NULL, *newSc = NULL, *newTb = NULL, *newCl = NULL;
		ConnectionClass *conn = SC_get_conn(stmt);

		if (SC_is_lower_case(stmt, conn)) /* case-insensitive identifier */
			ifallupper = FALSE;
		if (newCt = make_lstring_ifneeded(conn, szCatalogName, cbCatalogName, ifallupper), NULL != newCt)
		{
			ctName = newCt;
			reexec = TRUE;
		}
		if (newSc = make_lstring_ifneeded(conn, szSchemaName, cbSchemaName, ifallupper), NULL != newSc)
		{
			scName = newSc;
			reexec = TRUE;
		}
		if (newTb = make_lstring_ifneeded(conn, szTableName, cbTableName, ifallupper), NULL != newTb)
		{
			tbName = newTb;
			reexec = TRUE;
		}
		if (newCl = make_lstring_ifneeded(conn, szColumnName, cbColumnName, ifallupper), NULL != newCl)
		{
			clName = newCl;
			reexec = TRUE;
		}
		if (reexec)
		{
			ret = PGAPI_ColumnPrivileges(hstmt, ctName, cbCatalogName,
				scName, cbSchemaName, tbName, cbTableName,
						clName, cbColumnName, flag);
			if (newCt)
				free(newCt);
			if (newSc)
				free(newSc);
			if (newTb)
				free(newTb);
			if (newCl)
				free(newCl);
		}
	}
	ret = DiscardStatementSvp(stmt, ret, FALSE);
	LEAVE_STMT_CS(stmt);
	return ret;
}
示例#29
0
RETCODE		SQL_API
SQLTables(HSTMT StatementHandle,
		  SQLCHAR *CatalogName, SQLSMALLINT NameLength1,
		  SQLCHAR *SchemaName, SQLSMALLINT NameLength2,
		  SQLCHAR *TableName, SQLSMALLINT NameLength3,
		  SQLCHAR *TableType, SQLSMALLINT NameLength4)
{
	CSTR func = "SQLTables";
	RETCODE	ret;
	StatementClass *stmt = (StatementClass *) StatementHandle;
	SQLCHAR *ctName = CatalogName, *scName = SchemaName, *tbName = TableName;
	UWORD	flag = 0;

	mylog("[%s]", func);
	ENTER_STMT_CS(stmt);
	SC_clear_error(stmt);
	StartRollbackState(stmt);
#if (ODBCVER >= 0x0300)
	if (stmt->options.metadata_id)
		flag |= PODBC_NOT_SEARCH_PATTERN;
#endif
	if (SC_opencheck(stmt, func))
		ret = SQL_ERROR;
	else
		ret = PGAPI_Tables(StatementHandle, ctName, NameLength1,
				scName, NameLength2, tbName, NameLength3,
					TableType, NameLength4, flag);
	if (SQL_SUCCESS == ret && 0 == QR_get_num_total_tuples(SC_get_Result(stmt))) 
	{
		BOOL	ifallupper = TRUE, reexec = FALSE;
		char *newCt =NULL, *newSc = NULL, *newTb = NULL;
		ConnectionClass *conn = SC_get_conn(stmt);

		if (SC_is_lower_case(stmt, conn)) /* case-insensitive identifier */
			ifallupper = FALSE;
		if (newCt = make_lstring_ifneeded(conn, CatalogName, NameLength1, ifallupper), NULL != newCt)
		{
			ctName = newCt;
			reexec = TRUE;
		}
		if (newSc = make_lstring_ifneeded(conn, SchemaName, NameLength2, ifallupper), NULL != newSc)
		{
			scName = newSc;
			reexec = TRUE;
		}
		if (newTb = make_lstring_ifneeded(conn, TableName, NameLength3, ifallupper), NULL != newTb)
		{
			tbName = newTb;
			reexec = TRUE;
		}
		if (reexec)
		{
			ret = PGAPI_Tables(StatementHandle, ctName, NameLength1,
				scName, NameLength2, tbName, NameLength3,
						TableType, NameLength4, flag);
			if (newCt)
				free(newCt);
			if (newSc)
				free(newSc);
			if (newTb)
				free(newTb);
		}
	}
	ret = DiscardStatementSvp(stmt, ret, FALSE);
	LEAVE_STMT_CS(stmt);
	return ret;
}
示例#30
0
文件: execute.c 项目: vadz/psqlodbc
/*
 *	Supplies parameter data at execution time.
 *	Used in conjunction with SQLParamData.
 */
RETCODE		SQL_API
PGAPI_PutData(
			  HSTMT hstmt,
			  PTR rgbValue,
			  SQLLEN cbValue)
{
	CSTR func = "PGAPI_PutData";
	StatementClass *stmt = (StatementClass *) hstmt, *estmt;
	ConnectionClass *conn;
	RETCODE		retval = SQL_SUCCESS;
	APDFields	*apdopts;
	IPDFields	*ipdopts;
	PutDataInfo	*pdata;
	SQLLEN		old_pos;
	ParameterInfoClass *current_param;
	ParameterImplClass *current_iparam;
	PutDataClass	*current_pdata;
	char	   *buffer, *putbuf, *allocbuf = NULL;
	Int2		ctype;
	SQLLEN		putlen;
	BOOL		lenset = FALSE, handling_lo = FALSE;

	mylog("%s: entering...\n", func);

#define	return	DONT_CALL_RETURN_FROM_HERE???
	if (!stmt)
	{
		SC_log_error(func, "", NULL);
		retval = SQL_INVALID_HANDLE;
		goto cleanup;
	}
	if (SC_AcceptedCancelRequest(stmt))
	{
		SC_set_error(stmt, STMT_OPERATION_CANCELLED, "Cancel the statement, sorry.", func);
		retval = SQL_ERROR;
		goto cleanup;
	}

	estmt = stmt->execute_delegate ? stmt->execute_delegate : stmt;
	apdopts = SC_get_APDF(estmt);
	if (estmt->current_exec_param < 0)
	{
		SC_set_error(stmt, STMT_SEQUENCE_ERROR, "Previous call was not SQLPutData or SQLParamData", func);
		retval = SQL_ERROR;
		goto cleanup;
	}

	current_param = &(apdopts->parameters[estmt->current_exec_param]);
	ipdopts = SC_get_IPDF(estmt);
	current_iparam = &(ipdopts->parameters[estmt->current_exec_param]);
	pdata = SC_get_PDTI(estmt);
	current_pdata = &(pdata->pdata[estmt->current_exec_param]);
	ctype = current_param->CType;

	conn = SC_get_conn(estmt);
	if (ctype == SQL_C_DEFAULT)
	{
		ctype = sqltype_to_default_ctype(conn, current_iparam->SQLType);
		if (SQL_C_WCHAR == ctype &&
		    CC_default_is_c(conn))
			ctype = SQL_C_CHAR;
	}
	if (SQL_NTS == cbValue)
	{
#ifdef	UNICODE_SUPPORT
		if (SQL_C_WCHAR == ctype)
		{
			putlen = WCLEN * ucs2strlen((SQLWCHAR *) rgbValue);
			lenset = TRUE;
		}
		else
#endif /* UNICODE_SUPPORT */
		if (SQL_C_CHAR == ctype)
		{
			putlen = strlen(rgbValue);
			lenset = TRUE;
		}
	}
	if (!lenset)
	{
		if (cbValue < 0)
			putlen = cbValue;
		else
#ifdef	UNICODE_SUPPORT
		if (ctype == SQL_C_CHAR || ctype == SQL_C_BINARY || ctype == SQL_C_WCHAR)
#else
		if (ctype == SQL_C_CHAR || ctype == SQL_C_BINARY)
#endif /* UNICODE_SUPPORT */
			putlen = cbValue;
		else
			putlen = ctype_length(ctype);
	}
	putbuf = rgbValue;
	handling_lo = (PIC_dsp_pgtype(conn, *current_iparam) == conn->lobj_type);
	if (handling_lo && SQL_C_CHAR == ctype)
	{
		allocbuf = malloc(putlen / 2 + 1);
		if (allocbuf)
		{
			pg_hex2bin(rgbValue, allocbuf, putlen);
			putbuf = allocbuf;
			putlen /= 2;
		}
	}

	if (!estmt->put_data)
	{							/* first call */
		mylog("PGAPI_PutData: (1) cbValue = %d\n", cbValue);

		estmt->put_data = TRUE;

		current_pdata->EXEC_used = (SQLLEN *) malloc(sizeof(SQLLEN));
		if (!current_pdata->EXEC_used)
		{
			SC_set_error(stmt, STMT_NO_MEMORY_ERROR, "Out of memory in PGAPI_PutData (1)", func);
			retval = SQL_ERROR;
			goto cleanup;
		}

		*current_pdata->EXEC_used = putlen;

		if (cbValue == SQL_NULL_DATA)
		{
			retval = SQL_SUCCESS;
			goto cleanup;
		}

		/* Handle Long Var Binary with Large Objects */
		/* if (current_iparam->SQLType == SQL_LONGVARBINARY) */
		if (handling_lo)
		{
			/* begin transaction if needed */
			if (!CC_is_in_trans(conn))
			{
				if (!CC_begin(conn))
				{
					SC_set_error(stmt, STMT_EXEC_ERROR, "Could not begin (in-line) a transaction", func);
					retval = SQL_ERROR;
					goto cleanup;
				}
			}

			/* store the oid */
			current_pdata->lobj_oid = odbc_lo_creat(conn, INV_READ | INV_WRITE);
			if (current_pdata->lobj_oid == 0)
			{
				SC_set_error(stmt, STMT_EXEC_ERROR, "Couldnt create large object.", func);
				retval = SQL_ERROR;
				goto cleanup;
			}

			/*
			 * major hack -- to allow convert to see somethings there have
			 * to modify convert to handle this better
			 */
			/***current_param->EXEC_buffer = (char *) &current_param->lobj_oid;***/

			/* store the fd */
			estmt->lobj_fd = odbc_lo_open(conn, current_pdata->lobj_oid, INV_WRITE);
			if (estmt->lobj_fd < 0)
			{
				SC_set_error(stmt, STMT_EXEC_ERROR, "Couldnt open large object for writing.", func);
				retval = SQL_ERROR;
				goto cleanup;
			}

			retval = odbc_lo_write(conn, estmt->lobj_fd, putbuf, (Int4) putlen);
			mylog("lo_write: cbValue=%d, wrote %d bytes\n", putlen, retval);
		}
		else
		{
			current_pdata->EXEC_buffer = malloc(putlen + 1);
			if (!current_pdata->EXEC_buffer)
			{
				SC_set_error(stmt, STMT_NO_MEMORY_ERROR, "Out of memory in PGAPI_PutData (2)", func);
				retval = SQL_ERROR;
				goto cleanup;
			}
			memcpy(current_pdata->EXEC_buffer, putbuf, putlen);
			current_pdata->EXEC_buffer[putlen] = '\0';
		}
	}
	else
	{
		/* calling SQLPutData more than once */
		mylog("PGAPI_PutData: (>1) cbValue = %d\n", cbValue);

		/* if (current_iparam->SQLType == SQL_LONGVARBINARY) */
		if (handling_lo)
		{
			/* the large object fd is in EXEC_buffer */
			retval = odbc_lo_write(conn, estmt->lobj_fd, putbuf, (Int4) putlen);
			mylog("lo_write(2): cbValue = %d, wrote %d bytes\n", putlen, retval);

			*current_pdata->EXEC_used += putlen;
		}
		else
		{
			buffer = current_pdata->EXEC_buffer;
			old_pos = *current_pdata->EXEC_used;
			if (putlen > 0)
			{
				SQLLEN	used = *current_pdata->EXEC_used + putlen, allocsize;
				for (allocsize = (1 << 4); allocsize <= used; allocsize <<= 1) ;
				mylog("        cbValue = %d, old_pos = %d, *used = %d\n", putlen, old_pos, used);

				/* dont lose the old pointer in case out of memory */
				buffer = realloc(current_pdata->EXEC_buffer, allocsize);
				if (!buffer)
				{
					SC_set_error(stmt, STMT_NO_MEMORY_ERROR,"Out of memory in PGAPI_PutData (3)", func);
					retval = SQL_ERROR;
					goto cleanup;
				}

				memcpy(&buffer[old_pos], putbuf, putlen);
				buffer[used] = '\0';

				/* reassign buffer incase realloc moved it */
				*current_pdata->EXEC_used = used;
				current_pdata->EXEC_buffer = buffer;
			}
			else
			{
				SC_set_error(stmt, STMT_INTERNAL_ERROR, "bad cbValue", func);
				retval = SQL_ERROR;
				goto cleanup;
			}
		}
	}

	retval = SQL_SUCCESS;
cleanup:
#undef	return
	if (allocbuf)
		free(allocbuf);
	if (stmt->internal)
		retval = DiscardStatementSvp(stmt, retval, TRUE);

	return retval;
}