Initial commit.
[quanweb.git] / main / main.go
1 package main
2
3 import (
4   "database/sql"
5   "fmt"
6   _ "github.com/lib/pq"
7 //  "json"
8 )
9
10 type Book struct {
11   Id             int
12   Age            string  // recommended age, e.g. "beginner", "junior", "ya" (Young Adult), "adult"
13   AuthorGrouping string  // unique rendering of the author's name, used for internal grouping 
14   AuthorReading  string  // reading order of author's name, e.g. "Charles Dickens"
15   AuthorSort     string  // sort order of author's name, e.g. "Dickens, Charles"
16   DDC            string  // Dewey Decimal Classification
17   Description    string  // Back cover / inside flap blurb, describing the book
18   Genre          string  // e.g. "adventure", "historical", "mystery", "romance", "sf" (Science Fiction)
19   LCC            string  // Library of Congress Classification
20   SeriesName     string  
21   Title          string
22   Volume         string
23 }
24
25 func main() {
26   // TODO:  protect DB with a real password, and read DB config from an external file
27   db := openDb("quanlib", "quanlib", "quanlib")
28   if nil == db {
29     return
30   }
31   defer db.Close()
32
33   query := "SELECT COUNT(1) FROM Books"
34   ps, err := db.Prepare(query)
35   if nil != err {
36     fmt.Println("Error:  failed to prepare statement:  " + query)
37     return
38   }
39
40   var count int
41   err = ps.QueryRow().Scan(&count)
42   if sql.ErrNoRows == err {
43     fmt.Println("Error:  No rows returned by statement:  " + query)
44   } else {
45     fmt.Println("Found ", count, " books.")
46   }
47
48   ids := []int {1041, 1951, 2148, 103}
49   books := queryBooksByIds(db, ids)
50
51   fmt.Println("Found books:", books)
52 }
53
54 func nsVal(ns sql.NullString) string {
55   if ns.Valid {
56     return ns.String
57   }
58   return ""
59 }
60
61 func openDb(user, pass, dbName string) (*sql.DB) {
62   db, err := sql.Open("postgres","user=" + user + " password=" + pass + " dbname=" + dbName + " sslmode=disable")
63   if nil != err {
64     fmt.Println("Error:  DB arguments incorrect?", err)
65     return nil
66   }
67
68   err = db.Ping()
69   if nil != err {
70     fmt.Println("Error:  could not connect to DB.", err)
71     db.Close()
72     return nil
73   }
74
75   return db
76 }
77
78 func queryBooksByIds(db *sql.DB, ids []int) []Book {
79   query := `SELECT s.age,a.grouping,a.reading,a.sort,c.ddc,b.description,s.genre,c.lcc,s.descr,b.title,b.volume
80             FROM Authors a 
81             INNER JOIN Books b ON a.id=b.author
82             LEFT OUTER JOIN Classifications c ON c.id=b.classification
83             LEFT OUTER JOIN Series s ON s.id=b.series
84             WHERE b.id=$1`
85
86   ps, err := db.Prepare(query)
87   if nil != err {
88     fmt.Println("Error:  failed to prepare statement:  " + query)
89     return nil
90   }
91   defer ps.Close()
92
93   res := make([]Book, len(ids))
94   
95   for n, id := range ids {
96     row := ps.QueryRow(id)
97
98     var age, grouping, reading, sort, ddc, description, genre, lcc, name, title, volume sql.NullString
99
100     err = row.Scan(&age, &grouping, &reading, &sort, &ddc, &description, &genre, &lcc, &name, &title, &volume)
101     if err != nil {
102       fmt.Println("Error:  Failed to read book:", id, ":", err)
103     } else {
104       var b Book
105       b.Id = id
106       b.Age = nsVal(age)
107       b.AuthorGrouping = nsVal(grouping)
108       b.AuthorReading = nsVal(reading)
109       b.AuthorSort = nsVal(sort)
110       b.DDC = nsVal(ddc)
111       b.Description = nsVal(description)
112       b.Genre = nsVal(genre)
113       b.LCC = nsVal(lcc)
114       b.SeriesName = nsVal(name)
115       b.Title = nsVal(title)
116       b.Volume = nsVal(volume)
117
118       res[n] = b
119     }
120   }
121
122   return res
123 }
124