opsx
|
71d5afff03
|
fix(query): 结尾分号导致 LIMIT 拼接成两条语句(MySQL 1064)+ SQL 编辑器光标异常与无法滚动
=== 一、点表生成的语句带分号 → 查询必报 1064 ===
用户报错:
Error 1064 (42000): You have an error in your SQL syntax; ...
near 'LIMIT 100 OFFSET 0' at line 2
复现语句(点表自动生成的原文,天然带分号):
SELECT * FROM `cex_activity`.`concert_goods_language`;
根因在 instance_detail.go 的自动补 LIMIT:
sqlStr = fmt.Sprintf("%s LIMIT %d OFFSET %d", sqlStr, limit, offset)
原语句已以 ';' 结尾 → 拼完变成
SELECT * FROM ...; LIMIT 100 OFFSET 0
→ 两条语句,报错位置就是第 2 行的 LIMIT(与报错文案完全吻合)。
修复:新增 normalizeSQLForExec(),去掉首尾空白并反复剥掉结尾分号,
在两个「会拼 LIMIT」的入口统一调用:
① executeSQLQuery(查询)—— 归一化后再生效 COUNT(*) 统计与 LIMIT 注入
② exportSQLCSV(导出 CSV)—— 同样先归一化再拼 LIMIT
顺带收益:COUNT(*) 统计以前也会带上分号(虽然 MySQL 容忍),现在干净了。
安全边界未被放松:多语句仍被 isReadOnlySQL 拦住
SELECT 1; SELECT 2 → 拒绝「不允许一次执行多条语句」✅
SELECT 1; LIMIT 5 → 拒绝 ✅(这是一次性两条语句,不是尾分号)
双分号 ;; → 归一化后正常执行 ✅
=== 二、SQL / Redis / Mongo 编辑器:光标异常 + 只有 13 行且滚不动 ===
用户反馈:
「默认还是有一个很长的竖线 一闪一闪,需要回车后第 2 行才正常」
「输入框下面还有空白,最后只有 13 行可以输入,至少需要加一个滚动」
根因 1(滚不动,13 行):appTheme 的 '&' 没有 height:100%。
.cm-editor 会随内容无限增高,而外层 div 固定 200px 且裁切,
CodeMirror 内部的 .cm-scroller 永远拿不到受限高度 → 不产生滚动条。
13 行 = 200px ÷ 15px 行高,正好对上。
根因 2(光标拉长):appTheme 在 extensions 里排在 oneDark 【之前】。
CodeMirror theme 是后者覆盖前者,oneDark 的默认行高/内边距盖掉了我们的
line-height,首次测量拿到的行高不对 → 空文档时光标高度算成好几行。
修复:
① appTheme '&' 增加 height:'100%';外层容器 style 改为
height + minHeight:120px + resize:vertical + overflow:hidden
(.cm-scroller 立刻有确定高度 → 内部滚动生效;右下角还能拖动拉高)
② appTheme 移到 oneDark 之后(顺序即优先级)
③ 行高统一写成 1.55em,并在 .cm-scroller / .cm-content / .cm-line /
.cm-gutters 四处保持一致(CM 靠读 .cm-content 的 line-height 算光标高度)
④ 挂载后 requestMeasure() + 下一帧再测一次 + document.fonts.ready 后再测一次,
修掉「首帧测量错乱」这一大类问题
⑤ SqlEditorSection 默认高度 200px → 240px(约 15 行可见)
注意:仍然不要给 .cm-cursor 写死 height / marginTop ——
CM 自己按行高算,写死会溢出到相邻行(历史上已经踩过一次)。
=== 三、实测 ===
表本身为空:cex_activity.concert_goods_language COUNT(*)=0
→ SELECT * 返回 0 行是正确结果,不是故障
分号归一化:带分号 / 不带分号 / 双分号 → rows=100 total=17447 完全一致,无 1064 ✅
安全边界:两条语句、分号后接 LIMIT 均被拒 ✅
编辑器产物:SqlEditor-*.js 内含 1.55em 与 resize:"vertical" ✅
镜像:lghost/opsxsql:latest + v0.1 = sha256:72a00dda2419
|
2026-10-27 09:22:11 +00:00 |
|
opsx
|
36724bba94
|
fix(queries): MySQL 实例误调 Redis 接口 500 + 点表生成 SELECT + 光标多行闪烁
=== 一、/queries 打开 MySQL 实例报 500 ===
现象:GET /api/v1/redis/5/dbs → 500
后端日志 redis: invalid reply: "J\x00\x00\x00\n"
("J\x00\x00\x00" 是 MySQL 握手包,说明用 Redis 协议连了 3306)
根因:SchemaSidebar 是 mysql/redis 共用的组件,其中
const redisDbs = useRedisDbs(Number(instanceId));
是无条件调用(React hooks 不能条件调用),而 useRedisDbs 内部
只看 instanceId 就请求 /redis/{id}/dbs →
MySQL 实例也发 Redis 请求 → 后端用 Redis 协议连 MySQL → 500。
修复(前后端双保险):
1. useRedisDbs 增加 enabled 参数(默认 true),false 时不发请求并复位 [0]/false
2. SchemaSidebar 传 isRedis:useRedisDbs(Number(instanceId), isRedis)
3. redis.go getRedisClient 前置校验 DBType != "redis" 直接返回
4. resp 包新增 UserFacingError / UserFacing(),InternalErr 识别后返回
400 + 可读原因(不再把所有错误笼统包装成 500 "服务器内部错误")
验证:
GET /redis/5/dbs(MySQL)→ 400
{"code":"bad_request","detail":"实例「pre-mysql-只读」的类型是 mysql,
不是 redis。Redis 接口只适用于 redis 实例;MySQL/PostgreSQL 请使用
/api/v1/instances/5/databases 等对应接口"}
GET /instances/5/databases → 200
GET /redis/4/dbs(Redis 集群)→ 200 {"cluster":true,"dbs":[0]}
=== 二、左侧栏点表不生成 SELECT ===
原交互:单击=展开/折叠,双击=执行 SELECT,Alt+点击=插入表名。
需求:单击表 → 在右侧编辑器生成 SELECT * FROM <db>.<table>
修复:
1. SchemaSidebar 表节点:箭头图标包 data-chevron 单独触发展开/折叠;
点表名区域 → onInsert(previewSelectSql(...) + ';\n')
Alt+点击仍为只插表名;双击仍为直接执行
2. QueriesPage onInsert:生成的文本以 SELECT 开头时「替换」编辑器内容
(原来一律追加,会和上一条语句拼成非法 SQL);表名/字段名仍追加
=== 三、SQL 编辑器光标同时在多行闪烁 ===
根因:.cm-cursor 强制了 height:1.25em !important + marginTop:0.15em,
而 .cm-line 行高是 1.55em,光标高度溢出到相邻行,视觉上像两行同时闪。
修复:光标样式只保留颜色与 1.5px 宽度,height/marginTop 交回 CodeMirror 自行计算。
镜像:lghost/opsxsql:latest + v0.1
|
2026-10-27 00:58:22 +00:00 |
|
Logan.Li
|
f6d636fa44
|
feat(query): sql workspace conveniences per opsxdb patterns
- generic ContextMenu component (viewport flip, esc/outside close)
- SchemaSidebar table right-click menu: preview data, generate
SELECT/INSERT/UPDATE/DELETE templates with pk-aware WHERE, copy table
name; double-click table runs preview SELECT; column right-click
copy/insert; dialect-aware quoting; preview SELECT carries no LIMIT
- SqlEditor selection-first execution (Mod-Enter runs selection else
statement at cursor via quote/comment-aware splitter); pagination
replays last executed statement
- query history persisted server-side: drawer fetches query-histories
with keyword/mine/favorites filters, star toggle (new PUT favorite +
mine filter endpoints), insert and insert-and-run
- custom templates in localStorage alongside built-ins
- unit tests: genSql + statement splitter (28 tests green)
|
2026-10-26 18:53:02 +08:00 |
|
hermes-$(hostname)
|
0fcdbc5f6c
|
update
|
2026-07-08 08:53:48 +00:00 |
|
logan
|
889cce140b
|
refactor: 弹框架构重构 + 审核规则seed API + LDAP默认配置 + 全量初始数据
弹框架构:
- Layout header/sidebar z-[200] 隔离弹框层,弹框不再遮挡面包屑
- dialog.tsx 简化: 去掉 border/backdrop-blur,统一暗色主题变量
- ModalOverlay z-[100] 对齐 Radix Dialog overlay 层级
- EditInstanceDialog 同步 z-index 修复
- 修复 InstanceGroupPage/InstancePage/LdapConfigPage 缺失 import
- 修复 InstanceGroupPage 缺失 X icon import
- RedisDetailPage ModalOverlay 迁移为 FormDialog
审核规则:
- POST /audit-rules/seed/:dbType 初始化默认规则 (mysql 11/pg 7/redis 4/mongo 4)
- POST /audit-rules/:id/toggle 开关规则
- PUT /audit-rules/:id 编辑规则
- seed.go 启动时自动创建 26 条默认审核规则
LDAP 默认配置:
- seed.go 自动写入 9 条 LDAP 配置 (8.217.205.92:389, dc=opsx,dc=vip)
- 全新 DB 启动即就位,无需手动配置
|
2026-05-29 22:48:45 +08:00 |
|
logan
|
7e26837c5f
|
refactor: TicketCreatePage用SchemaSidebar替换手写浏览器+SqlEditor暴露insertText光标定位
- SqlEditor: 添加 forwardRef + useImperativeHandle 暴露 insertText 方法
- 支持在光标位置插入文本并移动光标
- TicketCreatePage: 删除300+行手写表结构/Redis/索引浏览代码
- 统一使用 SchemaSidebar 组件(与查询页一致)
- handleSchemaInsert: 已选库插table名,未选库插db.table名
- 清理未用 imports/icons/types/helpers (RedisKeyItem, formatBytes等)
- 848行 → 435行
|
2026-05-28 21:34:59 +08:00 |
|
logan
|
35a014e571
|
feat: 查询页增强 + 权限体系优化
- Redis DB0~DB15 下拉选择,默认DB0
- 查询历史粘贴按钮(一键填入SQL编辑器)
- 去掉导出历史按钮
- SchemaSidebar 按目标数据库筛选
- SQL自动补全 schema 双层注册(db→tables, table→columns)
- 后端 db-schema 接口(INFORMATION_SCHEMA.COLUMNS 一次加载)
- autocompletion 扩展激活
- Redis key 树形结构(冒号分隔层级)
- Redis 查询模板 GET/HGETALL/HGET
- guest 角色彻底移除,改为 auditor
- 登录页优化:去掉演示账号、placeholder 中文提示
|
2026-05-24 18:50:08 +08:00 |
|
logan
|
b39c426317
|
fix: merge后14个测试修复+前端TS编译修复 - 895/895通过+前端零错误
|
2026-05-23 17:50:13 +08:00 |
|
logan
|
58eb78c987
|
merge: SQL平台代码v1 优化包合并 — 193条审核规则 + 16页面UI优化
后端新增 (Step 1):
- mysql_audit_rules.py: 63条 MySQL审核规则 (DDL 36 + DML 9 + 命名 5 + 性能 5 + 安全 5)
- redis_audit_rules.py: 43条 Redis审核规则 (KEY管理 10 + 命令安全 12 + 数据结构 8 + 性能 8 + 安全 5)
- mongodb_audit_rules.py: 42条 MongoDB审核规则 (集合管理 + 查询安全 + 聚合管道 + 写入安全 + 性能)
- postgres_audit_rules.py: 45条 PostgreSQL审核规则 (DDL 18 + DML 8 + DQL 6 + 安全 6 + 性能 7)
后端合并 (Step 2):
- audit_engine_v2.py: 新增4个DB规则模块import (100+→200+规则)
- audit_rule_seeds.py: 新增30条MongoDB种子规则 + 别名映射
- audit_rule.py: 新增数据库类型别名 (postgresql→postgres, pg→postgres, mongo→mongodb)
前端优化 (Step 4) — 16页面全覆盖:
- InstancePage, WorkflowPage, TicketsPage, TicketCreatePage, TicketDetailPage
- UsersPage, SlowQueryPage, DataDictionaryPage, Dashboard
- InstanceGroupPage, AuditLogsPage, QueriesPage, AuditRulesPage, RolesPage
- useAuth.tsx, SqlEditor.tsx
后端测试 895/895 通过, 前端 tsc --noEmit 通过
|
2026-05-23 16:46:13 +08:00 |
|
logan
|
583e891619
|
fix: CodeMirror多实例冲突 — 移除@codemirror/rectangular-selection@0.19.x和codemirror元包
根因: @codemirror/rectangular-selection@0.19.2 引入 @codemirror/state@0.19.9 (旧版)
与主依赖 @codemirror/state@6.6.0 冲突,导致 instanceof 检查失败
修复:
- npm uninstall @codemirror/rectangular-selection (已合并到 @codemirror/view)
- npm uninstall codemirror (元包,无代码引用)
- SqlEditor.tsx 移除 rectangularSelection import 和调用
- 后端测试 843/843 通过
|
2026-05-23 15:07:51 +08:00 |
|
logan
|
4c9427e546
|
sync: 同步 sql-platform-pro 最新代码 — 权限体系安全修复 v0.8.1
- P0: 实例访问控制全线接入权限组 (829测试)
- P1: permissions字段激活 + 操作级权限检查 (843测试)
- 前端: 删除数据权限页面, 权限组合并为唯一入口
- 新增: CodeMirror编辑器 + 查询模板 + 慢查询分析
- 新增: MongoDB管理页面 + Dashboard增强
- 修复: Pydantic V2迁移 + 前端TS错误修复
|
2026-05-23 14:41:06 +08:00 |
|