SQL修复验证测试.py 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  1. #!/usr/bin/env python3
  2. # -*- coding: utf-8 -*-
  3. """
  4. SQL修复验证测试
  5. 直接测试学生信息管理SQL语句是否修复了重复WHERE子句问题
  6. """
  7. import time
  8. import requests
  9. import json
  10. from datetime import datetime
  11. # 配置
  12. BASE_URL = "http://localhost:8080"
  13. HEADERS = {
  14. 'Content-Type': 'application/json',
  15. 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36'
  16. }
  17. def test_service_health():
  18. """测试服务健康状态"""
  19. print("=== 测试服务健康状态 ===")
  20. try:
  21. response = requests.get(f"{BASE_URL}/", headers=HEADERS, timeout=5)
  22. print(f"服务状态码: {response.status_code}")
  23. print(f"服务响应: {response.text[:100]}...")
  24. if response.status_code == 200:
  25. print("✅ 服务正常运行")
  26. return True
  27. else:
  28. print(f"⚠️ 服务状态异常: {response.status_code}")
  29. return False
  30. except Exception as e:
  31. print(f"❌ 服务连接失败: {e}")
  32. return False
  33. def test_sql_error_pattern():
  34. """测试SQL错误模式"""
  35. print("\n=== 测试SQL错误模式 ===")
  36. # 测试会触发SQL错误的请求
  37. search_params = {
  38. 'pageNum': 1,
  39. 'pageSize': 10,
  40. 'gender': '男', # 这个参数会触发QueryWrapper生成WHERE子句
  41. }
  42. try:
  43. response = requests.get(f"{BASE_URL}/xg/studentInfo/list",
  44. params=search_params,
  45. headers=HEADERS,
  46. timeout=10)
  47. print(f"请求状态码: {response.status_code}")
  48. print(f"响应内容: {response.text[:400]}...")
  49. if response.status_code == 200:
  50. data = response.json()
  51. if data.get('code') == 401:
  52. print("✅ 正常返回401认证错误(预期行为)")
  53. return True
  54. elif data.get('code') == 500:
  55. error_msg = data.get('msg', '')
  56. if "WHERE deleted = 0 AND tenant_id = '000000' WHERE" in error_msg:
  57. print("❌ 仍然存在重复WHERE子句错误")
  58. print("🔧 XML映射文件修复可能没有生效")
  59. return False
  60. else:
  61. print("❌ 其他500错误")
  62. print(f"错误信息: {error_msg}")
  63. return False
  64. else:
  65. print(f"⚠️ 意外的响应码: {data.get('code')}")
  66. return False
  67. elif response.status_code == 500:
  68. # 直接500错误
  69. response_text = response.text
  70. if "WHERE deleted = 0 AND tenant_id = '000000' WHERE" in response_text:
  71. print("❌ 仍然存在重复WHERE子句错误")
  72. print("🔧 XML映射文件修复可能没有生效")
  73. return False
  74. else:
  75. print("❌ 其他500错误")
  76. print(f"错误详情: {response_text[:200]}...")
  77. return False
  78. else:
  79. print(f"⚠️ 预期200状态码,实际: {response.status_code}")
  80. return False
  81. except Exception as e:
  82. print(f"❌ 请求异常: {e}")
  83. return False
  84. def test_xml_file_content():
  85. """验证XML文件内容"""
  86. print("\n=== 验证XML文件内容 ===")
  87. xml_file_path = "../backend/ruoyi-modules/ruoyi-xg-xx/src/main/resources/mapper/xg/XgStudentInfoMapper.xml"
  88. try:
  89. with open(xml_file_path, 'r', encoding='utf-8') as f:
  90. content = f.read()
  91. # 检查是否包含正确的SQL结构
  92. if "WHERE deleted = 0 AND tenant_id = '000000'\n ${ew.customSqlSegment}" in content:
  93. print("✅ XML文件包含正确的SQL结构")
  94. return True
  95. elif "<where>" in content and "${ew.customSqlSegment}" in content:
  96. print("❌ XML文件仍然使用<where>标签包裹customSqlSegment")
  97. print("🔧 需要手动修复XML文件")
  98. return False
  99. else:
  100. print("⚠️ XML文件结构不明确")
  101. print("🔍 让我检查具体内容...")
  102. # 查找selectVoPage方法
  103. if "selectVoPage" in content:
  104. lines = content.split('\n')
  105. for i, line in enumerate(lines):
  106. if "selectVoPage" in line:
  107. print(f"找到selectVoPage方法,周围内容:")
  108. start = max(0, i-2)
  109. end = min(len(lines), i+10)
  110. for j in range(start, end):
  111. print(f"{j+1:3d}: {lines[j]}")
  112. break
  113. return False
  114. except Exception as e:
  115. print(f"❌ 读取XML文件失败: {e}")
  116. return False
  117. def show_correct_vs_incorrect():
  118. """显示正确与错误的SQL结构对比"""
  119. print("\n=== SQL结构对比 ===")
  120. print("✅ 正确的XML结构:")
  121. print("""
  122. <select id="selectVoPage" resultMap="XgStudentInfoResult">
  123. SELECT ... FROM xg_student_info
  124. WHERE deleted = 0 AND tenant_id = '000000'
  125. ${ew.customSqlSegment}
  126. </select>
  127. """)
  128. print("❌ 错误的XML结构:")
  129. print("""
  130. <select id="selectVoPage" resultMap="XgStudentInfoResult">
  131. SELECT ... FROM xg_student_info
  132. <where>
  133. deleted = 0 AND tenant_id = '000000'
  134. ${ew.customSqlSegment}
  135. </where>
  136. </select>
  137. """)
  138. print("🔍 错误原因:")
  139. print("- MyBatis-Plus的${ew.customSqlSegment}可能已经包含WHERE关键字")
  140. print("- 使用<where>标签包裹会导致重复的WHERE子句")
  141. print("- 正确做法是直接在SQL中写WHERE条件,然后跟${ew.customSqlSegment}")
  142. def main():
  143. """主函数"""
  144. print("🚀 SQL修复验证测试")
  145. print("=" * 50)
  146. # 测试服务健康状态
  147. if not test_service_health():
  148. print("❌ 服务未正常运行,无法进行测试")
  149. return
  150. # 验证XML文件内容
  151. xml_ok = test_xml_file_content()
  152. # 测试SQL错误模式
  153. sql_ok = test_sql_error_pattern()
  154. # 显示结构对比
  155. show_correct_vs_incorrect()
  156. print("\n" + "=" * 50)
  157. print("📊 测试结果总结:")
  158. print(f"XML文件结构: {'✅ 正确' if xml_ok else '❌ 错误'}")
  159. print(f"SQL执行结果: {'✅ 正常' if sql_ok else '❌ 异常'}")
  160. if xml_ok and sql_ok:
  161. print("🎉 SQL修复验证通过!")
  162. elif xml_ok and not sql_ok:
  163. print("⚠️ XML文件已修复,但可能需要重启服务")
  164. else:
  165. print("❌ 需要检查XML文件修复")
  166. if __name__ == "__main__":
  167. main()