PostGIS 3.7.0dev-r@@SVN_REVISION@@
Loading...
Searching...
No Matches

◆ gserialized_estimated_extent()

Datum gserialized_estimated_extent ( PG_FUNCTION_ARGS  )

Definition at line 2441 of file gserialized_estimate.c.

2442{
2443 text *coltxt = NULL;
2444 char *col = NULL;
2445 int16 attnum, idx_attnum;
2446 Oid atttypid = InvalidOid;
2447 char nsp_tbl[2*NAMEDATALEN+6];
2448 char *tbl = NULL;
2449 Oid tbl_oid, idx_oid = 0;
2450 ND_STATS *nd_stats;
2451 GBOX *gbox = NULL;
2452 bool only_parent = false;
2453 int key_type;
2454 Oid geographyOid = postgis_oid(GEOGRAPHYOID);
2455 Oid geometryOid = postgis_oid(GEOMETRYOID);
2456
2457 /* We need to initialize the internal cache to access it later via postgis_oid() */
2458 postgis_initialize_cache();
2459
2460 if (PG_NARGS() < 2 || PG_NARGS() > 4)
2461 elog(ERROR, "ST_EstimatedExtent() called with wrong number of arguments");
2462
2463 if ( PG_NARGS() == 4 )
2464 {
2465 only_parent = PG_GETARG_BOOL(3);
2466 }
2467 if ( PG_NARGS() >= 3 )
2468 {
2469 char *nsp = text_to_cstring(PG_GETARG_TEXT_P(0));
2470 tbl = text_to_cstring(PG_GETARG_TEXT_P(1));
2471 coltxt = PG_GETARG_TEXT_P(2);
2472 snprintf(nsp_tbl, sizeof(nsp_tbl), "\"%s\".\"%s\"", nsp, tbl);
2473 }
2474 if ( PG_NARGS() == 2 )
2475 {
2476 tbl = text_to_cstring(PG_GETARG_TEXT_P(0));
2477 coltxt = PG_GETARG_TEXT_P(1);
2478 snprintf(nsp_tbl, sizeof(nsp_tbl), "\"%s\"", tbl);
2479 }
2480
2481 /* Parse the namespace/table strings and lookup in system catalogs */
2482 tbl_oid = DatumGetObjectId(DirectFunctionCall1(regclassin, CStringGetDatum(nsp_tbl)));
2483 if (!tbl_oid)
2484 elog(ERROR, "cannot lookup table %s", nsp_tbl);
2485
2486 /* Get the attribute number and type from the column name */
2487 col = text_to_cstring(coltxt);
2488 if (!get_attnum_attypid(tbl_oid, col, &attnum, &atttypid))
2489 elog(ERROR, "column %s.\"%s\" does not exist", nsp_tbl, col);
2490
2491 /* We can only do estimates on geograpy and geometry */
2492 if ((atttypid != geographyOid) && (atttypid != geometryOid))
2493 {
2494 elog(ERROR, "column %s.\"%s\" must be a geometry or geography", nsp_tbl, col);
2495 }
2496
2497 /* Read the extent from the head of the spatial index */
2498 /* works if there is a spatial index */
2499 idx_oid = table_get_spatial_index(tbl_oid, attnum, &key_type, &idx_attnum);
2500 if (idx_oid != InvalidOid)
2501 {
2502 /* TODO: how about only_parent ? */
2503 gbox = spatial_index_read_extent(idx_oid, idx_attnum, key_type);
2504 elog(DEBUG3, "index for %s.\"%s\" exists, reading gbox from there", nsp_tbl, col);
2505 if (!gbox) PG_RETURN_NULL();
2506 }
2507 /* Read the extent from the stats tables, */
2508 /* works if ANALYZE has been run */
2509 else
2510 {
2511 int stats_mode = 2;
2512 elog(DEBUG3, "index for %s.\"%s\" does not exist", nsp_tbl, col);
2513
2514 /* For a geography column, we need the XYZ geocentric bounds */
2515 if (atttypid == geographyOid)
2516 stats_mode = 3;
2517
2518 /* ND stats include an extent for the histogram */
2519 nd_stats = pg_get_nd_stats_by_name(tbl_oid, coltxt, stats_mode, only_parent);
2520
2521 /* Error out on no stats */
2522 if (!nd_stats)
2523 {
2524 elog(WARNING, "stats for \"%s.%s\" do not exist", tbl, col);
2525 PG_RETURN_NULL();
2526 }
2527
2528 /* Construct the box */
2529 gbox = gbox_new(0);
2530 gbox->xmin = nd_stats->extent.min[0];
2531 gbox->xmax = nd_stats->extent.max[0];
2532 gbox->ymin = nd_stats->extent.min[1];
2533 gbox->ymax = nd_stats->extent.max[1];
2534 if (stats_mode != 2)
2535 {
2536 FLAGS_SET_Z(gbox->flags, 1);
2537 gbox->zmin = nd_stats->extent.min[2];
2538 gbox->zmax = nd_stats->extent.max[2];
2539 }
2540
2541 pfree(nd_stats);
2542 }
2543
2544 /* Convert geocentric geography box into a planar box */
2545 /* that users understand */
2546 if (atttypid == geographyOid)
2547 {
2548 GBOX *gbox_planar = gbox_new(0);
2549 gbox_geocentric_get_gbox_cartesian(gbox, gbox_planar);
2550 PG_RETURN_POINTER(gbox_planar);
2551 }
2552 else
2553 PG_RETURN_POINTER(gbox);
2554}
GBOX * gbox_new(lwflags_t flags)
Create a new gbox with the dimensionality indicated by the flags.
Definition gbox.c:32
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)
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.
#define FLAGS_SET_Z(flags, value)
Definition liblwgeom.h:172
int gbox_geocentric_get_gbox_cartesian(const GBOX *gbox_geocentric, GBOX *gbox_planar)
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

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: