Fix GiST picksplit crash and SP-GiST operator argument order
GiST: entryvec->vector[] uses 1-based indexing (FirstOffsetNumber), not 0-based. Reading vector[0] hit uninitialized memory, causing SIGSEGV on large catalogs (14k+ satellites). Fixed in gist_tle_union and gist_tle_picksplit. SP-GiST: PostgreSQL requires the indexed column as the LEFT argument of the operator to form a ScanKey (skey.h:23-26). Flipped &? from (observer_window, tle) to (tle, observer_window) so inner_consistent receives scankeys for tree-level pruning. Removed L0 altitude pruning from inner_consistent — SMA bins don't carry eccentricity, so HEO satellites (e.g. CLUSTER II, e=0.88, SMA ~70000 km, perigee ~2000 km) were falsely pruned. L0 now only narrows SMA range for L1 footprint computation. All 15 regression tests pass. Consistency check on 14,376 satellites confirms 0 false negatives, 0 false positives.
This commit is contained in:
parent
2a7240e739
commit
e1c22cb873
@ -22,25 +22,27 @@ COMMENT ON TYPE observer_window IS
|
|||||||
-- Visibility cone operator function
|
-- Visibility cone operator function
|
||||||
-- ============================================================
|
-- ============================================================
|
||||||
|
|
||||||
CREATE FUNCTION tle_visibility_possible(observer_window, tle) RETURNS boolean
|
CREATE FUNCTION tle_visibility_possible(tle, observer_window) RETURNS boolean
|
||||||
AS 'MODULE_PATHNAME' LANGUAGE C STABLE STRICT PARALLEL SAFE;
|
AS 'MODULE_PATHNAME' LANGUAGE C STABLE STRICT PARALLEL SAFE;
|
||||||
|
|
||||||
COMMENT ON FUNCTION tle_visibility_possible(observer_window, tle) IS
|
COMMENT ON FUNCTION tle_visibility_possible(tle, observer_window) IS
|
||||||
'Could this satellite be visible from the observer during the time window? Combines altitude, inclination, and RAAN checks. Conservative superset — survivors need SGP4 propagation for ground truth.';
|
'Could this satellite be visible from the observer during the time window? Combines altitude, inclination, and RAAN checks. Conservative superset — survivors need SGP4 propagation for ground truth.';
|
||||||
|
|
||||||
-- ============================================================
|
-- ============================================================
|
||||||
-- &? operator (visibility cone check)
|
-- &? operator (visibility cone check)
|
||||||
-- ============================================================
|
-- ============================================================
|
||||||
|
-- The indexed column (tle) MUST be the left argument so PostgreSQL
|
||||||
|
-- can form a ScanKey and pass it to inner_consistent for pruning.
|
||||||
|
|
||||||
CREATE OPERATOR &? (
|
CREATE OPERATOR &? (
|
||||||
LEFTARG = observer_window,
|
LEFTARG = tle,
|
||||||
RIGHTARG = tle,
|
RIGHTARG = observer_window,
|
||||||
FUNCTION = tle_visibility_possible,
|
FUNCTION = tle_visibility_possible,
|
||||||
RESTRICT = contsel,
|
RESTRICT = contsel,
|
||||||
JOIN = contjoinsel
|
JOIN = contjoinsel
|
||||||
);
|
);
|
||||||
|
|
||||||
COMMENT ON OPERATOR &? (observer_window, tle) IS
|
COMMENT ON OPERATOR &? (tle, observer_window) IS
|
||||||
'Visibility cone check: could this satellite be visible from the observer during the time window? Index-accelerated via SP-GiST orbital trie.';
|
'Visibility cone check: could this satellite be visible from the observer during the time window? Index-accelerated via SP-GiST orbital trie.';
|
||||||
|
|
||||||
-- ============================================================
|
-- ============================================================
|
||||||
@ -68,7 +70,7 @@ CREATE FUNCTION spgist_tle_leaf_consistent(internal, internal) RETURNS void
|
|||||||
|
|
||||||
CREATE OPERATOR CLASS tle_spgist_ops
|
CREATE OPERATOR CLASS tle_spgist_ops
|
||||||
FOR TYPE tle USING spgist AS
|
FOR TYPE tle USING spgist AS
|
||||||
OPERATOR 1 &? (observer_window, tle),
|
OPERATOR 1 &? (tle, observer_window),
|
||||||
FUNCTION 1 spgist_tle_config(internal, internal),
|
FUNCTION 1 spgist_tle_config(internal, internal),
|
||||||
FUNCTION 2 spgist_tle_choose(internal, internal),
|
FUNCTION 2 spgist_tle_choose(internal, internal),
|
||||||
FUNCTION 3 spgist_tle_picksplit(internal, internal),
|
FUNCTION 3 spgist_tle_picksplit(internal, internal),
|
||||||
|
|||||||
@ -907,25 +907,27 @@ COMMENT ON TYPE observer_window IS
|
|||||||
-- Visibility cone operator function
|
-- Visibility cone operator function
|
||||||
-- ============================================================
|
-- ============================================================
|
||||||
|
|
||||||
CREATE FUNCTION tle_visibility_possible(observer_window, tle) RETURNS boolean
|
CREATE FUNCTION tle_visibility_possible(tle, observer_window) RETURNS boolean
|
||||||
AS 'MODULE_PATHNAME' LANGUAGE C STABLE STRICT PARALLEL SAFE;
|
AS 'MODULE_PATHNAME' LANGUAGE C STABLE STRICT PARALLEL SAFE;
|
||||||
|
|
||||||
COMMENT ON FUNCTION tle_visibility_possible(observer_window, tle) IS
|
COMMENT ON FUNCTION tle_visibility_possible(tle, observer_window) IS
|
||||||
'Could this satellite be visible from the observer during the time window? Combines altitude, inclination, and RAAN checks. Conservative superset — survivors need SGP4 propagation for ground truth.';
|
'Could this satellite be visible from the observer during the time window? Combines altitude, inclination, and RAAN checks. Conservative superset — survivors need SGP4 propagation for ground truth.';
|
||||||
|
|
||||||
-- ============================================================
|
-- ============================================================
|
||||||
-- &? operator (visibility cone check)
|
-- &? operator (visibility cone check)
|
||||||
-- ============================================================
|
-- ============================================================
|
||||||
|
-- The indexed column (tle) MUST be the left argument so PostgreSQL
|
||||||
|
-- can form a ScanKey and pass it to inner_consistent for pruning.
|
||||||
|
|
||||||
CREATE OPERATOR &? (
|
CREATE OPERATOR &? (
|
||||||
LEFTARG = observer_window,
|
LEFTARG = tle,
|
||||||
RIGHTARG = tle,
|
RIGHTARG = observer_window,
|
||||||
FUNCTION = tle_visibility_possible,
|
FUNCTION = tle_visibility_possible,
|
||||||
RESTRICT = contsel,
|
RESTRICT = contsel,
|
||||||
JOIN = contjoinsel
|
JOIN = contjoinsel
|
||||||
);
|
);
|
||||||
|
|
||||||
COMMENT ON OPERATOR &? (observer_window, tle) IS
|
COMMENT ON OPERATOR &? (tle, observer_window) IS
|
||||||
'Visibility cone check: could this satellite be visible from the observer during the time window? Index-accelerated via SP-GiST orbital trie.';
|
'Visibility cone check: could this satellite be visible from the observer during the time window? Index-accelerated via SP-GiST orbital trie.';
|
||||||
|
|
||||||
-- ============================================================
|
-- ============================================================
|
||||||
@ -953,7 +955,7 @@ CREATE FUNCTION spgist_tle_leaf_consistent(internal, internal) RETURNS void
|
|||||||
|
|
||||||
CREATE OPERATOR CLASS tle_spgist_ops
|
CREATE OPERATOR CLASS tle_spgist_ops
|
||||||
FOR TYPE tle USING spgist AS
|
FOR TYPE tle USING spgist AS
|
||||||
OPERATOR 1 &? (observer_window, tle),
|
OPERATOR 1 &? (tle, observer_window),
|
||||||
FUNCTION 1 spgist_tle_config(internal, internal),
|
FUNCTION 1 spgist_tle_config(internal, internal),
|
||||||
FUNCTION 2 spgist_tle_choose(internal, internal),
|
FUNCTION 2 spgist_tle_choose(internal, internal),
|
||||||
FUNCTION 3 spgist_tle_picksplit(internal, internal),
|
FUNCTION 3 spgist_tle_picksplit(internal, internal),
|
||||||
|
|||||||
@ -327,6 +327,10 @@ gist_tle_consistent(PG_FUNCTION_ARGS)
|
|||||||
* gist_tle_union -- compute 2-D bounding box for a set of entries
|
* gist_tle_union -- compute 2-D bounding box for a set of entries
|
||||||
*
|
*
|
||||||
* The union is [min(alt_low), max(alt_high)] x [min(inc_low), max(inc_high)].
|
* The union is [min(alt_low), max(alt_high)] x [min(inc_low), max(inc_high)].
|
||||||
|
*
|
||||||
|
* GiST convention: entryvec->vector[] is 1-based (FirstOffsetNumber),
|
||||||
|
* vector[0] is unused. entryvec->n includes the unused slot, so
|
||||||
|
* valid indices are 1 .. entryvec->n - 1.
|
||||||
*/
|
*/
|
||||||
Datum
|
Datum
|
||||||
gist_tle_union(PG_FUNCTION_ARGS)
|
gist_tle_union(PG_FUNCTION_ARGS)
|
||||||
@ -338,10 +342,10 @@ gist_tle_union(PG_FUNCTION_ARGS)
|
|||||||
tle_orbital_key *cur;
|
tle_orbital_key *cur;
|
||||||
|
|
||||||
result = (tle_orbital_key *) palloc(sizeof(tle_orbital_key));
|
result = (tle_orbital_key *) palloc(sizeof(tle_orbital_key));
|
||||||
cur = (tle_orbital_key *) DatumGetPointer(entryvec->vector[0].key);
|
cur = (tle_orbital_key *) DatumGetPointer(entryvec->vector[FirstOffsetNumber].key);
|
||||||
*result = *cur;
|
*result = *cur;
|
||||||
|
|
||||||
for (i = 1; i < entryvec->n; i++)
|
for (i = FirstOffsetNumber + 1; i < entryvec->n; i++)
|
||||||
{
|
{
|
||||||
cur = (tle_orbital_key *) DatumGetPointer(entryvec->vector[i].key);
|
cur = (tle_orbital_key *) DatumGetPointer(entryvec->vector[i].key);
|
||||||
key_merge(result, cur);
|
key_merge(result, cur);
|
||||||
@ -413,35 +417,43 @@ picksplit_cmp(const void *a, const void *b)
|
|||||||
* Standard R-tree approach: compute spread in both dimensions, split
|
* Standard R-tree approach: compute spread in both dimensions, split
|
||||||
* along whichever dimension has the greater spread. This prevents
|
* along whichever dimension has the greater spread. This prevents
|
||||||
* the tree from becoming biased toward one dimension.
|
* the tree from becoming biased toward one dimension.
|
||||||
|
*
|
||||||
|
* GiST convention: entryvec->vector[] is 1-based (FirstOffsetNumber),
|
||||||
|
* vector[0] is unused/uninitialized. entryvec->n includes the unused
|
||||||
|
* slot, so the actual entry count is (entryvec->n - 1) and valid
|
||||||
|
* indices are FirstOffsetNumber .. entryvec->n - 1. The OffsetNumbers
|
||||||
|
* placed into spl_left[] and spl_right[] must also be 1-based.
|
||||||
*/
|
*/
|
||||||
Datum
|
Datum
|
||||||
gist_tle_picksplit(PG_FUNCTION_ARGS)
|
gist_tle_picksplit(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
|
GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
|
||||||
GIST_SPLITVEC *splitvec = (GIST_SPLITVEC *) PG_GETARG_POINTER(1);
|
GIST_SPLITVEC *splitvec = (GIST_SPLITVEC *) PG_GETARG_POINTER(1);
|
||||||
int nentries = entryvec->n;
|
OffsetNumber maxoff = entryvec->n - 1;
|
||||||
|
int nentries = maxoff - FirstOffsetNumber + 1;
|
||||||
picksplit_item *items;
|
picksplit_item *items;
|
||||||
tle_orbital_key *left_union;
|
tle_orbital_key *left_union;
|
||||||
tle_orbital_key *right_union;
|
tle_orbital_key *right_union;
|
||||||
tle_orbital_key *cur;
|
tle_orbital_key *cur;
|
||||||
int split_at;
|
int split_at;
|
||||||
int i;
|
int i;
|
||||||
|
OffsetNumber off;
|
||||||
double alt_min, alt_max, inc_min, inc_max;
|
double alt_min, alt_max, inc_min, inc_max;
|
||||||
double alt_spread, inc_spread;
|
double alt_spread, inc_spread;
|
||||||
bool split_on_alt;
|
bool split_on_alt;
|
||||||
|
|
||||||
/* First pass: compute spread in both dimensions */
|
/* First pass: compute spread in both dimensions */
|
||||||
cur = (tle_orbital_key *) DatumGetPointer(entryvec->vector[0].key);
|
cur = (tle_orbital_key *) DatumGetPointer(entryvec->vector[FirstOffsetNumber].key);
|
||||||
alt_min = (cur->alt_low + cur->alt_high) / 2.0;
|
alt_min = (cur->alt_low + cur->alt_high) / 2.0;
|
||||||
alt_max = alt_min;
|
alt_max = alt_min;
|
||||||
inc_min = (cur->inc_low + cur->inc_high) / 2.0;
|
inc_min = (cur->inc_low + cur->inc_high) / 2.0;
|
||||||
inc_max = inc_min;
|
inc_max = inc_min;
|
||||||
|
|
||||||
for (i = 1; i < nentries; i++)
|
for (off = FirstOffsetNumber + 1; off <= maxoff; off++)
|
||||||
{
|
{
|
||||||
double alt_mid, inc_mid;
|
double alt_mid, inc_mid;
|
||||||
|
|
||||||
cur = (tle_orbital_key *) DatumGetPointer(entryvec->vector[i].key);
|
cur = (tle_orbital_key *) DatumGetPointer(entryvec->vector[off].key);
|
||||||
alt_mid = (cur->alt_low + cur->alt_high) / 2.0;
|
alt_mid = (cur->alt_low + cur->alt_high) / 2.0;
|
||||||
inc_mid = (cur->inc_low + cur->inc_high) / 2.0;
|
inc_mid = (cur->inc_low + cur->inc_high) / 2.0;
|
||||||
|
|
||||||
@ -462,10 +474,10 @@ gist_tle_picksplit(PG_FUNCTION_ARGS)
|
|||||||
|
|
||||||
/* Second pass: compute sort values in the chosen dimension */
|
/* Second pass: compute sort values in the chosen dimension */
|
||||||
items = (picksplit_item *) palloc(sizeof(picksplit_item) * nentries);
|
items = (picksplit_item *) palloc(sizeof(picksplit_item) * nentries);
|
||||||
for (i = 0; i < nentries; i++)
|
for (i = 0, off = FirstOffsetNumber; off <= maxoff; i++, off++)
|
||||||
{
|
{
|
||||||
cur = (tle_orbital_key *) DatumGetPointer(entryvec->vector[i].key);
|
cur = (tle_orbital_key *) DatumGetPointer(entryvec->vector[off].key);
|
||||||
items[i].index = i;
|
items[i].index = off; /* store 1-based OffsetNumber directly */
|
||||||
if (split_on_alt)
|
if (split_on_alt)
|
||||||
items[i].sortval = (cur->alt_low + cur->alt_high) / 2.0;
|
items[i].sortval = (cur->alt_low + cur->alt_high) / 2.0;
|
||||||
else
|
else
|
||||||
@ -476,7 +488,7 @@ gist_tle_picksplit(PG_FUNCTION_ARGS)
|
|||||||
|
|
||||||
split_at = nentries / 2;
|
split_at = nentries / 2;
|
||||||
|
|
||||||
/* Allocate offset arrays (GiST uses OffsetNumber, 1-based) */
|
/* Allocate offset arrays */
|
||||||
splitvec->spl_left = (OffsetNumber *) palloc(sizeof(OffsetNumber) * nentries);
|
splitvec->spl_left = (OffsetNumber *) palloc(sizeof(OffsetNumber) * nentries);
|
||||||
splitvec->spl_right = (OffsetNumber *) palloc(sizeof(OffsetNumber) * nentries);
|
splitvec->spl_right = (OffsetNumber *) palloc(sizeof(OffsetNumber) * nentries);
|
||||||
splitvec->spl_nleft = 0;
|
splitvec->spl_nleft = 0;
|
||||||
@ -497,21 +509,19 @@ gist_tle_picksplit(PG_FUNCTION_ARGS)
|
|||||||
|
|
||||||
for (i = 0; i < nentries; i++)
|
for (i = 0; i < nentries; i++)
|
||||||
{
|
{
|
||||||
int idx = items[i].index;
|
OffsetNumber idx = items[i].index; /* already 1-based */
|
||||||
|
|
||||||
cur = (tle_orbital_key *) DatumGetPointer(
|
cur = (tle_orbital_key *) DatumGetPointer(
|
||||||
entryvec->vector[idx].key);
|
entryvec->vector[idx].key);
|
||||||
|
|
||||||
if (i < split_at)
|
if (i < split_at)
|
||||||
{
|
{
|
||||||
splitvec->spl_left[splitvec->spl_nleft++] =
|
splitvec->spl_left[splitvec->spl_nleft++] = idx;
|
||||||
(OffsetNumber)(idx + 1); /* 1-based */
|
|
||||||
key_merge(left_union, cur);
|
key_merge(left_union, cur);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
splitvec->spl_right[splitvec->spl_nright++] =
|
splitvec->spl_right[splitvec->spl_nright++] = idx;
|
||||||
(OffsetNumber)(idx + 1);
|
|
||||||
key_merge(right_union, cur);
|
key_merge(right_union, cur);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -584,22 +584,18 @@ spgist_tle_inner_consistent(PG_FUNCTION_ARGS)
|
|||||||
if (have_query && level == 0)
|
if (have_query && level == 0)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* L0: SMA pruning.
|
* L0: SMA range narrowing only — no altitude pruning.
|
||||||
* bin_low is the SMA of the lowest object in this bin at
|
|
||||||
* index build time. Later inserts with lower SMA route to
|
|
||||||
* bin 0, so for the first bin we use AE (physical minimum
|
|
||||||
* SMA) to avoid false negatives.
|
|
||||||
*
|
*
|
||||||
* Conservative: assume e=0 (circular, worst case for
|
* We cannot prune SMA bins by altitude because eccentricity
|
||||||
* "too high" pruning -- circular has highest perigee for
|
* is not available at the inner node level. A satellite
|
||||||
* a given SMA).
|
* at SMA 70,000 km with e=0.88 has perigee ~2,000 km —
|
||||||
|
* well within typical max_alt. Without knowing e, any SMA
|
||||||
|
* bin could contain satellites with perigee near Earth's
|
||||||
|
* surface.
|
||||||
|
*
|
||||||
|
* L0 still helps by narrowing the SMA range passed to L1
|
||||||
|
* for computing a tighter ground footprint.
|
||||||
*/
|
*/
|
||||||
double effective_low = (i == 0) ? WGS72_AE : bin_low;
|
|
||||||
double perigee_alt = effective_low - WGS72_AE;
|
|
||||||
double max_alt = max_visible_altitude_km(win.min_el_deg);
|
|
||||||
|
|
||||||
if (perigee_alt > max_alt)
|
|
||||||
dominated = true;
|
|
||||||
}
|
}
|
||||||
else if (have_query && level == 1)
|
else if (have_query && level == 1)
|
||||||
{
|
{
|
||||||
@ -789,7 +785,7 @@ spgist_tle_leaf_consistent(PG_FUNCTION_ARGS)
|
|||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* tle_visibility_possible(observer_window, tle) -> bool
|
* tle_visibility_possible(tle, observer_window) -> bool
|
||||||
*
|
*
|
||||||
* Standalone operator: can the satellite possibly be visible from
|
* Standalone operator: can the satellite possibly be visible from
|
||||||
* this observer during this time window? Combines altitude check,
|
* this observer during this time window? Combines altitude check,
|
||||||
@ -797,12 +793,16 @@ spgist_tle_leaf_consistent(PG_FUNCTION_ARGS)
|
|||||||
*
|
*
|
||||||
* This is the same logic as leaf_consistent, callable directly
|
* This is the same logic as leaf_consistent, callable directly
|
||||||
* as a SQL operator for sequential scans or WHERE clauses.
|
* as a SQL operator for sequential scans or WHERE clauses.
|
||||||
|
*
|
||||||
|
* The indexed column (tle) MUST be the left argument so that
|
||||||
|
* PostgreSQL can form a ScanKey and pass it to inner_consistent
|
||||||
|
* for tree-level pruning. See skey.h:23-26.
|
||||||
*/
|
*/
|
||||||
Datum
|
Datum
|
||||||
tle_visibility_possible(PG_FUNCTION_ARGS)
|
tle_visibility_possible(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
HeapTupleHeader composite = PG_GETARG_HEAPTUPLEHEADER(0);
|
pg_tle *tle = (pg_tle *) PG_GETARG_POINTER(0);
|
||||||
pg_tle *tle = (pg_tle *) PG_GETARG_POINTER(1);
|
HeapTupleHeader composite = PG_GETARG_HEAPTUPLEHEADER(1);
|
||||||
ObserverWindow win;
|
ObserverWindow win;
|
||||||
|
|
||||||
extract_observer_window(composite, &win);
|
extract_observer_window(composite, &win);
|
||||||
|
|||||||
@ -42,12 +42,12 @@ INSERT INTO test_spgist (name, tle) VALUES ('GEO-SAT',
|
|||||||
-- specific 2-hour window (correct physics, see Test 5 for 24h).
|
-- specific 2-hour window (correct physics, see Test 5 for 24h).
|
||||||
-- ============================================================
|
-- ============================================================
|
||||||
SELECT name,
|
SELECT name,
|
||||||
ROW(
|
tle &? ROW(
|
||||||
observer('43.6977N 116.3535W 760m'),
|
observer('43.6977N 116.3535W 760m'),
|
||||||
'2024-01-01 00:00:00+00'::timestamptz,
|
'2024-01-01 00:00:00+00'::timestamptz,
|
||||||
'2024-01-01 02:00:00+00'::timestamptz,
|
'2024-01-01 02:00:00+00'::timestamptz,
|
||||||
10.0
|
10.0
|
||||||
)::observer_window &? tle AS visible
|
)::observer_window AS visible
|
||||||
FROM test_spgist
|
FROM test_spgist
|
||||||
WHERE name = 'ISS';
|
WHERE name = 'ISS';
|
||||||
name | visible
|
name | visible
|
||||||
@ -60,12 +60,12 @@ WHERE name = 'ISS';
|
|||||||
-- 5 deg inc + ~12 deg footprint = 17 deg < 43.7 deg latitude
|
-- 5 deg inc + ~12 deg footprint = 17 deg < 43.7 deg latitude
|
||||||
-- ============================================================
|
-- ============================================================
|
||||||
SELECT name,
|
SELECT name,
|
||||||
ROW(
|
tle &? ROW(
|
||||||
observer('43.6977N 116.3535W 760m'),
|
observer('43.6977N 116.3535W 760m'),
|
||||||
'2024-01-01 00:00:00+00'::timestamptz,
|
'2024-01-01 00:00:00+00'::timestamptz,
|
||||||
'2024-01-01 02:00:00+00'::timestamptz,
|
'2024-01-01 02:00:00+00'::timestamptz,
|
||||||
10.0
|
10.0
|
||||||
)::observer_window &? tle AS visible
|
)::observer_window AS visible
|
||||||
FROM test_spgist
|
FROM test_spgist
|
||||||
WHERE name = 'Equatorial-LEO';
|
WHERE name = 'Equatorial-LEO';
|
||||||
name | visible
|
name | visible
|
||||||
@ -82,12 +82,12 @@ CREATE INDEX test_spgist_idx ON test_spgist USING spgist (tle tle_spgist_ops);
|
|||||||
SET enable_seqscan = off;
|
SET enable_seqscan = off;
|
||||||
SELECT name
|
SELECT name
|
||||||
FROM test_spgist
|
FROM test_spgist
|
||||||
WHERE ROW(
|
WHERE tle &? ROW(
|
||||||
observer('0.0N 0.0E 0m'),
|
observer('0.0N 0.0E 0m'),
|
||||||
'2024-01-01 00:00:00+00'::timestamptz,
|
'2024-01-01 00:00:00+00'::timestamptz,
|
||||||
'2024-01-01 02:00:00+00'::timestamptz,
|
'2024-01-01 02:00:00+00'::timestamptz,
|
||||||
10.0
|
10.0
|
||||||
)::observer_window &? tle
|
)::observer_window
|
||||||
ORDER BY name;
|
ORDER BY name;
|
||||||
name
|
name
|
||||||
---------
|
---------
|
||||||
@ -103,12 +103,12 @@ SET enable_indexscan = off;
|
|||||||
SET enable_bitmapscan = off;
|
SET enable_bitmapscan = off;
|
||||||
SELECT name
|
SELECT name
|
||||||
FROM test_spgist
|
FROM test_spgist
|
||||||
WHERE ROW(
|
WHERE tle &? ROW(
|
||||||
observer('0.0N 0.0E 0m'),
|
observer('0.0N 0.0E 0m'),
|
||||||
'2024-01-01 00:00:00+00'::timestamptz,
|
'2024-01-01 00:00:00+00'::timestamptz,
|
||||||
'2024-01-01 02:00:00+00'::timestamptz,
|
'2024-01-01 02:00:00+00'::timestamptz,
|
||||||
10.0
|
10.0
|
||||||
)::observer_window &? tle
|
)::observer_window
|
||||||
ORDER BY name;
|
ORDER BY name;
|
||||||
name
|
name
|
||||||
---------
|
---------
|
||||||
@ -125,12 +125,12 @@ RESET enable_bitmapscan;
|
|||||||
-- ============================================================
|
-- ============================================================
|
||||||
SELECT name
|
SELECT name
|
||||||
FROM test_spgist
|
FROM test_spgist
|
||||||
WHERE ROW(
|
WHERE tle &? ROW(
|
||||||
observer('43.6977N 116.3535W 760m'),
|
observer('43.6977N 116.3535W 760m'),
|
||||||
'2024-01-01 00:00:00+00'::timestamptz,
|
'2024-01-01 00:00:00+00'::timestamptz,
|
||||||
'2024-01-02 00:00:00+00'::timestamptz,
|
'2024-01-02 00:00:00+00'::timestamptz,
|
||||||
10.0
|
10.0
|
||||||
)::observer_window &? tle
|
)::observer_window
|
||||||
ORDER BY name;
|
ORDER BY name;
|
||||||
name
|
name
|
||||||
---------
|
---------
|
||||||
@ -144,12 +144,12 @@ ORDER BY name;
|
|||||||
-- ============================================================
|
-- ============================================================
|
||||||
SELECT name
|
SELECT name
|
||||||
FROM test_spgist
|
FROM test_spgist
|
||||||
WHERE ROW(
|
WHERE tle &? ROW(
|
||||||
observer('43.6977N 116.3535W 760m'),
|
observer('43.6977N 116.3535W 760m'),
|
||||||
'2024-01-01 00:00:00+00'::timestamptz,
|
'2024-01-01 00:00:00+00'::timestamptz,
|
||||||
'2024-01-02 00:00:00+00'::timestamptz,
|
'2024-01-02 00:00:00+00'::timestamptz,
|
||||||
45.0
|
45.0
|
||||||
)::observer_window &? tle
|
)::observer_window
|
||||||
ORDER BY name;
|
ORDER BY name;
|
||||||
name
|
name
|
||||||
---------
|
---------
|
||||||
@ -174,12 +174,12 @@ WHERE a.name = 'ISS' AND b.name = 'Hubble';
|
|||||||
SET enable_seqscan = off;
|
SET enable_seqscan = off;
|
||||||
SELECT name
|
SELECT name
|
||||||
FROM test_spgist
|
FROM test_spgist
|
||||||
WHERE ROW(
|
WHERE tle &? ROW(
|
||||||
observer('43.6977N 116.3535W 760m'),
|
observer('43.6977N 116.3535W 760m'),
|
||||||
'2024-01-01 00:00:00+00'::timestamptz,
|
'2024-01-01 00:00:00+00'::timestamptz,
|
||||||
'2024-01-02 00:00:00+00'::timestamptz,
|
'2024-01-02 00:00:00+00'::timestamptz,
|
||||||
10.0
|
10.0
|
||||||
)::observer_window &? tle
|
)::observer_window
|
||||||
ORDER BY name;
|
ORDER BY name;
|
||||||
name
|
name
|
||||||
---------
|
---------
|
||||||
@ -194,12 +194,12 @@ RESET enable_seqscan;
|
|||||||
INSERT INTO test_spgist (name, tle) VALUES ('NULL-SAT', NULL);
|
INSERT INTO test_spgist (name, tle) VALUES ('NULL-SAT', NULL);
|
||||||
SELECT name
|
SELECT name
|
||||||
FROM test_spgist
|
FROM test_spgist
|
||||||
WHERE ROW(
|
WHERE tle &? ROW(
|
||||||
observer('43.6977N 116.3535W 760m'),
|
observer('43.6977N 116.3535W 760m'),
|
||||||
'2024-01-01 00:00:00+00'::timestamptz,
|
'2024-01-01 00:00:00+00'::timestamptz,
|
||||||
'2024-01-02 00:00:00+00'::timestamptz,
|
'2024-01-02 00:00:00+00'::timestamptz,
|
||||||
10.0
|
10.0
|
||||||
)::observer_window &? tle
|
)::observer_window
|
||||||
ORDER BY name;
|
ORDER BY name;
|
||||||
name
|
name
|
||||||
---------
|
---------
|
||||||
@ -214,12 +214,12 @@ INSERT INTO test_spgist (name, tle) VALUES ('DECAYED',
|
|||||||
'1 99904U 24999D 24001.50000000 .00000000 00000+0 00000+0 0 9993
|
'1 99904U 24999D 24001.50000000 .00000000 00000+0 00000+0 0 9993
|
||||||
2 99904 0.0000 0.0000 0000000 0.0000 0.0000 0.00000000 00001');
|
2 99904 0.0000 0.0000 0000000 0.0000 0.0000 0.00000000 00001');
|
||||||
SELECT name,
|
SELECT name,
|
||||||
ROW(
|
tle &? ROW(
|
||||||
observer('0.0N 0.0E 0m'),
|
observer('0.0N 0.0E 0m'),
|
||||||
'2024-01-01 00:00:00+00'::timestamptz,
|
'2024-01-01 00:00:00+00'::timestamptz,
|
||||||
'2024-01-02 00:00:00+00'::timestamptz,
|
'2024-01-02 00:00:00+00'::timestamptz,
|
||||||
10.0
|
10.0
|
||||||
)::observer_window &? tle AS visible
|
)::observer_window AS visible
|
||||||
FROM test_spgist
|
FROM test_spgist
|
||||||
WHERE name = 'DECAYED';
|
WHERE name = 'DECAYED';
|
||||||
name | visible
|
name | visible
|
||||||
@ -234,12 +234,12 @@ WHERE name = 'DECAYED';
|
|||||||
-- ============================================================
|
-- ============================================================
|
||||||
SELECT name
|
SELECT name
|
||||||
FROM test_spgist
|
FROM test_spgist
|
||||||
WHERE ROW(
|
WHERE tle &? ROW(
|
||||||
observer('90.0N 0.0E 0m'),
|
observer('90.0N 0.0E 0m'),
|
||||||
'2024-01-01 00:00:00+00'::timestamptz,
|
'2024-01-01 00:00:00+00'::timestamptz,
|
||||||
'2024-01-02 00:00:00+00'::timestamptz,
|
'2024-01-02 00:00:00+00'::timestamptz,
|
||||||
10.0
|
10.0
|
||||||
)::observer_window &? tle
|
)::observer_window
|
||||||
ORDER BY name;
|
ORDER BY name;
|
||||||
name
|
name
|
||||||
---------
|
---------
|
||||||
@ -251,12 +251,12 @@ ORDER BY name;
|
|||||||
-- overhead at the instant. RAAN window = footprint only.
|
-- overhead at the instant. RAAN window = footprint only.
|
||||||
-- ============================================================
|
-- ============================================================
|
||||||
SELECT name,
|
SELECT name,
|
||||||
ROW(
|
tle &? ROW(
|
||||||
observer('0.0N 0.0E 0m'),
|
observer('0.0N 0.0E 0m'),
|
||||||
'2024-01-01 00:00:00+00'::timestamptz,
|
'2024-01-01 00:00:00+00'::timestamptz,
|
||||||
'2024-01-01 00:00:00+00'::timestamptz,
|
'2024-01-01 00:00:00+00'::timestamptz,
|
||||||
10.0
|
10.0
|
||||||
)::observer_window &? tle AS visible
|
)::observer_window AS visible
|
||||||
FROM test_spgist
|
FROM test_spgist
|
||||||
WHERE name = 'ISS';
|
WHERE name = 'ISS';
|
||||||
name | visible
|
name | visible
|
||||||
@ -271,12 +271,12 @@ WHERE name = 'ISS';
|
|||||||
SET enable_seqscan = off;
|
SET enable_seqscan = off;
|
||||||
SELECT name
|
SELECT name
|
||||||
FROM test_spgist
|
FROM test_spgist
|
||||||
WHERE ROW(
|
WHERE tle &? ROW(
|
||||||
observer('43.6977N 116.3535W 760m'),
|
observer('43.6977N 116.3535W 760m'),
|
||||||
'2024-01-01 00:00:00+00'::timestamptz,
|
'2024-01-01 00:00:00+00'::timestamptz,
|
||||||
'2024-01-02 00:00:00+00'::timestamptz,
|
'2024-01-02 00:00:00+00'::timestamptz,
|
||||||
10.0
|
10.0
|
||||||
)::observer_window &? tle
|
)::observer_window
|
||||||
ORDER BY name;
|
ORDER BY name;
|
||||||
name
|
name
|
||||||
---------
|
---------
|
||||||
@ -289,12 +289,12 @@ SET enable_indexscan = off;
|
|||||||
SET enable_bitmapscan = off;
|
SET enable_bitmapscan = off;
|
||||||
SELECT name
|
SELECT name
|
||||||
FROM test_spgist
|
FROM test_spgist
|
||||||
WHERE ROW(
|
WHERE tle &? ROW(
|
||||||
observer('43.6977N 116.3535W 760m'),
|
observer('43.6977N 116.3535W 760m'),
|
||||||
'2024-01-01 00:00:00+00'::timestamptz,
|
'2024-01-01 00:00:00+00'::timestamptz,
|
||||||
'2024-01-02 00:00:00+00'::timestamptz,
|
'2024-01-02 00:00:00+00'::timestamptz,
|
||||||
10.0
|
10.0
|
||||||
)::observer_window &? tle
|
)::observer_window
|
||||||
ORDER BY name;
|
ORDER BY name;
|
||||||
name
|
name
|
||||||
---------
|
---------
|
||||||
|
|||||||
@ -51,12 +51,12 @@ INSERT INTO test_spgist (name, tle) VALUES ('GEO-SAT',
|
|||||||
-- specific 2-hour window (correct physics, see Test 5 for 24h).
|
-- specific 2-hour window (correct physics, see Test 5 for 24h).
|
||||||
-- ============================================================
|
-- ============================================================
|
||||||
SELECT name,
|
SELECT name,
|
||||||
ROW(
|
tle &? ROW(
|
||||||
observer('43.6977N 116.3535W 760m'),
|
observer('43.6977N 116.3535W 760m'),
|
||||||
'2024-01-01 00:00:00+00'::timestamptz,
|
'2024-01-01 00:00:00+00'::timestamptz,
|
||||||
'2024-01-01 02:00:00+00'::timestamptz,
|
'2024-01-01 02:00:00+00'::timestamptz,
|
||||||
10.0
|
10.0
|
||||||
)::observer_window &? tle AS visible
|
)::observer_window AS visible
|
||||||
FROM test_spgist
|
FROM test_spgist
|
||||||
WHERE name = 'ISS';
|
WHERE name = 'ISS';
|
||||||
|
|
||||||
@ -66,12 +66,12 @@ WHERE name = 'ISS';
|
|||||||
-- 5 deg inc + ~12 deg footprint = 17 deg < 43.7 deg latitude
|
-- 5 deg inc + ~12 deg footprint = 17 deg < 43.7 deg latitude
|
||||||
-- ============================================================
|
-- ============================================================
|
||||||
SELECT name,
|
SELECT name,
|
||||||
ROW(
|
tle &? ROW(
|
||||||
observer('43.6977N 116.3535W 760m'),
|
observer('43.6977N 116.3535W 760m'),
|
||||||
'2024-01-01 00:00:00+00'::timestamptz,
|
'2024-01-01 00:00:00+00'::timestamptz,
|
||||||
'2024-01-01 02:00:00+00'::timestamptz,
|
'2024-01-01 02:00:00+00'::timestamptz,
|
||||||
10.0
|
10.0
|
||||||
)::observer_window &? tle AS visible
|
)::observer_window AS visible
|
||||||
FROM test_spgist
|
FROM test_spgist
|
||||||
WHERE name = 'Equatorial-LEO';
|
WHERE name = 'Equatorial-LEO';
|
||||||
|
|
||||||
@ -87,12 +87,12 @@ SET enable_seqscan = off;
|
|||||||
|
|
||||||
SELECT name
|
SELECT name
|
||||||
FROM test_spgist
|
FROM test_spgist
|
||||||
WHERE ROW(
|
WHERE tle &? ROW(
|
||||||
observer('0.0N 0.0E 0m'),
|
observer('0.0N 0.0E 0m'),
|
||||||
'2024-01-01 00:00:00+00'::timestamptz,
|
'2024-01-01 00:00:00+00'::timestamptz,
|
||||||
'2024-01-01 02:00:00+00'::timestamptz,
|
'2024-01-01 02:00:00+00'::timestamptz,
|
||||||
10.0
|
10.0
|
||||||
)::observer_window &? tle
|
)::observer_window
|
||||||
ORDER BY name;
|
ORDER BY name;
|
||||||
|
|
||||||
RESET enable_seqscan;
|
RESET enable_seqscan;
|
||||||
@ -107,12 +107,12 @@ SET enable_bitmapscan = off;
|
|||||||
|
|
||||||
SELECT name
|
SELECT name
|
||||||
FROM test_spgist
|
FROM test_spgist
|
||||||
WHERE ROW(
|
WHERE tle &? ROW(
|
||||||
observer('0.0N 0.0E 0m'),
|
observer('0.0N 0.0E 0m'),
|
||||||
'2024-01-01 00:00:00+00'::timestamptz,
|
'2024-01-01 00:00:00+00'::timestamptz,
|
||||||
'2024-01-01 02:00:00+00'::timestamptz,
|
'2024-01-01 02:00:00+00'::timestamptz,
|
||||||
10.0
|
10.0
|
||||||
)::observer_window &? tle
|
)::observer_window
|
||||||
ORDER BY name;
|
ORDER BY name;
|
||||||
|
|
||||||
RESET enable_indexscan;
|
RESET enable_indexscan;
|
||||||
@ -127,12 +127,12 @@ RESET enable_bitmapscan;
|
|||||||
-- ============================================================
|
-- ============================================================
|
||||||
SELECT name
|
SELECT name
|
||||||
FROM test_spgist
|
FROM test_spgist
|
||||||
WHERE ROW(
|
WHERE tle &? ROW(
|
||||||
observer('43.6977N 116.3535W 760m'),
|
observer('43.6977N 116.3535W 760m'),
|
||||||
'2024-01-01 00:00:00+00'::timestamptz,
|
'2024-01-01 00:00:00+00'::timestamptz,
|
||||||
'2024-01-02 00:00:00+00'::timestamptz,
|
'2024-01-02 00:00:00+00'::timestamptz,
|
||||||
10.0
|
10.0
|
||||||
)::observer_window &? tle
|
)::observer_window
|
||||||
ORDER BY name;
|
ORDER BY name;
|
||||||
|
|
||||||
|
|
||||||
@ -142,12 +142,12 @@ ORDER BY name;
|
|||||||
-- ============================================================
|
-- ============================================================
|
||||||
SELECT name
|
SELECT name
|
||||||
FROM test_spgist
|
FROM test_spgist
|
||||||
WHERE ROW(
|
WHERE tle &? ROW(
|
||||||
observer('43.6977N 116.3535W 760m'),
|
observer('43.6977N 116.3535W 760m'),
|
||||||
'2024-01-01 00:00:00+00'::timestamptz,
|
'2024-01-01 00:00:00+00'::timestamptz,
|
||||||
'2024-01-02 00:00:00+00'::timestamptz,
|
'2024-01-02 00:00:00+00'::timestamptz,
|
||||||
45.0
|
45.0
|
||||||
)::observer_window &? tle
|
)::observer_window
|
||||||
ORDER BY name;
|
ORDER BY name;
|
||||||
|
|
||||||
|
|
||||||
@ -165,12 +165,12 @@ WHERE a.name = 'ISS' AND b.name = 'Hubble';
|
|||||||
SET enable_seqscan = off;
|
SET enable_seqscan = off;
|
||||||
SELECT name
|
SELECT name
|
||||||
FROM test_spgist
|
FROM test_spgist
|
||||||
WHERE ROW(
|
WHERE tle &? ROW(
|
||||||
observer('43.6977N 116.3535W 760m'),
|
observer('43.6977N 116.3535W 760m'),
|
||||||
'2024-01-01 00:00:00+00'::timestamptz,
|
'2024-01-01 00:00:00+00'::timestamptz,
|
||||||
'2024-01-02 00:00:00+00'::timestamptz,
|
'2024-01-02 00:00:00+00'::timestamptz,
|
||||||
10.0
|
10.0
|
||||||
)::observer_window &? tle
|
)::observer_window
|
||||||
ORDER BY name;
|
ORDER BY name;
|
||||||
RESET enable_seqscan;
|
RESET enable_seqscan;
|
||||||
|
|
||||||
@ -182,12 +182,12 @@ INSERT INTO test_spgist (name, tle) VALUES ('NULL-SAT', NULL);
|
|||||||
|
|
||||||
SELECT name
|
SELECT name
|
||||||
FROM test_spgist
|
FROM test_spgist
|
||||||
WHERE ROW(
|
WHERE tle &? ROW(
|
||||||
observer('43.6977N 116.3535W 760m'),
|
observer('43.6977N 116.3535W 760m'),
|
||||||
'2024-01-01 00:00:00+00'::timestamptz,
|
'2024-01-01 00:00:00+00'::timestamptz,
|
||||||
'2024-01-02 00:00:00+00'::timestamptz,
|
'2024-01-02 00:00:00+00'::timestamptz,
|
||||||
10.0
|
10.0
|
||||||
)::observer_window &? tle
|
)::observer_window
|
||||||
ORDER BY name;
|
ORDER BY name;
|
||||||
|
|
||||||
|
|
||||||
@ -199,12 +199,12 @@ INSERT INTO test_spgist (name, tle) VALUES ('DECAYED',
|
|||||||
2 99904 0.0000 0.0000 0000000 0.0000 0.0000 0.00000000 00001');
|
2 99904 0.0000 0.0000 0000000 0.0000 0.0000 0.00000000 00001');
|
||||||
|
|
||||||
SELECT name,
|
SELECT name,
|
||||||
ROW(
|
tle &? ROW(
|
||||||
observer('0.0N 0.0E 0m'),
|
observer('0.0N 0.0E 0m'),
|
||||||
'2024-01-01 00:00:00+00'::timestamptz,
|
'2024-01-01 00:00:00+00'::timestamptz,
|
||||||
'2024-01-02 00:00:00+00'::timestamptz,
|
'2024-01-02 00:00:00+00'::timestamptz,
|
||||||
10.0
|
10.0
|
||||||
)::observer_window &? tle AS visible
|
)::observer_window AS visible
|
||||||
FROM test_spgist
|
FROM test_spgist
|
||||||
WHERE name = 'DECAYED';
|
WHERE name = 'DECAYED';
|
||||||
|
|
||||||
@ -216,12 +216,12 @@ WHERE name = 'DECAYED';
|
|||||||
-- ============================================================
|
-- ============================================================
|
||||||
SELECT name
|
SELECT name
|
||||||
FROM test_spgist
|
FROM test_spgist
|
||||||
WHERE ROW(
|
WHERE tle &? ROW(
|
||||||
observer('90.0N 0.0E 0m'),
|
observer('90.0N 0.0E 0m'),
|
||||||
'2024-01-01 00:00:00+00'::timestamptz,
|
'2024-01-01 00:00:00+00'::timestamptz,
|
||||||
'2024-01-02 00:00:00+00'::timestamptz,
|
'2024-01-02 00:00:00+00'::timestamptz,
|
||||||
10.0
|
10.0
|
||||||
)::observer_window &? tle
|
)::observer_window
|
||||||
ORDER BY name;
|
ORDER BY name;
|
||||||
|
|
||||||
|
|
||||||
@ -230,12 +230,12 @@ ORDER BY name;
|
|||||||
-- overhead at the instant. RAAN window = footprint only.
|
-- overhead at the instant. RAAN window = footprint only.
|
||||||
-- ============================================================
|
-- ============================================================
|
||||||
SELECT name,
|
SELECT name,
|
||||||
ROW(
|
tle &? ROW(
|
||||||
observer('0.0N 0.0E 0m'),
|
observer('0.0N 0.0E 0m'),
|
||||||
'2024-01-01 00:00:00+00'::timestamptz,
|
'2024-01-01 00:00:00+00'::timestamptz,
|
||||||
'2024-01-01 00:00:00+00'::timestamptz,
|
'2024-01-01 00:00:00+00'::timestamptz,
|
||||||
10.0
|
10.0
|
||||||
)::observer_window &? tle AS visible
|
)::observer_window AS visible
|
||||||
FROM test_spgist
|
FROM test_spgist
|
||||||
WHERE name = 'ISS';
|
WHERE name = 'ISS';
|
||||||
|
|
||||||
@ -247,12 +247,12 @@ WHERE name = 'ISS';
|
|||||||
SET enable_seqscan = off;
|
SET enable_seqscan = off;
|
||||||
SELECT name
|
SELECT name
|
||||||
FROM test_spgist
|
FROM test_spgist
|
||||||
WHERE ROW(
|
WHERE tle &? ROW(
|
||||||
observer('43.6977N 116.3535W 760m'),
|
observer('43.6977N 116.3535W 760m'),
|
||||||
'2024-01-01 00:00:00+00'::timestamptz,
|
'2024-01-01 00:00:00+00'::timestamptz,
|
||||||
'2024-01-02 00:00:00+00'::timestamptz,
|
'2024-01-02 00:00:00+00'::timestamptz,
|
||||||
10.0
|
10.0
|
||||||
)::observer_window &? tle
|
)::observer_window
|
||||||
ORDER BY name;
|
ORDER BY name;
|
||||||
RESET enable_seqscan;
|
RESET enable_seqscan;
|
||||||
|
|
||||||
@ -260,12 +260,12 @@ SET enable_indexscan = off;
|
|||||||
SET enable_bitmapscan = off;
|
SET enable_bitmapscan = off;
|
||||||
SELECT name
|
SELECT name
|
||||||
FROM test_spgist
|
FROM test_spgist
|
||||||
WHERE ROW(
|
WHERE tle &? ROW(
|
||||||
observer('43.6977N 116.3535W 760m'),
|
observer('43.6977N 116.3535W 760m'),
|
||||||
'2024-01-01 00:00:00+00'::timestamptz,
|
'2024-01-01 00:00:00+00'::timestamptz,
|
||||||
'2024-01-02 00:00:00+00'::timestamptz,
|
'2024-01-02 00:00:00+00'::timestamptz,
|
||||||
10.0
|
10.0
|
||||||
)::observer_window &? tle
|
)::observer_window
|
||||||
ORDER BY name;
|
ORDER BY name;
|
||||||
RESET enable_indexscan;
|
RESET enable_indexscan;
|
||||||
RESET enable_bitmapscan;
|
RESET enable_bitmapscan;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user