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

◆ gserialized_estimated_extent()

Datum gserialized_estimated_extent ( PG_FUNCTION_ARGS  )

Definition at line 2445 of file gserialized_estimate.c.

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