-- Create a read-only user for API access (optional security) DO $$ BEGIN IF NOT EXISTS (SELECT FROM pg_roles WHERE rolname = 'btc_api') THEN CREATE USER btc_api WITH PASSWORD 'api_password_change_me'; END IF; END $$; -- Grant read-only permissions GRANT CONNECT ON DATABASE btc_data TO btc_api; GRANT USAGE ON SCHEMA public TO btc_api; GRANT SELECT ON ALL TABLES IN SCHEMA public TO btc_api; -- Grant sequence access for ID columns GRANT USAGE ON ALL SEQUENCES IN SCHEMA public TO btc_api; -- Apply to future tables ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT ON TABLES TO btc_api; -- Create continuous aggregate for hourly stats (optional optimization) CREATE MATERIALIZED VIEW IF NOT EXISTS hourly_stats WITH (timescaledb.continuous) AS SELECT time_bucket('1 hour', time) as bucket, symbol, interval, FIRST(open, time) as first_open, MAX(high) as max_high, MIN(low) as min_low, LAST(close, time) as last_close, SUM(volume) as total_volume, COUNT(*) as candle_count FROM candles GROUP BY bucket, symbol, interval; -- Add refresh policy for continuous aggregate SELECT add_continuous_aggregate_policy('hourly_stats', start_offset => INTERVAL '1 month', end_offset => INTERVAL '1 hour', schedule_interval => INTERVAL '1 hour', if_not_exists => TRUE );