Browse Source

99.9% sqllogictest

Danilo Fragoso 4 months ago
parent
commit
e368dd2868
7 changed files with 813 additions and 112 deletions
  1. BIN
      bin/pizzasql
  2. BIN
      bin/sqllogictest
  3. 1 1
      cmd/sqllogictest/main.go
  4. 1 1
      main.go
  5. 669 104
      pkg/executor/executor.go
  6. 51 0
      pkg/executor/executor_join_test.go
  7. 91 6
      pkg/executor/executor_test.go

BIN
bin/pizzasql


BIN
bin/sqllogictest


+ 1 - 1
cmd/sqllogictest/main.go

@@ -485,7 +485,7 @@ func formatValue(v interface{}, colType byte) string {
 	case 'I':
 		switch n := v.(type) {
 		case float64:
-			return strconv.FormatInt(int64(math.Round(n)), 10)
+			return strconv.FormatInt(int64(n), 10)
 		case int64:
 			return strconv.FormatInt(n, 10)
 		case int:

+ 1 - 1
main.go

@@ -838,7 +838,7 @@ func launchPizzaKV() error {
 
 	fmt.Printf("\nPizzaKV started on %s (PID: %d)\n", info.Addr, info.PID)
 	fmt.Printf("Info written to: %s\n", *kvInfoFile)
-	fmt.Println("PizzaKV is ready!\n")
+	fmt.Println("PizzaKV is ready!")
 
 	// Update kvAddr to use the launched instance
 	*kvAddr = info.Addr

File diff suppressed because it is too large
+ 669 - 104
pkg/executor/executor.go


+ 51 - 0
pkg/executor/executor_join_test.go

@@ -80,3 +80,54 @@ func TestJoinConditionWithQualifiedNames(t *testing.T) {
 		t.Log("✓ JOIN condition can correctly compare o.id with om.org_id")
 	}
 }
+
+func TestLeftJoinWithNullConditions(t *testing.T) {
+	e := &Executor{}
+
+	// Create test rows
+	leftRows := []storage.Row{
+		{"col1": int64(1), "col2": "a"},
+		{"col1": int64(2), "col2": "b"},
+	}
+
+	// Test merging left row with null right row
+	left := leftRows[0]
+	nullRight := storage.Row{
+		"col3": nil,
+		"col4": nil,
+	}
+
+	merged := e.mergeRows(left, nullRight, "cor0", "cor1")
+
+	// Verify left columns are preserved
+	if merged["cor0.col1"] != int64(1) {
+		t.Errorf("Expected cor0.col1 = 1, got %v", merged["cor0.col1"])
+	}
+	if merged["cor0.col2"] != "a" {
+		t.Errorf("Expected cor0.col2 = 'a', got %v", merged["cor0.col2"])
+	}
+
+	// Verify right columns are NULL
+	if merged["cor1.col3"] != nil {
+		t.Errorf("Expected cor1.col3 = nil, got %v", merged["cor1.col3"])
+	}
+	if merged["cor1.col4"] != nil {
+		t.Errorf("Expected cor1.col4 = nil, got %v", merged["cor1.col4"])
+	}
+
+	// Verify unqualified columns exist
+	if merged["col1"] != int64(1) {
+		t.Errorf("Expected col1 = 1, got %v", merged["col1"])
+	}
+	if merged["col2"] != "a" {
+		t.Errorf("Expected col2 = 'a', got %v", merged["col2"])
+	}
+	if merged["col3"] != nil {
+		t.Errorf("Expected col3 = nil, got %v", merged["col3"])
+	}
+	if merged["col4"] != nil {
+		t.Errorf("Expected col4 = nil, got %v", merged["col4"])
+	}
+
+	t.Log("✓ LEFT JOIN with NULL conditions creates proper null rows for unmatched right table")
+}

+ 91 - 6
pkg/executor/executor_test.go

@@ -96,7 +96,92 @@ func TestEvalArithmetic(t *testing.T) {
 	}
 }
 
-func TestEvalComparison(t *testing.T) {
+func TestEvalConstantWhereClause(t *testing.T) {
+	// Test constant WHERE clauses that don't reference any columns
+	tests := []struct {
+		name     string
+		expr     string
+		expected bool
+	}{
+		{"NULL IS NULL", "NULL IS NULL", true},
+		{"NULL IS NOT NULL", "NULL IS NOT NULL", false},
+		{"NOT NULL IS NOT NULL", "NOT NULL IS NOT NULL", true},
+		{"79 IS NOT NULL", "79 IS NOT NULL", true},
+		{"79 IS NULL", "79 IS NULL", false},
+		{"+ 79 IS NOT NULL", "+ 79 IS NOT NULL", true},
+		{"- 78 IS NOT NULL", "- 78 IS NOT NULL", true},
+	}
+
+	exec := &Executor{}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			stmt := parse(t, "SELECT 1 WHERE "+tt.expr)
+			sel := stmt.(*parser.SelectStmt)
+			val, err := exec.evalExpr(sel.Where, nil)
+			if err != nil {
+				t.Fatalf("evalExpr error: %v", err)
+			}
+			result := toBool(val)
+			if result != tt.expected {
+				t.Errorf("expected %v, got %v", tt.expected, result)
+			}
+		})
+	}
+}
+
+func TestConstantWhereClauseWithTable(t *testing.T) {
+	// This test requires a real database connection
+	// Skip if not available
+	tests := []struct {
+		name          string
+		whereClause   string
+		expectAllRows bool
+		expectNoRows  bool
+	}{
+		{"WHERE NULL IS NULL", "NULL IS NULL", true, false},
+		{"WHERE NULL IS NOT NULL", "NULL IS NOT NULL", false, true},
+		{"WHERE NOT NULL IS NOT NULL", "NOT NULL IS NOT NULL", true, false},
+		{"WHERE 79 IS NOT NULL", "79 IS NOT NULL", true, false},
+		{"WHERE 79 IS NULL", "79 IS NULL", false, true},
+		{"WHERE + 79 IS NOT NULL", "+ 79 IS NOT NULL", true, false},
+		{"WHERE - 78 IS NOT NULL", "- 78 IS NOT NULL", true, false},
+		{"WHERE 1 = 1", "1 = 1", true, false},
+		{"WHERE 1 = 0", "1 = 0", false, true},
+		{"WHERE TRUE", "TRUE", true, false},
+		{"WHERE FALSE", "FALSE", false, true},
+	}
+
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			// Parse the WHERE clause
+			stmt := parse(t, "SELECT col0 FROM test WHERE "+tt.whereClause)
+			sel := stmt.(*parser.SelectStmt)
+
+			// Check that the WHERE clause doesn't reference any columns
+			refs := collectColumnRefs(sel.Where)
+			if len(refs) != 0 {
+				t.Errorf("expected constant WHERE clause (no column refs), got %d refs", len(refs))
+			}
+
+			// Create a minimal executor to test constant evaluation
+			exec := &Executor{}
+			val, err := exec.evalExpr(sel.Where, nil)
+			if err != nil {
+				t.Fatalf("evalExpr error: %v", err)
+			}
+			result := toBool(val)
+
+			if tt.expectAllRows && !result {
+				t.Errorf("expected WHERE to evaluate to TRUE (select all rows), got FALSE")
+			}
+			if tt.expectNoRows && result {
+				t.Errorf("expected WHERE to evaluate to FALSE (select no rows), got TRUE")
+			}
+		})
+	}
+}
+
+func TestComparison(t *testing.T) {
 	exec := &Executor{}
 
 	tests := []struct {
@@ -1374,7 +1459,7 @@ func TestAttachDetach(t *testing.T) {
 func TestDistinct(t *testing.T) {
 	// Simple test without requiring KV connection
 	exec := &Executor{}
-	
+
 	// Test applyDistinct function directly
 	t.Run("ApplyDistinct", func(t *testing.T) {
 		rows := [][]interface{}{
@@ -1384,20 +1469,20 @@ func TestDistinct(t *testing.T) {
 			{"c", 3},
 			{"b", 2}, // duplicate
 		}
-		
+
 		result := exec.applyDistinct(rows)
-		
+
 		if len(result) != 3 {
 			t.Errorf("expected 3 unique rows, got %d", len(result))
 		}
-		
+
 		// Check that we have the expected unique rows
 		expected := map[string]bool{
 			"a\x001": true,
 			"b\x002": true,
 			"c\x003": true,
 		}
-		
+
 		for _, row := range result {
 			key := fmt.Sprintf("%v\x00%v", row[0], row[1])
 			if !expected[key] {

Some files were not shown because too many files changed in this diff