/* * 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; }
Datum gin_compare_jsonb(PG_FUNCTION_ARGS) { text *arg1 = PG_GETARG_TEXT_PP(0); text *arg2 = PG_GETARG_TEXT_PP(1); int32 result; char *a1p, *a2p; int len1, len2; a1p = VARDATA_ANY(arg1); a2p = VARDATA_ANY(arg2); len1 = VARSIZE_ANY_EXHDR(arg1); len2 = VARSIZE_ANY_EXHDR(arg2); /* Compare text as bttextcmp does, but always using C collation */ result = varstr_cmp(a1p, len1, a2p, len2, C_COLLATION_OID); PG_FREE_IF_COPY(arg1, 0); PG_FREE_IF_COPY(arg2, 1); PG_RETURN_INT32(result); }
/* * nameeq - returns 1 iff arguments are equal * namene - returns 1 iff arguments are not equal * namelt - returns 1 iff a < b * namele - returns 1 iff a <= b * namegt - returns 1 iff a > b * namege - returns 1 iff a >= b * * Note that the use of strncmp with NAMEDATALEN limit is mostly historical; * strcmp would do as well, because we do not allow NAME values that don't * have a '\0' terminator. Whatever might be past the terminator is not * considered relevant to comparisons. */ static int namecmp(Name arg1, Name arg2, Oid collid) { /* Fast path for common case used in system catalogs */ if (collid == C_COLLATION_OID) return strncmp(NameStr(*arg1), NameStr(*arg2), NAMEDATALEN); /* Else rely on the varstr infrastructure */ return varstr_cmp(NameStr(*arg1), strlen(NameStr(*arg1)), NameStr(*arg2), strlen(NameStr(*arg2)), collid); }
/* text_cmp() * Internal comparison function for text strings. * Returns -1, 0 or 1 */ static int text_cmp(text *arg1, text *arg2, Oid collid) { char *a1p, *a2p; int len1, len2; a1p = VARDATA_ANY(arg1); a2p = VARDATA_ANY(arg2); len1 = VARSIZE_ANY_EXHDR(arg1); len2 = VARSIZE_ANY_EXHDR(arg2); return varstr_cmp(a1p, len1, a2p, len2, collid); }
Datum bpchar_smaller(PG_FUNCTION_ARGS) { BpChar *arg1 = PG_GETARG_BPCHAR_P(0); BpChar *arg2 = PG_GETARG_BPCHAR_P(1); int len1, len2; int cmp; len1 = bcTruelen(arg1); len2 = bcTruelen(arg2); cmp = varstr_cmp(VARDATA(arg1), len1, VARDATA(arg2), len2); PG_RETURN_BPCHAR_P((cmp <= 0) ? arg1 : arg2); }
/* * citextcmp() * Internal comparison function for citext strings. * Returns int32 negative, zero, or positive. */ static int32 citextcmp(text *left, text *right) { char *lcstr, *rcstr; int32 result; lcstr = str_tolower(VARDATA_ANY(left), VARSIZE_ANY_EXHDR(left)); rcstr = str_tolower(VARDATA_ANY(right), VARSIZE_ANY_EXHDR(right)); result = varstr_cmp(lcstr, strlen(lcstr), rcstr, strlen(rcstr)); pfree(lcstr); pfree(rcstr); return result; }
Datum bpcharcmp(PG_FUNCTION_ARGS) { BpChar *arg1 = PG_GETARG_BPCHAR_P(0); BpChar *arg2 = PG_GETARG_BPCHAR_P(1); int len1, len2; int cmp; len1 = bcTruelen(arg1); len2 = bcTruelen(arg2); cmp = varstr_cmp(VARDATA(arg1), len1, VARDATA(arg2), len2); PG_FREE_IF_COPY(arg1, 0); PG_FREE_IF_COPY(arg2, 1); PG_RETURN_INT32(cmp); }
/* * returns true, if query matches prefix ( common prefix ) */ static bool gbt_bytea_pf_match(const bytea *pf, const bytea *query, const gbtree_vinfo *tinfo) { bool out = FALSE; int32 k = 0; int32 qlen = VARSIZE(query) - VARHDRSZ; int32 nlen = VARSIZE(pf) - VARHDRSZ; if (nlen <= qlen) { char *q = VARDATA(query); char *n = VARDATA(pf); if (tinfo->eml > 1) { out = (varstr_cmp(q, nlen, n, nlen) == 0); } else { out = TRUE; for (k = 0; k < nlen; k++) { if (*n != *q) { out = FALSE; break; } if (k < (nlen - 1)) { q++; n++; } } } } return out; }
Datum bpcharne(PG_FUNCTION_ARGS) { BpChar *arg1 = PG_GETARG_BPCHAR_P(0); BpChar *arg2 = PG_GETARG_BPCHAR_P(1); int len1, len2; bool result; len1 = bcTruelen(arg1); len2 = bcTruelen(arg2); /* fast path for different-length inputs */ if (len1 != len2) result = true; else result = (varstr_cmp(VARDATA(arg1), len1, VARDATA(arg2), len2) != 0); PG_FREE_IF_COPY(arg1, 0); PG_FREE_IF_COPY(arg2, 1); PG_RETURN_BOOL(result); }
Datum spg_text_leaf_consistent(PG_FUNCTION_ARGS) { spgLeafConsistentIn *in = (spgLeafConsistentIn *) PG_GETARG_POINTER(0); spgLeafConsistentOut *out = (spgLeafConsistentOut *) PG_GETARG_POINTER(1); StrategyNumber strategy = in->strategy; text *query = DatumGetTextPP(in->query); int level = in->level; text *leafValue, *reconstrValue = NULL; char *fullValue; int fullLen; int queryLen; int r; bool res; /* all tests are exact */ out->recheck = false; leafValue = DatumGetTextPP(in->leafDatum); if (DatumGetPointer(in->reconstructedValue)) reconstrValue = DatumGetTextP(in->reconstructedValue); Assert(level == 0 ? reconstrValue == NULL : VARSIZE_ANY_EXHDR(reconstrValue) == level); fullLen = level + VARSIZE_ANY_EXHDR(leafValue); queryLen = VARSIZE_ANY_EXHDR(query); /* * For an equality check, we needn't reconstruct fullValue if not same * length; it can't match */ if (strategy == BTEqualStrategyNumber && queryLen != fullLen) PG_RETURN_BOOL(false); /* Else, reconstruct the full string represented by this leaf tuple */ if (VARSIZE_ANY_EXHDR(leafValue) == 0 && level > 0) { fullValue = VARDATA(reconstrValue); out->leafValue = PointerGetDatum(reconstrValue); } else { text *fullText = palloc(VARHDRSZ + fullLen); SET_VARSIZE(fullText, VARHDRSZ + fullLen); fullValue = VARDATA(fullText); if (level) memcpy(fullValue, VARDATA(reconstrValue), level); if (VARSIZE_ANY_EXHDR(leafValue) > 0) memcpy(fullValue + level, VARDATA_ANY(leafValue), VARSIZE_ANY_EXHDR(leafValue)); out->leafValue = PointerGetDatum(fullText); } /* Run the appropriate type of comparison */ if (strategy > 10) { /* Collation-aware comparison */ strategy -= 10; /* If asserts are enabled, verify encoding of reconstructed string */ Assert(pg_verifymbstr(fullValue, fullLen, false)); r = varstr_cmp(fullValue, Min(queryLen, fullLen), VARDATA_ANY(query), Min(queryLen, fullLen), PG_GET_COLLATION()); } else { /* Non-collation-aware comparison */ r = memcmp(fullValue, VARDATA_ANY(query), Min(queryLen, fullLen)); } if (r == 0) { if (queryLen > fullLen) r = -1; else if (queryLen < fullLen) r = 1; } switch (strategy) { case BTLessStrategyNumber: res = (r < 0); break; case BTLessEqualStrategyNumber: res = (r <= 0); break; case BTEqualStrategyNumber: res = (r == 0); break; case BTGreaterEqualStrategyNumber: res = (r >= 0); break; case BTGreaterStrategyNumber: res = (r > 0); break; default: elog(ERROR, "unrecognized strategy number: %d", in->strategy); res = false; break; } PG_RETURN_BOOL(res); }
Datum spg_text_leaf_consistent(PG_FUNCTION_ARGS) { spgLeafConsistentIn *in = (spgLeafConsistentIn *) PG_GETARG_POINTER(0); spgLeafConsistentOut *out = (spgLeafConsistentOut *) PG_GETARG_POINTER(1); int level = in->level; text *leafValue, *reconstrValue = NULL; char *fullValue; int fullLen; bool res; int j; /* all tests are exact */ out->recheck = false; leafValue = DatumGetTextPP(in->leafDatum); if (DatumGetPointer(in->reconstructedValue)) reconstrValue = DatumGetTextP(in->reconstructedValue); Assert(level == 0 ? reconstrValue == NULL : VARSIZE_ANY_EXHDR(reconstrValue) == level); /* Reconstruct the full string represented by this leaf tuple */ fullLen = level + VARSIZE_ANY_EXHDR(leafValue); if (VARSIZE_ANY_EXHDR(leafValue) == 0 && level > 0) { fullValue = VARDATA(reconstrValue); out->leafValue = PointerGetDatum(reconstrValue); } else { text *fullText = palloc(VARHDRSZ + fullLen); SET_VARSIZE(fullText, VARHDRSZ + fullLen); fullValue = VARDATA(fullText); if (level) memcpy(fullValue, VARDATA(reconstrValue), level); if (VARSIZE_ANY_EXHDR(leafValue) > 0) memcpy(fullValue + level, VARDATA_ANY(leafValue), VARSIZE_ANY_EXHDR(leafValue)); out->leafValue = PointerGetDatum(fullText); } /* Perform the required comparison(s) */ res = true; for (j = 0; j < in->nkeys; j++) { StrategyNumber strategy = in->scankeys[j].sk_strategy; text *query = DatumGetTextPP(in->scankeys[j].sk_argument); int queryLen = VARSIZE_ANY_EXHDR(query); int r; if (strategy > 10) { /* Collation-aware comparison */ strategy -= 10; /* If asserts enabled, verify encoding of reconstructed string */ Assert(pg_verifymbstr(fullValue, fullLen, false)); r = varstr_cmp(fullValue, Min(queryLen, fullLen), VARDATA_ANY(query), Min(queryLen, fullLen), PG_GET_COLLATION()); } else { /* Non-collation-aware comparison */ r = memcmp(fullValue, VARDATA_ANY(query), Min(queryLen, fullLen)); } if (r == 0) { if (queryLen > fullLen) r = -1; else if (queryLen < fullLen) r = 1; } switch (strategy) { case BTLessStrategyNumber: res = (r < 0); break; case BTLessEqualStrategyNumber: res = (r <= 0); break; case BTEqualStrategyNumber: res = (r == 0); break; case BTGreaterEqualStrategyNumber: res = (r >= 0); break; case BTGreaterStrategyNumber: res = (r > 0); break; default: elog(ERROR, "unrecognized strategy number: %d", in->scankeys[j].sk_strategy); res = false; break; } if (!res) break; /* no need to consider remaining conditions */ } PG_RETURN_BOOL(res); }