Пример #1
0
static
int HowToPrepareBeforeExec(StatementClass *stmt, BOOL checkOnly)
{
	SQLSMALLINT	num_params = stmt->num_params;
	ConnectionClass	*conn = SC_get_conn(stmt);
	ConnInfo *ci = &(conn->connInfo);
	int		nCallParse = doNothing, how_to_prepare = 0;
	BOOL		bNeedsTrans = FALSE;

	if (num_params < 0)
		PGAPI_NumParams(stmt, &num_params);
	how_to_prepare = decideHowToPrepare(stmt, checkOnly);
	if (checkOnly)
	{
		if (num_params <= 0)
			return doNothing;
	}
	else
	{
		switch (how_to_prepare)
		{
			case USING_PREPARE_COMMAND:
				return checkOnly ? doNothing : usingCommand;
			case NAMED_PARSE_REQUEST:
				return shouldParse;
			case PARSE_TO_EXEC_ONCE:
				switch (stmt->prepared)
				{
					case PREPARED_TEMPORARILY:
						nCallParse = preferParse;
						break;
					default:
						if (num_params <= 0)
							nCallParse = NOPARAM_ONESHOT_CALL_PARSE;
						else
							nCallParse = ONESHOT_CALL_PARSE;
				}
				break;
			default:
				return doNothing;
		}
	}
	if (PG_VERSION_LE(conn, 7.3) ||
	    !PROTOCOL_74(ci))
		return nCallParse;

	if (num_params > 0)
	{
		int	param_number = -1;
		ParameterInfoClass *apara;
		ParameterImplClass *ipara;
		OID	pgtype;

		while (TRUE)
		{
			SC_param_next(stmt, &param_number, &apara, &ipara);
			if (!ipara || !apara)
				break;
			pgtype = PIC_get_pgtype(*ipara);
			if (checkOnly)
			{
				switch (ipara->SQLType)
				{
					case SQL_LONGVARBINARY:
						if (0 == pgtype)
						{
							if (ci->bytea_as_longvarbinary &&
							    0 != conn->lobj_type)
								nCallParse = shouldParse;
						}
						break;
					case SQL_CHAR:
						if (ci->cvt_null_date_string)
							nCallParse = shouldParse;
						break;
					case SQL_VARCHAR:
						if (ci->drivers.bools_as_char &&
						    PG_WIDTH_OF_BOOLS_AS_CHAR == ipara->column_size)
							nCallParse = shouldParse;
						break;
				}
			}
			else
			{
				BOOL	bBytea = FALSE;

				switch (ipara->SQLType)
				{
					case SQL_LONGVARBINARY:
						if (conn->lobj_type == pgtype ||
					    	    PG_TYPE_OID == pgtype)
							bNeedsTrans = TRUE;
						else if (PG_TYPE_BYTEA == pgtype)
							bBytea = TRUE;
						else if (0 == pgtype)
						{
							if (ci->bytea_as_longvarbinary)
								bBytea = TRUE;
							else
								bNeedsTrans = TRUE;
						}
						if (bBytea)
							if (nCallParse < preferParse)
								nCallParse = preferParse;
						break;
				}
			}
		}
	}
	if (bNeedsTrans &&
	    PARSE_TO_EXEC_ONCE == how_to_prepare)
	{
		if (!CC_is_in_trans(conn) && CC_does_autocommit(conn))
			nCallParse = doNothing;
	}
	return nCallParse;
}
Пример #2
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;
}