⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ruleutils.c

📁 关系型数据库 Postgresql 6.5.2
💻 C
📖 第 1 页 / 共 3 页
字号:
		return pstrdup("");	buf[0] = '\0';	/* ----------	 * Each level of get_rule_expr must return an indivisible term	 * (parenthesized if necessary) to ensure result is reparsed into	 * the same expression tree.	 *	 * There might be some work left here to support additional node types...	 * ----------	 */	switch (nodeTag(node))	{		case T_Const:			return get_const_expr((Const *) node);			break;		case T_Var:			{				Var		   *var = (Var *) node;				RangeTblEntry *rte = get_rte_for_var(var, qh);				if (!strcmp(rte->refname, "*NEW*"))					strcat(buf, "new.");				else if (!strcmp(rte->refname, "*CURRENT*"))					strcat(buf, "old.");				else				{					strcat(buf, "\"");					strcat(buf, rte->refname);					strcat(buf, "\".");				}				strcat(buf, "\"");				strcat(buf, get_attribute_name(rte->relid, var->varattno));				strcat(buf, "\"");				return pstrdup(buf);			}			break;		case T_Expr:			{				Expr	   *expr = (Expr *) node;				List	   *args = expr->args;				/* ----------				 * Expr nodes have to be handled a bit detailed				 * ----------				 */				switch (expr->opType)				{					case OP_EXPR:						strcat(buf, "(");						if (length(args) == 2)						{							/* binary operator */							strcat(buf,								   get_rule_expr(qh, rt_index,												 (Node *) lfirst(args),												 varprefix));							strcat(buf, " ");							strcat(buf,								   get_opname(((Oper *) expr->oper)->opno));							strcat(buf, " ");							strcat(buf,								   get_rule_expr(qh, rt_index,												 (Node *) lsecond(args),												 varprefix));						}						else						{							/* unary operator --- but which side? */							Oid			opno = ((Oper *) expr->oper)->opno;							HeapTuple	tp;							Form_pg_operator optup;							tp = SearchSysCacheTuple(OPROID,													 ObjectIdGetDatum(opno),													 0, 0, 0);							Assert(HeapTupleIsValid(tp));							optup = (Form_pg_operator) GETSTRUCT(tp);							switch (optup->oprkind)							{								case 'l':									strcat(buf, get_opname(opno));									strcat(buf, " ");									strcat(buf,										   get_rule_expr(qh, rt_index,														 (Node *) lfirst(args),														 varprefix));									break;								case 'r':									strcat(buf,										   get_rule_expr(qh, rt_index,														 (Node *) lfirst(args),														 varprefix));									strcat(buf, " ");									strcat(buf, get_opname(opno));									break;								default:									elog(ERROR, "get_rule_expr: bogus oprkind");							}						}						strcat(buf, ")");						return pstrdup(buf);						break;					case OR_EXPR:						strcat(buf, "(");						strcat(buf, get_rule_expr(qh, rt_index,												  (Node *) lfirst(args),												  varprefix));						/* It's not clear that we can ever see N-argument						 * OR/AND clauses here, but might as well cope...						 */						while ((args = lnext(args)) != NIL)						{							strcat(buf, " OR ");							strcat(buf, get_rule_expr(qh, rt_index,													  (Node *) lfirst(args),													  varprefix));						}						strcat(buf, ")");						return pstrdup(buf);						break;					case AND_EXPR:						strcat(buf, "(");						strcat(buf, get_rule_expr(qh, rt_index,												  (Node *) lfirst(args),												  varprefix));						while ((args = lnext(args)) != NIL)						{							strcat(buf, " AND ");							strcat(buf, get_rule_expr(qh, rt_index,													  (Node *) lfirst(args),													  varprefix));						}						strcat(buf, ")");						return pstrdup(buf);						break;					case NOT_EXPR:						strcat(buf, "(NOT ");						strcat(buf, get_rule_expr(qh, rt_index,											   (Node *) get_leftop(expr),												  varprefix));						strcat(buf, ")");						return pstrdup(buf);						break;					case FUNC_EXPR:						return get_func_expr(qh, rt_index,											 (Expr *) node,											 varprefix);						break;					default:						printf("\n%s\n", nodeToString(node));						elog(ERROR, "get_rule_expr: expr type not supported");				}			}			break;		case T_Aggref:			{				Aggref	   *aggref = (Aggref *) node;				strcat(buf, "\"");				strcat(buf, aggref->aggname);				strcat(buf, "\"(");				strcat(buf, get_rule_expr(qh, rt_index,								  (Node *) (aggref->target), varprefix));				strcat(buf, ")");				return pstrdup(buf);			}			break;		case T_ArrayRef:			{				ArrayRef   *aref = (ArrayRef *) node;				List	   *lowlist;				List	   *uplist;				strcat(buf, get_rule_expr(qh, rt_index,										  aref->refexpr, varprefix));				lowlist = aref->reflowerindexpr;				foreach(uplist, aref->refupperindexpr)				{					strcat(buf, "[");					if (lowlist)					{						strcat(buf, get_rule_expr(qh, rt_index,												  (Node *) lfirst(lowlist),												  varprefix));						strcat(buf, ":");						lowlist = lnext(lowlist);					}					strcat(buf, get_rule_expr(qh, rt_index,											  (Node *) lfirst(uplist),											  varprefix));					strcat(buf, "]");				}				/* XXX need to do anything with refassgnexpr? */				return pstrdup(buf);			}			break;		case T_CaseExpr:			{				CaseExpr   *caseexpr = (CaseExpr *) node;				List	   *temp;				strcat(buf, "CASE");				foreach(temp, caseexpr->args)				{					CaseWhen   *when = (CaseWhen *) lfirst(temp);					strcat(buf, " WHEN ");					strcat(buf, get_rule_expr(qh, rt_index,											  when->expr, varprefix));					strcat(buf, " THEN ");					strcat(buf, get_rule_expr(qh, rt_index,											  when->result, varprefix));				}				strcat(buf, " ELSE ");				strcat(buf, get_rule_expr(qh, rt_index,										  caseexpr->defresult, varprefix));				strcat(buf, " END");				return pstrdup(buf);			}			break;		case T_SubLink:			return get_sublink_expr(qh, rt_index, node, varprefix);			break;		default:			printf("\n%s\n", nodeToString(node));			elog(ERROR, "get_ruledef of %s: unknown node type %d in get_rule_expr()",				 rulename, nodeTag(node));			break;	}	return FALSE;}/* ---------- * get_func_expr			- Parse back a Func node * ---------- */static char *get_func_expr(QryHier *qh, int rt_index, Expr *expr, bool varprefix){	char		buf[BUFSIZE];	HeapTuple	proctup;	Form_pg_proc procStruct;	List	   *l;	char	   *sep;	Func	   *func = (Func *) (expr->oper);	char	   *proname;	/* ----------	 * Get the functions pg_proc tuple	 * ----------	 */	proctup = SearchSysCacheTuple(PROOID,								ObjectIdGetDatum(func->funcid), 0, 0, 0);	if (!HeapTupleIsValid(proctup))		elog(ERROR, "cache lookup for proc %u failed", func->funcid);	procStruct = (Form_pg_proc) GETSTRUCT(proctup);	proname = nameout(&(procStruct->proname));	if (procStruct->pronargs == 1 && procStruct->proargtypes[0] == InvalidOid)	{		if (!strcmp(proname, "nullvalue"))		{			strcpy(buf, "(");			strcat(buf, get_rule_expr(qh, rt_index, lfirst(expr->args),									  varprefix));			strcat(buf, " ISNULL)");			return pstrdup(buf);		}		if (!strcmp(proname, "nonnullvalue"))		{			strcpy(buf, "(");			strcat(buf, get_rule_expr(qh, rt_index, lfirst(expr->args),									  varprefix));			strcat(buf, " NOTNULL)");			return pstrdup(buf);		}	}	/* ----------	 * Build a string of proname(args)	 * ----------	 */	strcpy(buf, "\"");	strcat(buf, proname);	strcat(buf, "\"(");	sep = "";	foreach(l, expr->args)	{		strcat(buf, sep);		sep = ", ";		strcat(buf, get_rule_expr(qh, rt_index, lfirst(l), varprefix));	}	strcat(buf, ")");	/* ----------	 * Copy the function call string into allocated space and return it	 * ----------	 */	return pstrdup(buf);}/* ---------- * get_tle_expr				- A target list expression is a bit *					  different from a normal expression. *					  If the target column has an *					  an atttypmod, the parser usually *					  puts a padding-/cut-function call *					  around the expression itself. We *					  we must get rid of it, otherwise *					  dump/reload/dump... would blow up *					  the expressions. * ---------- */static char *get_tle_expr(QryHier *qh, int rt_index, TargetEntry *tle, bool varprefix){	Expr	   *expr = (Expr *) (tle->expr);	Func	   *func;	HeapTuple	tup;	Form_pg_proc procStruct;	Form_pg_type typeStruct;	Const	   *second_arg;	/* ----------	 * Check if the result has an atttypmod and if the	 * expression in the targetlist entry is a function call	 * ----------	 */	if (tle->resdom->restypmod < 0 ||		! IsA(expr, Expr) ||		expr->opType != FUNC_EXPR)		return get_rule_expr(qh, rt_index, tle->expr, varprefix);	func = (Func *) (expr->oper);	/* ----------	 * Get the functions pg_proc tuple	 * ----------	 */	tup = SearchSysCacheTuple(PROOID,							  ObjectIdGetDatum(func->funcid), 0, 0, 0);	if (!HeapTupleIsValid(tup))		elog(ERROR, "cache lookup for proc %u failed", func->funcid);	procStruct = (Form_pg_proc) GETSTRUCT(tup);	/* ----------	 * It must be a function with two arguments where the first	 * is of the same type as the return value and the second is	 * an int4.	 * ----------	 */	if (procStruct->pronargs != 2 ||		procStruct->prorettype != procStruct->proargtypes[0] ||		procStruct->proargtypes[1] != INT4OID)		return get_rule_expr(qh, rt_index, tle->expr, varprefix);	/*	 * Furthermore, the name of the function must be the same	 * as the argument/result type name.	 */	tup = SearchSysCacheTuple(TYPOID,							  ObjectIdGetDatum(procStruct->prorettype),							  0, 0, 0);	if (!HeapTupleIsValid(tup))		elog(ERROR, "cache lookup for type %u failed",			 procStruct->prorettype);	typeStruct = (Form_pg_type) GETSTRUCT(tup);	if (strncmp(procStruct->proname.data, typeStruct->typname.data,				NAMEDATALEN) != 0)        return get_rule_expr(qh, rt_index, tle->expr, varprefix);	/* ----------	 * Finally (to be totally safe) the second argument must be a	 * const and match the value in the results atttypmod.	 * ----------	 */	second_arg = (Const *) nth(1, expr->args);	if (! IsA(second_arg, Const) ||		((int4) second_arg->constvalue) != tle->resdom->restypmod)		return get_rule_expr(qh, rt_index, tle->expr, varprefix);	/* ----------	 * Whow - got it. Now get rid of the padding function	 * ----------	 */	return get_rule_expr(qh, rt_index, lfirst(expr->args), varprefix);}/* ---------- * get_const_expr			- Make a string representation *					  with the type cast out of a Const * ---------- */static char *get_const_expr(Const *constval){	HeapTuple	typetup;	Form_pg_type typeStruct;	FmgrInfo	finfo_output;	char	   *extval;	bool		isnull = FALSE;	char		buf[BUFSIZE];	char		namebuf[64];	if (constval->constisnull)		return pstrdup("NULL");	typetup = SearchSysCacheTuple(TYPOID,						 ObjectIdGetDatum(constval->consttype), 0, 0, 0);	if (!HeapTupleIsValid(typetup))		elog(ERROR, "cache lookup of type %u failed", constval->consttype);	typeStruct = (Form_pg_type) GETSTRUCT(typetup);	fmgr_info(typeStruct->typoutput, &finfo_output);	extval = (char *) (*fmgr_faddr(&finfo_output)) (constval->constvalue,													&isnull, -1);	sprintf(namebuf, "::\"%s\"", nameout(&(typeStruct->typname)));	if (strcmp(namebuf, "::unknown") == 0)		namebuf[0] = '\0';	sprintf(buf, "'%s'%s", extval, namebuf);	return pstrdup(buf);}/* ---------- * get_sublink_expr			- Parse back a sublink * ---------- */static char *get_sublink_expr(QryHier *qh, int rt_index, Node *node, bool varprefix){	SubLink    *sublink = (SubLink *) node;	Query	   *query = (Query *) (sublink->subselect);	Expr	   *expr;	List	   *l;	char	   *sep;	char		buf[BUFSIZE];	buf[0] = '\0';	strcat(buf, "(");	if (sublink->lefthand != NULL)	{		if (length(sublink->lefthand) > 1)			strcat(buf, "(");		sep = "";		foreach(l, sublink->lefthand)		{			strcat(buf, sep);			sep = ", ";			strcat(buf, get_rule_expr(qh, rt_index,									  lfirst(l), varprefix));		}		if (length(sublink->lefthand) > 1)			strcat(buf, ") ");		else			strcat(buf, " ");	}	switch (sublink->subLinkType)	{		case EXISTS_SUBLINK:			strcat(buf, "EXISTS ");			break;		case ANY_SUBLINK:			expr = (Expr *) lfirst(sublink->oper);			strcat(buf, get_opname(((Oper *) (expr->oper))->opno));			strcat(buf, " ANY ");			break;		case ALL_SUBLINK:			expr = (Expr *) lfirst(sublink->oper);			strcat(buf, get_opname(((Oper *) (expr->oper))->opno));			strcat(buf, " ALL ");			break;		case EXPR_SUBLINK:			expr = (Expr *) lfirst(sublink->oper);			strcat(buf, get_opname(((Oper *) (expr->oper))->opno));			strcat(buf, " ");			break;		default:			elog(ERROR, "unupported sublink type %d",				 sublink->subLinkType);			break;	}	strcat(buf, "(");	strcat(buf, get_query_def(query, qh));	strcat(buf, "))");	return pstrdup(buf);}/* ---------- * get_relation_name			- Get a relation name by Oid * ---------- */static char *get_relation_name(Oid relid){	HeapTuple	classtup;	Form_pg_class classStruct;	classtup = SearchSysCacheTuple(RELOID,								   ObjectIdGetDatum(relid), 0, 0, 0);	if (!HeapTupleIsValid(classtup))		elog(ERROR, "cache lookup of relation %u failed", relid);	classStruct = (Form_pg_class) GETSTRUCT(classtup);	return nameout(&(classStruct->relname));}/* ---------- * get_attribute_name			- Get an attribute name by it's *					  relations Oid and it's attnum * ---------- */static char *get_attribute_name(Oid relid, int2 attnum){	HeapTuple	atttup;	Form_pg_attribute attStruct;	atttup = SearchSysCacheTuple(ATTNUM,						  ObjectIdGetDatum(relid), (Datum) attnum, 0, 0);	if (!HeapTupleIsValid(atttup))		elog(ERROR, "cache lookup of attribute %d in relation %u failed",			 attnum, relid);	attStruct = (Form_pg_attribute) GETSTRUCT(atttup);	return nameout(&(attStruct->attname));}/* ---------- * check_if_rte_used *		Check a targetlist or qual to see if a given rangetable entry *		is used in it * ---------- */static boolcheck_if_rte_used(Node *node, Index rt_index, int levelsup){	check_if_rte_used_context context;	context.rt_index = rt_index;	context.levelsup = levelsup;	return check_if_rte_used_walker(node, &context);}static boolcheck_if_rte_used_walker(Node *node,						 check_if_rte_used_context *context){	if (node == NULL)		return false;	if (IsA(node, Var))	{		Var		   *var = (Var *) node;		return var->varno == context->rt_index &&			var->varlevelsup == context->levelsup;	}	if (IsA(node, SubLink))	{		SubLink    *sublink = (SubLink *) node;		Query	   *query = (Query *) sublink->subselect;		/* Recurse into subquery; expression_tree_walker will not */		if (check_if_rte_used((Node *) (query->targetList),							  context->rt_index, context->levelsup + 1) ||			check_if_rte_used(query->qual,							  context->rt_index, context->levelsup + 1) ||			check_if_rte_used(query->havingQual,							  context->rt_index, context->levelsup + 1))			return true;		/* fall through to let expression_tree_walker examine lefthand args */	}	return expression_tree_walker(node, check_if_rte_used_walker,								  (void *) context);}

⌨️ 快捷键说明

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