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

📄 ruleutils.c

📁 关系型数据库 Postgresql 6.5.2
💻 C
📖 第 1 页 / 共 3 页
字号:
	fno = SPI_fnumber(rulettc, "is_instead");	is_instead = (bool) SPI_getbinval(ruletup, rulettc, fno, &isnull);	fno = SPI_fnumber(rulettc, "ev_qual");	ev_qual = SPI_getvalue(ruletup, rulettc, fno);	fno = SPI_fnumber(rulettc, "ev_action");	ev_action = SPI_getvalue(ruletup, rulettc, fno);	if (ev_action != NULL)		actions = (List *) stringToNode(ev_action);	/* ----------	 * Build the rules definition text	 * ----------	 */	strcpy(buf, "CREATE RULE \"");	/* The rule name */	strcat(buf, rulename);	strcat(buf, "\" AS ON ");	/* The event the rule is fired for */	switch (ev_type)	{		case '1':			strcat(buf, "SELECT TO \"");			break;		case '2':			strcat(buf, "UPDATE TO \"");			break;		case '3':			strcat(buf, "INSERT TO \"");			break;		case '4':			strcat(buf, "DELETE TO \"");			break;		default:			elog(ERROR, "get_ruledef: rule %s has unsupported event type %d",				 rulename, ev_type);			break;	}	/* The relation the rule is fired on */	strcat(buf, get_relation_name(ev_class));	strcat(buf, "\"");	if (ev_attr > 0)	{		strcat(buf, ".\"");		strcat(buf, get_attribute_name(ev_class, ev_attr));		strcat(buf, "\"");	}	/* If the rule has an event qualification, add it */	if (ev_qual == NULL)		ev_qual = "";	if (strlen(ev_qual) > 0 && strcmp(ev_qual, "<>") != 0)	{		Node	   *qual;		Query	   *query;		QryHier		qh;		qual = stringToNode(ev_qual);		query = (Query *) lfirst(actions);		qh.parent = NULL;		qh.query = query;		strcat(buf, " WHERE ");		strcat(buf, get_rule_expr(&qh, 0, qual, TRUE));	}	strcat(buf, " DO ");	/* The INSTEAD keyword (if so) */	if (is_instead)		strcat(buf, "INSTEAD ");	/* Finally the rules actions */	if (length(actions) > 1)	{		List	   *action;		Query	   *query;		strcat(buf, "(");		foreach(action, actions)		{			query = (Query *) lfirst(action);			strcat(buf, get_query_def(query, NULL));			strcat(buf, "; ");		}		strcat(buf, ");");	}	else	{		if (length(actions) == 0)		{			strcat(buf, "NOTHING;");		}		else		{			Query	   *query;			query = (Query *) lfirst(actions);			strcat(buf, get_query_def(query, NULL));			strcat(buf, ";");		}	}	/* ----------	 * That's it	 * ----------	 */	return buf;}/* ---------- * make_viewdef			- reconstruct the SELECT part of a *				  view rewrite rule * ---------- */static char *make_viewdef(HeapTuple ruletup, TupleDesc rulettc){	char		buf[BUFSIZE];	Query	   *query;	char		ev_type;	Oid			ev_class;	int2		ev_attr;	bool		is_instead;	char	   *ev_qual;	char	   *ev_action;	List	   *actions = NIL;	int			fno;	bool		isnull;	/* ----------	 * Get the attribute values from the rules tuple	 * ----------	 */	fno = SPI_fnumber(rulettc, "ev_type");	ev_type = (char) SPI_getbinval(ruletup, rulettc, fno, &isnull);	fno = SPI_fnumber(rulettc, "ev_class");	ev_class = (Oid) SPI_getbinval(ruletup, rulettc, fno, &isnull);	fno = SPI_fnumber(rulettc, "ev_attr");	ev_attr = (int2) SPI_getbinval(ruletup, rulettc, fno, &isnull);	fno = SPI_fnumber(rulettc, "is_instead");	is_instead = (bool) SPI_getbinval(ruletup, rulettc, fno, &isnull);	fno = SPI_fnumber(rulettc, "ev_qual");	ev_qual = SPI_getvalue(ruletup, rulettc, fno);	fno = SPI_fnumber(rulettc, "ev_action");	ev_action = SPI_getvalue(ruletup, rulettc, fno);	if (ev_action != NULL)		actions = (List *) stringToNode(ev_action);	if (length(actions) != 1)		return "Not a view";	query = (Query *) lfirst(actions);	if (ev_type != '1' || ev_attr >= 0 || !is_instead || strcmp(ev_qual, "<>"))		return "Not a view";	strcpy(buf, get_query_def(query, NULL));	strcat(buf, ";");	/* ----------	 * That's it	 * ----------	 */	return pstrdup(buf);}/* ---------- * get_query_def			- Parse back one action from *					  the parsetree in the actions *					  list * ---------- */static char *get_query_def(Query *query, QryHier *parentqh){	QryHier		qh;	qh.parent = parentqh;	qh.query = query;	switch (query->commandType)	{		case CMD_SELECT:			return get_select_query_def(query, &qh);			break;		case CMD_UPDATE:			return get_update_query_def(query, &qh);			break;		case CMD_INSERT:			return get_insert_query_def(query, &qh);			break;		case CMD_DELETE:			return get_delete_query_def(query, &qh);			break;		case CMD_NOTHING:			return "NOTHING";			break;		default:			elog(ERROR, "get_ruledef of %s: query command type %d not implemented yet",				 rulename, query->commandType);			break;	}	return NULL;}/* ---------- * get_select_query_def			- Parse back a SELECT parsetree * ---------- */static char *get_select_query_def(Query *query, QryHier *qh){	char		buf[BUFSIZE];	char	   *sep;	TargetEntry *tle;	RangeTblEntry *rte;	bool	   *rt_used;	int			rt_length;	int			rt_numused = 0;	bool		rt_constonly = TRUE;	int			i;	List	   *l;	/* ----------	 * First we need to know which and how many of the	 * range table entries in the query are used in the target list	 * or queries qualification	 * ----------	 */	rt_length = length(query->rtable);	rt_used = palloc(sizeof(bool) * rt_length);	for (i = 0; i < rt_length; i++)	{		if (check_if_rte_used((Node *) (query->targetList), i + 1, 0) ||			check_if_rte_used(query->qual, i + 1, 0) ||			check_if_rte_used(query->havingQual, i + 1, 0))		{			rt_used[i] = TRUE;			rt_numused++;		}		else			rt_used[i] = FALSE;	}	/* ----------	 * Now check if any of the used rangetable entries is different	 * from *NEW* and *CURRENT*. If so we must omit the FROM clause	 * later.	 * ----------	 */	i = 0;	foreach(l, query->rtable)	{		if (!rt_used[i++])			continue;		rte = (RangeTblEntry *) lfirst(l);		if (!strcmp(rte->refname, "*NEW*"))			continue;		if (!strcmp(rte->refname, "*CURRENT*"))			continue;		rt_constonly = FALSE;		break;	}	/* ----------	 * Build up the query string - first we say SELECT	 * ----------	 */	strcpy(buf, "SELECT");	/* Then we tell what to select (the targetlist) */	sep = " ";	foreach(l, query->targetList)	{		bool		tell_as = FALSE;		tle = (TargetEntry *) lfirst(l);		strcat(buf, sep);		sep = ", ";		strcat(buf, get_tle_expr(qh, 0, tle, (rt_numused > 1)));		/* Check if we must say AS ... */		if (! IsA(tle->expr, Var))			tell_as = strcmp(tle->resdom->resname, "?column?");		else		{			Var		   *var = (Var *) (tle->expr);			char	   *attname;			rte = get_rte_for_var(var, qh);			attname = get_attribute_name(rte->relid, var->varattno);			if (strcmp(attname, tle->resdom->resname))				tell_as = TRUE;		}		/* and do if so */		if (tell_as)		{			strcat(buf, " AS \"");			strcat(buf, tle->resdom->resname);			strcat(buf, "\"");		}	}	/* If we need other tables that *NEW* or *CURRENT* add the FROM clause */	if (!rt_constonly && rt_numused > 0)	{		strcat(buf, " FROM");		i = 0;		sep = " ";		foreach(l, query->rtable)		{			if (rt_used[i++])			{				rte = (RangeTblEntry *) lfirst(l);				if (!strcmp(rte->refname, "*NEW*"))					continue;				if (!strcmp(rte->refname, "*CURRENT*"))					continue;				strcat(buf, sep);				sep = ", ";				strcat(buf, "\"");				strcat(buf, rte->relname);				strcat(buf, "\"");				if (strcmp(rte->relname, rte->refname) != 0)				{					strcat(buf, " \"");					strcat(buf, rte->refname);					strcat(buf, "\"");				}			}		}	}	/* Add the WHERE clause if given */	if (query->qual != NULL)	{		strcat(buf, " WHERE ");		strcat(buf, get_rule_expr(qh, 0, query->qual, (rt_numused > 1)));	}	/* Add the GROUP BY CLAUSE */	if (query->groupClause != NULL)	{		strcat(buf, " GROUP BY ");		sep = "";		foreach(l, query->groupClause)		{			GroupClause *grp = (GroupClause *) lfirst(l);			Node *groupexpr;			groupexpr = (Node *) get_groupclause_expr(grp,													  query->targetList);			strcat(buf, sep);			strcat(buf, get_rule_expr(qh, 0, groupexpr, (rt_numused > 1)));			sep = ", ";		}	}	/* ----------	 * Copy the query string into allocated space and return it	 * ----------	 */	return pstrdup(buf);}/* ---------- * get_insert_query_def			- Parse back an INSERT parsetree * ---------- */static char *get_insert_query_def(Query *query, QryHier *qh){	char		buf[BUFSIZE];	char	   *sep;	TargetEntry *tle;	RangeTblEntry *rte;	bool	   *rt_used;	int			rt_length;	int			rt_numused = 0;	bool		rt_constonly = TRUE;	int			i;	List	   *l;	/* ----------	 * We need to know if other tables than *NEW* or *CURRENT*	 * are used in the query. If not, it's an INSERT ... VALUES,	 * otherwise an INSERT ... SELECT.	 * ----------	 */	rt_length = length(query->rtable);	rt_used = palloc(sizeof(bool) * rt_length);	for (i = 0; i < rt_length; i++)	{		if (check_if_rte_used((Node *) (query->targetList), i + 1, 0) ||			check_if_rte_used(query->qual, i + 1, 0) ||			check_if_rte_used(query->havingQual, i + 1, 0))		{			rt_used[i] = TRUE;			rt_numused++;		}		else			rt_used[i] = FALSE;	}	i = 0;	foreach(l, query->rtable)	{		if (!rt_used[i++])			continue;		rte = (RangeTblEntry *) lfirst(l);		if (!strcmp(rte->refname, "*NEW*"))			continue;		if (!strcmp(rte->refname, "*CURRENT*"))			continue;		rt_constonly = FALSE;		break;	}	/* ----------	 * Start the query with INSERT INTO relname	 * ----------	 */	rte = (RangeTblEntry *) nth(query->resultRelation - 1, query->rtable);	strcpy(buf, "INSERT INTO \"");	strcat(buf, rte->relname);	strcat(buf, "\"");	/* Add the target list */	sep = " (";	foreach(l, query->targetList)	{		tle = (TargetEntry *) lfirst(l);		strcat(buf, sep);		sep = ", ";		strcat(buf, "\"");		strcat(buf, tle->resdom->resname);		strcat(buf, "\"");	}	strcat(buf, ") ");	/* Add the VALUES or the SELECT */	if (rt_constonly && query->qual == NULL)	{		strcat(buf, "VALUES (");		sep = "";		foreach(l, query->targetList)		{			tle = (TargetEntry *) lfirst(l);			strcat(buf, sep);			sep = ", ";			strcat(buf, get_tle_expr(qh, 0, tle, (rt_numused > 1)));		}		strcat(buf, ")");	}	else		strcat(buf, get_select_query_def(query, qh));	/* ----------	 * Copy the query string into allocated space and return it	 * ----------	 */	return pstrdup(buf);}/* ---------- * get_update_query_def			- Parse back an UPDATE parsetree * ---------- */static char *get_update_query_def(Query *query, QryHier *qh){	char		buf[BUFSIZE];	char	   *sep;	TargetEntry *tle;	RangeTblEntry *rte;	List	   *l;	/* ----------	 * Start the query with UPDATE relname SET	 * ----------	 */	rte = (RangeTblEntry *) nth(query->resultRelation - 1, query->rtable);	strcpy(buf, "UPDATE ");	strcat(buf, rte->relname);	strcat(buf, " SET ");	/* Add the comma separated list of 'attname = value' */	sep = "";	foreach(l, query->targetList)	{		tle = (TargetEntry *) lfirst(l);		strcat(buf, sep);		sep = ", ";		strcat(buf, "\"");		strcat(buf, tle->resdom->resname);		strcat(buf, "\" = ");		strcat(buf, get_tle_expr(qh, query->resultRelation,								 tle, TRUE));	}	/* Finally add a WHERE clause if given */	if (query->qual != NULL)	{		strcat(buf, " WHERE ");		strcat(buf, get_rule_expr(qh, query->resultRelation,								  query->qual, TRUE));	}	/* ----------	 * Copy the query string into allocated space and return it	 * ----------	 */	return pstrdup(buf);}/* ---------- * get_delete_query_def			- Parse back a DELETE parsetree * ---------- */static char *get_delete_query_def(Query *query, QryHier *qh){	char		buf[BUFSIZE];	RangeTblEntry *rte;	/* ----------	 * Start the query with DELETE FROM relname	 * ----------	 */	rte = (RangeTblEntry *) nth(query->resultRelation - 1, query->rtable);	strcpy(buf, "DELETE FROM \"");	strcat(buf, rte->relname);	strcat(buf, "\"");	/* Add a WHERE clause if given */	if (query->qual != NULL)	{		strcat(buf, " WHERE ");		strcat(buf, get_rule_expr(qh, 0, query->qual, FALSE));	}	/* ----------	 * Copy the query string into allocated space and return it	 * ----------	 */	return pstrdup(buf);}/* * Find the RTE referenced by a (possibly nonlocal) Var. */static RangeTblEntry *get_rte_for_var(Var *var, QryHier *qh){	int		sup = var->varlevelsup;	while (sup-- > 0)		qh = qh->parent;	return (RangeTblEntry *) nth(var->varno - 1, qh->query->rtable);}/* ---------- * get_rule_expr			- Parse back an expression * ---------- */static char *get_rule_expr(QryHier *qh, int rt_index, Node *node, bool varprefix){	char		buf[BUFSIZE];	if (node == NULL)

⌨️ 快捷键说明

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