package stardb import ( "reflect" "testing" ) func TestNewQueryBuilder(t *testing.T) { qb := NewQueryBuilder("users") if qb.table != "users" { t.Errorf("Expected table 'users', got '%s'", qb.table) } if len(qb.columns) != 1 || qb.columns[0] != "*" { t.Errorf("Expected default columns ['*'], got %v", qb.columns) } } func TestQueryBuilder_Select(t *testing.T) { qb := NewQueryBuilder("users").Select("id", "name", "email") expected := []string{"id", "name", "email"} if !reflect.DeepEqual(qb.columns, expected) { t.Errorf("Expected columns %v, got %v", expected, qb.columns) } } func TestQueryBuilder_Where(t *testing.T) { qb := NewQueryBuilder("users"). Where("age > ?", 18). Where("active = ?", true) if len(qb.where) != 2 { t.Errorf("Expected 2 where conditions, got %d", len(qb.where)) } if qb.where[0] != "age > ?" { t.Errorf("Expected first where 'age > ?', got '%s'", qb.where[0]) } if qb.where[1] != "active = ?" { t.Errorf("Expected second where 'active = ?', got '%s'", qb.where[1]) } if len(qb.whereArgs) != 2 { t.Errorf("Expected 2 where args, got %d", len(qb.whereArgs)) } if qb.whereArgs[0] != 18 { t.Errorf("Expected first arg 18, got %v", qb.whereArgs[0]) } if qb.whereArgs[1] != true { t.Errorf("Expected second arg true, got %v", qb.whereArgs[1]) } } func TestQueryBuilder_OrderBy(t *testing.T) { qb := NewQueryBuilder("users").OrderBy("name ASC") if qb.orderBy != "name ASC" { t.Errorf("Expected orderBy 'name ASC', got '%s'", qb.orderBy) } } func TestQueryBuilder_Limit(t *testing.T) { qb := NewQueryBuilder("users").Limit(10) if qb.limit != 10 { t.Errorf("Expected limit 10, got %d", qb.limit) } } func TestQueryBuilder_Offset(t *testing.T) { qb := NewQueryBuilder("users").Offset(20) if qb.offset != 20 { t.Errorf("Expected offset 20, got %d", qb.offset) } } func TestQueryBuilder_Build_Simple(t *testing.T) { qb := NewQueryBuilder("users") query, args := qb.Build() expectedQuery := "SELECT * FROM users" if query != expectedQuery { t.Errorf("Expected query '%s', got '%s'", expectedQuery, query) } if len(args) != 0 { t.Errorf("Expected 0 args, got %d", len(args)) } } func TestQueryBuilder_Build_WithSelect(t *testing.T) { qb := NewQueryBuilder("users").Select("id", "name", "email") query, args := qb.Build() expectedQuery := "SELECT id, name, email FROM users" if query != expectedQuery { t.Errorf("Expected query '%s', got '%s'", expectedQuery, query) } if len(args) != 0 { t.Errorf("Expected 0 args, got %d", len(args)) } } func TestQueryBuilder_Build_WithWhere(t *testing.T) { qb := NewQueryBuilder("users"). Where("age > ?", 18). Where("active = ?", true) query, args := qb.Build() expectedQuery := "SELECT * FROM users WHERE age > ? AND active = ?" if query != expectedQuery { t.Errorf("Expected query '%s', got '%s'", expectedQuery, query) } if len(args) != 2 { t.Errorf("Expected 2 args, got %d", len(args)) } if args[0] != 18 { t.Errorf("Expected first arg 18, got %v", args[0]) } if args[1] != true { t.Errorf("Expected second arg true, got %v", args[1]) } } func TestQueryBuilder_Build_WithOrderBy(t *testing.T) { qb := NewQueryBuilder("users").OrderBy("created_at DESC") query, args := qb.Build() expectedQuery := "SELECT * FROM users ORDER BY created_at DESC" if query != expectedQuery { t.Errorf("Expected query '%s', got '%s'", expectedQuery, query) } if len(args) != 0 { t.Errorf("Expected 0 args, got %d", len(args)) } } func TestQueryBuilder_Build_WithLimit(t *testing.T) { qb := NewQueryBuilder("users").Limit(10) query, args := qb.Build() expectedQuery := "SELECT * FROM users LIMIT 10" if query != expectedQuery { t.Errorf("Expected query '%s', got '%s'", expectedQuery, query) } if len(args) != 0 { t.Errorf("Expected 0 args, got %d", len(args)) } } func TestQueryBuilder_Build_WithOffset(t *testing.T) { qb := NewQueryBuilder("users").Offset(20) query, args := qb.Build() expectedQuery := "SELECT * FROM users OFFSET 20" if query != expectedQuery { t.Errorf("Expected query '%s', got '%s'", expectedQuery, query) } if len(args) != 0 { t.Errorf("Expected 0 args, got %d", len(args)) } } func TestQueryBuilder_Build_WithLimitAndOffset(t *testing.T) { qb := NewQueryBuilder("users").Limit(10).Offset(20) query, args := qb.Build() expectedQuery := "SELECT * FROM users LIMIT 10 OFFSET 20" if query != expectedQuery { t.Errorf("Expected query '%s', got '%s'", expectedQuery, query) } if len(args) != 0 { t.Errorf("Expected 0 args, got %d", len(args)) } } func TestQueryBuilder_Build_Complex(t *testing.T) { qb := NewQueryBuilder("users"). Select("id", "name", "email", "age"). Where("age > ?", 18). Where("active = ?", true). Where("country = ?", "US"). OrderBy("name ASC"). Limit(10). Offset(20) query, args := qb.Build() expectedQuery := "SELECT id, name, email, age FROM users WHERE age > ? AND active = ? AND country = ? ORDER BY name ASC LIMIT 10 OFFSET 20" if query != expectedQuery { t.Errorf("Expected query:\n%s\nGot:\n%s", expectedQuery, query) } expectedArgs := []interface{}{18, true, "US"} if len(args) != len(expectedArgs) { t.Errorf("Expected %d args, got %d", len(expectedArgs), len(args)) } for i, expected := range expectedArgs { if args[i] != expected { t.Errorf("Expected arg[%d] = %v, got %v", i, expected, args[i]) } } } func TestQueryBuilder_Build_MultipleWhere(t *testing.T) { qb := NewQueryBuilder("orders"). Where("user_id = ?", 123). Where("status IN (?, ?, ?)", "pending", "processing", "shipped"). Where("created_at > ?", "2024-01-01") query, args := qb.Build() expectedQuery := "SELECT * FROM orders WHERE user_id = ? AND status IN (?, ?, ?) AND created_at > ?" if query != expectedQuery { t.Errorf("Expected query:\n%s\nGot:\n%s", expectedQuery, query) } if len(args) != 5 { t.Errorf("Expected 5 args, got %d", len(args)) } expectedArgs := []interface{}{123, "pending", "processing", "shipped", "2024-01-01"} for i, expected := range expectedArgs { if args[i] != expected { t.Errorf("Expected arg[%d] = %v, got %v", i, expected, args[i]) } } } func TestQueryBuilder_Chaining(t *testing.T) { // Test method chaining returns the same builder qb := NewQueryBuilder("users") qb2 := qb.Select("id", "name") if qb != qb2 { t.Error("Select should return the same builder instance") } qb3 := qb.Where("age > ?", 18) if qb != qb3 { t.Error("Where should return the same builder instance") } qb4 := qb.OrderBy("name ASC") if qb != qb4 { t.Error("OrderBy should return the same builder instance") } qb5 := qb.Limit(10) if qb != qb5 { t.Error("Limit should return the same builder instance") } qb6 := qb.Offset(20) if qb != qb6 { t.Error("Offset should return the same builder instance") } } func TestQueryBuilder_EmptyWhere(t *testing.T) { qb := NewQueryBuilder("users").Select("id", "name") query, args := qb.Build() expectedQuery := "SELECT id, name FROM users" if query != expectedQuery { t.Errorf("Expected query '%s', got '%s'", expectedQuery, query) } if len(args) != 0 { t.Errorf("Expected 0 args, got %d", len(args)) } } func TestQueryBuilder_OnlyLimit(t *testing.T) { qb := NewQueryBuilder("users").Limit(5) query, args := qb.Build() expectedQuery := "SELECT * FROM users LIMIT 5" if query != expectedQuery { t.Errorf("Expected query '%s', got '%s'", expectedQuery, query) } if len(args) != 0 { t.Errorf("Expected 0 args, got %d", len(args)) } } func TestQueryBuilder_OnlyOffset(t *testing.T) { qb := NewQueryBuilder("users").Offset(10) query, args := qb.Build() expectedQuery := "SELECT * FROM users OFFSET 10" if query != expectedQuery { t.Errorf("Expected query '%s', got '%s'", expectedQuery, query) } if len(args) != 0 { t.Errorf("Expected 0 args, got %d", len(args)) } } func TestQueryBuilder_ZeroLimit(t *testing.T) { qb := NewQueryBuilder("users").Limit(0) query, args := qb.Build() // Limit 0 should not be included expectedQuery := "SELECT * FROM users" if query != expectedQuery { t.Errorf("Expected query '%s', got '%s'", expectedQuery, query) } if len(args) != 0 { t.Errorf("Expected 0 args, got %d", len(args)) } } func TestQueryBuilder_ZeroOffset(t *testing.T) { qb := NewQueryBuilder("users").Offset(0) query, args := qb.Build() // Offset 0 should not be included expectedQuery := "SELECT * FROM users" if query != expectedQuery { t.Errorf("Expected query '%s', got '%s'", expectedQuery, query) } if len(args) != 0 { t.Errorf("Expected 0 args, got %d", len(args)) } } func TestQueryBuilder_MultipleSelect(t *testing.T) { // Last Select should override previous ones qb := NewQueryBuilder("users"). Select("id", "name"). Select("email", "age") query, _ := qb.Build() expectedQuery := "SELECT email, age FROM users" if query != expectedQuery { t.Errorf("Expected query '%s', got '%s'", expectedQuery, query) } } func TestQueryBuilder_MultipleOrderBy(t *testing.T) { // Last OrderBy should override previous ones qb := NewQueryBuilder("users"). OrderBy("name ASC"). OrderBy("created_at DESC") query, _ := qb.Build() expectedQuery := "SELECT * FROM users ORDER BY created_at DESC" if query != expectedQuery { t.Errorf("Expected query '%s', got '%s'", expectedQuery, query) } } func TestQueryBuilder_ComplexWhereConditions(t *testing.T) { qb := NewQueryBuilder("products"). Select("id", "name", "price"). Where("category_id = ?", 5). Where("price BETWEEN ? AND ?", 10.0, 100.0). Where("stock > ?", 0). Where("name LIKE ?", "%phone%"). OrderBy("price DESC"). Limit(20) query, args := qb.Build() expectedQuery := "SELECT id, name, price FROM products WHERE category_id = ? AND price BETWEEN ? AND ? AND stock > ? AND name LIKE ? ORDER BY price DESC LIMIT 20" if query != expectedQuery { t.Errorf("Expected query:\n%s\nGot:\n%s", expectedQuery, query) } expectedArgs := []interface{}{5, 10.0, 100.0, 0, "%phone%"} if len(args) != len(expectedArgs) { t.Errorf("Expected %d args, got %d", len(expectedArgs), len(args)) } for i, expected := range expectedArgs { if args[i] != expected { t.Errorf("Expected arg[%d] = %v, got %v", i, expected, args[i]) } } } func TestQueryBuilder_SingleColumn(t *testing.T) { qb := NewQueryBuilder("users").Select("COUNT(*)") query, args := qb.Build() expectedQuery := "SELECT COUNT(*) FROM users" if query != expectedQuery { t.Errorf("Expected query '%s', got '%s'", expectedQuery, query) } if len(args) != 0 { t.Errorf("Expected 0 args, got %d", len(args)) } } func TestQueryBuilder_JoinLikeWhere(t *testing.T) { // Test that WHERE can handle JOIN-like conditions qb := NewQueryBuilder("users"). Select("users.id", "users.name", "orders.total"). Where("users.id = orders.user_id"). Where("orders.status = ?", "completed") query, args := qb.Build() expectedQuery := "SELECT users.id, users.name, orders.total FROM users WHERE users.id = orders.user_id AND orders.status = ?" if query != expectedQuery { t.Errorf("Expected query:\n%s\nGot:\n%s", expectedQuery, query) } if len(args) != 1 { t.Errorf("Expected 1 arg, got %d", len(args)) } if args[0] != "completed" { t.Errorf("Expected arg 'completed', got %v", args[0]) } } // Benchmark tests func BenchmarkQueryBuilder_Simple(b *testing.B) { for i := 0; i < b.N; i++ { qb := NewQueryBuilder("users") qb.Build() } } func BenchmarkQueryBuilder_Complex(b *testing.B) { for i := 0; i < b.N; i++ { qb := NewQueryBuilder("users"). Select("id", "name", "email", "age"). Where("age > ?", 18). Where("active = ?", true). Where("country = ?", "US"). OrderBy("name ASC"). Limit(10). Offset(20) qb.Build() } }