init: 4 skills (bms-test-log-query, bms-prd-log-query, bms-mysql-test, bms-mysql-prd)

This commit is contained in:
yongjiang.lin
2026-06-11 14:46:29 +08:00
commit 337e26858b
8 changed files with 775 additions and 0 deletions
+74
View File
@@ -0,0 +1,74 @@
---
name: bms-mysql-test
description: Connect to BMS test MySQL database. Use when the user asks to query BMS database, execute SQL against BMS, check BMS data, or says "查询BMS数据库", "执行SQL", "连接BMS MySQL", "BMS数据库". This skill handles safe SQL execution — SELECT runs directly, but INSERT/UPDATE/DELETE/DDL require Windows popup confirmation before executing.
---
# BMS MySQL 数据库连接 Skill
Connect to the BMS test environment MySQL database and execute SQL queries safely.
## Available Databases
| Database | Description |
| ----------------------- | -------------------- |
| `bms_base_center` | 基础数据中心 |
| `bms_buyinvoice_center` | 采购发票中心 |
| `bms_ext_center` | 外部扩展中心 |
| `bms_invoice_center` | 发票中心 |
| `bms_order_center` | 订单中心 |
| `bms_payable_center` | 应付中心 |
| `bms_task_center` | 任务中心 |
| `cache_db` | 缓存数据库 |
| `leshop_v3` | 乐商 V3 |
| `lts` | LTS |
| `manager_db` | 管理数据库 |
| `mq_db` | 消息队列数据库 |
| `sap_push_data` | SAP 推送数据 |
| `sf_db` | SF 数据库 |
| `mysql` | 系统数据库 |
| `information_schema` | 系统信息库 |
## How to Use
Run the helper script with a SQL query:
```bash
python scripts/bms-mysql.py --query "SELECT * FROM your_table LIMIT 10"
```
## Safety Rules
### Read-only queries — execute directly
- `SELECT`, `SHOW`, `DESC`, `DESCRIBE`, `EXPLAIN` — run without confirmation
- Results are printed in a formatted table
### Write / DDL operations — require confirmation
- `INSERT`, `UPDATE`, `DELETE`, `REPLACE`
- `CREATE`, `ALTER`, `DROP`, `TRUNCATE`, `RENAME`
- `GRANT`, `REVOKE`
- A Windows popup dialog displays the full SQL and asks for Yes/No confirmation
- Only executes if user clicks **是 (Yes)**
## Script Location
- `scripts/bms-mysql.py` — the execution script (uses PyMySQL)
## Examples
```bash
# Query user table (no confirmation needed)
python scripts/bms-mysql.py --query "SELECT id, name FROM users WHERE status = 1 LIMIT 20"
# Show tables (no confirmation needed)
python scripts/bms-mysql.py --query "SHOW TABLES"
# Delete a record (requires confirmation popup)
python scripts/bms-mysql.py --query "DELETE FROM logs WHERE created_at < '2025-01-01'"
# Alter table (requires confirmation popup)
python scripts/bms-mysql.py --query "ALTER TABLE users ADD COLUMN phone VARCHAR(20)"
```
## Output Format
Results are printed as a formatted table with column headers and aligned values. Empty results show "0 rows returned." Write operations show the number of affected rows.
+171
View File
@@ -0,0 +1,171 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
BMS MySQL Database Query Tool
Executes SQL queries against the BMS test environment MySQL database.
- SELECT/SHOW/DESC/EXPLAIN: execute directly
- INSERT/UPDATE/DELETE/DDL: require Windows popup confirmation before executing
"""
import argparse
import re
import sys
import pymysql
# ─── Connection Config ───────────────────────────────────────────────────────
DB_CONFIG = {
"host": "47.106.125.251",
"port": 9696,
"user": "X7OTnSMa",
"password": "",
"charset": "utf8mb4",
"cursorclass": pymysql.cursors.DictCursor,
}
# ─── Query Classification ────────────────────────────────────────────────────
READ_ONLY_PATTERNS = re.compile(
r"^\s*(SELECT|SHOW|DESC|DESCRIBE|EXPLAIN|USE|SET)\b", re.IGNORECASE
)
WRITE_DDL_PATTERNS = re.compile(
r"^\s*(INSERT|UPDATE|DELETE|REPLACE|CREATE|ALTER|DROP|TRUNCATE|RENAME|GRANT|REVOKE|LOAD\s+DATA)\b",
re.IGNORECASE,
)
def is_read_only(sql: str) -> bool:
"""Return True if the SQL is a read-only query."""
return bool(READ_ONLY_PATTERNS.match(sql))
def is_write_or_ddl(sql: str) -> bool:
"""Return True if the SQL modifies data or schema."""
return bool(WRITE_DDL_PATTERNS.match(sql))
# ─── Confirmation Dialog ─────────────────────────────────────────────────────
def ask_confirmation(sql: str) -> bool:
"""Show a Windows popup dialog asking the user to confirm the SQL execution.
Returns True if the user clicks 'Yes', False otherwise.
"""
import tkinter as tk
from tkinter import messagebox
root = tk.Tk()
root.withdraw() # Hide the main window
title = "BMS MySQL - 写操作确认"
message = (
"即将执行以下写操作 / DDL 语句,是否继续?\n\n"
f"SQL:\n{sql}\n"
)
result = messagebox.askyesno(title, message, icon="warning")
root.destroy()
return result
# ─── Table Formatting ────────────────────────────────────────────────────────
def format_table(rows: list, columns: list) -> str:
"""Format query results as an aligned text table."""
if not rows:
return "0 rows returned."
# Calculate column widths
widths = {col: len(str(col)) for col in columns}
for row in rows:
for col in columns:
val = str(row.get(col, ""))
widths[col] = max(widths[col], len(val))
# Build header
header = " | ".join(str(col).ljust(widths[col]) for col in columns)
separator = "-+-".join("-" * widths[col] for col in columns)
# Build rows
lines = [header, separator]
for row in rows:
line = " | ".join(
str(row.get(col, "")).ljust(widths[col]) for col in columns
)
lines.append(line)
lines.append(f"\n{len(rows)} row(s) returned.")
return "\n".join(lines)
# ─── Main Execution ──────────────────────────────────────────────────────────
def execute_query(sql: str) -> None:
"""Connect to the database and execute the given SQL query."""
print(f"\n{'='*60}")
print(f"BMS MySQL (47.106.125.251:9696)")
print(f"{'='*60}")
print(f"SQL: {sql}\n")
# Classify the query
if is_read_only(sql):
query_type = "READ-ONLY"
elif is_write_or_ddl(sql):
query_type = "WRITE / DDL"
else:
query_type = "UNKNOWN"
print(f"类型: {query_type}\n")
# For write/DDL, require confirmation
if is_write_or_ddl(sql):
if not ask_confirmation(sql):
print("用户已取消操作。")
sys.exit(0)
# Connect and execute
try:
conn = pymysql.connect(**DB_CONFIG)
cursor = conn.cursor()
cursor.execute(sql)
if is_read_only(sql):
rows = cursor.fetchall()
columns = [desc[0] for desc in cursor.description] if cursor.description else []
print(format_table(rows, columns))
else:
conn.commit()
affected = cursor.rowcount
print(f"操作成功,影响 {affected} 行。")
cursor.close()
conn.close()
except pymysql.MySQLError as e:
print(f"数据库错误: {e}", file=sys.stderr)
sys.exit(1)
except Exception as e:
print(f"执行失败: {e}", file=sys.stderr)
sys.exit(1)
def main():
parser = argparse.ArgumentParser(
description="BMS MySQL 数据库查询工具"
)
parser.add_argument(
"--query", "-q",
required=True,
help="要执行的 SQL 语句",
)
args = parser.parse_args()
execute_query(args.query)
if __name__ == "__main__":
main()