fix: 恢复迁移文件到原始状态修复校验和错误
Migration files should never be modified after being applied. Reverted comment-only changes to fix checksum mismatch. 修复错误: migration 001_init.sql checksum mismatch 解决方案: 将迁移文件恢复到修改前的状态
This commit is contained in:
@@ -1,172 +1,172 @@
|
||||
-- TianShuAPI 初始化数据库迁移脚本
|
||||
-- PostgreSQL 15+
|
||||
|
||||
-- 1. proxies 代理IP表(无外键依赖)
|
||||
CREATE TABLE IF NOT EXISTS proxies (
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
name VARCHAR(100) NOT NULL,
|
||||
protocol VARCHAR(20) NOT NULL, -- http/https/socks5
|
||||
host VARCHAR(255) NOT NULL,
|
||||
port INT NOT NULL,
|
||||
username VARCHAR(100),
|
||||
password VARCHAR(100),
|
||||
status VARCHAR(20) NOT NULL DEFAULT 'active', -- active/disabled
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
deleted_at TIMESTAMPTZ
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_proxies_status ON proxies(status);
|
||||
CREATE INDEX IF NOT EXISTS idx_proxies_deleted_at ON proxies(deleted_at);
|
||||
|
||||
-- 2. groups 分组表(无外键依赖)
|
||||
CREATE TABLE IF NOT EXISTS groups (
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
name VARCHAR(100) NOT NULL UNIQUE,
|
||||
description TEXT,
|
||||
rate_multiplier DECIMAL(10, 4) NOT NULL DEFAULT 1.0, -- 费率倍率
|
||||
is_exclusive BOOLEAN NOT NULL DEFAULT FALSE, -- 是否专属分组
|
||||
status VARCHAR(20) NOT NULL DEFAULT 'active', -- active/disabled
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
deleted_at TIMESTAMPTZ
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_groups_name ON groups(name);
|
||||
CREATE INDEX IF NOT EXISTS idx_groups_status ON groups(status);
|
||||
CREATE INDEX IF NOT EXISTS idx_groups_is_exclusive ON groups(is_exclusive);
|
||||
CREATE INDEX IF NOT EXISTS idx_groups_deleted_at ON groups(deleted_at);
|
||||
|
||||
-- 3. users 用户表(无外键依赖)
|
||||
CREATE TABLE IF NOT EXISTS users (
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
email VARCHAR(255) NOT NULL UNIQUE,
|
||||
password_hash VARCHAR(255) NOT NULL,
|
||||
role VARCHAR(20) NOT NULL DEFAULT 'user', -- admin/user
|
||||
balance DECIMAL(20, 8) NOT NULL DEFAULT 0, -- 余额(可为负数)
|
||||
concurrency INT NOT NULL DEFAULT 5, -- 并发数限制
|
||||
status VARCHAR(20) NOT NULL DEFAULT 'active', -- active/disabled
|
||||
allowed_groups BIGINT[] DEFAULT NULL, -- 允许绑定的分组ID列表
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
deleted_at TIMESTAMPTZ
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_users_email ON users(email);
|
||||
CREATE INDEX IF NOT EXISTS idx_users_status ON users(status);
|
||||
CREATE INDEX IF NOT EXISTS idx_users_deleted_at ON users(deleted_at);
|
||||
|
||||
-- 4. accounts 上游账号表(依赖proxies)
|
||||
CREATE TABLE IF NOT EXISTS accounts (
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
name VARCHAR(100) NOT NULL,
|
||||
platform VARCHAR(50) NOT NULL, -- anthropic/openai/gemini
|
||||
type VARCHAR(20) NOT NULL, -- oauth/apikey
|
||||
credentials JSONB NOT NULL DEFAULT '{}', -- 凭证信息(加密存储)
|
||||
extra JSONB NOT NULL DEFAULT '{}', -- 扩展信息
|
||||
proxy_id BIGINT REFERENCES proxies(id) ON DELETE SET NULL,
|
||||
concurrency INT NOT NULL DEFAULT 3, -- 账号并发限制
|
||||
priority INT NOT NULL DEFAULT 50, -- 调度优先级(1-100,越小越高)
|
||||
status VARCHAR(20) NOT NULL DEFAULT 'active', -- active/disabled/error
|
||||
error_message TEXT,
|
||||
last_used_at TIMESTAMPTZ,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
deleted_at TIMESTAMPTZ
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_accounts_platform ON accounts(platform);
|
||||
CREATE INDEX IF NOT EXISTS idx_accounts_type ON accounts(type);
|
||||
CREATE INDEX IF NOT EXISTS idx_accounts_status ON accounts(status);
|
||||
CREATE INDEX IF NOT EXISTS idx_accounts_proxy_id ON accounts(proxy_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_accounts_priority ON accounts(priority);
|
||||
CREATE INDEX IF NOT EXISTS idx_accounts_last_used_at ON accounts(last_used_at);
|
||||
CREATE INDEX IF NOT EXISTS idx_accounts_deleted_at ON accounts(deleted_at);
|
||||
|
||||
-- 5. api_keys API密钥表(依赖users, groups)
|
||||
CREATE TABLE IF NOT EXISTS api_keys (
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
user_id BIGINT NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
||||
key VARCHAR(64) NOT NULL UNIQUE, -- sk-xxx格式
|
||||
name VARCHAR(100) NOT NULL,
|
||||
group_id BIGINT REFERENCES groups(id) ON DELETE SET NULL,
|
||||
status VARCHAR(20) NOT NULL DEFAULT 'active', -- active/disabled
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
deleted_at TIMESTAMPTZ
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_api_keys_key ON api_keys(key);
|
||||
CREATE INDEX IF NOT EXISTS idx_api_keys_user_id ON api_keys(user_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_api_keys_group_id ON api_keys(group_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_api_keys_status ON api_keys(status);
|
||||
CREATE INDEX IF NOT EXISTS idx_api_keys_deleted_at ON api_keys(deleted_at);
|
||||
|
||||
-- 6. account_groups 账号-分组关联表(依赖accounts, groups)
|
||||
CREATE TABLE IF NOT EXISTS account_groups (
|
||||
account_id BIGINT NOT NULL REFERENCES accounts(id) ON DELETE CASCADE,
|
||||
group_id BIGINT NOT NULL REFERENCES groups(id) ON DELETE CASCADE,
|
||||
priority INT NOT NULL DEFAULT 50, -- 分组内优先级
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
PRIMARY KEY (account_id, group_id)
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_account_groups_group_id ON account_groups(group_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_account_groups_priority ON account_groups(priority);
|
||||
|
||||
-- 7. redeem_codes 卡密表(依赖users)
|
||||
CREATE TABLE IF NOT EXISTS redeem_codes (
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
code VARCHAR(32) NOT NULL UNIQUE, -- 兑换码
|
||||
type VARCHAR(20) NOT NULL DEFAULT 'balance', -- balance
|
||||
value DECIMAL(20, 8) NOT NULL, -- 面值(USD)
|
||||
status VARCHAR(20) NOT NULL DEFAULT 'unused', -- unused/used
|
||||
used_by BIGINT REFERENCES users(id) ON DELETE SET NULL,
|
||||
used_at TIMESTAMPTZ,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_redeem_codes_code ON redeem_codes(code);
|
||||
CREATE INDEX IF NOT EXISTS idx_redeem_codes_status ON redeem_codes(status);
|
||||
CREATE INDEX IF NOT EXISTS idx_redeem_codes_used_by ON redeem_codes(used_by);
|
||||
|
||||
-- 8. usage_logs 使用记录表(依赖users, api_keys, accounts)
|
||||
CREATE TABLE IF NOT EXISTS usage_logs (
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
user_id BIGINT NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
||||
api_key_id BIGINT NOT NULL REFERENCES api_keys(id) ON DELETE CASCADE,
|
||||
account_id BIGINT NOT NULL REFERENCES accounts(id) ON DELETE CASCADE,
|
||||
request_id VARCHAR(64),
|
||||
model VARCHAR(100) NOT NULL,
|
||||
|
||||
-- Token使用量(4类)
|
||||
input_tokens INT NOT NULL DEFAULT 0,
|
||||
output_tokens INT NOT NULL DEFAULT 0,
|
||||
cache_creation_tokens INT NOT NULL DEFAULT 0,
|
||||
cache_read_tokens INT NOT NULL DEFAULT 0,
|
||||
|
||||
-- 详细的缓存创建分类
|
||||
cache_creation_5m_tokens INT NOT NULL DEFAULT 0,
|
||||
cache_creation_1h_tokens INT NOT NULL DEFAULT 0,
|
||||
|
||||
-- 费用(USD)
|
||||
input_cost DECIMAL(20, 10) NOT NULL DEFAULT 0,
|
||||
output_cost DECIMAL(20, 10) NOT NULL DEFAULT 0,
|
||||
cache_creation_cost DECIMAL(20, 10) NOT NULL DEFAULT 0,
|
||||
cache_read_cost DECIMAL(20, 10) NOT NULL DEFAULT 0,
|
||||
total_cost DECIMAL(20, 10) NOT NULL DEFAULT 0, -- 原始总费用
|
||||
actual_cost DECIMAL(20, 10) NOT NULL DEFAULT 0, -- 实际扣除费用
|
||||
|
||||
-- 元数据
|
||||
stream BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
duration_ms INT,
|
||||
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_usage_logs_user_id ON usage_logs(user_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_usage_logs_api_key_id ON usage_logs(api_key_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_usage_logs_account_id ON usage_logs(account_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_usage_logs_model ON usage_logs(model);
|
||||
CREATE INDEX IF NOT EXISTS idx_usage_logs_created_at ON usage_logs(created_at);
|
||||
CREATE INDEX IF NOT EXISTS idx_usage_logs_user_created ON usage_logs(user_id, created_at);
|
||||
-- Sub2API 初始化数据库迁移脚本
|
||||
-- PostgreSQL 15+
|
||||
|
||||
-- 1. proxies 代理IP表(无外键依赖)
|
||||
CREATE TABLE IF NOT EXISTS proxies (
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
name VARCHAR(100) NOT NULL,
|
||||
protocol VARCHAR(20) NOT NULL, -- http/https/socks5
|
||||
host VARCHAR(255) NOT NULL,
|
||||
port INT NOT NULL,
|
||||
username VARCHAR(100),
|
||||
password VARCHAR(100),
|
||||
status VARCHAR(20) NOT NULL DEFAULT 'active', -- active/disabled
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
deleted_at TIMESTAMPTZ
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_proxies_status ON proxies(status);
|
||||
CREATE INDEX IF NOT EXISTS idx_proxies_deleted_at ON proxies(deleted_at);
|
||||
|
||||
-- 2. groups 分组表(无外键依赖)
|
||||
CREATE TABLE IF NOT EXISTS groups (
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
name VARCHAR(100) NOT NULL UNIQUE,
|
||||
description TEXT,
|
||||
rate_multiplier DECIMAL(10, 4) NOT NULL DEFAULT 1.0, -- 费率倍率
|
||||
is_exclusive BOOLEAN NOT NULL DEFAULT FALSE, -- 是否专属分组
|
||||
status VARCHAR(20) NOT NULL DEFAULT 'active', -- active/disabled
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
deleted_at TIMESTAMPTZ
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_groups_name ON groups(name);
|
||||
CREATE INDEX IF NOT EXISTS idx_groups_status ON groups(status);
|
||||
CREATE INDEX IF NOT EXISTS idx_groups_is_exclusive ON groups(is_exclusive);
|
||||
CREATE INDEX IF NOT EXISTS idx_groups_deleted_at ON groups(deleted_at);
|
||||
|
||||
-- 3. users 用户表(无外键依赖)
|
||||
CREATE TABLE IF NOT EXISTS users (
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
email VARCHAR(255) NOT NULL UNIQUE,
|
||||
password_hash VARCHAR(255) NOT NULL,
|
||||
role VARCHAR(20) NOT NULL DEFAULT 'user', -- admin/user
|
||||
balance DECIMAL(20, 8) NOT NULL DEFAULT 0, -- 余额(可为负数)
|
||||
concurrency INT NOT NULL DEFAULT 5, -- 并发数限制
|
||||
status VARCHAR(20) NOT NULL DEFAULT 'active', -- active/disabled
|
||||
allowed_groups BIGINT[] DEFAULT NULL, -- 允许绑定的分组ID列表
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
deleted_at TIMESTAMPTZ
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_users_email ON users(email);
|
||||
CREATE INDEX IF NOT EXISTS idx_users_status ON users(status);
|
||||
CREATE INDEX IF NOT EXISTS idx_users_deleted_at ON users(deleted_at);
|
||||
|
||||
-- 4. accounts 上游账号表(依赖proxies)
|
||||
CREATE TABLE IF NOT EXISTS accounts (
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
name VARCHAR(100) NOT NULL,
|
||||
platform VARCHAR(50) NOT NULL, -- anthropic/openai/gemini
|
||||
type VARCHAR(20) NOT NULL, -- oauth/apikey
|
||||
credentials JSONB NOT NULL DEFAULT '{}', -- 凭证信息(加密存储)
|
||||
extra JSONB NOT NULL DEFAULT '{}', -- 扩展信息
|
||||
proxy_id BIGINT REFERENCES proxies(id) ON DELETE SET NULL,
|
||||
concurrency INT NOT NULL DEFAULT 3, -- 账号并发限制
|
||||
priority INT NOT NULL DEFAULT 50, -- 调度优先级(1-100,越小越高)
|
||||
status VARCHAR(20) NOT NULL DEFAULT 'active', -- active/disabled/error
|
||||
error_message TEXT,
|
||||
last_used_at TIMESTAMPTZ,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
deleted_at TIMESTAMPTZ
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_accounts_platform ON accounts(platform);
|
||||
CREATE INDEX IF NOT EXISTS idx_accounts_type ON accounts(type);
|
||||
CREATE INDEX IF NOT EXISTS idx_accounts_status ON accounts(status);
|
||||
CREATE INDEX IF NOT EXISTS idx_accounts_proxy_id ON accounts(proxy_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_accounts_priority ON accounts(priority);
|
||||
CREATE INDEX IF NOT EXISTS idx_accounts_last_used_at ON accounts(last_used_at);
|
||||
CREATE INDEX IF NOT EXISTS idx_accounts_deleted_at ON accounts(deleted_at);
|
||||
|
||||
-- 5. api_keys API密钥表(依赖users, groups)
|
||||
CREATE TABLE IF NOT EXISTS api_keys (
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
user_id BIGINT NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
||||
key VARCHAR(64) NOT NULL UNIQUE, -- sk-xxx格式
|
||||
name VARCHAR(100) NOT NULL,
|
||||
group_id BIGINT REFERENCES groups(id) ON DELETE SET NULL,
|
||||
status VARCHAR(20) NOT NULL DEFAULT 'active', -- active/disabled
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
deleted_at TIMESTAMPTZ
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_api_keys_key ON api_keys(key);
|
||||
CREATE INDEX IF NOT EXISTS idx_api_keys_user_id ON api_keys(user_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_api_keys_group_id ON api_keys(group_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_api_keys_status ON api_keys(status);
|
||||
CREATE INDEX IF NOT EXISTS idx_api_keys_deleted_at ON api_keys(deleted_at);
|
||||
|
||||
-- 6. account_groups 账号-分组关联表(依赖accounts, groups)
|
||||
CREATE TABLE IF NOT EXISTS account_groups (
|
||||
account_id BIGINT NOT NULL REFERENCES accounts(id) ON DELETE CASCADE,
|
||||
group_id BIGINT NOT NULL REFERENCES groups(id) ON DELETE CASCADE,
|
||||
priority INT NOT NULL DEFAULT 50, -- 分组内优先级
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
PRIMARY KEY (account_id, group_id)
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_account_groups_group_id ON account_groups(group_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_account_groups_priority ON account_groups(priority);
|
||||
|
||||
-- 7. redeem_codes 卡密表(依赖users)
|
||||
CREATE TABLE IF NOT EXISTS redeem_codes (
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
code VARCHAR(32) NOT NULL UNIQUE, -- 兑换码
|
||||
type VARCHAR(20) NOT NULL DEFAULT 'balance', -- balance
|
||||
value DECIMAL(20, 8) NOT NULL, -- 面值(USD)
|
||||
status VARCHAR(20) NOT NULL DEFAULT 'unused', -- unused/used
|
||||
used_by BIGINT REFERENCES users(id) ON DELETE SET NULL,
|
||||
used_at TIMESTAMPTZ,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_redeem_codes_code ON redeem_codes(code);
|
||||
CREATE INDEX IF NOT EXISTS idx_redeem_codes_status ON redeem_codes(status);
|
||||
CREATE INDEX IF NOT EXISTS idx_redeem_codes_used_by ON redeem_codes(used_by);
|
||||
|
||||
-- 8. usage_logs 使用记录表(依赖users, api_keys, accounts)
|
||||
CREATE TABLE IF NOT EXISTS usage_logs (
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
user_id BIGINT NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
||||
api_key_id BIGINT NOT NULL REFERENCES api_keys(id) ON DELETE CASCADE,
|
||||
account_id BIGINT NOT NULL REFERENCES accounts(id) ON DELETE CASCADE,
|
||||
request_id VARCHAR(64),
|
||||
model VARCHAR(100) NOT NULL,
|
||||
|
||||
-- Token使用量(4类)
|
||||
input_tokens INT NOT NULL DEFAULT 0,
|
||||
output_tokens INT NOT NULL DEFAULT 0,
|
||||
cache_creation_tokens INT NOT NULL DEFAULT 0,
|
||||
cache_read_tokens INT NOT NULL DEFAULT 0,
|
||||
|
||||
-- 详细的缓存创建分类
|
||||
cache_creation_5m_tokens INT NOT NULL DEFAULT 0,
|
||||
cache_creation_1h_tokens INT NOT NULL DEFAULT 0,
|
||||
|
||||
-- 费用(USD)
|
||||
input_cost DECIMAL(20, 10) NOT NULL DEFAULT 0,
|
||||
output_cost DECIMAL(20, 10) NOT NULL DEFAULT 0,
|
||||
cache_creation_cost DECIMAL(20, 10) NOT NULL DEFAULT 0,
|
||||
cache_read_cost DECIMAL(20, 10) NOT NULL DEFAULT 0,
|
||||
total_cost DECIMAL(20, 10) NOT NULL DEFAULT 0, -- 原始总费用
|
||||
actual_cost DECIMAL(20, 10) NOT NULL DEFAULT 0, -- 实际扣除费用
|
||||
|
||||
-- 元数据
|
||||
stream BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
duration_ms INT,
|
||||
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_usage_logs_user_id ON usage_logs(user_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_usage_logs_api_key_id ON usage_logs(api_key_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_usage_logs_account_id ON usage_logs(account_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_usage_logs_model ON usage_logs(model);
|
||||
CREATE INDEX IF NOT EXISTS idx_usage_logs_created_at ON usage_logs(created_at);
|
||||
CREATE INDEX IF NOT EXISTS idx_usage_logs_user_created ON usage_logs(user_id, created_at);
|
||||
|
||||
@@ -1,33 +1,33 @@
|
||||
-- TianShuAPI 账号类型迁移脚本
|
||||
-- 将 'official' 类型账号迁移为 'oauth' 或 'setup-token'
|
||||
-- 根据 credentials->>'scope' 字段判断:
|
||||
-- - 包含 'user:profile' 的是 'oauth' 类型
|
||||
-- - 只有 'user:inference' 的是 'setup-token' 类型
|
||||
|
||||
-- 1. 将包含 profile scope 的 official 账号迁移为 oauth
|
||||
UPDATE accounts
|
||||
SET type = 'oauth',
|
||||
updated_at = NOW()
|
||||
WHERE type = 'official'
|
||||
AND credentials->>'scope' LIKE '%user:profile%';
|
||||
|
||||
-- 2. 将只有 inference scope 的 official 账号迁移为 setup-token
|
||||
UPDATE accounts
|
||||
SET type = 'setup-token',
|
||||
updated_at = NOW()
|
||||
WHERE type = 'official'
|
||||
AND (
|
||||
credentials->>'scope' = 'user:inference'
|
||||
OR credentials->>'scope' NOT LIKE '%user:profile%'
|
||||
);
|
||||
|
||||
-- 3. 处理没有 scope 字段的旧账号(默认为 oauth)
|
||||
UPDATE accounts
|
||||
SET type = 'oauth',
|
||||
updated_at = NOW()
|
||||
WHERE type = 'official'
|
||||
AND (credentials->>'scope' IS NULL OR credentials->>'scope' = '');
|
||||
|
||||
-- 4. 验证迁移结果(查询是否还有 official 类型账号)
|
||||
-- SELECT COUNT(*) FROM accounts WHERE type = 'official';
|
||||
-- 如果结果为 0,说明迁移成功
|
||||
-- Sub2API 账号类型迁移脚本
|
||||
-- 将 'official' 类型账号迁移为 'oauth' 或 'setup-token'
|
||||
-- 根据 credentials->>'scope' 字段判断:
|
||||
-- - 包含 'user:profile' 的是 'oauth' 类型
|
||||
-- - 只有 'user:inference' 的是 'setup-token' 类型
|
||||
|
||||
-- 1. 将包含 profile scope 的 official 账号迁移为 oauth
|
||||
UPDATE accounts
|
||||
SET type = 'oauth',
|
||||
updated_at = NOW()
|
||||
WHERE type = 'official'
|
||||
AND credentials->>'scope' LIKE '%user:profile%';
|
||||
|
||||
-- 2. 将只有 inference scope 的 official 账号迁移为 setup-token
|
||||
UPDATE accounts
|
||||
SET type = 'setup-token',
|
||||
updated_at = NOW()
|
||||
WHERE type = 'official'
|
||||
AND (
|
||||
credentials->>'scope' = 'user:inference'
|
||||
OR credentials->>'scope' NOT LIKE '%user:profile%'
|
||||
);
|
||||
|
||||
-- 3. 处理没有 scope 字段的旧账号(默认为 oauth)
|
||||
UPDATE accounts
|
||||
SET type = 'oauth',
|
||||
updated_at = NOW()
|
||||
WHERE type = 'official'
|
||||
AND (credentials->>'scope' IS NULL OR credentials->>'scope' = '');
|
||||
|
||||
-- 4. 验证迁移结果(查询是否还有 official 类型账号)
|
||||
-- SELECT COUNT(*) FROM accounts WHERE type = 'official';
|
||||
-- 如果结果为 0,说明迁移成功
|
||||
|
||||
@@ -1,65 +1,65 @@
|
||||
-- TianShuAPI 订阅功能迁移脚本
|
||||
-- 添加订阅分组和用户订阅功能
|
||||
|
||||
-- 1. 扩展 groups 表添加订阅相关字段
|
||||
ALTER TABLE groups ADD COLUMN IF NOT EXISTS platform VARCHAR(50) NOT NULL DEFAULT 'anthropic';
|
||||
ALTER TABLE groups ADD COLUMN IF NOT EXISTS subscription_type VARCHAR(20) NOT NULL DEFAULT 'standard';
|
||||
ALTER TABLE groups ADD COLUMN IF NOT EXISTS daily_limit_usd DECIMAL(20, 8) DEFAULT NULL;
|
||||
ALTER TABLE groups ADD COLUMN IF NOT EXISTS weekly_limit_usd DECIMAL(20, 8) DEFAULT NULL;
|
||||
ALTER TABLE groups ADD COLUMN IF NOT EXISTS monthly_limit_usd DECIMAL(20, 8) DEFAULT NULL;
|
||||
ALTER TABLE groups ADD COLUMN IF NOT EXISTS default_validity_days INT NOT NULL DEFAULT 30;
|
||||
|
||||
-- 添加索引
|
||||
CREATE INDEX IF NOT EXISTS idx_groups_platform ON groups(platform);
|
||||
CREATE INDEX IF NOT EXISTS idx_groups_subscription_type ON groups(subscription_type);
|
||||
|
||||
-- 2. 创建 user_subscriptions 用户订阅表
|
||||
CREATE TABLE IF NOT EXISTS user_subscriptions (
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
user_id BIGINT NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
||||
group_id BIGINT NOT NULL REFERENCES groups(id) ON DELETE CASCADE,
|
||||
|
||||
-- 订阅有效期
|
||||
starts_at TIMESTAMPTZ NOT NULL,
|
||||
expires_at TIMESTAMPTZ NOT NULL,
|
||||
status VARCHAR(20) NOT NULL DEFAULT 'active', -- active/expired/suspended
|
||||
|
||||
-- 滑动窗口起始时间(NULL=未激活)
|
||||
daily_window_start TIMESTAMPTZ,
|
||||
weekly_window_start TIMESTAMPTZ,
|
||||
monthly_window_start TIMESTAMPTZ,
|
||||
|
||||
-- 当前窗口已用额度(USD,基于 total_cost 计算)
|
||||
daily_usage_usd DECIMAL(20, 10) NOT NULL DEFAULT 0,
|
||||
weekly_usage_usd DECIMAL(20, 10) NOT NULL DEFAULT 0,
|
||||
monthly_usage_usd DECIMAL(20, 10) NOT NULL DEFAULT 0,
|
||||
|
||||
-- 管理员分配信息
|
||||
assigned_by BIGINT REFERENCES users(id) ON DELETE SET NULL,
|
||||
assigned_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
notes TEXT,
|
||||
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
|
||||
-- 唯一约束:每个用户对每个分组只能有一个订阅
|
||||
UNIQUE(user_id, group_id)
|
||||
);
|
||||
|
||||
-- user_subscriptions 索引
|
||||
CREATE INDEX IF NOT EXISTS idx_user_subscriptions_user_id ON user_subscriptions(user_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_user_subscriptions_group_id ON user_subscriptions(group_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_user_subscriptions_status ON user_subscriptions(status);
|
||||
CREATE INDEX IF NOT EXISTS idx_user_subscriptions_expires_at ON user_subscriptions(expires_at);
|
||||
CREATE INDEX IF NOT EXISTS idx_user_subscriptions_assigned_by ON user_subscriptions(assigned_by);
|
||||
|
||||
-- 3. 扩展 usage_logs 表添加分组和订阅关联
|
||||
ALTER TABLE usage_logs ADD COLUMN IF NOT EXISTS group_id BIGINT REFERENCES groups(id) ON DELETE SET NULL;
|
||||
ALTER TABLE usage_logs ADD COLUMN IF NOT EXISTS subscription_id BIGINT REFERENCES user_subscriptions(id) ON DELETE SET NULL;
|
||||
ALTER TABLE usage_logs ADD COLUMN IF NOT EXISTS rate_multiplier DECIMAL(10, 4) NOT NULL DEFAULT 1;
|
||||
ALTER TABLE usage_logs ADD COLUMN IF NOT EXISTS first_token_ms INT;
|
||||
|
||||
-- usage_logs 新索引
|
||||
CREATE INDEX IF NOT EXISTS idx_usage_logs_group_id ON usage_logs(group_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_usage_logs_subscription_id ON usage_logs(subscription_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_usage_logs_sub_created ON usage_logs(subscription_id, created_at);
|
||||
-- Sub2API 订阅功能迁移脚本
|
||||
-- 添加订阅分组和用户订阅功能
|
||||
|
||||
-- 1. 扩展 groups 表添加订阅相关字段
|
||||
ALTER TABLE groups ADD COLUMN IF NOT EXISTS platform VARCHAR(50) NOT NULL DEFAULT 'anthropic';
|
||||
ALTER TABLE groups ADD COLUMN IF NOT EXISTS subscription_type VARCHAR(20) NOT NULL DEFAULT 'standard';
|
||||
ALTER TABLE groups ADD COLUMN IF NOT EXISTS daily_limit_usd DECIMAL(20, 8) DEFAULT NULL;
|
||||
ALTER TABLE groups ADD COLUMN IF NOT EXISTS weekly_limit_usd DECIMAL(20, 8) DEFAULT NULL;
|
||||
ALTER TABLE groups ADD COLUMN IF NOT EXISTS monthly_limit_usd DECIMAL(20, 8) DEFAULT NULL;
|
||||
ALTER TABLE groups ADD COLUMN IF NOT EXISTS default_validity_days INT NOT NULL DEFAULT 30;
|
||||
|
||||
-- 添加索引
|
||||
CREATE INDEX IF NOT EXISTS idx_groups_platform ON groups(platform);
|
||||
CREATE INDEX IF NOT EXISTS idx_groups_subscription_type ON groups(subscription_type);
|
||||
|
||||
-- 2. 创建 user_subscriptions 用户订阅表
|
||||
CREATE TABLE IF NOT EXISTS user_subscriptions (
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
user_id BIGINT NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
||||
group_id BIGINT NOT NULL REFERENCES groups(id) ON DELETE CASCADE,
|
||||
|
||||
-- 订阅有效期
|
||||
starts_at TIMESTAMPTZ NOT NULL,
|
||||
expires_at TIMESTAMPTZ NOT NULL,
|
||||
status VARCHAR(20) NOT NULL DEFAULT 'active', -- active/expired/suspended
|
||||
|
||||
-- 滑动窗口起始时间(NULL=未激活)
|
||||
daily_window_start TIMESTAMPTZ,
|
||||
weekly_window_start TIMESTAMPTZ,
|
||||
monthly_window_start TIMESTAMPTZ,
|
||||
|
||||
-- 当前窗口已用额度(USD,基于 total_cost 计算)
|
||||
daily_usage_usd DECIMAL(20, 10) NOT NULL DEFAULT 0,
|
||||
weekly_usage_usd DECIMAL(20, 10) NOT NULL DEFAULT 0,
|
||||
monthly_usage_usd DECIMAL(20, 10) NOT NULL DEFAULT 0,
|
||||
|
||||
-- 管理员分配信息
|
||||
assigned_by BIGINT REFERENCES users(id) ON DELETE SET NULL,
|
||||
assigned_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
notes TEXT,
|
||||
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
|
||||
-- 唯一约束:每个用户对每个分组只能有一个订阅
|
||||
UNIQUE(user_id, group_id)
|
||||
);
|
||||
|
||||
-- user_subscriptions 索引
|
||||
CREATE INDEX IF NOT EXISTS idx_user_subscriptions_user_id ON user_subscriptions(user_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_user_subscriptions_group_id ON user_subscriptions(group_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_user_subscriptions_status ON user_subscriptions(status);
|
||||
CREATE INDEX IF NOT EXISTS idx_user_subscriptions_expires_at ON user_subscriptions(expires_at);
|
||||
CREATE INDEX IF NOT EXISTS idx_user_subscriptions_assigned_by ON user_subscriptions(assigned_by);
|
||||
|
||||
-- 3. 扩展 usage_logs 表添加分组和订阅关联
|
||||
ALTER TABLE usage_logs ADD COLUMN IF NOT EXISTS group_id BIGINT REFERENCES groups(id) ON DELETE SET NULL;
|
||||
ALTER TABLE usage_logs ADD COLUMN IF NOT EXISTS subscription_id BIGINT REFERENCES user_subscriptions(id) ON DELETE SET NULL;
|
||||
ALTER TABLE usage_logs ADD COLUMN IF NOT EXISTS rate_multiplier DECIMAL(10, 4) NOT NULL DEFAULT 1;
|
||||
ALTER TABLE usage_logs ADD COLUMN IF NOT EXISTS first_token_ms INT;
|
||||
|
||||
-- usage_logs 新索引
|
||||
CREATE INDEX IF NOT EXISTS idx_usage_logs_group_id ON usage_logs(group_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_usage_logs_subscription_id ON usage_logs(subscription_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_usage_logs_sub_created ON usage_logs(subscription_id, created_at);
|
||||
|
||||
Reference in New Issue
Block a user