pg_orrery/bench/tle_to_sql.py
Ryan Malloy 845aeee3a5 Add pass prediction guide, operator reference, and benchmarks
New docs:
- guides/pass-prediction.mdx: two-stage workflow (SP-GiST filter
  then SGP4 propagation), query window comparison tabs, GiST/SP-GiST
  coexistence example
- reference/operators-gist.mdx: &? operator signature and description,
  observer_window type reference, SP-GiST operator class docs with
  eccentricity/HEO limitation aside

Benchmarks on 14,376 CelesTrak active satellites:
- SP-GiST index: 2,344 kB, builds in 19 ms
- GiST index: 2,904 kB, builds in 45 ms
- Consistency: 0 false negatives, 0 false positives
- At 14k catalog size, seqscan (~6 ms) still beats index scan (~8 ms)
  due to low page count; cross-over expected at ~100k objects
2026-02-17 21:30:57 -07:00

51 lines
1.5 KiB
Python

#!/usr/bin/env python3
"""Convert 3-line TLE file to SQL COPY format for pg_orrery benchmark."""
import sys
def main():
lines = open(sys.argv[1]).read().strip().split('\n')
print("-- CelesTrak active satellite catalog")
print("-- Auto-generated for SP-GiST benchmark")
print("CREATE TABLE IF NOT EXISTS bench_catalog (")
print(" norad_id integer PRIMARY KEY,")
print(" name text NOT NULL,")
print(" tle tle NOT NULL")
print(");")
print("TRUNCATE bench_catalog;")
print()
count = 0
errors = 0
i = 0
while i + 2 < len(lines):
name = lines[i].strip()
line1 = lines[i + 1].strip()
line2 = lines[i + 2].strip()
# Validate TLE format
if not line1.startswith('1 ') or not line2.startswith('2 '):
i += 1 # skip and try to resync
errors += 1
continue
# Extract NORAD ID from line 1 (cols 3-7)
try:
norad_id = int(line1[2:7].strip())
except ValueError:
i += 3
errors += 1
continue
# Escape single quotes in name
name_escaped = name.replace("'", "''")
tle_str = line1 + '\n' + line2
print(f"INSERT INTO bench_catalog VALUES ({norad_id}, '{name_escaped}', E'{tle_str}') ON CONFLICT (norad_id) DO NOTHING;")
count += 1
i += 3
print(f"\n-- Loaded {count} satellites ({errors} parse errors skipped)")
if __name__ == '__main__':
main()