From f447ae742b29bfa39962499911d3e015bbdac6eb Mon Sep 17 00:00:00 2001 From: Msystech Date: Thu, 13 Aug 2026 16:10:27 +0900 Subject: [PATCH] =?UTF-8?q?=EA=B2=80=EC=A6=9D=20=EC=8B=A4=ED=96=89=20?= =?UTF-8?q?=EA=B2=B0=EA=B3=BC=EC=97=90=20=EC=B6=9C=EB=A0=A5=20=ED=96=89?= =?UTF-8?q?=EC=9D=B4=20=EC=95=88=20=EB=B3=B4=EC=9D=B4=EB=8D=98=20=EB=AC=B8?= =?UTF-8?q?=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 결과를 ExpandoObject 목록으로 DataGrid 에 넘기고 있었다. DataGrid 의 AutoGenerateColumns 는 항목 타입의 속성을 반사해 열을 만드는데 ExpandoObject 에는 그런 속성이 없다 — 그래서 요약("성공 — 컬럼 2개, 표본 3행")은 맞게 뜨는데 표는 비어 있었다. DataTable 로 바꿨다. DataGrid 가 직접 알아본다. 같은 컬럼명이 두 번 나오면(별칭 없는 조인에서 흔하다) DataTable 이 예외를 내므로 뒤에 번호를 붙인다. ■ 0행과 실패를 구분한다 구문은 맞는데 조건에 걸리는 데이터가 없을 수 있다. 검증 실행은 치환 변수를 빈 값으로 바꿔 돌리므로(런타임과 같은 방식) 조건이 빡빡하면 0행이 정상이다. 그 경우 표를 감추고 "구문은 정상입니다 — 치환 변수를 빈 값으로 실행하므로 조건에 걸리는 행이 없을 수 있습니다" 를 덧붙인다. 빈 표를 보여 주면 실패한 것처럼 읽힌다. 결과 영역을 190 → 260px 로 키웠다. ■ 이 종류를 다시 놓치지 않도록 --query-popup 진단에 3건을 더 넣었다: 결과 창이 열리는가 · 표에 열이 생기는가 · 행이 채워지는가. 요약만 검사했다면 이번 결함을 그대로 통과시켰을 것이다. 현재 12/12. --dialog-shots 에도 검증 실행을 마친 상태(03b-query-trial)를 추가해 눈으로도 남는다. 회귀: 테스트 230/230, 편집 스모크 실패 0, 팝업·정렬·결과표 점검 12/12, 검증 실행 점검 10/10, DB 왕복 1,271건 diff 0/예외 0, 종이 렌더 P062 바이트 동일. Co-Authored-By: Claude Opus 5 --- src/SheetMe.Designer/Diagnostics/DbSmoke.cs | 14 ++++++ .../Diagnostics/DialogShots.cs | 14 ++++++ .../Views/QueryEditorWindow.xaml | 4 +- .../Views/QueryEditorWindow.xaml.cs | 50 ++++++++++++------- 4 files changed, 63 insertions(+), 19 deletions(-) diff --git a/src/SheetMe.Designer/Diagnostics/DbSmoke.cs b/src/SheetMe.Designer/Diagnostics/DbSmoke.cs index 01db52c..042a465 100644 --- a/src/SheetMe.Designer/Diagnostics/DbSmoke.cs +++ b/src/SheetMe.Designer/Diagnostics/DbSmoke.cs @@ -730,6 +730,20 @@ public static class DbSmoke !lastCharRect.IsEmpty && !caretRect.IsEmpty && caretRect.X >= lastCharRect.X, $"글자 {lastCharRect.X:F1} / 캐럿 {caretRect.X:F1}"); + // ⑨ 검증 실행 결과가 표로 실제로 채워지는가. + // 요약만 보고 넘어가면 '컬럼 2개, 표본 3행'이라 적혀 있는데 표는 비어 있는 상태를 놓친다 + // (ExpandoObject 를 넘기면 DataGrid 가 열을 못 만든다). + var grid = (System.Windows.Controls.DataGrid)window.FindName("TrialGrid")!; + var pane = (System.Windows.FrameworkElement)window.FindName("TrialPane")!; + Type("SELECT ShtCod, ShtKorNam FROM E_ShtMst WHERE ROWNUM <= 3"); + window.RunTrialForSmoke(); + DrainDispatcher(); + grid.UpdateLayout(); + + Check("검증 결과 창이 열린다", pane.Visibility == System.Windows.Visibility.Visible); + Check("결과 표에 열이 생긴다", grid.Columns.Count >= 2, $"열 {grid.Columns.Count}개"); + Check("결과 표에 행이 채워진다", grid.Items.Count >= 1, $"행 {grid.Items.Count}개"); + window.Close(); DrainDispatcher(); } diff --git a/src/SheetMe.Designer/Diagnostics/DialogShots.cs b/src/SheetMe.Designer/Diagnostics/DialogShots.cs index a679aed..6f4b2fa 100644 --- a/src/SheetMe.Designer/Diagnostics/DialogShots.cs +++ b/src/SheetMe.Designer/Diagnostics/DialogShots.cs @@ -115,6 +115,7 @@ public static class DialogShots ("02-sheet-history", () => new Views.SheetHistoryDialogView("S999", "표본 서식", SampleVersions())), ("03-query-editor", () => NewQueryEditor(designer, "SELECT ChtNum, PatNam FROM P_PatMst\nWHERE ChtNum = <>")), + ("03b-query-trial", () => NewQueryEditorWithTrial(designer)), // 실제 카탈로그(384종)와 실제 제안 순위로 찍는다 — 표본 몇 개로는 분류·건수가 안 보인다 ("04-tag-picker", () => new Views.TagPickerDialogView( "데이터 태그 선택 — 자동 채움 원천(bzDataInterface)", @@ -315,6 +316,19 @@ public static class DialogShots private static Window NewQueryEditor(DesignerViewModel designer, string sql) => new Views.QueryEditorWindow("데이터소스", sql, controlNames: designer.ControlNames()); + /// + /// 검증 실행까지 마친 상태 — 결과 표가 실제로 채워지는지 눈으로 확인할 유일한 경로다. + /// DB 가 없으면 실패 메시지가 찍히고, 그것도 봐야 하는 화면이다. + /// + private static Window NewQueryEditorWithTrial(DesignerViewModel designer) + { + var window = new Views.QueryEditorWindow("데이터소스", + "SELECT ShtCod, ShtKorNam, ShtTyp FROM E_ShtMst WHERE ROWNUM <= 5", + controlNames: designer.ControlNames()); + window.RunTrialForSmoke(); + return window; + } + private static DesignerViewModel SampleDesigner() { var document = new FormDocument { FormId = "S999", Title = "표본 서식" }; diff --git a/src/SheetMe.Designer/Views/QueryEditorWindow.xaml b/src/SheetMe.Designer/Views/QueryEditorWindow.xaml index 13e279e..de1368e 100644 --- a/src/SheetMe.Designer/Views/QueryEditorWindow.xaml +++ b/src/SheetMe.Designer/Views/QueryEditorWindow.xaml @@ -154,7 +154,7 @@ @@ -163,7 +163,7 @@ diff --git a/src/SheetMe.Designer/Views/QueryEditorWindow.xaml.cs b/src/SheetMe.Designer/Views/QueryEditorWindow.xaml.cs index 3fbd473..856372e 100644 --- a/src/SheetMe.Designer/Views/QueryEditorWindow.xaml.cs +++ b/src/SheetMe.Designer/Views/QueryEditorWindow.xaml.cs @@ -144,6 +144,9 @@ public partial class QueryEditorWindow : Window /// internal void RefreshCompletionForSmoke() => UpdateCompletion(); + /// 진단(--query-popup)에서 검증 실행을 부르는 통로 — 결과 표가 실제로 차는지 본다 + internal void RunTrialForSmoke() => OnTrial(this, new RoutedEventArgs()); + /// 커서 위치를 보고 목록을 띄우거나 닫는다 private void UpdateCompletion() { @@ -399,9 +402,13 @@ public partial class QueryEditorWindow : Window if (result.Ok) { TrialSummary.Foreground = (System.Windows.Media.Brush)FindResource("B.Ink"); - TrialSummary.Text = result.Summary; + // 행이 0인 것과 실패는 다르다 — 구문은 맞는데 조건에 걸리는 데이터가 없을 뿐이다. + // 치환 변수를 빈 값으로 바꿔 실행하므로 조건이 빡빡하면 0행이 정상이다. + TrialSummary.Text = result.Rows.Count == 0 + ? result.Summary + " — 구문은 정상입니다. 치환 변수를 빈 값으로 실행하므로 조건에 걸리는 행이 없을 수 있습니다." + : result.Summary; TrialGrid.ItemsSource = ToGridRows(result); - TrialGrid.Visibility = Visibility.Visible; + TrialGrid.Visibility = result.Rows.Count > 0 ? Visibility.Visible : Visibility.Collapsed; } else { @@ -412,27 +419,36 @@ public partial class QueryEditorWindow : Window } } - /// DataGrid 는 속성으로 열을 만든다 — 컬럼명이 동적이라 사전 행으로 넘긴다 - private static List ToGridRows(SheetMe.Data.Stores.QueryTrialResult result) + /// + /// 결과를 DataGrid 가 열까지 만들어 주는 형태로 옮긴다. + /// + /// ExpandoObject 로는 안 된다. DataGrid 의 AutoGenerateColumns 는 항목 타입의 + /// 속성을 반사해 열을 만드는데 ExpandoObject 에는 그런 속성이 없다 — + /// 그래서 요약만 뜨고 표는 비어 보였다. DataTable 은 DataGrid 가 직접 알아본다. + /// + private static System.Data.DataView ToGridRows(SheetMe.Data.Stores.QueryTrialResult result) { - var rows = new List(); + var table = new System.Data.DataTable(); + for (var i = 0; i < result.Columns.Count; i++) + { + // 같은 이름이 두 번 나오면 DataTable 이 예외를 낸다(별칭 없는 조인에서 흔하다) + var name = result.Columns[i]; + if (table.Columns.Contains(name)) + { + name = $"{name}_{i}"; + } + table.Columns.Add(name, typeof(string)); + } foreach (var values in result.Rows) { - var row = new System.Dynamic.ExpandoObject(); - var bag = (IDictionary)row; - for (var i = 0; i < result.Columns.Count && i < values.Length; i++) + var row = table.NewRow(); + for (var i = 0; i < table.Columns.Count && i < values.Length; i++) { - // 같은 이름이 두 번 나오면 DataGrid 가 열을 하나만 만든다 — 뒤에 번호를 붙인다 - var name = result.Columns[i]; - if (bag.ContainsKey(name)) - { - name += "_" + i; - } - bag[name] = values[i]; + row[i] = values[i]; } - rows.Add(row); + table.Rows.Add(row); } - return rows; + return table.DefaultView; } private void OnCloseTrial(object sender, RoutedEventArgs e) => TrialPane.Visibility = Visibility.Collapsed;