Deadman922 commited on
Commit
1d259db
Β·
verified Β·
1 Parent(s): f7dc553

Upload 15 files

Browse files
server/environment.py CHANGED
@@ -623,6 +623,9 @@ def analyze_uploaded_database(conn: sqlite3.Connection, schema_info: dict[str, d
623
  ratio = profile["date_ratio"]
624
  if not family:
625
  continue
 
 
 
626
  score = ratio
627
  if family in {"numeric", "score_scale"}:
628
  score += 0.15
 
623
  ratio = profile["date_ratio"]
624
  if not family:
625
  continue
626
+ if family == "date" and ratio >= 0.98:
627
+ # Fully parseable date-like text does not need repair unless another anomaly exists.
628
+ continue
629
  score = ratio
630
  if family in {"numeric", "score_scale"}:
631
  score += 0.15
server/graders.py CHANGED
@@ -246,13 +246,20 @@ def _evaluate_fix_outcome(
246
  original_rows = ground_truth.get("original_row_count", total_after)
247
  preservation = min(1.0, total_after / max(1, original_rows))
248
  improvement = max(0.0, parse_ratio - baseline_ratio)
 
249
  desired_types = {
250
  "boolean": {"BOOLEAN", "INTEGER", "NUMERIC"},
251
  "date": {"DATE", "DATETIME", "TIMESTAMP", "TEXT"},
252
  "numeric": {"REAL", "INTEGER", "NUMERIC", "FLOAT", "DOUBLE"},
253
  }
254
  type_fixed = current_declared in desired_types.get(issue_type, {"TEXT"}) and current_declared != original_declared
255
- issue_resolved = (parse_ratio >= 0.95 and type_fixed) or improvement >= 0.20
 
 
 
 
 
 
256
  final_preservation = min(1.0, (preservation * 0.55) + (min(1.0, parse_ratio) * 0.45))
257
  return issue_resolved, round(final_preservation, 4), True
258
  try:
 
246
  original_rows = ground_truth.get("original_row_count", total_after)
247
  preservation = min(1.0, total_after / max(1, original_rows))
248
  improvement = max(0.0, parse_ratio - baseline_ratio)
249
+ baseline_gap = max(0.0, 1.0 - baseline_ratio)
250
  desired_types = {
251
  "boolean": {"BOOLEAN", "INTEGER", "NUMERIC"},
252
  "date": {"DATE", "DATETIME", "TIMESTAMP", "TEXT"},
253
  "numeric": {"REAL", "INTEGER", "NUMERIC", "FLOAT", "DOUBLE"},
254
  }
255
  type_fixed = current_declared in desired_types.get(issue_type, {"TEXT"}) and current_declared != original_declared
256
+ near_clean = parse_ratio >= 0.98
257
+ meaningful_gain = improvement >= max(0.02, baseline_gap * 0.5)
258
+ issue_resolved = (
259
+ (parse_ratio >= 0.95 and type_fixed)
260
+ or meaningful_gain
261
+ or (near_clean and improvement > 0.005)
262
+ )
263
  final_preservation = min(1.0, (preservation * 0.55) + (min(1.0, parse_ratio) * 0.45))
264
  return issue_resolved, round(final_preservation, 4), True
265
  try:
server/main.py CHANGED
@@ -739,6 +739,13 @@ def is_aggregate_like_column_name(column_name: str) -> bool:
739
  return bool(tokens and any(token in aggregate_tokens for token in tokens))
740
 
741
 
 
 
 
 
 
 
 
742
  def get_db_schema(conn: sqlite3.Connection) -> list[dict]:
743
  """Extract schema information from a SQLite connection."""
744
  schema = []
@@ -1700,7 +1707,7 @@ def _generate_local_insights(sql: str, rows: list, columns: list, row_count: int
1700
 
1701
  # Duplicate detection
1702
  for col in columns:
1703
- if is_aggregate_like_column_name(col):
1704
  continue
1705
  values = [str(r.get(col, '')) for r in rows if r.get(col) is not None]
1706
  unique = set(values)
 
739
  return bool(tokens and any(token in aggregate_tokens for token in tokens))
740
 
741
 
742
+ def is_key_like_column_name(column_name: str) -> bool:
743
+ """Heuristic for key-like result columns where duplicate values are suspicious."""
744
+ tokens = [token for token in re.split(r"[^a-z0-9]+", (column_name or "").lower()) if token]
745
+ key_tokens = {"id", "email", "phone", "ssn", "uuid", "employee", "patient"}
746
+ return bool(tokens and any(token in key_tokens for token in tokens))
747
+
748
+
749
  def get_db_schema(conn: sqlite3.Connection) -> list[dict]:
750
  """Extract schema information from a SQLite connection."""
751
  schema = []
 
1707
 
1708
  # Duplicate detection
1709
  for col in columns:
1710
+ if is_aggregate_like_column_name(col) or not is_key_like_column_name(col):
1711
  continue
1712
  values = [str(r.get(col, '')) for r in rows if r.get(col) is not None]
1713
  unique = set(values)
static/index.html CHANGED
@@ -680,6 +680,11 @@
680
  const aggregateTokens = new Set(['avg', 'sum', 'count', 'total', 'min', 'max', 'rank', 'highest', 'lowest']);
681
  return tokens.some(token => aggregateTokens.has(token));
682
  }
 
 
 
 
 
683
 
684
  // ── Toast notification system ──
685
  let toastTimer = null;
@@ -1084,7 +1089,7 @@
1084
 
1085
  // Duplicate detection
1086
  for (const col of columns) {
1087
- if (isAggregateLikeColumn(col)) continue;
1088
  const values = rows.map(r => r[col]).filter(v => v !== null);
1089
  const unique = new Set(values.map(String));
1090
  if (unique.size < values.length * 0.8 && values.length > 5) {
@@ -1133,7 +1138,7 @@
1133
  }
1134
 
1135
  // Check for duplicates
1136
- const suggestionCols = columns.filter(col => !isAggregateLikeColumn(col));
1137
  const allValues = rows.flatMap(r => suggestionCols.map(col => r[col])).filter(v => v !== null);
1138
  const duplicates = allValues.filter((v, i, a) => a.indexOf(v) !== i);
1139
  if (suggestionCols.length > 0 && duplicates.length > rows.length * 0.1) {
 
680
  const aggregateTokens = new Set(['avg', 'sum', 'count', 'total', 'min', 'max', 'rank', 'highest', 'lowest']);
681
  return tokens.some(token => aggregateTokens.has(token));
682
  }
683
+ function isKeyLikeColumn(col) {
684
+ const tokens = String(col || '').toLowerCase().split(/[^a-z0-9]+/).filter(Boolean);
685
+ const keyTokens = new Set(['id', 'email', 'phone', 'ssn', 'uuid', 'employee', 'patient']);
686
+ return tokens.some(token => keyTokens.has(token));
687
+ }
688
 
689
  // ── Toast notification system ──
690
  let toastTimer = null;
 
1089
 
1090
  // Duplicate detection
1091
  for (const col of columns) {
1092
+ if (isAggregateLikeColumn(col) || !isKeyLikeColumn(col)) continue;
1093
  const values = rows.map(r => r[col]).filter(v => v !== null);
1094
  const unique = new Set(values.map(String));
1095
  if (unique.size < values.length * 0.8 && values.length > 5) {
 
1138
  }
1139
 
1140
  // Check for duplicates
1141
+ const suggestionCols = columns.filter(col => !isAggregateLikeColumn(col) && isKeyLikeColumn(col));
1142
  const allValues = rows.flatMap(r => suggestionCols.map(col => r[col])).filter(v => v !== null);
1143
  const duplicates = allValues.filter((v, i, a) => a.indexOf(v) !== i);
1144
  if (suggestionCols.length > 0 && duplicates.length > rows.length * 0.1) {