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 }