001package gudusoft.gsqlparser.resolver2.model; 002 003/** 004 * A side-channel annotation for deep struct field access (3+ part names without alias). 005 * 006 * <p>Unlike {@link ColumnSource} (which is part of the main resolution result and 007 * triggers sourceTable binding), this hint is purely informational. It provides 008 * struct field path information to downstream consumers (e.g., DataFlowAnalyzer) 009 * without altering the resolution path or lineage topology.</p> 010 * 011 * <p>This solves the problem where 3-part no-alias struct access like 012 * {@code customer.address.city FROM orders} cannot use the main EXACT_MATCH 013 * resolution path because doing so changes sourceTable binding and breaks 014 * existing lineage chains (see plan document Section 10).</p> 015 * 016 * <p>Example:</p> 017 * <pre> 018 * -- SQL: SELECT customer.address.city FROM orders 019 * -- StructFieldHint: 020 * -- baseColumn = "customer" 021 * -- fieldPath = ["address", "city"] 022 * -- evidence = "struct_field_hint_no_alias" 023 * -- confidence = 0.7 024 * </pre> 025 * 026 * @see FieldPath 027 */ 028public class StructFieldHint { 029 030 private final String baseColumn; 031 private final FieldPath fieldPath; 032 private final String evidence; 033 private final double confidence; 034 035 public StructFieldHint(String baseColumn, FieldPath fieldPath, String evidence, double confidence) { 036 this.baseColumn = baseColumn; 037 this.fieldPath = fieldPath; 038 this.evidence = evidence; 039 this.confidence = Math.max(0.0, Math.min(1.0, confidence)); 040 } 041 042 public String getBaseColumn() { 043 return baseColumn; 044 } 045 046 public FieldPath getFieldPath() { 047 return fieldPath; 048 } 049 050 public String getEvidence() { 051 return evidence; 052 } 053 054 public double getConfidence() { 055 return confidence; 056 } 057 058 /** 059 * Get the full dotted reference (e.g., "customer.address.city"). 060 */ 061 public String toFullReference() { 062 if (fieldPath == null || fieldPath.isEmpty()) { 063 return baseColumn != null ? baseColumn : ""; 064 } 065 return fieldPath.toFullReference(baseColumn); 066 } 067 068 @Override 069 public String toString() { 070 return "StructFieldHint{base=" + baseColumn + 071 ", path=" + fieldPath + 072 ", evidence=" + evidence + 073 ", confidence=" + confidence + "}"; 074 } 075}