Decimal 값 동등비교 누락 수정 계획 (Enum & Match, GlueSQL #1741)
NOTE
아직 착수 전 — 이번 주 일요일 작업 예정. Claude Code로 PR #2016 리뷰 코멘트를 확인하던 중, 함께 후보를 찾다가 발견한 이슈.
translate.rs가 아닌core/src/executor/evaluate쪽이라 지금까지 작업한 것과 다른 코드 경로를 볼 수 있음 — (Rust) 열거형과 패턴 매칭(Enum & Match) - 핵심 개념 및 특징 정리 노트에서 배운 걸 실제 코드에서 확인하기 좋은 크기.
📌 개념
문제 — Decimal과 숫자 리터럴을 비교하면 항상 false
CREATE TABLE T (d DECIMAL);
INSERT INTO T VALUES (3.14);
SELECT * FROM T WHERE d = 3.14;지금은 0 rows가 나옴 (원래는 1 row). Decimal 타입 컬럼을 리터럴 숫자와 =로 비교하는 모든 경우가 항상 거짓으로 평가됨.
원인 — value_eq_with_literal에 Value::Decimal 매치 암이 없음
core/src/executor/evaluate/evaluated/eq.rs의 value_eq_with_literal 함수(현재 153~190행 근처)가 Value와 Evaluated::Number(리터럴 숫자)를 매칭하는 곳인데, I8/I16/…/F64/Inet까지는 각각 매치 암이 있지만 Decimal만 빠져 있음 → _ => Tribool::from(false)로 폴백.
같은 파일 옆 cmp.rs(비교 연산자 </> 등을 담당)에는 이미 Decimal 처리가 있어서 =만 깨지고 </>는 정상 동작하는 비대칭 상태:
// core/src/executor/evaluate/evaluated/cmp.rs:69-70 (이미 있음, 참고용)
Value::Decimal(l) => {
BigDecimal::new(l.mantissa().into(), i64::from(l.scale())).partial_cmp(number)
}고쳐야 하는 pseudocode
// core/src/executor/evaluate/evaluated/eq.rs
// 1) 파일 상단 use에 BigDecimal 추가 (cmp.rs와 동일하게)
use bigdecimal::BigDecimal;
// 2) value_eq_with_literal의 match 안, 다른 Value::* 암들 사이에 추가
(Value::Decimal(l), Evaluated::Number(r)) => {
let l = BigDecimal::new(l.mantissa().into(), i64::from(l.scale()));
Tribool::from(l == *r)
}r은&BigDecimal이므로*r로 역참조 후 비교 (또는l == r.clone()이 아니라&l == r형태로 맞춰도 됨 — 실제 작성 시cmp.rs의partial_cmp(number)호출부와 타입을 맞춰서 컴파일 에러 보고 조정)eq()는 이미Evaluated::Number,Evaluated::Value(_)양쪽 순서를 최상위evaluate_eq에서 대칭으로 처리하고 있어서((a, Value) | (Value, a)패턴),value_eq_with_literal한 곳만 고치면3.14 = d,d = 3.14양방향 다 해결됨
테스트 방법
eq.rs맨 아래#[cfg(test)] mod tests에 이미value_eq_with_literal_matches_previous_behavior테스트가 있음 — 여기에 케이스 추가:assert_eq!( True, value_eq_with_literal(&Value::Decimal(Decimal::new(314, 2)), &num!("3.14")) ); // 스케일이 다른 경우도 확인 (3.00 vs 3) assert_eq!( True, value_eq_with_literal(&Value::Decimal(Decimal::new(300, 2)), &num!("3")) );cargo test -p gluesql-core --lib로 유닛 테스트 확인- SQL 레벨 회귀도 하나 추가 고려:
test-suite/fixtures/안에 decimal 관련 fixture가 있으면 거기에WHERE d = 3.14케이스 추가 (없으면pkg/rust/tests쪽에 작은 통합 테스트로 대체 가능 — 일요일에 fixture 유무부터 확인) - 마무리로
cargo clippy -p gluesql-core --all-targets -- -D warnings,cargo fmt --all
배울 Rust 개념
- 열거형과 패턴 매칭:
Value/Evaluated처럼 variant가 많은 enum에서match암이 하나 빠지면 컴파일러가 못 잡아주는 경우(와일드카드_폴백이 있을 때) vs 잡아주는 경우(와일드카드 없을 때)의 차이를 실제 코드로 체감 - 튜플 패턴 매칭
(Value::Decimal(l), Evaluated::Number(r))— 두 enum을 동시에 구조 분해
🔗 참고
- GlueSQL Issue #1741 — Missing Decimal equality with Literal::Number in evaluate_eq_with_literal
- 관련 코드:
core/src/executor/evaluate/evaluated/eq.rs,core/src/executor/evaluate/evaluated/cmp.rs(참고용 대칭 구현)
관련 문서
- (Rust) GlueSQL 프로젝트 구조와 필요 문법 개관 - 핵심 개념 및 특징 정리
- (Rust) 오픈소스 컨트리뷰션 실전 가이드(이슈 찾기부터 PR 작성까지, GlueSQL 사례) - 핵심 개념 및 특징 정리
- (Rust) 열거형과 패턴 매칭(Enum & Match) - 핵심 개념 및 특징 정리 — 이번 수정에 필요한 핵심 문법
-
- [Rust] Option
TryFrom 매크로 확장 계획(GlueSQL #1389) — 같은 날 후보로 같이 찾은 이슈
- [Rust] Option
-
- [Rust] Glue::execute 배치 planning 수정 계획(GlueSQL #2009) — 같은 날 후보로 같이 찾은 이슈