|
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 @@ Datumltree_textadd(PG_FUNCTION_ARGS);
|
44 | 51 | Datumlca(PG_FUNCTION_ARGS);
|
45 | 52 | Datumltree2text(PG_FUNCTION_ARGS);
|
46 | 53 | Datumtext2ltree(PG_FUNCTION_ARGS);
|
| 54 | +Datumltreeparentsel(PG_FUNCTION_ARGS); |
47 | 55 |
|
48 | 56 | int
|
49 | 57 | ltree_compare(constltree*a,constltree*b)
|
@@ -551,3 +559,181 @@ ltree2text(PG_FUNCTION_ARGS)
|
551 | 559 |
|
552 | 560 | PG_RETURN_POINTER(out);
|
553 | 561 | }
|
| 562 | + |
| 563 | + |
| 564 | +#defineDEFAULT_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 | +Oidoperator=PG_GETARG_OID(1); |
| 574 | +List*args= (List*)PG_GETARG_POINTER(2); |
| 575 | +intvarRelid=PG_GETARG_INT32(3); |
| 576 | +VariableStatDatavardata; |
| 577 | +Node*other; |
| 578 | +boolvaronleft; |
| 579 | +Datum*values; |
| 580 | +intnvalues; |
| 581 | +float4*numbers; |
| 582 | +intnnumbers; |
| 583 | +doubleselec=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_statisticstats; |
| 607 | +doublemcvsum=0.0; |
| 608 | +doublemcvsel=0.0; |
| 609 | +doublehissel=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 | +Datumconstval= ((Const*)other)->constvalue; |
| 617 | +boolmatch= false; |
| 618 | +inti; |
| 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 | +FmgrInfocontproc; |
| 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 | +FmgrInfocontproc; |
| 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 | +} |