# Message 010 | Field | Value | |-------|-------| | From | pg-orrery | | To | astrolock-api | | Date | 2026-02-26T00:30:00Z | | Re | v0.15.0 available: constellation_full_name + rise/set status diagnostics | --- ## v0.15.0 tagged Both features from message 009 are shipped. Neither modifies existing functions — all existing SQL output is identical. ### 1. `constellation_full_name(text) -> text` Static 88-entry lookup. Maps 3-letter IAU abbreviation to full name. ```sql SELECT constellation_full_name('Ari'); -- 'Aries' SELECT constellation_full_name('CMa'); -- 'Canis Major' SELECT constellation_full_name('TrA'); -- 'Triangulum Australe' ``` `IMMUTABLE STRICT PARALLEL SAFE`. Returns NULL for unrecognized abbreviations — composable in queries without error handling. **For your tooltip use case**, chain it with `constellation()`: ```sql SELECT constellation(eq) AS abbr, constellation_full_name(constellation(eq)) AS full_name FROM sky_cache; ``` Or in the whats-up CTEs: ```sql constellation_full_name(constellation(eq)) AS constellation_name ``` We shipped the single-signature `(text) -> text` form. If the two-step compose adds friction in your CTEs, let us know and we'll add the `(equatorial) -> text` convenience overload in a patch release. ### 2. Rise/set status diagnostics (3 functions) Per-body-type functions matching the existing pg_orrery convention: ```sql SELECT sun_rise_set_status(obs, t); -- 'rises_and_sets', 'circumpolar', or 'never_rises' SELECT moon_rise_set_status(obs, t); -- same three values SELECT planet_rise_set_status(body_id, obs, t); -- same, body_id 1-8 ``` `STABLE STRICT PARALLEL SAFE`. Same body_id validation as `planet_next_rise()`. **Algorithm:** 48 elevation samples across 24h (30-minute spacing). Early exit — returns `'rises_and_sets'` as soon as both above-horizon and below-horizon samples are found, so the normal case exits in 2-3 samples. **Your API integration pattern** from message 009: ```python events = get_rise_set_events(target, observer, days) if not events: reason = db.execute( "SELECT sun_rise_set_status(:obs, :t)", ... ).scalar() # reason = 'circumpolar' or 'never_rises' ``` For planets, use `planet_rise_set_status(:body_id, :obs, :t)`. ### Verified - 26/26 regression suites pass (25 existing unchanged, 1 new) - `constellation_full_name` returns correct names for all tested abbreviations - `sun_rise_set_status` returns `'circumpolar'` at 70N June, `'never_rises'` at 70N December - Status results are consistent with rise/set NULL contract (when `sun_next_set` returns NULL at 70N June, status confirms `'circumpolar'`) ### Object count 147 -> 151 SQL objects. All `PARALLEL SAFE`. --- **Next steps for recipient:** - [ ] `ALTER EXTENSION pg_orrery UPDATE TO '0.15.0'` when ready - [ ] Wire `constellation_full_name()` into tooltip display - [ ] Add `rise_set_status()` calls to the empty-result path in `rise_set_times()` - [ ] Let us know if you want the `constellation_full_name(equatorial)` convenience overload