mirror of
				https://github.com/postgres/postgres.git
				synced 2025-10-29 22:49:41 +03:00 
			
		
		
		
	
		
			
				
	
	
		
			112 lines
		
	
	
		
			2.4 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			112 lines
		
	
	
		
			2.4 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /*
 | |
|  * txtquery operations with ltree
 | |
|  * Teodor Sigaev <teodor@stack.net>
 | |
|  * $PostgreSQL: pgsql/contrib/ltree/ltxtquery_op.c,v 1.6 2006/03/11 04:38:29 momjian Exp $
 | |
|  */
 | |
| 
 | |
| #include "ltree.h"
 | |
| #include <ctype.h>
 | |
| 
 | |
| PG_FUNCTION_INFO_V1(ltxtq_exec);
 | |
| PG_FUNCTION_INFO_V1(ltxtq_rexec);
 | |
| 
 | |
| /*
 | |
|  * check for boolean condition
 | |
|  */
 | |
| bool
 | |
| ltree_execute(ITEM * curitem, void *checkval, bool calcnot, bool (*chkcond) (void *checkval, ITEM * val))
 | |
| {
 | |
| 	if (curitem->type == VAL)
 | |
| 		return (*chkcond) (checkval, curitem);
 | |
| 	else if (curitem->val == (int4) '!')
 | |
| 	{
 | |
| 		return (calcnot) ?
 | |
| 			((ltree_execute(curitem + 1, checkval, calcnot, chkcond)) ? false : true)
 | |
| 			: true;
 | |
| 	}
 | |
| 	else if (curitem->val == (int4) '&')
 | |
| 	{
 | |
| 		if (ltree_execute(curitem + curitem->left, checkval, calcnot, chkcond))
 | |
| 			return ltree_execute(curitem + 1, checkval, calcnot, chkcond);
 | |
| 		else
 | |
| 			return false;
 | |
| 	}
 | |
| 	else
 | |
| 	{							/* |-operator */
 | |
| 		if (ltree_execute(curitem + curitem->left, checkval, calcnot, chkcond))
 | |
| 			return true;
 | |
| 		else
 | |
| 			return ltree_execute(curitem + 1, checkval, calcnot, chkcond);
 | |
| 	}
 | |
| 	return false;
 | |
| }
 | |
| 
 | |
| typedef struct
 | |
| {
 | |
| 	ltree	   *node;
 | |
| 	char	   *operand;
 | |
| }	CHKVAL;
 | |
| 
 | |
| static bool
 | |
| checkcondition_str(void *checkval, ITEM * val)
 | |
| {
 | |
| 	ltree_level *level = LTREE_FIRST(((CHKVAL *) checkval)->node);
 | |
| 	int			tlen = ((CHKVAL *) checkval)->node->numlevel;
 | |
| 	char	   *op = ((CHKVAL *) checkval)->operand + val->distance;
 | |
| 	int			(*cmpptr) (const char *, const char *, size_t);
 | |
| 
 | |
| 	cmpptr = (val->flag & LVAR_INCASE) ? pg_strncasecmp : strncmp;
 | |
| 	while (tlen > 0)
 | |
| 	{
 | |
| 		if (val->flag & LVAR_SUBLEXEME)
 | |
| 		{
 | |
| 			if (compare_subnode(level, op, val->length, cmpptr, (val->flag & LVAR_ANYEND)))
 | |
| 				return true;
 | |
| 		}
 | |
| 		else if (
 | |
| 				 (
 | |
| 				  val->length == level->len ||
 | |
| 				  (level->len > val->length && (val->flag & LVAR_ANYEND))
 | |
| 				  ) &&
 | |
| 				 (*cmpptr) (op, level->name, val->length) == 0)
 | |
| 			return true;
 | |
| 
 | |
| 		tlen--;
 | |
| 		level = LEVEL_NEXT(level);
 | |
| 	}
 | |
| 
 | |
| 	return false;
 | |
| }
 | |
| 
 | |
| Datum
 | |
| ltxtq_exec(PG_FUNCTION_ARGS)
 | |
| {
 | |
| 	ltree	   *val = PG_GETARG_LTREE(0);
 | |
| 	ltxtquery  *query = PG_GETARG_LTXTQUERY(1);
 | |
| 	CHKVAL		chkval;
 | |
| 	bool		result;
 | |
| 
 | |
| 	chkval.node = val;
 | |
| 	chkval.operand = GETOPERAND(query);
 | |
| 
 | |
| 	result = ltree_execute(
 | |
| 						   GETQUERY(query),
 | |
| 						   &chkval,
 | |
| 						   true,
 | |
| 						   checkcondition_str
 | |
| 		);
 | |
| 
 | |
| 	PG_FREE_IF_COPY(val, 0);
 | |
| 	PG_FREE_IF_COPY(query, 1);
 | |
| 	PG_RETURN_BOOL(result);
 | |
| }
 | |
| 
 | |
| Datum
 | |
| ltxtq_rexec(PG_FUNCTION_ARGS)
 | |
| {
 | |
| 	PG_RETURN_DATUM(DirectFunctionCall2(ltxtq_exec,
 | |
| 										PG_GETARG_DATUM(1),
 | |
| 										PG_GETARG_DATUM(0)
 | |
| 										));
 | |
| }
 |