tsquery_cleanup.c

来自「postgresql8.3.4源码,开源数据库」· C语言 代码 · 共 292 行

C
292
字号
/*------------------------------------------------------------------------- * * tsquery_cleanup.c *	 Cleanup query from NOT values and/or stopword *	 Utility functions to correct work. * * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group * * * IDENTIFICATION *	  $PostgreSQL: pgsql/src/backend/utils/adt/tsquery_cleanup.c,v 1.10 2008/01/01 19:45:53 momjian Exp $ * *------------------------------------------------------------------------- */#include "postgres.h"#include "tsearch/ts_type.h"#include "tsearch/ts_utils.h"#include "miscadmin.h"typedef struct NODE{	struct NODE *left;	struct NODE *right;	QueryItem  *valnode;} NODE;/* * make query tree from plain view of query */static NODE *maketree(QueryItem *in){	NODE	   *node = (NODE *) palloc(sizeof(NODE));	node->valnode = in;	node->right = node->left = NULL;	if (in->type == QI_OPR)	{		node->right = maketree(in + 1);		if (in->operator.oper != OP_NOT)			node->left = maketree(in + in->operator.left);	}	return node;}/* * Internal state for plaintree and plainnode */typedef struct{	QueryItem  *ptr;	int			len;			/* allocated size of ptr */	int			cur;			/* number of elements in ptr */} PLAINTREE;static voidplainnode(PLAINTREE *state, NODE *node){	/* since this function recurses, it could be driven to stack overflow. */	check_stack_depth();	if (state->cur == state->len)	{		state->len *= 2;		state->ptr = (QueryItem *) repalloc((void *) state->ptr, state->len * sizeof(QueryItem));	}	memcpy((void *) &(state->ptr[state->cur]), (void *) node->valnode, sizeof(QueryItem));	if (node->valnode->type == QI_VAL)		state->cur++;	else if (node->valnode->operator.oper == OP_NOT)	{		state->ptr[state->cur].operator.left = 1;		state->cur++;		plainnode(state, node->right);	}	else	{		int			cur = state->cur;		state->cur++;		plainnode(state, node->right);		state->ptr[cur].operator.left = state->cur - cur;		plainnode(state, node->left);	}	pfree(node);}/* * make plain view of tree from a NODE-tree representation */static QueryItem *plaintree(NODE *root, int *len){	PLAINTREE	pl;	pl.cur = 0;	pl.len = 16;	if (root && (root->valnode->type == QI_VAL || root->valnode->type == QI_OPR))	{		pl.ptr = (QueryItem *) palloc(pl.len * sizeof(QueryItem));		plainnode(&pl, root);	}	else		pl.ptr = NULL;	*len = pl.cur;	return pl.ptr;}static voidfreetree(NODE *node){	/* since this function recurses, it could be driven to stack overflow. */	check_stack_depth();	if (!node)		return;	if (node->left)		freetree(node->left);	if (node->right)		freetree(node->right);	pfree(node);}/* * clean tree for ! operator. * It's usefull for debug, but in * other case, such view is used with search in index. * Operator ! always return TRUE */static NODE *clean_NOT_intree(NODE *node){	/* since this function recurses, it could be driven to stack overflow. */	check_stack_depth();	if (node->valnode->type == QI_VAL)		return node;	if (node->valnode->operator.oper == OP_NOT)	{		freetree(node);		return NULL;	}	/* operator & or | */	if (node->valnode->operator.oper == OP_OR)	{		if ((node->left = clean_NOT_intree(node->left)) == NULL ||			(node->right = clean_NOT_intree(node->right)) == NULL)		{			freetree(node);			return NULL;		}	}	else	{		NODE	   *res = node;		Assert(node->valnode->operator.oper == OP_AND);		node->left = clean_NOT_intree(node->left);		node->right = clean_NOT_intree(node->right);		if (node->left == NULL && node->right == NULL)		{			pfree(node);			res = NULL;		}		else if (node->left == NULL)		{			res = node->right;			pfree(node);		}		else if (node->right == NULL)		{			res = node->left;			pfree(node);		}		return res;	}	return node;}QueryItem *clean_NOT(QueryItem *ptr, int *len){	NODE	   *root = maketree(ptr);	return plaintree(clean_NOT_intree(root), len);}#ifdef V_UNKNOWN				/* exists in Windows headers */#undef V_UNKNOWN#endif#ifdef V_FALSE					/* exists in Solaris headers */#undef V_FALSE#endif/* * output values for result output parameter of clean_fakeval_intree */#define V_UNKNOWN	0			/* the expression can't be evaluated								 * statically */#define V_TRUE		1			/* the expression is always true (not								 * implemented) */#define V_FALSE		2			/* the expression is always false (not								 * implemented) */#define V_STOP		3			/* the expression is a stop word *//* * Clean query tree from values which is always in * text (stopword) */static NODE *clean_fakeval_intree(NODE *node, char *result){	char		lresult = V_UNKNOWN,				rresult = V_UNKNOWN;	/* since this function recurses, it could be driven to stack overflow. */	check_stack_depth();	if (node->valnode->type == QI_VAL)		return node;	else if (node->valnode->type == QI_VALSTOP)	{		pfree(node);		*result = V_STOP;		return NULL;	}	Assert(node->valnode->type == QI_OPR);	if (node->valnode->operator.oper == OP_NOT)	{		node->right = clean_fakeval_intree(node->right, &rresult);		if (!node->right)		{			*result = V_STOP;			freetree(node);			return NULL;		}	}	else	{		NODE	   *res = node;		node->left = clean_fakeval_intree(node->left, &lresult);		node->right = clean_fakeval_intree(node->right, &rresult);		if (lresult == V_STOP && rresult == V_STOP)		{			freetree(node);			*result = V_STOP;			return NULL;		}		else if (lresult == V_STOP)		{			res = node->right;			pfree(node);		}		else if (rresult == V_STOP)		{			res = node->left;			pfree(node);		}		return res;	}	return node;}QueryItem *clean_fakeval(QueryItem *ptr, int *len){	NODE	   *root = maketree(ptr);	char		result = V_UNKNOWN;	NODE	   *resroot;	resroot = clean_fakeval_intree(root, &result);	if (result != V_UNKNOWN)	{		ereport(NOTICE,				(errmsg("text-search query contains only stop words or doesn't contain lexemes, ignored")));		*len = 0;		return NULL;	}	return plaintree(resroot, len);}

⌨️ 快捷键说明

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