Esempio n. 1
0
static void add_projection_desc_httpheader(CHURL_HEADERS headers, ProjectionInfo *projInfo, List *qualsAttributes) {
    int i;
    char long_number[sizeof(int32) * 8];
    int *varNumbers = projInfo->pi_varNumbers;
    StringInfoData formatter;
    initStringInfo(&formatter);

    /* Convert the number of projection columns to a string */
    pg_ltoa(list_length(projInfo->pi_targetlist) + list_length(qualsAttributes), long_number);
    churl_headers_append(headers, "X-GP-ATTRS-PROJ", long_number);

    for(i = 0; i < list_length(projInfo->pi_targetlist); i++) {
        int number = varNumbers[i] - 1;
        pg_ltoa(number, long_number);
        resetStringInfo(&formatter);
        appendStringInfo(&formatter, "X-GP-ATTRS-PROJ-IDX");

        churl_headers_append(headers, formatter.data,long_number);
    }

	ListCell *attribute = NULL;

	foreach(attribute, qualsAttributes)
	{
		AttrNumber attrNumber = lfirst_int(attribute);

		pg_ltoa(attrNumber, long_number);
		resetStringInfo(&formatter);
		appendStringInfo(&formatter, "X-GP-ATTRS-PROJ-IDX");

		churl_headers_append(headers, formatter.data,long_number);
	}
Esempio n. 2
0
File: int.c Progetto: colinet/sqlix
/*
 *		int4out			- converts int4 to "num"
 */
datum_t int4out(PG_FUNC_ARGS)
{
	int32 arg1 = ARG_INT32(0);
	char *result = (char *)palloc(12);	/* sign, 10 digits, '\0' */

	pg_ltoa(arg1, result);
	RET_CSTRING(result);
}
Esempio n. 3
0
/*
 *		int4out			- converts int4 to "num"
 */
Datum
int4out(PG_FUNCTION_ARGS)
{
	int32		arg1 = PG_GETARG_INT32(0);
	char	   *result = (char *) palloc(12);	/* sign, 10 digits, '\0' */

	pg_ltoa(arg1, result);
	PG_RETURN_CSTRING(result);
}
Esempio n. 4
0
Datum
int4_text(PG_FUNCTION_ARGS)
{
	int32		arg1 = PG_GETARG_INT32(0);
	text	   *result = (text *) palloc(12 + VARHDRSZ);		/* sign,10 digits,'\0' */

	pg_ltoa(arg1, VARDATA(result));
	VARATT_SIZEP(result) = strlen(VARDATA(result)) + VARHDRSZ;
	PG_RETURN_TEXT_P(result);
}
Esempio n. 5
0
/* override port str with given new port int */
void port_to_str(char **port, int new_port)
{
	char tmp[10];

	if (!port)
		elog(ERROR, "unexpected internal error in pxfutils.c");
	if (*port)
		pfree(*port);

	Assert((new_port <= 65535) && (new_port >= 1)); /* legal port range */
	pg_ltoa(new_port, tmp);
	*port = pstrdup(tmp);
}
Esempio n. 6
0
Datum
int44out(PG_FUNCTION_ARGS)
{
	int32	   *an_array = (int32 *) PG_GETARG_POINTER(0);
	char	   *result = (char *) palloc(16 * 4);		/* Allow 14 digits +
														 * sign */
	int			i;
	char	   *walk;

	walk = result;
	for (i = 0; i < 4; i++)
	{
		pg_ltoa(an_array[i], walk);
		while (*++walk != '\0')
			;
		*walk++ = ' ';
	}
	*--walk = '\0';
	PG_RETURN_CSTRING(result);
}
Esempio n. 7
0
static int send_snmp_inform_or_trap(const GpErrorData * errorData, const char * subject, const char * severity)
{

	netsnmp_session session, *ss = NULL;
	netsnmp_pdu    *pdu, *response;
	int				status;
	char            csysuptime[20];
	static bool 	snmp_initialized = false;
	static char myhostname[255];	/* gethostname usually is limited to 65 chars out, but make this big to be safe */
	char	   *rawstring = NULL;
	List	   *elemlist = NIL;
	ListCell   *l = NULL;

	/*
	 * "inform" messages get a positive acknowledgement response from the SNMP manager.
	 * If it doesn't come, the message might be resent.
	 *
	 * "trap" messages are one-way, and we have no idea if the manager received it.
	 * But, it's faster and cheaper, and no need to retry.  So some people might prefer it.
	 */
	bool inform = strcmp(gp_snmp_use_inform_or_trap,"inform") == 0;


	if (gp_snmp_monitor_address == NULL || gp_snmp_monitor_address[0] == '\0')
	{
		static bool firsttime = 1;

		ereport(firsttime ? LOG : DEBUG1,(errmsg("SNMP inform/trap alerts are disabled")));
		firsttime = false;

		return -1;
	}


	/*
	 * SNMP managers are required to handle messages up to at least 484 bytes long, but I believe most existing
	 * managers support messages up to one packet (ethernet frame) in size, 1472 bytes.
	 *
	 * But, should we take that chance?  Or play it safe and limit the message to 484 bytes?
	 */

	elog(DEBUG2,"send_snmp_inform_or_trap");

	if (!snmp_initialized)
	{
		snmp_enable_stderrlog();

		if (gp_snmp_debug_log != NULL && gp_snmp_debug_log[0] != '\0')
		{
			snmp_enable_filelog(gp_snmp_debug_log, 1);

			//debug_register_tokens("ALL");
			snmp_set_do_debugging(1);
		}

		/*
		 * Initialize the SNMP library.  This also reads the MIB database.
		 */
		/* Add GPDB-MIB to the list to be loaded */
		putenv("MIBS=+GPDB-MIB:SNMP-FRAMEWORK-MIB:SNMPv2-CONF:SNMPv2-TC:SNMPv2-TC");

		init_snmp("sendalert");

		snmp_initialized = true;

		{
			char portnum[16];
			myhostname[0] = '\0';

			if (gethostname(myhostname, sizeof(myhostname)) == 0)
			{
				strcat(myhostname,":");
				pg_ltoa(PostPortNumber,portnum);
				strcat(myhostname,portnum);
			}
		}
	}

	/*
	 * Trap/Inform messages always start with the system up time. (SysUpTime.0)
	 *
	 * This presumably would be the uptime of GPDB, not the machine it is running on, I think.
	 *
	 * Use Postmaster's "MyStartTime" as a way to get that.
	 */

	sprintf(csysuptime, "%ld", (long)(time(NULL) - MyStartTime));


	/*
	// ERRCODE_DISK_FULL could be reported vi rbmsMIB rdbmsTraps rdbmsOutOfSpace trap.
	// But it appears we never generate that error?

	// ERRCODE_ADMIN_SHUTDOWN means SysAdmin aborted somebody's request.  Not interesting?

	// ERRCODE_CRASH_SHUTDOWN sounds interesting, but I don't see that we ever generate it.

	// ERRCODE_CANNOT_CONNECT_NOW means we are starting up, shutting down, in recovery, or Too many users are logged on.

	// abnormal database system shutdown
	*/



	/*
	 * The gpdbAlertSeverity is a crude attempt to classify some of these messages based on severity,
	 * where OK means everything is running normal, Down means everything is shut down, degraded would be
	 * for times when some segments are down, but the system is up, The others are maybe useful in the future
	 *
	 *  gpdbSevUnknown(0),
	 *	gpdbSevOk(1),
	 *	gpdbSevWarning(2),
	 *	gpdbSevError(3),
	 *	gpdbSevFatal(4),
	 *	gpdbSevPanic(5),
	 *	gpdbSevSystemDegraded(6),
	 *	gpdbSevSystemDown(7)
	 */


	char detail[MAX_ALERT_STRING+1];
	snprintf(detail, MAX_ALERT_STRING, "%s", errorData->error_detail);
	detail[127] = '\0';

	char sqlstmt[MAX_ALERT_STRING+1];
	char * sqlstmtp = errorData->debug_query_string;
	if (sqlstmtp == NULL || sqlstmtp[0] == '\0')
		sqlstmtp = errorData->internal_query;
	if (sqlstmtp == NULL)
		sqlstmtp = "";


	snprintf(sqlstmt, MAX_ALERT_STRING, "%s", sqlstmtp);
	sqlstmt[MAX_ALERT_STRING] = '\0';


	/* Need a modifiable copy of To list */
	rawstring = pstrdup(gp_snmp_monitor_address);

	/* Parse string into list of identifiers */
	if (!SplitMailString(rawstring, ',', &elemlist))
	{
		/* syntax error in list */
		ereport(LOG,
				(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
				 errmsg("invalid list syntax for \"gp_snmp_monitor_address\"")));
		return -1;
	}


	/*
	 * This session is just a template, and doesn't need to be connected.
	 * It is used by snmp_add(), which copies this info, opens the new session, and assigns the transport.
	 */
	snmp_sess_init( &session );	/* Initialize session to default values */
	session.version = SNMP_VERSION_2c;
	session.timeout = SNMP_DEFAULT_TIMEOUT;
	session.retries = SNMP_DEFAULT_RETRIES;
	session.remote_port = 162; 							// I think this isn't used by net-snmp any more.

	/*if (strchr(session.peername,':')==NULL)
		strcat(session.peername,":162");*/
	session.community = (u_char *)gp_snmp_community;
	session.community_len = strlen((const char *)session.community);  // SNMP_DEFAULT_COMMUNITY_LEN means "public"
	session.callback_magic = NULL;

	foreach(l, elemlist)
	{
		char	   *cur_gp_snmp_monitor_address = (char *) lfirst(l);

		if (cur_gp_snmp_monitor_address == NULL || cur_gp_snmp_monitor_address[0] == '\0')
			continue;

		session.peername = cur_gp_snmp_monitor_address;
		/*
		 * If we try to "snmp_open( &session )", net-snmp will set up a connection to that
		 * endpoint on port 161, assuming we are the network monitor, and the other side is an agent.
		 *
		 * But we are pretending to be an agent, sending traps to the NM, so we don't need this.
		 */

		/*if (!snmp_open( &session ))   	// Don't open the session here!
		{
			const char     *str;
			int             xerr;
			xerr = snmp_errno;
			str = snmp_api_errstring(xerr);
			elog(LOG, "snmp_open: %s", str);
			return -1;
		}*/

		/*
		 * This call copies the info from "session" to "ss", assigns the transport, and opens the session.
		 * We must specify "snmptrap" so the transport will know we want port 162 by default.
		 */
		ss = snmp_add(&session,
					  netsnmp_transport_open_client("snmptrap", cur_gp_snmp_monitor_address),
					  NULL, NULL);
		if (ss == NULL) {
			/*
			 * diagnose netsnmp_transport_open_client and snmp_add errors with
			 * the input netsnmp_session pointer
			 */
			{
				char           *err;
				snmp_error(&session, NULL, NULL, &err);
				elog(LOG, "send_alert snmp_add of %s failed: %s", cur_gp_snmp_monitor_address, err);
				free(err);
			}
			return -1;
		}

		/*
		 * We need to create the pdu each time, as it gets freed when we send a trap.
		 */
		pdu = snmp_pdu_create(inform ? SNMP_MSG_INFORM : SNMP_MSG_TRAP2);
		if (!pdu)
		{
			const char     *str;
			int             xerr;
			xerr = snmp_errno;
			str = snmp_api_errstring(xerr);
			elog(LOG, "Failed to create notification PDU: %s", str);
			return -1;
		}

		/*
		 * Trap/Inform messages always start with the system up time. (SysUpTime.0)
		 * We use Postmaster's "MyStartTime" as a way to get that.
		 */

		snmp_add_var(pdu, objid_sysuptime,
							sizeof(objid_sysuptime) / sizeof(oid),
							't', (const char *)csysuptime);

	#if 0
		/*
		 * In the future, we might want to send RDBMS-MIB::rdbmsStateChange when the system becomes unavailable or
		 * partially unavailable.  This code, which is not currently used, shows how to build the pdu for
		 * that trap.
		 */
		/* {iso(1) identified-organization(3) dod(6) internet(1) mgmt(2) mib-2(1) rdbmsMIB(39) rdbmsTraps(2) rdbmsStateChange(1)} */
		snmp_add_var(pdu, objid_snmptrap,
							sizeof(objid_snmptrap) / sizeof(oid),
							'o', "1.3.6.1.2.1.39.2.1");  // rdbmsStateChange


		snmp_add_var(pdu, objid_rdbmsrelstate,
							sizeof(objid_rdbmsrelstate) / sizeof(oid),
							'i', "5");  // 4 = restricted, 5 = unavailable
	#endif

		/* {iso(1) identified-organization(3) dod(6) internet(1) private(4) enterprises(1) gpdbMIB(31327) gpdbTraps(5) gpdbTrapsList(0) gpdbAlert(1)} */

		/*
		 * We could specify this trap oid by name, rather than numeric oid, but then if the GPDB-MIB wasn't
		 * found, we'd get an error.  Using the numeric oid means we can still work without the MIB loaded.
		 */
		snmp_add_var(pdu, objid_snmptrap,
							sizeof(objid_snmptrap) / sizeof(oid),
							'o', "1.3.6.1.4.1.31327.5.0.1");  // gpdbAlert


		snmp_add_var(pdu, objid_gpdbAlertMsg,
							sizeof(objid_gpdbAlertMsg) / sizeof(oid),
							's', subject);  // SnmpAdminString = UTF-8 text
		snmp_add_var(pdu, objid_gpdbAlertSeverity,
							sizeof(objid_gpdbAlertSeverity) / sizeof(oid),
							'i', (char *)severity);

		snmp_add_var(pdu, objid_gpdbAlertSqlstate,
							sizeof(objid_gpdbAlertSqlstate) / sizeof(oid),
							's', errorData->sql_state);

		snmp_add_var(pdu, objid_gpdbAlertDetail,
							sizeof(objid_gpdbAlertDetail) / sizeof(oid),
							's', detail); // SnmpAdminString = UTF-8 text

		snmp_add_var(pdu, objid_gpdbAlertSqlStmt,
							sizeof(objid_gpdbAlertSqlStmt) / sizeof(oid),
							's', sqlstmt); // SnmpAdminString = UTF-8 text

		snmp_add_var(pdu, objid_gpdbAlertSystemName,
							sizeof(objid_gpdbAlertSystemName) / sizeof(oid),
							's', myhostname); // SnmpAdminString = UTF-8 text



		elog(DEBUG2,"ready to send to %s",cur_gp_snmp_monitor_address);
		if (inform)
			status = snmp_synch_response(ss, pdu, &response);
		else
			status = snmp_send(ss, pdu) == 0;

		elog(DEBUG2,"send, status %d",status);
		if (status != STAT_SUCCESS)
		{
			/* Something went wrong */
			if (ss)
			{
				char           *err;
				snmp_error(ss, NULL, NULL, &err);
				elog(LOG, "sendalert failed to send %s: %s", inform ? "inform" : "trap", err);
				free(err);
			}
			else
			{
				elog(LOG, "sendalert failed to send %s: %s", inform ? "inform" : "trap", "Something went wrong");
			}
			if (!inform)
				snmp_free_pdu(pdu);
		}
		else if (inform)
			snmp_free_pdu(response);

		snmp_close(ss);
		ss = NULL;

	}
Esempio n. 8
0
void
test_build_http_headers(void **state)
{

	/* setup mock data and expectations */
	PxfInputData *input = (PxfInputData *) palloc0(sizeof(PxfInputData));
	CHURL_HEADERS headers = (CHURL_HEADERS) palloc0(sizeof(CHURL_HEADERS));
	GPHDUri    *gphd_uri = (GPHDUri *) palloc0(sizeof(GPHDUri));
	Relation	rel = (Relation) palloc0(sizeof(RelationData));

	ExtTableEntry ext_tbl;
	struct tupleDesc tuple;

	input->headers = headers;
	input->gphduri = gphd_uri;
	input->rel = rel;

	gphd_uri->host = "testhost";
	gphd_uri->port = "101";
	gphd_uri->data = "this is test data";
	gphd_uri->uri = "testuri";

	OptionData *option_data1 = (OptionData *) palloc0(sizeof(OptionData));

	option_data1->key = "option1-key";
	option_data1->value = "option1-value";
	OptionData *option_data2 = (OptionData *) palloc0(sizeof(OptionData));

	option_data2->key = "option2-key";
	option_data2->value = "option2-value";
	gphd_uri->options = list_make2(option_data1, option_data2);

	tuple.natts = 0;
	ext_tbl.fmtcode = 'c';
	rel->rd_id = 56;
	rel->rd_att = &tuple;

	expect_value(GetExtTableEntry, relid, rel->rd_id);
	will_return(GetExtTableEntry, &ext_tbl);
	expect_headers_append(headers, "X-GP-FORMAT", TextFormatName);
	expect_headers_append(headers, "X-GP-ATTRS", "0");

	expect_any(external_set_env_vars, extvar);
	expect_string(external_set_env_vars, uri, gphd_uri->uri);
	expect_value(external_set_env_vars, csv, false);
	expect_value(external_set_env_vars, escape, NULL);
	expect_value(external_set_env_vars, quote, NULL);
	expect_value(external_set_env_vars, header, false);
	expect_value(external_set_env_vars, scancounter, 0);

	struct extvar_t mock_extvar;
	mock_extvar.GP_USER = "******";
	snprintf(mock_extvar.GP_SEGMENT_ID, sizeof(mock_extvar.GP_SEGMENT_ID), "SegId");
	snprintf(mock_extvar.GP_SEGMENT_COUNT, sizeof(mock_extvar.GP_SEGMENT_COUNT), "10");
	snprintf(mock_extvar.GP_XID, sizeof(mock_extvar.GP_XID), "20");
	will_assign_memory(external_set_env_vars, extvar, &mock_extvar, sizeof(extvar_t));
	will_be_called(external_set_env_vars);

	expect_headers_append(headers, "X-GP-USER", "user");
	expect_headers_append(headers, "X-GP-SEGMENT-ID", "SegId");
	expect_headers_append(headers, "X-GP-SEGMENT-COUNT", "10");
	expect_headers_append(headers, "X-GP-XID", "20");

	char		alignment[3];

	pg_ltoa(sizeof(char *), alignment);
	expect_headers_append(headers, "X-GP-ALIGNMENT", alignment);
	expect_headers_append(headers, "X-GP-URL-HOST", gphd_uri->host);
	expect_headers_append(headers, "X-GP-URL-PORT", gphd_uri->port);
	expect_headers_append(headers, "X-GP-DATA-DIR", gphd_uri->data);


	expect_string(normalize_key_name, key, "option1-key");
	will_return(normalize_key_name, pstrdup("X-GP-OPTION1-KEY"));
	expect_headers_append(headers, "X-GP-OPTION1-KEY", "option1-value");

	expect_string(normalize_key_name, key, "option2-key");
	will_return(normalize_key_name, pstrdup("X-GP-OPTION2-KEY"));
	expect_headers_append(headers, "X-GP-OPTION2-KEY", "option2-value");

	expect_headers_append(headers, "X-GP-URI", gphd_uri->uri);
	expect_headers_append(headers, "X-GP-HAS-FILTER", "0");

	/* call function under test */
	build_http_headers(input);

	/* no asserts as the function just calls to set headers */

	/* cleanup */
	pfree(rel);
	pfree(gphd_uri);
	pfree(headers);
	pfree(input);
}
Esempio n. 9
0
void
test_add_tuple_desc_httpheader(void **state)
{

	/* setup mock data and expectations */
	CHURL_HEADERS headers = (CHURL_HEADERS) palloc0(sizeof(CHURL_HEADERS));
	Relation	rel = (Relation) palloc0(sizeof(RelationData));

	struct tupleDesc tuple;

	tuple.natts = 4;
	rel->rd_id = 56;
	rel->rd_att = &tuple;
	expect_headers_append(headers, "X-GP-ATTRS", "4");

	FormData_pg_attribute attrs[4];
	Form_pg_attribute attrs_ptr[4];

	tuple.attrs = attrs_ptr;

	/* define first attribute */
	attrs_ptr[0] = &attrs[0];
	char		data0[10] = "name0";

	snprintf(NameStr(attrs[0].attname), sizeof(data0), data0);
	char		typename0[12] = "NUMERICOID";

	attrs[0].atttypid = NUMERICOID;
	attrs[0].atttypmod = 10;
	char		typecode0[10];

	pg_ltoa(attrs[0].atttypid, typecode0);
	expect_value(TypeOidGetTypename, typid, NUMERICOID);
	will_return(TypeOidGetTypename, &typename0);
	expect_headers_append(headers, "X-GP-ATTR-NAME0", data0);
	expect_headers_append(headers, "X-GP-ATTR-TYPECODE0", typecode0);
	expect_headers_append(headers, "X-GP-ATTR-TYPENAME0", typename0);
	expect_headers_append(headers, "X-GP-ATTR-TYPEMOD0-COUNT", "2");
	char		typemod00[10];

	pg_ltoa((attrs[0].atttypmod >> 16) & 0xffff, typemod00);
	expect_headers_append(headers, "X-GP-ATTR-TYPEMOD0-0", typemod00);
	char		typemod01[10];

	pg_ltoa((attrs[0].atttypmod - VARHDRSZ) & 0xffff, typemod01);
	expect_headers_append(headers, "X-GP-ATTR-TYPEMOD0-1", typemod01);

	/* define second attribute */
	attrs_ptr[1] = &attrs[1];
	char		data1[10] = "name1";

	snprintf(NameStr(attrs[1].attname), sizeof(data1), data1);
	char		typename1[12] = "CHAROID";

	attrs[1].atttypid = CHAROID;
	attrs[1].atttypmod = 10;
	char		typecode1[10];

	pg_ltoa(attrs[1].atttypid, typecode1);
	expect_value(TypeOidGetTypename, typid, CHAROID);
	will_return(TypeOidGetTypename, &typename1);
	expect_headers_append(headers, "X-GP-ATTR-NAME1", data1);
	expect_headers_append(headers, "X-GP-ATTR-TYPECODE1", typecode1);
	expect_headers_append(headers, "X-GP-ATTR-TYPENAME1", typename1);
	expect_headers_append(headers, "X-GP-ATTR-TYPEMOD1-COUNT", "1");
	char		typemod10[10];

	pg_ltoa((attrs[1].atttypmod - VARHDRSZ), typemod10);
	expect_headers_append(headers, "X-GP-ATTR-TYPEMOD1-0", typemod10);

	/* define third attribute */
	attrs_ptr[2] = &attrs[2];
	char		data2[10] = "name2";

	snprintf(NameStr(attrs[2].attname), sizeof(data2), data2);
	char		typename2[12] = "TIMEOID";

	attrs[2].atttypid = TIMEOID;
	attrs[2].atttypmod = 10;
	char		typecode2[10];

	pg_ltoa(attrs[2].atttypid, typecode2);
	expect_value(TypeOidGetTypename, typid, TIMEOID);
	will_return(TypeOidGetTypename, &typename2);
	expect_headers_append(headers, "X-GP-ATTR-NAME2", data2);
	expect_headers_append(headers, "X-GP-ATTR-TYPECODE2", typecode2);
	expect_headers_append(headers, "X-GP-ATTR-TYPENAME2", typename2);
	expect_headers_append(headers, "X-GP-ATTR-TYPEMOD2-COUNT", "1");
	char		typemod20[10];

	pg_ltoa(attrs[2].atttypmod, typemod20);
	expect_headers_append(headers, "X-GP-ATTR-TYPEMOD2-0", typemod20);

	/* define fourth attribute */
	attrs_ptr[3] = &attrs[3];
	char		data3[10] = "name3";

	snprintf(NameStr(attrs[3].attname), sizeof(data3), data3);
	char		typename3[12] = "INTERVALOID";

	attrs[3].atttypid = INTERVALOID;
	attrs[3].atttypmod = 10;
	char		typecode3[10];

	pg_ltoa(attrs[3].atttypid, typecode3);
	expect_value(TypeOidGetTypename, typid, INTERVALOID);
	will_return(TypeOidGetTypename, &typename3);
	expect_headers_append(headers, "X-GP-ATTR-NAME3", data3);
	expect_headers_append(headers, "X-GP-ATTR-TYPECODE3", typecode3);
	expect_headers_append(headers, "X-GP-ATTR-TYPENAME3", typename3);
	expect_headers_append(headers, "X-GP-ATTR-TYPEMOD3-COUNT", "1");
	char		typemod30[10];

	pg_ltoa(INTERVAL_PRECISION(attrs[3].atttypmod), typemod30);
	expect_headers_append(headers, "X-GP-ATTR-TYPEMOD3-0", typemod30);

	/* call function under test */
	add_tuple_desc_httpheader(headers, rel);

	/* no asserts as the function just calls to set headers */

	/* cleanup */
	pfree(rel);
	pfree(headers);
}
Esempio n. 10
0
/*
 * pg_itoa: converts a signed 16-bit integer to its string representation
 *
 * Caller must ensure that 'a' points to enough memory to hold the result
 * (at least 7 bytes, counting a leading sign and trailing NUL).
 *
 * It doesn't seem worth implementing this separately.
 */
void
pg_itoa(int16 i, char *a)
{
	pg_ltoa((int32) i, a);
}
Esempio n. 11
0
/* 
 * Report tuple description to remote component 
 * Currently, number of attributes, attributes names, types and types modifiers
 * Each attribute has a pair of key/value 
 * where X is the number of the attribute
 * X-GP-ATTR-NAMEX - attribute X's name 
 * X-GP-ATTR-TYPECODEX - attribute X's type OID (e.g, 16)
 * X-GP-ATTR-TYPENAMEX - attribute X's type name (e.g, "boolean")
 * optional - X-GP-ATTR-TYPEMODX-COUNT - total number of modifier for attribute X
 * optional - X-GP-ATTR-TYPEMODX-Y - attribute X's modifiers Y (types which have precision info, like numeric(p,s))
 */
static void add_tuple_desc_httpheader(CHURL_HEADERS headers, Relation rel)
{	
    char long_number[INT32_CHAR_SIZE];
    StringInfoData formatter;	
    TupleDesc tuple;		
    initStringInfo(&formatter);
	
    /* Get tuple description itself */	
    tuple = RelationGetDescr(rel);	
	
    /* Convert the number of attributes to a string */	
    pg_ltoa(tuple->natts, long_number);	
    churl_headers_append(headers, "X-GP-ATTRS", long_number);
	
    /* Iterate attributes */	
    for (int i = 0; i < tuple->natts; ++i)		
    {		
        /* Add a key/value pair for attribute name */		
        resetStringInfo(&formatter);		
        appendStringInfo(&formatter, "X-GP-ATTR-NAME%u", i);		
        churl_headers_append(headers, formatter.data, tuple->attrs[i]->attname.data);
		
		/* Add a key/value pair for attribute type */		
        resetStringInfo(&formatter);		
        appendStringInfo(&formatter, "X-GP-ATTR-TYPECODE%u", i);
        pg_ltoa(tuple->attrs[i]->atttypid, long_number);		
        churl_headers_append(headers, formatter.data, long_number);

        /* Add a key/value pair for attribute type name */
        resetStringInfo(&formatter);
        appendStringInfo(&formatter, "X-GP-ATTR-TYPENAME%u", i);
        churl_headers_append(headers, formatter.data, TypeOidGetTypename(tuple->attrs[i]->atttypid));

		/* Add attribute type modifiers if any*/
		if (tuple->attrs[i]->atttypmod > -1)
		{
			switch (tuple->attrs[i]->atttypid)
			{
				case NUMERICOID:
				{
					resetStringInfo(&formatter);
					appendStringInfo(&formatter, "X-GP-ATTR-TYPEMOD%u-COUNT", i);
					pg_ltoa(2, long_number);
					churl_headers_append(headers, formatter.data, long_number);


					/* precision */
					resetStringInfo(&formatter);
					appendStringInfo(&formatter, "X-GP-ATTR-TYPEMOD%u-%u", i, 0);
					pg_ltoa((tuple->attrs[i]->atttypmod >> 16) & 0xffff, long_number);
					churl_headers_append(headers, formatter.data, long_number);

					/* scale */
					resetStringInfo(&formatter);
					appendStringInfo(&formatter, "X-GP-ATTR-TYPEMOD%u-%u", i, 1);
					pg_ltoa((tuple->attrs[i]->atttypmod - VARHDRSZ) & 0xffff, long_number);
					churl_headers_append(headers, formatter.data, long_number);
					break;
				}
				case CHAROID:
				case BPCHAROID:
				case VARCHAROID:
				{
					resetStringInfo(&formatter);
					appendStringInfo(&formatter, "X-GP-ATTR-TYPEMOD%u-COUNT", i);
					pg_ltoa(1, long_number);
					churl_headers_append(headers, formatter.data, long_number);

					resetStringInfo(&formatter);
					appendStringInfo(&formatter, "X-GP-ATTR-TYPEMOD%u-%u", i, 0);
					pg_ltoa((tuple->attrs[i]->atttypmod - VARHDRSZ), long_number);
					churl_headers_append(headers, formatter.data, long_number);
					break;
				}
				case VARBITOID:
				case BITOID:
				case TIMESTAMPOID:
				case TIMESTAMPTZOID:
				case TIMEOID:
				case TIMETZOID:
				{
					resetStringInfo(&formatter);
					appendStringInfo(&formatter, "X-GP-ATTR-TYPEMOD%u-COUNT", i);
					pg_ltoa(1, long_number);
					churl_headers_append(headers, formatter.data, long_number);

					resetStringInfo(&formatter);
					appendStringInfo(&formatter, "X-GP-ATTR-TYPEMOD%u-%u", i, 0);
					pg_ltoa((tuple->attrs[i]->atttypmod), long_number);
					churl_headers_append(headers, formatter.data, long_number);
					break;
				}
				case INTERVALOID:
				{
					resetStringInfo(&formatter);
					appendStringInfo(&formatter, "X-GP-ATTR-TYPEMOD%u-COUNT", i);
					pg_ltoa(1, long_number);
					churl_headers_append(headers, formatter.data, long_number);

					resetStringInfo(&formatter);
					appendStringInfo(&formatter, "X-GP-ATTR-TYPEMOD%u-%u", i, 0);
					pg_ltoa(INTERVAL_PRECISION(tuple->attrs[i]->atttypmod), long_number);
					churl_headers_append(headers, formatter.data, long_number);
					break;
				}
				default:
					elog(DEBUG5, "add_tuple_desc_httpheader: unsupported type %d ", tuple->attrs[i]->atttypid);
					break;
			}
		}
	}
	
	pfree(formatter.data);
}
Esempio n. 12
0
/* Report alignment size to remote component
 * GPDBWritable uses alignment that has to be the same as
 * in the C code. 
 * Since the C code can be compiled for both 32 and 64 bits, 
 * the alignment can be either 4 or 8. 
 */
static void add_alignment_size_httpheader(CHURL_HEADERS headers)
{	
    char tmp[sizeof(char*)];	
    pg_ltoa(sizeof(char*), tmp);	
    churl_headers_append(headers, "X-GP-ALIGNMENT", tmp);	
}