검증 실행 결과에 출력 행이 안 보이던 문제

결과를 ExpandoObject 목록으로 DataGrid 에 넘기고 있었다. DataGrid 의 AutoGenerateColumns 는
항목 <b>타입</b>의 속성을 반사해 열을 만드는데 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 <noreply@anthropic.com>
This commit is contained in:
Msystech
2026-08-13 16:10:27 +09:00
co-authored by Claude Opus 5
parent 3e26af8739
commit f447ae742b
4 changed files with 63 additions and 19 deletions
@@ -144,6 +144,9 @@ public partial class QueryEditorWindow : Window
/// </summary>
internal void RefreshCompletionForSmoke() => UpdateCompletion();
/// <summary>진단(--query-popup)에서 검증 실행을 부르는 통로 — 결과 표가 실제로 차는지 본다</summary>
internal void RunTrialForSmoke() => OnTrial(this, new RoutedEventArgs());
/// <summary>커서 위치를 보고 목록을 띄우거나 닫는다</summary>
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
}
}
/// <summary>DataGrid 는 속성으로 열을 만든다 — 컬럼명이 동적이라 사전 행으로 넘긴다</summary>
private static List<System.Dynamic.ExpandoObject> ToGridRows(SheetMe.Data.Stores.QueryTrialResult result)
/// <summary>
/// 결과를 DataGrid 가 열까지 만들어 주는 형태로 옮긴다.
///
/// <b>ExpandoObject 로는 안 된다.</b> DataGrid 의 AutoGenerateColumns 는 항목 <i>타입</i>의
/// 속성을 반사해 열을 만드는데 ExpandoObject 에는 그런 속성이 없다 —
/// 그래서 요약만 뜨고 표는 비어 보였다. DataTable 은 DataGrid 가 직접 알아본다.
/// </summary>
private static System.Data.DataView ToGridRows(SheetMe.Data.Stores.QueryTrialResult result)
{
var rows = new List<System.Dynamic.ExpandoObject>();
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<string, object?>)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;