package main import ( "context" "fmt" "log" "math" "math/rand" "os" "time" "github.com/jackc/pgx/v5/pgxpool" "github.com/joho/godotenv" ) var ( firstNames = []string{ "Juan", "María", "Carlos", "Ana", "Miguel", "Rosa", "Pedro", "Isabel", "Luis", "Carmen", "José", "Antonia", "Fernando", "Dolores", "Diego", "Margarita", "Alejandro", "Francisca", "Antonio", "Juana", "Francisco", "Pilar", "Andrés", "Elena", "Rafael", "Teresa", "Enrique", "Ángeles", "Jorge", "Soledad", "Ramón", "Asunción", } lastNames = []string{ "García", "Rodríguez", "González", "López", "Martínez", "Sánchez", "Peña", "Castellanos", "Moreno", "Jiménez", "Hernández", "Díaz", "Ramírez", "Cruz", "Velasco", "Campos", "Medina", "Ruiz", "Domínguez", "Delgado", "Flores", "Silver", "Torres", "Rivera", "Vargas", "Castro", "Vega", "Rojas", "Parra", "Salazar", "Guzmán", "Ochoa", } domainNames = []string{ "gmail.com", "yahoo.com", "hotmail.com", "outlook.com", "empresa.com", "mail.com", "correo.es", "example.com", "test.io", "domain.dev", } ) func init() { rand.Seed(time.Now().UnixNano()) } func randomFirstName() string { return firstNames[rand.Intn(len(firstNames))] } func randomLastName() string { return lastNames[rand.Intn(len(lastNames))] } func randomEmail() string { firstName := randomFirstName() lastName := randomLastName() domain := domainNames[rand.Intn(len(domainNames))] return fmt.Sprintf("%s.%s@%s", firstName, lastName, domain) } func randomAge() int { return rand.Intn(70) + 18 } func randomSalary() float64 { return math.Round((rand.Float64()*100000 + 25000)) / 100 } func randomBirthDate() time.Time { years := rand.Intn(70) + 18 days := rand.Intn(365) return time.Now().AddDate(-years, 0, -days) } func randomPhoneNumber() string { return fmt.Sprintf("+34 6%d %d%d%d%d%d%d%d", rand.Intn(10), rand.Intn(10), rand.Intn(10), rand.Intn(10), rand.Intn(10), rand.Intn(10), rand.Intn(10), rand.Intn(10), ) } func randomCity() string { cities := []string{ "Madrid", "Barcelona", "Valencia", "Sevilla", "Bilbao", "Zaragoza", "Málaga", "Murcia", "Palma", "Las Palmas", "Córdoba", "Valladolid", "Vigo", "Gijón", "Hospitalet", } return cities[rand.Intn(len(cities))] } func randomHobbies() []string { allHobbies := []string{ "lectura", "viajes", "cine", "música", "deportes", "cocina", "fotografía", "gaming", "yoga", "senderismo", "natación", "tenis", "ajedrez", "pintura", "jardinería", } numHobbies := rand.Intn(4) + 1 selected := make([]string, 0, numHobbies) used := make(map[int]bool) for len(selected) < numHobbies { idx := rand.Intn(len(allHobbies)) if !used[idx] { used[idx] = true selected = append(selected, allHobbies[idx]) } } return selected } func createUsersTable(db *pgxpool.Pool, ctx context.Context) error { createTableSQL := ` CREATE TABLE IF NOT EXISTS users ( id SERIAL PRIMARY KEY, first_name VARCHAR(100) NOT NULL, last_name VARCHAR(100) NOT NULL, email VARCHAR(255) UNIQUE NOT NULL, age INTEGER NOT NULL CHECK (age >= 18), birth_date DATE NOT NULL, salary NUMERIC(12, 2), phone_number VARCHAR(20), is_active BOOLEAN DEFAULT true, is_verified BOOLEAN DEFAULT false, city VARCHAR(100), hobbies TEXT[], created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, metadata JSONB ); ` _, err := db.Exec(ctx, createTableSQL) if err != nil { return fmt.Errorf("error creating users table: %w", err) } return nil } func truncateUsersTable(db *pgxpool.Pool, ctx context.Context) error { truncateSQL := `TRUNCATE TABLE users RESTART IDENTITY CASCADE;` _, err := db.Exec(ctx, truncateSQL) if err != nil { return fmt.Errorf("error truncating users table: %w", err) } return nil } func insertUserRecord(db *pgxpool.Pool, ctx context.Context, userNum int) error { firstName := randomFirstName() lastName := randomLastName() email := randomEmail() age := randomAge() birthDate := randomBirthDate() salary := randomSalary() phoneNumber := randomPhoneNumber() isActive := rand.Intn(2) == 1 isVerified := rand.Intn(2) == 1 city := randomCity() hobbies := randomHobbies() metadata := fmt.Sprintf( `{"user_number": %d, "registration_source": "%s", "tags": [%d, %d, %d]}`, userNum, []string{"web", "mobile", "api"}[rand.Intn(3)], rand.Intn(100), rand.Intn(100), rand.Intn(100), ) insertSQL := ` INSERT INTO users ( first_name, last_name, email, age, birth_date, salary, phone_number, is_active, is_verified, city, hobbies, metadata ) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12) ON CONFLICT (email) DO NOTHING; ` _, err := db.Exec( ctx, insertSQL, firstName, lastName, email, age, birthDate, salary, phoneNumber, isActive, isVerified, city, hobbies, metadata, ) if err != nil { return fmt.Errorf("error inserting user %d: %w", userNum, err) } return nil } func main() { err := godotenv.Load() if err != nil { log.Println("Warning: could not load .env file") } dbURL := os.Getenv("PG_FROM_DB_URL") if dbURL == "" { log.Fatal("PG_FROM_DB_URL environment variable not set") } ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second) defer cancel() db, err := pgxpool.New(ctx, dbURL) if err != nil { log.Fatalf("Unable to create connection pool: %v", err) } defer db.Close() err = db.Ping(ctx) if err != nil { log.Fatalf("Unable to ping database: %v", err) } fmt.Println("✓ Connected to database successfully") fmt.Println("Creating users table...") err = createUsersTable(db, ctx) if err != nil { log.Fatalf("Failed to create table: %v", err) } fmt.Println("✓ Users table created/already exists") fmt.Println("Clearing existing data...") err = truncateUsersTable(db, ctx) if err != nil { log.Fatalf("Failed to truncate table: %v", err) } fmt.Println("✓ Table cleared") fmt.Println("Inserting 1000 user records...") for i := 1; i <= 1000; i++ { err := insertUserRecord(db, ctx, i) if err != nil { log.Printf("Warning: failed to insert user %d: %v", i, err) } if i%100 == 0 { fmt.Printf(" Progress: %d/1000 records inserted\n", i) } } fmt.Println("✓ All 1000 user records inserted successfully") var count int err = db.QueryRow(ctx, "SELECT COUNT(*) FROM users;").Scan(&count) if err != nil { log.Printf("Warning: could not verify record count: %v", err) } else { fmt.Printf("✓ Final user count: %d\n", count) } fmt.Println("\n✅ Fixture creation completed successfully!") }