Day 1: Worked out more robust schema, wrote some go code for interacting with it.
This commit is contained in:
parent
5688a6546a
commit
d832463ded
15
README.md
15
README.md
|
@ -1,3 +1,16 @@
|
|||
# goread
|
||||
|
||||
Maybe rewrite the library
|
||||
Maybe rewrite the library, at the very least migrate to a better schema.
|
||||
|
||||
This is a proof of concept, mainly to get myself a bit more knowledgable about how our current library system works.
|
||||
|
||||
- file.out contains a dump of all tables that have a NULL ISBN.
|
||||
|
||||
TODO:
|
||||
- Tighten up the columns w.r.t. null and bad values
|
||||
- Add more checks to ensure data is actually valid / not bad
|
||||
- Ensure we have the books we have in the catalogue
|
||||
- Add UTF-8 support for the UI/UX/storage
|
||||
- Perform normalization on data entered by users (e.g. ISBN sanitization / verification).
|
||||
- Double check formats of everything else
|
||||
|
||||
|
|
Binary file not shown.
|
@ -0,0 +1,39 @@
|
|||
package db
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"time"
|
||||
)
|
||||
|
||||
type CheckedOut struct {
|
||||
ID int64
|
||||
UWID string
|
||||
DateOut sql.NullTime
|
||||
}
|
||||
|
||||
type Returned struct {
|
||||
ID int64
|
||||
UWID string
|
||||
DateOut sql.NullTime
|
||||
DateIn sql.NullTime
|
||||
}
|
||||
|
||||
// TODO: NARROW THIS DATA SOMEHOW
|
||||
type Book struct {
|
||||
ID int64
|
||||
ISBN sql.NullString
|
||||
LCCN sql.NullString
|
||||
Title string
|
||||
Subtitle sql.NullString
|
||||
Authors sql.NullString
|
||||
Edition sql.NullString
|
||||
Publisher sql.NullString
|
||||
PublishYear sql.NullString `db:"publish_year"`
|
||||
PublishMonth sql.NullString `db:"publish_month"`
|
||||
PublishLocation sql.NullString `db:"publish_location"`
|
||||
Pages sql.NullString
|
||||
Pagination sql.NullString
|
||||
Weight sql.NullString
|
||||
LastUpdated time.Time `db:"last_updated"`
|
||||
Deleted bool
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
package db
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/jmoiron/sqlx"
|
||||
)
|
||||
|
||||
const (
|
||||
getAllBooks = `SELECT * from books where deleted = 0`
|
||||
)
|
||||
|
||||
type Catalogue struct {
|
||||
db *sqlx.DB
|
||||
}
|
||||
|
||||
func OpenCatalogue(dsn string) (*Catalogue, error) {
|
||||
db, err := sqlx.Open("sqlite3", dsn)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to open sqlite3 database with dsn: %s, given error: %w", dsn, err)
|
||||
}
|
||||
|
||||
return &Catalogue{db: db}, nil
|
||||
}
|
||||
|
||||
func (c *Catalogue) GetAllBooks(ctx context.Context) ([]Book, error) {
|
||||
var books []Book
|
||||
err := c.db.SelectContext(ctx, &books, getAllBooks)
|
||||
return books, err
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
module git.csclub.uwaterloo.ca/joss/goread
|
||||
|
||||
go 1.19
|
||||
|
||||
require (
|
||||
github.com/jmoiron/sqlx v1.3.5 // indirect
|
||||
github.com/mattn/go-sqlite3 v1.14.15 // indirect
|
||||
)
|
|
@ -0,0 +1,7 @@
|
|||
github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
|
||||
github.com/jmoiron/sqlx v1.3.5 h1:vFFPA71p1o5gAeqtEAwLU4dnX2napprKtHr7PYIcN3g=
|
||||
github.com/jmoiron/sqlx v1.3.5/go.mod h1:nRVWtLre0KfCLJvgxzCsLVMogSvQ1zNJtpYr2Ccp0mQ=
|
||||
github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
||||
github.com/mattn/go-sqlite3 v1.14.6/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
|
||||
github.com/mattn/go-sqlite3 v1.14.15 h1:vfoHhTN1af61xCRSWzFIWzx2YskyMTwHLrExkBOjvxI=
|
||||
github.com/mattn/go-sqlite3 v1.14.15/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg=
|
|
@ -0,0 +1,37 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"git.csclub.uwaterloo.ca/joss/goread/db"
|
||||
|
||||
_ "github.com/mattn/go-sqlite3"
|
||||
)
|
||||
|
||||
const (
|
||||
CatalogueDBFile = "/users/libcom/catalogue.db"
|
||||
BookTableName = "books"
|
||||
BookCategoryTableName = "book_categories"
|
||||
CategoryTableName = "categories"
|
||||
|
||||
CheckoutDBFile = "/users/libcom/checkout/checkout.db"
|
||||
CheckoutTableName = "checked_out"
|
||||
ReturnedTableName = "returned"
|
||||
)
|
||||
|
||||
func main() {
|
||||
catalogue, err := db.OpenCatalogue("catalogue.db")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
books, err := catalogue.GetAllBooks(context.Background())
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
for _, b := range books {
|
||||
fmt.Printf("%#v\n", b)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os/user"
|
||||
)
|
||||
|
||||
// map groupname -> pretty name
|
||||
var privilegedGroups = map[string]string{
|
||||
"office": "Office worker",
|
||||
"libcom": "Library Committee",
|
||||
}
|
||||
|
||||
// IsPrivilegedUser checks to see if the current user is privileged.
|
||||
func IsPrivilegedUser() (bool, error) {
|
||||
person, err := user.Current()
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("failed to get current user: %w", err)
|
||||
}
|
||||
|
||||
groups, err := person.GroupIds()
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("failed to get group ids: %w", err)
|
||||
}
|
||||
|
||||
for _, gid := range groups {
|
||||
group, err := user.LookupGroupId(gid)
|
||||
if err != nil {
|
||||
// Log error
|
||||
continue
|
||||
}
|
||||
|
||||
if _, ok := privilegedGroups[group.Name]; ok {
|
||||
return true, nil
|
||||
}
|
||||
}
|
||||
|
||||
return false, nil
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
CREATE TABLE IF NOT EXISTS books (
|
||||
id INTEGER PRIMARY KEY ASC AUTOINCREMENT,
|
||||
isbn INTEGER NOT NULL,
|
||||
lccn INTEGER DEFAULT NULL,
|
||||
title TEXT NOT NULL,
|
||||
subtitle TEXT DEFAULT NULL,
|
||||
authours TEXT NOT NULL,
|
||||
variant TEXT DEFAULT NULL,
|
||||
publisher TEXT NOT NULL,
|
||||
publish_year INTEGER NOT NULL,
|
||||
publish_month INTEGER NOT NULL,
|
||||
publish_location TEXT DEFAULT NULL,
|
||||
pages INTEGER NOT NULL,
|
||||
pagination TEXT DEFAULT NULL,
|
||||
bookweight TEXT DEFAULT NULL,
|
||||
last_updated TEXT NOT NULL DEFAULT (datetime()),
|
||||
deleted INTEGER NOT NULL DEFAULT 0,
|
||||
donated_by TEXT NOT NULL,
|
||||
|
||||
CHECK ((log10(isbn) >= 9 AND log10(isbn) <= 10) OR (log10(isbn) >= 12 AND log10(isbn) <= 13)) -- This is a check to see if the isbn is a canonical format (either isbn)
|
||||
CHECK (length(title) > 0)
|
||||
CHECK (publsh_year <= strftime('%Y') AND publish_year >= 0)
|
||||
CHECK (publish_month >= 1 AND publish_month <= 12)
|
||||
CHECK (pages > 0)
|
||||
CHECK (bookweight is NULL OR bookweight > 0)
|
||||
);
|
Loading…
Reference in New Issue