ruleutils.c

来自「PostgreSQL7.4.6 for Linux」· C语言 代码 · 共 2,475 行 · 第 1/5 页

C
2,475
字号
						break;					case FKCONSTR_ACTION_CASCADE:						string = "CASCADE";						break;					case FKCONSTR_ACTION_SETNULL:						string = "SET NULL";						break;					case FKCONSTR_ACTION_SETDEFAULT:						string = "SET DEFAULT";						break;					default:						elog(ERROR, "unrecognized confdeltype: %d",							 conForm->confdeltype);						string = NULL;	/* keep compiler quiet */						break;				}				if (string)					appendStringInfo(&buf, " ON DELETE %s", string);				if (conForm->condeferrable)					appendStringInfo(&buf, " DEFERRABLE");				if (conForm->condeferred)					appendStringInfo(&buf, " INITIALLY DEFERRED");				break;			}		case CONSTRAINT_PRIMARY:		case CONSTRAINT_UNIQUE:			{				Datum		val;				bool		isnull;				/* Start off the constraint definition */				if (conForm->contype == CONSTRAINT_PRIMARY)					appendStringInfo(&buf, "PRIMARY KEY (");				else					appendStringInfo(&buf, "UNIQUE (");				/* Fetch and build target column list */				val = heap_getattr(tup, Anum_pg_constraint_conkey,								   RelationGetDescr(conDesc), &isnull);				if (isnull)					elog(ERROR, "null conkey for constraint %u",						 constraintId);				decompile_column_index_array(val, conForm->conrelid, &buf);				appendStringInfo(&buf, ")");				break;			}		case CONSTRAINT_CHECK:			{				Datum		val;				bool		isnull;				char	   *conbin;				char	   *consrc;				Node	   *expr;				List	   *context;				/* Fetch constraint expression in parsetree form */				val = heap_getattr(tup, Anum_pg_constraint_conbin,								   RelationGetDescr(conDesc), &isnull);				if (isnull)					elog(ERROR, "null conbin for constraint %u",						 constraintId);				conbin = DatumGetCString(DirectFunctionCall1(textout, val));				expr = stringToNode(conbin);				/*				 * If top level is a List, assume it is an implicit-AND				 * structure, and convert to explicit AND.	This is needed				 * for partial index predicates.				 */				if (expr && IsA(expr, List))					expr = (Node *) make_ands_explicit((List *) expr);				/* Set up deparsing context for Var nodes in constraint */				if (conForm->conrelid != InvalidOid)				{					/* relation constraint */					context = deparse_context_for(get_rel_name(conForm->conrelid),												  conForm->conrelid);				}				else				{					/* domain constraint --- can't have Vars */					context = NIL;				}				consrc = deparse_expression_pretty(expr, context, false, false,												   prettyFlags, 0);				/*				 * Now emit the constraint definition.  There are cases where				 * the constraint expression will be fully parenthesized and				 * we don't need the outer parens ... but there are other				 * cases where we do need 'em.  Be conservative for now.				 *				 * Note that simply checking for leading '(' and trailing ')'				 * would NOT be good enough, consider "(x > 0) AND (y > 0)".				 */				appendStringInfo(&buf, "CHECK (%s)", consrc);				break;			}		default:			elog(ERROR, "invalid constraint type \"%c\"", conForm->contype);			break;	}	/* Record the results */	len = buf.len + VARHDRSZ;	result = (text *) palloc(len);	VARATT_SIZEP(result) = len;	memcpy(VARDATA(result), buf.data, buf.len);	/* Cleanup */	pfree(buf.data);	systable_endscan(conscan);	heap_close(conDesc, AccessShareLock);	PG_RETURN_TEXT_P(result);}/* * Convert an int16[] Datum into a comma-separated list of column names * for the indicated relation; append the list to buf. */static voiddecompile_column_index_array(Datum column_index_array, Oid relId,							 StringInfo buf){	Datum	   *keys;	int			nKeys;	int			j;	/* Extract data from array of int16 */	deconstruct_array(DatumGetArrayTypeP(column_index_array),					  INT2OID, 2, true, 's',					  &keys, &nKeys);	for (j = 0; j < nKeys; j++)	{		char	   *colName;		colName = get_relid_attribute_name(relId, DatumGetInt16(keys[j]));		if (j == 0)			appendStringInfo(buf, "%s",							 quote_identifier(colName));		else			appendStringInfo(buf, ", %s",							 quote_identifier(colName));	}}/* ---------- * get_expr			- Decompile an expression tree * * Input: an expression tree in nodeToString form, and a relation OID * * Output: reverse-listed expression * * Currently, the expression can only refer to a single relation, namely * the one specified by the second parameter.  This is sufficient for * partial indexes, column default expressions, etc. * ---------- */Datumpg_get_expr(PG_FUNCTION_ARGS){	text	   *expr = PG_GETARG_TEXT_P(0);	Oid			relid = PG_GETARG_OID(1);	char	   *relname;	/* Get the name for the relation */	relname = get_rel_name(relid);	if (relname == NULL)		PG_RETURN_NULL();		/* should we raise an error? */	return pg_get_expr_worker(expr, relid, relname, 0);}Datumpg_get_expr_ext(PG_FUNCTION_ARGS){	text	   *expr = PG_GETARG_TEXT_P(0);	Oid			relid = PG_GETARG_OID(1);	bool		pretty = PG_GETARG_BOOL(2);	int			prettyFlags;	char	   *relname;	prettyFlags = pretty ? PRETTYFLAG_PAREN | PRETTYFLAG_INDENT : 0;	/* Get the name for the relation */	relname = get_rel_name(relid);	if (relname == NULL)		PG_RETURN_NULL();		/* should we raise an error? */	return pg_get_expr_worker(expr, relid, relname, prettyFlags);}static Datumpg_get_expr_worker(text *expr, Oid relid, char *relname, int prettyFlags){	text	   *result;	Node	   *node;	List	   *context;	char	   *exprstr;	char	   *str;	/* Convert input TEXT object to C string */	exprstr = DatumGetCString(DirectFunctionCall1(textout,												  PointerGetDatum(expr)));	/* Convert expression to node tree */	node = (Node *) stringToNode(exprstr);	/*	 * If top level is a List, assume it is an implicit-AND structure, and	 * convert to explicit AND.  This is needed for partial index	 * predicates.	 */	if (node && IsA(node, List))		node = (Node *) make_ands_explicit((List *) node);	/* Deparse */	context = deparse_context_for(relname, relid);	str = deparse_expression_pretty(node, context, false, false,									prettyFlags, 0);	/* Pass the result back as TEXT */	result = DatumGetTextP(DirectFunctionCall1(textin,											   CStringGetDatum(str)));	PG_RETURN_TEXT_P(result);}/* ---------- * get_userbyid			- Get a user name by usesysid and *				  fallback to 'unknown (UID=n)' * ---------- */Datumpg_get_userbyid(PG_FUNCTION_ARGS){	int32		uid = PG_GETARG_INT32(0);	Name		result;	HeapTuple	usertup;	Form_pg_shadow user_rec;	/*	 * Allocate space for the result	 */	result = (Name) palloc(NAMEDATALEN);	memset(NameStr(*result), 0, NAMEDATALEN);	/*	 * Get the pg_shadow entry and print the result	 */	usertup = SearchSysCache(SHADOWSYSID,							 ObjectIdGetDatum(uid),							 0, 0, 0);	if (HeapTupleIsValid(usertup))	{		user_rec = (Form_pg_shadow) GETSTRUCT(usertup);		StrNCpy(NameStr(*result), NameStr(user_rec->usename), NAMEDATALEN);		ReleaseSysCache(usertup);	}	else		sprintf(NameStr(*result), "unknown (UID=%d)", uid);	PG_RETURN_NAME(result);}/* ---------- * deparse_expression			- General utility for deparsing expressions * * calls deparse_expression_pretty with all prettyPrinting disabled */char *deparse_expression(Node *expr, List *dpcontext,				   bool forceprefix, bool showimplicit){	return deparse_expression_pretty(expr, dpcontext, forceprefix,									 showimplicit, 0, 0);}/* ---------- * deparse_expression_pretty	- General utility for deparsing expressions * * expr is the node tree to be deparsed.  It must be a transformed expression * tree (ie, not the raw output of gram.y). * * dpcontext is a list of deparse_namespace nodes representing the context * for interpreting Vars in the node tree. * * forceprefix is TRUE to force all Vars to be prefixed with their table names. * * showimplicit is TRUE to force all implicit casts to be shown explicitly. * * tries to pretty up the output according to prettyFlags and startIndent. * * The result is a palloc'd string. * ---------- */static char *deparse_expression_pretty(Node *expr, List *dpcontext,						  bool forceprefix, bool showimplicit,						  int prettyFlags, int startIndent){	StringInfoData buf;	deparse_context context;	initStringInfo(&buf);	context.buf = &buf;	context.namespaces = dpcontext;	context.varprefix = forceprefix;	context.prettyFlags = prettyFlags;	context.indentLevel = startIndent;	get_rule_expr(expr, &context, showimplicit);	return buf.data;}/* ---------- * deparse_context_for			- Build deparse context for a single relation * * Given the reference name (alias) and OID of a relation, build deparsing * context for an expression referencing only that relation (as varno 1, * varlevelsup 0).	This is sufficient for many uses of deparse_expression. * ---------- */List *deparse_context_for(const char *aliasname, Oid relid){	deparse_namespace *dpns;	RangeTblEntry *rte;	dpns = (deparse_namespace *) palloc(sizeof(deparse_namespace));	/* Build a minimal RTE for the rel */	rte = makeNode(RangeTblEntry);	rte->rtekind = RTE_RELATION;	rte->relid = relid;	rte->eref = makeAlias(aliasname, NIL);	rte->inh = false;	rte->inFromCl = true;	/* Build one-element rtable */	dpns->rtable = makeList1(rte);	dpns->outer_varno = dpns->inner_varno = 0;	dpns->outer_rte = dpns->inner_rte = NULL;	/* Return a one-deep namespace stack */	return makeList1(dpns);}/* * deparse_context_for_plan		- Build deparse context for a plan node * * We assume we are dealing with an upper-level plan node having either * one or two referenceable children (pass innercontext = NULL if only one). * The passed-in Nodes should be made using deparse_context_for_subplan * and/or deparse_context_for_relation.  The resulting context will work * for deparsing quals, tlists, etc of the plan node. * * An rtable list can also be passed in case plain Vars might be seen. * This is not needed for true upper-level expressions, but is helpful for * Sort nodes and similar cases with slightly bogus targetlists. */List *deparse_context_for_plan(int outer_varno, Node *outercontext,						 int inner_varno, Node *innercontext,						 List *rtable){	deparse_namespace *dpns;	dpns = (deparse_namespace *) palloc(sizeof(deparse_namespace));	dpns->rtable = rtable;	dpns->outer_varno = outer_varno;	dpns->outer_rte = (RangeTblEntry *) outercontext;	dpns->inner_varno = inner_varno;	dpns->inner_rte = (RangeTblEntry *) innercontext;	/* Return a one-deep namespace stack */	return makeList1(dpns);}/* * deparse_context_for_rte		- Build deparse context for 1 relation * * Helper routine to build one of the inputs for deparse_context_for_plan. * * The returned node is actually the given RangeTblEntry, but we declare it * as just Node to discourage callers from assuming anything. */Node *deparse_context_for_rte(RangeTblEntry *rte){	return (Node *) rte;}/* * deparse_context_for_subplan	- Build deparse context for a plan node * * Helper routine to build one of the inputs for deparse_context_for_plan. * Pass the tlist of the subplan node, plus the query rangetable. * * The returned node is actually a RangeTblEntry, but we declare it as just * Node to discourage callers from assuming anything. */Node *deparse_context_for_subplan(const char *name, List *tlist,							List *rtable){	RangeTblEntry *rte = makeNode(RangeTblEntry);	List	   *attrs = NIL;	int			nattrs = 0;	int			rtablelength = length(rtable);	List	   *tl;	char		buf[32];	foreach(tl, tlist)	{		TargetEntry *tle = lfirst(tl);		Resdom	   *resdom = tle->resdom;		nattrs++;		Assert(resdom->resno == nattrs);		if (resdom->resname)		{			attrs = lappend(attrs, makeString(resdom->resname));			continue;		}		if (tle->expr && IsA(tle->expr, Var))		{			Var		   *var = (Var *) tle->expr;			/* varno/varattno won't be any good, but varnoold might be */			if (var->varnoold > 0 && var->varnoold <= rtablelength)			{				RangeTblEntry *varrte = rt_fetch(var->varnoold, rtable);				char	   *varname;				varname = get_rte_attribute_name(varrte, var->varoattno);				attrs = lappend(attrs, makeString(varname));				continue;			}		}		/* Fallback if can't get name */		snprintf(buf, sizeof(buf), "?column%d?", resdom->resno);		attrs = lappend(attrs, makeString(pstrdup(buf)));	}	rte->rtekind = RTE_SPECIAL; /* XXX */	rte->relid = InvalidOid;	rte->eref = makeAlias(name, attrs);	rte->inh = false;	rte->inFromCl = true;	return (Node *) rte;}/* ---------- * make_ruledef			- reconstruct the CREATE RULE command *				  for a given pg_rewrite tuple * ---------- */static voidmake_ruledef(StringInfo buf, HeapTuple ruletup, TupleDesc rulettc,			 int prettyFlags){	char	   *rulename;	char		ev_type;	Oid			ev_class;	int2		ev_attr;	bool		is_instead;	char	   *ev_qual;	char	   *ev_action;	List	   *actions = NIL;	int			fno;	Datum		dat;	bool		isnull;	/*	 * Get the attribute values from the rules tuple	 */

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?