Beispiel #1
0
Datum
RestorePlanDXL(PG_FUNCTION_ARGS)
{
	char *szXmlString = text_to_cstring(PG_GETARG_TEXT_P(0));

	int iProcessed = executeXMLPlan(szXmlString);

	StringInfoData str;
	initStringInfo(&str);
	appendStringInfo(&str, "processed %d rows", iProcessed);

	text *ptResult = cstring_to_text(str.data);

	PG_RETURN_TEXT_P(ptResult);
}
Beispiel #2
0
Datum
DumpQuery(PG_FUNCTION_ARGS)
{
	char *szSqlText = text_to_cstring(PG_GETARG_TEXT_P(0));

	Query *pquery = parseSQL(szSqlText);
	elog(NOTICE, "(DumpQuery - Original) \n %s", pretty_format_node_dump(const_cast<char*>(gpdb::SzNodeToString(pquery))));

	Query *pqueryNormalized = preprocess_query_optimizer(pquery, NULL);
	elog(NOTICE, "(DumpQuery - Normalized) \n %s", pretty_format_node_dump(const_cast<char*>(gpdb::SzNodeToString(pqueryNormalized))));

	text *ptResult = cstring_to_text("Query dumped");

	PG_RETURN_TEXT_P(ptResult);
}
Beispiel #3
0
Datum
orafce_to_char_numeric(PG_FUNCTION_ARGS)
{
	Numeric		arg0 = PG_GETARG_NUMERIC(0);
	StringInfo	buf = makeStringInfo();
	struct lconv *lconv = PGLC_localeconv();
	char	   *p;

	appendStringInfoString(buf, DatumGetCString(DirectFunctionCall1(numeric_out, NumericGetDatum(arg0))));

	for (p = buf->data; *p; p++)
		if (*p == '.')
			*p = lconv->decimal_point[0];

	PG_RETURN_TEXT_P(cstring_to_text(buf->data));
}
Beispiel #4
0
/*
 * timeofday -
 *	   returns the current time as a text. similar to timenow() but returns
 *	   seconds with more precision (up to microsecs). (I need this to compare
 *	   the Wisconsin benchmark with Illustra whose TimeNow() shows current
 *	   time with precision up to microsecs.)			  - ay 3/95
 */
Datum
timeofday(PG_FUNCTION_ARGS)
{
	struct timeval tp;
	char		templ[128];
	char		buf[128];
	pg_time_t	tt;

	gettimeofday(&tp, NULL);
	tt = (pg_time_t) tp.tv_sec;
	pg_strftime(templ, sizeof(templ), "%a %b %d %H:%M:%S.%%06d %Y %Z",
				pg_localtime(&tt, session_timezone));
	snprintf(buf, sizeof(buf), templ, tp.tv_usec);

	PG_RETURN_TEXT_P(cstring_to_text(buf));
}
Beispiel #5
0
/*
 * dbms_random.string(opt IN CHAR, len IN NUMBER) RETURN VARCHAR2;
 * 
 *     Create Random Strings
 * opt seed values:
 * 'a','A'  alpha characters only (mixed case)
 * 'l','L'  lower case alpha characters only
 * 'p','P'  any printable characters
 * 'u','U'  upper case alpha characters only
 * 'x','X'  any alpha-numeric characters (upper)
 */
static text *
random_string(const char *charset, int chrset_size, int len)
{
	StringInfo	str;
	int	i;
	
	str = makeStringInfo();
	for (i = 0; i < len; i++)
	{
		int pos = (double) rand() / ((double) RAND_MAX + 1) * chrset_size;
		
		appendStringInfoChar(str, charset[pos]);
	}
	
	return cstring_to_text(str->data);
}
Beispiel #6
0
Datum pcpoint_as_text(PG_FUNCTION_ARGS)
{
	SERIALIZED_POINT *serpt = PG_GETARG_SERPOINT_P(0);
	text *txt;
	char *str;
	PCSCHEMA *schema = pc_schema_from_pcid(serpt->pcid, fcinfo);
	PCPOINT *pt = pc_point_deserialize(serpt, schema);
	if ( ! pt )
		PG_RETURN_NULL();

	str = pc_point_to_string(pt);
	pc_point_free(pt);
	txt = cstring_to_text(str);
	pfree(str);
	PG_RETURN_TEXT_P(txt);
}
Beispiel #7
0
Datum
orafce_to_char_timestamp(PG_FUNCTION_ARGS)
{
	Timestamp date_txt = PG_GETARG_TIMESTAMP(0);
	text *result = NULL;

	if(nls_date_format && strlen(nls_date_format))
	{
		/* it will return the DATE in nls_date_format*/
		result = DatumGetTextP(DirectFunctionCall2(timestamp_to_char,
							CStringGetDatum(date_txt),
								CStringGetDatum(cstring_to_text(nls_date_format))));
	}

	PG_RETURN_TEXT_P(result);
}
Beispiel #8
0
/*
 * returns src in case of no conversion or error
 */
static text *
convert_charset(text *src, int cset_from, int cset_to)
{
	int			src_len = VARSIZE(src) - VARHDRSZ;
	unsigned char *dst;
	unsigned char *csrc = (unsigned char *) VARDATA(src);
	text	   *res;

	dst = pg_do_encoding_conversion(csrc, src_len, cset_from, cset_to);
	if (dst == csrc)
		return src;

	res = cstring_to_text((char *) dst);
	pfree(dst);
	return res;
}
Beispiel #9
0
Datum pcpatch_as_text(PG_FUNCTION_ARGS)
{
	SERIALIZED_PATCH *serpatch = PG_GETARG_SERPATCH_P(0);
	text *txt;
	char *str;
	PCSCHEMA *schema = pc_schema_from_pcid(serpatch->pcid, fcinfo);
	PCPATCH *patch = pc_patch_deserialize(serpatch, schema);
	if ( ! patch )
		PG_RETURN_NULL();

	str = pc_patch_to_string(patch);
	pc_patch_free(patch);
	txt = cstring_to_text(str);
	pfree(str);
	PG_RETURN_TEXT_P(txt);
}
Beispiel #10
0
Datum
orafce_to_char_float8(PG_FUNCTION_ARGS)
{
	float8		arg0 = PG_GETARG_FLOAT8(0);
	StringInfo	buf = makeStringInfo();
	struct lconv *lconv = PGLC_localeconv();
	char	   *p;

	appendStringInfo(buf, "%f", arg0);

	for (p = buf->data; *p; p++)
		if (*p == '.')
			*p = lconv->decimal_point[0];

	PG_RETURN_TEXT_P(cstring_to_text(buf->data));
}
Beispiel #11
0
/*
 * SQL function jsonb_typeof(jsonb) -> text
 *
 * This function is here because the analog json function is in json.c, since
 * it uses the json parser internals not exposed elsewhere.
 */
Datum
jsonb_typeof(PG_FUNCTION_ARGS)
{
	Jsonb	   *in = PG_GETARG_JSONB(0);
	JsonbIterator *it;
	JsonbValue	v;
	char	   *result;

	if (JB_ROOT_IS_OBJECT(in))
		result = "object";
	else if (JB_ROOT_IS_ARRAY(in) && !JB_ROOT_IS_SCALAR(in))
		result = "array";
	else
	{
		Assert(JB_ROOT_IS_SCALAR(in));

		it = JsonbIteratorInit(VARDATA_ANY(in));

		/*
		 * A root scalar is stored as an array of one element, so we get the
		 * array and then its first (and only) member.
		 */
		(void) JsonbIteratorNext(&it, &v, true);
		Assert(v.type == jbvArray);
		(void) JsonbIteratorNext(&it, &v, true);
		switch (v.type)
		{
			case jbvNull:
				result = "null";
				break;
			case jbvString:
				result = "string";
				break;
			case jbvNumeric:
				result = "number";
				break;
			case jbvBool:
				result = "boolean";
				break;
			default:
				elog(ERROR, "unknown jsonb scalar type");
		}
	}

	PG_RETURN_TEXT_P(cstring_to_text(result));
}
Beispiel #12
0
Datum
DumpQueryDXL(PG_FUNCTION_ARGS)
{
	char *szSqlText = text_to_cstring(PG_GETARG_TEXT_P(0));

	Query *pquery = parseSQL(szSqlText);

	Assert(pquery);

	char *szXmlString = COptTasks::SzDXL(pquery);
	if (NULL == szXmlString)
	{
		elog(ERROR, "Error translating query to DXL");
	}

	PG_RETURN_TEXT_P(cstring_to_text(szXmlString));
}
Beispiel #13
0
/*
 * pg_start_backup: set up for taking an on-line backup dump
 *
 * Essentially what this does is to create a backup label file in $PGDATA,
 * where it will be archived as part of the backup dump.  The label file
 * contains the user-supplied label string (typically this would be used
 * to tell where the backup dump will be stored) and the starting time and
 * starting WAL location for the dump.
 */
Datum
pg_start_backup(PG_FUNCTION_ARGS)
{
	text	   *backupid = PG_GETARG_TEXT_P(0);
	bool		fast = PG_GETARG_BOOL(1);
	char	   *backupidstr;
	XLogRecPtr	startpoint;
	char		startxlogstr[MAXFNAMELEN];

	backupidstr = text_to_cstring(backupid);

	startpoint = do_pg_start_backup(backupidstr, fast, NULL);

	snprintf(startxlogstr, sizeof(startxlogstr), "%X/%X",
			 startpoint.xlogid, startpoint.xrecoff);
	PG_RETURN_TEXT_P(cstring_to_text(startxlogstr));
}
Beispiel #14
0
/*
 * Equivalent of X509_NAME_oneline that respects encoding
 *
 * This function converts X509_NAME structure to the text variable
 * converting all textual data into current database encoding.
 *
 * Parameter: X509_NAME *name X509_NAME structure to be converted
 *
 * Returns: text datum which contains string representation of
 * X509_NAME
 */
datum_t
X509_NAME_to_text(X509_NAME *name)
{
	BIO		   *membuf = BIO_new(BIO_s_mem());
	int			i,
				nid,
				count = X509_NAME_entry_count(name);
	X509_NAME_ENTRY *e;
	ASN1_STRING *v;
	const char *field_name;
	size_t		size;
	char		nullterm;
	char	   *sp;
	char	   *dp;
	text	   *result;

	(void) BIO_set_close(membuf, BIO_CLOSE);
	for (i = 0; i < count; i++)
	{
		e = X509_NAME_get_entry(name, i);
		nid = OBJ_obj2nid(X509_NAME_ENTRY_get_object(e));
		v = X509_NAME_ENTRY_get_data(e);
		field_name = OBJ_nid2sn(nid);
		if (!field_name)
			field_name = OBJ_nid2ln(nid);
		BIO_printf(membuf, "/%s=", field_name);
		ASN1_STRING_print_ex(membuf, v,
							 ((ASN1_STRFLGS_RFC2253 & ~ASN1_STRFLGS_ESC_MSB)
							  | ASN1_STRFLGS_UTF8_CONVERT));
	}

	/* ensure null termination of the BIO's content */
	nullterm = '\0';
	BIO_write(membuf, &nullterm, 1);
	size = BIO_get_mem_data(membuf, &sp);
	dp = (char *) pg_do_encoding_conversion((unsigned char *) sp,
											size - 1,
											PG_UTF8,
											get_db_encoding());
	result = cstring_to_text(dp);
	if (dp != sp)
		pfree(dp);
	BIO_free(membuf);

	RET_TEXT_P(result);
}
Beispiel #15
0
/*
 * json_agg final function
 */
Datum
json_agg_finalfn(PG_FUNCTION_ARGS)
{
	StringInfo	state;

	/* cannot be called directly because of internal-type argument */
	Assert(AggCheckCallContext(fcinfo, NULL));

	state = PG_ARGISNULL(0) ? NULL : (StringInfo) PG_GETARG_POINTER(0);

	if (state == NULL)
		PG_RETURN_NULL();

	appendStringInfoChar(state, ']');

	PG_RETURN_TEXT_P(cstring_to_text(state->data));
}
Beispiel #16
0
Datum
plvchr_char_name(PG_FUNCTION_ARGS)
{
	text *str = PG_GETARG_TEXT_PP(0);
	text *result;
	unsigned char c;

	NON_EMPTY_CHECK(str);
	c = (unsigned char)*(VARDATA_ANY(str));

	if (c >= lengthof(char_names))
		result = ora_substr_text(str, 1, 1);
	else
		result = cstring_to_text(char_names[c]);

	PG_RETURN_TEXT_P(result);
}
Beispiel #17
0
Datum
s3test(PG_FUNCTION_ARGS)
{
	CURL		   *curl;
	StringInfoData	buf;
	int				sc;
	char		   *url;
	char			tmp[1024];
	struct curl_slist *slist;
	char		   *datestring;
	char		   *signature;

	char		   *bucket = "umitanuki-dbtest";
	char		   *file = "1.txt";
	char		   *host = "s3-ap-northeast-1.amazonaws.com";

	char		   *accesskey = "";
	char		   *secretkey = "";

	url = text_to_cstring(PG_GETARG_TEXT_P(0));

	url = palloc0(1024);
	snprintf(url, 1024, "http://%s/%s/%s", host, bucket, file);
	datestring = httpdate(NULL);
	signature = s3_signature("GET", datestring, bucket, file, secretkey);

	slist = NULL;
	snprintf(tmp, sizeof(tmp), "Date: %s", datestring);
	slist = curl_slist_append(slist, tmp);
	snprintf(tmp, sizeof(tmp), "Authorization: AWS %s:%s", accesskey, signature);
	slist = curl_slist_append(slist, tmp);
	initStringInfo(&buf);

	curl = curl_easy_init();
	curl_easy_setopt(curl, CURLOPT_HTTPHEADER, slist);
	curl_easy_setopt(curl, CURLOPT_URL, url);
	curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data_to_buf);
	curl_easy_setopt(curl, CURLOPT_WRITEDATA, &buf);

	sc = curl_easy_perform(curl);

	curl_easy_cleanup(curl);

	PG_RETURN_TEXT_P(cstring_to_text(buf.data));
}
Beispiel #18
0
Datum
RestoreQuery(PG_FUNCTION_ARGS)
{
	bytea   *pbyteaData = PG_GETARG_BYTEA_P(0);

	char   *pcSerializedData = VARDATA(pbyteaData);

	int iProcessed = extractFrozenQueryPlanAndExecute(pcSerializedData);

	elog(NOTICE, "(RestorePlan) PROCESSED %d", iProcessed);
	StringInfoData str;
	initStringInfo(&str);

	appendStringInfo(&str, "Query processed %d rows", iProcessed);
	text *ptResult = cstring_to_text(str.data);

	PG_RETURN_TEXT_P(ptResult);
}
Beispiel #19
0
/*
 * Compute an xlog file name given a WAL location,
 * such as is returned by pg_stop_backup() or pg_xlog_switch().
 */
Datum
pg_xlogfile_name(PG_FUNCTION_ARGS)
{
	XLogSegNo	xlogsegno;
	XLogRecPtr	locationpoint = PG_GETARG_LSN(0);
	char		xlogfilename[MAXFNAMELEN];

	if (RecoveryInProgress())
		ereport(ERROR,
				(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
				 errmsg("recovery is in progress"),
		 errhint("pg_xlogfile_name() cannot be executed during recovery.")));

	XLByteToPrevSeg(locationpoint, xlogsegno);
	XLogFileName(xlogfilename, ThisTimeLineID, xlogsegno);

	PG_RETURN_TEXT_P(cstring_to_text(xlogfilename));
}
Datum
pg_sasl_prepare(PG_FUNCTION_ARGS)
{
	char	   *password = text_to_cstring(PG_GETARG_TEXT_PP(0));
	char	   *prep_password = NULL;

	if (GetDatabaseEncoding() != PG_UTF8)
		ereport(ERROR,
				(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
				 errmsg("Database encoding is not UTF-8")));

	if (pg_saslprep(password, &prep_password) != SASLPREP_SUCCESS)
		ereport(ERROR,
				(errcode(ERRCODE_INTERNAL_ERROR),
				 errmsg("Error while processing SASLprep")));

	PG_RETURN_TEXT_P(cstring_to_text(prep_password));
}
Beispiel #21
0
static void
get_scalar(void *state, char *token, JsonTokenType tokentype)
{
	GetState	_state = (GetState) state;

	if (_state->lex->lex_level == 0 && _state->search_type != JSON_SEARCH_PATH)
		ereport(ERROR,
				(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
				 errmsg("cannot extract element from a scalar")));
	if (_state->next_scalar)
	{
		/* a de-escaped text value is wanted, so supply it */
		_state->tresult = cstring_to_text(token);
		/* make sure the next call to get_scalar doesn't overwrite it */
		_state->next_scalar = false;
	}

}
Beispiel #22
0
/*
 * Report the current WAL insert location (same format as pg_start_backup etc)
 *
 * This function is mostly for debugging purposes.
 */
Datum
pg_current_xlog_insert_location(PG_FUNCTION_ARGS)
{
	XLogRecPtr	current_recptr;
	char		location[MAXFNAMELEN];

	if (RecoveryInProgress())
		ereport(ERROR,
				(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
				 errmsg("recovery is in progress"),
				 errhint("WAL control functions cannot be executed during recovery.")));

	current_recptr = GetXLogInsertRecPtr(true);

	snprintf(location, sizeof(location), "%X/%X",
			 current_recptr.xlogid, current_recptr.xrecoff);
	PG_RETURN_TEXT_P(cstring_to_text(location));
}
Beispiel #23
0
Datum
pg_stat_get_backend_activity(PG_FUNCTION_ARGS)
{
	int32		beid = PG_GETARG_INT32(0);
	PgBackendStatus *beentry;
	const char *activity;

	if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL)
		activity = "<backend information not available>";
	else if (!superuser() && beentry->st_userid != GetUserId())
		activity = "<insufficient privilege>";
	else if (*(beentry->st_activity) == '\0')
		activity = "<command string not enabled>";
	else
		activity = beentry->st_activity;

	PG_RETURN_TEXT_P(cstring_to_text(activity));
}
Beispiel #24
0
Datum
OptimizeMinidumpFromFile(PG_FUNCTION_ARGS)
{
	char *szFileName = text_to_cstring(PG_GETARG_TEXT_P(0));
	char *szResultDXL = COptTasks::SzOptimizeMinidumpFromFile(szFileName);
	if (NULL != szResultDXL)
	{
		text *ptResult = cstring_to_text(szResultDXL);
		gpdb::GPDBFree(szResultDXL);
		PG_RETURN_TEXT_P(ptResult);
	}
	else
	{
		elog(NOTICE, "Execution of UDF 'OptimizeMinidumpFromFile' failed. Consult the LOG for more information.");

		// return a dummy value
		PG_RETURN_NULL();
	}
}
Beispiel #25
0
Datum
Optimize(PG_FUNCTION_ARGS)
{
	char *szSQLText = text_to_cstring(PG_GETARG_TEXT_P(0));

	Query *pquery = parseSQL(szSQLText);
	Query *pqueryNormalized = preprocess_query_optimizer(pquery, NULL);

	Assert(pqueryNormalized);

	char *szOutput = COptTasks::SzOptimize(pqueryNormalized);

	if (NULL == szOutput)
	{
		elog(ERROR, "Error optimizing query");
	}

	PG_RETURN_TEXT_P(cstring_to_text(szOutput));
}
Beispiel #26
0
/*
 * GetNextPlacementId allocates and returns a unique placementId for
 * the placement to be created. This allocation occurs both in shared memory
 * and in write ahead logs; writing to logs avoids the risk of having shardId
 * collisions.
 *
 * NB: This can be called by any user; for now we have decided that that's
 * ok. We might want to restrict this to users part of a specific role or such
 * at some later point.
 */
uint64
GetNextPlacementId(void)
{
	text *sequenceName = NULL;
	Oid sequenceId = InvalidOid;
	Datum sequenceIdDatum = 0;
	Oid savedUserId = InvalidOid;
	int savedSecurityContext = 0;
	Datum placementIdDatum = 0;
	uint64 placementId = 0;

	/*
	 * In regression tests, we would like to generate placement IDs consistently
	 * even if the tests run in parallel. Instead of the sequence, we can use
	 * the next_placement_id GUC to specify which shard ID the current session
	 * should generate next. The GUC is automatically increased by 1 every time
	 * a new placement ID is generated.
	 */
	if (NextPlacementId > 0)
	{
		placementId = NextPlacementId;
		NextPlacementId += 1;

		return placementId;
	}

	sequenceName = cstring_to_text(PLACEMENTID_SEQUENCE_NAME);
	sequenceId = ResolveRelationId(sequenceName);
	sequenceIdDatum = ObjectIdGetDatum(sequenceId);

	GetUserIdAndSecContext(&savedUserId, &savedSecurityContext);
	SetUserIdAndSecContext(CitusExtensionOwner(), SECURITY_LOCAL_USERID_CHANGE);

	/* generate new and unique placement id from sequence */
	placementIdDatum = DirectFunctionCall1(nextval_oid, sequenceIdDatum);

	SetUserIdAndSecContext(savedUserId, savedSecurityContext);

	placementId = DatumGetInt64(placementIdDatum);

	return placementId;
}
Beispiel #27
0
/*
 * SQL function: format_type(type_oid, typemod)
 *
 * `type_oid' is from pg_type.oid, `typemod' is from
 * pg_attribute.atttypmod. This function will get the type name and
 * format it and the modifier to canonical SQL format, if the type is
 * a standard type. Otherwise you just get pg_type.typname back,
 * double quoted if it contains funny characters or matches a keyword.
 *
 * If typemod is NULL then we are formatting a type name in a context where
 * no typemod is available, eg a function argument or result type.	This
 * yields a slightly different result from specifying typemod = -1 in some
 * cases.  Given typemod = -1 we feel compelled to produce an output that
 * the parser will interpret as having typemod -1, so that pg_dump will
 * produce CREATE TABLE commands that recreate the original state.	But
 * given NULL typemod, we assume that the parser's interpretation of
 * typemod doesn't matter, and so we are willing to output a slightly
 * "prettier" representation of the same type.	For example, type = bpchar
 * and typemod = NULL gets you "character", whereas typemod = -1 gets you
 * "bpchar" --- the former will be interpreted as character(1) by the
 * parser, which does not yield typemod -1.
 *
 * XXX encoding a meaning in typemod = NULL is ugly; it'd have been
 * cleaner to make two functions of one and two arguments respectively.
 * Not worth changing it now, however.
 */
datum_t format_type(PG_FUNC_ARGS)
{
    oid_t type_oid;
    int32 typemod;
    char *result;

    /* Since this function is not strict, we must test for null args */
    if (PG_ARG_ISNULL(0))
        RET_NULL();

    type_oid = ARG_OID(0);
    if (PG_ARG_ISNULL(1)) {
        result = format_type_internal(type_oid, -1, false, true);
    } else {
        typemod = ARG_INT32(1);
        result = format_type_internal(type_oid, typemod, true, true);
    }

    RET_TEXT_P(cstring_to_text(result));
}
Beispiel #28
0
static text *
istatus_text(ItemId itemid)
{
	StringInfoData	buf;

	initStringInfo(&buf);

	if (ItemIdDeleted(itemid))
		appendStringInfoString(&buf, "DELETED ");
	if (ItemIdIsNormal(itemid))
		appendStringInfoString(&buf, "USED ");
	if (ItemIdIsDead(itemid))
		appendStringInfoString(&buf, "DEAD ");

	if (buf.len == 0)
		appendStringInfoString(&buf, "UNUSED ");

	buf.data[buf.len - 1] = '\0';
	return cstring_to_text(buf.data);
}
Beispiel #29
0
Datum
xml_encode_special_chars(PG_FUNCTION_ARGS)
{
	text	   *tin = PG_GETARG_TEXT_P(0);
	text	   *tout;
	xmlChar    *ts,
			   *tt;

	ts = pgxml_texttoxmlchar(tin);

	tt = xmlEncodeSpecialChars(NULL, ts);

	pfree(ts);

	tout = cstring_to_text((char *) tt);

	xmlFree(tt);

	PG_RETURN_TEXT_P(tout);
}
Beispiel #30
0
/*
 * master_get_new_shardid allocates and returns a unique shardId for the shard
 * to be created. This allocation occurs both in shared memory and in write
 * ahead logs; writing to logs avoids the risk of having shardId collisions.
 *
 * Please note that the caller is still responsible for finalizing shard data
 * and the shardId with the master node. Further note that this function relies
 * on an internal sequence created in initdb to generate unique identifiers.
 *
 * NB: This can be called by any user; for now we have decided that that's
 * ok. We might want to restrict this to users part of a specific role or such
 * at some later point.
 */
Datum
master_get_new_shardid(PG_FUNCTION_ARGS)
{
	text *sequenceName = cstring_to_text(SHARDID_SEQUENCE_NAME);
	Oid sequenceId = ResolveRelationId(sequenceName);
	Datum sequenceIdDatum = ObjectIdGetDatum(sequenceId);
	Oid savedUserId = InvalidOid;
	int savedSecurityContext = 0;
	Datum shardIdDatum = 0;

	GetUserIdAndSecContext(&savedUserId, &savedSecurityContext);
	SetUserIdAndSecContext(CitusExtensionOwner(), SECURITY_LOCAL_USERID_CHANGE);

	/* generate new and unique shardId from sequence */
	shardIdDatum = DirectFunctionCall1(nextval_oid, sequenceIdDatum);

	SetUserIdAndSecContext(savedUserId, savedSecurityContext);

	PG_RETURN_DATUM(shardIdDatum);
}