PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
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/builtins.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, VariableStatData *vardata1, VariableStatData *vardata2)
 
static Selectivity networkjoinsel_semi (Oid operator, VariableStatData *vardata1, VariableStatData *vardata2)
 
static Selectivity mcv_population (float4 *mcv_numbers, int mcv_nvalues)
 
static Selectivity inet_hist_value_sel (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 (Datum *mcv_values, float4 *mcv_numbers, int mcv_nvalues, Datum *hist_values, int hist_nvalues, int opr_codenum)
 
static Selectivity inet_hist_inclusion_join_sel (Datum *hist1_values, int hist1_nvalues, 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

#define DEFAULT_INCLUSION_SEL   0.005

Definition at line 36 of file network_selfuncs.c.

#define DEFAULT_OVERLAP_SEL   0.01

Definition at line 33 of file network_selfuncs.c.

#define DEFAULT_SEL (   operator)
Value:
((operator) == OID_INET_OVERLAP_OP ? \
#define DEFAULT_INCLUSION_SEL
#define DEFAULT_OVERLAP_SEL
#define OID_INET_OVERLAP_OP
Definition: pg_operator.h:1191

Definition at line 39 of file network_selfuncs.c.

Referenced by networkjoinsel_inner(), networkjoinsel_semi(), and networksel().

#define MAX_CONSIDERED_ELEMS   1024

Function Documentation

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

Definition at line 741 of file network_selfuncs.c.

References i, inet_hist_value_sel(), and MAX_CONSIDERED_ELEMS.

Referenced by networkjoinsel_inner().

744 {
745  double match = 0.0;
746  int i,
747  k,
748  n;
749 
750  if (hist2_nvalues <= 2)
751  return 0.0; /* no interior histogram elements */
752 
753  /* if there are too many histogram elements, decimate to limit runtime */
754  k = (hist2_nvalues - 3) / MAX_CONSIDERED_ELEMS + 1;
755 
756  n = 0;
757  for (i = 1; i < hist2_nvalues - 1; i += k)
758  {
759  match += inet_hist_value_sel(hist1_values, hist1_nvalues,
760  hist2_values[i], opr_codenum);
761  n++;
762  }
763 
764  return match / n;
765 }
static Selectivity inet_hist_value_sel(Datum *values, int nvalues, Datum constvalue, int opr_codenum)
int i
#define MAX_CONSIDERED_ELEMS
static int inet_hist_match_divider ( inet boundary,
inet query,
int  opr_codenum 
)
static

Definition at line 938 of file network_selfuncs.c.

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

Referenced by inet_hist_value_sel().

939 {
940  if (ip_family(boundary) == ip_family(query) &&
941  inet_masklen_inclusion_cmp(boundary, query, opr_codenum) == 0)
942  {
943  int min_bits,
944  decisive_bits;
945 
946  min_bits = Min(ip_bits(boundary), ip_bits(query));
947 
948  /*
949  * Set decisive_bits to the masklen of the one that should contain the
950  * other according to the operator.
951  */
952  if (opr_codenum < 0)
953  decisive_bits = ip_bits(boundary);
954  else if (opr_codenum > 0)
955  decisive_bits = ip_bits(query);
956  else
957  decisive_bits = min_bits;
958 
959  /*
960  * Now return the number of non-common decisive bits. (This will be
961  * zero if the boundary and query in fact match, else positive.)
962  */
963  if (min_bits > 0)
964  return decisive_bits - bitncommon(ip_addr(boundary),
965  ip_addr(query),
966  min_bits);
967  return decisive_bits;
968  }
969 
970  return -1;
971 }
#define ip_bits(inetptr)
Definition: inet.h:74
#define ip_family(inetptr)
Definition: inet.h:71
#define ip_addr(inetptr)
Definition: inet.h:77
#define Min(x, y)
Definition: c.h:806
int bitncommon(const unsigned char *l, const unsigned char *r, int n)
Definition: network.c:1004
static int inet_masklen_inclusion_cmp(inet *left, inet *right, int opr_codenum)
static Selectivity inet_hist_value_sel ( Datum values,
int  nvalues,
Datum  constvalue,
int  opr_codenum 
)
static

Definition at line 603 of file network_selfuncs.c.

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

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

605 {
606  Selectivity match = 0.0;
607  inet *query,
608  *left,
609  *right;
610  int i,
611  k,
612  n;
613  int left_order,
614  right_order,
615  left_divider,
616  right_divider;
617 
618  /* guard against zero-divide below */
619  if (nvalues <= 1)
620  return 0.0;
621 
622  /* if there are too many histogram elements, decimate to limit runtime */
623  k = (nvalues - 2) / MAX_CONSIDERED_ELEMS + 1;
624 
625  query = DatumGetInetPP(constvalue);
626 
627  /* "left" is the left boundary value of the current bucket ... */
628  left = DatumGetInetPP(values[0]);
629  left_order = inet_inclusion_cmp(left, query, opr_codenum);
630 
631  n = 0;
632  for (i = k; i < nvalues; i += k)
633  {
634  /* ... and "right" is the right boundary value */
635  right = DatumGetInetPP(values[i]);
636  right_order = inet_inclusion_cmp(right, query, opr_codenum);
637 
638  if (left_order == 0 && right_order == 0)
639  {
640  /* The whole bucket matches, since both endpoints do. */
641  match += 1.0;
642  }
643  else if ((left_order <= 0 && right_order >= 0) ||
644  (left_order >= 0 && right_order <= 0))
645  {
646  /* Partial bucket match. */
647  left_divider = inet_hist_match_divider(left, query, opr_codenum);
648  right_divider = inet_hist_match_divider(right, query, opr_codenum);
649 
650  if (left_divider >= 0 || right_divider >= 0)
651  match += 1.0 / pow(2.0, Max(left_divider, right_divider));
652  }
653 
654  /* Shift the variables. */
655  left = right;
656  left_order = right_order;
657 
658  /* Count the number of buckets considered. */
659  n++;
660  }
661 
662  return match / n;
663 }
static int inet_inclusion_cmp(inet *left, inet *right, int opr_codenum)
#define DatumGetInetPP(X)
Definition: inet.h:122
double Selectivity
Definition: nodes.h:639
static int inet_hist_match_divider(inet *boundary, inet *query, int opr_codenum)
Definition: inet.h:52
#define Max(x, y)
Definition: c.h:800
static Datum values[MAXATTR]
Definition: bootstrap.c:163
int i
#define MAX_CONSIDERED_ELEMS
static int inet_inclusion_cmp ( inet left,
inet right,
int  opr_codenum 
)
static

Definition at line 878 of file network_selfuncs.c.

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

Referenced by inet_hist_value_sel().

879 {
880  if (ip_family(left) == ip_family(right))
881  {
882  int order;
883 
884  order = bitncmp(ip_addr(left), ip_addr(right),
885  Min(ip_bits(left), ip_bits(right)));
886  if (order != 0)
887  return order;
888 
889  return inet_masklen_inclusion_cmp(left, right, opr_codenum);
890  }
891 
892  return ip_family(left) - ip_family(right);
893 }
#define ip_bits(inetptr)
Definition: inet.h:74
#define ip_family(inetptr)
Definition: inet.h:71
#define ip_addr(inetptr)
Definition: inet.h:77
#define Min(x, y)
Definition: c.h:806
static int inet_masklen_inclusion_cmp(inet *left, inet *right, int opr_codenum)
int bitncmp(const unsigned char *l, const unsigned char *r, int n)
Definition: network.c:970
static int inet_masklen_inclusion_cmp ( inet left,
inet right,
int  opr_codenum 
)
static

Definition at line 904 of file network_selfuncs.c.

References ip_bits.

Referenced by inet_hist_match_divider(), and inet_inclusion_cmp().

905 {
906  int order;
907 
908  order = (int) ip_bits(left) - (int) ip_bits(right);
909 
910  /*
911  * Return 0 if the operator would accept this combination of masklens.
912  * Note that opr_codenum zero (overlaps) will accept all cases.
913  */
914  if ((order > 0 && opr_codenum >= 0) ||
915  (order == 0 && opr_codenum >= -1 && opr_codenum <= 1) ||
916  (order < 0 && opr_codenum <= 0))
917  return 0;
918 
919  /*
920  * Otherwise, return a negative value for sup/supeq (notionally, the RHS
921  * needs to have a larger masklen than it has, which would make it sort
922  * later), or a positive value for sub/subeq (vice versa).
923  */
924  return opr_codenum;
925 }
#define ip_bits(inetptr)
Definition: inet.h:74
static Selectivity inet_mcv_hist_sel ( Datum mcv_values,
float4 mcv_numbers,
int  mcv_nvalues,
Datum hist_values,
int  hist_nvalues,
int  opr_codenum 
)
static

Definition at line 704 of file network_selfuncs.c.

References i, and inet_hist_value_sel().

Referenced by networkjoinsel_inner().

707 {
708  Selectivity selec = 0.0;
709  int i;
710 
711  /*
712  * We'll call inet_hist_value_selec with the histogram on the left, so we
713  * must commute the operator.
714  */
715  opr_codenum = -opr_codenum;
716 
717  for (i = 0; i < mcv_nvalues; i++)
718  {
719  selec += mcv_numbers[i] *
720  inet_hist_value_sel(hist_values, hist_nvalues, mcv_values[i],
721  opr_codenum);
722  }
723  return selec;
724 }
double Selectivity
Definition: nodes.h:639
static Selectivity inet_hist_value_sel(Datum *values, int nvalues, Datum constvalue, int opr_codenum)
int i
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 672 of file network_selfuncs.c.

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

Referenced by networkjoinsel_inner().

675 {
676  Selectivity selec = 0.0;
677  FmgrInfo proc;
678  int i,
679  j;
680 
681  fmgr_info(get_opcode(operator), &proc);
682 
683  for (i = 0; i < mcv1_nvalues; i++)
684  {
685  for (j = 0; j < mcv2_nvalues; j++)
686  if (DatumGetBool(FunctionCall2(&proc,
687  mcv1_values[i],
688  mcv2_values[j])))
689  selec += mcv1_numbers[i] * mcv2_numbers[j];
690  }
691  return selec;
692 }
Definition: fmgr.h:56
#define FunctionCall2(flinfo, arg1, arg2)
Definition: fmgr.h:604
double Selectivity
Definition: nodes.h:639
void fmgr_info(Oid functionId, FmgrInfo *finfo)
Definition: fmgr.c:127
#define DatumGetBool(X)
Definition: postgres.h:399
RegProcedure get_opcode(Oid opno)
Definition: lsyscache.c:1094
int i
static int inet_opr_codenum ( Oid  operator)
static

Definition at line 835 of file network_selfuncs.c.

References elog, ERROR, OID_INET_OVERLAP_OP, OID_INET_SUB_OP, OID_INET_SUBEQ_OP, OID_INET_SUP_OP, and OID_INET_SUPEQ_OP.

Referenced by networkjoinsel_inner(), networkjoinsel_semi(), and networksel().

836 {
837  switch (operator)
838  {
839  case OID_INET_SUP_OP:
840  return -2;
841  case OID_INET_SUPEQ_OP:
842  return -1;
843  case OID_INET_OVERLAP_OP:
844  return 0;
845  case OID_INET_SUBEQ_OP:
846  return 1;
847  case OID_INET_SUB_OP:
848  return 2;
849  default:
850  elog(ERROR, "unrecognized operator %u for inet selectivity",
851  operator);
852  }
853  return 0; /* unreached, but keep compiler quiet */
854 }
#define OID_INET_SUBEQ_OP
Definition: pg_operator.h:1182
#define ERROR
Definition: elog.h:43
#define OID_INET_SUP_OP
Definition: pg_operator.h:1185
#define OID_INET_OVERLAP_OP
Definition: pg_operator.h:1191
#define OID_INET_SUB_OP
Definition: pg_operator.h:1179
#define elog
Definition: elog.h:219
#define OID_INET_SUPEQ_OP
Definition: pg_operator.h:1188
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 792 of file network_selfuncs.c.

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

Referenced by networkjoinsel_semi().

797 {
798  if (mcv_exists)
799  {
800  int i;
801 
802  for (i = 0; i < mcv_nvalues; i++)
803  {
804  if (DatumGetBool(FunctionCall2(proc,
805  lhs_value,
806  mcv_values[i])))
807  return 1.0;
808  }
809  }
810 
811  if (hist_exists && hist_weight > 0)
812  {
813  Selectivity hist_selec;
814 
815  /* Commute operator, since we're passing lhs_value on the right */
816  hist_selec = inet_hist_value_sel(hist_values, hist_nvalues,
817  lhs_value, -opr_codenum);
818 
819  if (hist_selec > 0)
820  return Min(1.0, hist_weight * hist_selec);
821  }
822 
823  return 0.0;
824 }
#define Min(x, y)
Definition: c.h:806
#define FunctionCall2(flinfo, arg1, arg2)
Definition: fmgr.h:604
double Selectivity
Definition: nodes.h:639
static Selectivity inet_hist_value_sel(Datum *values, int nvalues, Datum constvalue, int opr_codenum)
#define DatumGetBool(X)
Definition: postgres.h:399
int i
static Selectivity mcv_population ( float4 mcv_numbers,
int  mcv_nvalues 
)
static

Definition at line 538 of file network_selfuncs.c.

References i.

Referenced by networkjoinsel_inner(), and networkjoinsel_semi().

539 {
540  Selectivity sumcommon = 0.0;
541  int i;
542 
543  for (i = 0; i < mcv_nvalues; i++)
544  {
545  sumcommon += mcv_numbers[i];
546  }
547 
548  return sumcommon;
549 }
double Selectivity
Definition: nodes.h:639
int i
Datum networkjoinsel ( PG_FUNCTION_ARGS  )

Definition at line 195 of file network_selfuncs.c.

References generate_unaccent_rules::args, CLAMP_PROBABILITY, elog, ERROR, get_commutator(), get_join_variables(), 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, and ReleaseVariableStats.

196 {
198  Oid operator = PG_GETARG_OID(1);
199  List *args = (List *) PG_GETARG_POINTER(2);
200 #ifdef NOT_USED
201  JoinType jointype = (JoinType) PG_GETARG_INT16(3);
202 #endif
204  double selec;
205  VariableStatData vardata1;
206  VariableStatData vardata2;
207  bool join_is_reversed;
208 
209  get_join_variables(root, args, sjinfo,
210  &vardata1, &vardata2, &join_is_reversed);
211 
212  switch (sjinfo->jointype)
213  {
214  case JOIN_INNER:
215  case JOIN_LEFT:
216  case JOIN_FULL:
217 
218  /*
219  * Selectivity for left/full join is not exactly the same as inner
220  * join, but we neglect the difference, as eqjoinsel does.
221  */
222  selec = networkjoinsel_inner(operator, &vardata1, &vardata2);
223  break;
224  case JOIN_SEMI:
225  case JOIN_ANTI:
226  /* Here, it's important that we pass the outer var on the left. */
227  if (!join_is_reversed)
228  selec = networkjoinsel_semi(operator, &vardata1, &vardata2);
229  else
230  selec = networkjoinsel_semi(get_commutator(operator),
231  &vardata2, &vardata1);
232  break;
233  default:
234  /* other values not expected here */
235  elog(ERROR, "unrecognized join type: %d",
236  (int) sjinfo->jointype);
237  selec = 0; /* keep compiler quiet */
238  break;
239  }
240 
241  ReleaseVariableStats(vardata1);
242  ReleaseVariableStats(vardata2);
243 
244  CLAMP_PROBABILITY(selec);
245 
246  PG_RETURN_FLOAT8((float8) selec);
247 }
Oid get_commutator(Oid opno)
Definition: lsyscache.c:1313
#define PG_RETURN_FLOAT8(x)
Definition: fmgr.h:326
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:241
unsigned int Oid
Definition: postgres_ext.h:31
JoinType
Definition: nodes.h:673
#define CLAMP_PROBABILITY(p)
Definition: selfuncs.h:57
#define ERROR
Definition: elog.h:43
double float8
Definition: c.h:381
void get_join_variables(PlannerInfo *root, List *args, SpecialJoinInfo *sjinfo, VariableStatData *vardata1, VariableStatData *vardata2, bool *join_is_reversed)
Definition: selfuncs.c:4510
#define PG_GETARG_OID(n)
Definition: fmgr.h:240
static Selectivity networkjoinsel_inner(Oid operator, VariableStatData *vardata1, VariableStatData *vardata2)
#define PG_GETARG_INT16(n)
Definition: fmgr.h:236
JoinType jointype
Definition: relation.h:1923
#define ReleaseVariableStats(vardata)
Definition: selfuncs.h:81
static Selectivity networkjoinsel_semi(Oid operator, VariableStatData *vardata1, VariableStatData *vardata2)
#define elog
Definition: elog.h:219
Definition: pg_list.h:45
static Selectivity networkjoinsel_inner ( Oid  operator,
VariableStatData vardata1,
VariableStatData vardata2 
)
static

Definition at line 262 of file network_selfuncs.c.

References ATTSTATSSLOT_NUMBERS, ATTSTATSSLOT_VALUES, DEFAULT_SEL, free_attstatsslot(), get_attstatsslot(), GETSTRUCT, HeapTupleIsValid, inet_hist_inclusion_join_sel(), inet_mcv_hist_sel(), inet_mcv_join_sel(), inet_opr_codenum(), InvalidOid, MAX_CONSIDERED_ELEMS, mcv_population(), Min, AttStatsSlot::numbers, AttStatsSlot::nvalues, STATISTIC_KIND_HISTOGRAM, STATISTIC_KIND_MCV, VariableStatData::statsTuple, and AttStatsSlot::values.

Referenced by networkjoinsel().

264 {
265  Form_pg_statistic stats;
266  double nullfrac1 = 0.0,
267  nullfrac2 = 0.0;
268  Selectivity selec = 0.0,
269  sumcommon1 = 0.0,
270  sumcommon2 = 0.0;
271  bool mcv1_exists = false,
272  mcv2_exists = false,
273  hist1_exists = false,
274  hist2_exists = false;
275  int opr_codenum;
276  int mcv1_length = 0,
277  mcv2_length = 0;
278  AttStatsSlot mcv1_slot;
279  AttStatsSlot mcv2_slot;
280  AttStatsSlot hist1_slot;
281  AttStatsSlot hist2_slot;
282 
283  if (HeapTupleIsValid(vardata1->statsTuple))
284  {
285  stats = (Form_pg_statistic) GETSTRUCT(vardata1->statsTuple);
286  nullfrac1 = stats->stanullfrac;
287 
288  mcv1_exists = get_attstatsslot(&mcv1_slot, vardata1->statsTuple,
291  hist1_exists = get_attstatsslot(&hist1_slot, vardata1->statsTuple,
294  /* Arbitrarily limit number of MCVs considered */
295  mcv1_length = Min(mcv1_slot.nvalues, MAX_CONSIDERED_ELEMS);
296  if (mcv1_exists)
297  sumcommon1 = mcv_population(mcv1_slot.numbers, mcv1_length);
298  }
299  else
300  {
301  memset(&mcv1_slot, 0, sizeof(mcv1_slot));
302  memset(&hist1_slot, 0, sizeof(hist1_slot));
303  }
304 
305  if (HeapTupleIsValid(vardata2->statsTuple))
306  {
307  stats = (Form_pg_statistic) GETSTRUCT(vardata2->statsTuple);
308  nullfrac2 = stats->stanullfrac;
309 
310  mcv2_exists = get_attstatsslot(&mcv2_slot, vardata2->statsTuple,
313  hist2_exists = get_attstatsslot(&hist2_slot, vardata2->statsTuple,
316  /* Arbitrarily limit number of MCVs considered */
317  mcv2_length = Min(mcv2_slot.nvalues, MAX_CONSIDERED_ELEMS);
318  if (mcv2_exists)
319  sumcommon2 = mcv_population(mcv2_slot.numbers, mcv2_length);
320  }
321  else
322  {
323  memset(&mcv2_slot, 0, sizeof(mcv2_slot));
324  memset(&hist2_slot, 0, sizeof(hist2_slot));
325  }
326 
327  opr_codenum = inet_opr_codenum(operator);
328 
329  /*
330  * Calculate selectivity for MCV vs MCV matches.
331  */
332  if (mcv1_exists && mcv2_exists)
333  selec += inet_mcv_join_sel(mcv1_slot.values, mcv1_slot.numbers,
334  mcv1_length,
335  mcv2_slot.values, mcv2_slot.numbers,
336  mcv2_length,
337  operator);
338 
339  /*
340  * Add in selectivities for MCV vs histogram matches, scaling according to
341  * the fractions of the populations represented by the histograms. Note
342  * that the second case needs to commute the operator.
343  */
344  if (mcv1_exists && hist2_exists)
345  selec += (1.0 - nullfrac2 - sumcommon2) *
346  inet_mcv_hist_sel(mcv1_slot.values, mcv1_slot.numbers, mcv1_length,
347  hist2_slot.values, hist2_slot.nvalues,
348  opr_codenum);
349  if (mcv2_exists && hist1_exists)
350  selec += (1.0 - nullfrac1 - sumcommon1) *
351  inet_mcv_hist_sel(mcv2_slot.values, mcv2_slot.numbers, mcv2_length,
352  hist1_slot.values, hist1_slot.nvalues,
353  -opr_codenum);
354 
355  /*
356  * Add in selectivity for histogram vs histogram matches, again scaling
357  * appropriately.
358  */
359  if (hist1_exists && hist2_exists)
360  selec += (1.0 - nullfrac1 - sumcommon1) *
361  (1.0 - nullfrac2 - sumcommon2) *
362  inet_hist_inclusion_join_sel(hist1_slot.values, hist1_slot.nvalues,
363  hist2_slot.values, hist2_slot.nvalues,
364  opr_codenum);
365 
366  /*
367  * If useful statistics are not available then use the default estimate.
368  * We can apply null fractions if known, though.
369  */
370  if ((!mcv1_exists && !hist1_exists) || (!mcv2_exists && !hist2_exists))
371  selec = (1.0 - nullfrac1) * (1.0 - nullfrac2) * DEFAULT_SEL(operator);
372 
373  /* Release stats. */
374  free_attstatsslot(&mcv1_slot);
375  free_attstatsslot(&mcv2_slot);
376  free_attstatsslot(&hist1_slot);
377  free_attstatsslot(&hist2_slot);
378 
379  return selec;
380 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
#define ATTSTATSSLOT_VALUES
Definition: lsyscache.h:39
HeapTuple statsTuple
Definition: selfuncs.h:71
#define STATISTIC_KIND_HISTOGRAM
Definition: pg_statistic.h:222
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)
#define Min(x, y)
Definition: c.h:806
double Selectivity
Definition: nodes.h:639
FormData_pg_statistic * Form_pg_statistic
Definition: pg_statistic.h:129
static Selectivity inet_mcv_hist_sel(Datum *mcv_values, float4 *mcv_numbers, int mcv_nvalues, Datum *hist_values, int hist_nvalues, int opr_codenum)
#define ATTSTATSSLOT_NUMBERS
Definition: lsyscache.h:40
float4 * numbers
Definition: lsyscache.h:52
#define STATISTIC_KIND_MCV
Definition: pg_statistic.h:204
static int inet_opr_codenum(Oid operator)
static Selectivity mcv_population(float4 *mcv_numbers, int mcv_nvalues)
#define InvalidOid
Definition: postgres_ext.h:36
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
bool get_attstatsslot(AttStatsSlot *sslot, HeapTuple statstuple, int reqkind, Oid reqop, int flags)
Definition: lsyscache.c:2895
Datum * values
Definition: lsyscache.h:49
#define DEFAULT_SEL(operator)
static Selectivity inet_hist_inclusion_join_sel(Datum *hist1_values, int hist1_nvalues, Datum *hist2_values, int hist2_nvalues, int opr_codenum)
#define MAX_CONSIDERED_ELEMS
void free_attstatsslot(AttStatsSlot *sslot)
Definition: lsyscache.c:3011
static Selectivity networkjoinsel_semi ( Oid  operator,
VariableStatData vardata1,
VariableStatData vardata2 
)
static

Definition at line 389 of file network_selfuncs.c.

References ATTSTATSSLOT_NUMBERS, ATTSTATSSLOT_VALUES, DEFAULT_SEL, fmgr_info(), free_attstatsslot(), get_attstatsslot(), get_opcode(), GETSTRUCT, HeapTupleIsValid, i, inet_opr_codenum(), inet_semi_join_sel(), InvalidOid, MAX_CONSIDERED_ELEMS, mcv_population(), Min, AttStatsSlot::numbers, AttStatsSlot::nvalues, VariableStatData::rel, RelOptInfo::rows, STATISTIC_KIND_HISTOGRAM, STATISTIC_KIND_MCV, VariableStatData::statsTuple, and AttStatsSlot::values.

Referenced by networkjoinsel().

391 {
392  Form_pg_statistic stats;
393  Selectivity selec = 0.0,
394  sumcommon1 = 0.0,
395  sumcommon2 = 0.0;
396  double nullfrac1 = 0.0,
397  nullfrac2 = 0.0,
398  hist2_weight = 0.0;
399  bool mcv1_exists = false,
400  mcv2_exists = false,
401  hist1_exists = false,
402  hist2_exists = false;
403  int opr_codenum;
404  FmgrInfo proc;
405  int i,
406  mcv1_length = 0,
407  mcv2_length = 0;
408  AttStatsSlot mcv1_slot;
409  AttStatsSlot mcv2_slot;
410  AttStatsSlot hist1_slot;
411  AttStatsSlot hist2_slot;
412 
413  if (HeapTupleIsValid(vardata1->statsTuple))
414  {
415  stats = (Form_pg_statistic) GETSTRUCT(vardata1->statsTuple);
416  nullfrac1 = stats->stanullfrac;
417 
418  mcv1_exists = get_attstatsslot(&mcv1_slot, vardata1->statsTuple,
421  hist1_exists = get_attstatsslot(&hist1_slot, vardata1->statsTuple,
424  /* Arbitrarily limit number of MCVs considered */
425  mcv1_length = Min(mcv1_slot.nvalues, MAX_CONSIDERED_ELEMS);
426  if (mcv1_exists)
427  sumcommon1 = mcv_population(mcv1_slot.numbers, mcv1_length);
428  }
429  else
430  {
431  memset(&mcv1_slot, 0, sizeof(mcv1_slot));
432  memset(&hist1_slot, 0, sizeof(hist1_slot));
433  }
434 
435  if (HeapTupleIsValid(vardata2->statsTuple))
436  {
437  stats = (Form_pg_statistic) GETSTRUCT(vardata2->statsTuple);
438  nullfrac2 = stats->stanullfrac;
439 
440  mcv2_exists = get_attstatsslot(&mcv2_slot, vardata2->statsTuple,
443  hist2_exists = get_attstatsslot(&hist2_slot, vardata2->statsTuple,
446  /* Arbitrarily limit number of MCVs considered */
447  mcv2_length = Min(mcv2_slot.nvalues, MAX_CONSIDERED_ELEMS);
448  if (mcv2_exists)
449  sumcommon2 = mcv_population(mcv2_slot.numbers, mcv2_length);
450  }
451  else
452  {
453  memset(&mcv2_slot, 0, sizeof(mcv2_slot));
454  memset(&hist2_slot, 0, sizeof(hist2_slot));
455  }
456 
457  opr_codenum = inet_opr_codenum(operator);
458  fmgr_info(get_opcode(operator), &proc);
459 
460  /* Estimate number of input rows represented by RHS histogram. */
461  if (hist2_exists && vardata2->rel)
462  hist2_weight = (1.0 - nullfrac2 - sumcommon2) * vardata2->rel->rows;
463 
464  /*
465  * Consider each element of the LHS MCV list, matching it to whatever RHS
466  * stats we have. Scale according to the known frequency of the MCV.
467  */
468  if (mcv1_exists && (mcv2_exists || hist2_exists))
469  {
470  for (i = 0; i < mcv1_length; i++)
471  {
472  selec += mcv1_slot.numbers[i] *
473  inet_semi_join_sel(mcv1_slot.values[i],
474  mcv2_exists, mcv2_slot.values, mcv2_length,
475  hist2_exists,
476  hist2_slot.values, hist2_slot.nvalues,
477  hist2_weight,
478  &proc, opr_codenum);
479  }
480  }
481 
482  /*
483  * Consider each element of the LHS histogram, except for the first and
484  * last elements, which we exclude on the grounds that they're outliers
485  * and thus not very representative. Scale on the assumption that each
486  * such histogram element represents an equal share of the LHS histogram
487  * population (which is a bit bogus, because the members of its bucket may
488  * not all act the same with respect to the join clause, but it's hard to
489  * do better).
490  *
491  * If there are too many histogram elements, decimate to limit runtime.
492  */
493  if (hist1_exists && hist1_slot.nvalues > 2 && (mcv2_exists || hist2_exists))
494  {
495  double hist_selec_sum = 0.0;
496  int k,
497  n;
498 
499  k = (hist1_slot.nvalues - 3) / MAX_CONSIDERED_ELEMS + 1;
500 
501  n = 0;
502  for (i = 1; i < hist1_slot.nvalues - 1; i += k)
503  {
504  hist_selec_sum +=
505  inet_semi_join_sel(hist1_slot.values[i],
506  mcv2_exists, mcv2_slot.values, mcv2_length,
507  hist2_exists,
508  hist2_slot.values, hist2_slot.nvalues,
509  hist2_weight,
510  &proc, opr_codenum);
511  n++;
512  }
513 
514  selec += (1.0 - nullfrac1 - sumcommon1) * hist_selec_sum / n;
515  }
516 
517  /*
518  * If useful statistics are not available then use the default estimate.
519  * We can apply null fractions if known, though.
520  */
521  if ((!mcv1_exists && !hist1_exists) || (!mcv2_exists && !hist2_exists))
522  selec = (1.0 - nullfrac1) * (1.0 - nullfrac2) * DEFAULT_SEL(operator);
523 
524  /* Release stats. */
525  free_attstatsslot(&mcv1_slot);
526  free_attstatsslot(&mcv2_slot);
527  free_attstatsslot(&hist1_slot);
528  free_attstatsslot(&hist2_slot);
529 
530  return selec;
531 }
Definition: fmgr.h:56
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
#define ATTSTATSSLOT_VALUES
Definition: lsyscache.h:39
HeapTuple statsTuple
Definition: selfuncs.h:71
#define STATISTIC_KIND_HISTOGRAM
Definition: pg_statistic.h:222
RelOptInfo * rel
Definition: selfuncs.h:70
#define Min(x, y)
Definition: c.h:806
double Selectivity
Definition: nodes.h:639
FormData_pg_statistic * Form_pg_statistic
Definition: pg_statistic.h:129
#define ATTSTATSSLOT_NUMBERS
Definition: lsyscache.h:40
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)
void fmgr_info(Oid functionId, FmgrInfo *finfo)
Definition: fmgr.c:127
float4 * numbers
Definition: lsyscache.h:52
#define STATISTIC_KIND_MCV
Definition: pg_statistic.h:204
static int inet_opr_codenum(Oid operator)
static Selectivity mcv_population(float4 *mcv_numbers, int mcv_nvalues)
double rows
Definition: relation.h:528
#define InvalidOid
Definition: postgres_ext.h:36
RegProcedure get_opcode(Oid opno)
Definition: lsyscache.c:1094
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
bool get_attstatsslot(AttStatsSlot *sslot, HeapTuple statstuple, int reqkind, Oid reqop, int flags)
Definition: lsyscache.c:2895
Datum * values
Definition: lsyscache.h:49
#define DEFAULT_SEL(operator)
int i
#define MAX_CONSIDERED_ELEMS
void free_attstatsslot(AttStatsSlot *sslot)
Definition: lsyscache.c:3011
Datum networksel ( PG_FUNCTION_ARGS  )

Definition at line 79 of file network_selfuncs.c.

References generate_unaccent_rules::args, ATTSTATSSLOT_VALUES, CLAMP_PROBABILITY, DEFAULT_SEL, fmgr_info(), free_attstatsslot(), get_attstatsslot(), get_opcode(), get_restriction_variable(), GETSTRUCT, HeapTupleIsValid, inet_hist_value_sel(), inet_opr_codenum(), InvalidOid, IsA, mcv_selectivity(), AttStatsSlot::nvalues, PG_GETARG_INT32, PG_GETARG_OID, PG_GETARG_POINTER, PG_RETURN_FLOAT8, ReleaseVariableStats, STATISTIC_KIND_HISTOGRAM, VariableStatData::statsTuple, and AttStatsSlot::values.

80 {
82  Oid operator = PG_GETARG_OID(1);
83  List *args = (List *) PG_GETARG_POINTER(2);
84  int varRelid = PG_GETARG_INT32(3);
85  VariableStatData vardata;
86  Node *other;
87  bool varonleft;
88  Selectivity selec,
89  mcv_selec,
90  non_mcv_selec;
91  Datum constvalue;
92  Form_pg_statistic stats;
93  AttStatsSlot hslot;
94  double sumcommon,
95  nullfrac;
96  FmgrInfo proc;
97 
98  /*
99  * If expression is not (variable op something) or (something op
100  * variable), then punt and return a default estimate.
101  */
102  if (!get_restriction_variable(root, args, varRelid,
103  &vardata, &other, &varonleft))
104  PG_RETURN_FLOAT8(DEFAULT_SEL(operator));
105 
106  /*
107  * Can't do anything useful if the something is not a constant, either.
108  */
109  if (!IsA(other, Const))
110  {
111  ReleaseVariableStats(vardata);
112  PG_RETURN_FLOAT8(DEFAULT_SEL(operator));
113  }
114 
115  /* All of the operators handled here are strict. */
116  if (((Const *) other)->constisnull)
117  {
118  ReleaseVariableStats(vardata);
119  PG_RETURN_FLOAT8(0.0);
120  }
121  constvalue = ((Const *) other)->constvalue;
122 
123  /* Otherwise, we need stats in order to produce a non-default estimate. */
124  if (!HeapTupleIsValid(vardata.statsTuple))
125  {
126  ReleaseVariableStats(vardata);
127  PG_RETURN_FLOAT8(DEFAULT_SEL(operator));
128  }
129 
130  stats = (Form_pg_statistic) GETSTRUCT(vardata.statsTuple);
131  nullfrac = stats->stanullfrac;
132 
133  /*
134  * If we have most-common-values info, add up the fractions of the MCV
135  * entries that satisfy MCV OP CONST. These fractions contribute directly
136  * to the result selectivity. Also add up the total fraction represented
137  * by MCV entries.
138  */
139  fmgr_info(get_opcode(operator), &proc);
140  mcv_selec = mcv_selectivity(&vardata, &proc, constvalue, varonleft,
141  &sumcommon);
142 
143  /*
144  * If we have a histogram, use it to estimate the proportion of the
145  * non-MCV population that satisfies the clause. If we don't, apply the
146  * default selectivity to that population.
147  */
148  if (get_attstatsslot(&hslot, vardata.statsTuple,
151  {
152  int opr_codenum = inet_opr_codenum(operator);
153 
154  /* Commute if needed, so we can consider histogram to be on the left */
155  if (!varonleft)
156  opr_codenum = -opr_codenum;
157  non_mcv_selec = inet_hist_value_sel(hslot.values, hslot.nvalues,
158  constvalue, opr_codenum);
159 
160  free_attstatsslot(&hslot);
161  }
162  else
163  non_mcv_selec = DEFAULT_SEL(operator);
164 
165  /* Combine selectivities for MCV and non-MCV populations */
166  selec = mcv_selec + (1.0 - nullfrac - sumcommon) * non_mcv_selec;
167 
168  /* Result should be in range, but make sure... */
169  CLAMP_PROBABILITY(selec);
170 
171  ReleaseVariableStats(vardata);
172 
173  PG_RETURN_FLOAT8(selec);
174 }
#define PG_GETARG_INT32(n)
Definition: fmgr.h:234
Definition: fmgr.h:56
#define IsA(nodeptr, _type_)
Definition: nodes.h:560
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
#define ATTSTATSSLOT_VALUES
Definition: lsyscache.h:39
HeapTuple statsTuple
Definition: selfuncs.h:71
#define STATISTIC_KIND_HISTOGRAM
Definition: pg_statistic.h:222
bool get_restriction_variable(PlannerInfo *root, List *args, int varRelid, VariableStatData *vardata, Node **other, bool *varonleft)
Definition: selfuncs.c:4450
#define PG_RETURN_FLOAT8(x)
Definition: fmgr.h:326
Definition: nodes.h:509
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:241
double Selectivity
Definition: nodes.h:639
unsigned int Oid
Definition: postgres_ext.h:31
FormData_pg_statistic * Form_pg_statistic
Definition: pg_statistic.h:129
static Selectivity inet_hist_value_sel(Datum *values, int nvalues, Datum constvalue, int opr_codenum)
#define CLAMP_PROBABILITY(p)
Definition: selfuncs.h:57
void fmgr_info(Oid functionId, FmgrInfo *finfo)
Definition: fmgr.c:127
#define PG_GETARG_OID(n)
Definition: fmgr.h:240
static int inet_opr_codenum(Oid operator)
uintptr_t Datum
Definition: postgres.h:372
double mcv_selectivity(VariableStatData *vardata, FmgrInfo *opproc, Datum constval, bool varonleft, double *sumcommonp)
Definition: selfuncs.c:632
#define InvalidOid
Definition: postgres_ext.h:36
RegProcedure get_opcode(Oid opno)
Definition: lsyscache.c:1094
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
bool get_attstatsslot(AttStatsSlot *sslot, HeapTuple statstuple, int reqkind, Oid reqop, int flags)
Definition: lsyscache.c:2895
Datum * values
Definition: lsyscache.h:49
#define DEFAULT_SEL(operator)
#define ReleaseVariableStats(vardata)
Definition: selfuncs.h:81
Definition: pg_list.h:45
void free_attstatsslot(AttStatsSlot *sslot)
Definition: lsyscache.c:3011