PostGIS  3.6.1dev-r@@SVN_REVISION@@

◆ gserialized_estimated_extent()

Datum gserialized_estimated_extent ( PG_FUNCTION_ARGS  )

Definition at line 2599 of file gserialized_estimate.c.

2600 {
2601  text *coltxt = NULL;
2602  char *col = NULL;
2603  int16 attnum, idx_attnum;
2604  Oid atttypid = InvalidOid;
2605  char nsp_tbl[2*NAMEDATALEN+6];
2606  char *tbl;
2607  Oid tbl_oid, idx_oid = 0;
2608  ND_STATS *nd_stats;
2609  GBOX *gbox = NULL;
2610  bool only_parent = false;
2611  int key_type;
2612  Oid geographyOid = postgis_oid(GEOGRAPHYOID);
2613  Oid geometryOid = postgis_oid(GEOMETRYOID);
2614 
2615  /* We need to initialize the internal cache to access it later via postgis_oid() */
2616  postgis_initialize_cache();
2617 
2618  if (PG_NARGS() < 2 || PG_NARGS() > 4)
2619  elog(ERROR, "ST_EstimatedExtent() called with wrong number of arguments");
2620 
2621  if ( PG_NARGS() == 4 )
2622  {
2623  only_parent = PG_GETARG_BOOL(3);
2624  }
2625  if ( PG_NARGS() >= 3 )
2626  {
2627  char *nsp = text_to_cstring(PG_GETARG_TEXT_P(0));
2628  tbl = text_to_cstring(PG_GETARG_TEXT_P(1));
2629  coltxt = PG_GETARG_TEXT_P(2);
2630  snprintf(nsp_tbl, sizeof(nsp_tbl), "\"%s\".\"%s\"", nsp, tbl);
2631  }
2632  if ( PG_NARGS() == 2 )
2633  {
2634  tbl = text_to_cstring(PG_GETARG_TEXT_P(0));
2635  coltxt = PG_GETARG_TEXT_P(1);
2636  snprintf(nsp_tbl, sizeof(nsp_tbl), "\"%s\"", tbl);
2637  }
2638 
2639  /* Parse the namespace/table strings and lookup in system catalogs */
2640  tbl_oid = DatumGetObjectId(DirectFunctionCall1(regclassin, CStringGetDatum(nsp_tbl)));
2641  if (!tbl_oid)
2642  elog(ERROR, "cannot lookup table %s", nsp_tbl);
2643 
2644  /* Get the attribute number and type from the column name */
2645  col = text_to_cstring(coltxt);
2646  if (!get_attnum_attypid(tbl_oid, col, &attnum, &atttypid))
2647  elog(ERROR, "column %s.\"%s\" does not exist", nsp_tbl, col);
2648 
2649  /* We can only do estimates on geograpy and geometry */
2650  if ((atttypid != geographyOid) && (atttypid != geometryOid))
2651  {
2652  elog(ERROR, "column %s.\"%s\" must be a geometry or geography", nsp_tbl, col);
2653  }
2654 
2655  /* Read the extent from the head of the spatial index */
2656  /* works if there is a spatial index */
2657  idx_oid = table_get_spatial_index(tbl_oid, attnum, &key_type, &idx_attnum);
2658  if (idx_oid != InvalidOid)
2659  {
2660  /* TODO: how about only_parent ? */
2661  gbox = spatial_index_read_extent(idx_oid, idx_attnum, key_type);
2662  elog(DEBUG3, "index for %s.\"%s\" exists, reading gbox from there", nsp_tbl, col);
2663  if (!gbox) PG_RETURN_NULL();
2664  }
2665  /* Read the extent from the stats tables, */
2666  /* works if ANALYZE has been run */
2667  else
2668  {
2669  int stats_mode = 2;
2670  elog(DEBUG3, "index for %s.\"%s\" does not exist", nsp_tbl, col);
2671 
2672  /* For a geography column, we need the XYZ geocentric bounds */
2673  if (atttypid == geographyOid)
2674  stats_mode = 3;
2675 
2676  /* ND stats include an extent for the histogram */
2677  nd_stats = pg_get_nd_stats_by_name(tbl_oid, coltxt, stats_mode, only_parent);
2678 
2679  /* Error out on no stats */
2680  if (!nd_stats)
2681  {
2682  elog(WARNING, "stats for \"%s.%s\" do not exist", tbl, col);
2683  PG_RETURN_NULL();
2684  }
2685 
2686  /* Construct the box */
2687  gbox = gbox_new(0);
2688  gbox->xmin = nd_stats->extent.min[0];
2689  gbox->xmax = nd_stats->extent.max[0];
2690  gbox->ymin = nd_stats->extent.min[1];
2691  gbox->ymax = nd_stats->extent.max[1];
2692  if (stats_mode != 2)
2693  {
2694  FLAGS_SET_Z(gbox->flags, 1);
2695  gbox->zmin = nd_stats->extent.min[2];
2696  gbox->zmax = nd_stats->extent.max[2];
2697  }
2698 
2699  pfree(nd_stats);
2700  }
2701 
2702  /* Convert geocentric geography box into a planar box */
2703  /* that users understand */
2704  if (atttypid == geographyOid)
2705  {
2706  GBOX *gbox_planar = gbox_new(0);
2707  gbox_geocentric_get_gbox_cartesian(gbox, gbox_planar);
2708  PG_RETURN_POINTER(gbox_planar);
2709  }
2710  else
2711  PG_RETURN_POINTER(gbox);
2712 }
GBOX * gbox_new(lwflags_t flags)
Create a new gbox with the dimensionality indicated by the flags.
Definition: gbox.c:32
static ND_STATS * pg_get_nd_stats_by_name(const Oid table_oid, const text *att_text, int mode, bool only_parent)
Pull the stats object from the PgSQL system catalogs.
static bool get_attnum_attypid(Oid table_oid, const char *col, int16 *attnum, Oid *atttypid)
static GBOX * spatial_index_read_extent(Oid idx_oid, int idx_att_num, int key_type)
static Oid table_get_spatial_index(Oid tbl_oid, int16 attnum, int *key_type, int16 *idx_attnum)
#define FLAGS_SET_Z(flags, value)
Definition: liblwgeom.h:172
int gbox_geocentric_get_gbox_cartesian(const GBOX *gbox_geocentric, GBOX *gbox_planar)
Definition: lwgeodetic.c:3596
double ymax
Definition: liblwgeom.h:357
double zmax
Definition: liblwgeom.h:359
double xmax
Definition: liblwgeom.h:355
double zmin
Definition: liblwgeom.h:358
double ymin
Definition: liblwgeom.h:356
double xmin
Definition: liblwgeom.h:354
lwflags_t flags
Definition: liblwgeom.h:353
float4 max[ND_DIMS]
float4 min[ND_DIMS]
N-dimensional statistics structure.

References ND_STATS_T::extent, GBOX::flags, FLAGS_SET_Z, gbox_geocentric_get_gbox_cartesian(), gbox_new(), get_attnum_attypid(), ND_BOX_T::max, ND_BOX_T::min, pg_get_nd_stats_by_name(), spatial_index_read_extent(), table_get_spatial_index(), GBOX::xmax, GBOX::xmin, GBOX::ymax, GBOX::ymin, GBOX::zmax, and GBOX::zmin.

Referenced by geometry_estimated_extent().

Here is the call graph for this function:
Here is the caller graph for this function: