示例#1
0
/*
 * Evaluate tsquery boolean expression using ternary logic.
 *
 * chkcond is a callback function used to evaluate each VAL node in the query.
 * checkval can be used to pass information to the callback. TS_execute doesn't
 * do anything with it.
 */
static GinTernaryValue
TS_execute_ternary(QueryItem *curitem, void *checkval,
			  GinTernaryValue (*chkcond) (void *checkval, QueryOperand *val))
{
	GinTernaryValue val1,
				val2,
				result;

	/* since this function recurses, it could be driven to stack overflow */
	check_stack_depth();

	if (curitem->type == QI_VAL)
		return chkcond(checkval, (QueryOperand *) curitem);

	switch (curitem->qoperator.oper)
	{
		case OP_NOT:
			result = TS_execute_ternary(curitem + 1, checkval, chkcond);
			if (result == GIN_MAYBE)
				return result;
			return !result;

		case OP_AND:
			val1 = TS_execute_ternary(curitem + curitem->qoperator.left,
									  checkval, chkcond);
			if (val1 == GIN_FALSE)
				return GIN_FALSE;
			val2 = TS_execute_ternary(curitem + 1, checkval, chkcond);
			if (val2 == GIN_FALSE)
				return GIN_FALSE;
			if (val1 == GIN_TRUE && val2 == GIN_TRUE)
				return GIN_TRUE;
			else
				return GIN_MAYBE;

		case OP_OR:
			val1 = TS_execute_ternary(curitem + curitem->qoperator.left,
									  checkval, chkcond);
			if (val1 == GIN_TRUE)
				return GIN_TRUE;
			val2 = TS_execute_ternary(curitem + 1, checkval, chkcond);
			if (val2 == GIN_TRUE)
				return GIN_TRUE;
			if (val1 == GIN_FALSE && val2 == GIN_FALSE)
				return GIN_FALSE;
			else
				return GIN_MAYBE;

		default:
			elog(ERROR, "unrecognized operator___: %d", curitem->qoperator.oper);
	}

	/* not reachable, but keep compiler quiet */
	return false;
}
示例#2
0
Datum
gin_tsquery_triconsistent(PG_FUNCTION_ARGS)
{
	GinTernaryValue *check = (GinTernaryValue *) PG_GETARG_POINTER(0);

	/* StrategyNumber strategy = PG_GETARG_UINT16(1); */
	TSQuery		query = PG_GETARG_TSQUERY(2);

	/* int32	nkeys = PG_GETARG_INT32(3); */
	Pointer    *extra_data = (Pointer *) PG_GETARG_POINTER(4);
	GinTernaryValue res = GIN_FALSE;
	bool		recheck;

	/* The query requires recheck only if it involves weights */
	recheck = false;

	if (query->size > 0)
	{
		QueryItem  *item;
		GinChkVal	gcv;

		/*
		 * check-parameter array has one entry for each value (operand) in the
		 * query.
		 */
		gcv.first_item = item = GETQUERY(query);
		gcv.check = check;
		gcv.map_item_operand = (int *) (extra_data[0]);
		gcv.need_recheck = &recheck;

		res = TS_execute_ternary(GETQUERY(query),
								 &gcv,
								 checkcondition_gin);

		if (res == GIN_TRUE && recheck)
			res = GIN_MAYBE;
	}

	PG_RETURN_GIN_TERNARY_VALUE(res);
}
示例#3
0
/*
 * Evaluate tsquery boolean expression using ternary logic.
 */
static GinTernaryValue
TS_execute_ternary(GinChkVal *gcv, QueryItem *curitem, bool in_phrase)
{
	GinTernaryValue val1,
				val2,
				result;

	/* since this function recurses, it could be driven to stack overflow */
	check_stack_depth();

	if (curitem->type == QI_VAL)
		return
			checkcondition_gin_internal(gcv,
										(QueryOperand *) curitem,
										NULL /* don't have position info */ );

	switch (curitem->qoperator.oper)
	{
		case OP_NOT:
			/* In phrase search, always return MAYBE since we lack positions */
			if (in_phrase)
				return GIN_MAYBE;
			result = TS_execute_ternary(gcv, curitem + 1, in_phrase);
			if (result == GIN_MAYBE)
				return result;
			return !result;

		case OP_PHRASE:

			/*
			 * GIN doesn't contain any information about positions, so treat
			 * OP_PHRASE as OP_AND with recheck requirement
			 */
			*(gcv->need_recheck) = true;
			/* Pass down in_phrase == true in case there's a NOT below */
			in_phrase = true;

			/* FALL THRU */

		case OP_AND:
			val1 = TS_execute_ternary(gcv, curitem + curitem->qoperator.left,
									  in_phrase);
			if (val1 == GIN_FALSE)
				return GIN_FALSE;
			val2 = TS_execute_ternary(gcv, curitem + 1, in_phrase);
			if (val2 == GIN_FALSE)
				return GIN_FALSE;
			if (val1 == GIN_TRUE && val2 == GIN_TRUE)
				return GIN_TRUE;
			else
				return GIN_MAYBE;

		case OP_OR:
			val1 = TS_execute_ternary(gcv, curitem + curitem->qoperator.left,
									  in_phrase);
			if (val1 == GIN_TRUE)
				return GIN_TRUE;
			val2 = TS_execute_ternary(gcv, curitem + 1, in_phrase);
			if (val2 == GIN_TRUE)
				return GIN_TRUE;
			if (val1 == GIN_FALSE && val2 == GIN_FALSE)
				return GIN_FALSE;
			else
				return GIN_MAYBE;

		default:
			elog(ERROR, "unrecognized operator: %d", curitem->qoperator.oper);
	}

	/* not reachable, but keep compiler quiet */
	return false;
}