github.com/ncruces/go-sqlite3@v0.15.1-0.20240520133447-53eef1510ff0/driver/example_test.go (about)

     1  //go:build (linux || darwin || windows || freebsd || illumos) && !sqlite3_nosys
     2  
     3  package driver_test
     4  
     5  // Adapted from: https://go.dev/doc/tutorial/database-access
     6  
     7  import (
     8  	"database/sql"
     9  	"fmt"
    10  	"log"
    11  	"os"
    12  
    13  	_ "github.com/ncruces/go-sqlite3/driver"
    14  	_ "github.com/ncruces/go-sqlite3/embed"
    15  )
    16  
    17  var db *sql.DB
    18  
    19  type Album struct {
    20  	ID     int64
    21  	Title  string
    22  	Artist string
    23  	Price  float32
    24  }
    25  
    26  func Example() {
    27  	// Get a database handle.
    28  	var err error
    29  	db, err = sql.Open("sqlite3", "./recordings.db")
    30  	if err != nil {
    31  		log.Fatal(err)
    32  	}
    33  	defer os.Remove("./recordings.db")
    34  	defer db.Close()
    35  
    36  	// Create a table with some data in it.
    37  	err = albumsSetup()
    38  	if err != nil {
    39  		log.Fatal(err)
    40  	}
    41  
    42  	albums, err := albumsByArtist("John Coltrane")
    43  	if err != nil {
    44  		log.Fatal(err)
    45  	}
    46  	fmt.Printf("Albums found: %v\n", albums)
    47  
    48  	// Hard-code ID 2 here to test the query.
    49  	alb, err := albumByID(2)
    50  	if err != nil {
    51  		log.Fatal(err)
    52  	}
    53  	fmt.Printf("Album found: %v\n", alb)
    54  
    55  	albID, err := addAlbum(Album{
    56  		Title:  "The Modern Sound of Betty Carter",
    57  		Artist: "Betty Carter",
    58  		Price:  49.99,
    59  	})
    60  	if err != nil {
    61  		log.Fatal(err)
    62  	}
    63  	fmt.Printf("ID of added album: %v\n", albID)
    64  	// Output:
    65  	// Albums found: [{1 Blue Train John Coltrane 56.99} {2 Giant Steps John Coltrane 63.99}]
    66  	// Album found: {2 Giant Steps John Coltrane 63.99}
    67  	// ID of added album: 5
    68  }
    69  
    70  func albumsSetup() error {
    71  	_, err := db.Exec(`
    72  		DROP TABLE IF EXISTS album;
    73  		CREATE TABLE album (
    74  			id         INTEGER PRIMARY KEY AUTOINCREMENT,
    75  			title      VARCHAR(128) NOT NULL,
    76  			artist     VARCHAR(255) NOT NULL,
    77  			price      DECIMAL(5,2) NOT NULL
    78  		);
    79  	`)
    80  	if err != nil {
    81  		return err
    82  	}
    83  
    84  	_, err = db.Exec(`
    85  		INSERT INTO album
    86  			(title, artist, price)
    87  		VALUES
    88  			('Blue Train', 'John Coltrane', 56.99),
    89  			('Giant Steps', 'John Coltrane', 63.99),
    90  			('Jeru', 'Gerry Mulligan', 17.99),
    91  			('Sarah Vaughan', 'Sarah Vaughan', 34.98)
    92  	`)
    93  	if err != nil {
    94  		return err
    95  	}
    96  
    97  	return nil
    98  }
    99  
   100  // albumsByArtist queries for albums that have the specified artist name.
   101  func albumsByArtist(name string) ([]Album, error) {
   102  	// An albums slice to hold data from returned rows.
   103  	var albums []Album
   104  
   105  	rows, err := db.Query("SELECT * FROM album WHERE artist = ?", name)
   106  	if err != nil {
   107  		return nil, fmt.Errorf("albumsByArtist %q: %w", name, err)
   108  	}
   109  	defer rows.Close()
   110  	// Loop through rows, using Scan to assign column data to struct fields.
   111  	for rows.Next() {
   112  		var alb Album
   113  		if err := rows.Scan(&alb.ID, &alb.Title, &alb.Artist, &alb.Price); err != nil {
   114  			return nil, fmt.Errorf("albumsByArtist %q: %w", name, err)
   115  		}
   116  		albums = append(albums, alb)
   117  	}
   118  	if err := rows.Err(); err != nil {
   119  		return nil, fmt.Errorf("albumsByArtist %q: %w", name, err)
   120  	}
   121  	return albums, nil
   122  }
   123  
   124  // albumByID queries for the album with the specified ID.
   125  func albumByID(id int64) (Album, error) {
   126  	// An album to hold data from the returned row.
   127  	var alb Album
   128  
   129  	row := db.QueryRow("SELECT * FROM album WHERE id = ?", id)
   130  	if err := row.Scan(&alb.ID, &alb.Title, &alb.Artist, &alb.Price); err != nil {
   131  		if err == sql.ErrNoRows {
   132  			return alb, fmt.Errorf("albumsById %d: no such album", id)
   133  		}
   134  		return alb, fmt.Errorf("albumsById %d: %w", id, err)
   135  	}
   136  	return alb, nil
   137  }
   138  
   139  // addAlbum adds the specified album to the database,
   140  // returning the album ID of the new entry
   141  func addAlbum(alb Album) (int64, error) {
   142  	result, err := db.Exec("INSERT INTO album (title, artist, price) VALUES (?, ?, ?)", alb.Title, alb.Artist, alb.Price)
   143  	if err != nil {
   144  		return 0, fmt.Errorf("addAlbum: %w", err)
   145  	}
   146  	id, err := result.LastInsertId()
   147  	if err != nil {
   148  		return 0, fmt.Errorf("addAlbum: %w", err)
   149  	}
   150  	return id, nil
   151  }