openGauss-server/contrib/citext/citext.cpp

266 lines
6.2 KiB
C++

/*
* contrib/citext/citext.c
*/
#include "postgres.h"
#include "knl/knl_variable.h"
#include "access/hash.h"
#include "catalog/pg_collation.h"
#include "utils/builtins.h"
#include "utils/formatting.h"
#ifdef PG_MODULE_MAGIC
PG_MODULE_MAGIC;
#endif
/*
* ====================
* FORWARD DECLARATIONS
* ====================
*/
static int32 citextcmp(text* left, text* right, Oid collid);
extern "C" Datum citext_cmp(PG_FUNCTION_ARGS);
extern "C" Datum citext_hash(PG_FUNCTION_ARGS);
extern "C" Datum citext_eq(PG_FUNCTION_ARGS);
extern "C" Datum citext_ne(PG_FUNCTION_ARGS);
extern "C" Datum citext_gt(PG_FUNCTION_ARGS);
extern "C" Datum citext_ge(PG_FUNCTION_ARGS);
extern "C" Datum citext_lt(PG_FUNCTION_ARGS);
extern "C" Datum citext_le(PG_FUNCTION_ARGS);
extern "C" Datum citext_smaller(PG_FUNCTION_ARGS);
extern "C" Datum citext_larger(PG_FUNCTION_ARGS);
/*
* =================
* UTILITY FUNCTIONS
* =================
*/
/*
* citextcmp()
* Internal comparison function for citext strings.
* Returns int32 negative, zero, or positive.
*/
static int32 citextcmp(text* left, text* right, Oid collid)
{
char *lcstr, *rcstr;
int32 result;
/*
* We must do our str_tolower calls with DEFAULT_COLLATION_OID, not the
* input collation as you might expect. This is so that the behavior of
* citext's equality and hashing functions is not collation-dependent. We
* should change this once the core infrastructure is able to cope with
* collation-dependent equality and hashing functions.
*/
lcstr = str_tolower(VARDATA_ANY(left), VARSIZE_ANY_EXHDR(left), DEFAULT_COLLATION_OID);
rcstr = str_tolower(VARDATA_ANY(right), VARSIZE_ANY_EXHDR(right), DEFAULT_COLLATION_OID);
result = varstr_cmp(lcstr, strlen(lcstr), rcstr, strlen(rcstr), collid);
pfree(lcstr);
pfree(rcstr);
return result;
}
/*
* ==================
* INDEXING FUNCTIONS
* ==================
*/
PG_FUNCTION_INFO_V1(citext_cmp);
Datum citext_cmp(PG_FUNCTION_ARGS)
{
text* left = PG_GETARG_TEXT_PP(0);
text* right = PG_GETARG_TEXT_PP(1);
int32 result;
result = citextcmp(left, right, PG_GET_COLLATION());
PG_FREE_IF_COPY(left, 0);
PG_FREE_IF_COPY(right, 1);
PG_RETURN_INT32(result);
}
PG_FUNCTION_INFO_V1(citext_hash);
Datum citext_hash(PG_FUNCTION_ARGS)
{
text* txt = PG_GETARG_TEXT_PP(0);
char* str = NULL;
Datum result;
str = str_tolower(VARDATA_ANY(txt), VARSIZE_ANY_EXHDR(txt), DEFAULT_COLLATION_OID);
result = hash_any((unsigned char*)str, strlen(str));
pfree(str);
/* Avoid leaking memory for toasted inputs */
PG_FREE_IF_COPY(txt, 0);
PG_RETURN_DATUM(result);
}
/*
* ==================
* OPERATOR FUNCTIONS
* ==================
*/
PG_FUNCTION_INFO_V1(citext_eq);
Datum citext_eq(PG_FUNCTION_ARGS)
{
text* left = PG_GETARG_TEXT_PP(0);
text* right = PG_GETARG_TEXT_PP(1);
char* lcstr = NULL;
char* rcstr = NULL;
bool result = false;
/* We can't compare lengths in advance of downcasing ... */
lcstr = str_tolower(VARDATA_ANY(left), VARSIZE_ANY_EXHDR(left), DEFAULT_COLLATION_OID);
rcstr = str_tolower(VARDATA_ANY(right), VARSIZE_ANY_EXHDR(right), DEFAULT_COLLATION_OID);
/*
* Since we only care about equality or not-equality, we can avoid all the
* expense of strcoll() here, and just do bitwise comparison.
*/
result = (strcmp(lcstr, rcstr) == 0);
pfree(lcstr);
pfree(rcstr);
PG_FREE_IF_COPY(left, 0);
PG_FREE_IF_COPY(right, 1);
PG_RETURN_BOOL(result);
}
PG_FUNCTION_INFO_V1(citext_ne);
Datum citext_ne(PG_FUNCTION_ARGS)
{
text* left = PG_GETARG_TEXT_PP(0);
text* right = PG_GETARG_TEXT_PP(1);
char* lcstr = NULL;
char* rcstr = NULL;
bool result = false;
/* We can't compare lengths in advance of downcasing ... */
lcstr = str_tolower(VARDATA_ANY(left), VARSIZE_ANY_EXHDR(left), DEFAULT_COLLATION_OID);
rcstr = str_tolower(VARDATA_ANY(right), VARSIZE_ANY_EXHDR(right), DEFAULT_COLLATION_OID);
/*
* Since we only care about equality or not-equality, we can avoid all the
* expense of strcoll() here, and just do bitwise comparison.
*/
result = (strcmp(lcstr, rcstr) != 0);
pfree(lcstr);
pfree(rcstr);
PG_FREE_IF_COPY(left, 0);
PG_FREE_IF_COPY(right, 1);
PG_RETURN_BOOL(result);
}
PG_FUNCTION_INFO_V1(citext_lt);
Datum citext_lt(PG_FUNCTION_ARGS)
{
text* left = PG_GETARG_TEXT_PP(0);
text* right = PG_GETARG_TEXT_PP(1);
bool result = false;
result = citextcmp(left, right, PG_GET_COLLATION()) < 0;
PG_FREE_IF_COPY(left, 0);
PG_FREE_IF_COPY(right, 1);
PG_RETURN_BOOL(result);
}
PG_FUNCTION_INFO_V1(citext_le);
Datum citext_le(PG_FUNCTION_ARGS)
{
text* left = PG_GETARG_TEXT_PP(0);
text* right = PG_GETARG_TEXT_PP(1);
bool result = false;
result = citextcmp(left, right, PG_GET_COLLATION()) <= 0;
PG_FREE_IF_COPY(left, 0);
PG_FREE_IF_COPY(right, 1);
PG_RETURN_BOOL(result);
}
PG_FUNCTION_INFO_V1(citext_gt);
Datum citext_gt(PG_FUNCTION_ARGS)
{
text* left = PG_GETARG_TEXT_PP(0);
text* right = PG_GETARG_TEXT_PP(1);
bool result = false;
result = citextcmp(left, right, PG_GET_COLLATION()) > 0;
PG_FREE_IF_COPY(left, 0);
PG_FREE_IF_COPY(right, 1);
PG_RETURN_BOOL(result);
}
PG_FUNCTION_INFO_V1(citext_ge);
Datum citext_ge(PG_FUNCTION_ARGS)
{
text* left = PG_GETARG_TEXT_PP(0);
text* right = PG_GETARG_TEXT_PP(1);
bool result = false;
result = citextcmp(left, right, PG_GET_COLLATION()) >= 0;
PG_FREE_IF_COPY(left, 0);
PG_FREE_IF_COPY(right, 1);
PG_RETURN_BOOL(result);
}
/*
* ===================
* AGGREGATE FUNCTIONS
* ===================
*/
PG_FUNCTION_INFO_V1(citext_smaller);
Datum citext_smaller(PG_FUNCTION_ARGS)
{
text* left = PG_GETARG_TEXT_PP(0);
text* right = PG_GETARG_TEXT_PP(1);
text* result = NULL;
result = (citextcmp(left, right, PG_GET_COLLATION()) < 0) ? left : right;
PG_RETURN_TEXT_P(result);
}
PG_FUNCTION_INFO_V1(citext_larger);
Datum citext_larger(PG_FUNCTION_ARGS)
{
text* left = PG_GETARG_TEXT_PP(0);
text* right = PG_GETARG_TEXT_PP(1);
text* result = NULL;
result = (citextcmp(left, right, PG_GET_COLLATION()) > 0) ? left : right;
PG_RETURN_TEXT_P(result);
}