Beispiel #1
0
static void ARDFields_free(ARDFields * self)
{
inolog("ARDFields_free %p bookmark=%p", self, self->bookmark);
	if (self->bookmark)
	{
		free(self->bookmark);
		self->bookmark = NULL;
	}
inolog(" hey");
	/*
	 * the memory pointed to by the bindings is not deallocated by the
	 * driver but by the application that uses that driver, so we don't
	 * have to care
	 */
	ARD_unbind_cols(self, TRUE);
}
Beispiel #2
0
void	TI_Destructor(TABLE_INFO **ti, int count)
{
	int	i;

inolog("TI_Destructor count=%d\n", count);
	if (ti)
	{
		for (i = 0; i < count; i++)
		{
			if (ti[i])
			{
				COL_INFO *coli = ti[i]->col_info;
				if (coli)
				{
mylog("!!!refcnt %p:%d -> %d\n", coli, coli->refcnt, coli->refcnt - 1);
					coli->refcnt--;
					if (coli->refcnt <= 0 && 0 == coli->acc_time) /* acc_time == 0 means the table is dropped */
						free_col_info_contents(coli);
				}
				NULL_THE_NAME(ti[i]->schema_name);
				NULL_THE_NAME(ti[i]->table_name);
				NULL_THE_NAME(ti[i]->table_alias);
				NULL_THE_NAME(ti[i]->bestitem);
				NULL_THE_NAME(ti[i]->bestqual);
				free(ti[i]);
				ti[i] = NULL;
			}
		}
	}
}
Beispiel #3
0
void	TI_Destructor(TABLE_INFO **ti, int count)
{
	int	i;

inolog("TI_Destructor count=%d\n", count);
	if (ti)
	{
		for (i = 0; i < count; i++)
		{
			if (ti[i])
			{
				COL_INFO *coli = ti[i]->col_info;
				if (coli)
				{
mylog("!!!refcnt %p:%d -> %d\n", coli, coli->refcnt, coli->refcnt - 1);
					coli->refcnt--;
				}
				NULL_THE_NAME(ti[i]->schema_name);
				NULL_THE_NAME(ti[i]->table_name);
				NULL_THE_NAME(ti[i]->table_alias);
				NULL_THE_NAME(ti[i]->bestitem);
				NULL_THE_NAME(ti[i]->bestqual);
				free(ti[i]);
				ti[i] = NULL;
			}
		}
	}
}
Beispiel #4
0
void	FI_Destructor(FIELD_INFO **fi, int count, BOOL freeFI)
{
	int	i;

inolog("FI_Destructor count=%d\n", count);
	if (fi)
	{
		for (i = 0; i < count; i++)
		{
			if (fi[i])
			{
				NULL_THE_NAME(fi[i]->column_name);
				NULL_THE_NAME(fi[i]->column_alias);
				NULL_THE_NAME(fi[i]->schema_name);
				NULL_THE_NAME(fi[i]->before_dot);
				if (freeFI)
				{
					free(fi[i]);
					fi[i] = NULL;
				}
			}
		}
		if (freeFI)
			free(fi);
	}
}
Beispiel #5
0
/*
 *	This function should really talk to the dbms to determine the number of
 *	"parameter markers" (not bound parameters) in the statement.  But, since
 *	Postgres doesn't support that, the driver should just count the number of markers
 *	and return that.  The reason the driver just can't say this function is unsupported
 *	like it does for SQLDescribeParam is that some applications don't care and try
 *	to call it anyway.
 *	If the statement does not have parameters, it should just return 0.
 */
RETCODE		SQL_API
PGAPI_NumParams(
				HSTMT hstmt,
				SQLSMALLINT FAR * pcpar)
{
	StatementClass *stmt = (StatementClass *) hstmt;
	CSTR func = "PGAPI_NumParams";

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

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

	if (pcpar)
		*pcpar = 0;
	else
	{
		SC_set_error(stmt, STMT_EXEC_ERROR, "parameter count address is null", func);
		return SQL_ERROR;
	}
inolog("num_params=%d,%d\n", stmt->num_params, stmt->proc_return);
	if (stmt->num_params >= 0)
		*pcpar = stmt->num_params;
	else if (!stmt->statement)
	{
		/* no statement has been allocated */
		SC_set_error(stmt, STMT_SEQUENCE_ERROR, "PGAPI_NumParams called with no statement ready.", func);
		return SQL_ERROR;
	}
	else
	{
		po_ind_t multi = FALSE, proc_return = 0;

		stmt->proc_return = 0;
		SC_scanQueryAndCountParams(stmt->statement, SC_get_conn(stmt), NULL, pcpar, &multi, &proc_return);
		stmt->num_params = *pcpar;
		stmt->proc_return = proc_return;
		stmt->multi_statement = multi;
		if (multi)
			SC_no_parse_tricky(stmt);
	}
inolog("num_params=%d,%d\n", stmt->num_params, stmt->proc_return);
	return SQL_SUCCESS;
}
Beispiel #6
0
/*		Performs the equivalent of SQLPrepare, followed by SQLExecute. */
RETCODE		SQL_API
PGAPI_ExecDirect(
				 HSTMT hstmt,
				 const SQLCHAR FAR * szSqlStr,
				 SQLINTEGER cbSqlStr,
				 UWORD flag)
{
	StatementClass *stmt = (StatementClass *) hstmt;
	RETCODE		result;
	CSTR func = "PGAPI_ExecDirect";
	const ConnectionClass	*conn = SC_get_conn(stmt);

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

	if (result = SC_initialize_and_recycle(stmt), SQL_SUCCESS != result)
		return result;

	/*
	 * keep a copy of the un-parametrized statement, in case they try to
	 * execute this statement again
	 */
	stmt->statement = make_string(szSqlStr, cbSqlStr, NULL, 0);
inolog("a2\n");
	if (!stmt->statement)
	{
		SC_set_error(stmt, STMT_NO_MEMORY_ERROR, "No memory available to store statement", func);
		return SQL_ERROR;
	}

	mylog("**** %s: hstmt=%p, statement='%s'\n", func, hstmt, stmt->statement);

	if (0 != (flag & PODBC_WITH_HOLD))
		SC_set_with_hold(stmt);

	/*
	 * If an SQLPrepare was performed prior to this, but was left in the
	 * premature state because an error occurred prior to SQLExecute then
	 * set the statement to finished so it can be recycled.
	 */
	if (stmt->status == STMT_PREMATURE)
		stmt->status = STMT_FINISHED;

	stmt->statement_type = statement_type(stmt->statement);

	/* Check if connection is onlyread (only selects are allowed) */
	if (CC_is_onlyread(conn) && STMT_UPDATE(stmt))
	{
		SC_set_error(stmt, STMT_EXEC_ERROR, "Connection is readonly, only select statements are allowed.", func);
		return SQL_ERROR;
	}

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

	flag = SC_is_with_hold(stmt) ? PODBC_WITH_HOLD : 0;
	result = PGAPI_Execute(hstmt, flag);

	mylog("%s: returned %hd from PGAPI_Execute\n", func, result);
	return result;
}
Beispiel #7
0
void	FI_Constructor(FIELD_INFO *self, BOOL reuse)
{
inolog("FI_Constructor reuse=%d\n", reuse);
	if (reuse)
		FI_Destructor(&self, 1, FALSE);
	memset(self, 0, sizeof(FIELD_INFO));
	self->nullable = TRUE;
	self->columnkey = -1;
}
Beispiel #8
0
void	ARD_unbind_cols(ARDFields *self, BOOL freeall)
{
	Int2	lf;

inolog("ARD_unbind_cols freeall=%d allocated=%d bindings=%p", freeall, self->allocated, self->bindings);
	for (lf = 1; lf <= self->allocated; lf++)
		reset_a_column_binding(self, lf);
	if (freeall)
	{
		if (self->bindings)
			free(self->bindings);
		self->bindings = NULL;
		self->allocated = 0;
	}
}
Beispiel #9
0
/*
 *	recv more than 1 bytes using SSL.
 */
static int SOCK_SSL_recv(SocketClass *sock, void *buffer, int len)
{
	CSTR	func = "SOCK_SSL_recv";
	int n, err, gerrno, retry_count = 0;

retry:
	n = SSL_read(sock->ssl, buffer, len);
	err = SSL_get_error(sock->ssl, len);
	gerrno = SOCK_ERRNO;
inolog("%s: %d get_error=%d Lasterror=%d\n", func, n, err, gerrno);
	switch (err)
	{
		case	SSL_ERROR_NONE:
			break;
		case	SSL_ERROR_WANT_READ:
			retry_count++;
			if (SOCK_wait_for_ready(sock, FALSE, retry_count) >= 0)
				goto retry;
			n = -1;
			break;
		case	SSL_ERROR_WANT_WRITE:
			goto retry;
			break;
		case	SSL_ERROR_SYSCALL:
			if (-1 != n)
			{
				n = -1;
				SOCK_ERRNO_SET(ECONNRESET);
			}
			break;
		case	SSL_ERROR_SSL:
		case	SSL_ERROR_ZERO_RETURN:
			n = -1;
			SOCK_ERRNO_SET(ECONNRESET);
			break;
		default:
			n = -1;
	}

	return n;
}
Beispiel #10
0
void	GDATA_unbind_cols(GetDataInfo *self, BOOL freeall)
{
	Int2	lf;

inolog("GDATA_unbind_cols freeall=%d allocated=%d gdata=%p", freeall, self->allocated, self->gdata);
	if (self->fdata.ttlbuf)
	{
		free(self->fdata.ttlbuf);
		self->fdata.ttlbuf = NULL;
	}
	self->fdata.ttlbuflen = self->fdata.ttlbufused = 0;
	self->fdata.data_left = -1;
	for (lf = 1; lf <= self->allocated; lf++)
		reset_a_getdata_info(self, lf);
	if (freeall)
	{
		if (self->gdata)
			free(self->gdata);
		self->gdata = NULL;
		self->allocated = 0;
	}
}
Beispiel #11
0
/*
 *	The execution after all parameters were resolved.
 */
static
RETCODE	Exec_with_parameters_resolved(StatementClass *stmt, BOOL *exec_end)
{
	CSTR func = "Exec_with_parameters_resolved";
	RETCODE		retval;
	SQLLEN		end_row;
	SQLINTEGER	cursor_type, scroll_concurrency;
	ConnectionClass	*conn;
	QResultClass	*res;
	APDFields	*apdopts;
	IPDFields	*ipdopts;
	BOOL		prepare_before_exec = FALSE;

	*exec_end = FALSE;
	conn = SC_get_conn(stmt);
	mylog("%s: copying statement params: trans_status=%d, len=%d, stmt='%s'\n", func, conn->transact_status, strlen(stmt->statement), stmt->statement);

#define	return	DONT_CALL_RETURN_FROM_HERE???
#define	RETURN(code)	{ retval = code; goto cleanup; }
	ENTER_CONN_CS(conn);
	/* save the cursor's info before the execution */
	cursor_type = stmt->options.cursor_type;
	scroll_concurrency = stmt->options.scroll_concurrency;
	/* Prepare the statement if possible at backend side */
	if (!stmt->inaccurate_result)
	{
		if (HowToPrepareBeforeExec(stmt, FALSE) >= allowParse)
			prepare_before_exec = TRUE;
	}
inolog("prepare_before_exec=%d srv=%d\n", prepare_before_exec, conn->connInfo.use_server_side_prepare);
	/* Create the statement with parameters substituted. */
	retval = copy_statement_with_parameters(stmt, prepare_before_exec);
	stmt->current_exec_param = -1;
	if (retval != SQL_SUCCESS)
	{
		stmt->exec_current_row = -1;
		*exec_end = TRUE;
		RETURN(retval) /* error msg is passed from the above */
	}
void    TI_Destructor(TABLE_INFO **ti, int count)
{
    int i;

inolog("TI_Destructor count=%d\n", count);
    if (ti)
    {
        for (i = 0; i < count; i++)
        {
            if (ti[i])
            {
                NULL_THE_NAME(ti[i]->schema_name);
                NULL_THE_NAME(ti[i]->table_name);
                NULL_THE_NAME(ti[i]->table_alias);
                NULL_THE_NAME(ti[i]->bestitem);
                NULL_THE_NAME(ti[i]->bestqual);
                free(ti[i]);
                ti[i] = NULL;
            }
        }
    }
}
Beispiel #13
0
/*	SQLAllocConnect/SQLAllocEnv/SQLAllocStmt -> SQLAllocHandle */
RETCODE		SQL_API
SQLAllocHandle(SQLSMALLINT HandleType,
			   SQLHANDLE InputHandle, SQLHANDLE * OutputHandle)
{
	CSTR	func = "SQLAllocHandle";
	RETCODE		ret;
	ConnectionClass	*conn;

	mylog("[[%s]]", func);
	switch (HandleType)
	{
		case SQL_HANDLE_ENV:
			ret = PGAPI_AllocEnv(OutputHandle);
			break;
		case SQL_HANDLE_DBC:
			ENTER_ENV_CS((EnvironmentClass *) InputHandle);
			ret = PGAPI_AllocConnect(InputHandle, OutputHandle);
			LEAVE_ENV_CS((EnvironmentClass *) InputHandle);
			break;
		case SQL_HANDLE_STMT:
			ENTER_CONN_CS((ConnectionClass *) InputHandle);
			ret = PGAPI_AllocStmt(InputHandle, OutputHandle);
			LEAVE_CONN_CS((ConnectionClass *) InputHandle);
			break;
		case SQL_HANDLE_DESC:
			conn = (ConnectionClass *) InputHandle;
			ENTER_CONN_CS(conn);
			ret = PGAPI_AllocDesc(InputHandle, OutputHandle);
			LEAVE_CONN_CS(conn);
inolog("OutputHandle=%p\n", *OutputHandle);
			break;
		default:
			ret = SQL_ERROR;
			break;
	}
	return ret;
}
Beispiel #14
0
int
StartRollbackState(StatementClass *stmt)
{
	CSTR	func = "StartRollbackState";
	int	ret;
	ConnectionClass	*conn;
	ConnInfo	*ci = NULL;
	
inolog("%s:%p->internal=%d\n", func, stmt, stmt->internal);
	conn = SC_get_conn(stmt);
	if (conn)
		ci = &conn->connInfo;
	ret = 0;
	if (!ci || ci->rollback_on_error < 0) /* default */
	{
		if (conn && PG_VERSION_GE(conn, 8.0))
			ret = 2; /* statement rollback */
		else
			ret = 1; /* transaction rollback */
	}
	else
	{
		ret = ci->rollback_on_error;
		if (2 == ret && PG_VERSION_LT(conn, 8.0))
			ret = 1;
	}
	switch (ret)
	{
		case 1:
			SC_start_tc_stmt(stmt);
			break;
		case 2:
			SC_start_rb_stmt(stmt);
			break;
	}
	return	ret;
}
Beispiel #15
0
RETCODE	SQL_API
PGAPI_CopyDesc(SQLHDESC SourceDescHandle,
			SQLHDESC TargetDescHandle)
{
	CSTR func = "PGAPI_CopyDesc";
	RETCODE ret = SQL_ERROR;
	DescriptorClass	*src, *target;
	ARDFields	*ard_src, *ard_tgt;
	APDFields	*apd_src, *apd_tgt;
	IPDFields	*ipd_src, *ipd_tgt;

	mylog("%s: entering...\n", func);
	src = (DescriptorClass *) SourceDescHandle;
	target = (DescriptorClass *) TargetDescHandle;
	if (!src->type_defined)
	{
		mylog("source type undefined\n");
		DC_set_error(target, DESC_EXEC_ERROR, "source handle type undefined");
		return ret;
	}
	if (target->type_defined)
	{
inolog("source type=%d -> target type=%d\n", src->desc_type, target->desc_type);
		if (SQL_ATTR_IMP_ROW_DESC == target->desc_type)
		{
			mylog("can't modify IRD\n");
			DC_set_error(target, DESC_EXEC_ERROR, "can't copy to IRD");
			return ret;
		}
		else if (target->desc_type != src->desc_type)
		{
			mylog("src type != target type\n");
			DC_set_error(target, DESC_EXEC_ERROR, "src descriptor != target type");
			return ret;
		}
		DC_Destructor(target);
	}
	ret = SQL_SUCCESS;
	switch (src->desc_type)
	{
		case SQL_ATTR_APP_ROW_DESC:
inolog("src=%p target=%p type=%d", src, target, src->desc_type);
			if (!target->type_defined)
			{
				target->desc_type = src->desc_type;
			}
			ard_src = (ARDFields *) (src + 1);
inolog(" rowset_size=%d bind_size=%d ope_ptr=%p off_ptr=%p\n",
ard_src->size_of_rowset, ard_src->bind_size,
ard_src->row_operation_ptr, ard_src->row_offset_ptr);
			ard_tgt = (ARDFields *) (target + 1);
inolog(" target=%p", ard_tgt);
			ARDFields_copy(ard_src, ard_tgt);
inolog(" offset_ptr=%p\n", ard_tgt->row_offset_ptr);
			break;
		case SQL_ATTR_APP_PARAM_DESC:
			if (!target->type_defined)
			{
				target->desc_type = src->desc_type;
			}
			apd_src = (APDFields *) (src + 1);
			apd_tgt = (APDFields *) (target + 1);
			APDFields_copy(apd_src, apd_tgt);
			break;
		case SQL_ATTR_IMP_PARAM_DESC:
			if (!target->type_defined)
			{
				target->desc_type = src->desc_type;
			}
			ipd_src = (IPDFields *) (src + 1);
			ipd_tgt = (IPDFields *) (target + 1);
			IPDFields_copy(ipd_src, ipd_tgt);
			break;
		default:
			mylog("invalid descriptor handle type=%d\n", src->desc_type);
			DC_set_error(target, DESC_EXEC_ERROR, "invalid descriptor type");
			ret = SQL_ERROR;
	}

	if (SQL_SUCCESS == ret)
		target->type_defined = TRUE;
        return ret;
}
Beispiel #16
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;
}
Beispiel #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;
}
Beispiel #18
0
void
makeConnectString(char *connect_string, const ConnInfo *ci, UWORD len)
{
	char		got_dsn = (ci->dsn[0] != '\0');
	char		encoded_item[LARGE_REGISTRY_LEN];
	ssize_t		hlen, nlen, olen;
	/*BOOL		abbrev = (len <= 400);*/
	BOOL		abbrev = (len < 1024) || 0 < ci->force_abbrev_connstr;
	UInt4		flag;

inolog("force_abbrev=%d abbrev=%d\n", ci->force_abbrev_connstr, abbrev);
	encode(ci->password, encoded_item, sizeof(encoded_item));
	/* fundamental info */
	nlen = MAX_CONNECT_STRING;
	olen = snprintf(connect_string, nlen, "%s=%s;DATABASE=%s;SERVER=%s;PORT=%s;UID=%s;PWD=%s",
			got_dsn ? "DSN" : "DRIVER",
			got_dsn ? ci->dsn : ci->drivername,
			ci->database,
			ci->server,
			ci->port,
			ci->username,
			encoded_item);
	if (olen < 0 || olen >= nlen)
	{
		connect_string[0] = '\0';
		return;
	}

	encode(ci->conn_settings, encoded_item, sizeof(encoded_item));

	/* extra info */
	hlen = strlen(connect_string);
	nlen = MAX_CONNECT_STRING - hlen;
inolog("hlen=%d", hlen);
	if (!abbrev)
	{
		char	protocol_and[16];
		
		if (ci->rollback_on_error >= 0)
			snprintf(protocol_and, sizeof(protocol_and), "%s-%d", ci->protocol, ci->rollback_on_error);
		else
			strncpy_null(protocol_and, ci->protocol, sizeof(protocol_and));
		olen = snprintf(&connect_string[hlen], nlen, ";"
			INI_SSLMODE "=%s;"
			INI_READONLY "=%s;"
			INI_PROTOCOL "=%s;"
			INI_FAKEOIDINDEX "=%s;"
			INI_SHOWOIDCOLUMN "=%s;"
			INI_ROWVERSIONING "=%s;"
			INI_SHOWSYSTEMTABLES "=%s;"
			INI_CONNSETTINGS "=%s;"
			INI_FETCH "=%d;"
			INI_SOCKET "=%d;"
			INI_UNKNOWNSIZES "=%d;"
			INI_MAXVARCHARSIZE "=%d;"
			INI_MAXLONGVARCHARSIZE "=%d;"
			INI_DEBUG "=%d;"
			INI_COMMLOG "=%d;"
			INI_OPTIMIZER "=%d;"
			INI_KSQO "=%d;"
			INI_USEDECLAREFETCH "=%d;"
			INI_TEXTASLONGVARCHAR "=%d;"
			INI_UNKNOWNSASLONGVARCHAR "=%d;"
			INI_BOOLSASCHAR "=%d;"
			INI_PARSE "=%d;"
			INI_CANCELASFREESTMT "=%d;"
			INI_EXTRASYSTABLEPREFIXES "=%s;"
			INI_LFCONVERSION "=%d;"
			INI_UPDATABLECURSORS "=%d;"
			INI_DISALLOWPREMATURE "=%d;"
			INI_TRUEISMINUS1 "=%d;"
			INI_INT8AS "=%d;"
			INI_BYTEAASLONGVARBINARY "=%d;"
			INI_USESERVERSIDEPREPARE "=%d;"
			INI_LOWERCASEIDENTIFIER "=%d;"
			INI_GREENPLUM "=%d;"
#ifdef	WIN32
			INI_GSSAUTHUSEGSSAPI "=%d;"
#endif /* WIN32 */
#ifdef	_HANDLE_ENLIST_IN_DTC_
			INI_XAOPT "=%d"	/* XAOPT */
#endif /* _HANDLE_ENLIST_IN_DTC_ */
			,ci->sslmode
			,ci->onlyread
			,protocol_and
			,ci->fake_oid_index
			,ci->show_oid_column
			,ci->row_versioning
			,ci->show_system_tables
			,encoded_item
			,ci->drivers.fetch_max
			,ci->drivers.socket_buffersize
			,ci->drivers.unknown_sizes
			,ci->drivers.max_varchar_size
			,ci->drivers.max_longvarchar_size
			,ci->drivers.debug
			,ci->drivers.commlog
			,ci->drivers.disable_optimizer
			,ci->drivers.ksqo
			,ci->drivers.use_declarefetch
			,ci->drivers.text_as_longvarchar
			,ci->drivers.unknowns_as_longvarchar
			,ci->drivers.bools_as_char
			,ci->drivers.parse
			,ci->drivers.cancel_as_freestmt
			,ci->drivers.extra_systable_prefixes
			,ci->lf_conversion
			,ci->allow_keyset
			,ci->disallow_premature
			,ci->true_is_minus1
			,ci->int8_as
			,ci->bytea_as_longvarbinary
			,ci->use_server_side_prepare
			,ci->lower_case_identifier
			,ci->greenplum
#ifdef	WIN32
			,ci->gssauth_use_gssapi
#endif /* WIN32 */
#ifdef	_HANDLE_ENLIST_IN_DTC_
			,ci->xa_opt
#endif /* _HANDLE_ENLIST_IN_DTC_ */
				);
	}
	/* Abbreviation is needed ? */
	if (abbrev || olen >= nlen || olen < 0)
	{
		flag = 0;
		if (ci->disallow_premature)
			flag |= BIT_DISALLOWPREMATURE;
		if (ci->allow_keyset)
			flag |= BIT_UPDATABLECURSORS;
		if (ci->lf_conversion)
			flag |= BIT_LFCONVERSION;
		if (ci->drivers.unique_index)
			flag |= BIT_UNIQUEINDEX;
		if (PROTOCOL_74(ci))
			flag |= (BIT_PROTOCOL_64 | BIT_PROTOCOL_63);
		else if (PROTOCOL_64(ci))
			flag |= BIT_PROTOCOL_64;
		else if (PROTOCOL_63(ci))
			flag |= BIT_PROTOCOL_63;
		switch (ci->drivers.unknown_sizes)
		{
			case UNKNOWNS_AS_DONTKNOW:
				flag |= BIT_UNKNOWN_DONTKNOW;
				break;
			case UNKNOWNS_AS_MAX:
				flag |= BIT_UNKNOWN_ASMAX;
				break;
		}
		if (ci->drivers.disable_optimizer)
			flag |= BIT_OPTIMIZER;
		if (ci->drivers.ksqo)
			flag |= BIT_KSQO;
		if (ci->drivers.commlog)
			flag |= BIT_COMMLOG;
		if (ci->drivers.debug)
			flag |= BIT_DEBUG;
		if (ci->drivers.parse)
			flag |= BIT_PARSE;
		if (ci->drivers.cancel_as_freestmt)
			flag |= BIT_CANCELASFREESTMT;
		if (ci->drivers.use_declarefetch)
			flag |= BIT_USEDECLAREFETCH;
		if (ci->onlyread[0] == '1')
			flag |= BIT_READONLY;
		if (ci->drivers.text_as_longvarchar)
			flag |= BIT_TEXTASLONGVARCHAR;
		if (ci->drivers.unknowns_as_longvarchar)
			flag |= BIT_UNKNOWNSASLONGVARCHAR;
		if (ci->drivers.bools_as_char)
			flag |= BIT_BOOLSASCHAR;
		if (ci->row_versioning[0] == '1')
			flag |= BIT_ROWVERSIONING;
		if (ci->show_system_tables[0] == '1')
			flag |= BIT_SHOWSYSTEMTABLES;
		if (ci->show_oid_column[0] == '1')
			flag |= BIT_SHOWOIDCOLUMN;
		if (ci->fake_oid_index[0] == '1')
			flag |= BIT_FAKEOIDINDEX;
		if (ci->true_is_minus1)
			flag |= BIT_TRUEISMINUS1;
		if (ci->bytea_as_longvarbinary)
			flag |= BIT_BYTEAASLONGVARBINARY;
		if (ci->use_server_side_prepare)
			flag |= BIT_USESERVERSIDEPREPARE;
		if (ci->lower_case_identifier)
			flag |= BIT_LOWERCASEIDENTIFIER;
		if (ci->gssauth_use_gssapi)
			flag |= BIT_GSSAUTHUSEGSSAPI;
		if (ci->greenplum)
			flag |= BIT_GREENPLUM;

		if (ci->sslmode[0])
		{
			char	abbrevmode[sizeof(ci->sslmode)];

			olen = snprintf(&connect_string[hlen], nlen, ";"
				ABBR_SSLMODE "=%s", abbrev_sslmode(ci->sslmode, abbrevmode));
		}
		hlen = strlen(connect_string);
		nlen = MAX_CONNECT_STRING - hlen;
		olen = snprintf(&connect_string[hlen], nlen, ";"
				ABBR_CONNSETTINGS "=%s;"
				ABBR_FETCH "=%d;"
				ABBR_SOCKET "=%d;"
				ABBR_MAXVARCHARSIZE "=%d;"
				ABBR_MAXLONGVARCHARSIZE "=%d;"
				INI_INT8AS "=%d;"
				ABBR_EXTRASYSTABLEPREFIXES "=%s;"
				INI_ABBREVIATE "=%02x%x",
				encoded_item,
				ci->drivers.fetch_max,
				ci->drivers.socket_buffersize,
				ci->drivers.max_varchar_size,
				ci->drivers.max_longvarchar_size,
				ci->int8_as,
				ci->drivers.extra_systable_prefixes,
				EFFECTIVE_BIT_COUNT, flag);
		if (olen < nlen && (PROTOCOL_74(ci) || ci->rollback_on_error >= 0))
		{
			hlen = strlen(connect_string);
			nlen = MAX_CONNECT_STRING - hlen;
			/*
			 * The PROTOCOL setting must be placed after CX flag
			 * so that this option can override the CX setting.
			 */
			if (ci->rollback_on_error >= 0)
				olen = snprintf(&connect_string[hlen], nlen, ";"
				ABBR_PROTOCOL "=%s-%d",
				ci->protocol, ci->rollback_on_error);
			else
				olen = snprintf(&connect_string[hlen], nlen, ";"
				ABBR_PROTOCOL "=%s",
				ci->protocol);
		}
	}
	if (olen < nlen)
	{
		flag = getExtraOptions(ci);
		if (0 != flag)
		{
			hlen = strlen(connect_string);
			nlen = MAX_CONNECT_STRING - hlen;
			olen = snprintf(&connect_string[hlen], nlen, ";"
				INI_EXTRAOPTIONS "=%x;",
				flag);
		}
	}
	if (olen < 0 || olen >= nlen) /* failed */
		connect_string[0] = '\0';
}
Beispiel #19
0
RETCODE
DiscardStatementSvp(StatementClass *stmt, RETCODE ret, BOOL errorOnly)
{
	CSTR	func = "DiscardStatementSvp";
	char	esavepoint[32], cmd[64];
	ConnectionClass	*conn = SC_get_conn(stmt);
	QResultClass *res;
	BOOL	cmd_success, start_stmt = FALSE;	

inolog("%s:%p->accessed=%d is_in=%d is_rb=%d is_tc=%d\n", func, stmt, SC_accessed_db(stmt),
CC_is_in_trans(conn), SC_is_rb_stmt(stmt), SC_is_tc_stmt(stmt));
	switch (ret)
	{
		case SQL_NEED_DATA:
			break;
		case SQL_ERROR:
			start_stmt = TRUE;
			break;
		default:
			if (!errorOnly)
				start_stmt = TRUE;
			break;
	}
	if (!SC_accessed_db(stmt) || !CC_is_in_trans(conn))
		goto cleanup;
	if (!SC_is_rb_stmt(stmt) && !SC_is_tc_stmt(stmt))
		goto cleanup;
	sprintf(esavepoint, "_EXEC_SVP_%p", stmt);
	if (SQL_ERROR == ret)
	{
		if (SC_started_rbpoint(stmt))
		{
			snprintf(cmd, sizeof(cmd), "ROLLBACK to %s", esavepoint);
			res = CC_send_query(conn, cmd, NULL, IGNORE_ABORT_ON_CONN, NULL);
			cmd_success = QR_command_maybe_successful(res);
			QR_Destructor(res);
			if (!cmd_success)
			{
				SC_set_error(stmt, STMT_INTERNAL_ERROR, "internal ROLLBACK failed", func);
				CC_abort(conn);
				goto cleanup;
			}
		}
		else
		{
			CC_abort(conn);
			goto cleanup;
		}
	}
	else if (errorOnly)
		return ret;
inolog("ret=%d\n", ret);
	if (SQL_NEED_DATA != ret && SC_started_rbpoint(stmt))
	{
		snprintf(cmd, sizeof(cmd), "RELEASE %s", esavepoint);
		res = CC_send_query(conn, cmd, NULL, IGNORE_ABORT_ON_CONN, NULL);
		cmd_success = QR_command_maybe_successful(res);
		QR_Destructor(res);
		if (!cmd_success)
		{
			SC_set_error(stmt, STMT_INTERNAL_ERROR, "internal RELEASE failed", func);
			CC_abort(conn);
			ret = SQL_ERROR;
		}
	}
cleanup:
	if (SQL_NEED_DATA != ret)
		SC_forget_unnamed(stmt); /* unnamed plan is no longer reliable */
	if (!SC_is_prepare_statement(stmt) && ONCE_DESCRIBED == stmt->prepared)
		SC_set_prepared(stmt, NOT_YET_PREPARED);
	if (start_stmt || SQL_ERROR == ret)
	{
		if (stmt->lock_CC_for_rb > 0)
		{
			LEAVE_CONN_CS(conn);
			stmt->lock_CC_for_rb--;
		}
		SC_start_stmt(stmt);
	}
	return ret;
}
Beispiel #20
0
/*
 *	Must be in a transaction or the subsequent execution
 *	invokes a transaction.
 */
RETCODE
SetStatementSvp(StatementClass *stmt)
{
	CSTR	func = "SetStatementSvp";
	char	esavepoint[32], cmd[64];
	ConnectionClass	*conn = SC_get_conn(stmt);
	QResultClass *res;
	RETCODE	ret = SQL_SUCCESS_WITH_INFO;

	if (CC_is_in_error_trans(conn))
		return ret;

	if (0 == stmt->lock_CC_for_rb)
	{
		ENTER_CONN_CS(conn);
		stmt->lock_CC_for_rb++;
	}
	switch (stmt->statement_type)
	{
		case STMT_TYPE_SPECIAL:
		case STMT_TYPE_TRANSACTION:
			return ret;
	}
	if (!SC_accessed_db(stmt))
	{
		BOOL	need_savep = FALSE;

		if (stmt->internal)
		{
			if (PG_VERSION_GE(conn, 8.0))
				SC_start_rb_stmt(stmt);
			else
				SC_start_tc_stmt(stmt);
		}
		if (SC_is_rb_stmt(stmt))
		{
			if (CC_is_in_trans(conn))
			{
				need_savep = TRUE;
			}
		}
		if (need_savep)
		{
			sprintf(esavepoint, "_EXEC_SVP_%p", stmt);
			snprintf(cmd, sizeof(cmd), "SAVEPOINT %s", esavepoint);
			res = CC_send_query(conn, cmd, NULL, 0, NULL);
			if (QR_command_maybe_successful(res))
			{
				SC_set_accessed_db(stmt);
				SC_start_rbpoint(stmt);
				ret = SQL_SUCCESS;
			}
			else
			{
				SC_set_error(stmt, STMT_INTERNAL_ERROR, "internal SAVEPOINT failed", func);
				ret = SQL_ERROR;
			}
			QR_Destructor(res);
		}
		else
			SC_set_accessed_db(stmt);
	}
inolog("%s:%p->accessed=%d\n", func, stmt, SC_accessed_db(stmt));
	return ret;
}
Beispiel #21
0
/*
 *	The execution after all parameters were resolved.
 */
static
RETCODE	Exec_with_parameters_resolved(StatementClass *stmt, BOOL *exec_end)
{
	CSTR func = "Exec_with_parameters_resolved";
	RETCODE		retval;
	SQLLEN		end_row;
	SQLINTEGER	cursor_type, scroll_concurrency;
	ConnectionClass	*conn;
	QResultClass	*res;
	APDFields	*apdopts;
	IPDFields	*ipdopts;
	BOOL		prepare_before_exec = FALSE;

	*exec_end = FALSE;
	conn = SC_get_conn(stmt);
	mylog("%s: copying statement params: trans_status=%d, len=%d, stmt='%s'\n", func, conn->transact_status, strlen(stmt->statement), stmt->statement);

	/* save the cursor's info before the execution */
	cursor_type = stmt->options.cursor_type;
	scroll_concurrency = stmt->options.scroll_concurrency;
	/* Prepare the statement if possible at backend side */
	if (!stmt->inaccurate_result)
	{
		if (HowToPrepareBeforeExec(stmt, FALSE) >= allowParse)
			prepare_before_exec = TRUE;
	}
inolog("prepare_before_exec=%d srv=%d\n", prepare_before_exec, conn->connInfo.use_server_side_prepare);
	/* Create the statement with parameters substituted. */
	retval = copy_statement_with_parameters(stmt, prepare_before_exec);
	stmt->current_exec_param = -1;
	if (retval != SQL_SUCCESS)
	{
		stmt->exec_current_row = -1;
		*exec_end = TRUE;
		return retval; /* error msg is passed from the above */
	}

	mylog("   stmt_with_params = '%s'\n", stmt->stmt_with_params);

	/*
	 *	Dummy exection to get the column info.
	 */ 
	if (stmt->inaccurate_result && SC_is_parse_tricky(stmt))
	{
		BOOL		in_trans = CC_is_in_trans(conn);
		BOOL		issued_begin = FALSE;
		QResultClass *curres;

		stmt->exec_current_row = -1;
		*exec_end = TRUE;
		if (!SC_is_pre_executable(stmt))
			return SQL_SUCCESS;
		if (strnicmp(stmt->stmt_with_params, "BEGIN;", 6) == 0)
		{
			/* do nothing */
		}
		else if (!in_trans)
		{
			if (issued_begin = CC_begin(conn), !issued_begin)
			{
				SC_set_error(stmt, STMT_EXEC_ERROR,  "Handle prepare error", func);
				return SQL_ERROR;
			}
		}
		/* we are now in a transaction */
		res = CC_send_query(conn, stmt->stmt_with_params, NULL, 0, SC_get_ancestor(stmt));
		if (!QR_command_maybe_successful(res))
		{
#ifndef	_LEGACY_MODE_
			if (PG_VERSION_LT(conn, 8.0))
				CC_abort(conn);
#endif /* LEGACY_MODE_ */
			SC_set_error(stmt, STMT_EXEC_ERROR, "Handle prepare error", func);
			QR_Destructor(res);
			return SQL_ERROR;
		}
		SC_set_Result(stmt, res);
		for (curres = res; !curres->num_fields; curres = curres->next)
			;
		SC_set_Curres(stmt, curres);
		if (CC_does_autocommit(conn))
		{
			if (issued_begin)
				CC_commit(conn);
		}
		stmt->status = STMT_FINISHED;
		return SQL_SUCCESS;
	}
	/*
	 *	The real execution.
	 */
mylog("about to begin SC_execute\n");
	retval = SC_execute(stmt);
	if (retval == SQL_ERROR)
	{
		stmt->exec_current_row = -1;
		*exec_end = TRUE;
		return retval;
	}
	res = SC_get_Result(stmt);
	/* special handling of result for keyset driven cursors */
	if (SQL_CURSOR_KEYSET_DRIVEN == stmt->options.cursor_type &&
	    SQL_CONCUR_READ_ONLY != stmt->options.scroll_concurrency)
	{
		QResultClass	*kres;

		if (kres = res->next, kres)
		{
			if (kres->fields)
				CI_Destructor(kres->fields);
			kres->fields = res->fields;
			res->fields = NULL;
			kres->num_fields = res->num_fields;
			res->next = NULL;
			SC_set_Result(stmt, kres);
			res = kres;
		}
	}
#ifdef	NOT_USED
	else if (SC_is_concat_prepare_exec(stmt))
	{
		if (res && QR_command_maybe_successful(res))
		{
			QResultClass	*kres;
		
			kres = res->next;
inolog("res->next=%p\n", kres);
			res->next = NULL;
			SC_set_Result(stmt, kres);
			res = kres;
			SC_set_prepared(stmt, PREPARED_PERMANENTLY);
		}
		else
		{
			retval = SQL_ERROR;
			if (stmt->execute_statement)
				free(stmt->execute_statement);
			stmt->execute_statement = NULL;
		}
	}
#endif /* NOT_USED */
#if (ODBCVER >= 0x0300)
	ipdopts = SC_get_IPDF(stmt);
	if (ipdopts->param_status_ptr)
	{
		switch (retval)
		{
			case SQL_SUCCESS: 
				ipdopts->param_status_ptr[stmt->exec_current_row] = SQL_PARAM_SUCCESS;
				break;
			case SQL_SUCCESS_WITH_INFO: 
				ipdopts->param_status_ptr[stmt->exec_current_row] = SQL_PARAM_SUCCESS_WITH_INFO;
				break;
			default: 
				ipdopts->param_status_ptr[stmt->exec_current_row] = SQL_PARAM_ERROR;
				break;
		}
	}
#endif /* ODBCVER */
	if (end_row = stmt->exec_end_row, end_row < 0)
	{
		apdopts = SC_get_APDF(stmt);
		end_row = (SQLINTEGER) apdopts->paramset_size - 1;
	}
	if (stmt->inaccurate_result ||
	    stmt->exec_current_row >= end_row)
	{
		*exec_end = TRUE;
		stmt->exec_current_row = -1;
	}
	else
		stmt->exec_current_row++;
	if (res)
	{
#if (ODBCVER >= 0x0300)
		EnvironmentClass *env = (EnvironmentClass *) CC_get_env(conn);
		const char *cmd = QR_get_command(res);
		SQLLEN	start_row;
		if (start_row = stmt->exec_start_row, start_row < 0)
			start_row = 0;

		if (retval == SQL_SUCCESS &&
		    NULL != cmd &&
		    start_row >= end_row &&
		    NULL != env &&
		    EN_is_odbc3(env))
		{
			int     count;

			if (sscanf(cmd , "UPDATE %d", &count) == 1)
				;
			else if (sscanf(cmd , "DELETE %d", &count) == 1)
				;
			else
				count = -1;
			if (0 == count)
				retval = SQL_NO_DATA;
		}
#endif /* ODBCVER */
		stmt->diag_row_count = res->recent_processed_row_count;
	}
	/*
	 *	The cursor's info was changed ?
	 */
	if (retval == SQL_SUCCESS &&
	    (stmt->options.cursor_type != cursor_type ||
	     stmt->options.scroll_concurrency != scroll_concurrency))
	{
		SC_set_error(stmt, STMT_OPTION_VALUE_CHANGED, "cursor updatability changed", func);
		retval = SQL_SUCCESS_WITH_INFO;
	}
	return retval;
}
Beispiel #22
0
/*		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;
}
UCHAR
SOCK_get_next_byte(SocketClass *self, BOOL peek)
{
	int	retry_count = 0, gerrno;
	BOOL	maybeEOF = FALSE;

	if (!self)
		return 0;
	if (self->buffer_read_in >= self->buffer_filled_in)
	{
		/*
		 * there are no more bytes left in the buffer so reload the buffer
		 */
		self->buffer_read_in = 0;
retry:
#ifdef USE_SSL 
		if (self->ssl)
			self->buffer_filled_in = SOCK_SSL_recv(self, (char *) self->buffer_in, self->buffer_size);
		else
#endif /* USE_SSL */
			self->buffer_filled_in = SOCK_SSPI_recv(self, (char *) self->buffer_in, self->buffer_size);
		gerrno = SOCK_ERRNO;

		mylog("read %d, global_socket_buffersize=%d\n", self->buffer_filled_in, self->buffer_size);

		if (self->buffer_filled_in < 0)
		{
mylog("Lasterror=%d\n", gerrno);
			switch (gerrno)
			{
				case	EINTR:
					goto retry;
					break;
#ifdef EAGAIN
				case	EAGAIN:
#endif /* EAGAIN */
#if defined(EWOULDBLOCK) && (!defined(EAGAIN) || (EWOULDBLOCK != EAGAIN))
				case	EWOULDBLOCK:
#endif /* EWOULDBLOCK */
					retry_count++;
					if (SOCK_wait_for_ready(self, FALSE, retry_count) >= 0)
						goto retry;
					break;
				case	ECONNRESET:
inolog("ECONNRESET\n");
					maybeEOF = TRUE;
					SOCK_set_error(self, SOCKET_CLOSED, "Connection reset by peer.");
					break;
			}
			if (0 == self->errornumber)
				SOCK_set_error(self, SOCKET_READ_ERROR, "Error while reading from the socket.");
			self->buffer_filled_in = 0;
			return 0;
		}
		if (self->buffer_filled_in == 0)
		{
			if (!maybeEOF)
			{
				int	nbytes = SOCK_wait_for_ready(self, FALSE, 0);
				if (nbytes > 0)
				{
					maybeEOF = TRUE;
					goto retry;
				}
				else if (0 == nbytes)
					maybeEOF = TRUE;
			}
			if (maybeEOF)
				SOCK_set_error(self, SOCKET_CLOSED, "Socket has been closed.");
			else
				SOCK_set_error(self, SOCKET_READ_ERROR, "Error while reading from the socket.");
			return 0;
		}
	}
	if (peek)
		return self->buffer_in[self->buffer_read_in];
	if (PG_PROTOCOL_74 == self->pversion)
		self->reslen--;
	return self->buffer_in[self->buffer_read_in++];
}
Beispiel #24
0
const char *
pgtype_attr_to_name(const ConnectionClass *conn, OID type, int atttypmod, BOOL auto_increment)
{
	const char	*tname = NULL;

	switch (type)
	{
		case PG_TYPE_CHAR:
			return "char";
		case PG_TYPE_INT8:
			return auto_increment ? "bigserial" : "int8";
		case PG_TYPE_NUMERIC:
			return "numeric";
		case PG_TYPE_VARCHAR:
			return "varchar";
		case PG_TYPE_BPCHAR:
			return "char";
		case PG_TYPE_TEXT:
			return "text";
		case PG_TYPE_NAME:
			return "name";
		case PG_TYPE_REFCURSOR:
			return "refcursor";
		case PG_TYPE_INT2:
			return "int2";
		case PG_TYPE_OID:
			return OID_NAME;
		case PG_TYPE_XID:
			return "xid";
		case PG_TYPE_INT4:
inolog("pgtype_to_name int4\n");
			return auto_increment ? "serial" : "int4";
		case PG_TYPE_FLOAT4:
			return "float4";
		case PG_TYPE_FLOAT8:
			return "float8";
		case PG_TYPE_DATE:
			return "date";
		case PG_TYPE_TIME:
			return "time";
		case PG_TYPE_ABSTIME:
			return "abstime";
		case PG_TYPE_DATETIME:
			return "timestamptz";
		case PG_TYPE_TIMESTAMP_NO_TMZONE:
			return "timestamp without time zone";
		case PG_TYPE_TIMESTAMP:
			return "timestamp";
		case PG_TYPE_MONEY:
			return "money";
		case PG_TYPE_BOOL:
			return "bool";
		case PG_TYPE_BYTEA:
			return "bytea";
		case PG_TYPE_XML:
			return "xml";
		case PG_TYPE_MACADDR:
			return "macaddr";
		case PG_TYPE_INET:
			return "inet";
		case PG_TYPE_CIDR:
			return "cidr";
		case PG_TYPE_UUID:
			return "uuid";
		case PG_TYPE_INTERVAL:
			get_interval_type(atttypmod, &tname);
			return tname;
		case PG_TYPE_LO_UNDEFINED:
			return PG_TYPE_LO_NAME;

		default:
			/* hack until permanent type is available */
			if (type == conn->lobj_type)
				return PG_TYPE_LO_NAME;

			/*
			 * "unknown" can actually be used in alter table because it is
			 * a real PG type!
			 */
			return "unknown";
	}
}
Beispiel #25
0
const char *
pgtype_to_name(StatementClass *stmt, OID type, BOOL auto_increment)
{
	ConnectionClass	*conn = SC_get_conn(stmt);
	switch (type)
	{
		case PG_TYPE_CHAR:
			return "char";
		case PG_TYPE_CHAR2:
			return "char2";
		case PG_TYPE_CHAR4:
			return "char4";
		case PG_TYPE_CHAR8:
			return "char8";
		case PG_TYPE_INT8:
			return auto_increment ? "bigserial" : "int8";
		case PG_TYPE_NUMERIC:
			return "numeric";
		case PG_TYPE_VARCHAR:
			return "varchar";
		case PG_TYPE_BPCHAR:
			return "char";
		case PG_TYPE_TEXT:
			return "text";
		case PG_TYPE_NAME:
			return "name";
		case PG_TYPE_INT2:
			return "int2";
		case PG_TYPE_OID:
			return OID_NAME;
		case PG_TYPE_XID:
			return "xid";
		case PG_TYPE_INT4:
inolog("pgtype_to_name int4\n");
			return auto_increment ? "serial" : "int4";
		case PG_TYPE_FLOAT4:
			return "float4";
		case PG_TYPE_FLOAT8:
			return "float8";
		case PG_TYPE_DATE:
			return "date";
		case PG_TYPE_TIME:
			return "time";
		case PG_TYPE_ABSTIME:
			return "abstime";
		case PG_TYPE_DATETIME:
			if (PG_VERSION_GT(conn, 7.1))
				return "timestamptz";
			else if (PG_VERSION_LT(conn, 7.0))
				return "datetime";
			else
				return "timestamp";
		case PG_TYPE_TIMESTAMP_NO_TMZONE:
			return "timestamp without time zone";
		case PG_TYPE_TIMESTAMP:
			return "timestamp";
		case PG_TYPE_MONEY:
			return "money";
		case PG_TYPE_BOOL:
			return "bool";
		case PG_TYPE_BYTEA:
			return "bytea";
		case PG_TYPE_XML:
			return "xml";
		case PG_TYPE_MACADDR:
			return "macaddr";
		case PG_TYPE_INET:
			return "inet";
		case PG_TYPE_CIDR:
			return "cidr";
		case PG_TYPE_UUID:
			return "uuid";

		case PG_TYPE_LO_UNDEFINED:
			return PG_TYPE_LO_NAME;

		default:
			/* hack until permanent type is available */
			if (type == stmt->hdbc->lobj_type)
				return PG_TYPE_LO_NAME;

			/*
			 * "unknown" can actually be used in alter table because it is
			 * a real PG type!
			 */
			return "unknown";
	}
}
Beispiel #26
0
RETCODE SQL_API
SQLDriverConnectW(HDBC hdbc,
				  HWND hwnd,
				  SQLWCHAR *szConnStrIn,
				  SQLSMALLINT cbConnStrIn,
				  SQLWCHAR *szConnStrOut,
				  SQLSMALLINT cbConnStrOutMax,
				  SQLSMALLINT *pcbConnStrOut,
				  SQLUSMALLINT fDriverCompletion)
{
	CSTR func = "SQLDriverConnectW";
	char	*szIn, *szOut = NULL;
	SQLSMALLINT	maxlen, obuflen = 0;
	SQLLEN		inlen;
	SQLSMALLINT	olen, *pCSO;
	RETCODE	ret;
	ConnectionClass *conn = (ConnectionClass *) hdbc;

	mylog("[%s]", func);
	CC_examine_global_transaction(conn);
	ENTER_CONN_CS(conn);
	CC_clear_error(conn);
	CC_set_in_unicode_driver(conn);
	szIn = ucs2_to_utf8(szConnStrIn, cbConnStrIn, &inlen, FALSE);
	maxlen = cbConnStrOutMax;
	pCSO = NULL;
	olen = 0;
	if (maxlen > 0)
	{
		obuflen = maxlen + 1;
		szOut = malloc(obuflen);
		if (!szOut)
		{
			CC_set_error(conn, CONN_NO_MEMORY_ERROR, "Could not allocate memory for output buffer", func);
			ret = SQL_ERROR;
			goto cleanup;
		}
		pCSO = &olen;
	}
	else if (pcbConnStrOut)
		pCSO = &olen;
	ret = PGAPI_DriverConnect(hdbc, hwnd,
							  (SQLCHAR *) szIn, (SQLSMALLINT) inlen,
							  (SQLCHAR *) szOut, maxlen,
							  pCSO, fDriverCompletion);
	if (ret != SQL_ERROR && NULL != pCSO)
	{
		SQLLEN outlen = olen;

		if (olen < obuflen)
			outlen = utf8_to_ucs2(szOut, olen, szConnStrOut, cbConnStrOutMax);
		else
			utf8_to_ucs2(szOut, maxlen, szConnStrOut, cbConnStrOutMax);
		if (outlen >= cbConnStrOutMax && NULL != szConnStrOut && NULL != pcbConnStrOut)
		{
inolog("cbConnstrOutMax=%d pcb=%p\n", cbConnStrOutMax, pcbConnStrOut);
			if (SQL_SUCCESS == ret)
			{
				CC_set_error(conn, CONN_TRUNCATED, "the ConnStrOut is too small", func);
				ret = SQL_SUCCESS_WITH_INFO;
			}
		}
		if (pcbConnStrOut)
			*pcbConnStrOut = (SQLSMALLINT) outlen;
	}
cleanup:
	LEAVE_CONN_CS(conn);
	if (szOut)
		free(szOut);
	if (szIn)
		free(szIn);
	return ret;
}
Beispiel #27
0
RETCODE		SQL_API
PGAPI_DriverConnect(
					HDBC hdbc,
					HWND hwnd,
					const SQLCHAR FAR * szConnStrIn,
					SQLSMALLINT cbConnStrIn,
					SQLCHAR FAR * szConnStrOut,
					SQLSMALLINT cbConnStrOutMax,
					SQLSMALLINT FAR * pcbConnStrOut,
					SQLUSMALLINT fDriverCompletion)
{
	CSTR func = "PGAPI_DriverConnect";
	ConnectionClass *conn = (ConnectionClass *) hdbc;
	ConnInfo   *ci;

#ifdef WIN32
	RETCODE		dialog_result;
#endif
	BOOL		paramRequired, didUI = FALSE;
	RETCODE		result;
	char		*connStrIn = NULL;
	char		connStrOut[MAX_CONNECT_STRING];
	int			retval;
	char		salt[5];
	char		password_required = AUTH_REQ_OK;
	ssize_t		len = 0;
	SQLSMALLINT	lenStrout;


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

	if (!conn)
	{
		CC_log_error(func, "", NULL);
		return SQL_INVALID_HANDLE;
	}

	connStrIn = make_string(szConnStrIn, cbConnStrIn, NULL, 0);

#ifdef	FORCE_PASSWORD_DISPLAY
	mylog("**** PGAPI_DriverConnect: fDriverCompletion=%d, connStrIn='%s'\n", fDriverCompletion, connStrIn);
	qlog("conn=%p, PGAPI_DriverConnect( in)='%s', fDriverCompletion=%d\n", conn, connStrIn, fDriverCompletion);
#else
	if (get_qlog() || get_mylog())
	{
		char	*hide_str = hide_password(connStrIn);

		mylog("**** PGAPI_DriverConnect: fDriverCompletion=%d, connStrIn='%s'\n", fDriverCompletion, NULL_IF_NULL(hide_str));
		qlog("conn=%p, PGAPI_DriverConnect( in)='%s', fDriverCompletion=%d\n", conn, NULL_IF_NULL(hide_str), fDriverCompletion);
		if (hide_str)
			free(hide_str);
	}
#endif	/* FORCE_PASSWORD_DISPLAY */

	ci = &(conn->connInfo);

	/* Parse the connect string and fill in conninfo for this hdbc. */
	dconn_get_connect_attributes(connStrIn, ci);

	/*
	 * If the ConnInfo in the hdbc is missing anything, this function will
	 * fill them in from the registry (assuming of course there is a DSN
	 * given -- if not, it does nothing!)
	 */
	getDSNinfo(ci, CONN_DONT_OVERWRITE);
	dconn_get_common_attributes(connStrIn, ci);
	logs_on_off(1, ci->drivers.debug, ci->drivers.commlog);
	if (connStrIn)
	{
		free(connStrIn);
		connStrIn = NULL;
	}

	/* Fill in any default parameters if they are not there. */
	getDSNdefaults(ci);
	/* initialize pg_version */
	CC_initialize_pg_version(conn);
	memset(salt, 0, sizeof(salt));

#ifdef WIN32
dialog:
#endif
	ci->focus_password = password_required;

inolog("DriverCompletion=%d\n", fDriverCompletion);
	switch (fDriverCompletion)
	{
#ifdef WIN32
		case SQL_DRIVER_PROMPT:
			dialog_result = dconn_DoDialog(hwnd, ci);
			didUI = TRUE;
			if (dialog_result != SQL_SUCCESS)
				return dialog_result;
			break;

		case SQL_DRIVER_COMPLETE_REQUIRED:

			/* Fall through */

		case SQL_DRIVER_COMPLETE:

			paramRequired = password_required;
			/* Password is not a required parameter. */
			if (ci->database[0] == '\0')
				paramRequired = TRUE;
			else if (ci->port[0] == '\0')
				paramRequired = TRUE;
#ifdef	WIN32
			else if (ci->server[0] == '\0')
				paramRequired = TRUE;
#endif /* WIN32 */
			if (paramRequired)
			{
				dialog_result = dconn_DoDialog(hwnd, ci);
				didUI = TRUE;
				if (dialog_result != SQL_SUCCESS)
					return dialog_result;
			}
			break;
#else
		case SQL_DRIVER_PROMPT:
		case SQL_DRIVER_COMPLETE:
		case SQL_DRIVER_COMPLETE_REQUIRED:
#endif
		case SQL_DRIVER_NOPROMPT:
			break;
	}

	/*
	 * Password is not a required parameter unless authentication asks for
	 * it. For now, I think it's better to just let the application ask
	 * over and over until a password is entered (the user can always hit
	 * Cancel to get out)
	 */
	paramRequired = FALSE;
	if (ci->database[0] == '\0')
		paramRequired = TRUE;
	else if (ci->port[0] == '\0')
		paramRequired = TRUE;
#ifdef	WIN32
	else if (ci->server[0] == '\0')
		paramRequired = TRUE;
#endif /* WIN32 */
	if (paramRequired)
	{
		if (didUI)
			return SQL_NO_DATA_FOUND;
		CC_set_error(conn, CONN_OPENDB_ERROR, "connction string lacks some options", func);
		return SQL_ERROR;
	}

inolog("before CC_connect\n");
	/* do the actual connect */
	retval = CC_connect(conn, password_required, salt);
	if (retval < 0)
	{							/* need a password */
		if (fDriverCompletion == SQL_DRIVER_NOPROMPT)
		{
			CC_log_error(func, "Need password but Driver_NoPrompt", conn);
			return SQL_ERROR;	/* need a password but not allowed to
								 * prompt so error */
		}
		else
		{
#ifdef WIN32
			password_required = -retval;
			goto dialog;
#else
			return SQL_ERROR;	/* until a better solution is found. */
#endif
		}
	}
	else if (retval == 0)
	{
		/* error msg filled in above */
		CC_log_error(func, "Error from CC_Connect", conn);
		return SQL_ERROR;
	}

	/*
	 * Create the Output Connection String
	 */
	result = SQL_SUCCESS;

	lenStrout = cbConnStrOutMax;
	if (conn->ms_jet && lenStrout > 255)
		lenStrout = 255;
	makeConnectString(connStrOut, ci, lenStrout);
	len = strlen(connStrOut);

	if (szConnStrOut)
	{
		/*
		 * Return the completed string to the caller. The correct method
		 * is to only construct the connect string if a dialog was put up,
		 * otherwise, it should just copy the connection input string to
		 * the output. However, it seems ok to just always construct an
		 * output string.  There are possible bad side effects on working
		 * applications (Access) by implementing the correct behavior,
		 * anyway.
		 */
		/*strncpy_null(szConnStrOut, connStrOut, cbConnStrOutMax);*/
		strncpy(szConnStrOut, connStrOut, cbConnStrOutMax);

		if (len >= cbConnStrOutMax)
		{
			int			clen;

			for (clen = cbConnStrOutMax - 1; clen >= 0 && szConnStrOut[clen] != ';'; clen--)
				szConnStrOut[clen] = '\0';
			result = SQL_SUCCESS_WITH_INFO;
			CC_set_error(conn, CONN_TRUNCATED, "The buffer was too small for the ConnStrOut.", func);
		}
	}

	if (pcbConnStrOut)
		*pcbConnStrOut = (SQLSMALLINT) len;

#ifdef	FORCE_PASSWORD_DISPLAY
	if (cbConnStrOutMax > 0)
	{
		mylog("szConnStrOut = '%s' len=%d,%d\n", NULL_IF_NULL(szConnStrOut), len, cbConnStrOutMax);
		qlog("conn=%p, PGAPI_DriverConnect(out)='%s'\n", conn, NULL_IF_NULL(szConnStrOut));
	}
#else
	if (get_qlog() || get_mylog())
	{
		char	*hide_str = NULL;

		if (cbConnStrOutMax > 0)
			hide_str = hide_password(szConnStrOut);
		mylog("szConnStrOut = '%s' len=%d,%d\n", NULL_IF_NULL(hide_str), len, cbConnStrOutMax);
		qlog("conn=%p, PGAPI_DriverConnect(out)='%s'\n", conn, NULL_IF_NULL(hide_str));
		if (hide_str)
			free(hide_str);
	}
#endif /* FORCE_PASSWORD_DISPLAY */

	if (connStrIn)
		free(connStrIn);
	mylog("PGAPI_DriverConnect: returning %d\n", result);
	return result;
}
Beispiel #28
0
/*
 *	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;
}
Beispiel #29
0
static int
SOCK_get_next_n_bytes(SocketClass *self, int n, char *buf)
{
	int	retry_count = 0, gerrno, rest, rlen;
	BOOL	maybeEOF = FALSE;

	if (!self || !n)
		return 0;
	for (rest = n; 0 < rest;)
	{
	if (self->buffer_read_in >= self->buffer_filled_in)
	{
		/*
		 * there are no more bytes left in the buffer so reload the buffer
		 */
		self->buffer_read_in = 0;
retry:
#ifdef USE_SSL 
		if (self->ssl)
			self->buffer_filled_in = SOCK_SSL_recv(self, (char *) self->buffer_in, self->buffer_size);
		else
#endif /* USE_SSL */
			self->buffer_filled_in = SOCK_SSPI_recv(self, (char *) self->buffer_in, self->buffer_size);
		gerrno = SOCK_ERRNO;

		mylog("read %d, global_socket_buffersize=%d\n", self->buffer_filled_in, self->buffer_size);

		if (self->buffer_filled_in < 0)
		{
mylog("Lasterror=%d\n", gerrno);
			switch (gerrno)
			{
				case	EINTR:
					goto retry;
					break;
#ifdef EAGAIN
				case	EAGAIN:
#endif /* EAGAIN */
#if defined(EWOULDBLOCK) && (!defined(EAGAIN) || (EWOULDBLOCK != EAGAIN))
				case	EWOULDBLOCK:
#endif /* EWOULDBLOCK */
					retry_count++;
					if (SOCK_wait_for_ready(self, FALSE, retry_count) >= 0)
						goto retry;
					break;
				case	ECONNRESET:
inolog("ECONNRESET\n");
					maybeEOF = TRUE;
					SOCK_set_error(self, SOCKET_CLOSED, "Connection reset by peer.");
					break;
			}
			if (0 == self->errornumber)
				SOCK_set_error(self, SOCKET_READ_ERROR, "Error while reading from the socket.");
			self->buffer_filled_in = 0;
			return -1;
		}
		if (self->buffer_filled_in == 0)
		{
			if (!maybeEOF)
			{
				int	nready = SOCK_wait_for_ready(self, FALSE, 0);
				if (nready > 0)
				{
					maybeEOF = TRUE;
					goto retry;
				}
				else if (0 == nready)
					maybeEOF = TRUE;
			}
			if (maybeEOF)
			{
				SOCK_set_error(self, SOCKET_CLOSED, "Socket has been closed.");
				break;
			}
			else
			{
				SOCK_set_error(self, SOCKET_READ_ERROR, "Error while reading from the socket.");
				return -1;
			}
		}
	}
	rlen = self->buffer_filled_in - self->buffer_read_in;
	if (rlen > rest)
		rlen = rest;
	if (buf)
		memcpy(buf + n - rest, self->buffer_in + self->buffer_read_in, rlen);
	rest -= rlen;
	if (PG_PROTOCOL_74 == self->pversion)
		self->reslen -= rlen;
	self->buffer_read_in += rlen;
	}

	return n - rest;
}
Beispiel #30
0
static Int4
getCharColumnSizeX(const ConnectionClass *conn, OID type, int atttypmod, int adtsize_or_longestlen, int handle_unknown_size_as)
{
	int		p = -1, maxsize;
	const ConnInfo	*ci = &(conn->connInfo);

	mylog("%s: type=%d, atttypmod=%d, adtsize_or=%d, unknown = %d\n", __FUNCTION__, type, atttypmod, adtsize_or_longestlen, handle_unknown_size_as);

	/* Assign Maximum size based on parameters */
	switch (type)
	{
		case PG_TYPE_TEXT:
			if (ci->drivers.text_as_longvarchar)
				maxsize = ci->drivers.max_longvarchar_size;
			else
				maxsize = ci->drivers.max_varchar_size;
			break;

		case PG_TYPE_VARCHAR:
		case PG_TYPE_BPCHAR:
			maxsize = ci->drivers.max_varchar_size;
			break;

		default:
			if (ci->drivers.unknowns_as_longvarchar)
				maxsize = ci->drivers.max_longvarchar_size;
			else
				maxsize = ci->drivers.max_varchar_size;
			break;
	}
#ifdef	UNICODE_SUPPORT
	if (CC_is_in_unicode_driver(conn) &&
	    isSqlServr() &&
	    maxsize > 4000)
		maxsize = 4000;
#endif /* UNICODE_SUPPORT */

	if (maxsize == TEXT_FIELD_SIZE + 1) /* magic length for testing */
		maxsize = 0;

	/*
	 * Static ColumnSize (i.e., the Maximum ColumnSize of the datatype) This
	 * has nothing to do with a result set.
	 */
inolog("!!! atttypmod  < 0 ?\n");
	if (atttypmod < 0 && adtsize_or_longestlen < 0)
		return maxsize;

inolog("!!! adtsize_or_logngest=%d\n", adtsize_or_longestlen);
	p = adtsize_or_longestlen; /* longest */
	/*
	 * Catalog Result Sets -- use assigned column width (i.e., from
	 * set_tuplefield_string)
	 */
inolog("!!! catalog_result=%d\n", handle_unknown_size_as);
	if (UNKNOWNS_AS_LONGEST == handle_unknown_size_as)
	{
		mylog("%s: LONGEST: p = %d\n", __FUNCTION__, p);
		if (p > 0 &&
		    (atttypmod < 0 || atttypmod > p))
			return p;
	}
	if (TYPE_MAY_BE_ARRAY(type))
	{
		if (p > 0)
			return p;
		return maxsize;
	}

	/* Size is unknown -- handle according to parameter */
	if (atttypmod > 0)	/* maybe the length is known */
	{
		return atttypmod;
	}

	/* The type is really unknown */
	switch (handle_unknown_size_as)
	{
		case UNKNOWNS_AS_DONTKNOW:
			return -1;
		case UNKNOWNS_AS_LONGEST:
		case UNKNOWNS_AS_MAX:
			break;
		default:
			return -1;
	}
	if (maxsize <= 0)
		return maxsize;
	switch (type)
	{
		case PG_TYPE_BPCHAR:
		case PG_TYPE_VARCHAR:
		case PG_TYPE_TEXT:
			return maxsize;
	}

	if (p > maxsize)
		maxsize = p;
	return maxsize;
}