mirror of
				https://github.com/postgres/postgres.git
				synced 2025-10-30 00:04:49 -04:00 
			
		
		
		
	comment line where output as too long, and update typedefs for /lib directory. Also fix case where identifiers were used as variable names in the backend, but as typedefs in ecpg (favor the backend for indenting). Backpatch to 8.1.X.
		
			
				
	
	
		
			205 lines
		
	
	
		
			4.3 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			205 lines
		
	
	
		
			4.3 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| #include "postgres.h"
 | |
| #include "fmgr.h"
 | |
| 
 | |
| #include "query_util.h"
 | |
| 
 | |
| PG_FUNCTION_INFO_V1(tsquery_numnode);
 | |
| Datum		tsquery_numnode(PG_FUNCTION_ARGS);
 | |
| 
 | |
| Datum
 | |
| tsquery_numnode(PG_FUNCTION_ARGS)
 | |
| {
 | |
| 	QUERYTYPE  *query = (QUERYTYPE *) DatumGetPointer(PG_DETOAST_DATUM_COPY(PG_GETARG_DATUM(0)));
 | |
| 	int			nnode = query->size;
 | |
| 
 | |
| 	PG_FREE_IF_COPY(query, 0);
 | |
| 	PG_RETURN_INT32(nnode);
 | |
| }
 | |
| 
 | |
| static QTNode *
 | |
| join_tsqueries(QUERYTYPE * a, QUERYTYPE * b)
 | |
| {
 | |
| 	QTNode	   *res = (QTNode *) palloc0(sizeof(QTNode));
 | |
| 
 | |
| 	res->flags |= QTN_NEEDFREE;
 | |
| 
 | |
| 	res->valnode = (ITEM *) palloc0(sizeof(ITEM));
 | |
| 	res->valnode->type = OPR;
 | |
| 
 | |
| 	res->child = (QTNode **) palloc0(sizeof(QTNode *) * 2);
 | |
| 	res->child[0] = QT2QTN(GETQUERY(b), GETOPERAND(b));
 | |
| 	res->child[1] = QT2QTN(GETQUERY(a), GETOPERAND(a));
 | |
| 	res->nchild = 2;
 | |
| 
 | |
| 	return res;
 | |
| }
 | |
| 
 | |
| PG_FUNCTION_INFO_V1(tsquery_and);
 | |
| Datum		tsquery_and(PG_FUNCTION_ARGS);
 | |
| 
 | |
| Datum
 | |
| tsquery_and(PG_FUNCTION_ARGS)
 | |
| {
 | |
| 	QUERYTYPE  *a = (QUERYTYPE *) DatumGetPointer(PG_DETOAST_DATUM_COPY(PG_GETARG_DATUM(0)));
 | |
| 	QUERYTYPE  *b = (QUERYTYPE *) DatumGetPointer(PG_DETOAST_DATUM_COPY(PG_GETARG_DATUM(1)));
 | |
| 	QTNode	   *res;
 | |
| 	QUERYTYPE  *query;
 | |
| 
 | |
| 	if (a->size == 0)
 | |
| 	{
 | |
| 		PG_FREE_IF_COPY(a, 1);
 | |
| 		PG_RETURN_POINTER(b);
 | |
| 	}
 | |
| 	else if (b->size == 0)
 | |
| 	{
 | |
| 		PG_FREE_IF_COPY(b, 1);
 | |
| 		PG_RETURN_POINTER(a);
 | |
| 	}
 | |
| 
 | |
| 	res = join_tsqueries(a, b);
 | |
| 
 | |
| 	res->valnode->val = '&';
 | |
| 
 | |
| 	query = QTN2QT(res, PlainMemory);
 | |
| 
 | |
| 	QTNFree(res);
 | |
| 	PG_FREE_IF_COPY(a, 0);
 | |
| 	PG_FREE_IF_COPY(b, 1);
 | |
| 
 | |
| 	PG_RETURN_POINTER(query);
 | |
| }
 | |
| 
 | |
| PG_FUNCTION_INFO_V1(tsquery_or);
 | |
| Datum		tsquery_or(PG_FUNCTION_ARGS);
 | |
| 
 | |
| Datum
 | |
| tsquery_or(PG_FUNCTION_ARGS)
 | |
| {
 | |
| 	QUERYTYPE  *a = (QUERYTYPE *) DatumGetPointer(PG_DETOAST_DATUM_COPY(PG_GETARG_DATUM(0)));
 | |
| 	QUERYTYPE  *b = (QUERYTYPE *) DatumGetPointer(PG_DETOAST_DATUM_COPY(PG_GETARG_DATUM(1)));
 | |
| 	QTNode	   *res;
 | |
| 	QUERYTYPE  *query;
 | |
| 
 | |
| 	if (a->size == 0)
 | |
| 	{
 | |
| 		PG_FREE_IF_COPY(a, 1);
 | |
| 		PG_RETURN_POINTER(b);
 | |
| 	}
 | |
| 	else if (b->size == 0)
 | |
| 	{
 | |
| 		PG_FREE_IF_COPY(b, 1);
 | |
| 		PG_RETURN_POINTER(a);
 | |
| 	}
 | |
| 
 | |
| 	res = join_tsqueries(a, b);
 | |
| 
 | |
| 	res->valnode->val = '|';
 | |
| 
 | |
| 	query = QTN2QT(res, PlainMemory);
 | |
| 
 | |
| 	QTNFree(res);
 | |
| 	PG_FREE_IF_COPY(a, 0);
 | |
| 	PG_FREE_IF_COPY(b, 1);
 | |
| 
 | |
| 	PG_RETURN_POINTER(query);
 | |
| }
 | |
| 
 | |
| PG_FUNCTION_INFO_V1(tsquery_not);
 | |
| Datum		tsquery_not(PG_FUNCTION_ARGS);
 | |
| 
 | |
| Datum
 | |
| tsquery_not(PG_FUNCTION_ARGS)
 | |
| {
 | |
| 	QUERYTYPE  *a = (QUERYTYPE *) DatumGetPointer(PG_DETOAST_DATUM_COPY(PG_GETARG_DATUM(0)));
 | |
| 	QTNode	   *res;
 | |
| 	QUERYTYPE  *query;
 | |
| 
 | |
| 	if (a->size == 0)
 | |
| 		PG_RETURN_POINTER(a);
 | |
| 
 | |
| 	res = (QTNode *) palloc0(sizeof(QTNode));
 | |
| 
 | |
| 	res->flags |= QTN_NEEDFREE;
 | |
| 
 | |
| 	res->valnode = (ITEM *) palloc0(sizeof(ITEM));
 | |
| 	res->valnode->type = OPR;
 | |
| 	res->valnode->val = '!';
 | |
| 
 | |
| 	res->child = (QTNode **) palloc0(sizeof(QTNode *));
 | |
| 	res->child[0] = QT2QTN(GETQUERY(a), GETOPERAND(a));
 | |
| 	res->nchild = 1;
 | |
| 
 | |
| 	query = QTN2QT(res, PlainMemory);
 | |
| 
 | |
| 	QTNFree(res);
 | |
| 	PG_FREE_IF_COPY(a, 0);
 | |
| 
 | |
| 	PG_RETURN_POINTER(query);
 | |
| }
 | |
| 
 | |
| static int
 | |
| CompareTSQ(QUERYTYPE * a, QUERYTYPE * b)
 | |
| {
 | |
| 	if (a->size != b->size)
 | |
| 	{
 | |
| 		return (a->size < b->size) ? -1 : 1;
 | |
| 	}
 | |
| 	else if (a->len != b->len)
 | |
| 	{
 | |
| 		return (a->len < b->len) ? -1 : 1;
 | |
| 	}
 | |
| 	else
 | |
| 	{
 | |
| 		QTNode	   *an = QT2QTN(GETQUERY(a), GETOPERAND(a));
 | |
| 		QTNode	   *bn = QT2QTN(GETQUERY(b), GETOPERAND(b));
 | |
| 		int			res = QTNodeCompare(an, bn);
 | |
| 
 | |
| 		QTNFree(an);
 | |
| 		QTNFree(bn);
 | |
| 
 | |
| 		return res;
 | |
| 	}
 | |
| 
 | |
| 	return 0;
 | |
| }
 | |
| 
 | |
| PG_FUNCTION_INFO_V1(tsquery_cmp);
 | |
| \
 | |
| Datum		tsquery_cmp(PG_FUNCTION_ARGS);
 | |
| 
 | |
| Datum
 | |
| tsquery_cmp(PG_FUNCTION_ARGS)
 | |
| {
 | |
| 	QUERYTYPE  *a = (QUERYTYPE *) DatumGetPointer(PG_DETOAST_DATUM_COPY(PG_GETARG_DATUM(0)));
 | |
| 	QUERYTYPE  *b = (QUERYTYPE *) DatumGetPointer(PG_DETOAST_DATUM_COPY(PG_GETARG_DATUM(1)));
 | |
| 	int			res = CompareTSQ(a, b);
 | |
| 
 | |
| 	PG_FREE_IF_COPY(a, 0);
 | |
| 	PG_FREE_IF_COPY(b, 1);
 | |
| 
 | |
| 	PG_RETURN_INT32(res);
 | |
| }
 | |
| 
 | |
| #define CMPFUNC( NAME, ACTION )										\
 | |
| PG_FUNCTION_INFO_V1(NAME);										\
 | |
| Datum	NAME(PG_FUNCTION_ARGS);										\
 | |
| 													\
 | |
| Datum													\
 | |
| NAME(PG_FUNCTION_ARGS) {										\
 | |
| 	QUERYTYPE  *a = (QUERYTYPE *) DatumGetPointer(PG_DETOAST_DATUM_COPY(PG_GETARG_DATUM(0)));	\
 | |
| 	QUERYTYPE  *b = (QUERYTYPE *) DatumGetPointer(PG_DETOAST_DATUM_COPY(PG_GETARG_DATUM(1)));	\
 | |
| 	int res = CompareTSQ(a,b);									\
 | |
| 													\
 | |
| 	PG_FREE_IF_COPY(a,0);										\
 | |
| 	PG_FREE_IF_COPY(b,1);										\
 | |
| 													\
 | |
| 	PG_RETURN_BOOL( ACTION );									\
 | |
| }
 | |
| 
 | |
| CMPFUNC(tsquery_lt, res < 0);
 | |
| CMPFUNC(tsquery_le, res <= 0);
 | |
| CMPFUNC(tsquery_eq, res == 0);
 | |
| CMPFUNC(tsquery_ge, res >= 0);
 | |
| CMPFUNC(tsquery_gt, res > 0);
 | |
| CMPFUNC(tsquery_ne, res != 0);
 |