diff options
Diffstat (limited to 'contrib/tsearch2/query_support.c')
-rw-r--r-- | contrib/tsearch2/query_support.c | 111 |
1 files changed, 111 insertions, 0 deletions
diff --git a/contrib/tsearch2/query_support.c b/contrib/tsearch2/query_support.c index c973def7d4d..edc2d48fcfb 100644 --- a/contrib/tsearch2/query_support.c +++ b/contrib/tsearch2/query_support.c @@ -14,6 +14,117 @@ tsquery_numnode(PG_FUNCTION_ARGS) { 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 ) { |