varchar.c 22.0 KB
Newer Older
1 2
/*-------------------------------------------------------------------------
 *
3
 * varchar.c
4
 *	  Functions for the built-in types char(n) and varchar(n).
5
 *
6
 * Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
B
Add:  
Bruce Momjian 已提交
7
 * Portions Copyright (c) 1994, Regents of the University of California
8 9 10
 *
 *
 * IDENTIFICATION
11
 *	  src/backend/utils/adt/varchar.c
12 13 14 15
 *
 *-------------------------------------------------------------------------
 */
#include "postgres.h"
16

17

18
#include "access/hash.h"
19
#include "access/tuptoaster.h"
20
#include "libpq/pqformat.h"
21
#include "utils/array.h"
B
Bruce Momjian 已提交
22
#include "utils/builtins.h"
B
Bruce Momjian 已提交
23 24
#include "mb/pg_wchar.h"

25

26 27 28 29
/* common code for bpchartypmodin and varchartypmodin */
static int32
anychar_typmodin(ArrayType *ta, const char *typename)
{
B
Bruce Momjian 已提交
30 31 32
	int32		typmod;
	int32	   *tl;
	int			n;
33

34
	tl = ArrayGetIntegerTypmods(ta, &n);
35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55

	/*
	 * we're not too tense about good error message here because grammar
	 * shouldn't allow wrong number of modifiers for CHAR
	 */
	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)));

	/*
B
Bruce Momjian 已提交
56 57 58
	 * For largely historical reasons, the typmod is VARHDRSZ plus the number
	 * of characters; there is enough client-side code that knows about that
	 * that we'd better not change it.
59 60 61 62 63 64 65 66 67 68
	 */
	typmod = VARHDRSZ + *tl;

	return typmod;
}

/* common code for bpchartypmodout and varchartypmodout */
static char *
anychar_typmodout(int32 typmod)
{
B
Bruce Momjian 已提交
69
	char	   *res = (char *) palloc(64);
70 71 72 73 74 75 76 77 78 79

	if (typmod > VARHDRSZ)
		snprintf(res, 64, "(%d)", (int) (typmod - VARHDRSZ));
	else
		*res = '\0';

	return res;
}


80
/*
81
 * CHAR() and VARCHAR() types are part of the SQL standard. CHAR()
82 83 84 85
 * is for blank-padded string whose length is specified in CREATE TABLE.
 * VARCHAR is for storing string whose length is at most the length specified
 * at CREATE TABLE time.
 *
86
 * It's hard to implement these types because we cannot figure out
87
 * the length of the type from the type itself. I changed (hopefully all) the
88 89 90 91
 * fmgr calls that invoke input functions of a data type to supply the
 * length also. (eg. in INSERTs, we have the tupleDescriptor which contains
 * the length of the attributes and hence the exact length of the char() or
 * varchar(). We pass this to bpcharin() or varcharin().) In the case where
92 93
 * we cannot determine the length, we pass in -1 instead and the input
 * converter does not enforce any length check.
94 95
 *
 * We actually implement this as a varlena so that we don't have to pass in
96 97 98
 * the length for the comparison functions. (The difference between these
 * types and "text" is that we truncate and possibly blank-pad the string
 * at insertion time.)
99
 *
100
 *															  - ay 6/95
101 102 103
 */


104 105
/*****************************************************************************
 *	 bpchar - char()														 *
106 107 108
 *****************************************************************************/

/*
109 110 111 112
 * bpchar_input -- common guts of bpcharin and bpcharrecv
 *
 * s is the input text of length len (may not be null-terminated)
 * atttypmod is the typmod value to apply
113
 *
114 115 116 117
 * Note that atttypmod is measured in characters, which
 * is not necessarily the same as the number of bytes.
 *
 * If the input string is too long, raise an error, unless the extra
118
 * characters are spaces, in which case they're truncated.  (per SQL)
119
 */
120 121
static BpChar *
bpchar_input(const char *s, size_t len, int32 atttypmod)
122
{
123 124
	BpChar	   *result;
	char	   *r;
125
	size_t		maxlen;
126

127 128
	/* If typmod is -1 (or invalid), use the actual string length */
	if (atttypmod < (int32) VARHDRSZ)
129
		maxlen = len;
130
	else
131
	{
B
Bruce Momjian 已提交
132
		size_t		charlen;	/* number of CHARACTERS in the input */
133

134
		maxlen = atttypmod - VARHDRSZ;
135
		charlen = pg_mbstrlen_with_len(s, len);
136 137 138 139
		if (charlen > maxlen)
		{
			/* Verify that extra characters are spaces, and clip them off */
			size_t		mbmaxlen = pg_mbcharcliplen(s, len, maxlen);
140
			size_t		j;
141 142 143 144

			/*
			 * at this point, len is the actual BYTE length of the input
			 * string, maxlen is the max number of CHARACTERS allowed for this
145
			 * bpchar type, mbmaxlen is the length in BYTES of those chars.
146
			 */
147 148 149 150 151 152 153 154
			for (j = mbmaxlen; j < len; j++)
			{
				if (s[j] != ' ')
					ereport(ERROR,
							(errcode(ERRCODE_STRING_DATA_RIGHT_TRUNCATION),
							 errmsg("value too long for type character(%d)",
									(int) maxlen)));
			}
155 156

			/*
B
Bruce Momjian 已提交
157 158
			 * Now we set maxlen to the necessary byte length, not the number
			 * of CHARACTERS!
159
			 */
160
			maxlen = len = mbmaxlen;
161
		}
162
		else
163 164
		{
			/*
B
Bruce Momjian 已提交
165 166
			 * Now we set maxlen to the necessary byte length, not the number
			 * of CHARACTERS!
167 168 169
			 */
			maxlen = len + (maxlen - charlen);
		}
T
Tatsuo Ishii 已提交
170
	}
171

172
	result = (BpChar *) palloc(maxlen + VARHDRSZ);
173
	SET_VARSIZE(result, maxlen + VARHDRSZ);
174
	r = VARDATA(result);
175
	memcpy(r, s, len);
176

177
	/* blank pad the string if necessary */
178 179
	if (maxlen > len)
		memset(r + len, ' ', maxlen - len);
180

181 182 183 184 185 186 187 188 189 190 191
	return result;
}

/*
 * Convert a C string to CHARACTER internal representation.  atttypmod
 * is the declared length of the type plus VARHDRSZ.
 */
Datum
bpcharin(PG_FUNCTION_ARGS)
{
	char	   *s = PG_GETARG_CSTRING(0);
B
Bruce Momjian 已提交
192

193 194 195 196 197 198 199
#ifdef NOT_USED
	Oid			typelem = PG_GETARG_OID(1);
#endif
	int32		atttypmod = PG_GETARG_INT32(2);
	BpChar	   *result;

	result = bpchar_input(s, strlen(s), atttypmod);
200
	PG_RETURN_BPCHAR_P(result);
201 202
}

203 204 205

/*
 * Convert a CHARACTER value to a C string.
206 207 208
 *
 * Uses the text conversion functions, which is only appropriate if BpChar
 * and text are equivalent types.
209
 */
210 211
Datum
bpcharout(PG_FUNCTION_ARGS)
212
{
213
	Datum		txt = PG_GETARG_DATUM(0);
214

215
	PG_RETURN_CSTRING(TextDatumGetCString(txt));
216 217
}

218 219 220 221 222 223
/*
 *		bpcharrecv			- converts external binary format to bpchar
 */
Datum
bpcharrecv(PG_FUNCTION_ARGS)
{
224
	StringInfo	buf = (StringInfo) PG_GETARG_POINTER(0);
B
Bruce Momjian 已提交
225

226 227 228 229 230 231 232 233 234 235 236 237
#ifdef NOT_USED
	Oid			typelem = PG_GETARG_OID(1);
#endif
	int32		atttypmod = PG_GETARG_INT32(2);
	BpChar	   *result;
	char	   *str;
	int			nbytes;

	str = pq_getmsgtext(buf, buf->len - buf->cursor, &nbytes);
	result = bpchar_input(str, nbytes, atttypmod);
	pfree(str);
	PG_RETURN_BPCHAR_P(result);
238 239 240 241 242 243 244 245 246 247 248 249
}

/*
 *		bpcharsend			- converts bpchar to binary format
 */
Datum
bpcharsend(PG_FUNCTION_ARGS)
{
	/* Exactly the same as textsend, so share code */
	return textsend(fcinfo);
}

250 251

/*
252 253 254 255 256 257 258
 * Converts a CHARACTER type to the specified size.
 *
 * maxlen is the typmod, ie, declared length plus VARHDRSZ bytes.
 * isExplicit is true if this is for an explicit cast to char(N).
 *
 * Truncation rules: for an explicit cast, silently truncate to the given
 * length; for an implicit cast, raise error unless extra characters are
B
Bruce Momjian 已提交
259
 * all spaces.	(This is sort-of per SQL: the spec would actually have us
260 261
 * raise a "completion condition" for the explicit cast case, but Postgres
 * hasn't got such a concept.)
262
 */
263 264
Datum
bpchar(PG_FUNCTION_ARGS)
265
{
266
	BpChar	   *source = PG_GETARG_BPCHAR_PP(0);
267
	int32		maxlen = PG_GETARG_INT32(1);
268
	bool		isExplicit = PG_GETARG_BOOL(2);
269
	BpChar	   *result;
270 271 272
	int32		len;
	char	   *r;
	char	   *s;
273
	int			i;
B
Bruce Momjian 已提交
274 275
	int			charlen;		/* number of characters in the input string +
								 * VARHDRSZ */
B
Bruce Momjian 已提交
276

277 278 279 280
	/* No work if typmod is invalid */
	if (maxlen < (int32) VARHDRSZ)
		PG_RETURN_BPCHAR_P(source);

281
	maxlen -= VARHDRSZ;
282

283 284 285 286
	len = VARSIZE_ANY_EXHDR(source);
	s = VARDATA_ANY(source);

	charlen = pg_mbstrlen_with_len(s, len);
287

288 289
	/* No work if supplied data matches typmod already */
	if (charlen == maxlen)
290
		PG_RETURN_BPCHAR_P(source);
291

T
Tatsuo Ishii 已提交
292
	if (charlen > maxlen)
293
	{
294
		/* Verify that extra characters are spaces, and clip them off */
295
		size_t		maxmblen;
296

297
		maxmblen = pg_mbcharcliplen(s, len, maxlen);
B
Bruce Momjian 已提交
298

299 300
		if (!isExplicit)
		{
301 302
			for (i = maxmblen; i < len; i++)
				if (s[i] != ' ')
303
					ereport(ERROR,
B
Bruce Momjian 已提交
304 305
							(errcode(ERRCODE_STRING_DATA_RIGHT_TRUNCATION),
							 errmsg("value too long for type character(%d)",
306
									maxlen)));
307
		}
B
Bruce Momjian 已提交
308

309
		len = maxmblen;
310

T
Tatsuo Ishii 已提交
311
		/*
B
Bruce Momjian 已提交
312 313
		 * At this point, maxlen is the necessary byte length, not the number
		 * of CHARACTERS!
T
Tatsuo Ishii 已提交
314 315
		 */
		maxlen = len;
316
	}
T
Tatsuo Ishii 已提交
317 318 319
	else
	{
		/*
B
Bruce Momjian 已提交
320 321
		 * At this point, maxlen is the necessary byte length, not the number
		 * of CHARACTERS!
T
Tatsuo Ishii 已提交
322 323 324
		 */
		maxlen = len + (maxlen - charlen);
	}
325

326
	Assert(maxlen >= len);
327

B
Bruce Momjian 已提交
328 329
	result = palloc(maxlen + VARHDRSZ);
	SET_VARSIZE(result, maxlen + VARHDRSZ);
330 331
	r = VARDATA(result);

332
	memcpy(r, s, len);
333 334

	/* blank pad the string if necessary */
335
	if (maxlen > len)
336
		memset(r + len, ' ', maxlen - len);
337

338 339
	PG_RETURN_BPCHAR_P(result);
}
340

341

342 343 344
/* char_bpchar()
 * Convert char to bpchar(1).
 */
345 346
Datum
char_bpchar(PG_FUNCTION_ARGS)
347
{
348
	char		c = PG_GETARG_CHAR(0);
349
	BpChar	   *result;
350

351
	result = (BpChar *) palloc(VARHDRSZ + 1);
352

353
	SET_VARSIZE(result, VARHDRSZ + 1);
354
	*(VARDATA(result)) = c;
355

356 357
	PG_RETURN_BPCHAR_P(result);
}
358 359


360 361 362
/* bpchar_name()
 * Converts a bpchar() type to a NameData type.
 */
363 364
Datum
bpchar_name(PG_FUNCTION_ARGS)
365
{
366
	BpChar	   *s = PG_GETARG_BPCHAR_PP(0);
B
Bruce Momjian 已提交
367
	char	   *s_data;
368
	Name		result;
369 370
	int			len;

371 372
	len = VARSIZE_ANY_EXHDR(s);
	s_data = VARDATA_ANY(s);
373 374

	/* Truncate to max length for a Name */
375
	if (len >= NAMEDATALEN)
B
Bruce Momjian 已提交
376
		len = NAMEDATALEN - 1;
377

378
	/* Remove trailing blanks */
379 380
	while (len > 0)
	{
381
		if (s_data[len - 1] != ' ')
382
			break;
383 384 385 386
		len--;
	}

	result = (NameData *) palloc(NAMEDATALEN);
387
	memcpy(NameStr(*result), s_data, len);
388

389
	/* Now null pad to full length... */
390 391
	while (len < NAMEDATALEN)
	{
392
		*(NameStr(*result) + len) = '\0';
393 394 395
		len++;
	}

396 397
	PG_RETURN_NAME(result);
}
398 399 400

/* name_bpchar()
 * Converts a NameData type to a bpchar type.
401 402 403
 *
 * Uses the text conversion functions, which is only appropriate if BpChar
 * and text are equivalent types.
404
 */
405 406
Datum
name_bpchar(PG_FUNCTION_ARGS)
407
{
408 409
	Name		s = PG_GETARG_NAME(0);
	BpChar	   *result;
410

411
	result = (BpChar *) cstring_to_text(NameStr(*s));
412 413
	PG_RETURN_BPCHAR_P(result);
}
414

415 416 417
Datum
bpchartypmodin(PG_FUNCTION_ARGS)
{
B
Bruce Momjian 已提交
418
	ArrayType  *ta = PG_GETARG_ARRAYTYPE_P(0);
419 420 421 422 423 424 425

	PG_RETURN_INT32(anychar_typmodin(ta, "char"));
}

Datum
bpchartypmodout(PG_FUNCTION_ARGS)
{
B
Bruce Momjian 已提交
426
	int32		typmod = PG_GETARG_INT32(0);
427 428 429 430

	PG_RETURN_CSTRING(anychar_typmodout(typmod));
}

431

432
/*****************************************************************************
433 434 435 436
 *	 varchar - varchar(n)
 *
 * Note: varchar piggybacks on type text for most operations, and so has no
 * C-coded functions except for I/O and typmod checking.
437 438 439
 *****************************************************************************/

/*
440 441 442 443
 * varchar_input -- common guts of varcharin and varcharrecv
 *
 * s is the input text of length len (may not be null-terminated)
 * atttypmod is the typmod value to apply
444
 *
445
 * Note that atttypmod is measured in characters, which
446
 * is not necessarily the same as the number of bytes.
T
Tatsuo Ishii 已提交
447
 *
448 449
 * If the input string is too long, raise an error, unless the extra
 * characters are spaces, in which case they're truncated.  (per SQL)
450 451 452
 *
 * Uses the C string to text conversion function, which is only appropriate
 * if VarChar and text are equivalent types.
453
 */
454 455
static VarChar *
varchar_input(const char *s, size_t len, int32 atttypmod)
456
{
B
Bruce Momjian 已提交
457
	VarChar    *result;
458
	size_t		maxlen;
459

460
	maxlen = atttypmod - VARHDRSZ;
461

462 463
	if (atttypmod >= (int32) VARHDRSZ && len > maxlen)
	{
464
		/* Verify that extra characters are spaces, and clip them off */
465
		size_t		mbmaxlen = pg_mbcharcliplen(s, len, maxlen);
466
		size_t		j;
467

468 469 470 471 472
		for (j = mbmaxlen; j < len; j++)
		{
			if (s[j] != ' ')
				ereport(ERROR,
						(errcode(ERRCODE_STRING_DATA_RIGHT_TRUNCATION),
B
Bruce Momjian 已提交
473 474
					  errmsg("value too long for type character varying(%d)",
							 (int) maxlen)));
475 476 477
		}

		len = mbmaxlen;
478
	}
479

480
	result = (VarChar *) cstring_to_text_with_len(s, len);
481 482 483 484 485 486 487 488 489 490 491
	return result;
}

/*
 * Convert a C string to VARCHAR internal representation.  atttypmod
 * is the declared length of the type plus VARHDRSZ.
 */
Datum
varcharin(PG_FUNCTION_ARGS)
{
	char	   *s = PG_GETARG_CSTRING(0);
B
Bruce Momjian 已提交
492

493 494 495 496 497 498 499
#ifdef NOT_USED
	Oid			typelem = PG_GETARG_OID(1);
#endif
	int32		atttypmod = PG_GETARG_INT32(2);
	VarChar    *result;

	result = varchar_input(s, strlen(s), atttypmod);
500
	PG_RETURN_VARCHAR_P(result);
501 502
}

503 504 505

/*
 * Convert a VARCHAR value to a C string.
506 507 508
 *
 * Uses the text to C string conversion function, which is only appropriate
 * if VarChar and text are equivalent types.
509
 */
510 511
Datum
varcharout(PG_FUNCTION_ARGS)
512
{
513
	Datum		txt = PG_GETARG_DATUM(0);
514

515
	PG_RETURN_CSTRING(TextDatumGetCString(txt));
516 517
}

518 519 520 521 522 523
/*
 *		varcharrecv			- converts external binary format to varchar
 */
Datum
varcharrecv(PG_FUNCTION_ARGS)
{
524
	StringInfo	buf = (StringInfo) PG_GETARG_POINTER(0);
B
Bruce Momjian 已提交
525

526 527 528 529
#ifdef NOT_USED
	Oid			typelem = PG_GETARG_OID(1);
#endif
	int32		atttypmod = PG_GETARG_INT32(2);
B
Bruce Momjian 已提交
530
	VarChar    *result;
531 532 533 534 535 536 537
	char	   *str;
	int			nbytes;

	str = pq_getmsgtext(buf, buf->len - buf->cursor, &nbytes);
	result = varchar_input(str, nbytes, atttypmod);
	pfree(str);
	PG_RETURN_VARCHAR_P(result);
538 539 540 541 542 543 544 545 546 547 548 549
}

/*
 *		varcharsend			- converts varchar to binary format
 */
Datum
varcharsend(PG_FUNCTION_ARGS)
{
	/* Exactly the same as textsend, so share code */
	return textsend(fcinfo);
}

550 551

/*
552 553 554 555 556 557 558
 * Converts a VARCHAR type to the specified size.
 *
 * maxlen is the typmod, ie, declared length plus VARHDRSZ bytes.
 * isExplicit is true if this is for an explicit cast to varchar(N).
 *
 * Truncation rules: for an explicit cast, silently truncate to the given
 * length; for an implicit cast, raise error unless extra characters are
B
Bruce Momjian 已提交
559
 * all spaces.	(This is sort-of per SQL: the spec would actually have us
560 561
 * raise a "completion condition" for the explicit cast case, but Postgres
 * hasn't got such a concept.)
562
 */
563 564
Datum
varchar(PG_FUNCTION_ARGS)
565
{
566 567
	VarChar    *source = PG_GETARG_VARCHAR_PP(0);
	int32		typmod = PG_GETARG_INT32(1);
568
	bool		isExplicit = PG_GETARG_BOOL(2);
B
Bruce Momjian 已提交
569 570
	int32		len,
				maxlen;
571
	size_t		maxmblen;
572
	int			i;
B
Bruce Momjian 已提交
573
	char	   *s_data;
574 575 576 577

	len = VARSIZE_ANY_EXHDR(source);
	s_data = VARDATA_ANY(source);
	maxlen = typmod - VARHDRSZ;
578

579
	/* No work if typmod is invalid or supplied data fits it already */
580
	if (maxlen < 0 || len <= maxlen)
581
		PG_RETURN_VARCHAR_P(source);
582

583
	/* only reach here if string is too long... */
584

585
	/* truncate multibyte string preserving multibyte boundary */
586
	maxmblen = pg_mbcharcliplen(s_data, len, maxlen);
587

588 589
	if (!isExplicit)
	{
590 591
		for (i = maxmblen; i < len; i++)
			if (s_data[i] != ' ')
592
				ereport(ERROR,
593
						(errcode(ERRCODE_STRING_DATA_RIGHT_TRUNCATION),
B
Bruce Momjian 已提交
594 595
					  errmsg("value too long for type character varying(%d)",
							 maxlen)));
596
	}
597

598
	PG_RETURN_VARCHAR_P((VarChar *) cstring_to_text_with_len(s_data,
599
															 maxmblen));
600
}
601

602 603 604
Datum
varchartypmodin(PG_FUNCTION_ARGS)
{
B
Bruce Momjian 已提交
605
	ArrayType  *ta = PG_GETARG_ARRAYTYPE_P(0);
606 607 608 609 610 611 612

	PG_RETURN_INT32(anychar_typmodin(ta, "varchar"));
}

Datum
varchartypmodout(PG_FUNCTION_ARGS)
{
B
Bruce Momjian 已提交
613
	int32		typmod = PG_GETARG_INT32(0);
614 615 616 617

	PG_RETURN_CSTRING(anychar_typmodout(typmod));
}

618 619 620 621 622

/*****************************************************************************
 * Exported functions
 *****************************************************************************/

623
/* "True" length (not counting trailing blanks) of a BpChar */
624
static int
625
bcTruelen(BpChar *arg)
626
{
627
	char	   *s = VARDATA_ANY(arg);
628 629
	int			i;
	int			len;
630

631
	len = VARSIZE_ANY_EXHDR(arg);
632 633 634 635 636
	for (i = len - 1; i >= 0; i--)
	{
		if (s[i] != ' ')
			break;
	}
637
	return i + 1;
638 639
}

640 641
Datum
bpcharlen(PG_FUNCTION_ARGS)
M
Marc G. Fournier 已提交
642
{
643
	BpChar	   *arg = PG_GETARG_BPCHAR_PP(0);
644
	int			len;
B
Bruce Momjian 已提交
645

646 647
	/* get number of bytes, ignoring trailing spaces */
	len = bcTruelen(arg);
B
Bruce Momjian 已提交
648

649 650
	/* in multibyte encoding, convert to number of characters */
	if (pg_database_encoding_max_length() != 1)
651
		len = pg_mbstrlen_with_len(VARDATA_ANY(arg), len);
652

653
	PG_RETURN_INT32(len);
M
Marc G. Fournier 已提交
654 655
}

656 657
Datum
bpcharoctetlen(PG_FUNCTION_ARGS)
658
{
B
Bruce Momjian 已提交
659
	Datum		arg = PG_GETARG_DATUM(0);
660

661 662
	/* We need not detoast the input at all */
	PG_RETURN_INT32(toast_raw_datum_size(arg) - VARHDRSZ);
B
Bruce Momjian 已提交
663
}
664

665 666 667 668 669 670 671 672 673 674 675

/*****************************************************************************
 *	Comparison Functions used for bpchar
 *
 * Note: btree indexes need these routines not to leak memory; therefore,
 * be careful to free working copies of toasted datums.  Most places don't
 * need to be so careful.
 *****************************************************************************/

Datum
bpchareq(PG_FUNCTION_ARGS)
676
{
677 678
	BpChar	   *arg1 = PG_GETARG_BPCHAR_PP(0);
	BpChar	   *arg2 = PG_GETARG_BPCHAR_PP(1);
679 680
	int			len1,
				len2;
681
	bool		result;
682 683 684

	len1 = bcTruelen(arg1);
	len2 = bcTruelen(arg2);
685

686
	/*
B
Bruce Momjian 已提交
687 688
	 * Since we only care about equality or not-equality, we can avoid all the
	 * expense of strcoll() here, and just do bitwise comparison.
689
	 */
690
	if (len1 != len2)
691 692
		result = false;
	else
693
		result = (memcmp(VARDATA_ANY(arg1), VARDATA_ANY(arg2), len1) == 0);
694

695 696 697 698
	PG_FREE_IF_COPY(arg1, 0);
	PG_FREE_IF_COPY(arg2, 1);

	PG_RETURN_BOOL(result);
699 700
}

701 702
Datum
bpcharne(PG_FUNCTION_ARGS)
703
{
704 705
	BpChar	   *arg1 = PG_GETARG_BPCHAR_PP(0);
	BpChar	   *arg2 = PG_GETARG_BPCHAR_PP(1);
706 707
	int			len1,
				len2;
708
	bool		result;
709

710 711
	len1 = bcTruelen(arg1);
	len2 = bcTruelen(arg2);
712

713
	/*
B
Bruce Momjian 已提交
714 715
	 * Since we only care about equality or not-equality, we can avoid all the
	 * expense of strcoll() here, and just do bitwise comparison.
716
	 */
717
	if (len1 != len2)
718 719
		result = true;
	else
720
		result = (memcmp(VARDATA_ANY(arg1), VARDATA_ANY(arg2), len1) != 0);
721 722 723

	PG_FREE_IF_COPY(arg1, 0);
	PG_FREE_IF_COPY(arg2, 1);
724

725
	PG_RETURN_BOOL(result);
726 727
}

728 729
Datum
bpcharlt(PG_FUNCTION_ARGS)
730
{
731 732
	BpChar	   *arg1 = PG_GETARG_BPCHAR_PP(0);
	BpChar	   *arg2 = PG_GETARG_BPCHAR_PP(1);
733 734 735
	int			len1,
				len2;
	int			cmp;
736 737 738 739

	len1 = bcTruelen(arg1);
	len2 = bcTruelen(arg2);

740
	cmp = varstr_cmp(VARDATA_ANY(arg1), len1, VARDATA_ANY(arg2), len2);
741 742 743 744 745

	PG_FREE_IF_COPY(arg1, 0);
	PG_FREE_IF_COPY(arg2, 1);

	PG_RETURN_BOOL(cmp < 0);
746 747
}

748 749
Datum
bpcharle(PG_FUNCTION_ARGS)
750
{
751 752
	BpChar	   *arg1 = PG_GETARG_BPCHAR_PP(0);
	BpChar	   *arg2 = PG_GETARG_BPCHAR_PP(1);
753 754 755
	int			len1,
				len2;
	int			cmp;
756 757 758 759

	len1 = bcTruelen(arg1);
	len2 = bcTruelen(arg2);

760
	cmp = varstr_cmp(VARDATA_ANY(arg1), len1, VARDATA_ANY(arg2), len2);
761 762 763 764 765

	PG_FREE_IF_COPY(arg1, 0);
	PG_FREE_IF_COPY(arg2, 1);

	PG_RETURN_BOOL(cmp <= 0);
766 767
}

768 769
Datum
bpchargt(PG_FUNCTION_ARGS)
770
{
771 772
	BpChar	   *arg1 = PG_GETARG_BPCHAR_PP(0);
	BpChar	   *arg2 = PG_GETARG_BPCHAR_PP(1);
773 774 775
	int			len1,
				len2;
	int			cmp;
776 777 778 779

	len1 = bcTruelen(arg1);
	len2 = bcTruelen(arg2);

780
	cmp = varstr_cmp(VARDATA_ANY(arg1), len1, VARDATA_ANY(arg2), len2);
781 782 783 784 785

	PG_FREE_IF_COPY(arg1, 0);
	PG_FREE_IF_COPY(arg2, 1);

	PG_RETURN_BOOL(cmp > 0);
786 787
}

788 789
Datum
bpcharge(PG_FUNCTION_ARGS)
790
{
791 792
	BpChar	   *arg1 = PG_GETARG_BPCHAR_PP(0);
	BpChar	   *arg2 = PG_GETARG_BPCHAR_PP(1);
793 794 795
	int			len1,
				len2;
	int			cmp;
796 797 798 799

	len1 = bcTruelen(arg1);
	len2 = bcTruelen(arg2);

800
	cmp = varstr_cmp(VARDATA_ANY(arg1), len1, VARDATA_ANY(arg2), len2);
801 802 803 804 805

	PG_FREE_IF_COPY(arg1, 0);
	PG_FREE_IF_COPY(arg2, 1);

	PG_RETURN_BOOL(cmp >= 0);
806 807
}

808 809
Datum
bpcharcmp(PG_FUNCTION_ARGS)
810
{
811 812
	BpChar	   *arg1 = PG_GETARG_BPCHAR_PP(0);
	BpChar	   *arg2 = PG_GETARG_BPCHAR_PP(1);
813 814 815
	int			len1,
				len2;
	int			cmp;
816 817 818 819

	len1 = bcTruelen(arg1);
	len2 = bcTruelen(arg2);

820
	cmp = varstr_cmp(VARDATA_ANY(arg1), len1, VARDATA_ANY(arg2), len2);
821 822 823 824 825

	PG_FREE_IF_COPY(arg1, 0);
	PG_FREE_IF_COPY(arg2, 1);

	PG_RETURN_INT32(cmp);
826 827
}

828 829 830
Datum
bpchar_larger(PG_FUNCTION_ARGS)
{
831 832
	BpChar	   *arg1 = PG_GETARG_BPCHAR_PP(0);
	BpChar	   *arg2 = PG_GETARG_BPCHAR_PP(1);
833 834 835 836 837 838 839
	int			len1,
				len2;
	int			cmp;

	len1 = bcTruelen(arg1);
	len2 = bcTruelen(arg2);

840
	cmp = varstr_cmp(VARDATA_ANY(arg1), len1, VARDATA_ANY(arg2), len2);
841 842 843 844 845 846 847

	PG_RETURN_BPCHAR_P((cmp >= 0) ? arg1 : arg2);
}

Datum
bpchar_smaller(PG_FUNCTION_ARGS)
{
848 849
	BpChar	   *arg1 = PG_GETARG_BPCHAR_PP(0);
	BpChar	   *arg2 = PG_GETARG_BPCHAR_PP(1);
850 851 852 853 854 855 856
	int			len1,
				len2;
	int			cmp;

	len1 = bcTruelen(arg1);
	len2 = bcTruelen(arg2);

857
	cmp = varstr_cmp(VARDATA_ANY(arg1), len1, VARDATA_ANY(arg2), len2);
858 859 860 861

	PG_RETURN_BPCHAR_P((cmp <= 0) ? arg1 : arg2);
}

862 863 864

/*
 * bpchar needs a specialized hash function because we want to ignore
865
 * trailing blanks in comparisons.
866
 *
867 868 869
 * Note: currently there is no need for locale-specific behavior here,
 * but if we ever change the semantics of bpchar comparison to trust
 * strcoll() completely, we'd need to do something different in non-C locales.
870 871 872 873
 */
Datum
hashbpchar(PG_FUNCTION_ARGS)
{
874
	BpChar	   *key = PG_GETARG_BPCHAR_PP(0);
875 876
	char	   *keydata;
	int			keylen;
877
	Datum		result;
878

879
	keydata = VARDATA_ANY(key);
880 881
	keylen = bcTruelen(key);

882
	result = hash_any((unsigned char *) keydata, keylen);
883 884 885 886 887

	/* Avoid leaking memory for toasted inputs */
	PG_FREE_IF_COPY(key, 0);

	return result;
888
}
889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907


/*
 * The following operators support character-by-character comparison
 * of bpchar datums, to allow building indexes suitable for LIKE clauses.
 * Note that the regular bpchareq/bpcharne comparison operators are assumed
 * to be compatible with these!
 */

static int
internal_bpchar_pattern_compare(BpChar *arg1, BpChar *arg2)
{
	int			result;
	int			len1,
				len2;

	len1 = bcTruelen(arg1);
	len2 = bcTruelen(arg2);

908
	result = memcmp(VARDATA_ANY(arg1), VARDATA_ANY(arg2), Min(len1, len2));
909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997
	if (result != 0)
		return result;
	else if (len1 < len2)
		return -1;
	else if (len1 > len2)
		return 1;
	else
		return 0;
}


Datum
bpchar_pattern_lt(PG_FUNCTION_ARGS)
{
	BpChar	   *arg1 = PG_GETARG_BPCHAR_PP(0);
	BpChar	   *arg2 = PG_GETARG_BPCHAR_PP(1);
	int			result;

	result = internal_bpchar_pattern_compare(arg1, arg2);

	PG_FREE_IF_COPY(arg1, 0);
	PG_FREE_IF_COPY(arg2, 1);

	PG_RETURN_BOOL(result < 0);
}


Datum
bpchar_pattern_le(PG_FUNCTION_ARGS)
{
	BpChar	   *arg1 = PG_GETARG_BPCHAR_PP(0);
	BpChar	   *arg2 = PG_GETARG_BPCHAR_PP(1);
	int			result;

	result = internal_bpchar_pattern_compare(arg1, arg2);

	PG_FREE_IF_COPY(arg1, 0);
	PG_FREE_IF_COPY(arg2, 1);

	PG_RETURN_BOOL(result <= 0);
}


Datum
bpchar_pattern_ge(PG_FUNCTION_ARGS)
{
	BpChar	   *arg1 = PG_GETARG_BPCHAR_PP(0);
	BpChar	   *arg2 = PG_GETARG_BPCHAR_PP(1);
	int			result;

	result = internal_bpchar_pattern_compare(arg1, arg2);

	PG_FREE_IF_COPY(arg1, 0);
	PG_FREE_IF_COPY(arg2, 1);

	PG_RETURN_BOOL(result >= 0);
}


Datum
bpchar_pattern_gt(PG_FUNCTION_ARGS)
{
	BpChar	   *arg1 = PG_GETARG_BPCHAR_PP(0);
	BpChar	   *arg2 = PG_GETARG_BPCHAR_PP(1);
	int			result;

	result = internal_bpchar_pattern_compare(arg1, arg2);

	PG_FREE_IF_COPY(arg1, 0);
	PG_FREE_IF_COPY(arg2, 1);

	PG_RETURN_BOOL(result > 0);
}


Datum
btbpchar_pattern_cmp(PG_FUNCTION_ARGS)
{
	BpChar	   *arg1 = PG_GETARG_BPCHAR_PP(0);
	BpChar	   *arg2 = PG_GETARG_BPCHAR_PP(1);
	int			result;

	result = internal_bpchar_pattern_compare(arg1, arg2);

	PG_FREE_IF_COPY(arg1, 0);
	PG_FREE_IF_COPY(arg2, 1);

	PG_RETURN_INT32(result);
}