ruleutils.c

来自「postgresql8.3.4源码,开源数据库」· C语言 代码 · 共 2,446 行 · 第 1/5 页

C
2,446
字号
			appendStringInfo(&buf, " DELETE");		findx++;	}	if (TRIGGER_FOR_UPDATE(trigrec->tgtype))	{		if (findx > 0)			appendStringInfo(&buf, " OR UPDATE");		else			appendStringInfo(&buf, " UPDATE");	}	appendStringInfo(&buf, " ON %s ",					 generate_relation_name(trigrec->tgrelid));	if (trigrec->tgisconstraint)	{		if (trigrec->tgconstrrelid != InvalidOid)			appendStringInfo(&buf, "FROM %s ",							 generate_relation_name(trigrec->tgconstrrelid));		if (!trigrec->tgdeferrable)			appendStringInfo(&buf, "NOT ");		appendStringInfo(&buf, "DEFERRABLE INITIALLY ");		if (trigrec->tginitdeferred)			appendStringInfo(&buf, "DEFERRED ");		else			appendStringInfo(&buf, "IMMEDIATE ");	}	if (TRIGGER_FOR_ROW(trigrec->tgtype))		appendStringInfo(&buf, "FOR EACH ROW ");	else		appendStringInfo(&buf, "FOR EACH STATEMENT ");	appendStringInfo(&buf, "EXECUTE PROCEDURE %s(",					 generate_function_name(trigrec->tgfoid, 0, NULL));	if (trigrec->tgnargs > 0)	{		bytea	   *val;		bool		isnull;		char	   *p;		int			i;		val = DatumGetByteaP(fastgetattr(ht_trig,										 Anum_pg_trigger_tgargs,										 tgrel->rd_att, &isnull));		if (isnull)			elog(ERROR, "tgargs is null for trigger %u", trigid);		p = (char *) VARDATA(val);		for (i = 0; i < trigrec->tgnargs; i++)		{			if (i > 0)				appendStringInfo(&buf, ", ");			/*			 * We form the string literal according to the prevailing setting			 * of standard_conforming_strings; we never use E''. User is			 * responsible for making sure result is used correctly.			 */			appendStringInfoChar(&buf, '\'');			while (*p)			{				char		ch = *p++;				if (SQL_STR_DOUBLE(ch, !standard_conforming_strings))					appendStringInfoChar(&buf, ch);				appendStringInfoChar(&buf, ch);			}			appendStringInfoChar(&buf, '\'');			/* advance p to next string embedded in tgargs */			p++;		}	}	/* We deliberately do not put semi-colon at end */	appendStringInfo(&buf, ")");	/* Clean up */	systable_endscan(tgscan);	heap_close(tgrel, AccessShareLock);	PG_RETURN_TEXT_P(string_to_text(buf.data));}/* ---------- * get_indexdef			- Get the definition of an index * * In the extended version, there is a colno argument as well as pretty bool. *	if colno == 0, we want a complete index definition. *	if colno > 0, we only want the Nth index key's variable or expression. * * Note that the SQL-function versions of this omit any info about the * index tablespace; this is intentional because pg_dump wants it that way. * However pg_get_indexdef_string() includes index tablespace if not default. * ---------- */Datumpg_get_indexdef(PG_FUNCTION_ARGS){	Oid			indexrelid = PG_GETARG_OID(0);	PG_RETURN_TEXT_P(string_to_text(pg_get_indexdef_worker(indexrelid, 0,														   false, 0)));}Datumpg_get_indexdef_ext(PG_FUNCTION_ARGS){	Oid			indexrelid = PG_GETARG_OID(0);	int32		colno = PG_GETARG_INT32(1);	bool		pretty = PG_GETARG_BOOL(2);	int			prettyFlags;	prettyFlags = pretty ? PRETTYFLAG_PAREN | PRETTYFLAG_INDENT : 0;	PG_RETURN_TEXT_P(string_to_text(pg_get_indexdef_worker(indexrelid, colno,													   false, prettyFlags)));}/* Internal version that returns a palloc'd C string */char *pg_get_indexdef_string(Oid indexrelid){	return pg_get_indexdef_worker(indexrelid, 0, true, 0);}static char *pg_get_indexdef_worker(Oid indexrelid, int colno, bool showTblSpc,					   int prettyFlags){	HeapTuple	ht_idx;	HeapTuple	ht_idxrel;	HeapTuple	ht_am;	Form_pg_index idxrec;	Form_pg_class idxrelrec;	Form_pg_am	amrec;	List	   *indexprs;	ListCell   *indexpr_item;	List	   *context;	Oid			indrelid;	int			keyno;	Oid			keycoltype;	Datum		indclassDatum;	Datum		indoptionDatum;	bool		isnull;	oidvector  *indclass;	int2vector *indoption;	StringInfoData buf;	char	   *str;	char	   *sep;	/*	 * Fetch the pg_index tuple by the Oid of the index	 */	ht_idx = SearchSysCache(INDEXRELID,							ObjectIdGetDatum(indexrelid),							0, 0, 0);	if (!HeapTupleIsValid(ht_idx))		elog(ERROR, "cache lookup failed for index %u", indexrelid);	idxrec = (Form_pg_index) GETSTRUCT(ht_idx);	indrelid = idxrec->indrelid;	Assert(indexrelid == idxrec->indexrelid);	/* Must get indclass and indoption the hard way */	indclassDatum = SysCacheGetAttr(INDEXRELID, ht_idx,									Anum_pg_index_indclass, &isnull);	Assert(!isnull);	indclass = (oidvector *) DatumGetPointer(indclassDatum);	indoptionDatum = SysCacheGetAttr(INDEXRELID, ht_idx,									 Anum_pg_index_indoption, &isnull);	Assert(!isnull);	indoption = (int2vector *) DatumGetPointer(indoptionDatum);	/*	 * Fetch the pg_class tuple of the index relation	 */	ht_idxrel = SearchSysCache(RELOID,							   ObjectIdGetDatum(indexrelid),							   0, 0, 0);	if (!HeapTupleIsValid(ht_idxrel))		elog(ERROR, "cache lookup failed for relation %u", indexrelid);	idxrelrec = (Form_pg_class) GETSTRUCT(ht_idxrel);	/*	 * Fetch the pg_am tuple of the index' access method	 */	ht_am = SearchSysCache(AMOID,						   ObjectIdGetDatum(idxrelrec->relam),						   0, 0, 0);	if (!HeapTupleIsValid(ht_am))		elog(ERROR, "cache lookup failed for access method %u",			 idxrelrec->relam);	amrec = (Form_pg_am) GETSTRUCT(ht_am);	/*	 * Get the index expressions, if any.  (NOTE: we do not use the relcache	 * versions of the expressions and predicate, because we want to display	 * non-const-folded expressions.)	 */	if (!heap_attisnull(ht_idx, Anum_pg_index_indexprs))	{		Datum		exprsDatum;		bool		isnull;		char	   *exprsString;		exprsDatum = SysCacheGetAttr(INDEXRELID, ht_idx,									 Anum_pg_index_indexprs, &isnull);		Assert(!isnull);		exprsString = DatumGetCString(DirectFunctionCall1(textout,														  exprsDatum));		indexprs = (List *) stringToNode(exprsString);		pfree(exprsString);	}	else		indexprs = NIL;	indexpr_item = list_head(indexprs);	context = deparse_context_for(get_rel_name(indrelid), indrelid);	/*	 * Start the index definition.	Note that the index's name should never be	 * schema-qualified, but the indexed rel's name may be.	 */	initStringInfo(&buf);	if (!colno)		appendStringInfo(&buf, "CREATE %sINDEX %s ON %s USING %s (",						 idxrec->indisunique ? "UNIQUE " : "",						 quote_identifier(NameStr(idxrelrec->relname)),						 generate_relation_name(indrelid),						 quote_identifier(NameStr(amrec->amname)));	/*	 * Report the indexed attributes	 */	sep = "";	for (keyno = 0; keyno < idxrec->indnatts; keyno++)	{		AttrNumber	attnum = idxrec->indkey.values[keyno];		int16		opt = indoption->values[keyno];		if (!colno)			appendStringInfoString(&buf, sep);		sep = ", ";		if (attnum != 0)		{			/* Simple index column */			char	   *attname;			attname = get_relid_attribute_name(indrelid, attnum);			if (!colno || colno == keyno + 1)				appendStringInfoString(&buf, quote_identifier(attname));			keycoltype = get_atttype(indrelid, attnum);		}		else		{			/* expressional index */			Node	   *indexkey;			if (indexpr_item == NULL)				elog(ERROR, "too few entries in indexprs list");			indexkey = (Node *) lfirst(indexpr_item);			indexpr_item = lnext(indexpr_item);			/* Deparse */			str = deparse_expression_pretty(indexkey, context, false, false,											prettyFlags, 0);			if (!colno || colno == keyno + 1)			{				/* Need parens if it's not a bare function call */				if (indexkey && IsA(indexkey, FuncExpr) &&				 ((FuncExpr *) indexkey)->funcformat == COERCE_EXPLICIT_CALL)					appendStringInfoString(&buf, str);				else					appendStringInfo(&buf, "(%s)", str);			}			keycoltype = exprType(indexkey);		}		/* Provide decoration only in the colno=0 case */		if (!colno)		{			/* Add the operator class name, if not default */			get_opclass_name(indclass->values[keyno], keycoltype, &buf);			/* Add options if relevant */			if (amrec->amcanorder)			{				/* if it supports sort ordering, report DESC and NULLS opts */				if (opt & INDOPTION_DESC)				{					appendStringInfo(&buf, " DESC");					/* NULLS FIRST is the default in this case */					if (!(opt & INDOPTION_NULLS_FIRST))						appendStringInfo(&buf, " NULLS LAST");				}				else				{					if (opt & INDOPTION_NULLS_FIRST)						appendStringInfo(&buf, " NULLS FIRST");				}			}		}	}	if (!colno)	{		appendStringInfoChar(&buf, ')');		/*		 * If it has options, append "WITH (options)"		 */		str = flatten_reloptions(indexrelid);		if (str)		{			appendStringInfo(&buf, " WITH (%s)", str);			pfree(str);		}		/*		 * If it's in a nondefault tablespace, say so, but only if requested		 */		if (showTblSpc)		{			Oid			tblspc;			tblspc = get_rel_tablespace(indexrelid);			if (OidIsValid(tblspc))				appendStringInfo(&buf, " TABLESPACE %s",							  quote_identifier(get_tablespace_name(tblspc)));		}		/*		 * If it's a partial index, decompile and append the predicate		 */		if (!heap_attisnull(ht_idx, Anum_pg_index_indpred))		{			Node	   *node;			Datum		predDatum;			bool		isnull;			char	   *predString;			/* Convert text string to node tree */			predDatum = SysCacheGetAttr(INDEXRELID, ht_idx,										Anum_pg_index_indpred, &isnull);			Assert(!isnull);			predString = DatumGetCString(DirectFunctionCall1(textout,															 predDatum));			node = (Node *) stringToNode(predString);			pfree(predString);			/* Deparse */			str = deparse_expression_pretty(node, context, false, false,											prettyFlags, 0);			appendStringInfo(&buf, " WHERE %s", str);		}	}	/* Clean up */	ReleaseSysCache(ht_idx);	ReleaseSysCache(ht_idxrel);	ReleaseSysCache(ht_am);	return buf.data;}/* * pg_get_constraintdef * * Returns the definition for the constraint, ie, everything that needs to * appear after "ALTER TABLE ... ADD CONSTRAINT <constraintname>". */Datumpg_get_constraintdef(PG_FUNCTION_ARGS){	Oid			constraintId = PG_GETARG_OID(0);	PG_RETURN_TEXT_P(string_to_text(pg_get_constraintdef_worker(constraintId,																false, 0)));}Datumpg_get_constraintdef_ext(PG_FUNCTION_ARGS){	Oid			constraintId = PG_GETARG_OID(0);	bool		pretty = PG_GETARG_BOOL(1);	int			prettyFlags;	prettyFlags = pretty ? PRETTYFLAG_PAREN | PRETTYFLAG_INDENT : 0;	PG_RETURN_TEXT_P(string_to_text(pg_get_constraintdef_worker(constraintId,													   false, prettyFlags)));}/* Internal version that returns a palloc'd C string */char *pg_get_constraintdef_string(Oid constraintId){	return pg_get_constraintdef_worker(constraintId, true, 0);}static char *pg_get_constraintdef_worker(Oid constraintId, bool fullCommand,							int prettyFlags){	HeapTuple	tup;	Form_pg_constraint conForm;	StringInfoData buf;	tup = SearchSysCache(CONSTROID,						 ObjectIdGetDatum(constraintId),						 0, 0, 0);	if (!HeapTupleIsValid(tup)) /* should not happen */		elog(ERROR, "cache lookup failed for constraint %u", constraintId);	conForm = (Form_pg_constraint) GETSTRUCT(tup);	initStringInfo(&buf);	if (fullCommand && OidIsValid(conForm->conrelid))	{		appendStringInfo(&buf, "ALTER TABLE ONLY %s ADD CONSTRAINT %s ",						 generate_relation_name(conForm->conrelid),						 quote_identifier(NameStr(conForm->conname)));	}	switch (conForm->contype)	{		case CONSTRAINT_FOREIGN:			{				Datum		val;				bool		isnull;				const char *string;				/* Start off the constraint definition */				appendStringInfo(&buf, "FOREIGN KEY (");				/* Fetch and build referencing-column list */				val = SysCacheGetAttr(CONSTROID, tup,									  Anum_pg_constraint_conkey, &isnull);				if (isnull)					elog(ERROR, "null conkey for constraint %u",						 constraintId);				decompile_column_index_array(val, conForm->conrelid, &buf);				/* add foreign relation name */				appendStringInfo(&buf, ") REFERENCES %s(",								 generate_relation_name(conForm->confrelid));				/* Fetch and build referenced-column list */				val = SysCacheGetAttr(CONSTROID, tup,									  Anum_pg_constraint_confkey, &isnull);				if (isnull)					elog(ERROR, "null confkey for constraint %u",						 constraintId);				decompile_column_index_array(val, conForm->confrelid, &buf);				appendStringInfo(&buf, ")");				/* Add match type */				switch (conForm->confmatchtype)				{					case FKCONSTR_MATCH_FULL:						string = " MATCH FULL";						break;					case FKCONSTR_MATCH_PARTIAL:						string = " MATCH PARTIAL";						break;					case FKCONSTR_MATCH_UNSPECIFIED:						string = "";						break;					default:						elog(ERROR, "unrecognized confmatchtype: %d",							 conForm->confmatchtype);						string = "";	/* keep compiler quiet */						break;				}				appendStringInfoString(&buf, string);				/* Add ON UPDATE and ON DELETE clauses, if needed */				switch (conForm->confupdtype)				{					case FKCONSTR_ACTION_NOACTION:						string = NULL;	/* suppress default */						break;					case FKCONSTR_ACTION_RESTRICT:						string = "RESTRICT";

⌨️ 快捷键说明

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