|
1 | 1 | /*
|
2 | 2 | * op function for ltree
|
3 | 3 | * Teodor Sigaev <teodor@stack.net>
|
4 |
| - * $PostgreSQL: pgsql/contrib/ltree/ltree_op.c,v 1.9 2006/03/11 04:38:29 momjian Exp $ |
| 4 | + * $PostgreSQL: pgsql/contrib/ltree/ltree_op.c,v 1.10 2006/04/26 22:32:36 momjian Exp $ |
5 | 5 | */
|
6 | 6 |
|
7 | 7 | #include "ltree.h"
|
8 | 8 | #include <ctype.h>
|
9 | 9 |
|
| 10 | +#include "access/heapam.h" |
| 11 | +#include "catalog/pg_statistic.h" |
| 12 | +#include "nodes/relation.h" |
| 13 | +#include "utils/lsyscache.h" |
| 14 | +#include "utils/selfuncs.h" |
| 15 | +#include "utils/syscache.h" |
| 16 | + |
10 | 17 | /* compare functions */
|
11 | 18 | PG_FUNCTION_INFO_V1(ltree_cmp);
|
12 | 19 | PG_FUNCTION_INFO_V1(ltree_lt);
|
@@ -44,6 +51,7 @@ Datum ltree_textadd(PG_FUNCTION_ARGS);
|
44 | 51 | Datum lca(PG_FUNCTION_ARGS);
|
45 | 52 | Datum ltree2text(PG_FUNCTION_ARGS);
|
46 | 53 | Datum text2ltree(PG_FUNCTION_ARGS);
|
| 54 | +Datum ltreeparentsel(PG_FUNCTION_ARGS); |
47 | 55 |
|
48 | 56 | int
|
49 | 57 | ltree_compare(const ltree * a, const ltree * b)
|
@@ -551,3 +559,181 @@ ltree2text(PG_FUNCTION_ARGS)
|
551 | 559 |
|
552 | 560 | PG_RETURN_POINTER(out);
|
553 | 561 | }
|
| 562 | + |
| 563 | + |
| 564 | +#define DEFAULT_PARENT_SEL 0.001 |
| 565 | + |
| 566 | +/* |
| 567 | + * ltreeparentsel - Selectivity of parent relationship for ltree data types. |
| 568 | + */ |
| 569 | +Datum |
| 570 | +ltreeparentsel(PG_FUNCTION_ARGS) |
| 571 | +{ |
| 572 | + PlannerInfo *root = (PlannerInfo *) PG_GETARG_POINTER(0); |
| 573 | + Oid operator = PG_GETARG_OID(1); |
| 574 | + List *args = (List *) PG_GETARG_POINTER(2); |
| 575 | + int varRelid = PG_GETARG_INT32(3); |
| 576 | + VariableStatData vardata; |
| 577 | + Node *other; |
| 578 | + bool varonleft; |
| 579 | + Datum *values; |
| 580 | + int nvalues; |
| 581 | + float4 *numbers; |
| 582 | + int nnumbers; |
| 583 | + double selec = 0.0; |
| 584 | + |
| 585 | + /* |
| 586 | + * If expression is not variable <@ something or something <@ variable, |
| 587 | + * then punt and return a default estimate. |
| 588 | + */ |
| 589 | + if (!get_restriction_variable(root, args, varRelid, |
| 590 | + &vardata, &other, &varonleft)) |
| 591 | + PG_RETURN_FLOAT8(DEFAULT_PARENT_SEL); |
| 592 | + |
| 593 | + /* |
| 594 | + * If the something is a NULL constant, assume operator is strict and |
| 595 | + * return zero, ie, operator will never return TRUE. |
| 596 | + */ |
| 597 | + if (IsA(other, Const) && |
| 598 | + ((Const *) other)->constisnull) |
| 599 | + { |
| 600 | + ReleaseVariableStats(vardata); |
| 601 | + PG_RETURN_FLOAT8(0.0); |
| 602 | + } |
| 603 | + |
| 604 | + if (HeapTupleIsValid(vardata.statsTuple)) |
| 605 | + { |
| 606 | + Form_pg_statistic stats; |
| 607 | + double mcvsum = 0.0; |
| 608 | + double mcvsel = 0.0; |
| 609 | + double hissel = 0.0; |
| 610 | + |
| 611 | + stats = (Form_pg_statistic) GETSTRUCT(vardata.statsTuple); |
| 612 | + |
| 613 | + if (IsA(other, Const)) |
| 614 | + { |
| 615 | + /* Variable is being compared to a known non-null constant */ |
| 616 | + Datum constval = ((Const *) other)->constvalue; |
| 617 | + bool match = false; |
| 618 | + int i; |
| 619 | + |
| 620 | + /* |
| 621 | + * Is the constant "<@" to any of the column's most common values? |
| 622 | + */ |
| 623 | + if (get_attstatsslot(vardata.statsTuple, |
| 624 | + vardata.atttype, vardata.atttypmod, |
| 625 | + STATISTIC_KIND_MCV, InvalidOid, |
| 626 | + &values, &nvalues, |
| 627 | + &numbers, &nnumbers)) |
| 628 | + { |
| 629 | + FmgrInfo contproc; |
| 630 | + |
| 631 | + fmgr_info(get_opcode(operator), &contproc); |
| 632 | + |
| 633 | + for (i = 0; i < nvalues; i++) |
| 634 | + { |
| 635 | + /* be careful to apply operator right way 'round */ |
| 636 | + if (varonleft) |
| 637 | + match = DatumGetBool(FunctionCall2(&contproc, |
| 638 | + values[i], |
| 639 | + constval)); |
| 640 | + else |
| 641 | + match = DatumGetBool(FunctionCall2(&contproc, |
| 642 | + constval, |
| 643 | + values[i])); |
| 644 | + |
| 645 | + /* calculate total selectivity of all most-common-values */ |
| 646 | + mcvsum += numbers[i]; |
| 647 | + |
| 648 | + /* calculate selectivity of matching most-common-values */ |
| 649 | + if (match) |
| 650 | + mcvsel += numbers[i]; |
| 651 | + } |
| 652 | + } |
| 653 | + else |
| 654 | + { |
| 655 | + /* no most-common-values info available */ |
| 656 | + values = NULL; |
| 657 | + numbers = NULL; |
| 658 | + i = nvalues = nnumbers = 0; |
| 659 | + } |
| 660 | + |
| 661 | + free_attstatsslot(vardata.atttype, values, nvalues, NULL, 0); |
| 662 | + |
| 663 | + /* |
| 664 | + * Is the constant "<@" to any of the column's histogram values? |
| 665 | + */ |
| 666 | + if (get_attstatsslot(vardata.statsTuple, |
| 667 | + vardata.atttype, vardata.atttypmod, |
| 668 | + STATISTIC_KIND_HISTOGRAM, InvalidOid, |
| 669 | + &values, &nvalues, |
| 670 | + NULL, NULL)) |
| 671 | + { |
| 672 | + FmgrInfo contproc; |
| 673 | + |
| 674 | + fmgr_info(get_opcode(operator), &contproc); |
| 675 | + |
| 676 | + for (i = 0; i < nvalues; i++) |
| 677 | + { |
| 678 | + /* be careful to apply operator right way 'round */ |
| 679 | + if (varonleft) |
| 680 | + match = DatumGetBool(FunctionCall2(&contproc, |
| 681 | + values[i], |
| 682 | + constval)); |
| 683 | + else |
| 684 | + match = DatumGetBool(FunctionCall2(&contproc, |
| 685 | + constval, |
| 686 | + values[i])); |
| 687 | + /* count matching histogram values */ |
| 688 | + if (match) |
| 689 | + hissel++; |
| 690 | + } |
| 691 | + |
| 692 | + if (hissel > 0.0) |
| 693 | + { |
| 694 | + /* |
| 695 | + * some matching values found inside histogram, divide |
| 696 | + * matching entries number by total histogram entries to |
| 697 | + * get the histogram related selectivity |
| 698 | + */ |
| 699 | + hissel /= nvalues; |
| 700 | + } |
| 701 | + } |
| 702 | + else |
| 703 | + { |
| 704 | + /* no histogram info available */ |
| 705 | + values = NULL; |
| 706 | + i = nvalues = 0; |
| 707 | + } |
| 708 | + |
| 709 | + free_attstatsslot(vardata.atttype, values, nvalues, |
| 710 | + NULL, 0); |
| 711 | + |
| 712 | + |
| 713 | + /* |
| 714 | + * calculate selectivity based on MCV and histogram result |
| 715 | + * histogram selectivity needs to be scaled down if there are any |
| 716 | + * most-common-values |
| 717 | + */ |
| 718 | + selec = mcvsel + hissel * (1.0 - mcvsum); |
| 719 | + |
| 720 | + /* |
| 721 | + * don't return 0.0 selectivity unless all table values are inside |
| 722 | + * mcv |
| 723 | + */ |
| 724 | + if (selec == 0.0 && mcvsum != 1.0) |
| 725 | + selec = DEFAULT_PARENT_SEL; |
| 726 | + } |
| 727 | + else |
| 728 | + selec = DEFAULT_PARENT_SEL; |
| 729 | + } |
| 730 | + else |
| 731 | + selec = DEFAULT_PARENT_SEL; |
| 732 | + |
| 733 | + ReleaseVariableStats(vardata); |
| 734 | + |
| 735 | + /* result should be in range, but make sure... */ |
| 736 | + CLAMP_PROBABILITY(selec); |
| 737 | + |
| 738 | + PG_RETURN_FLOAT8((float8) selec); |
| 739 | +} |
0 commit comments