コード例 #1
0
ファイル: cdbutil.c プロジェクト: BALDELab/incubator-hawq
Segment *
CopySegment(Segment *src, MemoryContext cxt)
{
	MemoryContext	valid_cxt = cxt ? cxt : CurrentMemoryContext;
	Segment	*dest = MemoryContextAllocZero(valid_cxt, sizeof(Segment));

	memcpy(dest, src, sizeof(Segment));
	/* memory leak risk! */
	dest->hostname = MemoryContextStrdup(valid_cxt, src->hostname);
	dest->hostip = MemoryContextStrdup(valid_cxt, src->hostip);

	return dest;
}
コード例 #2
0
ファイル: uavc.c プロジェクト: ArgenBarbie/postgresql-9.5.0
/*
 * sepgsql_avc_unlabeled
 *
 * Returns an alternative label to be applied when no label or an invalid
 * label would otherwise be assigned.
 */
static char *
sepgsql_avc_unlabeled(void)
{
	if (!avc_unlabeled)
	{
		security_context_t unlabeled;

		if (security_get_initial_context_raw("unlabeled", &unlabeled) < 0)
			ereport(ERROR,
					(errcode(ERRCODE_INTERNAL_ERROR),
			   errmsg("SELinux: failed to get initial security label: %m")));
		PG_TRY();
		{
			avc_unlabeled = MemoryContextStrdup(avc_mem_cxt, unlabeled);
		}
		PG_CATCH();
		{
			freecon(unlabeled);
			PG_RE_THROW();
		}
		PG_END_TRY();

		freecon(unlabeled);
	}
	return avc_unlabeled;
}
コード例 #3
0
ファイル: InstallHelper.c プロジェクト: greenplum-db/pljava
bool InstallHelper_isPLJavaFunction(Oid fn)
{
	char *itsPath;
	char *pljPath;
	bool result = false;

	itsPath = pljavaFnOidToLibPath(fn);
	if ( NULL == itsPath )
		return false;

	if ( NULL == pljavaLoadPath )
	{
		pljPath = NULL;
		if ( InvalidOid != pljavaTrustedOid )
			pljPath = pljavaFnOidToLibPath(pljavaTrustedOid);
		if ( NULL == pljPath && InvalidOid != pljavaUntrustedOid )
			pljPath = pljavaFnOidToLibPath(pljavaUntrustedOid);
		if ( NULL == pljPath )
		{
			elog(WARNING, "unable to determine PL/Java's load path");
			goto finally;
		}
		pljavaLoadPath =
			(char const *)MemoryContextStrdup(TopMemoryContext, pljPath);
		pfree(pljPath);
	}
	result = 0 == strcmp(itsPath, pljavaLoadPath);
finally:
	pfree(itsPath);
	return result;
}
コード例 #4
0
/*
 * Module initialize function: initialize info about Bloom relation options.
 *
 * Note: keep this in sync with makeDefaultBloomOptions().
 */
void
_PG_init(void)
{
	int			i;
	char		buf[16];

	bl_relopt_kind = add_reloption_kind();

	/* Option for length of signature */
	add_int_reloption(bl_relopt_kind, "length",
					  "Length of signature in bits",
					  DEFAULT_BLOOM_LENGTH, 1, MAX_BLOOM_LENGTH);
	bl_relopt_tab[0].optname = "length";
	bl_relopt_tab[0].opttype = RELOPT_TYPE_INT;
	bl_relopt_tab[0].offset = offsetof(BloomOptions, bloomLength);

	/* Number of bits for each possible index column: col1, col2, ... */
	for (i = 0; i < INDEX_MAX_KEYS; i++)
	{
		snprintf(buf, sizeof(buf), "col%d", i + 1);
		add_int_reloption(bl_relopt_kind, buf,
						  "Number of bits generated for each index column",
						  DEFAULT_BLOOM_BITS, 1, MAX_BLOOM_BITS);
		bl_relopt_tab[i + 1].optname = MemoryContextStrdup(TopMemoryContext,
														   buf);
		bl_relopt_tab[i + 1].opttype = RELOPT_TYPE_INT;
		bl_relopt_tab[i + 1].offset = offsetof(BloomOptions, bitSize[0]) + sizeof(int) * i;
	}
}
コード例 #5
0
ファイル: reloptions.c プロジェクト: Distrotech/postgresql
/*
 * add_string_reloption
 *		Add a new string reloption
 *
 * "validator" is an optional function pointer that can be used to test the
 * validity of the values.  It must elog(ERROR) when the argument string is
 * not acceptable for the variable.  Note that the default value must pass
 * the validation.
 */
void
add_string_reloption(bits32 kinds, char *name, char *desc, char *default_val,
					 validate_string_relopt validator)
{
	relopt_string *newoption;

	/* make sure the validator/default combination is sane */
	if (validator)
		(validator) (default_val);

	newoption = (relopt_string *) allocate_reloption(kinds, RELOPT_TYPE_STRING,
													 name, desc);
	newoption->validate_cb = validator;
	if (default_val)
	{
		newoption->default_val = MemoryContextStrdup(TopMemoryContext,
													 default_val);
		newoption->default_len = strlen(default_val);
		newoption->default_isnull = false;
	}
	else
	{
		newoption->default_val = "";
		newoption->default_len = 0;
		newoption->default_isnull = true;
	}

	add_reloption((relopt_gen *) newoption);
}
コード例 #6
0
ファイル: label.c プロジェクト: LDuderino/postgres
/*
 * sepgsql_xact_callback
 *
 * A callback routine of transaction commit/abort/prepare.  Commit or abort
 * changes in the client_label_pending list.
 */
static void
sepgsql_xact_callback(XactEvent event, void *arg)
{
	if (event == XACT_EVENT_COMMIT)
	{
		if (client_label_pending != NIL)
		{
			pending_label *plabel = llast(client_label_pending);
			char	   *new_label;

			if (plabel->label)
				new_label = MemoryContextStrdup(TopMemoryContext,
												plabel->label);
			else
				new_label = NULL;

			if (client_label_committed)
				pfree(client_label_committed);

			client_label_committed = new_label;

			/*
			 * XXX - Note that items of client_label_pending are allocated on
			 * CurTransactionContext, thus, all acquired memory region shall
			 * be released implicitly.
			 */
			client_label_pending = NIL;
		}
	}
	else if (event == XACT_EVENT_ABORT)
		client_label_pending = NIL;
}
コード例 #7
0
ファイル: zdbutils.c プロジェクト: zombodb/zombodb
char *lookup_primary_key(char *schemaName, char *tableName, bool failOnMissing) {
    StringInfo sql = makeStringInfo();
    char       *keyname;

    SPI_connect();
    appendStringInfo(sql, "SELECT column_name FROM information_schema.key_column_usage WHERE table_schema = '%s' AND table_name = '%s'", schemaName, tableName);
    SPI_execute(sql->data, true, 1);

    if (SPI_processed == 0) {
        if (failOnMissing)
            elog(ERROR, "Cannot find primary key column for: %s.%s", schemaName, tableName);
        else {
            SPI_finish();
            return NULL;
        }
    }

    keyname = SPI_getvalue(SPI_tuptable->vals[0], SPI_tuptable->tupdesc, 1);
    if (keyname == NULL)
        elog(ERROR, "Primary Key field is null for: %s.%s", schemaName, tableName);

    keyname = MemoryContextStrdup(TopTransactionContext, keyname);

    SPI_finish();

    return keyname;
}
コード例 #8
0
ファイル: common.c プロジェクト: ssinger/skytools
static void parse_newstyle_args(PgqTriggerEvent *ev, TriggerData *tg)
{
	int i;

	/*
	 * parse args
	 */
	for (i = 1; i < tg->tg_trigger->tgnargs; i++) {
		const char *arg = tg->tg_trigger->tgargs[i];
		if (strcmp(arg, "SKIP") == 0)
			ev->tgargs->skip = true;
		else if (strncmp(arg, "ignore=", 7) == 0)
			ev->tgargs->ignore_list = MemoryContextStrdup(tbl_cache_ctx, arg + 7);
		else if (strncmp(arg, "pkey=", 5) == 0)
			ev->tgargs->pkey_list = MemoryContextStrdup(tbl_cache_ctx, arg + 5);
		else if (strcmp(arg, "backup") == 0)
			ev->tgargs->backup = true;
		else if (strcmp(arg, "deny") == 0)
			ev->tgargs->deny = true;
		else if (strncmp(arg, "ev_extra4=", 10) == 0)
			make_query(ev, EV_EXTRA4, arg + 10);
		else if (strncmp(arg, "ev_extra3=", 10) == 0)
			make_query(ev, EV_EXTRA3, arg + 10);
		else if (strncmp(arg, "ev_extra2=", 10) == 0)
			make_query(ev, EV_EXTRA2, arg + 10);
		else if (strncmp(arg, "ev_extra1=", 10) == 0)
			make_query(ev, EV_EXTRA1, arg + 10);
		else if (strncmp(arg, "ev_data=", 8) == 0)
			make_query(ev, EV_DATA, arg + 8);
		else if (strncmp(arg, "ev_type=", 8) == 0)
			make_query(ev, EV_TYPE, arg + 8);
		else if (strncmp(arg, "when=", 5) == 0)
			make_query(ev, EV_WHEN, arg + 5);
		else
			elog(ERROR, "bad param to pgq trigger");
	}

	if (ev->op_type == 'R') {
		if (ev->tgargs->ignore_list)
			elog(ERROR, "Column ignore does not make sense for truncate trigger");
		if (ev->tgargs->pkey_list)
			elog(ERROR, "Custom pkey_list does not make sense for truncate trigger");
		if (ev->tgargs->backup)
			elog(ERROR, "Backup does not make sense for truncate trigger");
	}
}
コード例 #9
0
static PyObject *
PLy_cursor_query(const char *query)
{
	PLyCursorObject *cursor;
	volatile MemoryContext oldcontext;
	volatile ResourceOwner oldowner;

	if ((cursor = PyObject_New(PLyCursorObject, &PLy_CursorType)) == NULL)
		return NULL;
	cursor->portalname = NULL;
	cursor->closed = false;
	cursor->mcxt = AllocSetContextCreate(TopMemoryContext,
										 "PL/Python cursor context",
										 ALLOCSET_DEFAULT_MINSIZE,
										 ALLOCSET_DEFAULT_INITSIZE,
										 ALLOCSET_DEFAULT_MAXSIZE);
	PLy_typeinfo_init(&cursor->result, cursor->mcxt);

	oldcontext = CurrentMemoryContext;
	oldowner = CurrentResourceOwner;

	PLy_spi_subtransaction_begin(oldcontext, oldowner);

	PG_TRY();
	{
		PLyExecutionContext *exec_ctx = PLy_current_execution_context();
		SPIPlanPtr	plan;
		Portal		portal;

		pg_verifymbstr(query, strlen(query), false);

		plan = SPI_prepare(query, 0, NULL);
		if (plan == NULL)
			elog(ERROR, "SPI_prepare failed: %s",
				 SPI_result_code_string(SPI_result));

		portal = SPI_cursor_open(NULL, plan, NULL, NULL,
								 exec_ctx->curr_proc->fn_readonly);
		SPI_freeplan(plan);

		if (portal == NULL)
			elog(ERROR, "SPI_cursor_open() failed: %s",
				 SPI_result_code_string(SPI_result));

		cursor->portalname = MemoryContextStrdup(cursor->mcxt, portal->name);

		PLy_spi_subtransaction_commit(oldcontext, oldowner);
	}
	PG_CATCH();
	{
		PLy_spi_subtransaction_abort(oldcontext, oldowner);
		return NULL;
	}
	PG_END_TRY();

	Assert(cursor->portalname != NULL);
	return (PyObject *) cursor;
}
コード例 #10
0
ファイル: common.c プロジェクト: ssinger/skytools
/*
 * Fill table information in hash table.
 */
static void fill_tbl_info(Relation rel, struct PgqTableInfo *info)
{
	StringInfo pkeys;
	Datum values[1];
	const char *name = find_table_name(rel);
	TupleDesc desc;
	HeapTuple row;
	bool isnull;
	int res, i, attno;

	/* allow reset ASAP, but ignore it in this call */
	info->invalid = false;

	/* load pkeys */
	values[0] = ObjectIdGetDatum(rel->rd_id);
	res = SPI_execute_plan(pkey_plan, values, NULL, false, 0);
	if (res != SPI_OK_SELECT)
		elog(ERROR, "pkey_plan exec failed");

	/*
	 * Fill info
	 */

	desc = SPI_tuptable->tupdesc;
	pkeys = makeStringInfo();
	info->n_pkeys = SPI_processed;
	info->table_name = MemoryContextStrdup(tbl_cache_ctx, name);
	info->pkey_attno = MemoryContextAlloc(tbl_cache_ctx, info->n_pkeys * sizeof(int));

	for (i = 0; i < SPI_processed; i++) {
		row = SPI_tuptable->vals[i];

		attno = DatumGetInt16(SPI_getbinval(row, desc, 1, &isnull));
		name = SPI_getvalue(row, desc, 2);
		info->pkey_attno[i] = attno;
		if (i > 0)
			appendStringInfoChar(pkeys, ',');
		appendStringInfoString(pkeys, name);
	}
	info->pkey_list = MemoryContextStrdup(tbl_cache_ctx, pkeys->data);
	info->tg_cache = NULL;
}
コード例 #11
0
ファイル: variant.c プロジェクト: decibel/variant
/*
 * get_cache: get/set cached info
 */
static VariantCache *
get_cache(FunctionCallInfo fcinfo, VariantInt vi, IOFuncSelector func)
{
    VariantCache *cache = (VariantCache *) fcinfo->flinfo->fn_extra;

    /* IO type should always be the same, so assert that. But if we're not an assert build just force a reset. */
    if (cache != NULL && cache->typid == vi->typid && cache->typmod == vi->typmod && cache->IOfunc != func)
    {
        Assert(false);
        cache->typid ^= vi->typid;
    }

    if (cache == NULL || cache->typid != vi->typid || cache->typmod != vi->typmod)
    {
        char						typDelim;
        Oid							typIoFunc;

        /*
         * We can get different OIDs in one call, so don't needlessly palloc
         */
        if (cache == NULL)
            cache = (VariantCache *) MemoryContextAlloc(fcinfo->flinfo->fn_mcxt,
                    sizeof(VariantCache));

        cache->typid = vi->typid;
        cache->typmod = vi->typmod;
        cache->IOfunc = func;

        get_type_io_data(cache->typid,
                         func,
                         &cache->typlen,
                         &cache->typbyval,
                         &cache->typalign,
                         &typDelim,
                         &cache->typioparam,
                         &typIoFunc);
        fmgr_info_cxt(typIoFunc, &cache->proc, fcinfo->flinfo->fn_mcxt);

        if (func == IOFunc_output || func == IOFunc_send)
        {
            cache->formatted_name = MemoryContextStrdup(fcinfo->flinfo->fn_mcxt,
                                    format_type_with_typemod(cache->typid, cache->typmod));
        }
        else
            cache->formatted_name="\0";

        fcinfo->flinfo->fn_extra = (void *) cache;
    }

    return cache;
}
コード例 #12
0
ファイル: plpy_procedure.c プロジェクト: AmiGanguli/postgres
/*
 * Insert the procedure into the Python interpreter
 */
void
PLy_procedure_compile(PLyProcedure *proc, const char *src)
{
	PyObject   *crv = NULL;
	char	   *msrc;

	proc->globals = PyDict_Copy(PLy_interp_globals);

	/*
	 * SD is private preserved data between calls. GD is global data shared by
	 * all functions
	 */
	proc->statics = PyDict_New();
	if (!proc->statics)
		PLy_elog(ERROR, NULL);
	PyDict_SetItemString(proc->globals, "SD", proc->statics);

	/*
	 * insert the function code into the interpreter
	 */
	msrc = PLy_procedure_munge_source(proc->pyname, src);
	/* Save the mangled source for later inclusion in tracebacks */
	proc->src = MemoryContextStrdup(proc->mcxt, msrc);
	crv = PyRun_String(msrc, Py_file_input, proc->globals, NULL);
	pfree(msrc);

	if (crv != NULL)
	{
		int			clen;
		char		call[NAMEDATALEN + 256];

		Py_DECREF(crv);

		/*
		 * compile a call to the function
		 */
		clen = snprintf(call, sizeof(call), "%s()", proc->pyname);
		if (clen < 0 || clen >= sizeof(call))
			elog(ERROR, "string would overflow buffer");
		proc->code = Py_CompileString(call, "<string>", Py_eval_input);
		if (proc->code != NULL)
			return;
	}

	if (proc->proname)
		PLy_elog(ERROR, "could not compile PL/Python function \"%s\"",
				 proc->proname);
	else
		PLy_elog(ERROR, "could not compile anonymous PL/Python code block");
}
コード例 #13
0
ファイル: InstallHelper.c プロジェクト: greenplum-db/pljava
/*
 * As for pljavaCheckExtension, livecheck == null when called from _PG_init
 * (when the real questions are whether PL/Java itself is being loaded, from
 * what path, and whether or not as an extension). When livecheck is not null,
 * PL/Java is already alive and the caller wants to know if an extension is
 * being created for some other reason. That wouldn't even involve this
 * function, except for the need to work around creating_extension visibility
 * on Windows. So if livecheck isn't null, this function only needs to proceed
 * as far as the CREATING_EXTENSION_HACK and then return.
 */
static void checkLoadPath( bool *livecheck)
{
	List *l;
	Node *ut;
	LoadStmt *ls;

#ifndef CREATING_EXTENSION_HACK
	if ( NULL != livecheck )
		return;
#endif
	if ( NULL == ActivePortal )
		return;
	l = ActivePortal->stmts;
	if ( NULL == l )
		return;
	if ( 1 < list_length( l) )
		elog(DEBUG2, "ActivePortal lists %d statements", list_length( l));
	ut = (Node *)linitial(l);
	if ( NULL == ut )
	{
		elog(DEBUG2, "got null for first statement from ActivePortal");
		return;
	}
	if ( T_LoadStmt != nodeTag(ut) )
#ifdef CREATING_EXTENSION_HACK
		if ( T_CreateExtensionStmt == nodeTag(ut) )
		{
			if ( NULL != livecheck )
			{
				*livecheck = true;
				return;
			}
			getExtensionLoadPath();
			if ( NULL != pljavaLoadPath )
				pljavaLoadingAsExtension = true;
		}
#endif
		return;
	if ( NULL != livecheck )
		return;
	ls = (LoadStmt *)ut;
	if ( NULL == ls->filename )
	{
		elog(DEBUG2, "got null for a LOAD statement's filename");
		return;
	}
	pljavaLoadPath =
		(char const *)MemoryContextStrdup(TopMemoryContext, ls->filename);
}
コード例 #14
0
ファイル: denytriga.c プロジェクト: ssinger/skytools-cvs
Datum pgq_set_connection_context(PG_FUNCTION_ARGS)
{
	char *ctx;
	if (current_context)
		pfree(current_context);
	current_context = NULL;

	if (PG_NARGS() > 0 && !PG_ARGISNULL(0)) {
		ctx = DatumGetCString(DirectFunctionCall1(textout, PG_GETARG_DATUM(0)));
		current_context = MemoryContextStrdup(TopMemoryContext, ctx);
		pfree(ctx);
	}

	PG_RETURN_VOID();
}
コード例 #15
0
ファイル: pg_locale.c プロジェクト: myechuri/pipelinedb
/* Subroutine for cache_locale_time(). */
static void
cache_single_time(char **dst, const char *format, const struct tm * tm)
{
	char		buf[MAX_L10N_DATA];
	char	   *ptr;

	/*
	 * MAX_L10N_DATA is sufficient buffer space for every known locale, and
	 * POSIX defines no strftime() errors.  (Buffer space exhaustion is not an
	 * error.)  An implementation might report errors (e.g. ENOMEM) by
	 * returning 0 (or, less plausibly, a negative value) and setting errno.
	 * Report errno just in case the implementation did that, but clear it in
	 * advance of the call so we don't emit a stale, unrelated errno.
	 */
	errno = 0;
	if (strftime(buf, MAX_L10N_DATA, format, tm) <= 0)
		elog(ERROR, "strftime(%s) failed: %m", format);

	ptr = MemoryContextStrdup(TopMemoryContext, buf);
	if (*dst)
		pfree(*dst);
	*dst = ptr;
}
コード例 #16
0
ファイル: pg_locale.c プロジェクト: AXLEproject/postgres
/*
 * Update the lc_time localization cache variables if needed.
 */
void
cache_locale_time(void)
{
	char	   *save_lc_time;
	time_t		timenow;
	struct tm  *timeinfo;
	char		buf[MAX_L10N_DATA];
	char	   *ptr;
	int			i;

#ifdef WIN32
	char	   *save_lc_ctype;
#endif

	/* did we do this already? */
	if (CurrentLCTimeValid)
		return;

	elog(DEBUG3, "cache_locale_time() executed; locale: \"%s\"", locale_time);

	/* save user's value of time locale */
	save_lc_time = setlocale(LC_TIME, NULL);
	if (save_lc_time)
		save_lc_time = pstrdup(save_lc_time);

#ifdef WIN32

	/*
	 * On WIN32, there is no way to get locale-specific time values in a
	 * specified locale, like we do for monetary/numeric.  We can only get
	 * CP_ACP (see strftime_win32) or UTF16.  Therefore, we get UTF16 and
	 * convert it to the database locale.  However, wcsftime() internally uses
	 * LC_CTYPE, so we set it here.  See the WIN32 comment near the top of
	 * PGLC_localeconv().
	 */

	/* save user's value of ctype locale */
	save_lc_ctype = setlocale(LC_CTYPE, NULL);
	if (save_lc_ctype)
		save_lc_ctype = pstrdup(save_lc_ctype);

	/* use lc_time to set the ctype */
	setlocale(LC_CTYPE, locale_time);
#endif

	setlocale(LC_TIME, locale_time);

	timenow = time(NULL);
	timeinfo = localtime(&timenow);

	/* localized days */
	for (i = 0; i < 7; i++)
	{
		timeinfo->tm_wday = i;
		strftime(buf, MAX_L10N_DATA, "%a", timeinfo);
		ptr = MemoryContextStrdup(TopMemoryContext, buf);
		if (localized_abbrev_days[i])
			pfree(localized_abbrev_days[i]);
		localized_abbrev_days[i] = ptr;

		strftime(buf, MAX_L10N_DATA, "%A", timeinfo);
		ptr = MemoryContextStrdup(TopMemoryContext, buf);
		if (localized_full_days[i])
			pfree(localized_full_days[i]);
		localized_full_days[i] = ptr;
	}

	/* localized months */
	for (i = 0; i < 12; i++)
	{
		timeinfo->tm_mon = i;
		timeinfo->tm_mday = 1;	/* make sure we don't have invalid date */
		strftime(buf, MAX_L10N_DATA, "%b", timeinfo);
		ptr = MemoryContextStrdup(TopMemoryContext, buf);
		if (localized_abbrev_months[i])
			pfree(localized_abbrev_months[i]);
		localized_abbrev_months[i] = ptr;

		strftime(buf, MAX_L10N_DATA, "%B", timeinfo);
		ptr = MemoryContextStrdup(TopMemoryContext, buf);
		if (localized_full_months[i])
			pfree(localized_full_months[i]);
		localized_full_months[i] = ptr;
	}

	/* try to restore internal settings */
	if (save_lc_time)
	{
		if (!setlocale(LC_TIME, save_lc_time))
			elog(WARNING, "failed to restore old locale");
		pfree(save_lc_time);
	}

#ifdef WIN32
	/* try to restore internal ctype settings */
	if (save_lc_ctype)
	{
		if (!setlocale(LC_CTYPE, save_lc_ctype))
			elog(WARNING, "failed to restore old locale");
		pfree(save_lc_ctype);
	}
#endif

	CurrentLCTimeValid = true;
}
コード例 #17
0
/*
 * Implements the 'EXECUTE' utility statement.
 *
 * Note: this is one of very few places in the code that needs to deal with
 * two query strings at once.  The passed-in queryString is that of the
 * EXECUTE, which we might need for error reporting while processing the
 * parameter expressions.  The query_string that we copy from the plan
 * source is that of the original PREPARE.
 */
void
ExecuteQuery(ExecuteStmt *stmt, const char *queryString,
			 ParamListInfo params,
			 DestReceiver *dest, char *completionTag)
{
	PreparedStatement *entry;
	List	   *stmt_list;
	MemoryContext qcontext;
	ParamListInfo paramLI = NULL;
	EState	   *estate = NULL;
	Portal		portal;

	/* Look it up in the hash table */
	entry = FetchPreparedStatement(stmt->name, true);

	qcontext = entry->context;

	/* Evaluate parameters, if any */
	if (entry->argtype_list != NIL)
	{
		/*
		 * Need an EState to evaluate parameters; must not delete it till end
		 * of query, in case parameters are pass-by-reference.
		 */
		estate = CreateExecutorState();
		estate->es_param_list_info = params;
		paramLI = EvaluateParams(estate, stmt->params, entry->argtype_list);
	}

	/* Create a new portal to run the query in */
	portal = CreateNewPortal();
	/* Don't display the portal in pg_cursors, it is for internal use only */
	portal->visible = false;

	/* Plan the query.  If this is a CTAS, copy the "into" information into
	 * the query so that we construct the plan correctly.  Else the table
	 * might not be created on the segments.  (MPP-8135) */
	{
		List *query_list = copyObject(entry->query_list); /* planner scribbles on query tree :( */
		
		if ( stmt->into )
		{
			Query *query = (Query*)linitial(query_list);
			Assert(IsA(query, Query) && query->intoClause == NULL);
			query->intoClause = copyObject(stmt->into);
		}
		
		stmt_list = pg_plan_queries(query_list, paramLI, false, QRL_ONCE);
	}

	/*
	 * For CREATE TABLE / AS EXECUTE, make a copy of the stored query so that
	 * we can modify its destination (yech, but this has always been ugly).
	 * For regular EXECUTE we can just use the stored query where it sits,
	 * since the executor is read-only.
	 */
	if (stmt->into)
	{
		MemoryContext oldContext;
		PlannedStmt	 *pstmt;

		if (list_length(stmt_list) != 1)
			ereport(ERROR,
					(errcode(ERRCODE_WRONG_OBJECT_TYPE),
					 errmsg("prepared statement is not a SELECT")));

		oldContext = MemoryContextSwitchTo(PortalGetHeapMemory(portal));

		stmt_list = copyObject(stmt_list);
		qcontext = PortalGetHeapMemory(portal);
		pstmt = (PlannedStmt *) linitial(stmt_list);
		pstmt->qdContext = qcontext;
		if (pstmt->commandType != CMD_SELECT)
			ereport(ERROR,
					(errcode(ERRCODE_WRONG_OBJECT_TYPE),
					 errmsg("prepared statement is not a SELECT"),
							   errOmitLocation(true)));

		pstmt->intoClause = copyObject(stmt->into);

		/* XXX  Is it legitimate to assign a constant default policy without 
		 *      even checking the relation?
		 */
		pstmt->intoPolicy = palloc0(sizeof(GpPolicy)- sizeof(pstmt->intoPolicy->attrs)
									+ 255 * sizeof(pstmt->intoPolicy->attrs[0]));
		pstmt->intoPolicy->nattrs = 0;
		pstmt->intoPolicy->ptype = POLICYTYPE_PARTITIONED;
		pstmt->intoPolicy->bucketnum = GetRelOpt_bucket_num_fromRangeVar(stmt->into->rel, GetRandomDistPartitionNum());
		
		MemoryContextSwitchTo(oldContext);
	}

	/* Copy the plan's saved query string into the portal's memory */
	Assert(entry->query_string != NULL); 
	char *query_string = MemoryContextStrdup(PortalGetHeapMemory(portal),
					   entry->query_string);

	PortalDefineQuery(portal,
					  NULL,
					  query_string,
					  entry->sourceTag,
					  entry->commandTag,
					  stmt_list,
					  qcontext);

	create_filesystem_credentials(portal);

	/*
	 * Run the portal to completion.
	 */
	PortalStart(portal, paramLI, ActiveSnapshot,
				savedSeqServerHost, savedSeqServerPort);

	(void) PortalRun(portal, 
					FETCH_ALL, 
					 true, /* Effectively always top level. */
					 dest, 
					 dest, 
					 completionTag);

	PortalDrop(portal, false);

	if (estate)
		FreeExecutorState(estate);

	/* No need to pfree other memory, MemoryContext will be reset */
}
コード例 #18
0
ファイル: Backend.c プロジェクト: greenplum-db/pljava
/*
 * There are a few ways to arrive in the initsequencer.
 * 1. From _PG_init (called exactly once when the library is loaded for ANY
 *    reason).
 *    1a. Because of the command LOAD 'libraryname';
 *        This case can be distinguished because _PG_init will have found the
 *        LOAD command and saved the 'libraryname' in pljavaLoadPath.
 *    1b. Because of a CREATE FUNCTION naming this library. pljavaLoadPath will
 *        be NULL.
 *    1c. By the first actual use of a PL/Java function, causing this library
 *        to be loaded. pljavaLoadPath will be NULL. The called function's Oid
 *        will be available to the call handler once we return from _PG_init,
 *        but it isn't (easily) available here.
 * 2. From the call handler, if initialization isn't complete yet. That can only
 *    mean something failed in the earlier call to _PG_init, and whatever it was
 *    is highly likely to fail again. That may lead to the untidyness of
 *    duplicated diagnostic messages, but for now I like the belt-and-suspenders
 *    approach of making sure the init sequence gets as many chances as possible
 *    to succeed.
 * 3. From a GUC assign hook, if the user has updated a setting that might allow
 *    initialization to succeed. It resumes from where it left off.
 *
 * In all cases, the sequence must progress as far as starting the VM and
 * initializing the PL/Java classes. In all cases except 1a, that's enough,
 * assuming the language handlers and schema have all been set up already (or,
 * in case 1b, the user is intent on setting them up explicitly).
 *
 * In case 1a, we can go ahead and test for, and create, the schema, functions,
 * and language entries as needed, using pljavaLoadPath as the library path
 * if creating the language handler functions. One-stop shopping. (The presence
 * of pljavaLoadPath in any of the other cases, such as resumption by an assign
 * hook, indicates it is really a continuation of case 1a.)
 */
static void initsequencer(enum initstage is, bool tolerant)
{
	JVMOptList optList;
	Invocation ctx;
	jint JNIresult;
	char *greeting;

	switch (is)
	{
	case IS_FORMLESS_VOID:
		initstage = IS_GUCS_REGISTERED;

	case IS_GUCS_REGISTERED:
		libjvmlocation = strdup("libjvm.so");

		initstage = IS_PLJAVA_ENABLED;

	case IS_PLJAVA_ENABLED:
		libjvm_handle = pg_dlopen(libjvmlocation);
		if ( NULL == libjvm_handle )
		{
			ereport(ERROR, (
				errmsg("Cannot load libjvm.so library, check that it is available in LD_LIBRARY_PATH"),
				errdetail("%s", (char *)pg_dlerror())));
			goto check_tolerant;
		}
		initstage = IS_CAND_JVMOPENED;

	case IS_CAND_JVMOPENED:
		pljava_createvm =
			(jint (JNICALL *)(JavaVM **, void **, void *))
			pg_dlsym(libjvm_handle, "JNI_CreateJavaVM");
		if ( NULL == pljava_createvm )
		{
			/*
			 * If it hasn't got the symbol, it can't be the right
			 * library, so close/unload it so another can be tried.
			 * Format the dlerror string first: dlclose may clobber it.
			 */
			char *dle = MemoryContextStrdup(ErrorContext, pg_dlerror());
			pg_dlclose(libjvm_handle);
			initstage = IS_CAND_JVMLOCATION;
			ereport(ERROR, (
				errmsg("Cannot start Java VM"),
				errdetail("%s", dle),
				errhint("Check that libjvm.so is available in LD_LIBRARY_PATH")));
			goto check_tolerant;
		}
		initstage = IS_CREATEVM_SYM_FOUND;

	case IS_CREATEVM_SYM_FOUND:
		s_javaLogLevel = INFO;
		checkIntTimeType();
		HashMap_initialize(); /* creates things in TopMemoryContext */
#ifdef PLJAVA_DEBUG
		/* Hard setting for debug. Don't forget to recompile...
		 */
		pljava_debug = 1;
#endif
		initstage = IS_MISC_ONCE_DONE;

	case IS_MISC_ONCE_DONE:
		JVMOptList_init(&optList); /* uses CurrentMemoryContext */
		seenVisualVMName = false;
		addUserJVMOptions(&optList);
		if ( ! seenVisualVMName )
			JVMOptList_addVisualVMName(&optList);
		JVMOptList_add(&optList, "vfprintf", (void*)my_vfprintf, true);
#ifndef GCJ
		JVMOptList_add(&optList, "-Xrs", 0, true);
#endif
		effectiveClassPath = getClassPath("-Djava.class.path=");
		if(effectiveClassPath != 0)
		{
			JVMOptList_add(&optList, effectiveClassPath, 0, true);
		}
		initstage = IS_JAVAVM_OPTLIST;

	case IS_JAVAVM_OPTLIST:
		JNIresult = initializeJavaVM(&optList); /* frees the optList */
		if( JNI_OK != JNIresult )
		{
			initstage = IS_MISC_ONCE_DONE; /* optList has been freed */
			StaticAssertStmt(sizeof(jint) <= sizeof(long int),
				"jint wider than long int?!");
			ereport(WARNING,
				(errmsg("failed to create Java virtual machine"),
				 errdetail("JNI_CreateJavaVM returned an error code: %ld",
					(long int)JNIresult),
				 jvmStartedAtLeastOnce ?
					errhint("Because an earlier attempt during this session "
					"did start a VM before failing, this probably means your "
					"Java runtime environment does not support more than one "
					"VM creation per session.  You may need to exit this "
					"session and start a new one.") : 0));
			goto check_tolerant;
		}
		jvmStartedAtLeastOnce = true;
		elog(DEBUG2, "successfully created Java virtual machine");
		initstage = IS_JAVAVM_STARTED;

	case IS_JAVAVM_STARTED:
#ifdef USE_PLJAVA_SIGHANDLERS
		pqsignal(SIGINT,  pljavaStatementCancelHandler);
		pqsignal(SIGTERM, pljavaDieHandler);
#endif
		/* Register an on_proc_exit handler that destroys the VM
		 */
		on_proc_exit(_destroyJavaVM, 0);
		initstage = IS_SIGHANDLERS;

	case IS_SIGHANDLERS:
		Invocation_pushBootContext(&ctx);
		PG_TRY();
		{
			initPLJavaClasses();
			initJavaSession();
			Invocation_popBootContext();
			initstage = IS_PLJAVA_FOUND;
		}
		PG_CATCH();
		{
			MemoryContextSwitchTo(ctx.upperContext); /* leave ErrorContext */
			Invocation_popBootContext();
			initstage = IS_MISC_ONCE_DONE;
			/* We can't stay here...
			 */
			if ( tolerant )
				reLogWithChangedLevel(WARNING); /* so xact is not aborted */
			else
			{
				EmitErrorReport(); /* no more unwinding, just log it */
				/* Seeing an ERROR emitted to the log, without leaving the
				 * transaction aborted, would violate the principle of least
				 * astonishment. But at check_tolerant below, another ERROR will
				 * be thrown immediately, so the transaction effect will be as
				 * expected and this ERROR will contribute information beyond
				 * what is in the generic one thrown down there.
				 */
				FlushErrorState();
			}
		}
		PG_END_TRY();
		if ( IS_PLJAVA_FOUND != initstage )
		{
			/* JVM initialization failed for some reason. Destroy
			 * the VM if it exists. Perhaps the user will try
			 * fixing the pljava.classpath and make a new attempt.
			 */
			ereport(WARNING, (
				errmsg("failed to load initial PL/Java classes"),
				errhint("The most common reason is that \"pljava_classpath\" "
					"needs to be set, naming the proper \"pljava.jar\" file.")
					));
			_destroyJavaVM(0, 0);
			goto check_tolerant;
		}

	case IS_PLJAVA_FOUND:
		greeting = InstallHelper_hello();
		ereport(NULL != pljavaLoadPath ? NOTICE : DEBUG1, (
				errmsg("PL/Java loaded"),
				errdetail("versions:\n%s", greeting)));
		pfree(greeting);
		if ( NULL != pljavaLoadPath )
			InstallHelper_groundwork(); /* sqlj schema, language handlers, ...*/
		initstage = IS_COMPLETE;

	case IS_COMPLETE:
		pljavaLoadingAsExtension = false;
		if ( alteredSettingsWereNeeded )
		{
			/* Use this StringInfoData to conditionally construct part of the
			 * hint string suggesting ALTER DATABASE ... SET ... FROM CURRENT
			 * provided the server is >= 9.2 where that will actually work.
			 * In 9.3, psprintf appeared, which would make this all simpler,
			 * but if 9.3+ were all that had to be supported, this would all
			 * be moot anyway. Doing the initStringInfo inside the ereport
			 * ensures the string is allocated in ErrorContext and won't leak.
			 * Don't remove the extra parens grouping
			 * (initStringInfo, appendStringInfo, errhint) ... with the parens,
			 * that's a comma expression, which is sequenced; without them, they
			 * are just function parameters with evaluation order unknown.
			 */
			StringInfoData buf;
#if PG_VERSION_NUM >= 90200
#define MOREHINT \
				appendStringInfo(&buf, \
					"using ALTER DATABASE %s SET ... FROM CURRENT or ", \
					pljavaDbName()),
#else
#define MOREHINT
#endif
			ereport(NOTICE, (
				errmsg("PL/Java successfully started after adjusting settings"),
				(initStringInfo(&buf),
				MOREHINT
				errhint("The settings that worked should be saved (%s"
					"in the \"%s\" file). For a reminder of what has been set, "
					"try: SELECT name, setting FROM pg_settings WHERE name LIKE"
					" 'pljava.%%' AND source = 'session'",
					buf.data,
					superuser()
						? PG_GETCONFIGOPTION("config_file")
						: "postgresql.conf"))));
#undef MOREHINT
			if ( loadAsExtensionFailed )
			{
				ereport(NOTICE, (errmsg(
					"PL/Java load successful after failed CREATE EXTENSION"),
					errdetail(
					"PL/Java is now installed, but not as an extension."),
					errhint(
					"To correct that, either COMMIT or ROLLBACK, make sure "
					"the working settings are saved, exit this session, and "
					"in a new session, either: "
					"1. if committed, run "
					"\"CREATE EXTENSION pljava FROM unpackaged\", or 2. "
					"if rolled back, simply \"CREATE EXTENSION pljava\" again."
					)));
			}
		}
		return;

	default:
		ereport(ERROR, (
			errmsg("cannot set up PL/Java"),
			errdetail(
				"An unexpected stage was reached in the startup sequence."),
			errhint(
				"Please report the circumstances to the PL/Java maintainers.")
			));
	}

check_tolerant:
	if ( pljavaLoadingAsExtension )
	{
		tolerant = false;
		loadAsExtensionFailed = true;
		pljavaLoadingAsExtension = false;
	}
	if ( !tolerant )
	{
		ereport(ERROR, (
			errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
			errmsg(
				"cannot use PL/Java before successfully completing its setup"),
			errhint(
				"Check the log for messages closely preceding this one, "
				"detailing what step of setup failed and what will be needed, "
				"probably setting one of the \"pljava.\" configuration "
				"variables, to complete the setup. If there is not enough "
				"help in the log, try again with different settings for "
				"\"log_min_messages\" or \"log_error_verbosity\".")));
	}
}
コード例 #19
0
static PyObject *
PLy_cursor_plan(PyObject *ob, PyObject *args)
{
	PLyCursorObject *cursor;
	volatile int nargs;
	int			i;
	PLyPlanObject *plan;
	volatile MemoryContext oldcontext;
	volatile ResourceOwner oldowner;

	if (args)
	{
		if (!PySequence_Check(args) || PyString_Check(args) || PyUnicode_Check(args))
		{
			PLy_exception_set(PyExc_TypeError, "plpy.cursor takes a sequence as its second argument");
			return NULL;
		}
		nargs = PySequence_Length(args);
	}
	else
		nargs = 0;

	plan = (PLyPlanObject *) ob;

	if (nargs != plan->nargs)
	{
		char	   *sv;
		PyObject   *so = PyObject_Str(args);

		if (!so)
			PLy_elog(ERROR, "could not execute plan");
		sv = PyString_AsString(so);
		PLy_exception_set_plural(PyExc_TypeError,
							  "Expected sequence of %d argument, got %d: %s",
							 "Expected sequence of %d arguments, got %d: %s",
								 plan->nargs,
								 plan->nargs, nargs, sv);
		Py_DECREF(so);

		return NULL;
	}

	if ((cursor = PyObject_New(PLyCursorObject, &PLy_CursorType)) == NULL)
		return NULL;
	cursor->portalname = NULL;
	cursor->closed = false;
	cursor->mcxt = AllocSetContextCreate(TopMemoryContext,
										 "PL/Python cursor context",
										 ALLOCSET_DEFAULT_MINSIZE,
										 ALLOCSET_DEFAULT_INITSIZE,
										 ALLOCSET_DEFAULT_MAXSIZE);
	PLy_typeinfo_init(&cursor->result, cursor->mcxt);

	oldcontext = CurrentMemoryContext;
	oldowner = CurrentResourceOwner;

	PLy_spi_subtransaction_begin(oldcontext, oldowner);

	PG_TRY();
	{
		PLyExecutionContext *exec_ctx = PLy_current_execution_context();
		Portal		portal;
		char	   *volatile nulls;
		volatile int j;

		if (nargs > 0)
			nulls = palloc(nargs * sizeof(char));
		else
			nulls = NULL;

		for (j = 0; j < nargs; j++)
		{
			PyObject   *elem;

			elem = PySequence_GetItem(args, j);
			if (elem != Py_None)
			{
				PG_TRY();
				{
					plan->values[j] =
						plan->args[j].out.d.func(&(plan->args[j].out.d),
												 -1,
												 elem);
				}
				PG_CATCH();
				{
					Py_DECREF(elem);
					PG_RE_THROW();
				}
				PG_END_TRY();

				Py_DECREF(elem);
				nulls[j] = ' ';
			}
			else
			{
				Py_DECREF(elem);
				plan->values[j] =
					InputFunctionCall(&(plan->args[j].out.d.typfunc),
									  NULL,
									  plan->args[j].out.d.typioparam,
									  -1);
				nulls[j] = 'n';
			}
		}

		portal = SPI_cursor_open(NULL, plan->plan, plan->values, nulls,
								 exec_ctx->curr_proc->fn_readonly);
		if (portal == NULL)
			elog(ERROR, "SPI_cursor_open() failed: %s",
				 SPI_result_code_string(SPI_result));

		cursor->portalname = MemoryContextStrdup(cursor->mcxt, portal->name);

		PLy_spi_subtransaction_commit(oldcontext, oldowner);
	}
	PG_CATCH();
	{
		int			k;

		/* cleanup plan->values array */
		for (k = 0; k < nargs; k++)
		{
			if (!plan->args[k].out.d.typbyval &&
				(plan->values[k] != PointerGetDatum(NULL)))
			{
				pfree(DatumGetPointer(plan->values[k]));
				plan->values[k] = PointerGetDatum(NULL);
			}
		}

		Py_DECREF(cursor);

		PLy_spi_subtransaction_abort(oldcontext, oldowner);
		return NULL;
	}
	PG_END_TRY();

	for (i = 0; i < nargs; i++)
	{
		if (!plan->args[i].out.d.typbyval &&
			(plan->values[i] != PointerGetDatum(NULL)))
		{
			pfree(DatumGetPointer(plan->values[i]));
			plan->values[i] = PointerGetDatum(NULL);
		}
	}

	Assert(cursor->portalname != NULL);
	return (PyObject *) cursor;
}
コード例 #20
0
ファイル: smgr_ao.c プロジェクト: PengJi/gpdb-comments
void
AppendOnlyMirrorResyncEofs_Merge(RelFileNode *relFileNode,
								 int32 segmentFileNum,
								 int nestLevel, /* Transaction nesting level. */
								 char *relationName,
								 ItemPointer persistentTid,
								 int64 persistentSerialNum,
								 bool mirrorCatchupRequired,
								 MirrorDataLossTrackingState mirrorDataLossTrackingState,
								 int64 mirrorDataLossTrackingSessionNum,
								 int64 mirrorNewEof)
{
	int64		previousMirrorNewEof = 0;

	AppendOnlyMirrorResyncEofsKey key;
	AppendOnlyMirrorResyncEofs *entry;
	bool		found;

	if (AppendOnlyMirrorResyncEofsTable == NULL)
		AppendOnlyMirrorResyncEofs_HashTableInit();

	AppendOnlyMirrorResyncEofs_InitKey(
									   &key,
									   relFileNode,
									   segmentFileNum,
									   nestLevel);

	entry =
		(AppendOnlyMirrorResyncEofs *)
		hash_search(AppendOnlyMirrorResyncEofsTable,
					(void *) &key,
					HASH_ENTER,
					&found);

	if (!found)
	{
		entry->relationName = MemoryContextStrdup(TopMemoryContext, relationName);
		entry->persistentSerialNum = persistentSerialNum;
		entry->persistentTid = *persistentTid;
		entry->didIncrementCommitCount = false;
		entry->isDistributedTransaction = false;
		entry->gid[0] = '\0';
		entry->mirrorCatchupRequired = mirrorCatchupRequired;
		entry->mirrorDataLossTrackingState = mirrorDataLossTrackingState;
		entry->mirrorDataLossTrackingSessionNum = mirrorDataLossTrackingSessionNum;
		entry->mirrorNewEof = mirrorNewEof;
	}
	else
	{
		previousMirrorNewEof = entry->mirrorNewEof;

		/*
		 * UNDONE: What is the purpose of this IF stmt?  Shouldn't we always
		 * set the new EOF?
		 */
		if (mirrorNewEof > entry->mirrorNewEof)
			entry->mirrorNewEof = mirrorNewEof;

		/*
		 * We adopt the newer FileRep state because we accurately track the
		 * state of mirror data.  For example, the first write session might
		 * have had loss because the mirror was down.  But then the second
		 * write session discovered we were in sync and copied both the first
		 * and second write session to the mirror and flushed it.
		 */
		entry->mirrorCatchupRequired = mirrorCatchupRequired;
		entry->mirrorDataLossTrackingState = mirrorDataLossTrackingState;
		entry->mirrorDataLossTrackingSessionNum = mirrorDataLossTrackingSessionNum;
	}

	if (Debug_persistent_print ||
		Debug_persistent_appendonly_commit_count_print)
		elog(Persistent_DebugPrintLevel(),
			 "Storage Manager: %s Append-Only mirror resync eofs entry: %u/%u/%u, segment file #%d, relation name '%s' (transaction nest level %d, persistent TID %s, persistent serial number " INT64_FORMAT ", "
			 "mirror data loss tracking (state '%s', session num " INT64_FORMAT "), "
			 "previous mirror new EOF " INT64_FORMAT ", input mirror new EOF " INT64_FORMAT ", saved mirror new EOF " INT64_FORMAT ")",
			 (found ? "Merge" : "New"),
			 entry->key.relFileNode.spcNode,
			 entry->key.relFileNode.dbNode,
			 entry->key.relFileNode.relNode,
			 entry->key.segmentFileNum,
			 (entry->relationName == NULL ? "<null>" : entry->relationName),
			 entry->key.nestLevel,
			 ItemPointerToString(&entry->persistentTid),
			 entry->persistentSerialNum,
			 MirrorDataLossTrackingState_Name(mirrorDataLossTrackingState),
			 mirrorDataLossTrackingSessionNum,
			 previousMirrorNewEof,
			 mirrorNewEof,
			 entry->mirrorNewEof);
}
コード例 #21
0
ファイル: execWorkfile_test.c プロジェクト: AnLingm/gpdb
/*
 * This is a mocked version of pstrdup to be used in ExecWorkFile_Create.
 *   It asserts that it is executed in the TopMemoryContext.
 */
char *execWorkfile_pstrdup_mock(const char *string)
{
	assert_int_equal(CurrentMemoryContext, TopMemoryContext);
	return MemoryContextStrdup(CurrentMemoryContext, string);
}
コード例 #22
0
ファイル: pg_locale.c プロジェクト: PengJi/gpdb-comments
/*
 * Update the lc_time localization cache variables if needed.
 */
void
cache_locale_time(void)
{
	char	   *save_lc_time;
	time_t		timenow;
	struct tm  *timeinfo;
	char		buf[MAX_L10N_DATA];
	char	   *ptr;
	int			i;
#ifdef WIN32
	char	   *save_lc_ctype;
#endif

#ifdef WIN32
	char	   *save_lc_ctype;
#endif

	/* did we do this already? */
	if (CurrentLCTimeValid)
		return;

	elog(DEBUG3, "cache_locale_time() executed; locale: \"%s\"", locale_time);

#ifdef WIN32
	/* set user's value of ctype locale */
	save_lc_ctype = setlocale(LC_CTYPE, NULL);
	if (save_lc_ctype)
		save_lc_ctype = pstrdup(save_lc_ctype);

	setlocale(LC_CTYPE, locale_time);
#endif

	/* set user's value of time locale */
	save_lc_time = setlocale(LC_TIME, NULL);
	if (save_lc_time)
		save_lc_time = pstrdup(save_lc_time);

	setlocale(LC_TIME, locale_time);

	timenow = time(NULL);
	timeinfo = localtime(&timenow);

	/* localized days */
	for (i = 0; i < 7; i++)
	{
		timeinfo->tm_wday = i;
		strftime(buf, MAX_L10N_DATA, "%a", timeinfo);
		ptr = MemoryContextStrdup(TopMemoryContext, buf);
		if (localized_abbrev_days[i])
			pfree(localized_abbrev_days[i]);
		localized_abbrev_days[i] = ptr;

		strftime(buf, MAX_L10N_DATA, "%A", timeinfo);
		ptr = MemoryContextStrdup(TopMemoryContext, buf);
		if (localized_full_days[i])
			pfree(localized_full_days[i]);
		localized_full_days[i] = ptr;
	}

	/* localized months */
	for (i = 0; i < 12; i++)
	{
		timeinfo->tm_mon = i;
		timeinfo->tm_mday = 1;	/* make sure we don't have invalid date */
		strftime(buf, MAX_L10N_DATA, "%b", timeinfo);
		ptr = MemoryContextStrdup(TopMemoryContext, buf);
		if (localized_abbrev_months[i])
			pfree(localized_abbrev_months[i]);
		localized_abbrev_months[i] = ptr;

		strftime(buf, MAX_L10N_DATA, "%B", timeinfo);
		ptr = MemoryContextStrdup(TopMemoryContext, buf);
		if (localized_full_months[i])
			pfree(localized_full_months[i]);
		localized_full_months[i] = ptr;
	}

	/* try to restore internal settings */
	if (save_lc_time)
	{
		setlocale(LC_TIME, save_lc_time);
		pfree(save_lc_time);
	}

#ifdef WIN32
	/* try to restore internal ctype settings */
	if (save_lc_ctype)
	{
		setlocale(LC_CTYPE, save_lc_ctype);
		pfree(save_lc_ctype);
	}
#endif

	CurrentLCTimeValid = true;
}
コード例 #23
0
ファイル: mcxt.c プロジェクト: gavioto/postgres_cluster
char *
pstrdup(const char *in)
{
	return MemoryContextStrdup(CurrentMemoryContext, in);
}
コード例 #24
0
/*
 * StartPlacementListConnection returns a connection to a remote node suitable for
 * a placement accesses (SELECT, DML, DDL) or throws an error if no suitable
 * connection can be established if would cause a self-deadlock or consistency
 * violation.
 */
MultiConnection *
StartPlacementListConnection(uint32 flags, List *placementAccessList,
							 const char *userName)
{
	char *freeUserName = NULL;
	ListCell *placementAccessCell = NULL;
	List *placementEntryList = NIL;
	ListCell *placementEntryCell = NULL;
	MultiConnection *chosenConnection = NULL;

	if (userName == NULL)
	{
		userName = freeUserName = CurrentUserName();
	}

	chosenConnection = FindPlacementListConnection(flags, placementAccessList, userName,
												   &placementEntryList);
	if (chosenConnection == NULL)
	{
		/* use the first placement from the list to extract nodename and nodeport */
		ShardPlacementAccess *placementAccess =
			(ShardPlacementAccess *) linitial(placementAccessList);
		ShardPlacement *placement = placementAccess->placement;
		char *nodeName = placement->nodeName;
		int nodePort = placement->nodePort;

		/*
		 * No suitable connection in the placement->connection mapping, get one from
		 * the node->connection pool.
		 */
		chosenConnection = StartNodeUserDatabaseConnection(flags, nodeName, nodePort,
														   userName, NULL);

		if (flags & CONNECTION_PER_PLACEMENT &&
			ConnectionAccessedDifferentPlacement(chosenConnection, placement))
		{
			/*
			 * Cached connection accessed a non-co-located placement in the same
			 * table or co-location group, while the caller asked for a connection
			 * per placement. Open a new connection instead.
			 *
			 * We use this for situations in which we want to use a different
			 * connection for every placement, such as COPY. If we blindly returned
			 * a cached conection that already modified a different, non-co-located
			 * placement B in the same table or in a table with the same co-location
			 * ID as the current placement, then we'd no longer able to write to
			 * placement B later in the COPY.
			 */
			chosenConnection = StartNodeUserDatabaseConnection(flags |
															   FORCE_NEW_CONNECTION,
															   nodeName, nodePort,
															   userName, NULL);

			Assert(!ConnectionAccessedDifferentPlacement(chosenConnection, placement));
		}
	}

	/*
	 * Now that a connection has been chosen, initialise or update the connection
	 * references for all placements.
	 */
	forboth(placementAccessCell, placementAccessList,
			placementEntryCell, placementEntryList)
	{
		ShardPlacementAccess *placementAccess =
			(ShardPlacementAccess *) lfirst(placementAccessCell);
		ShardPlacementAccessType accessType = placementAccess->accessType;
		ConnectionPlacementHashEntry *placementEntry =
			(ConnectionPlacementHashEntry *) lfirst(placementEntryCell);
		ConnectionReference *placementConnection = placementEntry->primaryConnection;

		if (placementConnection->connection == chosenConnection)
		{
			/* using the connection that was already assigned to the placement */
		}
		else if (placementConnection->connection == NULL)
		{
			/* placement does not have a connection assigned yet */
			placementConnection->connection = chosenConnection;
			placementConnection->hadDDL = false;
			placementConnection->hadDML = false;
			placementConnection->userName = MemoryContextStrdup(TopTransactionContext,
																userName);
			placementConnection->placementId = placementAccess->placement->placementId;

			/* record association with connection */
			dlist_push_tail(&chosenConnection->referencedPlacements,
							&placementConnection->connectionNode);
		}
		else
		{
			/* using a different connection than the one assigned to the placement */

			if (accessType != PLACEMENT_ACCESS_SELECT)
			{
				/*
				 * We previously read from the placement, but now we're writing to
				 * it (if we had written to the placement, we would have either chosen
				 * the same connection, or errored out). Update the connection reference
				 * to point to the connection used for writing. We don't need to remember
				 * the existing connection since we won't be able to reuse it for
				 * accessing the placement. However, we do register that it exists in
				 * hasSecondaryConnections.
				 */
				placementConnection->connection = chosenConnection;
				placementConnection->userName = MemoryContextStrdup(TopTransactionContext,
																	userName);

				Assert(!placementConnection->hadDDL);
				Assert(!placementConnection->hadDML);

				/* record association with connection */
				dlist_push_tail(&chosenConnection->referencedPlacements,
								&placementConnection->connectionNode);
			}

			/*
			 * There are now multiple connections that read from the placement
			 * and DDL commands are forbidden.
			 */
			placementEntry->hasSecondaryConnections = true;

			if (placementEntry->colocatedEntry != NULL)
			{
				/* we also remember this for co-located placements */
				placementEntry->colocatedEntry->hasSecondaryConnections = true;
			}
		}

		/*
		 * Remember that we used the current connection for writes.
		 */
		if (accessType == PLACEMENT_ACCESS_DDL)
		{
			placementConnection->hadDDL = true;
		}

		if (accessType == PLACEMENT_ACCESS_DML)
		{
			placementConnection->hadDML = true;
		}
	}