001package gudusoft.gsqlparser.resolver2.inference; 002 003import gudusoft.gsqlparser.nodes.TParseTreeNode; 004 005/** 006 * Represents a piece of evidence for column inference. 007 * 008 * <p>Evidence is collected from various sources in the SQL statement: 009 * - Column references in WHERE clauses 010 * - JOIN conditions 011 * - SELECT list expressions 012 * - INSERT statements (column lists) 013 * - etc. 014 * 015 * <p>Each piece of evidence has a confidence weight that contributes 016 * to the overall inference confidence. 017 * 018 * <p>Example: 019 * <pre> 020 * SELECT t1.* FROM t1 WHERE t1.id = 100 021 * ^^ 022 * Evidence: "id" exists in t1 (from WHERE clause, high confidence) 023 * </pre> 024 */ 025public class InferenceEvidence { 026 027 /** The inferred column name */ 028 private final String columnName; 029 030 /** The table name this evidence relates to */ 031 private final String tableName; 032 033 /** Type of evidence */ 034 private final EvidenceType evidenceType; 035 036 /** Confidence weight [0.0, 1.0] */ 037 private final double confidence; 038 039 /** Source AST node that provides this evidence */ 040 private final TParseTreeNode sourceNode; 041 042 /** Description of how this evidence was obtained */ 043 private final String description; 044 045 public InferenceEvidence( 046 String columnName, 047 String tableName, 048 EvidenceType evidenceType, 049 double confidence, 050 TParseTreeNode sourceNode, 051 String description) { 052 this.columnName = columnName; 053 this.tableName = tableName; 054 this.evidenceType = evidenceType; 055 this.confidence = Math.max(0.0, Math.min(1.0, confidence)); 056 this.sourceNode = sourceNode; 057 this.description = description; 058 } 059 060 public String getColumnName() { 061 return columnName; 062 } 063 064 public String getTableName() { 065 return tableName; 066 } 067 068 public EvidenceType getEvidenceType() { 069 return evidenceType; 070 } 071 072 public double getConfidence() { 073 return confidence; 074 } 075 076 public TParseTreeNode getSourceNode() { 077 return sourceNode; 078 } 079 080 public String getDescription() { 081 return description; 082 } 083 084 /** 085 * Create evidence from a qualified column reference. 086 * Example: WHERE t1.id = 100 087 */ 088 public static InferenceEvidence fromQualifiedReference( 089 String columnName, 090 String tableName, 091 TParseTreeNode sourceNode) { 092 return new InferenceEvidence( 093 columnName, 094 tableName, 095 EvidenceType.QUALIFIED_REFERENCE, 096 0.95, // High confidence - explicit table reference 097 sourceNode, 098 "Qualified column reference: " + tableName + "." + columnName 099 ); 100 } 101 102 /** 103 * Create evidence from an unqualified column reference. 104 * Example: WHERE id = 100 (when only one table in scope) 105 */ 106 public static InferenceEvidence fromUnqualifiedReference( 107 String columnName, 108 String tableName, 109 TParseTreeNode sourceNode, 110 int tableCount) { 111 double confidence = tableCount == 1 ? 0.8 : 0.5; // Lower if ambiguous 112 return new InferenceEvidence( 113 columnName, 114 tableName, 115 EvidenceType.UNQUALIFIED_REFERENCE, 116 confidence, 117 sourceNode, 118 "Unqualified column reference: " + columnName + " (tables in scope: " + tableCount + ")" 119 ); 120 } 121 122 /** 123 * Create evidence from a JOIN condition. 124 * Example: JOIN t2 ON t1.id = t2.t1_id 125 */ 126 public static InferenceEvidence fromJoinCondition( 127 String columnName, 128 String tableName, 129 TParseTreeNode sourceNode) { 130 return new InferenceEvidence( 131 columnName, 132 tableName, 133 EvidenceType.JOIN_CONDITION, 134 0.9, // Very high confidence - explicit relationship 135 sourceNode, 136 "JOIN condition: " + tableName + "." + columnName 137 ); 138 } 139 140 /** 141 * Create evidence from SELECT list. 142 * Example: SELECT t1.name, t1.age FROM t1 143 */ 144 public static InferenceEvidence fromSelectList( 145 String columnName, 146 String tableName, 147 TParseTreeNode sourceNode) { 148 return new InferenceEvidence( 149 columnName, 150 tableName, 151 EvidenceType.SELECT_LIST, 152 0.85, 153 sourceNode, 154 "SELECT list column: " + tableName + "." + columnName 155 ); 156 } 157 158 /** 159 * Create evidence from INSERT statement column list. 160 * Example: INSERT INTO t1 (id, name) VALUES (...) 161 */ 162 public static InferenceEvidence fromInsertColumns( 163 String columnName, 164 String tableName, 165 TParseTreeNode sourceNode) { 166 return new InferenceEvidence( 167 columnName, 168 tableName, 169 EvidenceType.INSERT_COLUMN_LIST, 170 1.0, // Perfect confidence - explicit column definition 171 sourceNode, 172 "INSERT column list: " + columnName 173 ); 174 } 175 176 /** 177 * Create evidence from UPDATE statement. 178 * Example: UPDATE t1 SET name = 'value' 179 */ 180 public static InferenceEvidence fromUpdateSet( 181 String columnName, 182 String tableName, 183 TParseTreeNode sourceNode) { 184 return new InferenceEvidence( 185 columnName, 186 tableName, 187 EvidenceType.UPDATE_SET, 188 0.95, 189 sourceNode, 190 "UPDATE SET: " + columnName 191 ); 192 } 193 194 @Override 195 public String toString() { 196 return String.format("Evidence[%s.%s, type=%s, conf=%.2f]", 197 tableName, columnName, evidenceType, confidence); 198 } 199 200 @Override 201 public boolean equals(Object obj) { 202 if (this == obj) return true; 203 if (!(obj instanceof InferenceEvidence)) return false; 204 InferenceEvidence other = (InferenceEvidence) obj; 205 return columnName.equals(other.columnName) && 206 tableName.equals(other.tableName) && 207 evidenceType == other.evidenceType; 208 } 209 210 @Override 211 public int hashCode() { 212 int result = columnName.hashCode(); 213 result = 31 * result + tableName.hashCode(); 214 result = 31 * result + evidenceType.hashCode(); 215 return result; 216 } 217}