Esempio n. 1
0
static int
inquireHowToPrepare(const StatementClass *stmt)
{
	ConnectionClass	*conn;
	ConnInfo	*ci;
	int		ret = 0;

	conn = SC_get_conn(stmt);
	ci = &(conn->connInfo);
	if (!ci->use_server_side_prepare ||
		PG_VERSION_LT(conn, 7.3))
	{
		/* Do prepare operations by the driver itself */
		return PREPARE_BY_THE_DRIVER;
	}
	if (NOT_YET_PREPARED == stmt->prepared)
	{
		SQLSMALLINT	num_params;

		if (STMT_TYPE_DECLARE == stmt->statement_type &&
		    PG_VERSION_LT(conn, 8.0))
		{
			return PREPARE_BY_THE_DRIVER;
		}
		if (stmt->multi_statement < 0)
			PGAPI_NumParams((StatementClass *) stmt, &num_params);
		if (stmt->multi_statement > 0) /* would divide the query into multiple commands and apply V3 parse requests for each of them */
			ret = PROTOCOL_74(ci) ? PARSE_REQ_FOR_INFO : PREPARE_BY_THE_DRIVER;
		else if (PROTOCOL_74(ci))
		{
			if (SC_may_use_cursor(stmt))
			{
				if (ci->drivers.use_declarefetch)
					return PARSE_REQ_FOR_INFO;
				else if (SQL_CURSOR_FORWARD_ONLY != stmt->options.cursor_type)
					ret = PARSE_REQ_FOR_INFO;
				else
					ret = PARSE_TO_EXEC_ONCE;
			}
			else
				ret = PARSE_TO_EXEC_ONCE;
		}
		else
		{
			if (SC_may_use_cursor(stmt) &&
			    (SQL_CURSOR_FORWARD_ONLY != stmt->options.cursor_type ||
			    ci->drivers.use_declarefetch))
				ret = PREPARE_BY_THE_DRIVER;
			else if (SC_is_prepare_statement(stmt))
				ret = USING_PREPARE_COMMAND;
			else
				ret = PREPARE_BY_THE_DRIVER;
		}
	}
	if (SC_is_prepare_statement(stmt) && (PARSE_TO_EXEC_ONCE == ret))
		ret = NAMED_PARSE_REQUEST;

	return ret;
}
Esempio n. 2
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';
}
Esempio n. 3
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;
}
Esempio n. 4
0
/*
 *	Read in field descriptions.
 *	If self is not null, then also store the information.
 *	If self is null, then just read, don't store.
 */
char
CI_read_fields(ColumnInfoClass *self, ConnectionClass *conn)
{
	CSTR		func = "CI_read_fields";
	Int2		lf;
	int			new_num_fields;
	OID		new_adtid, new_relid = 0, new_attid = 0;
	Int2		new_adtsize;
	Int4		new_atttypmod = -1;

	/* COLUMN_NAME_STORAGE_LEN may be sufficient but for safety */
	char		new_field_name[2 * COLUMN_NAME_STORAGE_LEN + 1];
	SocketClass *sock;
	ConnInfo   *ci;

	sock = CC_get_socket(conn);
	ci = &conn->connInfo;

	/* at first read in the number of fields that are in the query */
	new_num_fields = (Int2) SOCK_get_int(sock, sizeof(Int2));

	mylog("num_fields = %d\n", new_num_fields);

	if (self)
		/* according to that allocate memory */
		CI_set_num_fields(self, new_num_fields, PROTOCOL_74(ci));

	/* now read in the descriptions */
	for (lf = 0; lf < new_num_fields; lf++)
	{
		SOCK_get_string(sock, new_field_name, 2 * COLUMN_NAME_STORAGE_LEN);
		if (PROTOCOL_74(ci))	/* tableid & columnid */
		{
			new_relid = SOCK_get_int(sock, sizeof(Int4));
			new_attid = SOCK_get_int(sock, sizeof(Int2));
		}
		new_adtid = (OID) SOCK_get_int(sock, 4);
		new_adtsize = (Int2) SOCK_get_int(sock, 2);

		/* If 6.4 protocol, then read the atttypmod field */
		if (PG_VERSION_GE(conn, 6.4))
		{
			mylog("READING ATTTYPMOD\n");
			new_atttypmod = (Int4) SOCK_get_int(sock, 4);

			/* Subtract the header length */
			switch (new_adtid)
			{
				case PG_TYPE_DATETIME:
				case PG_TYPE_TIMESTAMP_NO_TMZONE:
				case PG_TYPE_TIME:
				case PG_TYPE_TIME_WITH_TMZONE:
					break;
				default:
					new_atttypmod -= 4;
			}
			if (new_atttypmod < 0)
				new_atttypmod = -1;
			if (PROTOCOL_74(ci))	/* format */
				SOCK_get_int(sock, sizeof(Int2));

		}

		mylog("%s: fieldname='%s', adtid=%d, adtsize=%d, atttypmod=%d (rel,att)=(%d,%d)\n", func, new_field_name, new_adtid, new_adtsize, new_atttypmod, new_relid, new_attid);

		if (self)
			CI_set_field_info(self, lf, new_field_name, new_adtid, new_adtsize, new_atttypmod, new_relid, new_attid);
	}

	return (SOCK_get_errcode(sock) == 0);
}