|
6 | 6 | #include <limits.h>
|
7 | 7 |
|
8 | 8 | #include "access/stratnum.h"
|
| 9 | +#include "mb/pg_wchar.h" |
9 | 10 | #include "utils/builtins.h"
|
10 | 11 | #include "utils/date.h"
|
11 | 12 | #include "utils/float.h"
|
12 | 13 | #include "utils/inet.h"
|
13 | 14 | #include "utils/numeric.h"
|
14 | 15 | #include "utils/timestamp.h"
|
15 | 16 | #include "utils/uuid.h"
|
| 17 | +#include "varatt.h" |
16 | 18 |
|
17 | 19 | PG_MODULE_MAGIC_EXT(
|
18 | 20 | .name = "btree_gin",
|
@@ -401,27 +403,59 @@ leftmostvalue_float4(void)
|
401 | 403 | return Float4GetDatum(-get_float4_infinity());
|
402 | 404 | }
|
403 | 405 |
|
| 406 | +static Datum |
| 407 | +cvt_float8_float4(Datum input) |
| 408 | +{ |
| 409 | + float8 val = DatumGetFloat8(input); |
| 410 | + float4 result; |
| 411 | + |
| 412 | + /* |
| 413 | + * Assume that ordinary C conversion will produce a usable result. |
| 414 | + * (Compare dtof(), which raises error conditions that we don't need.) |
| 415 | + * Note that for inputs that aren't exactly representable as float4, it |
| 416 | + * doesn't matter whether the conversion rounds up or down. That might |
| 417 | + * cause us to scan a few index entries that we'll reject as not matching, |
| 418 | + * but we won't miss any that should match. |
| 419 | + */ |
| 420 | + result = (float4) val; |
| 421 | + return Float4GetDatum(result); |
| 422 | +} |
| 423 | + |
404 | 424 | static const bool float4_rhs_is_varlena[] =
|
405 |
| -{false}; |
| 425 | +{false, false}; |
| 426 | + |
| 427 | +static const btree_gin_convert_function float4_cvt_fns[] = |
| 428 | +{NULL, cvt_float8_float4}; |
406 | 429 |
|
407 | 430 | static const PGFunction float4_cmp_fns[] =
|
408 |
| -{btfloat4cmp}; |
| 431 | +{btfloat4cmp, btfloat84cmp}; |
409 | 432 |
|
410 |
| -GIN_SUPPORT(float4, leftmostvalue_float4, float4_rhs_is_varlena, NULL, float4_cmp_fns) |
| 433 | +GIN_SUPPORT(float4, leftmostvalue_float4, float4_rhs_is_varlena, float4_cvt_fns, float4_cmp_fns) |
411 | 434 |
|
412 | 435 | static Datum
|
413 | 436 | leftmostvalue_float8(void)
|
414 | 437 | {
|
415 | 438 | return Float8GetDatum(-get_float8_infinity());
|
416 | 439 | }
|
417 | 440 |
|
| 441 | +static Datum |
| 442 | +cvt_float4_float8(Datum input) |
| 443 | +{ |
| 444 | + float4 val = DatumGetFloat4(input); |
| 445 | + |
| 446 | + return Float8GetDatum((float8) val); |
| 447 | +} |
| 448 | + |
418 | 449 | static const bool float8_rhs_is_varlena[] =
|
419 |
| -{false}; |
| 450 | +{false, false}; |
| 451 | + |
| 452 | +static const btree_gin_convert_function float8_cvt_fns[] = |
| 453 | +{NULL, cvt_float4_float8}; |
420 | 454 |
|
421 | 455 | static const PGFunction float8_cmp_fns[] =
|
422 |
| -{btfloat8cmp}; |
| 456 | +{btfloat8cmp, btfloat48cmp}; |
423 | 457 |
|
424 |
| -GIN_SUPPORT(float8, leftmostvalue_float8, float8_rhs_is_varlena, NULL, float8_cmp_fns) |
| 458 | +GIN_SUPPORT(float8, leftmostvalue_float8, float8_rhs_is_varlena, float8_cvt_fns, float8_cmp_fns) |
425 | 459 |
|
426 | 460 | static Datum
|
427 | 461 | leftmostvalue_money(void)
|
@@ -457,21 +491,75 @@ leftmostvalue_timestamp(void)
|
457 | 491 | return TimestampGetDatum(DT_NOBEGIN);
|
458 | 492 | }
|
459 | 493 |
|
| 494 | +static Datum |
| 495 | +cvt_date_timestamp(Datum input) |
| 496 | +{ |
| 497 | + DateADT val = DatumGetDateADT(input); |
| 498 | + Timestamp result; |
| 499 | + int overflow; |
| 500 | + |
| 501 | + result = date2timestamp_opt_overflow(val, &overflow); |
| 502 | + /* We can ignore the overflow result, since result is useful as-is */ |
| 503 | + return TimestampGetDatum(result); |
| 504 | +} |
| 505 | + |
| 506 | +static Datum |
| 507 | +cvt_timestamptz_timestamp(Datum input) |
| 508 | +{ |
| 509 | + TimestampTz val = DatumGetTimestampTz(input); |
| 510 | + Timestamp result; |
| 511 | + int overflow; |
| 512 | + |
| 513 | + result = timestamptz2timestamp_opt_overflow(val, &overflow); |
| 514 | + /* We can ignore the overflow result, since result is useful as-is */ |
| 515 | + return TimestampGetDatum(result); |
| 516 | +} |
| 517 | + |
460 | 518 | static const bool timestamp_rhs_is_varlena[] =
|
461 |
| -{false}; |
| 519 | +{false, false, false}; |
| 520 | + |
| 521 | +static const btree_gin_convert_function timestamp_cvt_fns[] = |
| 522 | +{NULL, cvt_date_timestamp, cvt_timestamptz_timestamp}; |
462 | 523 |
|
463 | 524 | static const PGFunction timestamp_cmp_fns[] =
|
464 |
| -{timestamp_cmp}; |
| 525 | +{timestamp_cmp, date_cmp_timestamp, timestamptz_cmp_timestamp}; |
465 | 526 |
|
466 |
| -GIN_SUPPORT(timestamp, leftmostvalue_timestamp, timestamp_rhs_is_varlena, NULL, timestamp_cmp_fns) |
| 527 | +GIN_SUPPORT(timestamp, leftmostvalue_timestamp, timestamp_rhs_is_varlena, timestamp_cvt_fns, timestamp_cmp_fns) |
| 528 | + |
| 529 | +static Datum |
| 530 | +cvt_date_timestamptz(Datum input) |
| 531 | +{ |
| 532 | + DateADT val = DatumGetDateADT(input); |
| 533 | + TimestampTz result; |
| 534 | + int overflow; |
| 535 | + |
| 536 | + result = date2timestamptz_opt_overflow(val, &overflow); |
| 537 | + /* We can ignore the overflow result, since result is useful as-is */ |
| 538 | + return TimestampTzGetDatum(result); |
| 539 | +} |
| 540 | + |
| 541 | +static Datum |
| 542 | +cvt_timestamp_timestamptz(Datum input) |
| 543 | +{ |
| 544 | + Timestamp val = DatumGetTimestamp(input); |
| 545 | + TimestampTz result; |
| 546 | + int overflow; |
| 547 | + |
| 548 | + result = timestamp2timestamptz_opt_overflow(val, &overflow); |
| 549 | + /* We can ignore the overflow result, since result is useful as-is */ |
| 550 | + return TimestampTzGetDatum(result); |
| 551 | +} |
467 | 552 |
|
468 | 553 | static const bool timestamptz_rhs_is_varlena[] =
|
469 |
| -{false}; |
| 554 | +{false, false, false}; |
| 555 | + |
| 556 | +static const btree_gin_convert_function timestamptz_cvt_fns[] = |
| 557 | +{NULL, cvt_date_timestamptz, cvt_timestamp_timestamptz}; |
470 | 558 |
|
471 | 559 | static const PGFunction timestamptz_cmp_fns[] =
|
472 |
| -{timestamp_cmp}; |
| 560 | +{timestamp_cmp, date_cmp_timestamptz, timestamp_cmp_timestamptz}; |
473 | 561 |
|
474 |
| -GIN_SUPPORT(timestamptz, leftmostvalue_timestamp, timestamptz_rhs_is_varlena, NULL, timestamptz_cmp_fns) |
| 562 | +GIN_SUPPORT(timestamptz, leftmostvalue_timestamp, timestamptz_rhs_is_varlena, timestamptz_cvt_fns, timestamptz_cmp_fns) |
475 | 563 |
|
476 | 564 | static Datum
|
477 | 565 | leftmostvalue_time(void)
|
@@ -512,13 +600,40 @@ leftmostvalue_date(void)
|
512 | 600 | return DateADTGetDatum(DATEVAL_NOBEGIN);
|
513 | 601 | }
|
514 | 602 |
|
| 603 | +static Datum |
| 604 | +cvt_timestamp_date(Datum input) |
| 605 | +{ |
| 606 | + Timestamp val = DatumGetTimestamp(input); |
| 607 | + DateADT result; |
| 608 | + int overflow; |
| 609 | + |
| 610 | + result = timestamp2date_opt_overflow(val, &overflow); |
| 611 | + /* We can ignore the overflow result, since result is useful as-is */ |
| 612 | + return DateADTGetDatum(result); |
| 613 | +} |
| 614 | + |
| 615 | +static Datum |
| 616 | +cvt_timestamptz_date(Datum input) |
| 617 | +{ |
| 618 | + TimestampTz val = DatumGetTimestampTz(input); |
| 619 | + DateADT result; |
| 620 | + int overflow; |
| 621 | + |
| 622 | + result = timestamptz2date_opt_overflow(val, &overflow); |
| 623 | + /* We can ignore the overflow result, since result is useful as-is */ |
| 624 | + return DateADTGetDatum(result); |
| 625 | +} |
| 626 | + |
515 | 627 | static const bool date_rhs_is_varlena[] =
|
516 |
| -{false}; |
| 628 | +{false, false, false}; |
| 629 | + |
| 630 | +static const btree_gin_convert_function date_cvt_fns[] = |
| 631 | +{NULL, cvt_timestamp_date, cvt_timestamptz_date}; |
517 | 632 |
|
518 | 633 | static const PGFunction date_cmp_fns[] =
|
519 |
| -{date_cmp}; |
| 634 | +{date_cmp, timestamp_cmp_date, timestamptz_cmp_date}; |
520 | 635 |
|
521 |
| -GIN_SUPPORT(date, leftmostvalue_date, date_rhs_is_varlena, NULL, date_cmp_fns) |
| 636 | +GIN_SUPPORT(date, leftmostvalue_date, date_rhs_is_varlena, date_cvt_fns, date_cmp_fns) |
522 | 637 |
|
523 | 638 | static Datum
|
524 | 639 | leftmostvalue_interval(void)
|
@@ -598,13 +713,24 @@ leftmostvalue_text(void)
|
598 | 713 | return PointerGetDatum(cstring_to_text_with_len("", 0));
|
599 | 714 | }
|
600 | 715 |
|
| 716 | +static Datum |
| 717 | +cvt_name_text(Datum input) |
| 718 | +{ |
| 719 | + Name val = DatumGetName(input); |
| 720 | + |
| 721 | + return PointerGetDatum(cstring_to_text(NameStr(*val))); |
| 722 | +} |
| 723 | + |
601 | 724 | static const bool text_rhs_is_varlena[] =
|
602 |
| -{true}; |
| 725 | +{true, false}; |
| 726 | + |
| 727 | +static const btree_gin_convert_function text_cvt_fns[] = |
| 728 | +{NULL, cvt_name_text}; |
603 | 729 |
|
604 | 730 | static const PGFunction text_cmp_fns[] =
|
605 |
| -{bttextcmp}; |
| 731 | +{bttextcmp, btnametextcmp}; |
606 | 732 |
|
607 |
| -GIN_SUPPORT(text, leftmostvalue_text, text_rhs_is_varlena, NULL, text_cmp_fns) |
| 733 | +GIN_SUPPORT(text, leftmostvalue_text, text_rhs_is_varlena, text_cvt_fns, text_cmp_fns) |
608 | 734 |
|
609 | 735 | static const bool bpchar_rhs_is_varlena[] =
|
610 | 736 | {true};
|
@@ -804,13 +930,37 @@ leftmostvalue_name(void)
|
804 | 930 | return NameGetDatum(result);
|
805 | 931 | }
|
806 | 932 |
|
| 933 | +static Datum |
| 934 | +cvt_text_name(Datum input) |
| 935 | +{ |
| 936 | + text *val = DatumGetTextPP(input); |
| 937 | + NameData *result = (NameData *) palloc0(NAMEDATALEN); |
| 938 | + int len = VARSIZE_ANY_EXHDR(val); |
| 939 | + |
| 940 | + /* |
| 941 | + * Truncate oversize input. We're assuming this will produce a result |
| 942 | + * considered less than the original. That could be a bad assumption in |
| 943 | + * some collations, but fortunately an index on "name" is generally going |
| 944 | + * to use C collation. |
| 945 | + */ |
| 946 | + if (len >= NAMEDATALEN) |
| 947 | + len = pg_mbcliplen(VARDATA_ANY(val), len, NAMEDATALEN - 1); |
| 948 | + |
| 949 | + memcpy(NameStr(*result), VARDATA_ANY(val), len); |
| 950 | + |
| 951 | + return NameGetDatum(result); |
| 952 | +} |
| 953 | + |
807 | 954 | static const bool name_rhs_is_varlena[] =
|
808 |
| -{false}; |
| 955 | +{false, true}; |
| 956 | + |
| 957 | +static const btree_gin_convert_function name_cvt_fns[] = |
| 958 | +{NULL, cvt_text_name}; |
809 | 959 |
|
810 | 960 | static const PGFunction name_cmp_fns[] =
|
811 |
| -{btnamecmp}; |
| 961 | +{btnamecmp, bttextnamecmp}; |
812 | 962 |
|
813 |
| -GIN_SUPPORT(name, leftmostvalue_name, name_rhs_is_varlena, NULL, name_cmp_fns) |
| 963 | +GIN_SUPPORT(name, leftmostvalue_name, name_rhs_is_varlena, name_cvt_fns, name_cmp_fns) |
814 | 964 |
|
815 | 965 | static Datum
|
816 | 966 | leftmostvalue_bool(void)
|
|
0 commit comments