Skip to content

Commit b13d755

Browse files
author
AbhiPra
committed
Add 5 tables missed in initial schema/migration scan
core/database.py actually defines 14 tables (ticker_mapping, backfill_requests, data_health, portfolio_value_history, stock_metadata were not in the original 9-table plan -- codebase had drifted further than the pre-Phase-1 exploration found). ticker_mapping and stock_metadata use stock_code as their primary key (no id column), so migrate_to_supabase.py now tracks per-table has_id/order_col instead of assuming every table has a surrogate id. All 14 tables verified: schema created, 38,517 rows migrated.
1 parent dc8c1c0 commit b13d755

2 files changed

Lines changed: 73 additions & 18 deletions

File tree

scripts/init_supabase_schema.py

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,51 @@ async def connect_with_retry(dsn):
124124
timestamp TIMESTAMPTZ DEFAULT now()
125125
)
126126
""",
127+
"""
128+
CREATE TABLE IF NOT EXISTS ticker_mapping (
129+
stock_code TEXT PRIMARY KEY,
130+
nse_symbol TEXT,
131+
isin TEXT,
132+
resolved_at TIMESTAMPTZ DEFAULT now()
133+
)
134+
""",
135+
"""
136+
CREATE TABLE IF NOT EXISTS backfill_requests (
137+
id INTEGER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
138+
stock_code TEXT,
139+
requested_at TIMESTAMPTZ DEFAULT now(),
140+
processed_at TIMESTAMPTZ,
141+
status TEXT,
142+
error TEXT
143+
)
144+
""",
145+
"""
146+
CREATE TABLE IF NOT EXISTS data_health (
147+
id INTEGER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
148+
stock_code TEXT,
149+
source TEXT,
150+
status TEXT,
151+
message TEXT,
152+
timestamp TIMESTAMPTZ DEFAULT now()
153+
)
154+
""",
155+
"""
156+
CREATE TABLE IF NOT EXISTS portfolio_value_history (
157+
id INTEGER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
158+
timestamp TIMESTAMPTZ DEFAULT now(),
159+
total_invested DOUBLE PRECISION,
160+
total_current_value DOUBLE PRECISION,
161+
total_pnl DOUBLE PRECISION
162+
)
163+
""",
164+
"""
165+
CREATE TABLE IF NOT EXISTS stock_metadata (
166+
stock_code TEXT PRIMARY KEY,
167+
sector TEXT,
168+
industry TEXT,
169+
updated_at TIMESTAMPTZ DEFAULT now()
170+
)
171+
""",
127172
]
128173

129174

scripts/migrate_to_supabase.py

Lines changed: 28 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -32,23 +32,32 @@ def parse_ts(value):
3232
return datetime.strptime(value, "%Y-%m-%d %H:%M:%S").replace(tzinfo=timezone.utc)
3333

3434

35-
# (table_name, columns in migration order, columns that need SQLite-text -> datetime parsing)
35+
# (table_name, columns in migration order, columns that need SQLite-text -> datetime
36+
# parsing, order-by column for the SELECT). Tables keyed by stock_code (no surrogate
37+
# `id` column) pass has_id=False so no identity-sequence fixup is attempted.
3638
TABLES = [
37-
("holdings_snapshot", ["id", "stock_code", "quantity", "average_price", "current_price", "timestamp"], ["timestamp"]),
38-
("watchlist", ["id", "stock_code"], []),
39-
("ohlcv_cache", ["id", "stock_code", "date", "open", "high", "low", "close", "volume"], []),
39+
("holdings_snapshot", ["id", "stock_code", "quantity", "average_price", "current_price", "timestamp"], ["timestamp"], "id", True),
40+
("watchlist", ["id", "stock_code"], [], "id", True),
41+
("ohlcv_cache", ["id", "stock_code", "date", "open", "high", "low", "close", "volume"], [], "id", True),
4042
("signals", ["id", "stock_code", "rsi14", "macd_line", "macd_signal", "sma50", "sma200",
41-
"pct_from_52w_high", "volume_ratio_20d", "composite_score", "timestamp"], ["timestamp"]),
42-
("job_heartbeats", ["id", "job_name", "timestamp"], ["timestamp"]),
43-
("session_tokens", ["id", "token", "timestamp"], ["timestamp"]),
44-
("refresh_requests", ["id", "requested_at", "processed_at"], ["requested_at", "processed_at"]),
45-
("stage_history", ["id", "stock_code", "date", "stage", "sma_150", "slope"], []),
46-
("stock_actions", ["id", "stock_code", "action", "rationale", "timestamp"], ["timestamp"]),
43+
"pct_from_52w_high", "volume_ratio_20d", "composite_score", "timestamp"], ["timestamp"], "id", True),
44+
("job_heartbeats", ["id", "job_name", "timestamp"], ["timestamp"], "id", True),
45+
("session_tokens", ["id", "token", "timestamp"], ["timestamp"], "id", True),
46+
("refresh_requests", ["id", "requested_at", "processed_at"], ["requested_at", "processed_at"], "id", True),
47+
("stage_history", ["id", "stock_code", "date", "stage", "sma_150", "slope"], [], "id", True),
48+
("stock_actions", ["id", "stock_code", "action", "rationale", "timestamp"], ["timestamp"], "id", True),
49+
("ticker_mapping", ["stock_code", "nse_symbol", "isin", "resolved_at"], ["resolved_at"], "stock_code", False),
50+
("backfill_requests", ["id", "stock_code", "requested_at", "processed_at", "status", "error"],
51+
["requested_at", "processed_at"], "id", True),
52+
("data_health", ["id", "stock_code", "source", "status", "message", "timestamp"], ["timestamp"], "id", True),
53+
("portfolio_value_history", ["id", "timestamp", "total_invested", "total_current_value", "total_pnl"],
54+
["timestamp"], "id", True),
55+
("stock_metadata", ["stock_code", "sector", "industry", "updated_at"], ["updated_at"], "stock_code", False),
4756
]
4857

4958

50-
async def migrate_table(pg_conn, sqlite_conn, table, columns, ts_columns, truncate):
51-
cur = sqlite_conn.execute(f"SELECT {', '.join(columns)} FROM {table} ORDER BY id")
59+
async def migrate_table(pg_conn, sqlite_conn, table, columns, ts_columns, order_col, has_id, truncate):
60+
cur = sqlite_conn.execute(f"SELECT {', '.join(columns)} FROM {table} ORDER BY {order_col}")
5261
rows = cur.fetchall()
5362

5463
if truncate:
@@ -69,10 +78,11 @@ async def migrate_table(pg_conn, sqlite_conn, table, columns, ts_columns, trunca
6978
insert_sql = f"INSERT INTO {table} ({', '.join(columns)}) VALUES ({placeholders})"
7079
await pg_conn.executemany(insert_sql, processed_rows)
7180

72-
await pg_conn.execute(
73-
f"SELECT setval(pg_get_serial_sequence('{table}', 'id'), "
74-
f"COALESCE((SELECT MAX(id) FROM {table}), 0) + 1, false)"
75-
)
81+
if has_id:
82+
await pg_conn.execute(
83+
f"SELECT setval(pg_get_serial_sequence('{table}', 'id'), "
84+
f"COALESCE((SELECT MAX(id) FROM {table}), 0) + 1, false)"
85+
)
7686

7787
logger.info(f"{table}: migrated {len(rows)} rows")
7888
return len(rows)
@@ -99,8 +109,8 @@ async def main():
99109

100110
try:
101111
total = 0
102-
for table, columns, ts_columns in TABLES:
103-
total += await migrate_table(pg_conn, sqlite_conn, table, columns, ts_columns, args.truncate)
112+
for table, columns, ts_columns, order_col, has_id in TABLES:
113+
total += await migrate_table(pg_conn, sqlite_conn, table, columns, ts_columns, order_col, has_id, args.truncate)
104114
logger.info(f"Migration complete. {total} total row(s) migrated across {len(TABLES)} tables.")
105115
finally:
106116
sqlite_conn.close()

0 commit comments

Comments
 (0)