PostgreSQL Source Code git master
Loading...
Searching...
No Matches
network_selfuncs.c File Reference
#include "postgres.h"
#include <math.h>
#include "access/htup_details.h"
#include "catalog/pg_operator.h"
#include "catalog/pg_statistic.h"
#include "utils/fmgrprotos.h"
#include "utils/inet.h"
#include "utils/lsyscache.h"
#include "utils/selfuncs.h"
Include dependency graph for network_selfuncs.c:

Go to the source code of this file.

Macros

#define DEFAULT_OVERLAP_SEL   0.01
 
#define DEFAULT_INCLUSION_SEL   0.005
 
#define DEFAULT_SEL(operator)
 
#define MAX_CONSIDERED_ELEMS   1024
 

Functions

static Selectivity networkjoinsel_inner (Oid operator, int opr_codenum, VariableStatData *vardata1, VariableStatData *vardata2)
 
static Selectivity networkjoinsel_semi (Oid operator, int opr_codenum, VariableStatData *vardata1, VariableStatData *vardata2)
 
static Selectivity mcv_population (float4 *mcv_numbers, int mcv_nvalues)
 
static Selectivity inet_hist_value_sel (const Datum *values, int nvalues, Datum constvalue, int opr_codenum)
 
static Selectivity inet_mcv_join_sel (Datum *mcv1_values, float4 *mcv1_numbers, int mcv1_nvalues, Datum *mcv2_values, float4 *mcv2_numbers, int mcv2_nvalues, Oid operator)
 
static Selectivity inet_mcv_hist_sel (const Datum *mcv_values, float4 *mcv_numbers, int mcv_nvalues, const Datum *hist_values, int hist_nvalues, int opr_codenum)
 
static Selectivity inet_hist_inclusion_join_sel (const Datum *hist1_values, int hist1_nvalues, const Datum *hist2_values, int hist2_nvalues, int opr_codenum)
 
static Selectivity inet_semi_join_sel (Datum lhs_value, bool mcv_exists, Datum *mcv_values, int mcv_nvalues, bool hist_exists, Datum *hist_values, int hist_nvalues, double hist_weight, FmgrInfo *proc, int opr_codenum)
 
static int inet_opr_codenum (Oid operator)
 
static int inet_inclusion_cmp (inet *left, inet *right, int opr_codenum)
 
static int inet_masklen_inclusion_cmp (inet *left, inet *right, int opr_codenum)
 
static int inet_hist_match_divider (inet *boundary, inet *query, int opr_codenum)
 
Datum networksel (PG_FUNCTION_ARGS)
 
Datum networkjoinsel (PG_FUNCTION_ARGS)
 

Macro Definition Documentation

◆ DEFAULT_INCLUSION_SEL

#define DEFAULT_INCLUSION_SEL   0.005

Definition at line 36 of file network_selfuncs.c.

◆ DEFAULT_OVERLAP_SEL

#define DEFAULT_OVERLAP_SEL   0.01

Definition at line 33 of file network_selfuncs.c.

◆ DEFAULT_SEL

#define DEFAULT_SEL (   operator)
Value:
((operator) == OID_INET_OVERLAP_OP ? \
#define DEFAULT_OVERLAP_SEL
#define DEFAULT_INCLUSION_SEL
static int fb(int x)

Definition at line 39 of file network_selfuncs.c.

◆ MAX_CONSIDERED_ELEMS

#define MAX_CONSIDERED_ELEMS   1024

Definition at line 44 of file network_selfuncs.c.

Function Documentation

◆ inet_hist_inclusion_join_sel()

static Selectivity inet_hist_inclusion_join_sel ( const Datum hist1_values,
int  hist1_nvalues,
const Datum hist2_values,
int  hist2_nvalues,
int  opr_codenum 
)
static

Definition at line 757 of file network_selfuncs.c.

760{
761 double match = 0.0;
762 int i,
763 k,
764 n;
765
766 if (hist2_nvalues <= 2)
767 return 0.0; /* no interior histogram elements */
768
769 /* if there are too many histogram elements, decimate to limit runtime */
770 k = (hist2_nvalues - 3) / MAX_CONSIDERED_ELEMS + 1;
771
772 n = 0;
773 for (i = 1; i < hist2_nvalues - 1; i += k)
774 {
777 n++;
778 }
779
780 return match / n;
781}
int i
Definition isn.c:77
#define MAX_CONSIDERED_ELEMS
static Selectivity inet_hist_value_sel(const Datum *values, int nvalues, Datum constvalue, int opr_codenum)

References fb(), i, inet_hist_value_sel(), and MAX_CONSIDERED_ELEMS.

Referenced by networkjoinsel_inner().

◆ inet_hist_match_divider()

static int inet_hist_match_divider ( inet boundary,
inet query,
int  opr_codenum 
)
static

Definition at line 957 of file network_selfuncs.c.

958{
959 if (ip_family(boundary) == ip_family(query) &&
960 inet_masklen_inclusion_cmp(boundary, query, opr_codenum) == 0)
961 {
962 int min_bits,
964
965 min_bits = Min(ip_bits(boundary), ip_bits(query));
966
967 /*
968 * Set decisive_bits to the masklen of the one that should contain the
969 * other according to the operator.
970 */
971 if (opr_codenum < 0)
972 decisive_bits = ip_bits(boundary);
973 else if (opr_codenum > 0)
974 decisive_bits = ip_bits(query);
975 else
977
978 /*
979 * Now return the number of non-common decisive bits. (This will be
980 * zero if the boundary and query in fact match, else positive.)
981 */
982 if (min_bits > 0)
983 return decisive_bits - bitncommon(ip_addr(boundary),
984 ip_addr(query),
985 min_bits);
986 return decisive_bits;
987 }
988
989 return -1;
990}
#define Min(x, y)
Definition c.h:997
int bitncommon(const unsigned char *l, const unsigned char *r, int n)
Definition network.c:1536
static int inet_masklen_inclusion_cmp(inet *left, inet *right, int opr_codenum)
#define ip_addr(inetptr)
Definition inet.h:77
#define ip_family(inetptr)
Definition inet.h:71
#define ip_bits(inetptr)
Definition inet.h:74

References bitncommon(), fb(), inet_masklen_inclusion_cmp(), ip_addr, ip_bits, ip_family, and Min.

Referenced by inet_hist_value_sel().

◆ inet_hist_value_sel()

static Selectivity inet_hist_value_sel ( const Datum values,
int  nvalues,
Datum  constvalue,
int  opr_codenum 
)
static

Definition at line 619 of file network_selfuncs.c.

621{
622 Selectivity match = 0.0;
623 inet *query,
624 *left,
625 *right;
626 int i,
627 k,
628 n;
629 int left_order,
633
634 /* guard against zero-divide below */
635 if (nvalues <= 1)
636 return 0.0;
637
638 /* if there are too many histogram elements, decimate to limit runtime */
639 k = (nvalues - 2) / MAX_CONSIDERED_ELEMS + 1;
640
641 query = DatumGetInetPP(constvalue);
642
643 /* "left" is the left boundary value of the current bucket ... */
644 left = DatumGetInetPP(values[0]);
646
647 n = 0;
648 for (i = k; i < nvalues; i += k)
649 {
650 /* ... and "right" is the right boundary value */
651 right = DatumGetInetPP(values[i]);
653
654 if (left_order == 0 && right_order == 0)
655 {
656 /* The whole bucket matches, since both endpoints do. */
657 match += 1.0;
658 }
659 else if ((left_order <= 0 && right_order >= 0) ||
660 (left_order >= 0 && right_order <= 0))
661 {
662 /* Partial bucket match. */
665
666 if (left_divider >= 0 || right_divider >= 0)
667 match += 1.0 / pow(2.0, Max(left_divider, right_divider));
668 }
669
670 /* Shift the variables. */
671 left = right;
673
674 /* Count the number of buckets considered. */
675 n++;
676 }
677
678 return match / n;
679}
static Datum values[MAXATTR]
Definition bootstrap.c:155
#define Max(x, y)
Definition c.h:991
static int inet_inclusion_cmp(inet *left, inet *right, int opr_codenum)
static int inet_hist_match_divider(inet *boundary, inet *query, int opr_codenum)
double Selectivity
Definition nodes.h:260
Definition inet.h:53
static inet * DatumGetInetPP(Datum X)
Definition inet.h:123

References DatumGetInetPP(), fb(), i, inet_hist_match_divider(), inet_inclusion_cmp(), Max, MAX_CONSIDERED_ELEMS, and values.

Referenced by inet_hist_inclusion_join_sel(), inet_mcv_hist_sel(), inet_semi_join_sel(), and networksel().

◆ inet_inclusion_cmp()

static int inet_inclusion_cmp ( inet left,
inet right,
int  opr_codenum 
)
static

Definition at line 897 of file network_selfuncs.c.

898{
899 if (ip_family(left) == ip_family(right))
900 {
901 int order;
902
903 order = bitncmp(ip_addr(left), ip_addr(right),
904 Min(ip_bits(left), ip_bits(right)));
905 if (order != 0)
906 return order;
907
908 return inet_masklen_inclusion_cmp(left, right, opr_codenum);
909 }
910
911 return ip_family(left) - ip_family(right);
912}
int bitncmp(const unsigned char *l, const unsigned char *r, int n)
Definition network.c:1502

References bitncmp(), fb(), inet_masklen_inclusion_cmp(), ip_addr, ip_bits, ip_family, and Min.

Referenced by inet_hist_value_sel().

◆ inet_masklen_inclusion_cmp()

static int inet_masklen_inclusion_cmp ( inet left,
inet right,
int  opr_codenum 
)
static

Definition at line 923 of file network_selfuncs.c.

924{
925 int order;
926
927 order = (int) ip_bits(left) - (int) ip_bits(right);
928
929 /*
930 * Return 0 if the operator would accept this combination of masklens.
931 * Note that opr_codenum zero (overlaps) will accept all cases.
932 */
933 if ((order > 0 && opr_codenum >= 0) ||
934 (order == 0 && opr_codenum >= -1 && opr_codenum <= 1) ||
935 (order < 0 && opr_codenum <= 0))
936 return 0;
937
938 /*
939 * Otherwise, return a negative value for sup/supeq (notionally, the RHS
940 * needs to have a larger masklen than it has, which would make it sort
941 * later), or a positive value for sub/subeq (vice versa).
942 */
943 return opr_codenum;
944}

References fb(), and ip_bits.

Referenced by inet_hist_match_divider(), and inet_inclusion_cmp().

◆ inet_mcv_hist_sel()

static Selectivity inet_mcv_hist_sel ( const Datum mcv_values,
float4 mcv_numbers,
int  mcv_nvalues,
const Datum hist_values,
int  hist_nvalues,
int  opr_codenum 
)
static

Definition at line 720 of file network_selfuncs.c.

723{
724 Selectivity selec = 0.0;
725 int i;
726
727 /*
728 * We'll call inet_hist_value_selec with the histogram on the left, so we
729 * must commute the operator.
730 */
732
733 for (i = 0; i < mcv_nvalues; i++)
734 {
735 selec += mcv_numbers[i] *
738 }
739 return selec;
740}

References fb(), i, and inet_hist_value_sel().

Referenced by networkjoinsel_inner().

◆ inet_mcv_join_sel()

static Selectivity inet_mcv_join_sel ( Datum mcv1_values,
float4 mcv1_numbers,
int  mcv1_nvalues,
Datum mcv2_values,
float4 mcv2_numbers,
int  mcv2_nvalues,
Oid  operator 
)
static

Definition at line 688 of file network_selfuncs.c.

691{
692 Selectivity selec = 0.0;
693 FmgrInfo proc;
694 int i,
695 j;
696
697 fmgr_info(get_opcode(operator), &proc);
698
699 for (i = 0; i < mcv1_nvalues; i++)
700 {
701 for (j = 0; j < mcv2_nvalues; j++)
702 if (DatumGetBool(FunctionCall2(&proc,
703 mcv1_values[i],
704 mcv2_values[j])))
706 }
707 return selec;
708}
void fmgr_info(Oid functionId, FmgrInfo *finfo)
Definition fmgr.c:128
#define FunctionCall2(flinfo, arg1, arg2)
Definition fmgr.h:704
int j
Definition isn.c:78
RegProcedure get_opcode(Oid opno)
Definition lsyscache.c:1435
static bool DatumGetBool(Datum X)
Definition postgres.h:100

References DatumGetBool(), fb(), fmgr_info(), FunctionCall2, get_opcode(), i, and j.

Referenced by networkjoinsel_inner().

◆ inet_opr_codenum()

static int inet_opr_codenum ( Oid  operator)
static

Definition at line 854 of file network_selfuncs.c.

855{
856 switch (operator)
857 {
858 case OID_INET_SUP_OP:
859 return -2;
861 return -1;
863 return 0;
865 return 1;
866 case OID_INET_SUB_OP:
867 return 2;
868 default:
869 elog(ERROR, "unrecognized operator %u for inet selectivity",
870 operator);
871 }
872 return 0; /* unreached, but keep compiler quiet */
873}
#define ERROR
Definition elog.h:39
#define elog(elevel,...)
Definition elog.h:226

References elog, ERROR, and fb().

Referenced by networkjoinsel(), and networksel().

◆ inet_semi_join_sel()

static Selectivity inet_semi_join_sel ( Datum  lhs_value,
bool  mcv_exists,
Datum mcv_values,
int  mcv_nvalues,
bool  hist_exists,
Datum hist_values,
int  hist_nvalues,
double  hist_weight,
FmgrInfo proc,
int  opr_codenum 
)
static

Definition at line 808 of file network_selfuncs.c.

813{
814 if (mcv_exists)
815 {
816 int i;
817
818 for (i = 0; i < mcv_nvalues; i++)
819 {
821 lhs_value,
822 mcv_values[i])))
823 return 1.0;
824 }
825 }
826
827 if (hist_exists && hist_weight > 0)
828 {
830
831 /* Commute operator, since we're passing lhs_value on the right */
834
835 if (hist_selec > 0)
836 return Min(1.0, hist_weight * hist_selec);
837 }
838
839 return 0.0;
840}

References DatumGetBool(), fb(), FunctionCall2, i, inet_hist_value_sel(), and Min.

Referenced by networkjoinsel_semi().

◆ mcv_population()

static Selectivity mcv_population ( float4 mcv_numbers,
int  mcv_nvalues 
)
static

Definition at line 554 of file network_selfuncs.c.

555{
557 int i;
558
559 for (i = 0; i < mcv_nvalues; i++)
560 {
562 }
563
564 return sumcommon;
565}

References fb(), and i.

Referenced by networkjoinsel_inner(), and networkjoinsel_semi().

◆ networkjoinsel()

Datum networkjoinsel ( PG_FUNCTION_ARGS  )

Definition at line 204 of file network_selfuncs.c.

205{
207 Oid operator = PG_GETARG_OID(1);
209#ifdef NOT_USED
210 JoinType jointype = (JoinType) PG_GETARG_INT16(3);
211#endif
213 double selec;
214 int opr_codenum;
217 bool join_is_reversed;
218
219 /*
220 * Before all else, verify that the operator is one of the ones supported
221 * by this function, which in turn proves that the input datatypes are
222 * what we expect. Otherwise, attaching this selectivity function to some
223 * unexpected operator could cause trouble.
224 */
225 opr_codenum = inet_opr_codenum(operator);
226
227 get_join_variables(root, args, sjinfo,
229
230 switch (sjinfo->jointype)
231 {
232 case JOIN_INNER:
233 case JOIN_LEFT:
234 case JOIN_FULL:
235
236 /*
237 * Selectivity for left/full join is not exactly the same as inner
238 * join, but we neglect the difference, as eqjoinsel does.
239 */
241 &vardata1, &vardata2);
242 break;
243 case JOIN_SEMI:
244 case JOIN_ANTI:
245 /* Here, it's important that we pass the outer var on the left. */
246 if (!join_is_reversed)
248 &vardata1, &vardata2);
249 else
252 &vardata2, &vardata1);
253 break;
254 default:
255 /* other values not expected here */
256 elog(ERROR, "unrecognized join type: %d",
257 (int) sjinfo->jointype);
258 selec = 0; /* keep compiler quiet */
259 break;
260 }
261
264
266
268}
double float8
Definition c.h:644
#define PG_GETARG_OID(n)
Definition fmgr.h:275
#define PG_RETURN_FLOAT8(x)
Definition fmgr.h:369
#define PG_GETARG_POINTER(n)
Definition fmgr.h:277
#define PG_GETARG_INT16(n)
Definition fmgr.h:271
Oid get_commutator(Oid opno)
Definition lsyscache.c:1659
static int inet_opr_codenum(Oid operator)
static Selectivity networkjoinsel_inner(Oid operator, int opr_codenum, VariableStatData *vardata1, VariableStatData *vardata2)
static Selectivity networkjoinsel_semi(Oid operator, int opr_codenum, VariableStatData *vardata1, VariableStatData *vardata2)
JoinType
Definition nodes.h:298
@ JOIN_SEMI
Definition nodes.h:317
@ JOIN_FULL
Definition nodes.h:305
@ JOIN_INNER
Definition nodes.h:303
@ JOIN_LEFT
Definition nodes.h:304
@ JOIN_ANTI
Definition nodes.h:318
unsigned int Oid
tree ctl root
Definition radixtree.h:1857
void get_join_variables(PlannerInfo *root, List *args, SpecialJoinInfo *sjinfo, VariableStatData *vardata1, VariableStatData *vardata2, bool *join_is_reversed)
Definition selfuncs.c:5567
#define ReleaseVariableStats(vardata)
Definition selfuncs.h:101
#define CLAMP_PROBABILITY(p)
Definition selfuncs.h:63
Definition pg_list.h:54
JoinType jointype
Definition pathnodes.h:3215

References CLAMP_PROBABILITY, elog, ERROR, fb(), get_commutator(), get_join_variables(), inet_opr_codenum(), JOIN_ANTI, JOIN_FULL, JOIN_INNER, JOIN_LEFT, JOIN_SEMI, SpecialJoinInfo::jointype, networkjoinsel_inner(), networkjoinsel_semi(), PG_GETARG_INT16, PG_GETARG_OID, PG_GETARG_POINTER, PG_RETURN_FLOAT8, ReleaseVariableStats, and root.

◆ networkjoinsel_inner()

static Selectivity networkjoinsel_inner ( Oid  operator,
int  opr_codenum,
VariableStatData vardata1,
VariableStatData vardata2 
)
static

Definition at line 283 of file network_selfuncs.c.

285{
286 Form_pg_statistic stats;
287 double nullfrac1 = 0.0,
288 nullfrac2 = 0.0;
289 Selectivity selec = 0.0,
290 sumcommon1 = 0.0,
291 sumcommon2 = 0.0;
292 bool mcv1_exists = false,
293 mcv2_exists = false,
294 hist1_exists = false,
295 hist2_exists = false;
296 int mcv1_length = 0,
297 mcv2_length = 0;
302
303 if (HeapTupleIsValid(vardata1->statsTuple))
304 {
305 stats = (Form_pg_statistic) GETSTRUCT(vardata1->statsTuple);
306 nullfrac1 = stats->stanullfrac;
307
314 /* Arbitrarily limit number of MCVs considered */
316 if (mcv1_exists)
318 }
319 else
320 {
321 memset(&mcv1_slot, 0, sizeof(mcv1_slot));
322 memset(&hist1_slot, 0, sizeof(hist1_slot));
323 }
324
325 if (HeapTupleIsValid(vardata2->statsTuple))
326 {
327 stats = (Form_pg_statistic) GETSTRUCT(vardata2->statsTuple);
328 nullfrac2 = stats->stanullfrac;
329
336 /* Arbitrarily limit number of MCVs considered */
338 if (mcv2_exists)
340 }
341 else
342 {
343 memset(&mcv2_slot, 0, sizeof(mcv2_slot));
344 memset(&hist2_slot, 0, sizeof(hist2_slot));
345 }
346
347 /*
348 * Calculate selectivity for MCV vs MCV matches.
349 */
351 selec += inet_mcv_join_sel(mcv1_slot.values, mcv1_slot.numbers,
353 mcv2_slot.values, mcv2_slot.numbers,
355 operator);
356
357 /*
358 * Add in selectivities for MCV vs histogram matches, scaling according to
359 * the fractions of the populations represented by the histograms. Note
360 * that the second case needs to commute the operator.
361 */
363 selec += (1.0 - nullfrac2 - sumcommon2) *
365 hist2_slot.values, hist2_slot.nvalues,
368 selec += (1.0 - nullfrac1 - sumcommon1) *
370 hist1_slot.values, hist1_slot.nvalues,
371 -opr_codenum);
372
373 /*
374 * Add in selectivity for histogram vs histogram matches, again scaling
375 * appropriately.
376 */
378 selec += (1.0 - nullfrac1 - sumcommon1) *
379 (1.0 - nullfrac2 - sumcommon2) *
381 hist2_slot.values, hist2_slot.nvalues,
383
384 /*
385 * If useful statistics are not available then use the default estimate.
386 * We can apply null fractions if known, though.
387 */
389 selec = (1.0 - nullfrac1) * (1.0 - nullfrac2) * DEFAULT_SEL(operator);
390
391 /* Release stats. */
396
397 return selec;
398}
#define HeapTupleIsValid(tuple)
Definition htup.h:78
static void * GETSTRUCT(const HeapTupleData *tuple)
void free_attstatsslot(AttStatsSlot *sslot)
Definition lsyscache.c:3494
bool get_attstatsslot(AttStatsSlot *sslot, HeapTuple statstuple, int reqkind, Oid reqop, int flags)
Definition lsyscache.c:3384
#define ATTSTATSSLOT_NUMBERS
Definition lsyscache.h:44
#define ATTSTATSSLOT_VALUES
Definition lsyscache.h:43
static Selectivity mcv_population(float4 *mcv_numbers, int mcv_nvalues)
static Selectivity inet_mcv_join_sel(Datum *mcv1_values, float4 *mcv1_numbers, int mcv1_nvalues, Datum *mcv2_values, float4 *mcv2_numbers, int mcv2_nvalues, Oid operator)
static Selectivity inet_hist_inclusion_join_sel(const Datum *hist1_values, int hist1_nvalues, const Datum *hist2_values, int hist2_nvalues, int opr_codenum)
static Selectivity inet_mcv_hist_sel(const Datum *mcv_values, float4 *mcv_numbers, int mcv_nvalues, const Datum *hist_values, int hist_nvalues, int opr_codenum)
#define DEFAULT_SEL(operator)
FormData_pg_statistic * Form_pg_statistic
#define InvalidOid

References ATTSTATSSLOT_NUMBERS, ATTSTATSSLOT_VALUES, DEFAULT_SEL, fb(), free_attstatsslot(), get_attstatsslot(), GETSTRUCT(), HeapTupleIsValid, inet_hist_inclusion_join_sel(), inet_mcv_hist_sel(), inet_mcv_join_sel(), InvalidOid, MAX_CONSIDERED_ELEMS, mcv_population(), and Min.

Referenced by networkjoinsel().

◆ networkjoinsel_semi()

static Selectivity networkjoinsel_semi ( Oid  operator,
int  opr_codenum,
VariableStatData vardata1,
VariableStatData vardata2 
)
static

Definition at line 407 of file network_selfuncs.c.

409{
410 Form_pg_statistic stats;
411 Selectivity selec = 0.0,
412 sumcommon1 = 0.0,
413 sumcommon2 = 0.0;
414 double nullfrac1 = 0.0,
415 nullfrac2 = 0.0,
416 hist2_weight = 0.0;
417 bool mcv1_exists = false,
418 mcv2_exists = false,
419 hist1_exists = false,
420 hist2_exists = false;
421 FmgrInfo proc;
422 int i,
423 mcv1_length = 0,
424 mcv2_length = 0;
429
430 if (HeapTupleIsValid(vardata1->statsTuple))
431 {
432 stats = (Form_pg_statistic) GETSTRUCT(vardata1->statsTuple);
433 nullfrac1 = stats->stanullfrac;
434
441 /* Arbitrarily limit number of MCVs considered */
443 if (mcv1_exists)
445 }
446 else
447 {
448 memset(&mcv1_slot, 0, sizeof(mcv1_slot));
449 memset(&hist1_slot, 0, sizeof(hist1_slot));
450 }
451
452 if (HeapTupleIsValid(vardata2->statsTuple))
453 {
454 stats = (Form_pg_statistic) GETSTRUCT(vardata2->statsTuple);
455 nullfrac2 = stats->stanullfrac;
456
463 /* Arbitrarily limit number of MCVs considered */
465 if (mcv2_exists)
467 }
468 else
469 {
470 memset(&mcv2_slot, 0, sizeof(mcv2_slot));
471 memset(&hist2_slot, 0, sizeof(hist2_slot));
472 }
473
474 fmgr_info(get_opcode(operator), &proc);
475
476 /* Estimate number of input rows represented by RHS histogram. */
477 if (hist2_exists && vardata2->rel)
478 hist2_weight = (1.0 - nullfrac2 - sumcommon2) * vardata2->rel->rows;
479
480 /*
481 * Consider each element of the LHS MCV list, matching it to whatever RHS
482 * stats we have. Scale according to the known frequency of the MCV.
483 */
485 {
486 for (i = 0; i < mcv1_length; i++)
487 {
488 selec += mcv1_slot.numbers[i] *
492 hist2_slot.values, hist2_slot.nvalues,
494 &proc, opr_codenum);
495 }
496 }
497
498 /*
499 * Consider each element of the LHS histogram, except for the first and
500 * last elements, which we exclude on the grounds that they're outliers
501 * and thus not very representative. Scale on the assumption that each
502 * such histogram element represents an equal share of the LHS histogram
503 * population (which is a bit bogus, because the members of its bucket may
504 * not all act the same with respect to the join clause, but it's hard to
505 * do better).
506 *
507 * If there are too many histogram elements, decimate to limit runtime.
508 */
509 if (hist1_exists && hist1_slot.nvalues > 2 && (mcv2_exists || hist2_exists))
510 {
511 double hist_selec_sum = 0.0;
512 int k,
513 n;
514
515 k = (hist1_slot.nvalues - 3) / MAX_CONSIDERED_ELEMS + 1;
516
517 n = 0;
518 for (i = 1; i < hist1_slot.nvalues - 1; i += k)
519 {
524 hist2_slot.values, hist2_slot.nvalues,
526 &proc, opr_codenum);
527 n++;
528 }
529
530 selec += (1.0 - nullfrac1 - sumcommon1) * hist_selec_sum / n;
531 }
532
533 /*
534 * If useful statistics are not available then use the default estimate.
535 * We can apply null fractions if known, though.
536 */
538 selec = (1.0 - nullfrac1) * (1.0 - nullfrac2) * DEFAULT_SEL(operator);
539
540 /* Release stats. */
545
546 return selec;
547}
static Selectivity inet_semi_join_sel(Datum lhs_value, bool mcv_exists, Datum *mcv_values, int mcv_nvalues, bool hist_exists, Datum *hist_values, int hist_nvalues, double hist_weight, FmgrInfo *proc, int opr_codenum)

References ATTSTATSSLOT_NUMBERS, ATTSTATSSLOT_VALUES, DEFAULT_SEL, fb(), fmgr_info(), free_attstatsslot(), get_attstatsslot(), get_opcode(), GETSTRUCT(), HeapTupleIsValid, i, inet_semi_join_sel(), InvalidOid, MAX_CONSIDERED_ELEMS, mcv_population(), and Min.

Referenced by networkjoinsel().

◆ networksel()

Datum networksel ( PG_FUNCTION_ARGS  )

Definition at line 79 of file network_selfuncs.c.

80{
82 Oid operator = PG_GETARG_OID(1);
84 int varRelid = PG_GETARG_INT32(3);
85 int opr_codenum;
87 Node *other;
88 bool varonleft;
95 double sumcommon,
97 FmgrInfo proc;
98
99 /*
100 * Before all else, verify that the operator is one of the ones supported
101 * by this function, which in turn proves that the input datatypes are
102 * what we expect. Otherwise, attaching this selectivity function to some
103 * unexpected operator could cause trouble.
104 */
105 opr_codenum = inet_opr_codenum(operator);
106
107 /*
108 * If expression is not (variable op something) or (something op
109 * variable), then punt and return a default estimate.
110 */
111 if (!get_restriction_variable(root, args, varRelid,
112 &vardata, &other, &varonleft))
113 PG_RETURN_FLOAT8(DEFAULT_SEL(operator));
114
115 /*
116 * Can't do anything useful if the something is not a constant, either.
117 */
118 if (!IsA(other, Const))
119 {
121 PG_RETURN_FLOAT8(DEFAULT_SEL(operator));
122 }
123
124 /* All of the operators handled here are strict. */
125 if (((Const *) other)->constisnull)
126 {
128 PG_RETURN_FLOAT8(0.0);
129 }
130 constvalue = ((Const *) other)->constvalue;
131
132 /* Otherwise, we need stats in order to produce a non-default estimate. */
133 if (!HeapTupleIsValid(vardata.statsTuple))
134 {
136 PG_RETURN_FLOAT8(DEFAULT_SEL(operator));
137 }
138
139 stats = (Form_pg_statistic) GETSTRUCT(vardata.statsTuple);
140 nullfrac = stats->stanullfrac;
141
142 /*
143 * If we have most-common-values info, add up the fractions of the MCV
144 * entries that satisfy MCV OP CONST. These fractions contribute directly
145 * to the result selectivity. Also add up the total fraction represented
146 * by MCV entries.
147 */
148 fmgr_info(get_opcode(operator), &proc);
151 &sumcommon);
152
153 /*
154 * If we have a histogram, use it to estimate the proportion of the
155 * non-MCV population that satisfies the clause. If we don't, apply the
156 * default selectivity to that population.
157 */
158 if (get_attstatsslot(&hslot, vardata.statsTuple,
161 {
162 int h_codenum;
163
164 /* Commute if needed, so we can consider histogram to be on the left */
168
170 }
171 else
172 non_mcv_selec = DEFAULT_SEL(operator);
173
174 /* Combine selectivities for MCV and non-MCV populations */
176
177 /* Result should be in range, but make sure... */
179
181
183}
#define PG_GETARG_INT32(n)
Definition fmgr.h:269
#define IsA(nodeptr, _type_)
Definition nodes.h:164
uint64_t Datum
Definition postgres.h:70
bool get_restriction_variable(PlannerInfo *root, List *args, int varRelid, VariableStatData *vardata, Node **other, bool *varonleft)
Definition selfuncs.c:5507
double mcv_selectivity(VariableStatData *vardata, FmgrInfo *opproc, Oid collation, Datum constval, bool varonleft, double *sumcommonp)
Definition selfuncs.c:805
Definition nodes.h:135

References ATTSTATSSLOT_VALUES, CLAMP_PROBABILITY, DEFAULT_SEL, fb(), fmgr_info(), free_attstatsslot(), get_attstatsslot(), get_opcode(), get_restriction_variable(), GETSTRUCT(), HeapTupleIsValid, inet_hist_value_sel(), inet_opr_codenum(), InvalidOid, IsA, mcv_selectivity(), PG_GETARG_INT32, PG_GETARG_OID, PG_GETARG_POINTER, PG_RETURN_FLOAT8, ReleaseVariableStats, and root.