rebuild_all.sh 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292
  1. #!/bin/bash
  2. # ============================================
  3. # 数据库完整重建脚本
  4. # 删除所有表并重新初始化(包含所有迁移)
  5. # ============================================
  6. set -e
  7. # 颜色定义
  8. RED='\033[0;31m'
  9. GREEN='\033[0;32m'
  10. YELLOW='\033[1;33m'
  11. BLUE='\033[0;34m'
  12. NC='\033[0m'
  13. # 数据库配置(根据实际情况修改)
  14. DB_HOST=${DB_HOST:-localhost}
  15. DB_PORT=${DB_PORT:-5432}
  16. DB_NAME=${DB_NAME:-lingyue_zhibao}
  17. DB_USER=${DB_USER:-postgres}
  18. DB_PASSWORD=${DB_PASSWORD:-postgres}
  19. log_info() { echo -e "${GREEN}[INFO]${NC} $1"; }
  20. log_warn() { echo -e "${YELLOW}[WARN]${NC} $1"; }
  21. log_error() { echo -e "${RED}[ERROR]${NC} $1"; }
  22. log_title() { echo -e "\n${BLUE}========== $1 ==========${NC}\n"; }
  23. # 获取脚本所在目录
  24. SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
  25. PROJECT_ROOT="$(cd "${SCRIPT_DIR}/../.." && pwd)"
  26. SQL_DIR="${SCRIPT_DIR}"
  27. MIGRATIONS_DIR="${PROJECT_ROOT}/database/migrations"
  28. # 删除所有表
  29. drop_all_tables() {
  30. log_title "删除所有表"
  31. if [ "$FORCE" != "yes" ]; then
  32. log_warn "这将删除数据库 ${DB_NAME} 中的所有表和数据!"
  33. read -p "是否继续?(yes/no): " confirm
  34. if [ "$confirm" != "yes" ]; then
  35. log_info "操作已取消"
  36. exit 0
  37. fi
  38. fi
  39. log_info "开始删除表..."
  40. PGPASSWORD=${DB_PASSWORD} psql -h ${DB_HOST} -p ${DB_PORT} -U ${DB_USER} -d ${DB_NAME} <<EOF
  41. -- 禁用外键约束检查
  42. SET session_replication_role = 'replica';
  43. -- 删除所有表
  44. DO \$\$
  45. DECLARE
  46. r RECORD;
  47. BEGIN
  48. FOR r IN (SELECT tablename FROM pg_tables WHERE schemaname = 'public')
  49. LOOP
  50. EXECUTE 'DROP TABLE IF EXISTS public.' || quote_ident(r.tablename) || ' CASCADE';
  51. RAISE NOTICE 'Dropped table: %', r.tablename;
  52. END LOOP;
  53. END
  54. \$\$;
  55. -- 删除所有序列
  56. DO \$\$
  57. DECLARE
  58. r RECORD;
  59. BEGIN
  60. FOR r IN (SELECT sequencename FROM pg_sequences WHERE schemaname = 'public')
  61. LOOP
  62. EXECUTE 'DROP SEQUENCE IF EXISTS public.' || quote_ident(r.sequencename) || ' CASCADE';
  63. END LOOP;
  64. END
  65. \$\$;
  66. -- 删除所有函数
  67. DO \$\$
  68. DECLARE
  69. r RECORD;
  70. BEGIN
  71. FOR r IN (SELECT proname, oidvectortypes(proargtypes) as args
  72. FROM pg_proc
  73. INNER JOIN pg_namespace ns ON (pg_proc.pronamespace = ns.oid)
  74. WHERE ns.nspname = 'public')
  75. LOOP
  76. EXECUTE 'DROP FUNCTION IF EXISTS public.' || quote_ident(r.proname) || '(' || r.args || ') CASCADE';
  77. END LOOP;
  78. END
  79. \$\$;
  80. -- 恢复外键约束检查
  81. SET session_replication_role = 'origin';
  82. SELECT 'Tables remaining:' as status, COUNT(*) as count FROM pg_tables WHERE schemaname = 'public';
  83. EOF
  84. log_info "所有表已删除"
  85. }
  86. # 执行 SQL 文件
  87. execute_sql() {
  88. local file=$1
  89. local desc=$2
  90. if [ -f "$file" ]; then
  91. log_info "执行: ${desc} (${file})"
  92. PGPASSWORD=${DB_PASSWORD} psql -h ${DB_HOST} -p ${DB_PORT} -U ${DB_USER} -d ${DB_NAME} -f "$file" 2>&1 | grep -v "^NOTICE:" || true
  93. log_info "${desc} 完成"
  94. else
  95. log_warn "文件不存在: ${file}"
  96. fi
  97. }
  98. # 初始化所有表
  99. init_all_tables() {
  100. log_title "初始化数据库表"
  101. # 1. 基础表(users, documents 等核心表)
  102. execute_sql "${SQL_DIR}/init.sql" "基础表 (users, documents, elements, etc.)"
  103. # 2. 图谱表(graph_nodes, graph_relations - 先于 supplement_tables)
  104. execute_sql "${SQL_DIR}/graph_tables.sql" "图谱表 (graph_nodes, graph_relations)"
  105. # 3. 补充表(rules, data_sources, templates, text_storage 等)
  106. execute_sql "${SQL_DIR}/supplement_tables.sql" "补充表 (rules, data_sources, templates, text_storage)"
  107. # 4. RAG 表(text_chunks, vector_embeddings - 可能需要 pgvector)
  108. execute_sql "${SQL_DIR}/rag_tables_compatible.sql" "RAG 表 (text_chunks, vector_embeddings)"
  109. # 5. 执行迁移文件(按文件名排序)
  110. log_title "执行迁移脚本"
  111. if [ -d "$MIGRATIONS_DIR" ]; then
  112. for migration in $(ls -1 "${MIGRATIONS_DIR}"/*.sql 2>/dev/null | sort); do
  113. if [ -f "$migration" ]; then
  114. execute_sql "$migration" "迁移: $(basename $migration)"
  115. fi
  116. done
  117. else
  118. log_warn "迁移目录不存在: ${MIGRATIONS_DIR}"
  119. fi
  120. }
  121. # 验证表创建
  122. verify_tables() {
  123. log_title "验证表创建"
  124. PGPASSWORD=${DB_PASSWORD} psql -h ${DB_HOST} -p ${DB_PORT} -U ${DB_USER} -d ${DB_NAME} <<EOF
  125. SELECT tablename as "表名"
  126. FROM pg_tables
  127. WHERE schemaname = 'public'
  128. ORDER BY tablename;
  129. SELECT COUNT(*) as "表总数" FROM pg_tables WHERE schemaname = 'public';
  130. EOF
  131. }
  132. # 创建测试用户
  133. create_test_user() {
  134. log_title "创建测试用户"
  135. PGPASSWORD=${DB_PASSWORD} psql -h ${DB_HOST} -p ${DB_PORT} -U ${DB_USER} -d ${DB_NAME} <<EOF
  136. -- 插入测试管理员用户(密码: Admin123!)
  137. INSERT INTO users (id, username, email, password_hash, role, create_time, update_time)
  138. VALUES (
  139. '00000000000000000000000000000001',
  140. 'admin',
  141. 'admin@lingyue.com',
  142. '\$2a\$10\$N.zmdr9k7uOCQb376NoUnuTJ8iUtkWBrq.VZbISbAi1L9sNPIiMMi',
  143. 'admin',
  144. CURRENT_TIMESTAMP,
  145. CURRENT_TIMESTAMP
  146. )
  147. ON CONFLICT (id) DO NOTHING;
  148. -- 插入测试普通用户(密码: User1234!)
  149. INSERT INTO users (id, username, email, password_hash, role, create_time, update_time)
  150. VALUES (
  151. '00000000000000000000000000000002',
  152. 'testuser',
  153. 'test@lingyue.com',
  154. '\$2a\$10\$5XvCJaLqDXJz.YqL8TnNKegHH7q6KM7YFzMVxLPNMvJx5f7mxnKQi',
  155. 'user',
  156. CURRENT_TIMESTAMP,
  157. CURRENT_TIMESTAMP
  158. )
  159. ON CONFLICT (id) DO NOTHING;
  160. SELECT id, username, email, role FROM users;
  161. EOF
  162. log_info "测试用户创建完成"
  163. log_info " admin / Admin123!"
  164. log_info " testuser / User1234!"
  165. }
  166. # 显示帮助
  167. show_help() {
  168. cat <<EOF
  169. 数据库完整重建脚本
  170. 用法: ./rebuild_all.sh [选项]
  171. 选项:
  172. -h, --help 显示帮助
  173. -f, --force 跳过确认提示
  174. --no-test-user 不创建测试用户
  175. 环境变量:
  176. DB_HOST 数据库主机 (默认: localhost)
  177. DB_PORT 数据库端口 (默认: 5432)
  178. DB_NAME 数据库名称 (默认: lingyue_zhibao)
  179. DB_USER 数据库用户 (默认: postgres)
  180. DB_PASSWORD 数据库密码 (默认: postgres)
  181. 示例:
  182. # 使用默认配置
  183. ./rebuild_all.sh
  184. # 指定数据库配置
  185. DB_PASSWORD=mypassword ./rebuild_all.sh
  186. # 强制执行(跳过确认)
  187. FORCE=yes ./rebuild_all.sh
  188. # 服务器上执行
  189. DB_USER=lingyue DB_PASSWORD=123123 ./rebuild_all.sh
  190. 执行顺序:
  191. 1. 删除所有表、序列、函数
  192. 2. 执行 init.sql(用户、文档、元素等基础表)
  193. 3. 执行 supplement_tables.sql(补充表)
  194. 4. 执行 graph_tables.sql(图谱表)
  195. 5. 执行 rag_tables_compatible.sql(RAG表)
  196. 6. 执行 database/migrations/*.sql(迁移脚本)
  197. 7. 创建测试用户
  198. 8. 验证表创建
  199. EOF
  200. }
  201. # 主函数
  202. main() {
  203. CREATE_TEST_USER=true
  204. while [[ $# -gt 0 ]]; do
  205. case $1 in
  206. -h|--help)
  207. show_help
  208. exit 0
  209. ;;
  210. -f|--force)
  211. FORCE=yes
  212. shift
  213. ;;
  214. --no-test-user)
  215. CREATE_TEST_USER=false
  216. shift
  217. ;;
  218. *)
  219. log_error "未知选项: $1"
  220. show_help
  221. exit 1
  222. ;;
  223. esac
  224. done
  225. log_title "数据库完整重建脚本"
  226. echo "数据库: ${DB_NAME}"
  227. echo "主机: ${DB_HOST}:${DB_PORT}"
  228. echo "用户: ${DB_USER}"
  229. echo "SQL目录: ${SQL_DIR}"
  230. echo "迁移目录: ${MIGRATIONS_DIR}"
  231. echo ""
  232. drop_all_tables
  233. init_all_tables
  234. if [ "$CREATE_TEST_USER" = true ]; then
  235. create_test_user
  236. fi
  237. verify_tables
  238. log_title "数据库重建完成"
  239. log_info "所有表已创建并验证"
  240. }
  241. main "$@"