refactor: drive pg sqlite copy from target schema

This commit is contained in:
HsungKayphoon
2026-05-16 17:29:14 +08:00
parent 527feb69db
commit f9f1fa928a
18 changed files with 628 additions and 5406 deletions

View File

@@ -80,8 +80,6 @@ enum ExportDomainArg {
Wallets, Wallets,
Usage, Usage,
Billing, Billing,
Stats,
Auxiliary,
} }
impl From<ExportDomainArg> for ExportDomain { impl From<ExportDomainArg> for ExportDomain {
@@ -98,8 +96,6 @@ impl From<ExportDomainArg> for ExportDomain {
ExportDomainArg::Wallets => ExportDomain::Wallets, ExportDomainArg::Wallets => ExportDomain::Wallets,
ExportDomainArg::Usage => ExportDomain::Usage, ExportDomainArg::Usage => ExportDomain::Usage,
ExportDomainArg::Billing => ExportDomain::Billing, ExportDomainArg::Billing => ExportDomain::Billing,
ExportDomainArg::Stats => ExportDomain::Stats,
ExportDomainArg::Auxiliary => ExportDomain::Auxiliary,
} }
} }
} }

View File

@@ -1,34 +0,0 @@
CREATE TABLE IF NOT EXISTS usage_body_blobs (
body_ref TEXT PRIMARY KEY NOT NULL,
request_id TEXT NOT NULL,
body_field TEXT NOT NULL,
payload_gzip BLOB NOT NULL,
created_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP,
UNIQUE (request_id, body_field),
FOREIGN KEY (request_id) REFERENCES "usage"(request_id) ON DELETE CASCADE
);
CREATE INDEX IF NOT EXISTS usage_body_blobs_request_id_idx
ON usage_body_blobs (request_id);
CREATE TABLE IF NOT EXISTS usage_http_audits (
request_id TEXT PRIMARY KEY NOT NULL,
request_headers TEXT,
provider_request_headers TEXT,
response_headers TEXT,
client_response_headers TEXT,
request_body_ref TEXT,
provider_request_body_ref TEXT,
response_body_ref TEXT,
client_response_body_ref TEXT,
request_body_state TEXT,
provider_request_body_state TEXT,
response_body_state TEXT,
client_response_body_state TEXT,
body_capture_mode TEXT NOT NULL DEFAULT 'none',
created_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (request_id) REFERENCES "usage"(request_id) ON DELETE CASCADE
);
CREATE INDEX IF NOT EXISTS usage_http_audits_updated_at_idx
ON usage_http_audits (updated_at);

View File

@@ -1,570 +0,0 @@
CREATE TABLE IF NOT EXISTS api_key_provider_mappings (
id TEXT PRIMARY KEY NOT NULL,
api_key_id TEXT NOT NULL,
provider_id TEXT NOT NULL,
priority_adjustment INTEGER NOT NULL DEFAULT 0,
weight_multiplier REAL NOT NULL DEFAULT 1,
is_enabled INTEGER NOT NULL DEFAULT 1,
created_at INTEGER NOT NULL,
updated_at INTEGER NOT NULL,
UNIQUE (api_key_id, provider_id)
);
CREATE INDEX IF NOT EXISTS api_key_provider_mappings_api_key_id_idx
ON api_key_provider_mappings (api_key_id);
CREATE INDEX IF NOT EXISTS api_key_provider_mappings_provider_id_idx
ON api_key_provider_mappings (provider_id);
CREATE INDEX IF NOT EXISTS idx_apikey_provider_enabled
ON api_key_provider_mappings (api_key_id, is_enabled);
CREATE TABLE IF NOT EXISTS provider_usage_tracking (
id TEXT PRIMARY KEY NOT NULL,
provider_id TEXT NOT NULL,
window_start INTEGER NOT NULL,
window_end INTEGER NOT NULL,
total_requests INTEGER NOT NULL DEFAULT 0,
successful_requests INTEGER NOT NULL DEFAULT 0,
failed_requests INTEGER NOT NULL DEFAULT 0,
avg_response_time_ms REAL NOT NULL DEFAULT 0,
total_response_time_ms REAL NOT NULL DEFAULT 0,
total_cost_usd REAL NOT NULL DEFAULT 0,
created_at INTEGER NOT NULL,
updated_at INTEGER NOT NULL
);
CREATE INDEX IF NOT EXISTS provider_usage_tracking_provider_id_idx
ON provider_usage_tracking (provider_id);
CREATE INDEX IF NOT EXISTS provider_usage_tracking_window_start_idx
ON provider_usage_tracking (window_start);
CREATE INDEX IF NOT EXISTS idx_provider_window
ON provider_usage_tracking (provider_id, window_start);
CREATE INDEX IF NOT EXISTS idx_window_time
ON provider_usage_tracking (window_start, window_end);
CREATE TABLE IF NOT EXISTS usage_routing_snapshots (
request_id TEXT PRIMARY KEY NOT NULL,
candidate_id TEXT,
candidate_index INTEGER,
key_name TEXT,
planner_kind TEXT,
route_family TEXT,
route_kind TEXT,
execution_path TEXT,
local_execution_runtime_miss_reason TEXT,
selected_provider_id TEXT,
selected_endpoint_id TEXT,
selected_provider_api_key_id TEXT,
has_format_conversion INTEGER,
created_at INTEGER NOT NULL DEFAULT 0,
updated_at INTEGER NOT NULL DEFAULT 0,
FOREIGN KEY (request_id) REFERENCES "usage"(request_id) ON DELETE CASCADE
);
CREATE INDEX IF NOT EXISTS ix_usage_routing_snapshots_route_family_kind
ON usage_routing_snapshots (route_family, route_kind);
CREATE INDEX IF NOT EXISTS ix_usage_routing_snapshots_candidate_id
ON usage_routing_snapshots (candidate_id);
CREATE TABLE IF NOT EXISTS stats_summary (
id TEXT PRIMARY KEY NOT NULL,
cutoff_date INTEGER NOT NULL,
all_time_requests INTEGER NOT NULL DEFAULT 0,
all_time_success_requests INTEGER NOT NULL DEFAULT 0,
all_time_error_requests INTEGER NOT NULL DEFAULT 0,
all_time_input_tokens INTEGER NOT NULL DEFAULT 0,
all_time_output_tokens INTEGER NOT NULL DEFAULT 0,
all_time_cache_creation_tokens INTEGER NOT NULL DEFAULT 0,
all_time_cache_read_tokens INTEGER NOT NULL DEFAULT 0,
all_time_cost REAL NOT NULL DEFAULT 0,
all_time_actual_cost REAL NOT NULL DEFAULT 0,
total_users INTEGER NOT NULL DEFAULT 0,
active_users INTEGER NOT NULL DEFAULT 0,
total_api_keys INTEGER NOT NULL DEFAULT 0,
active_api_keys INTEGER NOT NULL DEFAULT 0,
created_at INTEGER NOT NULL,
updated_at INTEGER NOT NULL
);
CREATE TABLE IF NOT EXISTS user_model_usage_counts (
id TEXT PRIMARY KEY NOT NULL,
user_id TEXT NOT NULL,
model TEXT NOT NULL,
usage_count INTEGER NOT NULL DEFAULT 0,
created_at INTEGER NOT NULL,
updated_at INTEGER NOT NULL,
UNIQUE (user_id, model)
);
CREATE INDEX IF NOT EXISTS idx_user_model_usage_user
ON user_model_usage_counts (user_id);
CREATE INDEX IF NOT EXISTS idx_user_model_usage_model
ON user_model_usage_counts (model);
ALTER TABLE stats_hourly
ADD COLUMN response_time_sum_ms REAL NOT NULL DEFAULT 0;
ALTER TABLE stats_hourly
ADD COLUMN response_time_samples INTEGER NOT NULL DEFAULT 0;
ALTER TABLE stats_hourly
ADD COLUMN cache_hit_total_requests INTEGER NOT NULL DEFAULT 0;
ALTER TABLE stats_hourly
ADD COLUMN cache_hit_requests INTEGER NOT NULL DEFAULT 0;
ALTER TABLE stats_hourly
ADD COLUMN completed_total_requests INTEGER NOT NULL DEFAULT 0;
ALTER TABLE stats_hourly
ADD COLUMN completed_cache_hit_requests INTEGER NOT NULL DEFAULT 0;
ALTER TABLE stats_hourly
ADD COLUMN completed_input_tokens INTEGER NOT NULL DEFAULT 0;
ALTER TABLE stats_hourly
ADD COLUMN completed_cache_creation_tokens INTEGER NOT NULL DEFAULT 0;
ALTER TABLE stats_hourly
ADD COLUMN completed_cache_read_tokens INTEGER NOT NULL DEFAULT 0;
ALTER TABLE stats_hourly
ADD COLUMN completed_total_input_context INTEGER NOT NULL DEFAULT 0;
ALTER TABLE stats_hourly
ADD COLUMN completed_cache_creation_cost REAL NOT NULL DEFAULT 0;
ALTER TABLE stats_hourly
ADD COLUMN completed_cache_read_cost REAL NOT NULL DEFAULT 0;
ALTER TABLE stats_hourly
ADD COLUMN settled_total_cost REAL NOT NULL DEFAULT 0;
ALTER TABLE stats_hourly
ADD COLUMN settled_total_requests INTEGER NOT NULL DEFAULT 0;
ALTER TABLE stats_hourly
ADD COLUMN settled_input_tokens INTEGER NOT NULL DEFAULT 0;
ALTER TABLE stats_hourly
ADD COLUMN settled_output_tokens INTEGER NOT NULL DEFAULT 0;
ALTER TABLE stats_hourly
ADD COLUMN settled_cache_creation_tokens INTEGER NOT NULL DEFAULT 0;
ALTER TABLE stats_hourly
ADD COLUMN settled_cache_read_tokens INTEGER NOT NULL DEFAULT 0;
ALTER TABLE stats_hourly
ADD COLUMN settled_first_finalized_at_unix_secs INTEGER;
ALTER TABLE stats_hourly
ADD COLUMN settled_last_finalized_at_unix_secs INTEGER;
ALTER TABLE stats_hourly_user
ADD COLUMN cache_creation_tokens INTEGER NOT NULL DEFAULT 0;
ALTER TABLE stats_hourly_user
ADD COLUMN cache_read_tokens INTEGER NOT NULL DEFAULT 0;
ALTER TABLE stats_hourly_user
ADD COLUMN actual_total_cost REAL NOT NULL DEFAULT 0;
ALTER TABLE stats_hourly_user
ADD COLUMN response_time_sum_ms REAL NOT NULL DEFAULT 0;
ALTER TABLE stats_hourly_user
ADD COLUMN response_time_samples INTEGER NOT NULL DEFAULT 0;
ALTER TABLE stats_hourly_user
ADD COLUMN settled_total_cost REAL NOT NULL DEFAULT 0;
ALTER TABLE stats_hourly_user
ADD COLUMN settled_total_requests INTEGER NOT NULL DEFAULT 0;
ALTER TABLE stats_hourly_user
ADD COLUMN settled_input_tokens INTEGER NOT NULL DEFAULT 0;
ALTER TABLE stats_hourly_user
ADD COLUMN settled_output_tokens INTEGER NOT NULL DEFAULT 0;
ALTER TABLE stats_hourly_user
ADD COLUMN settled_cache_creation_tokens INTEGER NOT NULL DEFAULT 0;
ALTER TABLE stats_hourly_user
ADD COLUMN settled_cache_read_tokens INTEGER NOT NULL DEFAULT 0;
ALTER TABLE stats_hourly_user
ADD COLUMN settled_first_finalized_at_unix_secs INTEGER;
ALTER TABLE stats_hourly_user
ADD COLUMN settled_last_finalized_at_unix_secs INTEGER;
ALTER TABLE stats_hourly_user_model
ADD COLUMN response_time_sum_ms REAL NOT NULL DEFAULT 0;
ALTER TABLE stats_hourly_user_model
ADD COLUMN response_time_samples INTEGER NOT NULL DEFAULT 0;
ALTER TABLE stats_hourly_model
ADD COLUMN response_time_sum_ms REAL NOT NULL DEFAULT 0;
ALTER TABLE stats_hourly_model
ADD COLUMN response_time_samples INTEGER NOT NULL DEFAULT 0;
ALTER TABLE stats_daily
ADD COLUMN effective_input_tokens INTEGER NOT NULL DEFAULT 0;
ALTER TABLE stats_daily
ADD COLUMN total_input_context INTEGER NOT NULL DEFAULT 0;
ALTER TABLE stats_daily
ADD COLUMN response_time_sum_ms REAL NOT NULL DEFAULT 0;
ALTER TABLE stats_daily
ADD COLUMN response_time_samples INTEGER NOT NULL DEFAULT 0;
ALTER TABLE stats_daily
ADD COLUMN cache_creation_ephemeral_5m_tokens INTEGER NOT NULL DEFAULT 0;
ALTER TABLE stats_daily
ADD COLUMN cache_creation_ephemeral_1h_tokens INTEGER NOT NULL DEFAULT 0;
ALTER TABLE stats_daily
ADD COLUMN cache_hit_total_requests INTEGER NOT NULL DEFAULT 0;
ALTER TABLE stats_daily
ADD COLUMN cache_hit_requests INTEGER NOT NULL DEFAULT 0;
ALTER TABLE stats_daily
ADD COLUMN completed_total_requests INTEGER NOT NULL DEFAULT 0;
ALTER TABLE stats_daily
ADD COLUMN completed_cache_hit_requests INTEGER NOT NULL DEFAULT 0;
ALTER TABLE stats_daily
ADD COLUMN completed_input_tokens INTEGER NOT NULL DEFAULT 0;
ALTER TABLE stats_daily
ADD COLUMN completed_cache_creation_tokens INTEGER NOT NULL DEFAULT 0;
ALTER TABLE stats_daily
ADD COLUMN completed_cache_read_tokens INTEGER NOT NULL DEFAULT 0;
ALTER TABLE stats_daily
ADD COLUMN completed_total_input_context INTEGER NOT NULL DEFAULT 0;
ALTER TABLE stats_daily
ADD COLUMN completed_cache_creation_cost REAL NOT NULL DEFAULT 0;
ALTER TABLE stats_daily
ADD COLUMN completed_cache_read_cost REAL NOT NULL DEFAULT 0;
ALTER TABLE stats_daily
ADD COLUMN settled_total_cost REAL NOT NULL DEFAULT 0;
ALTER TABLE stats_daily
ADD COLUMN settled_total_requests INTEGER NOT NULL DEFAULT 0;
ALTER TABLE stats_daily
ADD COLUMN settled_input_tokens INTEGER NOT NULL DEFAULT 0;
ALTER TABLE stats_daily
ADD COLUMN settled_output_tokens INTEGER NOT NULL DEFAULT 0;
ALTER TABLE stats_daily
ADD COLUMN settled_cache_creation_tokens INTEGER NOT NULL DEFAULT 0;
ALTER TABLE stats_daily
ADD COLUMN settled_cache_read_tokens INTEGER NOT NULL DEFAULT 0;
ALTER TABLE stats_daily
ADD COLUMN settled_first_finalized_at_unix_secs INTEGER;
ALTER TABLE stats_daily
ADD COLUMN settled_last_finalized_at_unix_secs INTEGER;
ALTER TABLE stats_daily_model
ADD COLUMN cache_creation_ephemeral_5m_tokens INTEGER NOT NULL DEFAULT 0;
ALTER TABLE stats_daily_model
ADD COLUMN cache_creation_ephemeral_1h_tokens INTEGER NOT NULL DEFAULT 0;
ALTER TABLE stats_daily_model
ADD COLUMN response_time_sum_ms REAL NOT NULL DEFAULT 0;
ALTER TABLE stats_daily_model
ADD COLUMN response_time_samples INTEGER NOT NULL DEFAULT 0;
ALTER TABLE stats_user_daily
ADD COLUMN actual_total_cost REAL NOT NULL DEFAULT 0;
ALTER TABLE stats_user_daily
ADD COLUMN response_time_sum_ms REAL NOT NULL DEFAULT 0;
ALTER TABLE stats_user_daily
ADD COLUMN response_time_samples INTEGER NOT NULL DEFAULT 0;
ALTER TABLE stats_user_daily
ADD COLUMN effective_input_tokens INTEGER NOT NULL DEFAULT 0;
ALTER TABLE stats_user_daily
ADD COLUMN total_input_context INTEGER NOT NULL DEFAULT 0;
ALTER TABLE stats_user_daily
ADD COLUMN cache_creation_cost REAL NOT NULL DEFAULT 0;
ALTER TABLE stats_user_daily
ADD COLUMN cache_read_cost REAL NOT NULL DEFAULT 0;
ALTER TABLE stats_user_daily
ADD COLUMN cache_creation_ephemeral_5m_tokens INTEGER NOT NULL DEFAULT 0;
ALTER TABLE stats_user_daily
ADD COLUMN cache_creation_ephemeral_1h_tokens INTEGER NOT NULL DEFAULT 0;
ALTER TABLE stats_user_daily
ADD COLUMN settled_total_cost REAL NOT NULL DEFAULT 0;
ALTER TABLE stats_user_daily
ADD COLUMN settled_total_requests INTEGER NOT NULL DEFAULT 0;
ALTER TABLE stats_user_daily
ADD COLUMN settled_input_tokens INTEGER NOT NULL DEFAULT 0;
ALTER TABLE stats_user_daily
ADD COLUMN settled_output_tokens INTEGER NOT NULL DEFAULT 0;
ALTER TABLE stats_user_daily
ADD COLUMN settled_cache_creation_tokens INTEGER NOT NULL DEFAULT 0;
ALTER TABLE stats_user_daily
ADD COLUMN settled_cache_read_tokens INTEGER NOT NULL DEFAULT 0;
ALTER TABLE stats_user_daily
ADD COLUMN settled_first_finalized_at_unix_secs INTEGER;
ALTER TABLE stats_user_daily
ADD COLUMN settled_last_finalized_at_unix_secs INTEGER;
CREATE TABLE IF NOT EXISTS stats_user_summary (
id TEXT PRIMARY KEY NOT NULL,
user_id TEXT NOT NULL,
username TEXT,
cutoff_date INTEGER NOT NULL,
all_time_requests INTEGER NOT NULL DEFAULT 0,
all_time_success_requests INTEGER NOT NULL DEFAULT 0,
all_time_error_requests INTEGER NOT NULL DEFAULT 0,
all_time_input_tokens INTEGER NOT NULL DEFAULT 0,
all_time_output_tokens INTEGER NOT NULL DEFAULT 0,
all_time_cache_creation_tokens INTEGER NOT NULL DEFAULT 0,
all_time_cache_read_tokens INTEGER NOT NULL DEFAULT 0,
all_time_cost REAL NOT NULL DEFAULT 0,
all_time_actual_cost REAL NOT NULL DEFAULT 0,
active_days INTEGER NOT NULL DEFAULT 0,
first_active_date INTEGER,
last_active_date INTEGER,
created_at INTEGER NOT NULL DEFAULT 0,
updated_at INTEGER NOT NULL DEFAULT 0,
UNIQUE (user_id)
);
CREATE INDEX IF NOT EXISTS idx_stats_user_summary_cutoff_date
ON stats_user_summary (cutoff_date);
CREATE TABLE IF NOT EXISTS stats_user_daily_model (
id TEXT PRIMARY KEY NOT NULL,
user_id TEXT NOT NULL,
username TEXT,
date INTEGER NOT NULL,
model TEXT NOT NULL,
total_requests INTEGER NOT NULL DEFAULT 0,
success_requests INTEGER NOT NULL DEFAULT 0,
input_tokens INTEGER NOT NULL DEFAULT 0,
effective_input_tokens INTEGER NOT NULL DEFAULT 0,
output_tokens INTEGER NOT NULL DEFAULT 0,
total_tokens INTEGER NOT NULL DEFAULT 0,
total_input_context INTEGER NOT NULL DEFAULT 0,
cache_creation_tokens INTEGER NOT NULL DEFAULT 0,
cache_creation_ephemeral_5m_tokens INTEGER NOT NULL DEFAULT 0,
cache_creation_ephemeral_1h_tokens INTEGER NOT NULL DEFAULT 0,
cache_read_tokens INTEGER NOT NULL DEFAULT 0,
total_cost REAL NOT NULL DEFAULT 0,
actual_total_cost REAL NOT NULL DEFAULT 0,
response_time_sum_ms REAL NOT NULL DEFAULT 0,
response_time_samples INTEGER NOT NULL DEFAULT 0,
successful_response_time_sum_ms REAL NOT NULL DEFAULT 0,
successful_response_time_samples INTEGER NOT NULL DEFAULT 0,
created_at INTEGER NOT NULL DEFAULT 0,
updated_at INTEGER NOT NULL DEFAULT 0,
UNIQUE (user_id, date, model)
);
CREATE INDEX IF NOT EXISTS idx_stats_user_daily_model_date
ON stats_user_daily_model (date);
CREATE INDEX IF NOT EXISTS idx_stats_user_daily_model_user_id
ON stats_user_daily_model (user_id);
CREATE TABLE IF NOT EXISTS stats_user_daily_provider (
id TEXT PRIMARY KEY NOT NULL,
user_id TEXT NOT NULL,
username TEXT,
date INTEGER NOT NULL,
provider_name TEXT NOT NULL,
total_requests INTEGER NOT NULL DEFAULT 0,
success_requests INTEGER NOT NULL DEFAULT 0,
input_tokens INTEGER NOT NULL DEFAULT 0,
effective_input_tokens INTEGER NOT NULL DEFAULT 0,
output_tokens INTEGER NOT NULL DEFAULT 0,
total_tokens INTEGER NOT NULL DEFAULT 0,
total_input_context INTEGER NOT NULL DEFAULT 0,
cache_creation_tokens INTEGER NOT NULL DEFAULT 0,
cache_creation_ephemeral_5m_tokens INTEGER NOT NULL DEFAULT 0,
cache_creation_ephemeral_1h_tokens INTEGER NOT NULL DEFAULT 0,
cache_read_tokens INTEGER NOT NULL DEFAULT 0,
total_cost REAL NOT NULL DEFAULT 0,
actual_total_cost REAL NOT NULL DEFAULT 0,
response_time_sum_ms REAL NOT NULL DEFAULT 0,
response_time_samples INTEGER NOT NULL DEFAULT 0,
successful_response_time_sum_ms REAL NOT NULL DEFAULT 0,
successful_response_time_samples INTEGER NOT NULL DEFAULT 0,
created_at INTEGER NOT NULL DEFAULT 0,
updated_at INTEGER NOT NULL DEFAULT 0,
UNIQUE (user_id, date, provider_name)
);
CREATE INDEX IF NOT EXISTS idx_stats_user_daily_provider_date
ON stats_user_daily_provider (date);
CREATE INDEX IF NOT EXISTS idx_stats_user_daily_provider_user_id
ON stats_user_daily_provider (user_id);
CREATE TABLE IF NOT EXISTS stats_user_daily_api_format (
id TEXT PRIMARY KEY NOT NULL,
user_id TEXT NOT NULL,
username TEXT,
date INTEGER NOT NULL,
api_format TEXT NOT NULL,
total_requests INTEGER NOT NULL DEFAULT 0,
success_requests INTEGER NOT NULL DEFAULT 0,
input_tokens INTEGER NOT NULL DEFAULT 0,
effective_input_tokens INTEGER NOT NULL DEFAULT 0,
output_tokens INTEGER NOT NULL DEFAULT 0,
total_tokens INTEGER NOT NULL DEFAULT 0,
total_input_context INTEGER NOT NULL DEFAULT 0,
cache_creation_tokens INTEGER NOT NULL DEFAULT 0,
cache_creation_ephemeral_5m_tokens INTEGER NOT NULL DEFAULT 0,
cache_creation_ephemeral_1h_tokens INTEGER NOT NULL DEFAULT 0,
cache_read_tokens INTEGER NOT NULL DEFAULT 0,
total_cost REAL NOT NULL DEFAULT 0,
actual_total_cost REAL NOT NULL DEFAULT 0,
response_time_sum_ms REAL NOT NULL DEFAULT 0,
response_time_samples INTEGER NOT NULL DEFAULT 0,
successful_response_time_sum_ms REAL NOT NULL DEFAULT 0,
successful_response_time_samples INTEGER NOT NULL DEFAULT 0,
created_at INTEGER NOT NULL DEFAULT 0,
updated_at INTEGER NOT NULL DEFAULT 0,
UNIQUE (user_id, date, api_format)
);
CREATE INDEX IF NOT EXISTS idx_stats_user_daily_api_format_date
ON stats_user_daily_api_format (date);
CREATE INDEX IF NOT EXISTS idx_stats_user_daily_api_format_user_id
ON stats_user_daily_api_format (user_id);
CREATE TABLE IF NOT EXISTS stats_daily_model_provider (
id TEXT PRIMARY KEY NOT NULL,
date INTEGER NOT NULL,
model TEXT NOT NULL,
provider_name TEXT NOT NULL,
total_requests INTEGER NOT NULL DEFAULT 0,
total_tokens INTEGER NOT NULL DEFAULT 0,
total_cost REAL NOT NULL DEFAULT 0,
response_time_sum_ms REAL NOT NULL DEFAULT 0,
response_time_samples INTEGER NOT NULL DEFAULT 0,
created_at INTEGER NOT NULL DEFAULT 0,
updated_at INTEGER NOT NULL DEFAULT 0,
UNIQUE (date, model, provider_name)
);
CREATE INDEX IF NOT EXISTS idx_stats_daily_model_provider_date
ON stats_daily_model_provider (date);
CREATE INDEX IF NOT EXISTS idx_stats_daily_model_provider_date_model_provider
ON stats_daily_model_provider (date, model, provider_name);
CREATE TABLE IF NOT EXISTS stats_user_daily_model_provider (
id TEXT PRIMARY KEY NOT NULL,
user_id TEXT NOT NULL,
username TEXT,
date INTEGER NOT NULL,
model TEXT NOT NULL,
provider_name TEXT NOT NULL,
total_requests INTEGER NOT NULL DEFAULT 0,
total_tokens INTEGER NOT NULL DEFAULT 0,
total_cost REAL NOT NULL DEFAULT 0,
response_time_sum_ms REAL NOT NULL DEFAULT 0,
response_time_samples INTEGER NOT NULL DEFAULT 0,
created_at INTEGER NOT NULL DEFAULT 0,
updated_at INTEGER NOT NULL DEFAULT 0,
UNIQUE (user_id, date, model, provider_name)
);
CREATE INDEX IF NOT EXISTS idx_stats_user_daily_model_provider_date
ON stats_user_daily_model_provider (date);
CREATE INDEX IF NOT EXISTS idx_stats_user_daily_model_provider_user_date
ON stats_user_daily_model_provider (user_id, date);
CREATE TABLE IF NOT EXISTS stats_daily_cost_savings (
id TEXT PRIMARY KEY NOT NULL,
date INTEGER NOT NULL,
cache_read_tokens INTEGER NOT NULL DEFAULT 0,
cache_read_cost REAL NOT NULL DEFAULT 0,
cache_creation_cost REAL NOT NULL DEFAULT 0,
estimated_full_cost REAL NOT NULL DEFAULT 0,
created_at INTEGER NOT NULL DEFAULT 0,
updated_at INTEGER NOT NULL DEFAULT 0,
UNIQUE (date)
);
CREATE INDEX IF NOT EXISTS idx_stats_daily_cost_savings_date
ON stats_daily_cost_savings (date);
CREATE TABLE IF NOT EXISTS stats_daily_cost_savings_provider (
id TEXT PRIMARY KEY NOT NULL,
date INTEGER NOT NULL,
provider_name TEXT NOT NULL,
cache_read_tokens INTEGER NOT NULL DEFAULT 0,
cache_read_cost REAL NOT NULL DEFAULT 0,
cache_creation_cost REAL NOT NULL DEFAULT 0,
estimated_full_cost REAL NOT NULL DEFAULT 0,
created_at INTEGER NOT NULL DEFAULT 0,
updated_at INTEGER NOT NULL DEFAULT 0,
UNIQUE (date, provider_name)
);
CREATE INDEX IF NOT EXISTS idx_stats_daily_cost_savings_provider_date
ON stats_daily_cost_savings_provider (date);
CREATE INDEX IF NOT EXISTS idx_stats_daily_cost_savings_provider_date_provider
ON stats_daily_cost_savings_provider (date, provider_name);
CREATE TABLE IF NOT EXISTS stats_daily_cost_savings_model (
id TEXT PRIMARY KEY NOT NULL,
date INTEGER NOT NULL,
model TEXT NOT NULL,
cache_read_tokens INTEGER NOT NULL DEFAULT 0,
cache_read_cost REAL NOT NULL DEFAULT 0,
cache_creation_cost REAL NOT NULL DEFAULT 0,
estimated_full_cost REAL NOT NULL DEFAULT 0,
created_at INTEGER NOT NULL DEFAULT 0,
updated_at INTEGER NOT NULL DEFAULT 0,
UNIQUE (date, model)
);
CREATE INDEX IF NOT EXISTS idx_stats_daily_cost_savings_model_date
ON stats_daily_cost_savings_model (date);
CREATE INDEX IF NOT EXISTS idx_stats_daily_cost_savings_model_date_model
ON stats_daily_cost_savings_model (date, model);
CREATE TABLE IF NOT EXISTS stats_daily_cost_savings_model_provider (
id TEXT PRIMARY KEY NOT NULL,
date INTEGER NOT NULL,
model TEXT NOT NULL,
provider_name TEXT NOT NULL,
cache_read_tokens INTEGER NOT NULL DEFAULT 0,
cache_read_cost REAL NOT NULL DEFAULT 0,
cache_creation_cost REAL NOT NULL DEFAULT 0,
estimated_full_cost REAL NOT NULL DEFAULT 0,
created_at INTEGER NOT NULL DEFAULT 0,
updated_at INTEGER NOT NULL DEFAULT 0,
UNIQUE (date, model, provider_name)
);
CREATE INDEX IF NOT EXISTS idx_stats_daily_cost_savings_model_provider_date
ON stats_daily_cost_savings_model_provider (date);
CREATE INDEX IF NOT EXISTS idx_stats_daily_cost_savings_model_provider_date_dims
ON stats_daily_cost_savings_model_provider (date, model, provider_name);
CREATE TABLE IF NOT EXISTS stats_user_daily_cost_savings (
id TEXT PRIMARY KEY NOT NULL,
user_id TEXT NOT NULL,
username TEXT,
date INTEGER NOT NULL,
cache_read_tokens INTEGER NOT NULL DEFAULT 0,
cache_read_cost REAL NOT NULL DEFAULT 0,
cache_creation_cost REAL NOT NULL DEFAULT 0,
estimated_full_cost REAL NOT NULL DEFAULT 0,
created_at INTEGER NOT NULL DEFAULT 0,
updated_at INTEGER NOT NULL DEFAULT 0,
UNIQUE (user_id, date)
);
CREATE INDEX IF NOT EXISTS idx_stats_user_daily_cost_savings_date
ON stats_user_daily_cost_savings (date);
CREATE INDEX IF NOT EXISTS idx_stats_user_daily_cost_savings_user_date
ON stats_user_daily_cost_savings (user_id, date);
CREATE TABLE IF NOT EXISTS stats_user_daily_cost_savings_provider (
id TEXT PRIMARY KEY NOT NULL,
user_id TEXT NOT NULL,
username TEXT,
date INTEGER NOT NULL,
provider_name TEXT NOT NULL,
cache_read_tokens INTEGER NOT NULL DEFAULT 0,
cache_read_cost REAL NOT NULL DEFAULT 0,
cache_creation_cost REAL NOT NULL DEFAULT 0,
estimated_full_cost REAL NOT NULL DEFAULT 0,
created_at INTEGER NOT NULL DEFAULT 0,
updated_at INTEGER NOT NULL DEFAULT 0,
UNIQUE (user_id, date, provider_name)
);
CREATE INDEX IF NOT EXISTS idx_stats_user_daily_cost_savings_provider_date
ON stats_user_daily_cost_savings_provider (date);
CREATE INDEX IF NOT EXISTS idx_stats_user_daily_cost_savings_provider_user_date
ON stats_user_daily_cost_savings_provider (user_id, date);
CREATE TABLE IF NOT EXISTS stats_user_daily_cost_savings_model (
id TEXT PRIMARY KEY NOT NULL,
user_id TEXT NOT NULL,
username TEXT,
date INTEGER NOT NULL,
model TEXT NOT NULL,
cache_read_tokens INTEGER NOT NULL DEFAULT 0,
cache_read_cost REAL NOT NULL DEFAULT 0,
cache_creation_cost REAL NOT NULL DEFAULT 0,
estimated_full_cost REAL NOT NULL DEFAULT 0,
created_at INTEGER NOT NULL DEFAULT 0,
updated_at INTEGER NOT NULL DEFAULT 0,
UNIQUE (user_id, date, model)
);
CREATE INDEX IF NOT EXISTS idx_stats_user_daily_cost_savings_model_date
ON stats_user_daily_cost_savings_model (date);
CREATE INDEX IF NOT EXISTS idx_stats_user_daily_cost_savings_model_user_date
ON stats_user_daily_cost_savings_model (user_id, date);
CREATE TABLE IF NOT EXISTS stats_user_daily_cost_savings_model_provider (
id TEXT PRIMARY KEY NOT NULL,
user_id TEXT NOT NULL,
username TEXT,
date INTEGER NOT NULL,
model TEXT NOT NULL,
provider_name TEXT NOT NULL,
cache_read_tokens INTEGER NOT NULL DEFAULT 0,
cache_read_cost REAL NOT NULL DEFAULT 0,
cache_creation_cost REAL NOT NULL DEFAULT 0,
estimated_full_cost REAL NOT NULL DEFAULT 0,
created_at INTEGER NOT NULL DEFAULT 0,
updated_at INTEGER NOT NULL DEFAULT 0,
UNIQUE (user_id, date, model, provider_name)
);
CREATE INDEX IF NOT EXISTS idx_stats_user_daily_cost_savings_model_provider_date
ON stats_user_daily_cost_savings_model_provider (date);
CREATE INDEX IF NOT EXISTS idx_stats_user_daily_cost_savings_model_provider_user_date
ON stats_user_daily_cost_savings_model_provider (user_id, date);

View File

@@ -111,63 +111,6 @@ CREATE TABLE IF NOT EXISTS `usage` (
KEY usage_wallet_id_idx (`wallet_id`) KEY usage_wallet_id_idx (`wallet_id`)
); );
CREATE TABLE IF NOT EXISTS usage_body_blobs (
`body_ref` VARCHAR(160) NOT NULL,
`request_id` VARCHAR(128) NOT NULL,
`body_field` VARCHAR(64) NOT NULL,
`payload_gzip` LONGBLOB NOT NULL,
`created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
`updated_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`body_ref`),
UNIQUE KEY usage_body_blobs_request_id_field_key (`request_id`, `body_field`),
KEY usage_body_blobs_request_id_idx (`request_id`),
CONSTRAINT usage_body_blobs_request_id_fkey FOREIGN KEY (`request_id`) REFERENCES usage (`request_id`) ON DELETE CASCADE
);
CREATE TABLE IF NOT EXISTS usage_http_audits (
`request_id` VARCHAR(128) NOT NULL,
`request_headers` JSON,
`provider_request_headers` JSON,
`response_headers` JSON,
`client_response_headers` JSON,
`request_body_ref` VARCHAR(160),
`provider_request_body_ref` VARCHAR(160),
`response_body_ref` VARCHAR(160),
`client_response_body_ref` VARCHAR(160),
`request_body_state` VARCHAR(32),
`provider_request_body_state` VARCHAR(32),
`response_body_state` VARCHAR(32),
`client_response_body_state` VARCHAR(32),
`body_capture_mode` VARCHAR(32) NOT NULL DEFAULT 'none',
`created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
`updated_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`request_id`),
KEY usage_http_audits_updated_at_idx (`updated_at`),
CONSTRAINT usage_http_audits_request_id_fkey FOREIGN KEY (`request_id`) REFERENCES usage (`request_id`) ON DELETE CASCADE
);
CREATE TABLE IF NOT EXISTS usage_routing_snapshots (
`request_id` VARCHAR(128) NOT NULL,
`candidate_id` VARCHAR(160),
`candidate_index` BIGINT,
`key_name` VARCHAR(255),
`planner_kind` VARCHAR(120),
`route_family` VARCHAR(80),
`route_kind` VARCHAR(80),
`execution_path` VARCHAR(80),
`local_execution_runtime_miss_reason` VARCHAR(120),
`selected_provider_id` VARCHAR(64),
`selected_endpoint_id` VARCHAR(64),
`selected_provider_api_key_id` VARCHAR(64),
`has_format_conversion` TINYINT(1),
`created_at` BIGINT NOT NULL DEFAULT 0,
`updated_at` BIGINT NOT NULL DEFAULT 0,
PRIMARY KEY (`request_id`),
KEY ix_usage_routing_snapshots_route_family_kind (`route_family`, `route_kind`),
KEY ix_usage_routing_snapshots_candidate_id (`candidate_id`),
CONSTRAINT usage_routing_snapshots_request_id_fkey FOREIGN KEY (`request_id`) REFERENCES usage (`request_id`) ON DELETE CASCADE
);
CREATE TABLE IF NOT EXISTS usage_settlement_snapshots ( CREATE TABLE IF NOT EXISTS usage_settlement_snapshots (
`request_id` VARCHAR(128) NOT NULL, `request_id` VARCHAR(128) NOT NULL,
`billing_status` VARCHAR(64) NOT NULL, `billing_status` VARCHAR(64) NOT NULL,

View File

@@ -18,26 +18,6 @@ CREATE TABLE IF NOT EXISTS stats_hourly (
`aggregated_at` BIGINT, `aggregated_at` BIGINT,
`created_at` BIGINT NOT NULL, `created_at` BIGINT NOT NULL,
`updated_at` BIGINT NOT NULL, `updated_at` BIGINT NOT NULL,
`response_time_sum_ms` DOUBLE NOT NULL DEFAULT 0,
`response_time_samples` BIGINT NOT NULL DEFAULT 0,
`cache_hit_total_requests` BIGINT NOT NULL DEFAULT 0,
`cache_hit_requests` BIGINT NOT NULL DEFAULT 0,
`completed_total_requests` BIGINT NOT NULL DEFAULT 0,
`completed_cache_hit_requests` BIGINT NOT NULL DEFAULT 0,
`completed_input_tokens` BIGINT NOT NULL DEFAULT 0,
`completed_cache_creation_tokens` BIGINT NOT NULL DEFAULT 0,
`completed_cache_read_tokens` BIGINT NOT NULL DEFAULT 0,
`completed_total_input_context` BIGINT NOT NULL DEFAULT 0,
`completed_cache_creation_cost` DOUBLE NOT NULL DEFAULT 0,
`completed_cache_read_cost` DOUBLE NOT NULL DEFAULT 0,
`settled_total_cost` DOUBLE NOT NULL DEFAULT 0,
`settled_total_requests` BIGINT NOT NULL DEFAULT 0,
`settled_input_tokens` BIGINT NOT NULL DEFAULT 0,
`settled_output_tokens` BIGINT NOT NULL DEFAULT 0,
`settled_cache_creation_tokens` BIGINT NOT NULL DEFAULT 0,
`settled_cache_read_tokens` BIGINT NOT NULL DEFAULT 0,
`settled_first_finalized_at_unix_secs` BIGINT,
`settled_last_finalized_at_unix_secs` BIGINT,
PRIMARY KEY (`id`), PRIMARY KEY (`id`),
UNIQUE KEY uq_stats_hourly_hour (`hour_utc`) UNIQUE KEY uq_stats_hourly_hour (`hour_utc`)
); );
@@ -75,19 +55,6 @@ CREATE TABLE IF NOT EXISTS stats_hourly_user (
`total_cost` DOUBLE NOT NULL DEFAULT 0, `total_cost` DOUBLE NOT NULL DEFAULT 0,
`created_at` BIGINT NOT NULL, `created_at` BIGINT NOT NULL,
`updated_at` BIGINT NOT NULL, `updated_at` BIGINT NOT NULL,
`cache_creation_tokens` BIGINT NOT NULL DEFAULT 0,
`cache_read_tokens` BIGINT NOT NULL DEFAULT 0,
`actual_total_cost` DOUBLE NOT NULL DEFAULT 0,
`response_time_sum_ms` DOUBLE NOT NULL DEFAULT 0,
`response_time_samples` BIGINT NOT NULL DEFAULT 0,
`settled_total_cost` DOUBLE NOT NULL DEFAULT 0,
`settled_total_requests` BIGINT NOT NULL DEFAULT 0,
`settled_input_tokens` BIGINT NOT NULL DEFAULT 0,
`settled_output_tokens` BIGINT NOT NULL DEFAULT 0,
`settled_cache_creation_tokens` BIGINT NOT NULL DEFAULT 0,
`settled_cache_read_tokens` BIGINT NOT NULL DEFAULT 0,
`settled_first_finalized_at_unix_secs` BIGINT,
`settled_last_finalized_at_unix_secs` BIGINT,
PRIMARY KEY (`id`), PRIMARY KEY (`id`),
UNIQUE KEY uq_stats_hourly_user (`hour_utc`, `user_id`) UNIQUE KEY uq_stats_hourly_user (`hour_utc`, `user_id`)
); );
@@ -103,8 +70,6 @@ CREATE TABLE IF NOT EXISTS stats_hourly_user_model (
`total_cost` DOUBLE NOT NULL DEFAULT 0, `total_cost` DOUBLE NOT NULL DEFAULT 0,
`created_at` BIGINT NOT NULL, `created_at` BIGINT NOT NULL,
`updated_at` BIGINT NOT NULL, `updated_at` BIGINT NOT NULL,
`response_time_sum_ms` DOUBLE NOT NULL DEFAULT 0,
`response_time_samples` BIGINT NOT NULL DEFAULT 0,
PRIMARY KEY (`id`), PRIMARY KEY (`id`),
UNIQUE KEY uq_stats_hourly_user_model (`hour_utc`, `user_id`, `model`) UNIQUE KEY uq_stats_hourly_user_model (`hour_utc`, `user_id`, `model`)
); );
@@ -133,8 +98,6 @@ CREATE TABLE IF NOT EXISTS stats_hourly_model (
`avg_response_time_ms` DOUBLE NOT NULL DEFAULT 0, `avg_response_time_ms` DOUBLE NOT NULL DEFAULT 0,
`created_at` BIGINT NOT NULL, `created_at` BIGINT NOT NULL,
`updated_at` BIGINT NOT NULL, `updated_at` BIGINT NOT NULL,
`response_time_sum_ms` DOUBLE NOT NULL DEFAULT 0,
`response_time_samples` BIGINT NOT NULL DEFAULT 0,
PRIMARY KEY (`id`), PRIMARY KEY (`id`),
UNIQUE KEY uq_stats_hourly_model (`hour_utc`, `model`) UNIQUE KEY uq_stats_hourly_model (`hour_utc`, `model`)
); );
@@ -183,30 +146,6 @@ CREATE TABLE IF NOT EXISTS stats_daily (
`p50_first_byte_time_ms` BIGINT, `p50_first_byte_time_ms` BIGINT,
`p90_first_byte_time_ms` BIGINT, `p90_first_byte_time_ms` BIGINT,
`p99_first_byte_time_ms` BIGINT, `p99_first_byte_time_ms` BIGINT,
`effective_input_tokens` BIGINT NOT NULL DEFAULT 0,
`total_input_context` BIGINT NOT NULL DEFAULT 0,
`response_time_sum_ms` DOUBLE NOT NULL DEFAULT 0,
`response_time_samples` BIGINT NOT NULL DEFAULT 0,
`cache_creation_ephemeral_5m_tokens` BIGINT NOT NULL DEFAULT 0,
`cache_creation_ephemeral_1h_tokens` BIGINT NOT NULL DEFAULT 0,
`cache_hit_total_requests` BIGINT NOT NULL DEFAULT 0,
`cache_hit_requests` BIGINT NOT NULL DEFAULT 0,
`completed_total_requests` BIGINT NOT NULL DEFAULT 0,
`completed_cache_hit_requests` BIGINT NOT NULL DEFAULT 0,
`completed_input_tokens` BIGINT NOT NULL DEFAULT 0,
`completed_cache_creation_tokens` BIGINT NOT NULL DEFAULT 0,
`completed_cache_read_tokens` BIGINT NOT NULL DEFAULT 0,
`completed_total_input_context` BIGINT NOT NULL DEFAULT 0,
`completed_cache_creation_cost` DOUBLE NOT NULL DEFAULT 0,
`completed_cache_read_cost` DOUBLE NOT NULL DEFAULT 0,
`settled_total_cost` DOUBLE NOT NULL DEFAULT 0,
`settled_total_requests` BIGINT NOT NULL DEFAULT 0,
`settled_input_tokens` BIGINT NOT NULL DEFAULT 0,
`settled_output_tokens` BIGINT NOT NULL DEFAULT 0,
`settled_cache_creation_tokens` BIGINT NOT NULL DEFAULT 0,
`settled_cache_read_tokens` BIGINT NOT NULL DEFAULT 0,
`settled_first_finalized_at_unix_secs` BIGINT,
`settled_last_finalized_at_unix_secs` BIGINT,
PRIMARY KEY (`id`), PRIMARY KEY (`id`),
UNIQUE KEY uq_stats_daily_date (`date`) UNIQUE KEY uq_stats_daily_date (`date`)
); );
@@ -224,10 +163,6 @@ CREATE TABLE IF NOT EXISTS stats_daily_model (
`avg_response_time_ms` DOUBLE NOT NULL DEFAULT 0, `avg_response_time_ms` DOUBLE NOT NULL DEFAULT 0,
`created_at` BIGINT NOT NULL, `created_at` BIGINT NOT NULL,
`updated_at` BIGINT NOT NULL, `updated_at` BIGINT NOT NULL,
`cache_creation_ephemeral_5m_tokens` BIGINT NOT NULL DEFAULT 0,
`cache_creation_ephemeral_1h_tokens` BIGINT NOT NULL DEFAULT 0,
`response_time_sum_ms` DOUBLE NOT NULL DEFAULT 0,
`response_time_samples` BIGINT NOT NULL DEFAULT 0,
PRIMARY KEY (`id`), PRIMARY KEY (`id`),
UNIQUE KEY uq_stats_daily_model (`date`, `model`) UNIQUE KEY uq_stats_daily_model (`date`, `model`)
); );
@@ -295,314 +230,7 @@ CREATE TABLE IF NOT EXISTS stats_user_daily (
`username` VARCHAR(255), `username` VARCHAR(255),
`created_at` BIGINT NOT NULL, `created_at` BIGINT NOT NULL,
`updated_at` BIGINT NOT NULL, `updated_at` BIGINT NOT NULL,
`actual_total_cost` DOUBLE NOT NULL DEFAULT 0,
`response_time_sum_ms` DOUBLE NOT NULL DEFAULT 0,
`response_time_samples` BIGINT NOT NULL DEFAULT 0,
`effective_input_tokens` BIGINT NOT NULL DEFAULT 0,
`total_input_context` BIGINT NOT NULL DEFAULT 0,
`cache_creation_cost` DOUBLE NOT NULL DEFAULT 0,
`cache_read_cost` DOUBLE NOT NULL DEFAULT 0,
`cache_creation_ephemeral_5m_tokens` BIGINT NOT NULL DEFAULT 0,
`cache_creation_ephemeral_1h_tokens` BIGINT NOT NULL DEFAULT 0,
`settled_total_cost` DOUBLE NOT NULL DEFAULT 0,
`settled_total_requests` BIGINT NOT NULL DEFAULT 0,
`settled_input_tokens` BIGINT NOT NULL DEFAULT 0,
`settled_output_tokens` BIGINT NOT NULL DEFAULT 0,
`settled_cache_creation_tokens` BIGINT NOT NULL DEFAULT 0,
`settled_cache_read_tokens` BIGINT NOT NULL DEFAULT 0,
`settled_first_finalized_at_unix_secs` BIGINT,
`settled_last_finalized_at_unix_secs` BIGINT,
PRIMARY KEY (`id`), PRIMARY KEY (`id`),
UNIQUE KEY uq_stats_user_daily (`date`, `user_id`) UNIQUE KEY uq_stats_user_daily (`date`, `user_id`)
); );
CREATE TABLE IF NOT EXISTS stats_user_summary (
`id` VARCHAR(64) NOT NULL,
`user_id` VARCHAR(64) NOT NULL,
`username` VARCHAR(255),
`cutoff_date` BIGINT NOT NULL,
`all_time_requests` BIGINT NOT NULL DEFAULT 0,
`all_time_success_requests` BIGINT NOT NULL DEFAULT 0,
`all_time_error_requests` BIGINT NOT NULL DEFAULT 0,
`all_time_input_tokens` BIGINT NOT NULL DEFAULT 0,
`all_time_output_tokens` BIGINT NOT NULL DEFAULT 0,
`all_time_cache_creation_tokens` BIGINT NOT NULL DEFAULT 0,
`all_time_cache_read_tokens` BIGINT NOT NULL DEFAULT 0,
`all_time_cost` DOUBLE NOT NULL DEFAULT 0,
`all_time_actual_cost` DOUBLE NOT NULL DEFAULT 0,
`active_days` BIGINT NOT NULL DEFAULT 0,
`first_active_date` BIGINT,
`last_active_date` BIGINT,
`created_at` BIGINT NOT NULL DEFAULT 0,
`updated_at` BIGINT NOT NULL DEFAULT 0,
PRIMARY KEY (`id`),
UNIQUE KEY uq_stats_user_summary_user_id (`user_id`),
KEY idx_stats_user_summary_cutoff_date (`cutoff_date`)
);
CREATE TABLE IF NOT EXISTS stats_user_daily_model (
`id` VARCHAR(64) NOT NULL,
`user_id` VARCHAR(64) NOT NULL,
`username` VARCHAR(255),
`date` BIGINT NOT NULL,
`model` VARCHAR(255) NOT NULL,
`total_requests` BIGINT NOT NULL DEFAULT 0,
`success_requests` BIGINT NOT NULL DEFAULT 0,
`input_tokens` BIGINT NOT NULL DEFAULT 0,
`effective_input_tokens` BIGINT NOT NULL DEFAULT 0,
`output_tokens` BIGINT NOT NULL DEFAULT 0,
`total_tokens` BIGINT NOT NULL DEFAULT 0,
`total_input_context` BIGINT NOT NULL DEFAULT 0,
`cache_creation_tokens` BIGINT NOT NULL DEFAULT 0,
`cache_creation_ephemeral_5m_tokens` BIGINT NOT NULL DEFAULT 0,
`cache_creation_ephemeral_1h_tokens` BIGINT NOT NULL DEFAULT 0,
`cache_read_tokens` BIGINT NOT NULL DEFAULT 0,
`total_cost` DOUBLE NOT NULL DEFAULT 0,
`actual_total_cost` DOUBLE NOT NULL DEFAULT 0,
`response_time_sum_ms` DOUBLE NOT NULL DEFAULT 0,
`response_time_samples` BIGINT NOT NULL DEFAULT 0,
`successful_response_time_sum_ms` DOUBLE NOT NULL DEFAULT 0,
`successful_response_time_samples` BIGINT NOT NULL DEFAULT 0,
`created_at` BIGINT NOT NULL DEFAULT 0,
`updated_at` BIGINT NOT NULL DEFAULT 0,
PRIMARY KEY (`id`),
UNIQUE KEY uq_stats_user_daily_model_user_id_date_model (`user_id`, `date`, `model`),
KEY idx_stats_user_daily_model_date (`date`),
KEY idx_stats_user_daily_model_user_id (`user_id`)
);
CREATE TABLE IF NOT EXISTS stats_user_daily_provider (
`id` VARCHAR(64) NOT NULL,
`user_id` VARCHAR(64) NOT NULL,
`username` VARCHAR(255),
`date` BIGINT NOT NULL,
`provider_name` VARCHAR(255) NOT NULL,
`total_requests` BIGINT NOT NULL DEFAULT 0,
`success_requests` BIGINT NOT NULL DEFAULT 0,
`input_tokens` BIGINT NOT NULL DEFAULT 0,
`effective_input_tokens` BIGINT NOT NULL DEFAULT 0,
`output_tokens` BIGINT NOT NULL DEFAULT 0,
`total_tokens` BIGINT NOT NULL DEFAULT 0,
`total_input_context` BIGINT NOT NULL DEFAULT 0,
`cache_creation_tokens` BIGINT NOT NULL DEFAULT 0,
`cache_creation_ephemeral_5m_tokens` BIGINT NOT NULL DEFAULT 0,
`cache_creation_ephemeral_1h_tokens` BIGINT NOT NULL DEFAULT 0,
`cache_read_tokens` BIGINT NOT NULL DEFAULT 0,
`total_cost` DOUBLE NOT NULL DEFAULT 0,
`actual_total_cost` DOUBLE NOT NULL DEFAULT 0,
`response_time_sum_ms` DOUBLE NOT NULL DEFAULT 0,
`response_time_samples` BIGINT NOT NULL DEFAULT 0,
`successful_response_time_sum_ms` DOUBLE NOT NULL DEFAULT 0,
`successful_response_time_samples` BIGINT NOT NULL DEFAULT 0,
`created_at` BIGINT NOT NULL DEFAULT 0,
`updated_at` BIGINT NOT NULL DEFAULT 0,
PRIMARY KEY (`id`),
UNIQUE KEY uq_stats_user_daily_provider_user_id_date_provider_name (`user_id`, `date`, `provider_name`),
KEY idx_stats_user_daily_provider_date (`date`),
KEY idx_stats_user_daily_provider_user_id (`user_id`)
);
CREATE TABLE IF NOT EXISTS stats_user_daily_api_format (
`id` VARCHAR(64) NOT NULL,
`user_id` VARCHAR(64) NOT NULL,
`username` VARCHAR(255),
`date` BIGINT NOT NULL,
`api_format` VARCHAR(255) NOT NULL,
`total_requests` BIGINT NOT NULL DEFAULT 0,
`success_requests` BIGINT NOT NULL DEFAULT 0,
`input_tokens` BIGINT NOT NULL DEFAULT 0,
`effective_input_tokens` BIGINT NOT NULL DEFAULT 0,
`output_tokens` BIGINT NOT NULL DEFAULT 0,
`total_tokens` BIGINT NOT NULL DEFAULT 0,
`total_input_context` BIGINT NOT NULL DEFAULT 0,
`cache_creation_tokens` BIGINT NOT NULL DEFAULT 0,
`cache_creation_ephemeral_5m_tokens` BIGINT NOT NULL DEFAULT 0,
`cache_creation_ephemeral_1h_tokens` BIGINT NOT NULL DEFAULT 0,
`cache_read_tokens` BIGINT NOT NULL DEFAULT 0,
`total_cost` DOUBLE NOT NULL DEFAULT 0,
`actual_total_cost` DOUBLE NOT NULL DEFAULT 0,
`response_time_sum_ms` DOUBLE NOT NULL DEFAULT 0,
`response_time_samples` BIGINT NOT NULL DEFAULT 0,
`successful_response_time_sum_ms` DOUBLE NOT NULL DEFAULT 0,
`successful_response_time_samples` BIGINT NOT NULL DEFAULT 0,
`created_at` BIGINT NOT NULL DEFAULT 0,
`updated_at` BIGINT NOT NULL DEFAULT 0,
PRIMARY KEY (`id`),
UNIQUE KEY uq_stats_user_daily_api_format_user_id_date_api_format (`user_id`, `date`, `api_format`),
KEY idx_stats_user_daily_api_format_date (`date`),
KEY idx_stats_user_daily_api_format_user_id (`user_id`)
);
CREATE TABLE IF NOT EXISTS stats_daily_model_provider (
`id` VARCHAR(64) NOT NULL,
`date` BIGINT NOT NULL,
`model` VARCHAR(255) NOT NULL,
`provider_name` VARCHAR(255) NOT NULL,
`total_requests` BIGINT NOT NULL DEFAULT 0,
`total_tokens` BIGINT NOT NULL DEFAULT 0,
`total_cost` DOUBLE NOT NULL DEFAULT 0,
`response_time_sum_ms` DOUBLE NOT NULL DEFAULT 0,
`response_time_samples` BIGINT NOT NULL DEFAULT 0,
`created_at` BIGINT NOT NULL DEFAULT 0,
`updated_at` BIGINT NOT NULL DEFAULT 0,
PRIMARY KEY (`id`),
UNIQUE KEY uq_stats_daily_model_provider_date_model_provider_name (`date`, `model`, `provider_name`),
KEY idx_stats_daily_model_provider_date (`date`),
KEY idx_stats_daily_model_provider_date_model_provider (`date`, `model`, `provider_name`)
);
CREATE TABLE IF NOT EXISTS stats_user_daily_model_provider (
`id` VARCHAR(64) NOT NULL,
`user_id` VARCHAR(64) NOT NULL,
`username` VARCHAR(255),
`date` BIGINT NOT NULL,
`model` VARCHAR(255) NOT NULL,
`provider_name` VARCHAR(255) NOT NULL,
`total_requests` BIGINT NOT NULL DEFAULT 0,
`total_tokens` BIGINT NOT NULL DEFAULT 0,
`total_cost` DOUBLE NOT NULL DEFAULT 0,
`response_time_sum_ms` DOUBLE NOT NULL DEFAULT 0,
`response_time_samples` BIGINT NOT NULL DEFAULT 0,
`created_at` BIGINT NOT NULL DEFAULT 0,
`updated_at` BIGINT NOT NULL DEFAULT 0,
PRIMARY KEY (`id`),
UNIQUE KEY uq_stats_user_daily_model_provider_user_id_date_model_provider_name (`user_id`, `date`, `model`, `provider_name`),
KEY idx_stats_user_daily_model_provider_date (`date`),
KEY idx_stats_user_daily_model_provider_user_date (`user_id`, `date`)
);
CREATE TABLE IF NOT EXISTS stats_daily_cost_savings (
`id` VARCHAR(64) NOT NULL,
`date` BIGINT NOT NULL,
`cache_read_tokens` BIGINT NOT NULL DEFAULT 0,
`cache_read_cost` DOUBLE NOT NULL DEFAULT 0,
`cache_creation_cost` DOUBLE NOT NULL DEFAULT 0,
`estimated_full_cost` DOUBLE NOT NULL DEFAULT 0,
`created_at` BIGINT NOT NULL DEFAULT 0,
`updated_at` BIGINT NOT NULL DEFAULT 0,
PRIMARY KEY (`id`),
UNIQUE KEY uq_stats_daily_cost_savings_date (`date`),
KEY idx_stats_daily_cost_savings_date (`date`)
);
CREATE TABLE IF NOT EXISTS stats_daily_cost_savings_provider (
`id` VARCHAR(64) NOT NULL,
`date` BIGINT NOT NULL,
`provider_name` VARCHAR(255) NOT NULL,
`cache_read_tokens` BIGINT NOT NULL DEFAULT 0,
`cache_read_cost` DOUBLE NOT NULL DEFAULT 0,
`cache_creation_cost` DOUBLE NOT NULL DEFAULT 0,
`estimated_full_cost` DOUBLE NOT NULL DEFAULT 0,
`created_at` BIGINT NOT NULL DEFAULT 0,
`updated_at` BIGINT NOT NULL DEFAULT 0,
PRIMARY KEY (`id`),
UNIQUE KEY uq_stats_daily_cost_savings_provider_date_provider_name (`date`, `provider_name`),
KEY idx_stats_daily_cost_savings_provider_date (`date`),
KEY idx_stats_daily_cost_savings_provider_date_provider (`date`, `provider_name`)
);
CREATE TABLE IF NOT EXISTS stats_daily_cost_savings_model (
`id` VARCHAR(64) NOT NULL,
`date` BIGINT NOT NULL,
`model` VARCHAR(255) NOT NULL,
`cache_read_tokens` BIGINT NOT NULL DEFAULT 0,
`cache_read_cost` DOUBLE NOT NULL DEFAULT 0,
`cache_creation_cost` DOUBLE NOT NULL DEFAULT 0,
`estimated_full_cost` DOUBLE NOT NULL DEFAULT 0,
`created_at` BIGINT NOT NULL DEFAULT 0,
`updated_at` BIGINT NOT NULL DEFAULT 0,
PRIMARY KEY (`id`),
UNIQUE KEY uq_stats_daily_cost_savings_model_date_model (`date`, `model`),
KEY idx_stats_daily_cost_savings_model_date (`date`),
KEY idx_stats_daily_cost_savings_model_date_model (`date`, `model`)
);
CREATE TABLE IF NOT EXISTS stats_daily_cost_savings_model_provider (
`id` VARCHAR(64) NOT NULL,
`date` BIGINT NOT NULL,
`model` VARCHAR(255) NOT NULL,
`provider_name` VARCHAR(255) NOT NULL,
`cache_read_tokens` BIGINT NOT NULL DEFAULT 0,
`cache_read_cost` DOUBLE NOT NULL DEFAULT 0,
`cache_creation_cost` DOUBLE NOT NULL DEFAULT 0,
`estimated_full_cost` DOUBLE NOT NULL DEFAULT 0,
`created_at` BIGINT NOT NULL DEFAULT 0,
`updated_at` BIGINT NOT NULL DEFAULT 0,
PRIMARY KEY (`id`),
UNIQUE KEY uq_stats_daily_cost_savings_model_provider_date_model_provider_name (`date`, `model`, `provider_name`),
KEY idx_stats_daily_cost_savings_model_provider_date (`date`),
KEY idx_stats_daily_cost_savings_model_provider_date_dims (`date`, `model`, `provider_name`)
);
CREATE TABLE IF NOT EXISTS stats_user_daily_cost_savings (
`id` VARCHAR(64) NOT NULL,
`user_id` VARCHAR(64) NOT NULL,
`username` VARCHAR(255),
`date` BIGINT NOT NULL,
`cache_read_tokens` BIGINT NOT NULL DEFAULT 0,
`cache_read_cost` DOUBLE NOT NULL DEFAULT 0,
`cache_creation_cost` DOUBLE NOT NULL DEFAULT 0,
`estimated_full_cost` DOUBLE NOT NULL DEFAULT 0,
`created_at` BIGINT NOT NULL DEFAULT 0,
`updated_at` BIGINT NOT NULL DEFAULT 0,
PRIMARY KEY (`id`),
UNIQUE KEY uq_stats_user_daily_cost_savings_user_id_date (`user_id`, `date`),
KEY idx_stats_user_daily_cost_savings_date (`date`),
KEY idx_stats_user_daily_cost_savings_user_date (`user_id`, `date`)
);
CREATE TABLE IF NOT EXISTS stats_user_daily_cost_savings_provider (
`id` VARCHAR(64) NOT NULL,
`user_id` VARCHAR(64) NOT NULL,
`username` VARCHAR(255),
`date` BIGINT NOT NULL,
`provider_name` VARCHAR(255) NOT NULL,
`cache_read_tokens` BIGINT NOT NULL DEFAULT 0,
`cache_read_cost` DOUBLE NOT NULL DEFAULT 0,
`cache_creation_cost` DOUBLE NOT NULL DEFAULT 0,
`estimated_full_cost` DOUBLE NOT NULL DEFAULT 0,
`created_at` BIGINT NOT NULL DEFAULT 0,
`updated_at` BIGINT NOT NULL DEFAULT 0,
PRIMARY KEY (`id`),
UNIQUE KEY uq_stats_user_daily_cost_savings_provider_user_id_date_provider_name (`user_id`, `date`, `provider_name`),
KEY idx_stats_user_daily_cost_savings_provider_date (`date`),
KEY idx_stats_user_daily_cost_savings_provider_user_date (`user_id`, `date`)
);
CREATE TABLE IF NOT EXISTS stats_user_daily_cost_savings_model (
`id` VARCHAR(64) NOT NULL,
`user_id` VARCHAR(64) NOT NULL,
`username` VARCHAR(255),
`date` BIGINT NOT NULL,
`model` VARCHAR(255) NOT NULL,
`cache_read_tokens` BIGINT NOT NULL DEFAULT 0,
`cache_read_cost` DOUBLE NOT NULL DEFAULT 0,
`cache_creation_cost` DOUBLE NOT NULL DEFAULT 0,
`estimated_full_cost` DOUBLE NOT NULL DEFAULT 0,
`created_at` BIGINT NOT NULL DEFAULT 0,
`updated_at` BIGINT NOT NULL DEFAULT 0,
PRIMARY KEY (`id`),
UNIQUE KEY uq_stats_user_daily_cost_savings_model_user_id_date_model (`user_id`, `date`, `model`),
KEY idx_stats_user_daily_cost_savings_model_date (`date`),
KEY idx_stats_user_daily_cost_savings_model_user_date (`user_id`, `date`)
);
CREATE TABLE IF NOT EXISTS stats_user_daily_cost_savings_model_provider (
`id` VARCHAR(64) NOT NULL,
`user_id` VARCHAR(64) NOT NULL,
`username` VARCHAR(255),
`date` BIGINT NOT NULL,
`model` VARCHAR(255) NOT NULL,
`provider_name` VARCHAR(255) NOT NULL,
`cache_read_tokens` BIGINT NOT NULL DEFAULT 0,
`cache_read_cost` DOUBLE NOT NULL DEFAULT 0,
`cache_creation_cost` DOUBLE NOT NULL DEFAULT 0,
`estimated_full_cost` DOUBLE NOT NULL DEFAULT 0,
`created_at` BIGINT NOT NULL DEFAULT 0,
`updated_at` BIGINT NOT NULL DEFAULT 0,
PRIMARY KEY (`id`),
UNIQUE KEY uq_stats_user_daily_cost_savings_model_provider_user_id_date_model_provider_name (`user_id`, `date`, `model`, `provider_name`),
KEY idx_stats_user_daily_cost_savings_model_provider_date (`date`),
KEY idx_stats_user_daily_cost_savings_model_provider_user_date (`user_id`, `date`)
);

View File

@@ -112,66 +112,6 @@ CREATE INDEX IF NOT EXISTS usage_request_id_idx ON public.usage USING btree (req
CREATE INDEX IF NOT EXISTS usage_user_id_idx ON public.usage USING btree (user_id); CREATE INDEX IF NOT EXISTS usage_user_id_idx ON public.usage USING btree (user_id);
CREATE INDEX IF NOT EXISTS usage_wallet_id_idx ON public.usage USING btree (wallet_id); CREATE INDEX IF NOT EXISTS usage_wallet_id_idx ON public.usage USING btree (wallet_id);
CREATE TABLE IF NOT EXISTS public.usage_body_blobs (
body_ref character varying(160) NOT NULL,
request_id character varying(128) NOT NULL,
body_field character varying(64) NOT NULL,
payload_gzip bytea NOT NULL,
created_at timestamp with time zone DEFAULT CURRENT_TIMESTAMP NOT NULL,
updated_at timestamp with time zone DEFAULT CURRENT_TIMESTAMP NOT NULL
);
ALTER TABLE ONLY public.usage_body_blobs ADD CONSTRAINT usage_body_blobs_pkey PRIMARY KEY (body_ref);
ALTER TABLE ONLY public.usage_body_blobs ADD CONSTRAINT usage_body_blobs_request_id_field_key UNIQUE (request_id, body_field);
CREATE INDEX IF NOT EXISTS usage_body_blobs_request_id_idx ON public.usage_body_blobs USING btree (request_id);
ALTER TABLE ONLY public.usage_body_blobs ADD CONSTRAINT usage_body_blobs_request_id_fkey FOREIGN KEY (request_id) REFERENCES public.usage(request_id) ON DELETE CASCADE;
CREATE TABLE IF NOT EXISTS public.usage_http_audits (
request_id character varying(128) NOT NULL,
request_headers jsonb,
provider_request_headers jsonb,
response_headers jsonb,
client_response_headers jsonb,
request_body_ref character varying(160),
provider_request_body_ref character varying(160),
response_body_ref character varying(160),
client_response_body_ref character varying(160),
request_body_state character varying(32),
provider_request_body_state character varying(32),
response_body_state character varying(32),
client_response_body_state character varying(32),
body_capture_mode character varying(32) DEFAULT 'none' NOT NULL,
created_at timestamp with time zone DEFAULT CURRENT_TIMESTAMP NOT NULL,
updated_at timestamp with time zone DEFAULT CURRENT_TIMESTAMP NOT NULL
);
ALTER TABLE ONLY public.usage_http_audits ADD CONSTRAINT usage_http_audits_pkey PRIMARY KEY (request_id);
CREATE INDEX IF NOT EXISTS usage_http_audits_updated_at_idx ON public.usage_http_audits USING btree (updated_at);
ALTER TABLE ONLY public.usage_http_audits ADD CONSTRAINT usage_http_audits_request_id_fkey FOREIGN KEY (request_id) REFERENCES public.usage(request_id) ON DELETE CASCADE;
CREATE TABLE IF NOT EXISTS public.usage_routing_snapshots (
request_id character varying(128) NOT NULL,
candidate_id character varying(160),
candidate_index bigint,
key_name character varying(255),
planner_kind character varying(120),
route_family character varying(80),
route_kind character varying(80),
execution_path character varying(80),
local_execution_runtime_miss_reason character varying(120),
selected_provider_id character varying(64),
selected_endpoint_id character varying(64),
selected_provider_api_key_id character varying(64),
has_format_conversion boolean,
created_at bigint DEFAULT 0 NOT NULL,
updated_at bigint DEFAULT 0 NOT NULL
);
ALTER TABLE ONLY public.usage_routing_snapshots ADD CONSTRAINT usage_routing_snapshots_pkey PRIMARY KEY (request_id);
CREATE INDEX IF NOT EXISTS ix_usage_routing_snapshots_route_family_kind ON public.usage_routing_snapshots USING btree (route_family, route_kind);
CREATE INDEX IF NOT EXISTS ix_usage_routing_snapshots_candidate_id ON public.usage_routing_snapshots USING btree (candidate_id);
ALTER TABLE ONLY public.usage_routing_snapshots ADD CONSTRAINT usage_routing_snapshots_request_id_fkey FOREIGN KEY (request_id) REFERENCES public.usage(request_id) ON DELETE CASCADE;
CREATE TABLE IF NOT EXISTS public.usage_settlement_snapshots ( CREATE TABLE IF NOT EXISTS public.usage_settlement_snapshots (
request_id character varying(128) NOT NULL, request_id character varying(128) NOT NULL,
billing_status character varying(64) NOT NULL, billing_status character varying(64) NOT NULL,

View File

@@ -17,27 +17,7 @@ CREATE TABLE IF NOT EXISTS public.stats_hourly (
is_complete boolean DEFAULT false NOT NULL, is_complete boolean DEFAULT false NOT NULL,
aggregated_at bigint, aggregated_at bigint,
created_at bigint NOT NULL, created_at bigint NOT NULL,
updated_at bigint NOT NULL, updated_at bigint NOT NULL
response_time_sum_ms double precision DEFAULT 0 NOT NULL,
response_time_samples bigint DEFAULT 0 NOT NULL,
cache_hit_total_requests bigint DEFAULT 0 NOT NULL,
cache_hit_requests bigint DEFAULT 0 NOT NULL,
completed_total_requests bigint DEFAULT 0 NOT NULL,
completed_cache_hit_requests bigint DEFAULT 0 NOT NULL,
completed_input_tokens bigint DEFAULT 0 NOT NULL,
completed_cache_creation_tokens bigint DEFAULT 0 NOT NULL,
completed_cache_read_tokens bigint DEFAULT 0 NOT NULL,
completed_total_input_context bigint DEFAULT 0 NOT NULL,
completed_cache_creation_cost double precision DEFAULT 0 NOT NULL,
completed_cache_read_cost double precision DEFAULT 0 NOT NULL,
settled_total_cost double precision DEFAULT 0 NOT NULL,
settled_total_requests bigint DEFAULT 0 NOT NULL,
settled_input_tokens bigint DEFAULT 0 NOT NULL,
settled_output_tokens bigint DEFAULT 0 NOT NULL,
settled_cache_creation_tokens bigint DEFAULT 0 NOT NULL,
settled_cache_read_tokens bigint DEFAULT 0 NOT NULL,
settled_first_finalized_at_unix_secs bigint,
settled_last_finalized_at_unix_secs bigint
); );
ALTER TABLE ONLY public.stats_hourly ADD CONSTRAINT stats_hourly_pkey PRIMARY KEY (id); ALTER TABLE ONLY public.stats_hourly ADD CONSTRAINT stats_hourly_pkey PRIMARY KEY (id);
@@ -76,20 +56,7 @@ CREATE TABLE IF NOT EXISTS public.stats_hourly_user (
output_tokens bigint DEFAULT 0 NOT NULL, output_tokens bigint DEFAULT 0 NOT NULL,
total_cost double precision DEFAULT 0 NOT NULL, total_cost double precision DEFAULT 0 NOT NULL,
created_at bigint NOT NULL, created_at bigint NOT NULL,
updated_at bigint NOT NULL, updated_at bigint NOT NULL
cache_creation_tokens bigint DEFAULT 0 NOT NULL,
cache_read_tokens bigint DEFAULT 0 NOT NULL,
actual_total_cost double precision DEFAULT 0 NOT NULL,
response_time_sum_ms double precision DEFAULT 0 NOT NULL,
response_time_samples bigint DEFAULT 0 NOT NULL,
settled_total_cost double precision DEFAULT 0 NOT NULL,
settled_total_requests bigint DEFAULT 0 NOT NULL,
settled_input_tokens bigint DEFAULT 0 NOT NULL,
settled_output_tokens bigint DEFAULT 0 NOT NULL,
settled_cache_creation_tokens bigint DEFAULT 0 NOT NULL,
settled_cache_read_tokens bigint DEFAULT 0 NOT NULL,
settled_first_finalized_at_unix_secs bigint,
settled_last_finalized_at_unix_secs bigint
); );
ALTER TABLE ONLY public.stats_hourly_user ADD CONSTRAINT stats_hourly_user_pkey PRIMARY KEY (id); ALTER TABLE ONLY public.stats_hourly_user ADD CONSTRAINT stats_hourly_user_pkey PRIMARY KEY (id);
@@ -105,9 +72,7 @@ CREATE TABLE IF NOT EXISTS public.stats_hourly_user_model (
output_tokens bigint DEFAULT 0 NOT NULL, output_tokens bigint DEFAULT 0 NOT NULL,
total_cost double precision DEFAULT 0 NOT NULL, total_cost double precision DEFAULT 0 NOT NULL,
created_at bigint NOT NULL, created_at bigint NOT NULL,
updated_at bigint NOT NULL, updated_at bigint NOT NULL
response_time_sum_ms double precision DEFAULT 0 NOT NULL,
response_time_samples bigint DEFAULT 0 NOT NULL
); );
ALTER TABLE ONLY public.stats_hourly_user_model ADD CONSTRAINT stats_hourly_user_model_pkey PRIMARY KEY (id); ALTER TABLE ONLY public.stats_hourly_user_model ADD CONSTRAINT stats_hourly_user_model_pkey PRIMARY KEY (id);
@@ -137,9 +102,7 @@ CREATE TABLE IF NOT EXISTS public.stats_hourly_model (
total_cost double precision DEFAULT 0 NOT NULL, total_cost double precision DEFAULT 0 NOT NULL,
avg_response_time_ms double precision DEFAULT 0 NOT NULL, avg_response_time_ms double precision DEFAULT 0 NOT NULL,
created_at bigint NOT NULL, created_at bigint NOT NULL,
updated_at bigint NOT NULL, updated_at bigint NOT NULL
response_time_sum_ms double precision DEFAULT 0 NOT NULL,
response_time_samples bigint DEFAULT 0 NOT NULL
); );
ALTER TABLE ONLY public.stats_hourly_model ADD CONSTRAINT stats_hourly_model_pkey PRIMARY KEY (id); ALTER TABLE ONLY public.stats_hourly_model ADD CONSTRAINT stats_hourly_model_pkey PRIMARY KEY (id);
@@ -189,31 +152,7 @@ CREATE TABLE IF NOT EXISTS public.stats_daily (
p99_response_time_ms bigint, p99_response_time_ms bigint,
p50_first_byte_time_ms bigint, p50_first_byte_time_ms bigint,
p90_first_byte_time_ms bigint, p90_first_byte_time_ms bigint,
p99_first_byte_time_ms bigint, p99_first_byte_time_ms bigint
effective_input_tokens bigint DEFAULT 0 NOT NULL,
total_input_context bigint DEFAULT 0 NOT NULL,
response_time_sum_ms double precision DEFAULT 0 NOT NULL,
response_time_samples bigint DEFAULT 0 NOT NULL,
cache_creation_ephemeral_5m_tokens bigint DEFAULT 0 NOT NULL,
cache_creation_ephemeral_1h_tokens bigint DEFAULT 0 NOT NULL,
cache_hit_total_requests bigint DEFAULT 0 NOT NULL,
cache_hit_requests bigint DEFAULT 0 NOT NULL,
completed_total_requests bigint DEFAULT 0 NOT NULL,
completed_cache_hit_requests bigint DEFAULT 0 NOT NULL,
completed_input_tokens bigint DEFAULT 0 NOT NULL,
completed_cache_creation_tokens bigint DEFAULT 0 NOT NULL,
completed_cache_read_tokens bigint DEFAULT 0 NOT NULL,
completed_total_input_context bigint DEFAULT 0 NOT NULL,
completed_cache_creation_cost double precision DEFAULT 0 NOT NULL,
completed_cache_read_cost double precision DEFAULT 0 NOT NULL,
settled_total_cost double precision DEFAULT 0 NOT NULL,
settled_total_requests bigint DEFAULT 0 NOT NULL,
settled_input_tokens bigint DEFAULT 0 NOT NULL,
settled_output_tokens bigint DEFAULT 0 NOT NULL,
settled_cache_creation_tokens bigint DEFAULT 0 NOT NULL,
settled_cache_read_tokens bigint DEFAULT 0 NOT NULL,
settled_first_finalized_at_unix_secs bigint,
settled_last_finalized_at_unix_secs bigint
); );
ALTER TABLE ONLY public.stats_daily ADD CONSTRAINT stats_daily_pkey PRIMARY KEY (id); ALTER TABLE ONLY public.stats_daily ADD CONSTRAINT stats_daily_pkey PRIMARY KEY (id);
@@ -231,11 +170,7 @@ CREATE TABLE IF NOT EXISTS public.stats_daily_model (
total_cost double precision DEFAULT 0 NOT NULL, total_cost double precision DEFAULT 0 NOT NULL,
avg_response_time_ms double precision DEFAULT 0 NOT NULL, avg_response_time_ms double precision DEFAULT 0 NOT NULL,
created_at bigint NOT NULL, created_at bigint NOT NULL,
updated_at bigint NOT NULL, updated_at bigint NOT NULL
cache_creation_ephemeral_5m_tokens bigint DEFAULT 0 NOT NULL,
cache_creation_ephemeral_1h_tokens bigint DEFAULT 0 NOT NULL,
response_time_sum_ms double precision DEFAULT 0 NOT NULL,
response_time_samples bigint DEFAULT 0 NOT NULL
); );
ALTER TABLE ONLY public.stats_daily_model ADD CONSTRAINT stats_daily_model_pkey PRIMARY KEY (id); ALTER TABLE ONLY public.stats_daily_model ADD CONSTRAINT stats_daily_model_pkey PRIMARY KEY (id);
@@ -306,330 +241,9 @@ CREATE TABLE IF NOT EXISTS public.stats_user_daily (
total_cost double precision DEFAULT 0 NOT NULL, total_cost double precision DEFAULT 0 NOT NULL,
username character varying(255), username character varying(255),
created_at bigint NOT NULL, created_at bigint NOT NULL,
updated_at bigint NOT NULL, updated_at bigint NOT NULL
actual_total_cost double precision DEFAULT 0 NOT NULL,
response_time_sum_ms double precision DEFAULT 0 NOT NULL,
response_time_samples bigint DEFAULT 0 NOT NULL,
effective_input_tokens bigint DEFAULT 0 NOT NULL,
total_input_context bigint DEFAULT 0 NOT NULL,
cache_creation_cost double precision DEFAULT 0 NOT NULL,
cache_read_cost double precision DEFAULT 0 NOT NULL,
cache_creation_ephemeral_5m_tokens bigint DEFAULT 0 NOT NULL,
cache_creation_ephemeral_1h_tokens bigint DEFAULT 0 NOT NULL,
settled_total_cost double precision DEFAULT 0 NOT NULL,
settled_total_requests bigint DEFAULT 0 NOT NULL,
settled_input_tokens bigint DEFAULT 0 NOT NULL,
settled_output_tokens bigint DEFAULT 0 NOT NULL,
settled_cache_creation_tokens bigint DEFAULT 0 NOT NULL,
settled_cache_read_tokens bigint DEFAULT 0 NOT NULL,
settled_first_finalized_at_unix_secs bigint,
settled_last_finalized_at_unix_secs bigint
); );
ALTER TABLE ONLY public.stats_user_daily ADD CONSTRAINT stats_user_daily_pkey PRIMARY KEY (id); ALTER TABLE ONLY public.stats_user_daily ADD CONSTRAINT stats_user_daily_pkey PRIMARY KEY (id);
ALTER TABLE ONLY public.stats_user_daily ADD CONSTRAINT uq_stats_user_daily UNIQUE (date, user_id); ALTER TABLE ONLY public.stats_user_daily ADD CONSTRAINT uq_stats_user_daily UNIQUE (date, user_id);
CREATE TABLE IF NOT EXISTS public.stats_user_summary (
id character varying(64) NOT NULL,
user_id character varying(64) NOT NULL,
username character varying(255),
cutoff_date bigint NOT NULL,
all_time_requests bigint DEFAULT 0 NOT NULL,
all_time_success_requests bigint DEFAULT 0 NOT NULL,
all_time_error_requests bigint DEFAULT 0 NOT NULL,
all_time_input_tokens bigint DEFAULT 0 NOT NULL,
all_time_output_tokens bigint DEFAULT 0 NOT NULL,
all_time_cache_creation_tokens bigint DEFAULT 0 NOT NULL,
all_time_cache_read_tokens bigint DEFAULT 0 NOT NULL,
all_time_cost double precision DEFAULT 0 NOT NULL,
all_time_actual_cost double precision DEFAULT 0 NOT NULL,
active_days bigint DEFAULT 0 NOT NULL,
first_active_date bigint,
last_active_date bigint,
created_at bigint DEFAULT 0 NOT NULL,
updated_at bigint DEFAULT 0 NOT NULL
);
ALTER TABLE ONLY public.stats_user_summary ADD CONSTRAINT stats_user_summary_pkey PRIMARY KEY (id);
ALTER TABLE ONLY public.stats_user_summary ADD CONSTRAINT uq_stats_user_summary_user_id UNIQUE (user_id);
CREATE INDEX IF NOT EXISTS idx_stats_user_summary_cutoff_date ON public.stats_user_summary USING btree (cutoff_date);
CREATE TABLE IF NOT EXISTS public.stats_user_daily_model (
id character varying(64) NOT NULL,
user_id character varying(64) NOT NULL,
username character varying(255),
date bigint NOT NULL,
model character varying(255) NOT NULL,
total_requests bigint DEFAULT 0 NOT NULL,
success_requests bigint DEFAULT 0 NOT NULL,
input_tokens bigint DEFAULT 0 NOT NULL,
effective_input_tokens bigint DEFAULT 0 NOT NULL,
output_tokens bigint DEFAULT 0 NOT NULL,
total_tokens bigint DEFAULT 0 NOT NULL,
total_input_context bigint DEFAULT 0 NOT NULL,
cache_creation_tokens bigint DEFAULT 0 NOT NULL,
cache_creation_ephemeral_5m_tokens bigint DEFAULT 0 NOT NULL,
cache_creation_ephemeral_1h_tokens bigint DEFAULT 0 NOT NULL,
cache_read_tokens bigint DEFAULT 0 NOT NULL,
total_cost double precision DEFAULT 0 NOT NULL,
actual_total_cost double precision DEFAULT 0 NOT NULL,
response_time_sum_ms double precision DEFAULT 0 NOT NULL,
response_time_samples bigint DEFAULT 0 NOT NULL,
successful_response_time_sum_ms double precision DEFAULT 0 NOT NULL,
successful_response_time_samples bigint DEFAULT 0 NOT NULL,
created_at bigint DEFAULT 0 NOT NULL,
updated_at bigint DEFAULT 0 NOT NULL
);
ALTER TABLE ONLY public.stats_user_daily_model ADD CONSTRAINT stats_user_daily_model_pkey PRIMARY KEY (id);
ALTER TABLE ONLY public.stats_user_daily_model ADD CONSTRAINT uq_stats_user_daily_model_user_id_date_model UNIQUE (user_id, date, model);
CREATE INDEX IF NOT EXISTS idx_stats_user_daily_model_date ON public.stats_user_daily_model USING btree (date);
CREATE INDEX IF NOT EXISTS idx_stats_user_daily_model_user_id ON public.stats_user_daily_model USING btree (user_id);
CREATE TABLE IF NOT EXISTS public.stats_user_daily_provider (
id character varying(64) NOT NULL,
user_id character varying(64) NOT NULL,
username character varying(255),
date bigint NOT NULL,
provider_name character varying(255) NOT NULL,
total_requests bigint DEFAULT 0 NOT NULL,
success_requests bigint DEFAULT 0 NOT NULL,
input_tokens bigint DEFAULT 0 NOT NULL,
effective_input_tokens bigint DEFAULT 0 NOT NULL,
output_tokens bigint DEFAULT 0 NOT NULL,
total_tokens bigint DEFAULT 0 NOT NULL,
total_input_context bigint DEFAULT 0 NOT NULL,
cache_creation_tokens bigint DEFAULT 0 NOT NULL,
cache_creation_ephemeral_5m_tokens bigint DEFAULT 0 NOT NULL,
cache_creation_ephemeral_1h_tokens bigint DEFAULT 0 NOT NULL,
cache_read_tokens bigint DEFAULT 0 NOT NULL,
total_cost double precision DEFAULT 0 NOT NULL,
actual_total_cost double precision DEFAULT 0 NOT NULL,
response_time_sum_ms double precision DEFAULT 0 NOT NULL,
response_time_samples bigint DEFAULT 0 NOT NULL,
successful_response_time_sum_ms double precision DEFAULT 0 NOT NULL,
successful_response_time_samples bigint DEFAULT 0 NOT NULL,
created_at bigint DEFAULT 0 NOT NULL,
updated_at bigint DEFAULT 0 NOT NULL
);
ALTER TABLE ONLY public.stats_user_daily_provider ADD CONSTRAINT stats_user_daily_provider_pkey PRIMARY KEY (id);
ALTER TABLE ONLY public.stats_user_daily_provider ADD CONSTRAINT uq_stats_user_daily_provider_user_id_date_provider_name UNIQUE (user_id, date, provider_name);
CREATE INDEX IF NOT EXISTS idx_stats_user_daily_provider_date ON public.stats_user_daily_provider USING btree (date);
CREATE INDEX IF NOT EXISTS idx_stats_user_daily_provider_user_id ON public.stats_user_daily_provider USING btree (user_id);
CREATE TABLE IF NOT EXISTS public.stats_user_daily_api_format (
id character varying(64) NOT NULL,
user_id character varying(64) NOT NULL,
username character varying(255),
date bigint NOT NULL,
api_format character varying(255) NOT NULL,
total_requests bigint DEFAULT 0 NOT NULL,
success_requests bigint DEFAULT 0 NOT NULL,
input_tokens bigint DEFAULT 0 NOT NULL,
effective_input_tokens bigint DEFAULT 0 NOT NULL,
output_tokens bigint DEFAULT 0 NOT NULL,
total_tokens bigint DEFAULT 0 NOT NULL,
total_input_context bigint DEFAULT 0 NOT NULL,
cache_creation_tokens bigint DEFAULT 0 NOT NULL,
cache_creation_ephemeral_5m_tokens bigint DEFAULT 0 NOT NULL,
cache_creation_ephemeral_1h_tokens bigint DEFAULT 0 NOT NULL,
cache_read_tokens bigint DEFAULT 0 NOT NULL,
total_cost double precision DEFAULT 0 NOT NULL,
actual_total_cost double precision DEFAULT 0 NOT NULL,
response_time_sum_ms double precision DEFAULT 0 NOT NULL,
response_time_samples bigint DEFAULT 0 NOT NULL,
successful_response_time_sum_ms double precision DEFAULT 0 NOT NULL,
successful_response_time_samples bigint DEFAULT 0 NOT NULL,
created_at bigint DEFAULT 0 NOT NULL,
updated_at bigint DEFAULT 0 NOT NULL
);
ALTER TABLE ONLY public.stats_user_daily_api_format ADD CONSTRAINT stats_user_daily_api_format_pkey PRIMARY KEY (id);
ALTER TABLE ONLY public.stats_user_daily_api_format ADD CONSTRAINT uq_stats_user_daily_api_format_user_id_date_api_format UNIQUE (user_id, date, api_format);
CREATE INDEX IF NOT EXISTS idx_stats_user_daily_api_format_date ON public.stats_user_daily_api_format USING btree (date);
CREATE INDEX IF NOT EXISTS idx_stats_user_daily_api_format_user_id ON public.stats_user_daily_api_format USING btree (user_id);
CREATE TABLE IF NOT EXISTS public.stats_daily_model_provider (
id character varying(64) NOT NULL,
date bigint NOT NULL,
model character varying(255) NOT NULL,
provider_name character varying(255) NOT NULL,
total_requests bigint DEFAULT 0 NOT NULL,
total_tokens bigint DEFAULT 0 NOT NULL,
total_cost double precision DEFAULT 0 NOT NULL,
response_time_sum_ms double precision DEFAULT 0 NOT NULL,
response_time_samples bigint DEFAULT 0 NOT NULL,
created_at bigint DEFAULT 0 NOT NULL,
updated_at bigint DEFAULT 0 NOT NULL
);
ALTER TABLE ONLY public.stats_daily_model_provider ADD CONSTRAINT stats_daily_model_provider_pkey PRIMARY KEY (id);
ALTER TABLE ONLY public.stats_daily_model_provider ADD CONSTRAINT uq_stats_daily_model_provider_date_model_provider_name UNIQUE (date, model, provider_name);
CREATE INDEX IF NOT EXISTS idx_stats_daily_model_provider_date ON public.stats_daily_model_provider USING btree (date);
CREATE INDEX IF NOT EXISTS idx_stats_daily_model_provider_date_model_provider ON public.stats_daily_model_provider USING btree (date, model, provider_name);
CREATE TABLE IF NOT EXISTS public.stats_user_daily_model_provider (
id character varying(64) NOT NULL,
user_id character varying(64) NOT NULL,
username character varying(255),
date bigint NOT NULL,
model character varying(255) NOT NULL,
provider_name character varying(255) NOT NULL,
total_requests bigint DEFAULT 0 NOT NULL,
total_tokens bigint DEFAULT 0 NOT NULL,
total_cost double precision DEFAULT 0 NOT NULL,
response_time_sum_ms double precision DEFAULT 0 NOT NULL,
response_time_samples bigint DEFAULT 0 NOT NULL,
created_at bigint DEFAULT 0 NOT NULL,
updated_at bigint DEFAULT 0 NOT NULL
);
ALTER TABLE ONLY public.stats_user_daily_model_provider ADD CONSTRAINT stats_user_daily_model_provider_pkey PRIMARY KEY (id);
ALTER TABLE ONLY public.stats_user_daily_model_provider ADD CONSTRAINT uq_stats_user_daily_model_provider_user_id_date_model_provider_name UNIQUE (user_id, date, model, provider_name);
CREATE INDEX IF NOT EXISTS idx_stats_user_daily_model_provider_date ON public.stats_user_daily_model_provider USING btree (date);
CREATE INDEX IF NOT EXISTS idx_stats_user_daily_model_provider_user_date ON public.stats_user_daily_model_provider USING btree (user_id, date);
CREATE TABLE IF NOT EXISTS public.stats_daily_cost_savings (
id character varying(64) NOT NULL,
date bigint NOT NULL,
cache_read_tokens bigint DEFAULT 0 NOT NULL,
cache_read_cost double precision DEFAULT 0 NOT NULL,
cache_creation_cost double precision DEFAULT 0 NOT NULL,
estimated_full_cost double precision DEFAULT 0 NOT NULL,
created_at bigint DEFAULT 0 NOT NULL,
updated_at bigint DEFAULT 0 NOT NULL
);
ALTER TABLE ONLY public.stats_daily_cost_savings ADD CONSTRAINT stats_daily_cost_savings_pkey PRIMARY KEY (id);
ALTER TABLE ONLY public.stats_daily_cost_savings ADD CONSTRAINT uq_stats_daily_cost_savings_date UNIQUE (date);
CREATE INDEX IF NOT EXISTS idx_stats_daily_cost_savings_date ON public.stats_daily_cost_savings USING btree (date);
CREATE TABLE IF NOT EXISTS public.stats_daily_cost_savings_provider (
id character varying(64) NOT NULL,
date bigint NOT NULL,
provider_name character varying(255) NOT NULL,
cache_read_tokens bigint DEFAULT 0 NOT NULL,
cache_read_cost double precision DEFAULT 0 NOT NULL,
cache_creation_cost double precision DEFAULT 0 NOT NULL,
estimated_full_cost double precision DEFAULT 0 NOT NULL,
created_at bigint DEFAULT 0 NOT NULL,
updated_at bigint DEFAULT 0 NOT NULL
);
ALTER TABLE ONLY public.stats_daily_cost_savings_provider ADD CONSTRAINT stats_daily_cost_savings_provider_pkey PRIMARY KEY (id);
ALTER TABLE ONLY public.stats_daily_cost_savings_provider ADD CONSTRAINT uq_stats_daily_cost_savings_provider_date_provider_name UNIQUE (date, provider_name);
CREATE INDEX IF NOT EXISTS idx_stats_daily_cost_savings_provider_date ON public.stats_daily_cost_savings_provider USING btree (date);
CREATE INDEX IF NOT EXISTS idx_stats_daily_cost_savings_provider_date_provider ON public.stats_daily_cost_savings_provider USING btree (date, provider_name);
CREATE TABLE IF NOT EXISTS public.stats_daily_cost_savings_model (
id character varying(64) NOT NULL,
date bigint NOT NULL,
model character varying(255) NOT NULL,
cache_read_tokens bigint DEFAULT 0 NOT NULL,
cache_read_cost double precision DEFAULT 0 NOT NULL,
cache_creation_cost double precision DEFAULT 0 NOT NULL,
estimated_full_cost double precision DEFAULT 0 NOT NULL,
created_at bigint DEFAULT 0 NOT NULL,
updated_at bigint DEFAULT 0 NOT NULL
);
ALTER TABLE ONLY public.stats_daily_cost_savings_model ADD CONSTRAINT stats_daily_cost_savings_model_pkey PRIMARY KEY (id);
ALTER TABLE ONLY public.stats_daily_cost_savings_model ADD CONSTRAINT uq_stats_daily_cost_savings_model_date_model UNIQUE (date, model);
CREATE INDEX IF NOT EXISTS idx_stats_daily_cost_savings_model_date ON public.stats_daily_cost_savings_model USING btree (date);
CREATE INDEX IF NOT EXISTS idx_stats_daily_cost_savings_model_date_model ON public.stats_daily_cost_savings_model USING btree (date, model);
CREATE TABLE IF NOT EXISTS public.stats_daily_cost_savings_model_provider (
id character varying(64) NOT NULL,
date bigint NOT NULL,
model character varying(255) NOT NULL,
provider_name character varying(255) NOT NULL,
cache_read_tokens bigint DEFAULT 0 NOT NULL,
cache_read_cost double precision DEFAULT 0 NOT NULL,
cache_creation_cost double precision DEFAULT 0 NOT NULL,
estimated_full_cost double precision DEFAULT 0 NOT NULL,
created_at bigint DEFAULT 0 NOT NULL,
updated_at bigint DEFAULT 0 NOT NULL
);
ALTER TABLE ONLY public.stats_daily_cost_savings_model_provider ADD CONSTRAINT stats_daily_cost_savings_model_provider_pkey PRIMARY KEY (id);
ALTER TABLE ONLY public.stats_daily_cost_savings_model_provider ADD CONSTRAINT uq_stats_daily_cost_savings_model_provider_date_model_provider_name UNIQUE (date, model, provider_name);
CREATE INDEX IF NOT EXISTS idx_stats_daily_cost_savings_model_provider_date ON public.stats_daily_cost_savings_model_provider USING btree (date);
CREATE INDEX IF NOT EXISTS idx_stats_daily_cost_savings_model_provider_date_dims ON public.stats_daily_cost_savings_model_provider USING btree (date, model, provider_name);
CREATE TABLE IF NOT EXISTS public.stats_user_daily_cost_savings (
id character varying(64) NOT NULL,
user_id character varying(64) NOT NULL,
username character varying(255),
date bigint NOT NULL,
cache_read_tokens bigint DEFAULT 0 NOT NULL,
cache_read_cost double precision DEFAULT 0 NOT NULL,
cache_creation_cost double precision DEFAULT 0 NOT NULL,
estimated_full_cost double precision DEFAULT 0 NOT NULL,
created_at bigint DEFAULT 0 NOT NULL,
updated_at bigint DEFAULT 0 NOT NULL
);
ALTER TABLE ONLY public.stats_user_daily_cost_savings ADD CONSTRAINT stats_user_daily_cost_savings_pkey PRIMARY KEY (id);
ALTER TABLE ONLY public.stats_user_daily_cost_savings ADD CONSTRAINT uq_stats_user_daily_cost_savings_user_id_date UNIQUE (user_id, date);
CREATE INDEX IF NOT EXISTS idx_stats_user_daily_cost_savings_date ON public.stats_user_daily_cost_savings USING btree (date);
CREATE INDEX IF NOT EXISTS idx_stats_user_daily_cost_savings_user_date ON public.stats_user_daily_cost_savings USING btree (user_id, date);
CREATE TABLE IF NOT EXISTS public.stats_user_daily_cost_savings_provider (
id character varying(64) NOT NULL,
user_id character varying(64) NOT NULL,
username character varying(255),
date bigint NOT NULL,
provider_name character varying(255) NOT NULL,
cache_read_tokens bigint DEFAULT 0 NOT NULL,
cache_read_cost double precision DEFAULT 0 NOT NULL,
cache_creation_cost double precision DEFAULT 0 NOT NULL,
estimated_full_cost double precision DEFAULT 0 NOT NULL,
created_at bigint DEFAULT 0 NOT NULL,
updated_at bigint DEFAULT 0 NOT NULL
);
ALTER TABLE ONLY public.stats_user_daily_cost_savings_provider ADD CONSTRAINT stats_user_daily_cost_savings_provider_pkey PRIMARY KEY (id);
ALTER TABLE ONLY public.stats_user_daily_cost_savings_provider ADD CONSTRAINT uq_stats_user_daily_cost_savings_provider_user_id_date_provider_name UNIQUE (user_id, date, provider_name);
CREATE INDEX IF NOT EXISTS idx_stats_user_daily_cost_savings_provider_date ON public.stats_user_daily_cost_savings_provider USING btree (date);
CREATE INDEX IF NOT EXISTS idx_stats_user_daily_cost_savings_provider_user_date ON public.stats_user_daily_cost_savings_provider USING btree (user_id, date);
CREATE TABLE IF NOT EXISTS public.stats_user_daily_cost_savings_model (
id character varying(64) NOT NULL,
user_id character varying(64) NOT NULL,
username character varying(255),
date bigint NOT NULL,
model character varying(255) NOT NULL,
cache_read_tokens bigint DEFAULT 0 NOT NULL,
cache_read_cost double precision DEFAULT 0 NOT NULL,
cache_creation_cost double precision DEFAULT 0 NOT NULL,
estimated_full_cost double precision DEFAULT 0 NOT NULL,
created_at bigint DEFAULT 0 NOT NULL,
updated_at bigint DEFAULT 0 NOT NULL
);
ALTER TABLE ONLY public.stats_user_daily_cost_savings_model ADD CONSTRAINT stats_user_daily_cost_savings_model_pkey PRIMARY KEY (id);
ALTER TABLE ONLY public.stats_user_daily_cost_savings_model ADD CONSTRAINT uq_stats_user_daily_cost_savings_model_user_id_date_model UNIQUE (user_id, date, model);
CREATE INDEX IF NOT EXISTS idx_stats_user_daily_cost_savings_model_date ON public.stats_user_daily_cost_savings_model USING btree (date);
CREATE INDEX IF NOT EXISTS idx_stats_user_daily_cost_savings_model_user_date ON public.stats_user_daily_cost_savings_model USING btree (user_id, date);
CREATE TABLE IF NOT EXISTS public.stats_user_daily_cost_savings_model_provider (
id character varying(64) NOT NULL,
user_id character varying(64) NOT NULL,
username character varying(255),
date bigint NOT NULL,
model character varying(255) NOT NULL,
provider_name character varying(255) NOT NULL,
cache_read_tokens bigint DEFAULT 0 NOT NULL,
cache_read_cost double precision DEFAULT 0 NOT NULL,
cache_creation_cost double precision DEFAULT 0 NOT NULL,
estimated_full_cost double precision DEFAULT 0 NOT NULL,
created_at bigint DEFAULT 0 NOT NULL,
updated_at bigint DEFAULT 0 NOT NULL
);
ALTER TABLE ONLY public.stats_user_daily_cost_savings_model_provider ADD CONSTRAINT stats_user_daily_cost_savings_model_provider_pkey PRIMARY KEY (id);
ALTER TABLE ONLY public.stats_user_daily_cost_savings_model_provider ADD CONSTRAINT uq_stats_user_daily_cost_savings_model_provider_user_id_date_model_provider_name UNIQUE (user_id, date, model, provider_name);
CREATE INDEX IF NOT EXISTS idx_stats_user_daily_cost_savings_model_provider_date ON public.stats_user_daily_cost_savings_model_provider USING btree (date);
CREATE INDEX IF NOT EXISTS idx_stats_user_daily_cost_savings_model_provider_user_date ON public.stats_user_daily_cost_savings_model_provider USING btree (user_id, date);

View File

@@ -110,60 +110,6 @@ CREATE INDEX IF NOT EXISTS usage_request_id_idx ON "usage" (request_id);
CREATE INDEX IF NOT EXISTS usage_user_id_idx ON "usage" (user_id); CREATE INDEX IF NOT EXISTS usage_user_id_idx ON "usage" (user_id);
CREATE INDEX IF NOT EXISTS usage_wallet_id_idx ON "usage" (wallet_id); CREATE INDEX IF NOT EXISTS usage_wallet_id_idx ON "usage" (wallet_id);
CREATE TABLE IF NOT EXISTS usage_body_blobs (
body_ref TEXT PRIMARY KEY NOT NULL,
request_id TEXT NOT NULL,
body_field TEXT NOT NULL,
payload_gzip BLOB NOT NULL,
created_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP,
UNIQUE (request_id, body_field),
CONSTRAINT usage_body_blobs_request_id_fkey FOREIGN KEY (request_id) REFERENCES usage (request_id) ON DELETE CASCADE
);
CREATE INDEX IF NOT EXISTS usage_body_blobs_request_id_idx ON usage_body_blobs (request_id);
CREATE TABLE IF NOT EXISTS usage_http_audits (
request_id TEXT PRIMARY KEY NOT NULL,
request_headers TEXT,
provider_request_headers TEXT,
response_headers TEXT,
client_response_headers TEXT,
request_body_ref TEXT,
provider_request_body_ref TEXT,
response_body_ref TEXT,
client_response_body_ref TEXT,
request_body_state TEXT,
provider_request_body_state TEXT,
response_body_state TEXT,
client_response_body_state TEXT,
body_capture_mode TEXT NOT NULL DEFAULT 'none',
created_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT usage_http_audits_request_id_fkey FOREIGN KEY (request_id) REFERENCES usage (request_id) ON DELETE CASCADE
);
CREATE INDEX IF NOT EXISTS usage_http_audits_updated_at_idx ON usage_http_audits (updated_at);
CREATE TABLE IF NOT EXISTS usage_routing_snapshots (
request_id TEXT PRIMARY KEY NOT NULL,
candidate_id TEXT,
candidate_index INTEGER,
key_name TEXT,
planner_kind TEXT,
route_family TEXT,
route_kind TEXT,
execution_path TEXT,
local_execution_runtime_miss_reason TEXT,
selected_provider_id TEXT,
selected_endpoint_id TEXT,
selected_provider_api_key_id TEXT,
has_format_conversion INTEGER,
created_at INTEGER NOT NULL DEFAULT 0,
updated_at INTEGER NOT NULL DEFAULT 0,
CONSTRAINT usage_routing_snapshots_request_id_fkey FOREIGN KEY (request_id) REFERENCES usage (request_id) ON DELETE CASCADE
);
CREATE INDEX IF NOT EXISTS ix_usage_routing_snapshots_route_family_kind ON usage_routing_snapshots (route_family, route_kind);
CREATE INDEX IF NOT EXISTS ix_usage_routing_snapshots_candidate_id ON usage_routing_snapshots (candidate_id);
CREATE TABLE IF NOT EXISTS usage_settlement_snapshots ( CREATE TABLE IF NOT EXISTS usage_settlement_snapshots (
request_id TEXT PRIMARY KEY NOT NULL, request_id TEXT PRIMARY KEY NOT NULL,
billing_status TEXT NOT NULL, billing_status TEXT NOT NULL,

View File

@@ -18,26 +18,6 @@ CREATE TABLE IF NOT EXISTS stats_hourly (
aggregated_at INTEGER, aggregated_at INTEGER,
created_at INTEGER NOT NULL, created_at INTEGER NOT NULL,
updated_at INTEGER NOT NULL, updated_at INTEGER NOT NULL,
response_time_sum_ms REAL NOT NULL DEFAULT 0,
response_time_samples INTEGER NOT NULL DEFAULT 0,
cache_hit_total_requests INTEGER NOT NULL DEFAULT 0,
cache_hit_requests INTEGER NOT NULL DEFAULT 0,
completed_total_requests INTEGER NOT NULL DEFAULT 0,
completed_cache_hit_requests INTEGER NOT NULL DEFAULT 0,
completed_input_tokens INTEGER NOT NULL DEFAULT 0,
completed_cache_creation_tokens INTEGER NOT NULL DEFAULT 0,
completed_cache_read_tokens INTEGER NOT NULL DEFAULT 0,
completed_total_input_context INTEGER NOT NULL DEFAULT 0,
completed_cache_creation_cost REAL NOT NULL DEFAULT 0,
completed_cache_read_cost REAL NOT NULL DEFAULT 0,
settled_total_cost REAL NOT NULL DEFAULT 0,
settled_total_requests INTEGER NOT NULL DEFAULT 0,
settled_input_tokens INTEGER NOT NULL DEFAULT 0,
settled_output_tokens INTEGER NOT NULL DEFAULT 0,
settled_cache_creation_tokens INTEGER NOT NULL DEFAULT 0,
settled_cache_read_tokens INTEGER NOT NULL DEFAULT 0,
settled_first_finalized_at_unix_secs INTEGER,
settled_last_finalized_at_unix_secs INTEGER,
UNIQUE (hour_utc) UNIQUE (hour_utc)
); );
@@ -73,19 +53,6 @@ CREATE TABLE IF NOT EXISTS stats_hourly_user (
total_cost REAL NOT NULL DEFAULT 0, total_cost REAL NOT NULL DEFAULT 0,
created_at INTEGER NOT NULL, created_at INTEGER NOT NULL,
updated_at INTEGER NOT NULL, updated_at INTEGER NOT NULL,
cache_creation_tokens INTEGER NOT NULL DEFAULT 0,
cache_read_tokens INTEGER NOT NULL DEFAULT 0,
actual_total_cost REAL NOT NULL DEFAULT 0,
response_time_sum_ms REAL NOT NULL DEFAULT 0,
response_time_samples INTEGER NOT NULL DEFAULT 0,
settled_total_cost REAL NOT NULL DEFAULT 0,
settled_total_requests INTEGER NOT NULL DEFAULT 0,
settled_input_tokens INTEGER NOT NULL DEFAULT 0,
settled_output_tokens INTEGER NOT NULL DEFAULT 0,
settled_cache_creation_tokens INTEGER NOT NULL DEFAULT 0,
settled_cache_read_tokens INTEGER NOT NULL DEFAULT 0,
settled_first_finalized_at_unix_secs INTEGER,
settled_last_finalized_at_unix_secs INTEGER,
UNIQUE (hour_utc, user_id) UNIQUE (hour_utc, user_id)
); );
@@ -100,8 +67,6 @@ CREATE TABLE IF NOT EXISTS stats_hourly_user_model (
total_cost REAL NOT NULL DEFAULT 0, total_cost REAL NOT NULL DEFAULT 0,
created_at INTEGER NOT NULL, created_at INTEGER NOT NULL,
updated_at INTEGER NOT NULL, updated_at INTEGER NOT NULL,
response_time_sum_ms REAL NOT NULL DEFAULT 0,
response_time_samples INTEGER NOT NULL DEFAULT 0,
UNIQUE (hour_utc, user_id, model) UNIQUE (hour_utc, user_id, model)
); );
@@ -128,8 +93,6 @@ CREATE TABLE IF NOT EXISTS stats_hourly_model (
avg_response_time_ms REAL NOT NULL DEFAULT 0, avg_response_time_ms REAL NOT NULL DEFAULT 0,
created_at INTEGER NOT NULL, created_at INTEGER NOT NULL,
updated_at INTEGER NOT NULL, updated_at INTEGER NOT NULL,
response_time_sum_ms REAL NOT NULL DEFAULT 0,
response_time_samples INTEGER NOT NULL DEFAULT 0,
UNIQUE (hour_utc, model) UNIQUE (hour_utc, model)
); );
@@ -176,30 +139,6 @@ CREATE TABLE IF NOT EXISTS stats_daily (
p50_first_byte_time_ms INTEGER, p50_first_byte_time_ms INTEGER,
p90_first_byte_time_ms INTEGER, p90_first_byte_time_ms INTEGER,
p99_first_byte_time_ms INTEGER, p99_first_byte_time_ms INTEGER,
effective_input_tokens INTEGER NOT NULL DEFAULT 0,
total_input_context INTEGER NOT NULL DEFAULT 0,
response_time_sum_ms REAL NOT NULL DEFAULT 0,
response_time_samples INTEGER NOT NULL DEFAULT 0,
cache_creation_ephemeral_5m_tokens INTEGER NOT NULL DEFAULT 0,
cache_creation_ephemeral_1h_tokens INTEGER NOT NULL DEFAULT 0,
cache_hit_total_requests INTEGER NOT NULL DEFAULT 0,
cache_hit_requests INTEGER NOT NULL DEFAULT 0,
completed_total_requests INTEGER NOT NULL DEFAULT 0,
completed_cache_hit_requests INTEGER NOT NULL DEFAULT 0,
completed_input_tokens INTEGER NOT NULL DEFAULT 0,
completed_cache_creation_tokens INTEGER NOT NULL DEFAULT 0,
completed_cache_read_tokens INTEGER NOT NULL DEFAULT 0,
completed_total_input_context INTEGER NOT NULL DEFAULT 0,
completed_cache_creation_cost REAL NOT NULL DEFAULT 0,
completed_cache_read_cost REAL NOT NULL DEFAULT 0,
settled_total_cost REAL NOT NULL DEFAULT 0,
settled_total_requests INTEGER NOT NULL DEFAULT 0,
settled_input_tokens INTEGER NOT NULL DEFAULT 0,
settled_output_tokens INTEGER NOT NULL DEFAULT 0,
settled_cache_creation_tokens INTEGER NOT NULL DEFAULT 0,
settled_cache_read_tokens INTEGER NOT NULL DEFAULT 0,
settled_first_finalized_at_unix_secs INTEGER,
settled_last_finalized_at_unix_secs INTEGER,
UNIQUE (date) UNIQUE (date)
); );
@@ -216,10 +155,6 @@ CREATE TABLE IF NOT EXISTS stats_daily_model (
avg_response_time_ms REAL NOT NULL DEFAULT 0, avg_response_time_ms REAL NOT NULL DEFAULT 0,
created_at INTEGER NOT NULL, created_at INTEGER NOT NULL,
updated_at INTEGER NOT NULL, updated_at INTEGER NOT NULL,
cache_creation_ephemeral_5m_tokens INTEGER NOT NULL DEFAULT 0,
cache_creation_ephemeral_1h_tokens INTEGER NOT NULL DEFAULT 0,
response_time_sum_ms REAL NOT NULL DEFAULT 0,
response_time_samples INTEGER NOT NULL DEFAULT 0,
UNIQUE (date, model) UNIQUE (date, model)
); );
@@ -283,299 +218,6 @@ CREATE TABLE IF NOT EXISTS stats_user_daily (
username TEXT, username TEXT,
created_at INTEGER NOT NULL, created_at INTEGER NOT NULL,
updated_at INTEGER NOT NULL, updated_at INTEGER NOT NULL,
actual_total_cost REAL NOT NULL DEFAULT 0,
response_time_sum_ms REAL NOT NULL DEFAULT 0,
response_time_samples INTEGER NOT NULL DEFAULT 0,
effective_input_tokens INTEGER NOT NULL DEFAULT 0,
total_input_context INTEGER NOT NULL DEFAULT 0,
cache_creation_cost REAL NOT NULL DEFAULT 0,
cache_read_cost REAL NOT NULL DEFAULT 0,
cache_creation_ephemeral_5m_tokens INTEGER NOT NULL DEFAULT 0,
cache_creation_ephemeral_1h_tokens INTEGER NOT NULL DEFAULT 0,
settled_total_cost REAL NOT NULL DEFAULT 0,
settled_total_requests INTEGER NOT NULL DEFAULT 0,
settled_input_tokens INTEGER NOT NULL DEFAULT 0,
settled_output_tokens INTEGER NOT NULL DEFAULT 0,
settled_cache_creation_tokens INTEGER NOT NULL DEFAULT 0,
settled_cache_read_tokens INTEGER NOT NULL DEFAULT 0,
settled_first_finalized_at_unix_secs INTEGER,
settled_last_finalized_at_unix_secs INTEGER,
UNIQUE (date, user_id) UNIQUE (date, user_id)
); );
CREATE TABLE IF NOT EXISTS stats_user_summary (
id TEXT PRIMARY KEY NOT NULL,
user_id TEXT NOT NULL,
username TEXT,
cutoff_date INTEGER NOT NULL,
all_time_requests INTEGER NOT NULL DEFAULT 0,
all_time_success_requests INTEGER NOT NULL DEFAULT 0,
all_time_error_requests INTEGER NOT NULL DEFAULT 0,
all_time_input_tokens INTEGER NOT NULL DEFAULT 0,
all_time_output_tokens INTEGER NOT NULL DEFAULT 0,
all_time_cache_creation_tokens INTEGER NOT NULL DEFAULT 0,
all_time_cache_read_tokens INTEGER NOT NULL DEFAULT 0,
all_time_cost REAL NOT NULL DEFAULT 0,
all_time_actual_cost REAL NOT NULL DEFAULT 0,
active_days INTEGER NOT NULL DEFAULT 0,
first_active_date INTEGER,
last_active_date INTEGER,
created_at INTEGER NOT NULL DEFAULT 0,
updated_at INTEGER NOT NULL DEFAULT 0,
UNIQUE (user_id)
);
CREATE INDEX IF NOT EXISTS idx_stats_user_summary_cutoff_date ON stats_user_summary (cutoff_date);
CREATE TABLE IF NOT EXISTS stats_user_daily_model (
id TEXT PRIMARY KEY NOT NULL,
user_id TEXT NOT NULL,
username TEXT,
date INTEGER NOT NULL,
model TEXT NOT NULL,
total_requests INTEGER NOT NULL DEFAULT 0,
success_requests INTEGER NOT NULL DEFAULT 0,
input_tokens INTEGER NOT NULL DEFAULT 0,
effective_input_tokens INTEGER NOT NULL DEFAULT 0,
output_tokens INTEGER NOT NULL DEFAULT 0,
total_tokens INTEGER NOT NULL DEFAULT 0,
total_input_context INTEGER NOT NULL DEFAULT 0,
cache_creation_tokens INTEGER NOT NULL DEFAULT 0,
cache_creation_ephemeral_5m_tokens INTEGER NOT NULL DEFAULT 0,
cache_creation_ephemeral_1h_tokens INTEGER NOT NULL DEFAULT 0,
cache_read_tokens INTEGER NOT NULL DEFAULT 0,
total_cost REAL NOT NULL DEFAULT 0,
actual_total_cost REAL NOT NULL DEFAULT 0,
response_time_sum_ms REAL NOT NULL DEFAULT 0,
response_time_samples INTEGER NOT NULL DEFAULT 0,
successful_response_time_sum_ms REAL NOT NULL DEFAULT 0,
successful_response_time_samples INTEGER NOT NULL DEFAULT 0,
created_at INTEGER NOT NULL DEFAULT 0,
updated_at INTEGER NOT NULL DEFAULT 0,
UNIQUE (user_id, date, model)
);
CREATE INDEX IF NOT EXISTS idx_stats_user_daily_model_date ON stats_user_daily_model (date);
CREATE INDEX IF NOT EXISTS idx_stats_user_daily_model_user_id ON stats_user_daily_model (user_id);
CREATE TABLE IF NOT EXISTS stats_user_daily_provider (
id TEXT PRIMARY KEY NOT NULL,
user_id TEXT NOT NULL,
username TEXT,
date INTEGER NOT NULL,
provider_name TEXT NOT NULL,
total_requests INTEGER NOT NULL DEFAULT 0,
success_requests INTEGER NOT NULL DEFAULT 0,
input_tokens INTEGER NOT NULL DEFAULT 0,
effective_input_tokens INTEGER NOT NULL DEFAULT 0,
output_tokens INTEGER NOT NULL DEFAULT 0,
total_tokens INTEGER NOT NULL DEFAULT 0,
total_input_context INTEGER NOT NULL DEFAULT 0,
cache_creation_tokens INTEGER NOT NULL DEFAULT 0,
cache_creation_ephemeral_5m_tokens INTEGER NOT NULL DEFAULT 0,
cache_creation_ephemeral_1h_tokens INTEGER NOT NULL DEFAULT 0,
cache_read_tokens INTEGER NOT NULL DEFAULT 0,
total_cost REAL NOT NULL DEFAULT 0,
actual_total_cost REAL NOT NULL DEFAULT 0,
response_time_sum_ms REAL NOT NULL DEFAULT 0,
response_time_samples INTEGER NOT NULL DEFAULT 0,
successful_response_time_sum_ms REAL NOT NULL DEFAULT 0,
successful_response_time_samples INTEGER NOT NULL DEFAULT 0,
created_at INTEGER NOT NULL DEFAULT 0,
updated_at INTEGER NOT NULL DEFAULT 0,
UNIQUE (user_id, date, provider_name)
);
CREATE INDEX IF NOT EXISTS idx_stats_user_daily_provider_date ON stats_user_daily_provider (date);
CREATE INDEX IF NOT EXISTS idx_stats_user_daily_provider_user_id ON stats_user_daily_provider (user_id);
CREATE TABLE IF NOT EXISTS stats_user_daily_api_format (
id TEXT PRIMARY KEY NOT NULL,
user_id TEXT NOT NULL,
username TEXT,
date INTEGER NOT NULL,
api_format TEXT NOT NULL,
total_requests INTEGER NOT NULL DEFAULT 0,
success_requests INTEGER NOT NULL DEFAULT 0,
input_tokens INTEGER NOT NULL DEFAULT 0,
effective_input_tokens INTEGER NOT NULL DEFAULT 0,
output_tokens INTEGER NOT NULL DEFAULT 0,
total_tokens INTEGER NOT NULL DEFAULT 0,
total_input_context INTEGER NOT NULL DEFAULT 0,
cache_creation_tokens INTEGER NOT NULL DEFAULT 0,
cache_creation_ephemeral_5m_tokens INTEGER NOT NULL DEFAULT 0,
cache_creation_ephemeral_1h_tokens INTEGER NOT NULL DEFAULT 0,
cache_read_tokens INTEGER NOT NULL DEFAULT 0,
total_cost REAL NOT NULL DEFAULT 0,
actual_total_cost REAL NOT NULL DEFAULT 0,
response_time_sum_ms REAL NOT NULL DEFAULT 0,
response_time_samples INTEGER NOT NULL DEFAULT 0,
successful_response_time_sum_ms REAL NOT NULL DEFAULT 0,
successful_response_time_samples INTEGER NOT NULL DEFAULT 0,
created_at INTEGER NOT NULL DEFAULT 0,
updated_at INTEGER NOT NULL DEFAULT 0,
UNIQUE (user_id, date, api_format)
);
CREATE INDEX IF NOT EXISTS idx_stats_user_daily_api_format_date ON stats_user_daily_api_format (date);
CREATE INDEX IF NOT EXISTS idx_stats_user_daily_api_format_user_id ON stats_user_daily_api_format (user_id);
CREATE TABLE IF NOT EXISTS stats_daily_model_provider (
id TEXT PRIMARY KEY NOT NULL,
date INTEGER NOT NULL,
model TEXT NOT NULL,
provider_name TEXT NOT NULL,
total_requests INTEGER NOT NULL DEFAULT 0,
total_tokens INTEGER NOT NULL DEFAULT 0,
total_cost REAL NOT NULL DEFAULT 0,
response_time_sum_ms REAL NOT NULL DEFAULT 0,
response_time_samples INTEGER NOT NULL DEFAULT 0,
created_at INTEGER NOT NULL DEFAULT 0,
updated_at INTEGER NOT NULL DEFAULT 0,
UNIQUE (date, model, provider_name)
);
CREATE INDEX IF NOT EXISTS idx_stats_daily_model_provider_date ON stats_daily_model_provider (date);
CREATE INDEX IF NOT EXISTS idx_stats_daily_model_provider_date_model_provider ON stats_daily_model_provider (date, model, provider_name);
CREATE TABLE IF NOT EXISTS stats_user_daily_model_provider (
id TEXT PRIMARY KEY NOT NULL,
user_id TEXT NOT NULL,
username TEXT,
date INTEGER NOT NULL,
model TEXT NOT NULL,
provider_name TEXT NOT NULL,
total_requests INTEGER NOT NULL DEFAULT 0,
total_tokens INTEGER NOT NULL DEFAULT 0,
total_cost REAL NOT NULL DEFAULT 0,
response_time_sum_ms REAL NOT NULL DEFAULT 0,
response_time_samples INTEGER NOT NULL DEFAULT 0,
created_at INTEGER NOT NULL DEFAULT 0,
updated_at INTEGER NOT NULL DEFAULT 0,
UNIQUE (user_id, date, model, provider_name)
);
CREATE INDEX IF NOT EXISTS idx_stats_user_daily_model_provider_date ON stats_user_daily_model_provider (date);
CREATE INDEX IF NOT EXISTS idx_stats_user_daily_model_provider_user_date ON stats_user_daily_model_provider (user_id, date);
CREATE TABLE IF NOT EXISTS stats_daily_cost_savings (
id TEXT PRIMARY KEY NOT NULL,
date INTEGER NOT NULL,
cache_read_tokens INTEGER NOT NULL DEFAULT 0,
cache_read_cost REAL NOT NULL DEFAULT 0,
cache_creation_cost REAL NOT NULL DEFAULT 0,
estimated_full_cost REAL NOT NULL DEFAULT 0,
created_at INTEGER NOT NULL DEFAULT 0,
updated_at INTEGER NOT NULL DEFAULT 0,
UNIQUE (date)
);
CREATE INDEX IF NOT EXISTS idx_stats_daily_cost_savings_date ON stats_daily_cost_savings (date);
CREATE TABLE IF NOT EXISTS stats_daily_cost_savings_provider (
id TEXT PRIMARY KEY NOT NULL,
date INTEGER NOT NULL,
provider_name TEXT NOT NULL,
cache_read_tokens INTEGER NOT NULL DEFAULT 0,
cache_read_cost REAL NOT NULL DEFAULT 0,
cache_creation_cost REAL NOT NULL DEFAULT 0,
estimated_full_cost REAL NOT NULL DEFAULT 0,
created_at INTEGER NOT NULL DEFAULT 0,
updated_at INTEGER NOT NULL DEFAULT 0,
UNIQUE (date, provider_name)
);
CREATE INDEX IF NOT EXISTS idx_stats_daily_cost_savings_provider_date ON stats_daily_cost_savings_provider (date);
CREATE INDEX IF NOT EXISTS idx_stats_daily_cost_savings_provider_date_provider ON stats_daily_cost_savings_provider (date, provider_name);
CREATE TABLE IF NOT EXISTS stats_daily_cost_savings_model (
id TEXT PRIMARY KEY NOT NULL,
date INTEGER NOT NULL,
model TEXT NOT NULL,
cache_read_tokens INTEGER NOT NULL DEFAULT 0,
cache_read_cost REAL NOT NULL DEFAULT 0,
cache_creation_cost REAL NOT NULL DEFAULT 0,
estimated_full_cost REAL NOT NULL DEFAULT 0,
created_at INTEGER NOT NULL DEFAULT 0,
updated_at INTEGER NOT NULL DEFAULT 0,
UNIQUE (date, model)
);
CREATE INDEX IF NOT EXISTS idx_stats_daily_cost_savings_model_date ON stats_daily_cost_savings_model (date);
CREATE INDEX IF NOT EXISTS idx_stats_daily_cost_savings_model_date_model ON stats_daily_cost_savings_model (date, model);
CREATE TABLE IF NOT EXISTS stats_daily_cost_savings_model_provider (
id TEXT PRIMARY KEY NOT NULL,
date INTEGER NOT NULL,
model TEXT NOT NULL,
provider_name TEXT NOT NULL,
cache_read_tokens INTEGER NOT NULL DEFAULT 0,
cache_read_cost REAL NOT NULL DEFAULT 0,
cache_creation_cost REAL NOT NULL DEFAULT 0,
estimated_full_cost REAL NOT NULL DEFAULT 0,
created_at INTEGER NOT NULL DEFAULT 0,
updated_at INTEGER NOT NULL DEFAULT 0,
UNIQUE (date, model, provider_name)
);
CREATE INDEX IF NOT EXISTS idx_stats_daily_cost_savings_model_provider_date ON stats_daily_cost_savings_model_provider (date);
CREATE INDEX IF NOT EXISTS idx_stats_daily_cost_savings_model_provider_date_dims ON stats_daily_cost_savings_model_provider (date, model, provider_name);
CREATE TABLE IF NOT EXISTS stats_user_daily_cost_savings (
id TEXT PRIMARY KEY NOT NULL,
user_id TEXT NOT NULL,
username TEXT,
date INTEGER NOT NULL,
cache_read_tokens INTEGER NOT NULL DEFAULT 0,
cache_read_cost REAL NOT NULL DEFAULT 0,
cache_creation_cost REAL NOT NULL DEFAULT 0,
estimated_full_cost REAL NOT NULL DEFAULT 0,
created_at INTEGER NOT NULL DEFAULT 0,
updated_at INTEGER NOT NULL DEFAULT 0,
UNIQUE (user_id, date)
);
CREATE INDEX IF NOT EXISTS idx_stats_user_daily_cost_savings_date ON stats_user_daily_cost_savings (date);
CREATE INDEX IF NOT EXISTS idx_stats_user_daily_cost_savings_user_date ON stats_user_daily_cost_savings (user_id, date);
CREATE TABLE IF NOT EXISTS stats_user_daily_cost_savings_provider (
id TEXT PRIMARY KEY NOT NULL,
user_id TEXT NOT NULL,
username TEXT,
date INTEGER NOT NULL,
provider_name TEXT NOT NULL,
cache_read_tokens INTEGER NOT NULL DEFAULT 0,
cache_read_cost REAL NOT NULL DEFAULT 0,
cache_creation_cost REAL NOT NULL DEFAULT 0,
estimated_full_cost REAL NOT NULL DEFAULT 0,
created_at INTEGER NOT NULL DEFAULT 0,
updated_at INTEGER NOT NULL DEFAULT 0,
UNIQUE (user_id, date, provider_name)
);
CREATE INDEX IF NOT EXISTS idx_stats_user_daily_cost_savings_provider_date ON stats_user_daily_cost_savings_provider (date);
CREATE INDEX IF NOT EXISTS idx_stats_user_daily_cost_savings_provider_user_date ON stats_user_daily_cost_savings_provider (user_id, date);
CREATE TABLE IF NOT EXISTS stats_user_daily_cost_savings_model (
id TEXT PRIMARY KEY NOT NULL,
user_id TEXT NOT NULL,
username TEXT,
date INTEGER NOT NULL,
model TEXT NOT NULL,
cache_read_tokens INTEGER NOT NULL DEFAULT 0,
cache_read_cost REAL NOT NULL DEFAULT 0,
cache_creation_cost REAL NOT NULL DEFAULT 0,
estimated_full_cost REAL NOT NULL DEFAULT 0,
created_at INTEGER NOT NULL DEFAULT 0,
updated_at INTEGER NOT NULL DEFAULT 0,
UNIQUE (user_id, date, model)
);
CREATE INDEX IF NOT EXISTS idx_stats_user_daily_cost_savings_model_date ON stats_user_daily_cost_savings_model (date);
CREATE INDEX IF NOT EXISTS idx_stats_user_daily_cost_savings_model_user_date ON stats_user_daily_cost_savings_model (user_id, date);
CREATE TABLE IF NOT EXISTS stats_user_daily_cost_savings_model_provider (
id TEXT PRIMARY KEY NOT NULL,
user_id TEXT NOT NULL,
username TEXT,
date INTEGER NOT NULL,
model TEXT NOT NULL,
provider_name TEXT NOT NULL,
cache_read_tokens INTEGER NOT NULL DEFAULT 0,
cache_read_cost REAL NOT NULL DEFAULT 0,
cache_creation_cost REAL NOT NULL DEFAULT 0,
estimated_full_cost REAL NOT NULL DEFAULT 0,
created_at INTEGER NOT NULL DEFAULT 0,
updated_at INTEGER NOT NULL DEFAULT 0,
UNIQUE (user_id, date, model, provider_name)
);
CREATE INDEX IF NOT EXISTS idx_stats_user_daily_cost_savings_model_provider_date ON stats_user_daily_cost_savings_model_provider (date);
CREATE INDEX IF NOT EXISTS idx_stats_user_daily_cost_savings_model_provider_user_date ON stats_user_daily_cost_savings_model_provider (user_id, date);

View File

@@ -554,269 +554,6 @@ columns = ["user_id"]
name = "usage_wallet_id_idx" name = "usage_wallet_id_idx"
columns = ["wallet_id"] columns = ["wallet_id"]
[table.usage_body_blobs]
domain = "usage"
order = 12
primary_key = ["body_ref"]
[[table.usage_body_blobs.columns]]
name = "body_ref"
type = "text"
length = 160
[[table.usage_body_blobs.columns]]
name = "request_id"
type = "text"
length = 128
[[table.usage_body_blobs.columns]]
name = "body_field"
type = "text"
length = 64
[[table.usage_body_blobs.columns]]
name = "payload_gzip"
type = "bytes"
[[table.usage_body_blobs.columns]]
name = "created_at"
type = "timestamp"
default = { raw = "CURRENT_TIMESTAMP" }
driver = { mysql = { type = "TIMESTAMP" }, sqlite = { type = "TEXT" } }
[[table.usage_body_blobs.columns]]
name = "updated_at"
type = "timestamp"
default = { raw = "CURRENT_TIMESTAMP" }
driver = { mysql = { type = "TIMESTAMP" }, sqlite = { type = "TEXT" } }
[[table.usage_body_blobs.uniques]]
name = "usage_body_blobs_request_id_field_key"
columns = ["request_id", "body_field"]
[[table.usage_body_blobs.indexes]]
name = "usage_body_blobs_request_id_idx"
columns = ["request_id"]
[[table.usage_body_blobs.foreign_keys]]
name = "usage_body_blobs_request_id_fkey"
columns = ["request_id"]
references_table = "usage"
references_columns = ["request_id"]
on_delete = "cascade"
[table.usage_http_audits]
domain = "usage"
order = 14
primary_key = ["request_id"]
[[table.usage_http_audits.columns]]
name = "request_id"
type = "text"
length = 128
[[table.usage_http_audits.columns]]
name = "request_headers"
type = "json"
nullable = true
[[table.usage_http_audits.columns]]
name = "provider_request_headers"
type = "json"
nullable = true
[[table.usage_http_audits.columns]]
name = "response_headers"
type = "json"
nullable = true
[[table.usage_http_audits.columns]]
name = "client_response_headers"
type = "json"
nullable = true
[[table.usage_http_audits.columns]]
name = "request_body_ref"
type = "text"
length = 160
nullable = true
[[table.usage_http_audits.columns]]
name = "provider_request_body_ref"
type = "text"
length = 160
nullable = true
[[table.usage_http_audits.columns]]
name = "response_body_ref"
type = "text"
length = 160
nullable = true
[[table.usage_http_audits.columns]]
name = "client_response_body_ref"
type = "text"
length = 160
nullable = true
[[table.usage_http_audits.columns]]
name = "request_body_state"
type = "text"
length = 32
nullable = true
[[table.usage_http_audits.columns]]
name = "provider_request_body_state"
type = "text"
length = 32
nullable = true
[[table.usage_http_audits.columns]]
name = "response_body_state"
type = "text"
length = 32
nullable = true
[[table.usage_http_audits.columns]]
name = "client_response_body_state"
type = "text"
length = 32
nullable = true
[[table.usage_http_audits.columns]]
name = "body_capture_mode"
type = "text"
length = 32
default = "none"
[[table.usage_http_audits.columns]]
name = "created_at"
type = "timestamp"
default = { raw = "CURRENT_TIMESTAMP" }
driver = { mysql = { type = "TIMESTAMP" }, sqlite = { type = "TEXT" } }
[[table.usage_http_audits.columns]]
name = "updated_at"
type = "timestamp"
default = { raw = "CURRENT_TIMESTAMP" }
driver = { mysql = { type = "TIMESTAMP" }, sqlite = { type = "TEXT" } }
[[table.usage_http_audits.indexes]]
name = "usage_http_audits_updated_at_idx"
columns = ["updated_at"]
[[table.usage_http_audits.foreign_keys]]
name = "usage_http_audits_request_id_fkey"
columns = ["request_id"]
references_table = "usage"
references_columns = ["request_id"]
on_delete = "cascade"
[table.usage_routing_snapshots]
domain = "usage"
order = 16
primary_key = ["request_id"]
[[table.usage_routing_snapshots.columns]]
name = "request_id"
type = "text"
length = 128
[[table.usage_routing_snapshots.columns]]
name = "candidate_id"
type = "text"
length = 160
nullable = true
[[table.usage_routing_snapshots.columns]]
name = "candidate_index"
type = "int64"
nullable = true
[[table.usage_routing_snapshots.columns]]
name = "key_name"
type = "text"
length = 255
nullable = true
[[table.usage_routing_snapshots.columns]]
name = "planner_kind"
type = "text"
length = 120
nullable = true
[[table.usage_routing_snapshots.columns]]
name = "route_family"
type = "text"
length = 80
nullable = true
[[table.usage_routing_snapshots.columns]]
name = "route_kind"
type = "text"
length = 80
nullable = true
[[table.usage_routing_snapshots.columns]]
name = "execution_path"
type = "text"
length = 80
nullable = true
[[table.usage_routing_snapshots.columns]]
name = "local_execution_runtime_miss_reason"
type = "text"
length = 120
nullable = true
[[table.usage_routing_snapshots.columns]]
name = "selected_provider_id"
type = "text_id"
length = 64
nullable = true
[[table.usage_routing_snapshots.columns]]
name = "selected_endpoint_id"
type = "text_id"
length = 64
nullable = true
[[table.usage_routing_snapshots.columns]]
name = "selected_provider_api_key_id"
type = "text_id"
length = 64
nullable = true
[[table.usage_routing_snapshots.columns]]
name = "has_format_conversion"
type = "bool"
nullable = true
[[table.usage_routing_snapshots.columns]]
name = "created_at"
type = "unix_seconds"
default = 0
[[table.usage_routing_snapshots.columns]]
name = "updated_at"
type = "unix_seconds"
default = 0
[[table.usage_routing_snapshots.indexes]]
name = "ix_usage_routing_snapshots_route_family_kind"
columns = ["route_family", "route_kind"]
[[table.usage_routing_snapshots.indexes]]
name = "ix_usage_routing_snapshots_candidate_id"
columns = ["candidate_id"]
[[table.usage_routing_snapshots.foreign_keys]]
name = "usage_routing_snapshots_request_id_fkey"
columns = ["request_id"]
references_table = "usage"
references_columns = ["request_id"]
on_delete = "cascade"
[table.usage_settlement_snapshots] [table.usage_settlement_snapshots]
domain = "usage" domain = "usage"
order = 20 order = 20

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -603,8 +603,6 @@ fn mysql_and_sqlite_migrations_include_enabled_incrementals() {
20260512000000, 20260512000000,
20260512090000, 20260512090000,
20260512110000, 20260512110000,
20260513000000,
20260514000000,
] ]
); );
} }

View File

@@ -75,10 +75,11 @@ The script keeps the production cutover window short:
`AETHER_GATEWAY_DATA_ENCRYPTION_KEY`, admin settings, port, and app config. `AETHER_GATEWAY_DATA_ENCRYPTION_KEY`, admin settings, port, and app config.
3. Installs the single-node release with `install.sh --mode single-node --skip-start`. 3. Installs the single-node release with `install.sh --mode single-node --skip-start`.
4. Preflights SQLite migrations with the installed single-node binary. 4. Preflights SQLite migrations with the installed single-node binary.
5. Pulls the target single-node image, confirms its `copy` command supports the 5. Pulls the target single-node image, confirms its `copy` command is available,
current migration domains, and verifies that its Docker image ID matches the and verifies that its Docker image ID matches the currently running source
currently running source `app` image ID. `app` image ID.
6. Checks for non-empty Postgres tables not covered by the migration domains. 6. Uses the target SQLite schema as the migration plan: same-name source
Postgres tables and columns are copied into the temporary SQLite DB.
7. Applies the compressed body and HTTP body detail policy. The default is full, 7. Applies the compressed body and HTTP body detail policy. The default is full,
and you can opt into an omit mode for large artifacts. and you can opt into an omit mode for large artifacts.
8. Checks that the work directory and target SQLite directory have enough free 8. Checks that the work directory and target SQLite directory have enough free
@@ -93,8 +94,8 @@ The image check compares Docker image IDs, not just tag strings. If both source
and target say `latest` but resolve to different image IDs, migration stops. and target say `latest` but resolve to different image IDs, migration stops.
Upgrade the source PG Compose `app` to the target single-node version first, Upgrade the source PG Compose `app` to the target single-node version first,
verify it is healthy, then run the migration. The scripts also check that the verify it is healthy, then run the migration. The scripts also check that the
target image supports `stats`, `auxiliary`, and the request-body omit flag; using target image supports direct copy and the request-body omit flag; using a new
a new script with an old image stops before cutover to avoid missing data. script with an old image stops before cutover to avoid missing data.
## Production Cutover ## Production Cutover
@@ -175,16 +176,16 @@ you want to inspect the stopped source deployment manually instead.
## Data Coverage Guard ## Data Coverage Guard
The current migration covers these persistent domains: users, API keys, The migration does not maintain a separate business-domain table list. The
providers, provider keys, endpoints, models, global models, auth modules, OAuth target single-node image first builds a temporary SQLite database with its
links, user groups, proxy nodes, system configs, wallets, usage, and billing normal migrations, then `aether-gateway copy` reads that SQLite schema and copies
data. matching public Postgres tables and columns.
Before stopping the app, and again after the source app has stopped, the script If the source Postgres database has a non-empty public table that does not exist
checks the source Postgres database for non-empty tables outside that migration in the target SQLite schema, the copy stops instead of silently dropping it. It
coverage. It does not run source Postgres migrations or backfills during the ignores lifecycle metadata tables such as `_sqlx_migrations` and
cutover. It ignores lifecycle metadata tables such as `_sqlx_migrations` and `schema_backfills`. Extra source columns that are absent from the target schema
`schema_backfills`. Any other non-empty uncovered table blocks the migration. are not copied.
## Request Body Detail Policy ## Request Body Detail Policy
@@ -220,15 +221,6 @@ scripts/migrate-pg-to-single-node.sh \
`omit` only skips writing those large artifacts and detail tables into the `omit` only skips writing those large artifacts and detail tables into the
target SQLite database. It does not delete or clear the source Postgres data. target SQLite database. It does not delete or clear the source Postgres data.
If a table is intentionally excluded, allow it explicitly:
```bash
scripts/migrate-pg-to-single-node.sh \
--allow-non-exported-table legacy_custom_table
```
Use that only after confirming the table is not required in the single-node target.
## Notes ## Notes
- Single Node requires root or sudo because it writes `/opt/aether`, `/etc/aether`, and - Single Node requires root or sudo because it writes `/opt/aether`, `/etc/aether`, and

View File

@@ -71,9 +71,10 @@ PG Compose 文件,并确认该 Compose 配置里存在默认的 `app` 和 `pos
3. 执行 `install.sh --mode single-node --skip-start`,提前安装 single-node 3. 执行 `install.sh --mode single-node --skip-start`,提前安装 single-node
release但不启动服务。 release但不启动服务。
4. 使用已安装的 single-node 二进制预检 SQLite schema migration。 4. 使用已安装的 single-node 二进制预检 SQLite schema migration。
5. 拉取目标 single-node 镜像,确认其 `copy` 命令支持当前迁移域,并检查源 5. 拉取目标 single-node 镜像,确认其 `copy` 命令可用,并检查源 `app`
`app` 当前运行镜像 ID 与目标镜像 ID 一致。 当前运行镜像 ID 与目标镜像 ID 一致。
6. 检查 Postgres 里是否存在当前迁移域没有覆盖、但又非空的表。 6. 以目标 SQLite schema 作为迁移计划:把源 Postgres 中同名表、同名字段
复制到临时 SQLite DB。
7. 检查请求体明细迁移策略;默认全部迁移,也可以选择只跳过请求体明细。 7. 检查请求体明细迁移策略;默认全部迁移,也可以选择只跳过请求体明细。
8. 检查 work-dir 和目标 SQLite 目录是否有足够空间容纳临时库和正式库。 8. 检查 work-dir 和目标 SQLite 目录是否有足够空间容纳临时库和正式库。
9. 只停止源 Compose 的 `app` 服务,保留 Postgres 和 Redis 运行,方便回滚。 9. 只停止源 Compose 的 `app` 服务,保留 Postgres 和 Redis 运行,方便回滚。
@@ -84,8 +85,8 @@ PG Compose 文件,并确认该 Compose 配置里存在默认的 `app` 和 `pos
镜像一致性检查比较的是 Docker 镜像 ID不只是 tag 字符串。即使源和目标都写着 镜像一致性检查比较的是 Docker 镜像 ID不只是 tag 字符串。即使源和目标都写着
`latest`,只要实际镜像 ID 不同,迁移也会中止。请先把源 PG Compose 的 `app` `latest`,只要实际镜像 ID 不同,迁移也会中止。请先把源 PG Compose 的 `app`
升级到目标 single-node 相同版本,确认运行正常后再迁移。迁移脚本也会检查目标镜像 升级到目标 single-node 相同版本,确认运行正常后再迁移。迁移脚本也会检查目标镜像
是否支持 `stats``auxiliary` 和请求体跳过开关;如果只是换了脚本但镜像还是旧版本, 是否支持直接 copy 和请求体跳过开关;如果只是换了脚本但镜像还是旧版本,脚本会
脚本会直接中止,避免漏迁。 直接中止,避免漏迁。
## 生产切换 ## 生产切换
@@ -166,14 +167,13 @@ docker compose -f docker-compose.yml up -d app
## 数据覆盖保护 ## 数据覆盖保护
当前迁移覆盖的持久化域包括用户、API Key、供应商、供应商 Key、 迁移不再维护一份额外的业务表清单。目标 single-node 镜像会先用正常
端点、模型、全局模型、认证模块、OAuth 关联、用户组、代理节点、系统配置、 migrations 建出临时 SQLite 数据库,然后 `aether-gateway copy` 读取这个
钱包、用量和计费数据 SQLite schema把源 Postgres 里同名表、同名字段复制过去
脚本会在停机前,以及源 `app` 停止之后,再检查一次源 Postgres如果发现 如果源 Postgres 里存在非空 public 表,但目标 SQLite schema 中没有同名表,
当前迁移域没有覆盖的非空表,会直接中止迁移,避免漏迁。切换期间不会对源 copy 会直接中止,不会静默丢弃。生命周期元数据表 `_sqlx_migrations`
Postgres 执行 migrations 或 backfills。生命周期元数据表 `_sqlx_migrations` `schema_backfills` 会被忽略。源表中存在但目标 SQLite 不存在的额外字段不会复制。
`schema_backfills` 会被忽略。
## 请求体明细策略 ## 请求体明细策略
@@ -206,15 +206,6 @@ scripts/migrate-pg-to-single-node.sh \
`omit` 只是不把这些大字段和明细表写进目标 SQLite不会删除或清空源 Postgres。 `omit` 只是不把这些大字段和明细表写进目标 SQLite不会删除或清空源 Postgres。
如果某个表确认不需要迁移,可以显式允许:
```bash
scripts/migrate-pg-to-single-node.sh \
--allow-non-exported-table legacy_custom_table
```
只有在确认该表对 single-node 目标库不重要时才这样做。
## 注意事项 ## 注意事项
- single-node 安装需要 root 或 sudo 权限,因为会写入 `/opt/aether` - single-node 安装需要 root 或 sudo 权限,因为会写入 `/opt/aether`

View File

@@ -62,7 +62,6 @@ MIGRATE_REPLACE_TARGET_COMPOSE="false"
MIGRATE_KEEP_SOURCE_STOPPED_ON_ERROR="false" MIGRATE_KEEP_SOURCE_STOPPED_ON_ERROR="false"
MIGRATE_INTERACTIVE="false" MIGRATE_INTERACTIVE="false"
MIGRATE_REQUEST_BODY_MODE="" MIGRATE_REQUEST_BODY_MODE=""
MIGRATE_ALLOW_NON_EXPORTED_TABLES=()
usage() { usage() {
cat <<'EOF' cat <<'EOF'
@@ -105,8 +104,6 @@ Options:
Source compose Postgres service for migration Source compose Postgres service for migration
--single-node-service NAME --single-node-service NAME
Target compose service for --mode compose-single-node migration Target compose service for --mode compose-single-node migration
--allow-non-exported-table TABLE
Allow one source table outside export coverage to be non-empty
--replace-existing Allow replacing an existing target SQLite DB during migration --replace-existing Allow replacing an existing target SQLite DB during migration
--replace-target-compose --replace-target-compose
Overwrite target compose file from the single-node template during migration Overwrite target compose file from the single-node template during migration
@@ -343,11 +340,6 @@ parse_args() {
MIGRATE_SINGLE_NODE_SERVICE="$2" MIGRATE_SINGLE_NODE_SERVICE="$2"
shift 2 shift 2
;; ;;
--allow-non-exported-table)
[[ $# -ge 2 ]] || die "--allow-non-exported-table requires a table name"
MIGRATE_ALLOW_NON_EXPORTED_TABLES+=("$2")
shift 2
;;
--replace-existing) --replace-existing)
MIGRATE_REPLACE_EXISTING="true" MIGRATE_REPLACE_EXISTING="true"
shift shift
@@ -1007,7 +999,6 @@ migration_options_requested() {
[[ "${MIGRATE_REPLACE_TARGET_COMPOSE}" == "true" ]] && return 0 [[ "${MIGRATE_REPLACE_TARGET_COMPOSE}" == "true" ]] && return 0
[[ -n "${MIGRATE_REQUEST_BODY_MODE}" ]] && return 0 [[ -n "${MIGRATE_REQUEST_BODY_MODE}" ]] && return 0
[[ "${MIGRATE_KEEP_SOURCE_STOPPED_ON_ERROR}" == "true" ]] && return 0 [[ "${MIGRATE_KEEP_SOURCE_STOPPED_ON_ERROR}" == "true" ]] && return 0
[[ "${#MIGRATE_ALLOW_NON_EXPORTED_TABLES[@]}" -gt 0 ]] && return 0
return 1 return 1
} }
@@ -1353,9 +1344,6 @@ run_compose_single_node_migration() {
[[ -z "${MIGRATE_APP_SERVICE}" ]] || migrate_args+=(--app-service "${MIGRATE_APP_SERVICE}") [[ -z "${MIGRATE_APP_SERVICE}" ]] || migrate_args+=(--app-service "${MIGRATE_APP_SERVICE}")
[[ -z "${MIGRATE_POSTGRES_SERVICE}" ]] || migrate_args+=(--postgres-service "${MIGRATE_POSTGRES_SERVICE}") [[ -z "${MIGRATE_POSTGRES_SERVICE}" ]] || migrate_args+=(--postgres-service "${MIGRATE_POSTGRES_SERVICE}")
[[ -z "${MIGRATE_SINGLE_NODE_SERVICE}" ]] || migrate_args+=(--single-node-service "${MIGRATE_SINGLE_NODE_SERVICE}") [[ -z "${MIGRATE_SINGLE_NODE_SERVICE}" ]] || migrate_args+=(--single-node-service "${MIGRATE_SINGLE_NODE_SERVICE}")
for table in "${MIGRATE_ALLOW_NON_EXPORTED_TABLES[@]}"; do
migrate_args+=(--allow-non-exported-table "${table}")
done
[[ "${MIGRATE_REPLACE_EXISTING}" != "true" ]] || migrate_args+=(--replace-existing) [[ "${MIGRATE_REPLACE_EXISTING}" != "true" ]] || migrate_args+=(--replace-existing)
[[ "${MIGRATE_REPLACE_TARGET_COMPOSE}" != "true" ]] || migrate_args+=(--replace-target-compose) [[ "${MIGRATE_REPLACE_TARGET_COMPOSE}" != "true" ]] || migrate_args+=(--replace-target-compose)
[[ -z "${MIGRATE_REQUEST_BODY_MODE}" ]] || migrate_args+=(--request-body-mode "${MIGRATE_REQUEST_BODY_MODE}") [[ -z "${MIGRATE_REQUEST_BODY_MODE}" ]] || migrate_args+=(--request-body-mode "${MIGRATE_REQUEST_BODY_MODE}")
@@ -1399,9 +1387,6 @@ run_single_node_service_migration() {
[[ -z "${MIGRATE_WORK_DIR}" ]] || migrate_args+=(--work-dir "${MIGRATE_WORK_DIR}") [[ -z "${MIGRATE_WORK_DIR}" ]] || migrate_args+=(--work-dir "${MIGRATE_WORK_DIR}")
[[ -z "${MIGRATE_APP_SERVICE}" ]] || migrate_args+=(--app-service "${MIGRATE_APP_SERVICE}") [[ -z "${MIGRATE_APP_SERVICE}" ]] || migrate_args+=(--app-service "${MIGRATE_APP_SERVICE}")
[[ -z "${MIGRATE_POSTGRES_SERVICE}" ]] || migrate_args+=(--postgres-service "${MIGRATE_POSTGRES_SERVICE}") [[ -z "${MIGRATE_POSTGRES_SERVICE}" ]] || migrate_args+=(--postgres-service "${MIGRATE_POSTGRES_SERVICE}")
for table in "${MIGRATE_ALLOW_NON_EXPORTED_TABLES[@]}"; do
migrate_args+=(--allow-non-exported-table "${table}")
done
[[ "${MIGRATE_REPLACE_EXISTING}" != "true" ]] || migrate_args+=(--replace-existing) [[ "${MIGRATE_REPLACE_EXISTING}" != "true" ]] || migrate_args+=(--replace-existing)
[[ -z "${MIGRATE_REQUEST_BODY_MODE}" ]] || migrate_args+=(--request-body-mode "${MIGRATE_REQUEST_BODY_MODE}") [[ -z "${MIGRATE_REQUEST_BODY_MODE}" ]] || migrate_args+=(--request-body-mode "${MIGRATE_REQUEST_BODY_MODE}")
[[ "${MIGRATE_KEEP_SOURCE_STOPPED_ON_ERROR}" != "true" ]] || migrate_args+=(--keep-source-stopped-on-error) [[ "${MIGRATE_KEEP_SOURCE_STOPPED_ON_ERROR}" != "true" ]] || migrate_args+=(--keep-source-stopped-on-error)

View File

@@ -33,93 +33,6 @@ DB_NAME=""
DB_PASSWORD="" DB_PASSWORD=""
NOW="" NOW=""
EXPORTED_TABLES=(
announcement_reads
announcements
api_key_provider_mappings
users
api_keys
audit_logs
management_tokens
user_preferences
user_sessions
providers
provider_api_keys
provider_endpoints
provider_usage_tracking
models
global_models
gemini_file_mappings
ldap_configs
auth_modules
oauth_providers
user_oauth_links
user_groups
user_group_members
pool_member_scores
proxy_nodes
proxy_node_events
proxy_node_metrics_1m
proxy_node_metrics_1h
system_configs
request_candidates
video_tasks
usage
usage_routing_snapshots
billing_rules
dimension_collectors
usage_settlement_snapshots
wallets
wallet_transactions
wallet_daily_usage_ledgers
payment_orders
payment_callbacks
refund_requests
redeem_code_batches
redeem_codes
background_task_runs
background_task_events
stats_hourly
stats_summary
stats_hourly_user
stats_hourly_user_model
user_model_usage_counts
stats_hourly_model
stats_hourly_provider
stats_daily
stats_daily_model
stats_daily_provider
stats_daily_api_key
stats_daily_error
stats_user_daily
stats_user_summary
stats_user_daily_model
stats_user_daily_provider
stats_user_daily_api_format
stats_daily_model_provider
stats_user_daily_model_provider
stats_daily_cost_savings
stats_daily_cost_savings_provider
stats_daily_cost_savings_model
stats_daily_cost_savings_model_provider
stats_user_daily_cost_savings
stats_user_daily_cost_savings_provider
stats_user_daily_cost_savings_model
stats_user_daily_cost_savings_model_provider
)
IGNORED_LIFECYCLE_TABLES=(
_sqlx_migrations
schema_backfills
)
REQUEST_BODY_ARTIFACT_TABLES=(
usage_body_blobs
usage_http_audits
)
EXTRA_ALLOWED_NON_EXPORTED_TABLES=()
usage() { usage() {
cat <<'EOF' cat <<'EOF'
Usage: scripts/migrate-pg-compose-to-single-node.sh [options] Usage: scripts/migrate-pg-compose-to-single-node.sh [options]
@@ -140,8 +53,6 @@ Options:
--postgres-service NAME Source compose Postgres service (default: postgres) --postgres-service NAME Source compose Postgres service (default: postgres)
--single-node-service NAME Target single-node compose service (default: app) --single-node-service NAME Target single-node compose service (default: app)
--app-image IMAGE Override APP_IMAGE for the target single-node compose env --app-image IMAGE Override APP_IMAGE for the target single-node compose env
--allow-non-exported-table TABLE
Allow a specific non-exported source table to be non-empty
--replace-existing Allow replacing an existing target SQLite database --replace-existing Allow replacing an existing target SQLite database
--replace-target-compose Overwrite target compose file from the template --replace-target-compose Overwrite target compose file from the template
--dry-run Pull/preflight/direct-copy without stopping or switching --dry-run Pull/preflight/direct-copy without stopping or switching
@@ -275,11 +186,6 @@ parse_args() {
APP_IMAGE="$2" APP_IMAGE="$2"
shift 2 shift 2
;; ;;
--allow-non-exported-table)
[[ $# -ge 2 ]] || die "--allow-non-exported-table requires a value"
EXTRA_ALLOWED_NON_EXPORTED_TABLES+=("$2")
shift 2
;;
--replace-existing) --replace-existing)
REPLACE_EXISTING="true" REPLACE_EXISTING="true"
shift shift
@@ -445,16 +351,6 @@ target_run_app() {
"$SINGLE_NODE_SERVICE" "$@" "$SINGLE_NODE_SERVICE" "$@"
} }
sql_quote_list() {
local sep=""
local item escaped
for item in "$@"; do
escaped="${item//\'/\'\'}"
printf "%s'%s'" "$sep" "$escaped"
sep=", "
done
}
run_psql_stdin() { run_psql_stdin() {
local sql_file="$1" local sql_file="$1"
source_compose exec -T \ source_compose exec -T \
@@ -582,55 +478,6 @@ check_disk_space() {
fi fi
} }
check_non_exported_tables() {
local allowed_tables=("${EXPORTED_TABLES[@]}" "${IGNORED_LIFECYCLE_TABLES[@]}" "${REQUEST_BODY_ARTIFACT_TABLES[@]}" "${EXTRA_ALLOWED_NON_EXPORTED_TABLES[@]}")
local allow_sql
local sql_file
local result_file
allow_sql="$(sql_quote_list "${allowed_tables[@]}")"
sql_file="${WORK_DIR}/check-non-exported-tables.sql"
result_file="${WORK_DIR}/non-exported-tables.txt"
cat > "$sql_file" <<SQL
CREATE TEMP TABLE aether_non_exported_nonempty_tables (
table_name text PRIMARY KEY
) ON COMMIT PRESERVE ROWS;
DO \$\$
DECLARE
candidate record;
has_rows boolean;
BEGIN
FOR candidate IN
SELECT tablename
FROM pg_tables
WHERE schemaname = 'public'
AND tablename NOT IN (${allow_sql})
ORDER BY tablename
LOOP
EXECUTE format('SELECT EXISTS (SELECT 1 FROM %I.%I LIMIT 1)', 'public', candidate.tablename)
INTO has_rows;
IF has_rows THEN
INSERT INTO aether_non_exported_nonempty_tables(table_name)
VALUES (candidate.tablename)
ON CONFLICT DO NOTHING;
END IF;
END LOOP;
END
\$\$;
SELECT table_name FROM aether_non_exported_nonempty_tables ORDER BY table_name;
SQL
run_psql_stdin "$sql_file" > "$result_file"
if [[ -s "$result_file" ]]; then
cat "$result_file" >&2
die "source Postgres has non-empty tables that are not covered by the current migration domains"
fi
}
check_request_body_artifacts() { check_request_body_artifacts() {
local sql_file local sql_file
local result_file local result_file
@@ -771,13 +618,13 @@ assert_source_and_target_images_match() {
fi fi
} }
assert_target_copy_supports_migration_domains() { assert_target_copy_command_available() {
local target_image="$1" local target_image="$1"
local help_output local help_output
help_output="$(docker run --rm --entrypoint aether-gateway "$target_image" copy --help 2>&1 || true)" help_output="$(docker run --rm --entrypoint aether-gateway "$target_image" copy --help 2>&1 || true)"
if [[ "$help_output" != *"stats"* || "$help_output" != *"auxiliary"* || "$help_output" != *"--omit-request-body-details"* ]]; then if [[ "$help_output" != *"--source-driver"* || "$help_output" != *"--target-driver"* || "$help_output" != *"--omit-request-body-details"* ]]; then
die "target single-node image does not support the current PG-to-SQLite copy domains; use a matching Aether release image" die "target single-node image does not support direct PG-to-SQLite copy; use a matching Aether release image"
fi fi
} }
@@ -976,8 +823,8 @@ main() {
target_image="$(env_file_get "$TARGET_ENV_ABS" "APP_IMAGE")" target_image="$(env_file_get "$TARGET_ENV_ABS" "APP_IMAGE")"
[[ -n "$target_image" ]] || die "target env must define APP_IMAGE" [[ -n "$target_image" ]] || die "target env must define APP_IMAGE"
log "checking target image copy command supports current migration domains" log "checking target image copy command is available"
assert_target_copy_supports_migration_domains "$target_image" assert_target_copy_command_available "$target_image"
log "checking source app image matches target single-node image" log "checking source app image matches target single-node image"
assert_source_and_target_images_match "$target_image" assert_source_and_target_images_match "$target_image"
@@ -986,16 +833,15 @@ main() {
rm -f "$preflight_db" "${preflight_db}-wal" "${preflight_db}-shm" rm -f "$preflight_db" "${preflight_db}-wal" "${preflight_db}-shm"
target_run_app "sqlite:///migration/$(basename "$preflight_db")" --migrate target_run_app "sqlite:///migration/$(basename "$preflight_db")" --migrate
log "checking source tables that are outside the migration domains" log "checking request body detail policy"
check_request_body_artifacts check_request_body_artifacts
check_non_exported_tables
log "checking available disk space before copy" log "checking available disk space before copy"
check_disk_space check_disk_space
if [[ "$DRY_RUN" == "true" ]]; then if [[ "$DRY_RUN" == "true" ]]; then
warn "dry-run copy happens while the source app may still be writing; use only for rehearsal" warn "dry-run copy happens while the source app may still be writing; use only for rehearsal"
log "copying source Postgres records directly into dry-run SQLite target" log "copying source Postgres tables directly into dry-run SQLite target"
copy_source_to_sqlite "$dry_run_db" copy_source_to_sqlite "$dry_run_db"
log "dry run complete; temporary SQLite DB is ${dry_run_db}" log "dry run complete; temporary SQLite DB is ${dry_run_db}"
return return
@@ -1005,11 +851,10 @@ main() {
source_compose stop "$APP_SERVICE" source_compose stop "$APP_SERVICE"
APP_STOPPED="true" APP_STOPPED="true"
log "checking source tables again after the app has stopped" log "checking request body detail policy again after the app has stopped"
check_request_body_artifacts check_request_body_artifacts
check_non_exported_tables
log "copying source Postgres records directly into temporary SQLite DB" log "copying source Postgres tables directly into temporary SQLite DB"
copy_source_to_sqlite "$target_temp_db" copy_source_to_sqlite "$target_temp_db"
finalize_target_db "$target_temp_db" finalize_target_db "$target_temp_db"

View File

@@ -30,8 +30,6 @@ INSTALL_DOWNLOAD_URL=""
INSTALL_REPO="" INSTALL_REPO=""
INSTALL_SOURCE_REF="" INSTALL_SOURCE_REF=""
EXTRA_ALLOWED_NON_EXPORTED_TABLES=()
APP_STOPPED="false" APP_STOPPED="false"
CUTOVER_COMPLETE="false" CUTOVER_COMPLETE="false"
SOURCE_COMPOSE_ABS="" SOURCE_COMPOSE_ABS=""
@@ -46,91 +44,6 @@ SINGLE_NODE_BIN=""
NOW="" NOW=""
ENV_FILE_ARGS=() ENV_FILE_ARGS=()
EXPORTED_TABLES=(
announcement_reads
announcements
api_key_provider_mappings
users
api_keys
audit_logs
management_tokens
user_preferences
user_sessions
providers
provider_api_keys
provider_endpoints
provider_usage_tracking
models
global_models
gemini_file_mappings
ldap_configs
auth_modules
oauth_providers
user_oauth_links
user_groups
user_group_members
pool_member_scores
proxy_nodes
proxy_node_events
proxy_node_metrics_1m
proxy_node_metrics_1h
system_configs
request_candidates
video_tasks
usage
usage_routing_snapshots
billing_rules
dimension_collectors
usage_settlement_snapshots
wallets
wallet_transactions
wallet_daily_usage_ledgers
payment_orders
payment_callbacks
refund_requests
redeem_code_batches
redeem_codes
background_task_runs
background_task_events
stats_hourly
stats_summary
stats_hourly_user
stats_hourly_user_model
user_model_usage_counts
stats_hourly_model
stats_hourly_provider
stats_daily
stats_daily_model
stats_daily_provider
stats_daily_api_key
stats_daily_error
stats_user_daily
stats_user_summary
stats_user_daily_model
stats_user_daily_provider
stats_user_daily_api_format
stats_daily_model_provider
stats_user_daily_model_provider
stats_daily_cost_savings
stats_daily_cost_savings_provider
stats_daily_cost_savings_model
stats_daily_cost_savings_model_provider
stats_user_daily_cost_savings
stats_user_daily_cost_savings_provider
stats_user_daily_cost_savings_model
stats_user_daily_cost_savings_model_provider
)
IGNORED_LIFECYCLE_TABLES=(
_sqlx_migrations
schema_backfills
)
REQUEST_BODY_ARTIFACT_TABLES=(
usage_body_blobs
usage_http_audits
)
usage() { usage() {
cat <<'EOF' cat <<'EOF'
Usage: scripts/migrate-pg-to-single-node.sh [options] Usage: scripts/migrate-pg-to-single-node.sh [options]
@@ -158,8 +71,6 @@ Options:
--install-download-url URL Pass --download-url to install.sh --install-download-url URL Pass --download-url to install.sh
--install-repo OWNER/REPO Pass --repo to install.sh --install-repo OWNER/REPO Pass --repo to install.sh
--install-source-ref REF Pass --source-ref to install.sh --install-source-ref REF Pass --source-ref to install.sh
--allow-non-exported-table TABLE
Allow a specific non-exported source table to be non-empty
--replace-existing Allow replacing an existing target SQLite database --replace-existing Allow replacing an existing target SQLite database
--dry-run Install/preflight and copy to a temporary SQLite DB, but do not stop/switch --dry-run Install/preflight and copy to a temporary SQLite DB, but do not stop/switch
--request-body-mode MODE Request/response body detail handling: full/1 or omit/2 --request-body-mode MODE Request/response body detail handling: full/1 or omit/2
@@ -174,7 +85,7 @@ Default cutover behavior:
1. Derive a single-node env file from the source .env, preserving JWT/encryption keys. 1. Derive a single-node env file from the source .env, preserving JWT/encryption keys.
2. Run install.sh --mode single-node --skip-start with that env file. 2. Run install.sh --mode single-node --skip-start with that env file.
3. Preflight SQLite migrations with the single-node binary. 3. Preflight SQLite migrations with the single-node binary.
4. Check migration coverage and available disk space. 4. Check request-body policy and available disk space.
5. Pull the target single-node image and verify it matches the running source app image ID. 5. Pull the target single-node image and verify it matches the running source app image ID.
6. Stop only the source app service; keep Postgres/Redis running. 6. Stop only the source app service; keep Postgres/Redis running.
7. Copy Postgres records directly into a temporary SQLite DB without JSONL files. 7. Copy Postgres records directly into a temporary SQLite DB without JSONL files.
@@ -341,11 +252,6 @@ parse_args() {
INSTALL_SOURCE_REF="$2" INSTALL_SOURCE_REF="$2"
shift 2 shift 2
;; ;;
--allow-non-exported-table)
[[ $# -ge 2 ]] || die "--allow-non-exported-table requires a value"
EXTRA_ALLOWED_NON_EXPORTED_TABLES+=("$2")
shift 2
;;
--replace-existing) --replace-existing)
REPLACE_EXISTING="true" REPLACE_EXISTING="true"
shift shift
@@ -609,16 +515,6 @@ copy_source_to_sqlite() {
"${copy_args[@]}" "${copy_args[@]}"
} }
sql_quote_list() {
local sep=""
local item escaped
for item in "$@"; do
escaped="${item//\'/\'\'}"
printf "%s'%s'" "$sep" "$escaped"
sep=", "
done
}
run_psql_stdin() { run_psql_stdin() {
local sql_file="$1" local sql_file="$1"
compose exec -T \ compose exec -T \
@@ -746,55 +642,6 @@ check_disk_space() {
fi fi
} }
check_non_exported_tables() {
local allowed_tables=("${EXPORTED_TABLES[@]}" "${IGNORED_LIFECYCLE_TABLES[@]}" "${REQUEST_BODY_ARTIFACT_TABLES[@]}" "${EXTRA_ALLOWED_NON_EXPORTED_TABLES[@]}")
local allow_sql
local sql_file
local result_file
allow_sql="$(sql_quote_list "${allowed_tables[@]}")"
sql_file="${WORK_DIR}/check-non-exported-tables.sql"
result_file="${WORK_DIR}/non-exported-tables.txt"
cat > "$sql_file" <<SQL
CREATE TEMP TABLE aether_non_exported_nonempty_tables (
table_name text PRIMARY KEY
) ON COMMIT PRESERVE ROWS;
DO \$\$
DECLARE
candidate record;
has_rows boolean;
BEGIN
FOR candidate IN
SELECT tablename
FROM pg_tables
WHERE schemaname = 'public'
AND tablename NOT IN (${allow_sql})
ORDER BY tablename
LOOP
EXECUTE format('SELECT EXISTS (SELECT 1 FROM %I.%I LIMIT 1)', 'public', candidate.tablename)
INTO has_rows;
IF has_rows THEN
INSERT INTO aether_non_exported_nonempty_tables(table_name)
VALUES (candidate.tablename)
ON CONFLICT DO NOTHING;
END IF;
END LOOP;
END
\$\$;
SELECT table_name FROM aether_non_exported_nonempty_tables ORDER BY table_name;
SQL
run_psql_stdin "$sql_file" > "$result_file"
if [[ -s "$result_file" ]]; then
cat "$result_file" >&2
die "source Postgres has non-empty tables that are not covered by the current migration domains"
fi
}
check_request_body_artifacts() { check_request_body_artifacts() {
local sql_file local sql_file
local result_file local result_file
@@ -935,13 +782,13 @@ assert_source_and_target_images_match() {
fi fi
} }
assert_target_copy_supports_migration_domains() { assert_target_copy_command_available() {
local target_image="$1" local target_image="$1"
local help_output local help_output
help_output="$(docker run --rm --entrypoint aether-gateway "$target_image" copy --help 2>&1 || true)" help_output="$(docker run --rm --entrypoint aether-gateway "$target_image" copy --help 2>&1 || true)"
if [[ "$help_output" != *"stats"* || "$help_output" != *"auxiliary"* || "$help_output" != *"--omit-request-body-details"* ]]; then if [[ "$help_output" != *"--source-driver"* || "$help_output" != *"--target-driver"* || "$help_output" != *"--omit-request-body-details"* ]]; then
die "target single-node image does not support the current PG-to-SQLite copy domains; use a matching Aether release image" die "target single-node image does not support direct PG-to-SQLite copy; use a matching Aether release image"
fi fi
} }
@@ -1132,9 +979,8 @@ main() {
rm -f "$preflight_db" rm -f "$preflight_db"
run_single_node_gateway "sqlite://${preflight_db}" --migrate run_single_node_gateway "sqlite://${preflight_db}" --migrate
log "checking source tables that are outside the migration domains" log "checking request body detail policy"
check_request_body_artifacts check_request_body_artifacts
check_non_exported_tables
log "checking available disk space before copy" log "checking available disk space before copy"
check_disk_space check_disk_space
@@ -1143,15 +989,15 @@ main() {
target_image="$(copy_image)" target_image="$(copy_image)"
docker pull "$target_image" docker pull "$target_image"
log "checking target image copy command supports current migration domains" log "checking target image copy command is available"
assert_target_copy_supports_migration_domains "$target_image" assert_target_copy_command_available "$target_image"
log "checking source app image matches target single-node image" log "checking source app image matches target single-node image"
assert_source_and_target_images_match "$target_image" assert_source_and_target_images_match "$target_image"
if [[ "$DRY_RUN" == "true" ]]; then if [[ "$DRY_RUN" == "true" ]]; then
warn "dry-run copy happens while the source app may still be writing; use only for rehearsal" warn "dry-run copy happens while the source app may still be writing; use only for rehearsal"
log "copying source Postgres records directly into dry-run SQLite target" log "copying source Postgres tables directly into dry-run SQLite target"
copy_source_to_sqlite "$dry_run_db" copy_source_to_sqlite "$dry_run_db"
log "dry run complete; temporary SQLite DB is ${dry_run_db}" log "dry run complete; temporary SQLite DB is ${dry_run_db}"
return return
@@ -1165,11 +1011,10 @@ main() {
compose stop "$APP_SERVICE" compose stop "$APP_SERVICE"
APP_STOPPED="true" APP_STOPPED="true"
log "checking source tables again after the app has stopped" log "checking request body detail policy again after the app has stopped"
check_request_body_artifacts check_request_body_artifacts
check_non_exported_tables
log "copying source Postgres records directly into temporary SQLite DB" log "copying source Postgres tables directly into temporary SQLite DB"
copy_source_to_sqlite "$target_temp_db" copy_source_to_sqlite "$target_temp_db"
finalize_target_db "$target_temp_db" finalize_target_db "$target_temp_db"