mirror of
https://git.postgresql.org/git/postgresql.git
synced 2024-12-27 08:39:28 +08:00
c52795d18a
- supports multibyte encodings - more strict rules for lexemes - flex isn't used Add: - tsquery plainto_tsquery(text) Function makes tsquery from plain text. - &&, ||, !! operation for tsquery for combining tsquery from it's parts: 'foo & bar' || 'asd' => 'foo & bar | asd'
188 lines
4.4 KiB
C
188 lines
4.4 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 );
|
|
|
|
|
|
|