pg_orrery/test/sql/convenience.sql
Ryan Malloy 3915d1784f Rename pg_orbit to pg_orrery
An existing product called PG Orbit (a mobile PostgreSQL client)
creates a naming conflict. pg_orrery — a database orrery built from
Keplerian parameters and SQL instead of brass gears.

Build system: control file, Makefile, Dockerfile, docker init script.
C source: GUC prefix, PG_FUNCTION_INFO_V1 symbol, header guards,
ereport prefixes, comments across ~30 files including vendored SGP4.
SQL: all 5 install/migration scripts, function name pg_orrery_ephemeris_info.
Tests: 9 SQL suites, 8 expected outputs, standalone DE reader test.
Documentation: CLAUDE.md, README.md, DESIGN.md, Starlight site infra,
36 MDX pages, OG renderer, logo SVG, docker-compose, agent threads.

All 13 regression suites pass. Docs site builds (37 pages).
2026-02-17 13:36:22 -07:00

76 lines
2.8 KiB
SQL

-- convenience functions requested by Craft (Astrolock) integration
CREATE EXTENSION IF NOT EXISTS pg_orrery;
-- tle_from_lines: two-argument constructor
SELECT tle_norad_id(tle_from_lines(
'1 25544U 98067A 24001.50000000 .00016717 00000-0 10270-3 0 9002',
'2 25544 51.6400 208.5000 0007417 68.5000 291.5000 15.49560000100001'
)) AS iss_norad_id;
-- observer_from_geodetic: numeric constructor
SELECT observer_from_geodetic(40.0, -105.3, 1655);
-- observer_from_geodetic: default altitude = 0
SELECT observer_from_geodetic(40.0, -105.3);
-- sgp4_propagate_safe: normal propagation returns result
SELECT (sgp4_propagate_safe(
'1 25544U 98067A 24001.50000000 .00016717 00000-0 10270-3 0 9002
2 25544 51.6400 208.5000 0007417 68.5000 291.5000 15.49560000100001'::tle,
'2024-01-01 12:00:00+00'::timestamptz
) IS NOT NULL) AS safe_returns_result;
-- sgp4_propagate_safe: diverged orbit returns NULL
SELECT sgp4_propagate_safe(
'1 25544U 98067A 24001.50000000 .00016717 00000-0 10270-3 0 9002
2 25544 51.6400 208.5000 0007417 68.5000 291.5000 15.49560000100001'::tle,
'2124-01-01 12:00:00+00'::timestamptz
) IS NULL AS safe_null_on_diverge;
-- observe: single-call propagate + topocentric
SELECT observe(
'1 25544U 98067A 24001.50000000 .00016717 00000-0 10270-3 0 9002
2 25544 51.6400 208.5000 0007417 68.5000 291.5000 15.49560000100001'::tle,
observer_from_geodetic(40.0, -105.3, 1655),
'2024-01-01 12:00:00+00'::timestamptz
);
-- observe_safe: returns NULL on diverged orbit
SELECT observe_safe(
'1 25544U 98067A 24001.50000000 .00016717 00000-0 10270-3 0 9002
2 25544 51.6400 208.5000 0007417 68.5000 291.5000 15.49560000100001'::tle,
'40.0N 105.3W 1655m'::observer,
'2124-01-01 12:00:00+00'::timestamptz
) IS NULL AS observe_safe_null;
-- observe matches manual eci_to_topocentric pipeline
-- (verify observe() produces same result as the two-step approach)
WITH propagated AS (
SELECT sgp4_propagate(
'1 25544U 98067A 24001.50000000 .00016717 00000-0 10270-3 0 9002
2 25544 51.6400 208.5000 0007417 68.5000 291.5000 15.49560000100001'::tle,
'2024-01-01 12:00:00+00'::timestamptz
) AS eci
),
manual AS (
SELECT eci_to_topocentric(
eci,
'40.0N 105.3W 1655m'::observer,
'2024-01-01 12:00:00+00'::timestamptz
) AS topo
FROM propagated
),
single_call AS (
SELECT observe(
'1 25544U 98067A 24001.50000000 .00016717 00000-0 10270-3 0 9002
2 25544 51.6400 208.5000 0007417 68.5000 291.5000 15.49560000100001'::tle,
'40.0N 105.3W 1655m'::observer,
'2024-01-01 12:00:00+00'::timestamptz
) AS topo
)
SELECT
topo_azimuth(m.topo) = topo_azimuth(s.topo) AS az_match,
topo_elevation(m.topo) = topo_elevation(s.topo) AS el_match,
topo_range(m.topo) = topo_range(s.topo) AS range_match
FROM manual m, single_call s;