an ORM-free SQL experience

write tests for scanner

Signed-off-by: oppiliappan <me@oppi.li>

oppi.li fdf9d236 1f0a0426

verified
+55 -181
query_test.go
··· 1 1 package norm 2 2 3 3 import ( 4 - "database/sql" 5 4 "testing" 6 5 "time" 7 6 ··· 91 90 } 92 91 93 92 func TestComplexExpressions(t *testing.T) { 94 - // Test chained logical operations 95 93 age := Eq("age", 25) 96 94 status := Eq("status", "active") 97 95 score := Gt("score", 100) ··· 119 117 } 120 118 121 119 func TestSelectAPI(t *testing.T) { 122 - // Test fluent API chaining 123 120 s := Select("*"). 124 121 From("users"). 125 122 Where(Eq("id", 1)). ··· 163 160 func TestSelectBuild_Success(t *testing.T) { 164 161 tests := []struct { 165 162 name string 166 - builder func() select_ 163 + stmt select_ 167 164 expectedSql string 168 165 expectedArgs []any 169 166 }{ 170 167 { 171 - name: "Simple select", 172 - builder: func() select_ { 173 - return Select("name", "age").From("users") 174 - }, 168 + name: "Simple select", 169 + stmt: Select("name", "age").From("users"), 175 170 expectedSql: "SELECT name, age FROM users", 176 171 expectedArgs: nil, 177 172 }, 178 173 { 179 174 name: "Select with where", 180 - builder: func() select_ { 181 - return Select("*"). 182 - From("users"). 183 - Where(Eq("active", true)) 184 - }, 175 + stmt: Select("*"). 176 + From("users"). 177 + Where(Eq("active", true)), 185 178 expectedSql: "SELECT * FROM users WHERE (active) = (?)", 186 179 expectedArgs: []any{true}, 187 180 }, 188 181 { 189 182 name: "Select with order by", 190 - builder: func() select_ { 191 - return Select("name"). 192 - From("users"). 193 - OrderBy("name", Ascending) 194 - }, 183 + stmt: Select("name"). 184 + From("users"). 185 + OrderBy("name", Ascending), 195 186 expectedSql: "SELECT name FROM users ORDER BY name asc", 196 187 expectedArgs: nil, 197 188 }, 198 189 { 199 190 name: "Select with multiple order by", 200 - builder: func() select_ { 201 - return Select("name", "age"). 202 - From("users"). 203 - OrderBy("name", Ascending). 204 - OrderBy("age", Descending) 205 - }, 191 + stmt: Select("name", "age"). 192 + From("users"). 193 + OrderBy("name", Ascending). 194 + OrderBy("age", Descending), 206 195 expectedSql: "SELECT name, age FROM users ORDER BY name asc, age desc", 207 196 expectedArgs: nil, 208 197 }, 209 198 { 210 199 name: "Select with group by", 211 - builder: func() select_ { 212 - return Select("department", "COUNT(*)"). 213 - From("users"). 214 - GroupBy("department") 215 - }, 200 + stmt: Select("department", "COUNT(*)"). 201 + From("users"). 202 + GroupBy("department"), 216 203 expectedSql: "SELECT department, COUNT(*) FROM users GROUP BY department", 217 204 expectedArgs: nil, 218 205 }, 219 206 { 220 207 name: "Select with limit", 221 - builder: func() select_ { 222 - return Select("*"). 223 - From("users"). 224 - Limit(5) 225 - }, 208 + stmt: Select("*"). 209 + From("users"). 210 + Limit(5), 226 211 expectedSql: "SELECT * FROM users LIMIT 5", 227 212 expectedArgs: nil, 228 213 }, 229 214 { 230 215 name: "Complex select", 231 - builder: func() select_ { 232 - return Select("name", "age", "department"). 233 - From("users"). 234 - Where(Eq("active", true).And(Gt("age", 18))). 235 - GroupBy("department"). 236 - OrderBy("name", Ascending). 237 - Limit(10) 238 - }, 216 + stmt: Select("name", "age", "department"). 217 + From("users"). 218 + Where(Eq("active", true).And(Gt("age", 18))). 219 + GroupBy("department"). 220 + OrderBy("name", Ascending). 221 + Limit(10), 239 222 expectedSql: "SELECT name, age, department FROM users WHERE ((active) = (?)) and ((age) > (?)) GROUP BY department ORDER BY name asc LIMIT 10", 240 223 expectedArgs: []any{true, 18}, 241 224 }, ··· 243 226 244 227 for _, test := range tests { 245 228 t.Run(test.name, func(t *testing.T) { 246 - s := test.builder() 247 - sql, args, err := s.Build() 229 + sql, args, err := test.stmt.Build() 248 230 249 231 if err != nil { 250 232 t.Errorf("Expected no error, got %v", err) ··· 270 252 func TestSelectBuild_Errors(t *testing.T) { 271 253 tests := []struct { 272 254 name string 273 - builder func() select_ 255 + stmt select_ 274 256 expectedError string 275 257 }{ 276 258 { 277 - name: "No columns", 278 - builder: func() select_ { 279 - return Select() 280 - }, 259 + name: "No columns", 260 + stmt: Select(), 281 261 expectedError: "result columns empty", 282 262 }, 283 263 { 284 - name: "No from clause", 285 - builder: func() select_ { 286 - return Select("name") 287 - }, 264 + name: "No from clause", 265 + stmt: Select("name"), 288 266 expectedError: "FROM clause is required", 289 267 }, 290 268 { 291 269 name: "Invalid limit", 292 - builder: func() select_ { 293 - return Select("name"). 294 - From("users"). 295 - Limit(0) 296 - }, 270 + stmt: Select("name"). 271 + From("users"). 272 + Limit(0), 297 273 expectedError: "LIMIT must be positive, got 0", 298 274 }, 299 275 { 300 276 name: "Negative limit", 301 - builder: func() select_ { 302 - return Select("name"). 303 - From("users"). 304 - Limit(-5) 305 - }, 277 + stmt: Select("name"). 278 + From("users"). 279 + Limit(-5), 306 280 expectedError: "LIMIT must be positive, got -5", 307 281 }, 308 282 } 309 283 310 284 for _, test := range tests { 311 285 t.Run(test.name, func(t *testing.T) { 312 - s := test.builder() 313 - sql, args, err := s.Build() 286 + sql, args, err := test.stmt.Build() 314 287 315 288 if err == nil { 316 289 t.Error("Expected error, got nil") ··· 384 357 } 385 358 } 386 359 387 - // setupTestDB creates an in-memory SQLite database with test data 388 - func setupTestDB(t *testing.T) *sql.DB { 389 - db, err := sql.Open("sqlite3", ":memory:") 390 - if err != nil { 391 - t.Fatalf("Failed to open database: %v", err) 392 - } 393 - 394 - // Create users table 395 - _, err = db.Exec(` 396 - CREATE TABLE users ( 397 - id INTEGER PRIMARY KEY AUTOINCREMENT, 398 - name TEXT NOT NULL, 399 - age INTEGER NOT NULL, 400 - email TEXT UNIQUE NOT NULL, 401 - department TEXT, 402 - active BOOLEAN DEFAULT TRUE, 403 - salary REAL, 404 - created_at DATETIME DEFAULT CURRENT_TIMESTAMP 405 - ) 406 - `) 407 - if err != nil { 408 - t.Fatalf("Failed to create users table: %v", err) 409 - } 410 - 411 - // Create departments table 412 - _, err = db.Exec(` 413 - CREATE TABLE departments ( 414 - id INTEGER PRIMARY KEY AUTOINCREMENT, 415 - name TEXT NOT NULL, 416 - budget REAL 417 - ) 418 - `) 419 - if err != nil { 420 - t.Fatalf("Failed to create departments table: %v", err) 421 - } 422 - 423 - // Insert test data 424 - users := []struct { 425 - name, email, department string 426 - age int 427 - active bool 428 - salary float64 429 - }{ 430 - {"John Doe", "john@example.com", "Engineering", 30, true, 75000.0}, 431 - {"Jane Smith", "jane@example.com", "Marketing", 25, true, 65000.0}, 432 - {"Bob Johnson", "bob@example.com", "Engineering", 35, false, 80000.0}, 433 - {"Alice Brown", "alice@example.com", "Sales", 28, true, 70000.0}, 434 - {"Charlie Wilson", "charlie@example.com", "Engineering", 32, true, 85000.0}, 435 - {"Diana Prince", "diana@example.com", "Marketing", 29, false, 68000.0}, 436 - } 437 - 438 - for _, user := range users { 439 - _, err = db.Exec(` 440 - INSERT INTO users (name, email, department, age, active, salary) 441 - VALUES (?, ?, ?, ?, ?, ?) 442 - `, user.name, user.email, user.department, user.age, user.active, user.salary) 443 - if err != nil { 444 - t.Fatalf("Failed to insert user %s: %v", user.name, err) 445 - } 446 - } 447 - 448 - // Insert departments 449 - departments := []struct { 450 - name string 451 - budget float64 452 - }{ 453 - {"Engineering", 500000.0}, 454 - {"Marketing", 300000.0}, 455 - {"Sales", 400000.0}, 456 - } 457 - 458 - for _, dept := range departments { 459 - _, err = db.Exec(` 460 - INSERT INTO departments (name, budget) 461 - VALUES (?, ?) 462 - `, dept.name, dept.budget) 463 - if err != nil { 464 - t.Fatalf("Failed to insert department %s: %v", dept.name, err) 465 - } 466 - } 467 - 468 - return db 469 - } 470 - 471 360 func TestSelectIntegration_BasicQueries(t *testing.T) { 472 361 db := setupTestDB(t) 473 362 defer db.Close() 474 363 475 364 tests := []struct { 476 365 name string 477 - builder func() select_ 366 + stmt select_ 478 367 expectedRows int 479 368 }{ 480 369 { 481 - name: "Select all users", 482 - builder: func() select_ { 483 - return Select("*").From("users") 484 - }, 370 + name: "Select all users", 371 + stmt: Select("*").From("users"), 485 372 expectedRows: 6, 486 373 }, 487 374 { 488 375 name: "Select active users only", 489 - builder: func() select_ { 490 - return Select("name", "email"). 491 - From("users"). 492 - Where(Eq("active", true)) 493 - }, 376 + stmt: Select("name", "email"). 377 + From("users"). 378 + Where(Eq("active", true)), 494 379 expectedRows: 4, 495 380 }, 496 381 { 497 382 name: "Select users in Engineering", 498 - builder: func() select_ { 499 - return Select("name", "age"). 500 - From("users"). 501 - Where(Eq("department", "Engineering")) 502 - }, 383 + stmt: Select("name", "age"). 384 + From("users"). 385 + Where(Eq("department", "Engineering")), 503 386 expectedRows: 3, 504 387 }, 505 388 { 506 389 name: "Select users with age > 30", 507 - builder: func() select_ { 508 - return Select("name", "age"). 509 - From("users"). 510 - Where(Gt("age", 30)) 511 - }, 390 + stmt: Select("name", "age"). 391 + From("users"). 392 + Where(Gt("age", 30)), 512 393 expectedRows: 2, 513 394 }, 514 395 { 515 396 name: "Select users with salary between 70000 and 80000", 516 - builder: func() select_ { 517 - return Select("name", "salary"). 518 - From("users"). 519 - Where(Gte("salary", 70000.0).And(Lte("salary", 80000.0))) 520 - }, 397 + stmt: Select("name", "salary"). 398 + From("users"). 399 + Where(Gte("salary", 70000.0).And(Lte("salary", 80000.0))), 521 400 expectedRows: 3, 522 401 }, 523 402 } 524 403 525 404 for _, test := range tests { 526 405 t.Run(test.name, func(t *testing.T) { 527 - s := test.builder() 528 - sql, args, err := s.Build() 406 + sql, args, err := test.stmt.Build() 529 407 if err != nil { 530 408 t.Fatalf("Failed to build query: %v", err) 531 409 } ··· 637 515 t.Fatalf("Expected 6 results, got %d", len(results)) 638 516 } 639 517 640 - // First result should be from Engineering (alphabetically first) with highest age 641 518 if results[0].department != "Engineering" { 642 519 t.Errorf("Expected first result to be from Engineering, got %s", results[0].department) 643 520 } ··· 684 561 t.Errorf("Expected 3 departments, got %d", len(results)) 685 562 } 686 563 687 - // Engineering should have the most users (3) 688 564 if results[0].department != "Engineering" || results[0].count != 3 { 689 565 t.Errorf("Expected Engineering with 3 users first, got %s with %d users", results[0].department, results[0].count) 690 566 } ··· 729 605 t.Errorf("Expected 2 results, got %d", len(results)) 730 606 } 731 607 732 - // Should get Charlie Wilson (85000) and John Doe (75000) 733 608 if results[0].salary != 85000.0 { 734 609 t.Errorf("Expected highest salary to be 85000, got %f", results[0].salary) 735 610 } ··· 859 734 db := setupTestDB(t) 860 735 defer db.Close() 861 736 862 - // Add more test data for performance testing 863 737 start := time.Now() 864 - for i := 0; i < 1000; i++ { 738 + for i := range 1000 { 865 739 _, err := db.Exec(` 866 740 INSERT INTO users (name, email, department, age, active, salary) 867 741 VALUES (?, ?, ?, ?, ?, ?)
+4 -2
scanner.go
··· 33 33 34 34 func (s *Scanner[T]) Scan() iter.Seq[T] { 35 35 return func(yield func(T) bool) { 36 - defer s.rows.Close() 37 - 38 36 for s.rows.Next() { 39 37 var data T 40 38 elem := reflect.ValueOf(&data).Elem() ··· 58 56 } 59 57 } 60 58 } 59 + 60 + func (s *Scanner[T]) Close() error { 61 + return s.rows.Close() 62 + }
+333
scanner_test.go
··· 1 + package norm 2 + 3 + import ( 4 + "database/sql" 5 + "testing" 6 + "time" 7 + 8 + _ "github.com/mattn/go-sqlite3" 9 + ) 10 + 11 + type User struct { 12 + ID int 13 + Name string 14 + Age int 15 + Email string 16 + Department sql.NullString 17 + Active bool 18 + Salary sql.NullFloat64 19 + CreatedAt time.Time 20 + } 21 + 22 + type UserBasic struct { 23 + ID int 24 + Name string 25 + Email string 26 + } 27 + 28 + type Department struct { 29 + ID int 30 + Name string 31 + Budget float64 32 + } 33 + 34 + type SimpleStruct struct { 35 + Value int 36 + } 37 + 38 + func TestScannerWithDepartments(t *testing.T) { 39 + db := setupTestDB(t) 40 + defer db.Close() 41 + 42 + rows, err := db.Query("SELECT id, name, budget FROM departments ORDER BY id") 43 + if err != nil { 44 + t.Fatalf("Failed to query departments: %v", err) 45 + } 46 + 47 + scanner := NewScanner[Department](rows) 48 + defer scanner.Close() 49 + var departments []Department 50 + 51 + for dept := range scanner.Scan() { 52 + departments = append(departments, dept) 53 + } 54 + 55 + if len(departments) != 3 { 56 + t.Errorf("Expected 3 departments, got %d", len(departments)) 57 + } 58 + 59 + d1 := departments[0] 60 + if d1.ID != 1 || d1.Name != "Engineering" || d1.Budget != 500000.0 { 61 + t.Errorf("Engineering department data incorrect: %+v", d1) 62 + } 63 + 64 + d2 := departments[1] 65 + if d2.ID != 2 || d2.Name != "Marketing" || d2.Budget != 300000.0 { 66 + t.Errorf("Marketing department data incorrect: %+v", d2) 67 + } 68 + } 69 + 70 + func TestScannerBasicFunctionality(t *testing.T) { 71 + db := setupTestDB(t) 72 + defer db.Close() 73 + 74 + rows, err := db.Query("SELECT id, name, email FROM users ORDER BY id") 75 + if err != nil { 76 + t.Fatalf("Failed to query users: %v", err) 77 + } 78 + 79 + scanner := NewScanner[UserBasic](rows) 80 + defer scanner.Close() 81 + var users []UserBasic 82 + 83 + for user := range scanner.Scan() { 84 + users = append(users, user) 85 + } 86 + 87 + if len(users) != 6 { 88 + t.Errorf("Expected 6 users, got %d", len(users)) 89 + } 90 + 91 + if users[0].ID != 1 || users[0].Name != "John Doe" || users[0].Email != "john@example.com" { 92 + t.Errorf("Expected first user to be John Doe, got %+v", users[0]) 93 + } 94 + 95 + if users[5].Name != "Diana Prince" || users[5].Email != "diana@example.com" { 96 + t.Errorf("Expected last user to be Diana Prince, got %+v", users[5]) 97 + } 98 + } 99 + 100 + func TestScannerWithAllFields(t *testing.T) { 101 + db := setupTestDB(t) 102 + defer db.Close() 103 + 104 + rows, err := db.Query("SELECT id, name, age, email, department, active, salary, created_at FROM users ORDER BY id") 105 + if err != nil { 106 + t.Fatalf("Failed to query users: %v", err) 107 + } 108 + 109 + scanner := NewScanner[User](rows) 110 + defer scanner.Close() 111 + var users []User 112 + 113 + for user := range scanner.Scan() { 114 + users = append(users, user) 115 + } 116 + 117 + if len(users) != 6 { 118 + t.Errorf("Expected 6 users, got %d", len(users)) 119 + } 120 + 121 + u1 := users[0] 122 + if u1.ID != 1 || u1.Name != "John Doe" || u1.Age != 30 || u1.Email != "john@example.com" || !u1.Active { 123 + t.Errorf("User 1 basic data incorrect: %+v", u1) 124 + } 125 + if !u1.Department.Valid || u1.Department.String != "Engineering" { 126 + t.Errorf("User 1 department incorrect: %v", u1.Department) 127 + } 128 + if !u1.Salary.Valid || u1.Salary.Float64 != 75000.0 { 129 + t.Errorf("User 1 salary incorrect: %v", u1.Salary) 130 + } 131 + 132 + u3 := users[2] 133 + if u3.Name != "Bob Johnson" || u3.Active { 134 + t.Errorf("User 3 should be inactive Bob Johnson: %+v", u3) 135 + } 136 + 137 + if u1.CreatedAt.IsZero() { 138 + t.Error("User 1 created_at should not be zero") 139 + } 140 + } 141 + 142 + func TestScannerWithErrorHandler(t *testing.T) { 143 + db := setupTestDB(t) 144 + defer db.Close() 145 + 146 + rows, err := db.Query("SELECT id, name, email FROM users LIMIT 1") 147 + if err != nil { 148 + t.Fatalf("Failed to query users: %v", err) 149 + } 150 + 151 + var capturedError error 152 + scanner := NewScanner(rows, OnScannerError[SimpleStruct](func(err error) { 153 + capturedError = err 154 + })) 155 + defer scanner.Close() 156 + 157 + var results []SimpleStruct 158 + for result := range scanner.Scan() { 159 + results = append(results, result) 160 + } 161 + 162 + if capturedError == nil { 163 + t.Error("Expected an error to be captured, but none was") 164 + } 165 + 166 + if len(results) != 0 { 167 + t.Errorf("Expected 0 results due to scan error, got %d", len(results)) 168 + } 169 + } 170 + 171 + func TestScannerEarlyTermination(t *testing.T) { 172 + db := setupTestDB(t) 173 + defer db.Close() 174 + 175 + rows, err := db.Query("SELECT id, name, email FROM users ORDER BY id") 176 + if err != nil { 177 + t.Fatalf("Failed to query users: %v", err) 178 + } 179 + 180 + scanner := NewScanner[UserBasic](rows) 181 + defer scanner.Close() 182 + var users []UserBasic 183 + count := 0 184 + 185 + for user := range scanner.Scan() { 186 + users = append(users, user) 187 + count++ 188 + if count == 1 { 189 + break 190 + } 191 + } 192 + 193 + if len(users) != 1 { 194 + t.Errorf("Expected 1 user due to early termination, got %d", len(users)) 195 + } 196 + 197 + if users[0].ID != 1 || users[0].Name != "John Doe" { 198 + t.Errorf("Expected first user to be John Doe, got %+v", users[0]) 199 + } 200 + } 201 + 202 + func TestScannerEmptyResults(t *testing.T) { 203 + db := setupTestDB(t) 204 + defer db.Close() 205 + 206 + rows, err := db.Query("SELECT id, name, email FROM users WHERE id = 999") 207 + if err != nil { 208 + t.Fatalf("Failed to query users: %v", err) 209 + } 210 + 211 + scanner := NewScanner[UserBasic](rows) 212 + defer scanner.Close() 213 + var users []UserBasic 214 + 215 + for user := range scanner.Scan() { 216 + users = append(users, user) 217 + } 218 + 219 + if len(users) != 0 { 220 + t.Errorf("Expected 0 users from empty query, got %d", len(users)) 221 + } 222 + } 223 + 224 + func TestScannerMultipleIterations(t *testing.T) { 225 + db := setupTestDB(t) 226 + defer db.Close() 227 + 228 + rows, err := db.Query("SELECT id, name, email FROM users ORDER BY id LIMIT 1") 229 + if err != nil { 230 + t.Fatalf("Failed to query users: %v", err) 231 + } 232 + 233 + scanner := NewScanner[UserBasic](rows) 234 + defer scanner.Close() 235 + seq := scanner.Scan() 236 + 237 + var users1 []UserBasic 238 + for user := range seq { 239 + users1 = append(users1, user) 240 + } 241 + 242 + var users2 []UserBasic 243 + for user := range seq { 244 + users2 = append(users2, user) 245 + } 246 + 247 + if len(users1) != 1 { 248 + t.Errorf("Expected 1 user from first iteration, got %d", len(users1)) 249 + } 250 + 251 + if len(users2) != 0 { 252 + t.Errorf("Expected 0 users from second iteration, got %d", len(users2)) 253 + } 254 + } 255 + 256 + func TestScannerWithNilErrorHandler(t *testing.T) { 257 + db := setupTestDB(t) 258 + defer db.Close() 259 + 260 + rows, err := db.Query("SELECT id, name, email FROM users LIMIT 1") 261 + if err != nil { 262 + t.Fatalf("Failed to query users: %v", err) 263 + } 264 + 265 + scanner := NewScanner[UserBasic](rows) 266 + defer scanner.Close() 267 + var users []UserBasic 268 + 269 + for user := range scanner.Scan() { 270 + users = append(users, user) 271 + } 272 + 273 + if len(users) != 1 { 274 + t.Errorf("Expected 1 user, got %d", len(users)) 275 + } 276 + } 277 + 278 + func TestScannerResourceCleanup(t *testing.T) { 279 + db := setupTestDB(t) 280 + defer db.Close() 281 + 282 + rows, err := db.Query("SELECT id, name, email FROM users") 283 + if err != nil { 284 + t.Fatalf("Failed to query users: %v", err) 285 + } 286 + 287 + scanner := NewScanner[UserBasic](rows) 288 + 289 + for user := range scanner.Scan() { 290 + _ = user 291 + break 292 + } 293 + 294 + scanner.Close() 295 + if err := rows.Err(); err != nil { 296 + t.Errorf("Expected no error, got %s", err) 297 + } 298 + } 299 + 300 + func TestScannerFilterByDepartment(t *testing.T) { 301 + db := setupTestDB(t) 302 + defer db.Close() 303 + 304 + rows, err := db.Query("SELECT id, name, age, email, department, active, salary, created_at FROM users WHERE department = 'Engineering' ORDER BY id") 305 + if err != nil { 306 + t.Fatalf("Failed to query users: %v", err) 307 + } 308 + 309 + scanner := NewScanner[User](rows) 310 + defer scanner.Close() 311 + var users []User 312 + 313 + for user := range scanner.Scan() { 314 + users = append(users, user) 315 + } 316 + 317 + if len(users) != 3 { 318 + t.Errorf("Expected 3 Engineering users, got %d", len(users)) 319 + } 320 + 321 + for i, user := range users { 322 + if !user.Department.Valid || user.Department.String != "Engineering" { 323 + t.Errorf("User %d should be from Engineering: %+v", i, user) 324 + } 325 + } 326 + 327 + expectedNames := []string{"John Doe", "Bob Johnson", "Charlie Wilson"} 328 + for i, user := range users { 329 + if user.Name != expectedNames[i] { 330 + t.Errorf("Expected user %d to be %s, got %s", i, expectedNames[i], user.Name) 331 + } 332 + } 333 + }
+92
test_util.go
··· 1 + package norm 2 + 3 + import ( 4 + "database/sql" 5 + "testing" 6 + 7 + _ "github.com/mattn/go-sqlite3" 8 + ) 9 + 10 + // setupTestDB creates an in-memory SQLite database with test data 11 + func setupTestDB(t *testing.T) *sql.DB { 12 + db, err := sql.Open("sqlite3", ":memory:") 13 + if err != nil { 14 + t.Fatalf("Failed to open database: %v", err) 15 + } 16 + 17 + // Create users table 18 + _, err = db.Exec(` 19 + CREATE TABLE users ( 20 + id INTEGER PRIMARY KEY AUTOINCREMENT, 21 + name TEXT NOT NULL, 22 + age INTEGER NOT NULL, 23 + email TEXT UNIQUE NOT NULL, 24 + department TEXT, 25 + active BOOLEAN DEFAULT TRUE, 26 + salary REAL, 27 + created_at DATETIME DEFAULT CURRENT_TIMESTAMP 28 + ) 29 + `) 30 + if err != nil { 31 + t.Fatalf("Failed to create users table: %v", err) 32 + } 33 + 34 + // Create departments table 35 + _, err = db.Exec(` 36 + CREATE TABLE departments ( 37 + id INTEGER PRIMARY KEY AUTOINCREMENT, 38 + name TEXT NOT NULL, 39 + budget REAL 40 + ) 41 + `) 42 + if err != nil { 43 + t.Fatalf("Failed to create departments table: %v", err) 44 + } 45 + 46 + // Insert test data 47 + users := []struct { 48 + name, email, department string 49 + age int 50 + active bool 51 + salary float64 52 + }{ 53 + {"John Doe", "john@example.com", "Engineering", 30, true, 75000.0}, 54 + {"Jane Smith", "jane@example.com", "Marketing", 25, true, 65000.0}, 55 + {"Bob Johnson", "bob@example.com", "Engineering", 35, false, 80000.0}, 56 + {"Alice Brown", "alice@example.com", "Sales", 28, true, 70000.0}, 57 + {"Charlie Wilson", "charlie@example.com", "Engineering", 32, true, 85000.0}, 58 + {"Diana Prince", "diana@example.com", "Marketing", 29, false, 68000.0}, 59 + } 60 + 61 + for _, user := range users { 62 + _, err = db.Exec(` 63 + INSERT INTO users (name, email, department, age, active, salary) 64 + VALUES (?, ?, ?, ?, ?, ?) 65 + `, user.name, user.email, user.department, user.age, user.active, user.salary) 66 + if err != nil { 67 + t.Fatalf("Failed to insert user %s: %v", user.name, err) 68 + } 69 + } 70 + 71 + // Insert departments 72 + departments := []struct { 73 + name string 74 + budget float64 75 + }{ 76 + {"Engineering", 500000.0}, 77 + {"Marketing", 300000.0}, 78 + {"Sales", 400000.0}, 79 + } 80 + 81 + for _, dept := range departments { 82 + _, err = db.Exec(` 83 + INSERT INTO departments (name, budget) 84 + VALUES (?, ?) 85 + `, dept.name, dept.budget) 86 + if err != nil { 87 + t.Fatalf("Failed to insert department %s: %v", dept.name, err) 88 + } 89 + } 90 + 91 + return db 92 + }