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

📄 tsquery_rewrite.c

📁 postgresql8.3.4源码,开源数据库
💻 C
字号:
/*------------------------------------------------------------------------- * * tsquery_rewrite.c *	  Utilities for reconstructing tsquery * * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group * * * IDENTIFICATION *	  $PostgreSQL: pgsql/src/backend/utils/adt/tsquery_rewrite.c,v 1.11 2008/01/01 19:45:53 momjian Exp $ * *------------------------------------------------------------------------- */#include "postgres.h"#include "executor/spi.h"#include "tsearch/ts_type.h"#include "tsearch/ts_utils.h"#include "miscadmin.h"static intaddone(int *counters, int last, int total){	/* since this function recurses, it could be driven to stack overflow. */	check_stack_depth();	counters[last]++;	if (counters[last] >= total)	{		if (last == 0)			return 0;		if (addone(counters, last - 1, total - 1) == 0)			return 0;		counters[last] = counters[last - 1] + 1;	}	return 1;}/* * If node is equal to ex, replace it with subs. Replacement is actually done * by returning either node or a copy of subs. */static QTNode *findeq(QTNode *node, QTNode *ex, QTNode *subs, bool *isfind){	if ((node->sign & ex->sign) != ex->sign ||		node->valnode->type != ex->valnode->type)		return node;	if (node->flags & QTN_NOCHANGE)		return node;	if (node->valnode->type == QI_OPR)	{		if (node->valnode->operator.oper != ex->valnode->operator.oper)			return node;		if (node->nchild == ex->nchild)		{			if (QTNEq(node, ex))			{				QTNFree(node);				if (subs)				{					node = QTNCopy(subs);					node->flags |= QTN_NOCHANGE;				}				else					node = NULL;				*isfind = true;			}		}		else if (node->nchild > ex->nchild)		{			/*			 * AND and NOT are commutative, so we check if a subset of the			 * children match. For example, if tnode is A | B | C, and ex is B			 * | C, we have a match after we convert tnode to A | (B | C).			 */			int		   *counters = (int *) palloc(sizeof(int) * node->nchild);			int			i;			QTNode	   *tnode = (QTNode *) palloc(sizeof(QTNode));			memset(tnode, 0, sizeof(QTNode));			tnode->child = (QTNode **) palloc(sizeof(QTNode *) * ex->nchild);			tnode->nchild = ex->nchild;			tnode->valnode = (QueryItem *) palloc(sizeof(QueryItem));			*(tnode->valnode) = *(ex->valnode);			for (i = 0; i < ex->nchild; i++)				counters[i] = i;			do			{				tnode->sign = 0;				for (i = 0; i < ex->nchild; i++)				{					tnode->child[i] = node->child[counters[i]];					tnode->sign |= tnode->child[i]->sign;				}				if (QTNEq(tnode, ex))				{					int			j = 0;					pfree(tnode->valnode);					pfree(tnode->child);					pfree(tnode);					if (subs)					{						tnode = QTNCopy(subs);						tnode->flags = QTN_NOCHANGE | QTN_NEEDFREE;					}					else						tnode = NULL;					node->child[counters[0]] = tnode;					for (i = 1; i < ex->nchild; i++)						node->child[counters[i]] = NULL;					for (i = 0; i < node->nchild; i++)					{						if (node->child[i])						{							node->child[j] = node->child[i];							j++;						}					}					node->nchild = j;					*isfind = true;					break;				}			} while (addone(counters, ex->nchild - 1, node->nchild));			if (tnode && (tnode->flags & QTN_NOCHANGE) == 0)			{				pfree(tnode->valnode);				pfree(tnode->child);				pfree(tnode);			}			else				QTNSort(node);			pfree(counters);		}	}	else	{		Assert(node->valnode->type == QI_VAL);		if (node->valnode->operand.valcrc != ex->valnode->operand.valcrc)			return node;		else if (QTNEq(node, ex))		{			QTNFree(node);			if (subs)			{				node = QTNCopy(subs);				node->flags |= QTN_NOCHANGE;			}			else			{				node = NULL;			}			*isfind = true;		}	}	return node;}static QTNode *dofindsubquery(QTNode *root, QTNode *ex, QTNode *subs, bool *isfind){	/* since this function recurses, it could be driven to stack overflow. */	check_stack_depth();	root = findeq(root, ex, subs, isfind);	if (root && (root->flags & QTN_NOCHANGE) == 0 && root->valnode->type == QI_OPR)	{		int			i;		for (i = 0; i < root->nchild; i++)			root->child[i] = dofindsubquery(root->child[i], ex, subs, isfind);	}	return root;}static QTNode *dropvoidsubtree(QTNode *root){	if (!root)		return NULL;	if (root->valnode->type == QI_OPR)	{		int			i,					j = 0;		for (i = 0; i < root->nchild; i++)		{			if (root->child[i])			{				root->child[j] = root->child[i];				j++;			}		}		root->nchild = j;		if (root->valnode->operator.oper == OP_NOT && root->nchild == 0)		{			QTNFree(root);			root = NULL;		}		else if (root->nchild == 1)		{			QTNode	   *nroot = root->child[0];			pfree(root);			root = nroot;		}	}	return root;}QTNode *findsubquery(QTNode *root, QTNode *ex, QTNode *subs, bool *isfind){	bool		DidFind = false;	root = dofindsubquery(root, ex, subs, &DidFind);	if (!subs && DidFind)		root = dropvoidsubtree(root);	if (isfind)		*isfind = DidFind;	return root;}Datumtsquery_rewrite_query(PG_FUNCTION_ARGS){	TSQuery		query = PG_GETARG_TSQUERY_COPY(0);	text	   *in = PG_GETARG_TEXT_P(1);	TSQuery		rewrited = query;	MemoryContext outercontext = CurrentMemoryContext;	MemoryContext oldcontext;	QTNode	   *tree;	char	   *buf;	SPIPlanPtr	plan;	Portal		portal;	bool		isnull;	int			i;	if (query->size == 0)	{		PG_FREE_IF_COPY(in, 1);		PG_RETURN_POINTER(rewrited);	}	tree = QT2QTN(GETQUERY(query), GETOPERAND(query));	QTNTernary(tree);	QTNSort(tree);	buf = TextPGetCString(in);	SPI_connect();	if ((plan = SPI_prepare(buf, 0, NULL)) == NULL)		elog(ERROR, "SPI_prepare(\"%s\") failed", buf);	if ((portal = SPI_cursor_open(NULL, plan, NULL, NULL, true)) == NULL)		elog(ERROR, "SPI_cursor_open(\"%s\") failed", buf);	SPI_cursor_fetch(portal, true, 100);	if (SPI_tuptable == NULL ||		SPI_tuptable->tupdesc->natts != 2 ||		SPI_gettypeid(SPI_tuptable->tupdesc, 1) != TSQUERYOID ||		SPI_gettypeid(SPI_tuptable->tupdesc, 2) != TSQUERYOID)		ereport(ERROR,				(errcode(ERRCODE_INVALID_PARAMETER_VALUE),				 errmsg("ts_rewrite query must return two tsquery columns")));	while (SPI_processed > 0 && tree)	{		for (i = 0; i < SPI_processed && tree; i++)		{			Datum		qdata = SPI_getbinval(SPI_tuptable->vals[i], SPI_tuptable->tupdesc, 1, &isnull);			Datum		sdata;			if (isnull)				continue;			sdata = SPI_getbinval(SPI_tuptable->vals[i], SPI_tuptable->tupdesc, 2, &isnull);			if (!isnull)			{				TSQuery		qtex = DatumGetTSQuery(qdata);				TSQuery		qtsubs = DatumGetTSQuery(sdata);				QTNode	   *qex,						   *qsubs = NULL;				if (qtex->size == 0)				{					if (qtex != (TSQuery) DatumGetPointer(qdata))						pfree(qtex);					if (qtsubs != (TSQuery) DatumGetPointer(sdata))						pfree(qtsubs);					continue;				}				qex = QT2QTN(GETQUERY(qtex), GETOPERAND(qtex));				QTNTernary(qex);				QTNSort(qex);				if (qtsubs->size)					qsubs = QT2QTN(GETQUERY(qtsubs), GETOPERAND(qtsubs));				oldcontext = MemoryContextSwitchTo(outercontext);				tree = findsubquery(tree, qex, qsubs, NULL);				MemoryContextSwitchTo(oldcontext);				QTNFree(qex);				if (qtex != (TSQuery) DatumGetPointer(qdata))					pfree(qtex);				QTNFree(qsubs);				if (qtsubs != (TSQuery) DatumGetPointer(sdata))					pfree(qtsubs);				if (tree)				{					/* ready the tree for another pass */					QTNClearFlags(tree, QTN_NOCHANGE);					QTNSort(tree);				}			}		}		SPI_freetuptable(SPI_tuptable);		SPI_cursor_fetch(portal, true, 100);	}	SPI_freetuptable(SPI_tuptable);	SPI_cursor_close(portal);	SPI_freeplan(plan);	SPI_finish();	if (tree)	{		QTNBinary(tree);		rewrited = QTN2QT(tree);		QTNFree(tree);		PG_FREE_IF_COPY(query, 0);	}	else	{		SET_VARSIZE(rewrited, HDRSIZETQ);		rewrited->size = 0;	}	pfree(buf);	PG_FREE_IF_COPY(in, 1);	PG_RETURN_POINTER(rewrited);}Datumtsquery_rewrite(PG_FUNCTION_ARGS){	TSQuery		query = PG_GETARG_TSQUERY_COPY(0);	TSQuery		ex = PG_GETARG_TSQUERY(1);	TSQuery		subst = PG_GETARG_TSQUERY(2);	TSQuery		rewrited = query;	QTNode	   *tree,			   *qex,			   *subs = NULL;	if (query->size == 0 || ex->size == 0)	{		PG_FREE_IF_COPY(ex, 1);		PG_FREE_IF_COPY(subst, 2);		PG_RETURN_POINTER(rewrited);	}	tree = QT2QTN(GETQUERY(query), GETOPERAND(query));	QTNTernary(tree);	QTNSort(tree);	qex = QT2QTN(GETQUERY(ex), GETOPERAND(ex));	QTNTernary(qex);	QTNSort(qex);	if (subst->size)		subs = QT2QTN(GETQUERY(subst), GETOPERAND(subst));	tree = findsubquery(tree, qex, subs, NULL);	QTNFree(qex);	QTNFree(subs);	if (!tree)	{		SET_VARSIZE(rewrited, HDRSIZETQ);		rewrited->size = 0;		PG_FREE_IF_COPY(ex, 1);		PG_FREE_IF_COPY(subst, 2);		PG_RETURN_POINTER(rewrited);	}	else	{		QTNBinary(tree);		rewrited = QTN2QT(tree);		QTNFree(tree);	}	PG_FREE_IF_COPY(query, 0);	PG_FREE_IF_COPY(ex, 1);	PG_FREE_IF_COPY(subst, 2);	PG_RETURN_POINTER(rewrited);}

⌨️ 快捷键说明

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