Skip to content

US-P09: Chạy câu SQL đã lập danh mục trên DB Ops ​

Thuộc FS: 00-overview.md — Nền tảng dùng chung của cụm tool SAPP (as-built @ e77c47a) Phần chung (tổng quan, roles, flow tổng, related features, NFR, Open Questions, References) xem ở Overview. File này chỉ chứa nội dung riêng của US.

FieldValue
US IDUS-P09
Role thực hiệnR1 - Người dùng tool (qua sub-tool sapp.010 — SAPP 26878 và sapp.011 — SAPP 26297) — Assumption (OQ về G-01), xem OQ-P-13
PhaseAs-built (đã triển khai)
PriorityN/A — as-built
StatusDraft
NFR liên quanNFR-P-01, NFR-P-04, NFR-P-05 — xem Overview §5
OQ liên quanOQ-P-10 — xem Overview §6; Drift DR-P-11

Nguồn inventory: A-20.

Sub-tool đang dùng dịch vụ này (Fact):

Sub-toolCách dùngBằng chứng
sapp.010 — FS 26878Bước loại sql trong flow (panel "SQL cho bước này"), danh mục SAPP_26878_SQL_STATEMENTSfe/src/ui/components/works/sapp/sapp-26878-step-sql.tsx:360-445
sapp.011 — FS 26297Bước SQL của case, dùng lại đúng panel của 26878, danh mục s26297.* (39 câu: 20 đọc, 19 ghi)fe/src/ui/components/works/sapp/sapp-26297-tool.tsx:14, :100; inventory 26297 E-16, A-10

Danh mục câu lệnh (nội dung SQL) thuộc FS nhóm; US này mô tả cơ chế chạy và panel dùng chung.

1. US Statement ​

text
As a Người dùng tool (qua sub-tool 26878 / 26297)  [Assumption — OQ-P-13 / G-01]
I want xem câu SQL của bước (đã điền sẵn id của lượt chạy), rồi chạy thẳng trên DB SAPP Ops dev/staging hoặc copy sang DBeaver
So that [Assumption] dựng / kiểm / dọn dữ liệu test mà không phải tự viết SQL và không thể chạy SQL tuỳ ý

2. Dependencies & Definition Of Ready ​

N/A — đã triển khai (Mode B).

Dependency runtime: SAPP_OPS_DB_{HOST,NAME,USERNAME,PASSWORD}_{DEV,STAGING} (+ PORT tuỳ chọn) trong env_systems (US-P04); DB Ops cho phép kết nối từ API mind_keep.

3. Business Rules ​

IDRuleÁp dụng ởĐã cover bởi (AC)Nguồn code (Mode B/C)
BR-01Chỉ chạy câu lệnh có trong danh mục, gọi theo id; không bao giờ nhận SQL do người gọi gửi; giá trị tham số được driver bind, không ghép chuỗi. id không có → 13055A2AC-M1.4, EC-M1.1be/libs/modules/src/lib/sapp/sapp-ops-sql.common.service.ts:62-73, :112-122, :52-60
BR-02Không chạy được trên prod: không có bộ key prod và không có route prod. Trên prod panel chỉ cho copyM1, A2AC-M1.5be/libs/constants/src/lib/sapp/sapp-26878-sql.constants.ts:272-307, be/apps/api/src/sapp/sapp-ops.controller.ts:2404-2442, fe/src/ui/components/works/sapp/sapp-26878-step-sql.tsx:434
BR-03Hỏi trạng thái trả configured=false khi môi trường thiếu host / name / username / password — là câu trả lời bình thường, không phải lỗi; cổng mặc định 5432A1AC-M1.1, AC-M1.2be/libs/modules/src/lib/sapp/sapp-ops-sql.common.service.ts:83-108, be/apps/api/src/sapp/sapp-ops.controller.ts:82-90
BR-04Tham số thiếu hoặc rỗng → dừng với 13056 (không bao giờ bind giá trị rỗng/NULL); placeholder còn sót sau khi thay → 13057 kèm tên token và hướng dẫn viết '{token}'A2EC-M1.2, EC-M1.3be/libs/modules/src/lib/sapp/sapp-ops-sql.common.service.ts:130-163
BR-05Một mục gồm nhiều câu chạy trong một transaction; timeout 15 giây mỗi câu; SELECT trả tối đa 200 dòng (dòng thừa bị cắt, màn ghi "(đã cắt bớt)")A2AC-M1.6be/libs/modules/src/lib/sapp/sapp-ops-sql.common.service.ts:25-38, :165-174, be/libs/constants/src/lib/sapp/sapp-26878-sql.constants.ts:309-313, fe/src/ui/components/works/sapp/sapp-26878-step-sql.tsx:328
BR-06Kết quả trả id, cờ đọc/ghi, từng câu lệnh dạng placeholder (không kèm giá trị đã bind), số dòng / dòng trả về, thời gian chạyA2AC-M1.4be/libs/modules/src/lib/sapp/sapp-ops-sql.common.service.ts:17-22, :175-180
BR-07Hai danh mục có id trùng nhau → dịch vụ API từ chối khởi độngCấu hìnhAC-M1.8be/libs/constants/src/lib/sapp/sapp-ops-sql.constants.ts:7-32
BR-08Câu gắn nhãn GHI phải xác nhận trước khi chạy: "Chạy câu GHI này trên <ENV>? … Không có undo."A2AC-M1.3fe/src/ui/components/works/sapp/sapp-26878-step-sql.tsx:200-208
BR-09Nút "Chạy" chỉ bật khi môi trường là dev/staging, đã cấu hình và mọi tham số đã điền; thiếu tham số → "Còn tham số chưa điền"M1 - action ChạyAC-M1.2, AC-M1.7fe/src/ui/components/works/sapp/sapp-26878-step-sql.tsx:195, :278-291
BR-10Câu ĐỌC được đánh dấu tự chạy sẽ chạy một lần khi mở bước; câu GHI không bao giờ tự chạy; lỗi của câu tự chạy chỉ hiện tại chỗ (không bật hộp lỗi)A3AC-M1.9fe/src/ui/components/works/sapp/sapp-26878-step-sql.tsx:215-246
BR-11Panel phân biệt ba lý do không chạy được: thiếu credential DB (nêu tên key thiếu) · 401/403 · không gọi được APIM1 - UI stateAC-M1.2, EC-M1.5fe/src/ui/components/works/sapp/sapp-26878-step-sql.tsx:153-159, :380-410, :434-443

⚠️ Observed (không phải BR): lỗi DB trả nguyên thông điệp Postgres qua route public (OQ-P-10); câu chữ FE nói route chạy SQL cần JWT trong khi BE để public (DR-P-11).

4. Design &ZeroWidthSpace;

a. Mối liên hệ giữa các màn & User Flow &ZeroWidthSpace;

text
[Bước SQL của 26878 / case SQL của 26297]
  ↓ mở bước → A1 hỏi trạng thái SQL của env
[M1: Panel "SQL cho bước này"]
  ├─ prod ──────────────→ chỉ copy (BR-02)
  ├─ chưa cấu hình / 401 / không gọi được → chỉ copy + câu giải thích (BR-11)
  └─ sẵn sàng → mỗi câu: [Copy] [Chạy]
        ├─ câu ĐỌC tự chạy (BR-10)
        ├─ câu GHI → xác nhận (BR-08) → A2 chạy
        └─ kết quả / lỗi hiện dưới câu

b. Chi tiết từng màn &ZeroWidthSpace;

Màn M1 - Panel "SQL cho bước này" &ZeroWidthSpace;

FieldValue
Figma frameN/A — as-built, không có Figma
Trigger vào mànMở một bước loại SQL trong sub-tool 26878 hoặc 26297
Mô tả ngắn"Chạy trong DBeaver. Các id của lượt chạy này đã được điền sẵn." — liệt kê các câu của bước, nhãn ĐỌC/GHI, tham số, nút Copy / Chạy
UI States &ZeroWidthSpace;
StateKhi nàoHiển thịFigma frame
LoadingĐang hỏi trạng thái"Đang kiểm kết nối DB Ops…"N/A
Default (sẵn sàng)configured=true"Câu gắn nhãn GHI sửa thẳng dữ liệu và KHÔNG có undo — nút Chạy sẽ hỏi lại một lần. Một câu gồm nhiều lệnh chạy trong MỘT transaction."N/A
Disabled (prod)Môi trường prod"Production không có đường chạy SQL — chỉ copy sang DBeaver được. Câu gắn nhãn GHI không có undo."N/A
Disabled (thiếu credential)configured=false"API trả lời được nhưng chưa có credential DB cho <env>: thiếu các dòng SAPP_OPS_DB_HOST_<ENV> / NAME / USERNAME / PASSWORD trong bảng env_systems…"N/A
Error (401/403)Hỏi trạng thái bị từ chối"Chưa đăng nhập (401): route chạy SQL là route DUY NHẤT của tool này cần JWT…" (⚠️ DR-P-11)N/A
Error (không gọi được)Lỗi mạng / 404"Không gọi được API kiểm tra (<chi tiết>). Nếu backend chưa deploy bản có route /sapp-ops/sql/status thì đây là lý do. Chỉ copy sang DBeaver được."N/A
Has dataCâu đã chạySố dòng / dòng trả về từng câu, "(đã cắt bớt)" nếu vượt 200, thời gian msN/A
EmptyCâu chạy không trả dòngKết quả 0 dòngN/A

Nguồn: fe/src/ui/components/works/sapp/sapp-26878-step-sql.tsx:425-445, :310-335.

Fields &ZeroWidthSpace;
FieldRequiredTypeDefaultFormatValidationError MessageVisibilityDepends On
Câu lệnh (hiển thị)—Text readonlyĐiền sẵn từ id của lượt chạySQL với '{token}' đã thay——AlwaysTham số
Nhãn ĐỌC / GHI—BadgeTheo danh mục———Always—
Tham số của bướcYes (mọi placeholder)TextMẫu mặc định của bước (nếu có)—Không rỗng (BR-04, BR-09)"Còn tham số chưa điền" / 13056Khi câu có placeholderDữ liệu các bước trước
Filter / Search / Sort &ZeroWidthSpace;

N/A — không phải màn List.

Actions &ZeroWidthSpace;
A1 - Hỏi trạng thái SQL của môi trường (hệ thống) &ZeroWidthSpace;
ItemDescription
TriggerMở panel (env dev/staging)
BehaviorGET /api/v1/sapp/<dev|staging>/sapp-ops/sql/status. Chỉ đọc env_systems; không kết nối DB
Success Result{ configured: true/false } (BR-03)

Error cases:

CaseExpected Handling
401/403State "Chưa đăng nhập (401)…"
Lỗi mạng / 404State "Không gọi được API kiểm tra…"
A2 - Chạy một câu &ZeroWidthSpace;
ItemDescription
TriggerBấm "Chạy" (câu GHI: xác nhận trước — BR-08)
BehaviorPOST /api/v1/sapp/<dev|staging>/sapp-ops/sql/run với { statementId, params } (BR-01). Kết nối trực tiếp Postgres SAPP Ops dev hoặc staging; câu GHI sửa thẳng dữ liệu, không undo. Không có đường ghi PROD (BR-02)
Success ResultKết quả theo BR-06; id đọc được từ kết quả được đưa ngược vào dữ liệu lượt chạy cho bước sau

Error cases:

CaseExpected Handling
id không có trong danh mục13055
Môi trường chưa cấu hình13054 "No SAPP Ops database is configured for this environment…"
Thiếu tham số13056
DB từ chối13057 "The SAPP Ops database refused the statement: <thông điệp Postgres>"
A3 - Tự chạy câu đọc &ZeroWidthSpace;
ItemDescription
TriggerMở bước có câu ĐỌC đánh dấu tự chạy, môi trường sẵn sàng
BehaviorChạy một lần (BR-10); chỉ đọc DB Ops dev/staging
Success ResultKết quả hiện sẵn, id điền cho bước sau

Error cases:

CaseExpected Handling
LỗiHiện tại chỗ, không bật hộp lỗi
A4 - Copy câu lệnh &ZeroWidthSpace;
ItemDescription
TriggerBấm "Copy câu lệnh" / "Copy"
BehaviorCopy câu đã điền tham số vào clipboard. Không gọi API
Success Result"Đã copy"

Error cases:

CaseExpected Handling
Còn tham số chưa điềnNút hiện "Còn tham số chưa điền"
Acceptance Criteria của màn M1 &ZeroWidthSpace;
AC-M1.1 - Sẵn sàng &ZeroWidthSpace;
gherkin
Given staging có đủ SAPP_OPS_DB_HOST/NAME/USERNAME/PASSWORD_STAGING
When mở bước SQL trên staging
Then panel hiện state sẵn sàng và nút "Chạy" dùng được cho câu đã đủ tham số

Maps to:

  • Business Rule: BR-03, BR-09
AC-M1.2 - Chưa cấu hình không phải lỗi &ZeroWidthSpace;
gherkin
Given dev thiếu SAPP_OPS_DB_PASSWORD_DEV
When mở bước SQL trên dev
Then API trả configured = false (HTTP thành công); panel nêu các key còn thiếu và chỉ cho copy

Maps to:

  • Business Rule: BR-03, BR-09, BR-11
AC-M1.3 - Câu GHI phải xác nhận &ZeroWidthSpace;
gherkin
Given câu có nhãn GHI
When bấm "Chạy"
Then hiện xác nhận "Chạy câu GHI này trên STAGING? … Không có undo."
And bấm huỷ thì không gọi API

Maps to:

  • Business Rule: BR-08
AC-M1.4 - Chỉ chạy theo id, kết quả không lộ giá trị &ZeroWidthSpace;
gherkin
Given câu "us09.sign.1" có placeholder '{class_id}'
When chạy với class_id = "abc"
Then BE lấy SQL từ danh mục, bind "abc" làm tham số
And kết quả trả câu lệnh dạng "$1" (không chứa "abc"), số dòng và thời gian

Maps to:

  • Business Rule: BR-01, BR-06
AC-M1.5 - Prod chỉ copy &ZeroWidthSpace;
gherkin
Given sub-tool đang ở prod
When mở bước SQL
Then panel hiện "Production không có đường chạy SQL — chỉ copy sang DBeaver được…"
And không có route prod để gọi

Maps to:

  • Business Rule: BR-02
AC-M1.6 - Nhiều câu một transaction, giới hạn &ZeroWidthSpace;
gherkin
Given mục dọn dữ liệu gồm 3 câu, câu thứ 3 lỗi ràng buộc
When chạy
Then cả 3 câu bị huỷ (không câu nào được giữ) và trả 13057
And một câu SELECT trả 500 dòng thì chỉ nhận 200 dòng, đánh dấu "(đã cắt bớt)"

Maps to:

  • Business Rule: BR-05
AC-M1.7 - Thiếu tham số &ZeroWidthSpace;
gherkin
Given câu còn placeholder chưa có giá trị
When xem panel
Then nút Chạy vô hiệu với nhãn "Còn tham số chưa điền"

Maps to:

  • Business Rule: BR-09
AC-M1.8 - Id trùng chặn khởi động &ZeroWidthSpace;
gherkin
Given danh mục 26878 và 26297 có cùng một id câu lệnh
When API khởi động
Then API không khởi động được (lỗi cấu hình)

Maps to:

  • Business Rule: BR-07
AC-M1.9 - Câu đọc tự chạy &ZeroWidthSpace;
gherkin
Given bước có câu ĐỌC đánh dấu tự chạy và env sẵn sàng
When mở bước
Then câu đó chạy đúng một lần; câu GHI trong cùng bước không tự chạy

Maps to:

  • Business Rule: BR-10
Negative AC / Edge Cases của màn M1 &ZeroWidthSpace;
IDTình huốngHành vi mong đợi
EC-M1.1Gọi API với id không có trong danh mục13055 "Unknown SQL statement id…raw SQL is never accepted."
EC-M1.2Gọi API thiếu một tham số13056, không chạy câu nào
EC-M1.3Placeholder viết '{code_prefix}%' (không chiếm trọn cặp nháy)13057 nêu token chưa được thay
EC-M1.4⚠️ Observed — DB từ chối câu lệnhThông điệp Postgres gốc (tên cột, ràng buộc) trả qua route public (be/libs/modules/src/lib/sapp/sapp-ops-sql.common.service.ts:181-193; OQ-P-10)
EC-M1.5⚠️ Observed — Panel nói route SQL "cần JWT"BE để route public; state 401 chỉ xảy ra nếu hạ tầng chặn (DR-P-11)
EC-M1.6Câu một phần mất > 15 giâyHết thời gian → 13057; transaction bị huỷ

5. Cross-feature AC &ZeroWidthSpace;

AC-X.1 - 26878 và 26297 dùng chung panel &ZeroWidthSpace;

gherkin
Given FS 26878 (bước sql) và FS 26297 (case SQL)
When đặc tả bước SQL
Then cả hai tham chiếu US-P09 cho cơ chế chạy, xác nhận GHI, trạng thái; chỉ mô tả nội dung câu trong danh mục của mình

Maps to:

  • REL-05 (Be Affected - FS 26878)
  • REL-06 (Be Affected - FS 26297)