db/generate_orders.go (86 lines of code) (raw):

package opbeansdb import ( "context" "math/rand" "github.com/jmoiron/sqlx" "github.com/pkg/errors" ) const ( maxOrderAmount = 3 ) // GenerateOrders generates n orders, randomizing the // products and customers in use. func GenerateOrders(db *sqlx.DB, driver string, n int, rng *rand.Rand) error { ctx, cancel := context.WithCancel(context.Background()) defer cancel() productIDs, err := getIDs(ctx, db, "products") if err != nil { return err } customerIDs, err := getIDs(ctx, db, "customers") if err != nil { return err } tx, err := db.BeginTx(ctx, nil) if err != nil { return err } returningID := "RETURNING id" if driver == "sqlite3" { returningID = "" } insertOrderStmt, err := tx.PrepareContext(ctx, db.Rebind( "INSERT INTO orders (customer_id) VALUES (?) "+returningID, )) if err != nil { return errors.Wrap(err, "failed to prepare insert orders statement") } defer insertOrderStmt.Close() insertOrderLineStmt, err := tx.PrepareContext(ctx, db.Rebind( "INSERT INTO order_lines (order_id, product_id, amount) VALUES(?, ?, ?)", )) if err != nil { return errors.Wrap(err, "failed to prepare insert order lines statement") } defer insertOrderLineStmt.Close() for i := 0; i < n; i++ { productID := productIDs[rng.Intn(len(productIDs))] customerID := customerIDs[rng.Intn(len(customerIDs))] var orderID int64 if driver == "sqlite3" { result, err := insertOrderStmt.ExecContext(ctx, customerID) if err != nil { return err } rowID, err := result.LastInsertId() if err != nil { return err } orderID = rowID } else { err := insertOrderStmt.QueryRowContext(ctx, customerID).Scan(&orderID) if err != nil { return err } } amount := rng.Intn(maxOrderAmount + 1) if _, err := insertOrderLineStmt.ExecContext(ctx, orderID, productID, amount); err != nil { return err } } return tx.Commit() } func getIDs(ctx context.Context, db *sqlx.DB, table string) ([]int, error) { var ids []int rows, err := db.QueryContext(ctx, "SELECT id FROM "+table) if err != nil { return nil, err } defer rows.Close() for rows.Next() { var id int if err := rows.Scan(&id); err != nil { return nil, err } ids = append(ids, id) } return ids, rows.Close() }