| package main |
| |
| import ( |
| "context" |
| "database/sql" |
| "fmt" |
| "time" |
| |
| _ "github.com/lib/pq" |
| ) |
| |
| // app is the model of the oodviewer app. |
| // The data modeled is a K/V map from string ('Term') to list of entries. |
| type app struct { |
| db *sql.DB |
| } |
| |
| // term represents a key in the K/V map of the model. |
| type term struct { |
| // Name of the term, the 'K' of the K/V map. |
| Name string |
| // Count of entries (len(V) of the K/V map). |
| Entries uint64 |
| } |
| |
| // entry is an element contained under a term. A list of entries ([]entry) is |
| // the 'V' of the K/V map. |
| type entry struct { |
| Entry string `json:"entry"` |
| Added int64 `json:"added"` |
| Author string `json:"author"` |
| } |
| |
| // newApp returns an instantiated app given a lib/pq postgres connection |
| // string. |
| func newApp(postgres string) (*app, error) { |
| db, err := sql.Open("postgres", flagPostgres) |
| if err != nil { |
| return nil, fmt.Errorf("Open: %v", err) |
| } |
| |
| return &app{ |
| db: db, |
| }, nil |
| } |
| |
| // getTerms returns all terms stored in the database. |
| func (a *app) getTerms(ctx context.Context) ([]term, error) { |
| rows, err := a.db.QueryContext(ctx, ` |
| SELECT |
| _term._name, |
| count(_entry._text) |
| FROM |
| _term |
| LEFT JOIN _entry |
| ON |
| _entry._term_oid = _term._oid |
| GROUP BY _term._oid |
| ORDER BY _term._name |
| `) |
| if err != nil { |
| return nil, err |
| } |
| var res []term |
| for rows.Next() { |
| var name string |
| var count uint64 |
| if err := rows.Scan(&name, &count); err != nil { |
| return nil, err |
| } |
| res = append(res, term{ |
| Name: name, |
| Entries: count, |
| }) |
| } |
| if err := rows.Err(); err != nil { |
| return nil, err |
| } |
| return res, err |
| } |
| |
| // getEntries returns all entries of a given term stored in the database. |
| func (a *app) getEntries(ctx context.Context, name string) ([]entry, error) { |
| rows, err := a.db.QueryContext(ctx, ` |
| SELECT |
| _entry._text, |
| _entry._added_at, |
| _entry._added_by |
| FROM |
| _term |
| LEFT JOIN _entry |
| ON _entry._term_oid = _term._oid |
| WHERE lower(_term._name) = lower($1) |
| ORDER BY _entry._added_at |
| `, name) |
| if err != nil { |
| return nil, err |
| } |
| var res []entry |
| for rows.Next() { |
| var text string |
| var added time.Time |
| var author string |
| if err := rows.Scan(&text, &added, &author); err != nil { |
| return nil, err |
| } |
| res = append(res, entry{ |
| Entry: text, |
| Added: added.Unix(), |
| Author: author, |
| }) |
| } |
| if err := rows.Err(); err != nil { |
| return nil, err |
| } |
| return res, err |
| } |