/* common code for bpchartypmodin and varchartypmodin */ static int32
anychar_typmodin(ArrayType *ta, constchar *typename)
{
int32 typmod;
int32 *tl; int n;
tl = ArrayGetIntegerTypmods(ta, &n);
/* *we'renottootenseaboutgooderrormessageherebecausegrammar *shouldn'tallowwrongnumberofmodifiersforCHAR
*/ if (n != 1)
ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("invalid type modifier")));
if (*tl < 1)
ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("length for type %s must be at least 1", typename))); if (*tl > MaxAttrSize)
ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("length for type %s cannot exceed %d", typename, MaxAttrSize)));
/* If typmod is -1 (or invalid), use the actual string length */ if (atttypmod < (int32) VARHDRSZ)
maxlen = len; else
{
size_t charlen; /* number of CHARACTERS in the input */
maxlen = atttypmod - VARHDRSZ;
charlen = pg_mbstrlen_with_len(s, len); if (charlen > maxlen)
{ /* Verify that extra characters are spaces, and clip them off */
size_t mbmaxlen = pg_mbcharcliplen(s, len, maxlen);
size_t j;
/* *atthispoint,lenistheactualBYTElengthoftheinput *string,maxlenisthemaxnumberofCHARACTERSallowedforthis *bpchartype,mbmaxlenisthelengthinBYTESofthosechars.
*/ for (j = mbmaxlen; j < len; j++)
{ if (s[j] != ' ')
ereturn(escontext, NULL,
(errcode(ERRCODE_STRING_DATA_RIGHT_TRUNCATION),
errmsg("value too long for type character(%d)",
(int) maxlen)));
}
/* *bpcharsend-convertsbpchartobinaryformat
*/
Datum
bpcharsend(PG_FUNCTION_ARGS)
{ /* Exactly the same as textsend, so share code */ return textsend(fcinfo);
}
/* *ConvertsaCHARACTERtypetothespecifiedsize. * *maxlenisthetypmod,ie,declaredlengthplusVARHDRSZbytes. *isExplicitistrueifthisisforanexplicitcasttochar(N). * *Truncationrules:foranexplicitcast,silentlytruncatetothegiven *length;foranimplicitcast,raiseerrorunlessextracharactersare *allspaces.(Thisissort-ofperSQL:thespecwouldactuallyhaveus *raisea"completioncondition"fortheexplicitcastcase,butPostgres *hasn'tgotsuchaconcept.)
*/
Datum
bpchar(PG_FUNCTION_ARGS)
{
BpChar *source = PG_GETARG_BPCHAR_PP(0);
int32 maxlen = PG_GETARG_INT32(1); bool isExplicit = PG_GETARG_BOOL(2);
BpChar *result;
int32 len; char *r; char *s; int i; int charlen; /* number of characters in the input string +
* VARHDRSZ */
/* No work if typmod is invalid */ if (maxlen < (int32) VARHDRSZ)
PG_RETURN_BPCHAR_P(source);
maxlen -= VARHDRSZ;
len = VARSIZE_ANY_EXHDR(source);
s = VARDATA_ANY(source);
charlen = pg_mbstrlen_with_len(s, len);
/* No work if supplied data matches typmod already */ if (charlen == maxlen)
PG_RETURN_BPCHAR_P(source);
if (charlen > maxlen)
{ /* Verify that extra characters are spaces, and clip them off */
size_t maxmblen;
maxmblen = pg_mbcharcliplen(s, len, maxlen);
if (!isExplicit)
{ for (i = maxmblen; i < len; i++) if (s[i] != ' ')
ereport(ERROR,
(errcode(ERRCODE_STRING_DATA_RIGHT_TRUNCATION),
errmsg("value too long for type character(%d)",
maxlen)));
}
if (atttypmod >= (int32) VARHDRSZ && len > maxlen)
{ /* Verify that extra characters are spaces, and clip them off */
size_t mbmaxlen = pg_mbcharcliplen(s, len, maxlen);
size_t j;
for (j = mbmaxlen; j < len; j++)
{ if (s[j] != ' ')
ereturn(escontext, NULL,
(errcode(ERRCODE_STRING_DATA_RIGHT_TRUNCATION),
errmsg("value too long for type character varying(%d)",
(int) maxlen)));
}
/* *varcharsend-convertsvarchartobinaryformat
*/
Datum
varcharsend(PG_FUNCTION_ARGS)
{ /* Exactly the same as textsend, so share code */ return textsend(fcinfo);
}
if (!isExplicit)
{ for (i = maxmblen; i < len; i++) if (s_data[i] != ' ')
ereport(ERROR,
(errcode(ERRCODE_STRING_DATA_RIGHT_TRUNCATION),
errmsg("value too long for type character varying(%d)",
maxlen)));
}
/* "True" length (not counting trailing blanks) of a BpChar */ staticinlineint
bcTruelen(BpChar *arg)
{ return bpchartruelen(VARDATA_ANY(arg), VARSIZE_ANY_EXHDR(arg));
}
int
bpchartruelen(char *s, int len)
{ int i;
/* *Notethatwerelyontheassumptionthat''isasingletonuniton *everysupportedmultibyteserverencoding.
*/ for (i = len - 1; i >= 0; i--)
{ if (s[i] != ' ') break;
} return i + 1;
}
Datum
bpcharlen(PG_FUNCTION_ARGS)
{
BpChar *arg = PG_GETARG_BPCHAR_PP(0); int len;
/* get number of bytes, ignoring trailing spaces */
len = bcTruelen(arg);
/* in multibyte encoding, convert to number of characters */ if (pg_database_encoding_max_length() != 1)
len = pg_mbstrlen_with_len(VARDATA_ANY(arg), len);
PG_RETURN_INT32(len);
}
Datum
bpcharoctetlen(PG_FUNCTION_ARGS)
{
Datum arg = PG_GETARG_DATUM(0);
/* We need not detoast the input at all */
PG_RETURN_INT32(toast_raw_datum_size(arg) - VARHDRSZ);
}
staticvoid
check_collation_set(Oid collid)
{ if (!OidIsValid(collid))
{ /* *Thistypicallymeansthattheparsercouldnotresolveaconflict *ofimplicitcollations,soreportitthatway.
*/
ereport(ERROR,
(errcode(ERRCODE_INDETERMINATE_COLLATION),
errmsg("could not determine which collation to use for string comparison"),
errhint("Use the COLLATE clause to set the collation explicitly.")));
}
}
Datum
bpchareq(PG_FUNCTION_ARGS)
{
BpChar *arg1 = PG_GETARG_BPCHAR_PP(0);
BpChar *arg2 = PG_GETARG_BPCHAR_PP(1); int len1,
len2; bool result;
Oid collid = PG_GET_COLLATION();
pg_locale_t mylocale;
check_collation_set(collid);
len1 = bcTruelen(arg1);
len2 = bcTruelen(arg2);
mylocale = pg_newlocale_from_collation(collid);
if (mylocale->deterministic)
{ /* *Sinceweonlycareaboutequalityornot-equality,wecanavoidall *theexpenseofstrcoll()here,andjustdobitwisecomparison.
*/ if (len1 != len2)
result = false; else
result = (memcmp(VARDATA_ANY(arg1), VARDATA_ANY(arg2), len1) == 0);
} else
{
result = (varstr_cmp(VARDATA_ANY(arg1), len1, VARDATA_ANY(arg2), len2,
collid) == 0);
}
/* *bpcharneedsaspecializedhashfunctionbecausewewanttoignore *trailingblanksincomparisons.
*/
Datum
hashbpchar(PG_FUNCTION_ARGS)
{
BpChar *key = PG_GETARG_BPCHAR_PP(0);
Oid collid = PG_GET_COLLATION(); char *keydata; int keylen;
pg_locale_t mylocale;
Datum result;
if (!collid)
ereport(ERROR,
(errcode(ERRCODE_INDETERMINATE_COLLATION),
errmsg("could not determine which collation to use for string hashing"),
errhint("Use the COLLATE clause to set the collation explicitly.")));
/* Avoid leaking memory for toasted inputs */
PG_FREE_IF_COPY(key, 0);
return result;
}
Datum
hashbpcharextended(PG_FUNCTION_ARGS)
{
BpChar *key = PG_GETARG_BPCHAR_PP(0);
Oid collid = PG_GET_COLLATION(); char *keydata; int keylen;
pg_locale_t mylocale;
Datum result;
if (!collid)
ereport(ERROR,
(errcode(ERRCODE_INDETERMINATE_COLLATION),
errmsg("could not determine which collation to use for string hashing"),
errhint("Use the COLLATE clause to set the collation explicitly.")));
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.