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
|
||||
-- ============================================================
|
||||
|
||||
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;
|
||||
|
||||
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.';
|
||||
|
||||
-- ============================================================
|
||||
-- &? 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 &? (
|
||||
LEFTARG = observer_window,
|
||||
RIGHTARG = tle,
|
||||
LEFTARG = tle,
|
||||
RIGHTARG = observer_window,
|
||||
FUNCTION = tle_visibility_possible,
|
||||
RESTRICT = contsel,
|
||||
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.';
|
||||
|
||||
-- ============================================================
|
||||
@ -68,7 +70,7 @@ CREATE FUNCTION spgist_tle_leaf_consistent(internal, internal) RETURNS void
|
||||
|
||||
CREATE OPERATOR CLASS tle_spgist_ops
|
||||
FOR TYPE tle USING spgist AS
|
||||
OPERATOR 1 &? (observer_window, tle),
|
||||
OPERATOR 1 &? (tle, observer_window),
|
||||
FUNCTION 1 spgist_tle_config(internal, internal),
|
||||
FUNCTION 2 spgist_tle_choose(internal, internal),
|
||||
FUNCTION 3 spgist_tle_picksplit(internal, internal),
|
||||
|
||||
@ -907,25 +907,27 @@ COMMENT ON TYPE observer_window IS
|
||||
-- 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;
|
||||
|
||||
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.';
|
||||
|
||||
-- ============================================================
|
||||
-- &? 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 &? (
|
||||
LEFTARG = observer_window,
|
||||
RIGHTARG = tle,
|
||||
LEFTARG = tle,
|
||||
RIGHTARG = observer_window,
|
||||
FUNCTION = tle_visibility_possible,
|
||||
RESTRICT = contsel,
|
||||
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.';
|
||||
|
||||
-- ============================================================
|
||||
@ -953,7 +955,7 @@ CREATE FUNCTION spgist_tle_leaf_consistent(internal, internal) RETURNS void
|
||||
|
||||
CREATE OPERATOR CLASS tle_spgist_ops
|
||||
FOR TYPE tle USING spgist AS
|
||||
OPERATOR 1 &? (observer_window, tle),
|
||||
OPERATOR 1 &? (tle, observer_window),
|
||||
FUNCTION 1 spgist_tle_config(internal, internal),
|
||||
FUNCTION 2 spgist_tle_choose(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
|
||||
*
|
||||
* 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
|
||||
gist_tle_union(PG_FUNCTION_ARGS)
|
||||
@ -338,10 +342,10 @@ gist_tle_union(PG_FUNCTION_ARGS)
|
||||
tle_orbital_key *cur;
|
||||
|
||||
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;
|
||||
|
||||
for (i = 1; i < entryvec->n; i++)
|
||||
for (i = FirstOffsetNumber + 1; i < entryvec->n; i++)
|
||||
{
|
||||
cur = (tle_orbital_key *) DatumGetPointer(entryvec->vector[i].key);
|
||||
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
|
||||
* along whichever dimension has the greater spread. This prevents
|
||||
* 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
|
||||
gist_tle_picksplit(PG_FUNCTION_ARGS)
|
||||
{
|
||||
GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
|
||||
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;
|
||||
tle_orbital_key *left_union;
|
||||
tle_orbital_key *right_union;
|
||||
tle_orbital_key *cur;
|
||||
int split_at;
|
||||
int i;
|
||||
OffsetNumber off;
|
||||
double alt_min, alt_max, inc_min, inc_max;
|
||||
double alt_spread, inc_spread;
|
||||
bool split_on_alt;
|
||||
|
||||
/* 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_max = alt_min;
|
||||
inc_min = (cur->inc_low + cur->inc_high) / 2.0;
|
||||
inc_max = inc_min;
|
||||
|
||||
for (i = 1; i < nentries; i++)
|
||||
for (off = FirstOffsetNumber + 1; off <= maxoff; off++)
|
||||
{
|
||||
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;
|
||||
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 */
|
||||
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);
|
||||
items[i].index = i;
|
||||
cur = (tle_orbital_key *) DatumGetPointer(entryvec->vector[off].key);
|
||||
items[i].index = off; /* store 1-based OffsetNumber directly */
|
||||
if (split_on_alt)
|
||||
items[i].sortval = (cur->alt_low + cur->alt_high) / 2.0;
|
||||
else
|
||||
@ -476,7 +488,7 @@ gist_tle_picksplit(PG_FUNCTION_ARGS)
|
||||
|
||||
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_right = (OffsetNumber *) palloc(sizeof(OffsetNumber) * nentries);
|
||||
splitvec->spl_nleft = 0;
|
||||
@ -497,21 +509,19 @@ gist_tle_picksplit(PG_FUNCTION_ARGS)
|
||||
|
||||
for (i = 0; i < nentries; i++)
|
||||
{
|
||||
int idx = items[i].index;
|
||||
OffsetNumber idx = items[i].index; /* already 1-based */
|
||||
|
||||
cur = (tle_orbital_key *) DatumGetPointer(
|
||||
entryvec->vector[idx].key);
|
||||
|
||||
if (i < split_at)
|
||||
{
|
||||
splitvec->spl_left[splitvec->spl_nleft++] =
|
||||
(OffsetNumber)(idx + 1); /* 1-based */
|
||||
splitvec->spl_left[splitvec->spl_nleft++] = idx;
|
||||
key_merge(left_union, cur);
|
||||
}
|
||||
else
|
||||
{
|
||||
splitvec->spl_right[splitvec->spl_nright++] =
|
||||
(OffsetNumber)(idx + 1);
|
||||
splitvec->spl_right[splitvec->spl_nright++] = idx;
|
||||
key_merge(right_union, cur);
|
||||
}
|
||||
}
|
||||
|
||||
@ -584,22 +584,18 @@ spgist_tle_inner_consistent(PG_FUNCTION_ARGS)
|
||||
if (have_query && level == 0)
|
||||
{
|
||||
/*
|
||||
* L0: SMA 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.
|
||||
* L0: SMA range narrowing only — no altitude pruning.
|
||||
*
|
||||
* Conservative: assume e=0 (circular, worst case for
|
||||
* "too high" pruning -- circular has highest perigee for
|
||||
* a given SMA).
|
||||
* We cannot prune SMA bins by altitude because eccentricity
|
||||
* is not available at the inner node level. A satellite
|
||||
* 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)
|
||||
{
|
||||
@ -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
|
||||
* 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
|
||||
* 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
|
||||
tle_visibility_possible(PG_FUNCTION_ARGS)
|
||||
{
|
||||
HeapTupleHeader composite = PG_GETARG_HEAPTUPLEHEADER(0);
|
||||
pg_tle *tle = (pg_tle *) PG_GETARG_POINTER(1);
|
||||
pg_tle *tle = (pg_tle *) PG_GETARG_POINTER(0);
|
||||
HeapTupleHeader composite = PG_GETARG_HEAPTUPLEHEADER(1);
|
||||
ObserverWindow 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).
|
||||
-- ============================================================
|
||||
SELECT name,
|
||||
ROW(
|
||||
tle &? ROW(
|
||||
observer('43.6977N 116.3535W 760m'),
|
||||
'2024-01-01 00:00:00+00'::timestamptz,
|
||||
'2024-01-01 02:00:00+00'::timestamptz,
|
||||
10.0
|
||||
)::observer_window &? tle AS visible
|
||||
)::observer_window AS visible
|
||||
FROM test_spgist
|
||||
WHERE name = 'ISS';
|
||||
name | visible
|
||||
@ -60,12 +60,12 @@ WHERE name = 'ISS';
|
||||
-- 5 deg inc + ~12 deg footprint = 17 deg < 43.7 deg latitude
|
||||
-- ============================================================
|
||||
SELECT name,
|
||||
ROW(
|
||||
tle &? ROW(
|
||||
observer('43.6977N 116.3535W 760m'),
|
||||
'2024-01-01 00:00:00+00'::timestamptz,
|
||||
'2024-01-01 02:00:00+00'::timestamptz,
|
||||
10.0
|
||||
)::observer_window &? tle AS visible
|
||||
)::observer_window AS visible
|
||||
FROM test_spgist
|
||||
WHERE name = 'Equatorial-LEO';
|
||||
name | visible
|
||||
@ -82,12 +82,12 @@ CREATE INDEX test_spgist_idx ON test_spgist USING spgist (tle tle_spgist_ops);
|
||||
SET enable_seqscan = off;
|
||||
SELECT name
|
||||
FROM test_spgist
|
||||
WHERE ROW(
|
||||
WHERE tle &? ROW(
|
||||
observer('0.0N 0.0E 0m'),
|
||||
'2024-01-01 00:00:00+00'::timestamptz,
|
||||
'2024-01-01 02:00:00+00'::timestamptz,
|
||||
10.0
|
||||
)::observer_window &? tle
|
||||
)::observer_window
|
||||
ORDER BY name;
|
||||
name
|
||||
---------
|
||||
@ -103,12 +103,12 @@ SET enable_indexscan = off;
|
||||
SET enable_bitmapscan = off;
|
||||
SELECT name
|
||||
FROM test_spgist
|
||||
WHERE ROW(
|
||||
WHERE tle &? ROW(
|
||||
observer('0.0N 0.0E 0m'),
|
||||
'2024-01-01 00:00:00+00'::timestamptz,
|
||||
'2024-01-01 02:00:00+00'::timestamptz,
|
||||
10.0
|
||||
)::observer_window &? tle
|
||||
)::observer_window
|
||||
ORDER BY name;
|
||||
name
|
||||
---------
|
||||
@ -125,12 +125,12 @@ RESET enable_bitmapscan;
|
||||
-- ============================================================
|
||||
SELECT name
|
||||
FROM test_spgist
|
||||
WHERE ROW(
|
||||
WHERE tle &? ROW(
|
||||
observer('43.6977N 116.3535W 760m'),
|
||||
'2024-01-01 00:00:00+00'::timestamptz,
|
||||
'2024-01-02 00:00:00+00'::timestamptz,
|
||||
10.0
|
||||
)::observer_window &? tle
|
||||
)::observer_window
|
||||
ORDER BY name;
|
||||
name
|
||||
---------
|
||||
@ -144,12 +144,12 @@ ORDER BY name;
|
||||
-- ============================================================
|
||||
SELECT name
|
||||
FROM test_spgist
|
||||
WHERE ROW(
|
||||
WHERE tle &? ROW(
|
||||
observer('43.6977N 116.3535W 760m'),
|
||||
'2024-01-01 00:00:00+00'::timestamptz,
|
||||
'2024-01-02 00:00:00+00'::timestamptz,
|
||||
45.0
|
||||
)::observer_window &? tle
|
||||
)::observer_window
|
||||
ORDER BY name;
|
||||
name
|
||||
---------
|
||||
@ -174,12 +174,12 @@ WHERE a.name = 'ISS' AND b.name = 'Hubble';
|
||||
SET enable_seqscan = off;
|
||||
SELECT name
|
||||
FROM test_spgist
|
||||
WHERE ROW(
|
||||
WHERE tle &? ROW(
|
||||
observer('43.6977N 116.3535W 760m'),
|
||||
'2024-01-01 00:00:00+00'::timestamptz,
|
||||
'2024-01-02 00:00:00+00'::timestamptz,
|
||||
10.0
|
||||
)::observer_window &? tle
|
||||
)::observer_window
|
||||
ORDER BY name;
|
||||
name
|
||||
---------
|
||||
@ -194,12 +194,12 @@ RESET enable_seqscan;
|
||||
INSERT INTO test_spgist (name, tle) VALUES ('NULL-SAT', NULL);
|
||||
SELECT name
|
||||
FROM test_spgist
|
||||
WHERE ROW(
|
||||
WHERE tle &? ROW(
|
||||
observer('43.6977N 116.3535W 760m'),
|
||||
'2024-01-01 00:00:00+00'::timestamptz,
|
||||
'2024-01-02 00:00:00+00'::timestamptz,
|
||||
10.0
|
||||
)::observer_window &? tle
|
||||
)::observer_window
|
||||
ORDER BY 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
|
||||
2 99904 0.0000 0.0000 0000000 0.0000 0.0000 0.00000000 00001');
|
||||
SELECT name,
|
||||
ROW(
|
||||
tle &? ROW(
|
||||
observer('0.0N 0.0E 0m'),
|
||||
'2024-01-01 00:00:00+00'::timestamptz,
|
||||
'2024-01-02 00:00:00+00'::timestamptz,
|
||||
10.0
|
||||
)::observer_window &? tle AS visible
|
||||
)::observer_window AS visible
|
||||
FROM test_spgist
|
||||
WHERE name = 'DECAYED';
|
||||
name | visible
|
||||
@ -234,12 +234,12 @@ WHERE name = 'DECAYED';
|
||||
-- ============================================================
|
||||
SELECT name
|
||||
FROM test_spgist
|
||||
WHERE ROW(
|
||||
WHERE tle &? ROW(
|
||||
observer('90.0N 0.0E 0m'),
|
||||
'2024-01-01 00:00:00+00'::timestamptz,
|
||||
'2024-01-02 00:00:00+00'::timestamptz,
|
||||
10.0
|
||||
)::observer_window &? tle
|
||||
)::observer_window
|
||||
ORDER BY name;
|
||||
name
|
||||
---------
|
||||
@ -251,12 +251,12 @@ ORDER BY name;
|
||||
-- overhead at the instant. RAAN window = footprint only.
|
||||
-- ============================================================
|
||||
SELECT name,
|
||||
ROW(
|
||||
tle &? ROW(
|
||||
observer('0.0N 0.0E 0m'),
|
||||
'2024-01-01 00:00:00+00'::timestamptz,
|
||||
'2024-01-01 00:00:00+00'::timestamptz,
|
||||
10.0
|
||||
)::observer_window &? tle AS visible
|
||||
)::observer_window AS visible
|
||||
FROM test_spgist
|
||||
WHERE name = 'ISS';
|
||||
name | visible
|
||||
@ -271,12 +271,12 @@ WHERE name = 'ISS';
|
||||
SET enable_seqscan = off;
|
||||
SELECT name
|
||||
FROM test_spgist
|
||||
WHERE ROW(
|
||||
WHERE tle &? ROW(
|
||||
observer('43.6977N 116.3535W 760m'),
|
||||
'2024-01-01 00:00:00+00'::timestamptz,
|
||||
'2024-01-02 00:00:00+00'::timestamptz,
|
||||
10.0
|
||||
)::observer_window &? tle
|
||||
)::observer_window
|
||||
ORDER BY name;
|
||||
name
|
||||
---------
|
||||
@ -289,12 +289,12 @@ SET enable_indexscan = off;
|
||||
SET enable_bitmapscan = off;
|
||||
SELECT name
|
||||
FROM test_spgist
|
||||
WHERE ROW(
|
||||
WHERE tle &? ROW(
|
||||
observer('43.6977N 116.3535W 760m'),
|
||||
'2024-01-01 00:00:00+00'::timestamptz,
|
||||
'2024-01-02 00:00:00+00'::timestamptz,
|
||||
10.0
|
||||
)::observer_window &? tle
|
||||
)::observer_window
|
||||
ORDER BY 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).
|
||||
-- ============================================================
|
||||
SELECT name,
|
||||
ROW(
|
||||
tle &? ROW(
|
||||
observer('43.6977N 116.3535W 760m'),
|
||||
'2024-01-01 00:00:00+00'::timestamptz,
|
||||
'2024-01-01 02:00:00+00'::timestamptz,
|
||||
10.0
|
||||
)::observer_window &? tle AS visible
|
||||
)::observer_window AS visible
|
||||
FROM test_spgist
|
||||
WHERE name = 'ISS';
|
||||
|
||||
@ -66,12 +66,12 @@ WHERE name = 'ISS';
|
||||
-- 5 deg inc + ~12 deg footprint = 17 deg < 43.7 deg latitude
|
||||
-- ============================================================
|
||||
SELECT name,
|
||||
ROW(
|
||||
tle &? ROW(
|
||||
observer('43.6977N 116.3535W 760m'),
|
||||
'2024-01-01 00:00:00+00'::timestamptz,
|
||||
'2024-01-01 02:00:00+00'::timestamptz,
|
||||
10.0
|
||||
)::observer_window &? tle AS visible
|
||||
)::observer_window AS visible
|
||||
FROM test_spgist
|
||||
WHERE name = 'Equatorial-LEO';
|
||||
|
||||
@ -87,12 +87,12 @@ SET enable_seqscan = off;
|
||||
|
||||
SELECT name
|
||||
FROM test_spgist
|
||||
WHERE ROW(
|
||||
WHERE tle &? ROW(
|
||||
observer('0.0N 0.0E 0m'),
|
||||
'2024-01-01 00:00:00+00'::timestamptz,
|
||||
'2024-01-01 02:00:00+00'::timestamptz,
|
||||
10.0
|
||||
)::observer_window &? tle
|
||||
)::observer_window
|
||||
ORDER BY name;
|
||||
|
||||
RESET enable_seqscan;
|
||||
@ -107,12 +107,12 @@ SET enable_bitmapscan = off;
|
||||
|
||||
SELECT name
|
||||
FROM test_spgist
|
||||
WHERE ROW(
|
||||
WHERE tle &? ROW(
|
||||
observer('0.0N 0.0E 0m'),
|
||||
'2024-01-01 00:00:00+00'::timestamptz,
|
||||
'2024-01-01 02:00:00+00'::timestamptz,
|
||||
10.0
|
||||
)::observer_window &? tle
|
||||
)::observer_window
|
||||
ORDER BY name;
|
||||
|
||||
RESET enable_indexscan;
|
||||
@ -127,12 +127,12 @@ RESET enable_bitmapscan;
|
||||
-- ============================================================
|
||||
SELECT name
|
||||
FROM test_spgist
|
||||
WHERE ROW(
|
||||
WHERE tle &? ROW(
|
||||
observer('43.6977N 116.3535W 760m'),
|
||||
'2024-01-01 00:00:00+00'::timestamptz,
|
||||
'2024-01-02 00:00:00+00'::timestamptz,
|
||||
10.0
|
||||
)::observer_window &? tle
|
||||
)::observer_window
|
||||
ORDER BY name;
|
||||
|
||||
|
||||
@ -142,12 +142,12 @@ ORDER BY name;
|
||||
-- ============================================================
|
||||
SELECT name
|
||||
FROM test_spgist
|
||||
WHERE ROW(
|
||||
WHERE tle &? ROW(
|
||||
observer('43.6977N 116.3535W 760m'),
|
||||
'2024-01-01 00:00:00+00'::timestamptz,
|
||||
'2024-01-02 00:00:00+00'::timestamptz,
|
||||
45.0
|
||||
)::observer_window &? tle
|
||||
)::observer_window
|
||||
ORDER BY name;
|
||||
|
||||
|
||||
@ -165,12 +165,12 @@ WHERE a.name = 'ISS' AND b.name = 'Hubble';
|
||||
SET enable_seqscan = off;
|
||||
SELECT name
|
||||
FROM test_spgist
|
||||
WHERE ROW(
|
||||
WHERE tle &? ROW(
|
||||
observer('43.6977N 116.3535W 760m'),
|
||||
'2024-01-01 00:00:00+00'::timestamptz,
|
||||
'2024-01-02 00:00:00+00'::timestamptz,
|
||||
10.0
|
||||
)::observer_window &? tle
|
||||
)::observer_window
|
||||
ORDER BY name;
|
||||
RESET enable_seqscan;
|
||||
|
||||
@ -182,12 +182,12 @@ INSERT INTO test_spgist (name, tle) VALUES ('NULL-SAT', NULL);
|
||||
|
||||
SELECT name
|
||||
FROM test_spgist
|
||||
WHERE ROW(
|
||||
WHERE tle &? ROW(
|
||||
observer('43.6977N 116.3535W 760m'),
|
||||
'2024-01-01 00:00:00+00'::timestamptz,
|
||||
'2024-01-02 00:00:00+00'::timestamptz,
|
||||
10.0
|
||||
)::observer_window &? tle
|
||||
)::observer_window
|
||||
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');
|
||||
|
||||
SELECT name,
|
||||
ROW(
|
||||
tle &? ROW(
|
||||
observer('0.0N 0.0E 0m'),
|
||||
'2024-01-01 00:00:00+00'::timestamptz,
|
||||
'2024-01-02 00:00:00+00'::timestamptz,
|
||||
10.0
|
||||
)::observer_window &? tle AS visible
|
||||
)::observer_window AS visible
|
||||
FROM test_spgist
|
||||
WHERE name = 'DECAYED';
|
||||
|
||||
@ -216,12 +216,12 @@ WHERE name = 'DECAYED';
|
||||
-- ============================================================
|
||||
SELECT name
|
||||
FROM test_spgist
|
||||
WHERE ROW(
|
||||
WHERE tle &? ROW(
|
||||
observer('90.0N 0.0E 0m'),
|
||||
'2024-01-01 00:00:00+00'::timestamptz,
|
||||
'2024-01-02 00:00:00+00'::timestamptz,
|
||||
10.0
|
||||
)::observer_window &? tle
|
||||
)::observer_window
|
||||
ORDER BY name;
|
||||
|
||||
|
||||
@ -230,12 +230,12 @@ ORDER BY name;
|
||||
-- overhead at the instant. RAAN window = footprint only.
|
||||
-- ============================================================
|
||||
SELECT name,
|
||||
ROW(
|
||||
tle &? ROW(
|
||||
observer('0.0N 0.0E 0m'),
|
||||
'2024-01-01 00:00:00+00'::timestamptz,
|
||||
'2024-01-01 00:00:00+00'::timestamptz,
|
||||
10.0
|
||||
)::observer_window &? tle AS visible
|
||||
)::observer_window AS visible
|
||||
FROM test_spgist
|
||||
WHERE name = 'ISS';
|
||||
|
||||
@ -247,12 +247,12 @@ WHERE name = 'ISS';
|
||||
SET enable_seqscan = off;
|
||||
SELECT name
|
||||
FROM test_spgist
|
||||
WHERE ROW(
|
||||
WHERE tle &? ROW(
|
||||
observer('43.6977N 116.3535W 760m'),
|
||||
'2024-01-01 00:00:00+00'::timestamptz,
|
||||
'2024-01-02 00:00:00+00'::timestamptz,
|
||||
10.0
|
||||
)::observer_window &? tle
|
||||
)::observer_window
|
||||
ORDER BY name;
|
||||
RESET enable_seqscan;
|
||||
|
||||
@ -260,12 +260,12 @@ SET enable_indexscan = off;
|
||||
SET enable_bitmapscan = off;
|
||||
SELECT name
|
||||
FROM test_spgist
|
||||
WHERE ROW(
|
||||
WHERE tle &? ROW(
|
||||
observer('43.6977N 116.3535W 760m'),
|
||||
'2024-01-01 00:00:00+00'::timestamptz,
|
||||
'2024-01-02 00:00:00+00'::timestamptz,
|
||||
10.0
|
||||
)::observer_window &? tle
|
||||
)::observer_window
|
||||
ORDER BY name;
|
||||
RESET enable_indexscan;
|
||||
RESET enable_bitmapscan;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user