diff --git a/sqliteutil/README.md b/sqliteutil/README.md index eb59767..84dd630 100644 --- a/sqliteutil/README.md +++ b/sqliteutil/README.md @@ -2,9 +2,7 @@ ## Transactions -Simplify postgres transactions using `WithTx` for serializable transactions, -or `WithTxDefault` for the default isolation level. Use the `SerialTxRunner` -type to get automatic retries of serialization errors. +Simplify transactions using `WithTx`. ## Migrations @@ -20,26 +18,3 @@ func init() { Migrate(db, migrations) // Check the error, of course. } ``` - -## Testing - -In order to test this packge, we need to create a test user and database: - -``` -sudo su postgres -psql - -CREATE DATABASE test; -CREATE USER test WITH ENCRYPTED PASSWORD 'test'; -GRANT ALL PRIVILEGES ON DATABASE test TO test; - -use test - -GRANT ALL ON SCHEMA public TO test; -``` - -Check that you can connect via the command line: - -``` -psql -h 127.0.0.1 -U test --password test -``` diff --git a/webutil/formscanner.go b/webutil/formscanner.go new file mode 100644 index 0000000..0d50cb3 --- /dev/null +++ b/webutil/formscanner.go @@ -0,0 +1,111 @@ +package webutil + +import ( + "errors" + "net/url" + "strconv" +) + +var ErrUnsupportedType = errors.New("unsupported type") + +type FormScanner struct { + form url.Values + err error +} + +func NewFormScanner(form url.Values) *FormScanner { + return &FormScanner{form: form} +} + +func (s *FormScanner) Scan(name string, val any) *FormScanner { + if s.err != nil { + return s + } + + switch v := val.(type) { + case *bool: + *v = s.form.Has(name) + case *string: + *v = s.form.Get(name) + case *int: + if i, err := strconv.ParseInt(s.form.Get(name), 10, 64); err != nil { + s.err = err + } else { + *v = int(i) + } + case *int8: + if i, err := strconv.ParseInt(s.form.Get(name), 10, 8); err != nil { + s.err = err + } else { + *v = int8(i) + } + case *int16: + if i, err := strconv.ParseInt(s.form.Get(name), 10, 16); err != nil { + s.err = err + } else { + *v = int16(i) + } + case *int32: + if i, err := strconv.ParseInt(s.form.Get(name), 10, 32); err != nil { + s.err = err + } else { + *v = int32(i) + } + case *int64: + if i, err := strconv.ParseInt(s.form.Get(name), 10, 64); err != nil { + s.err = err + } else { + *v = int64(i) + } + case *uint: + if i, err := strconv.ParseUint(s.form.Get(name), 10, 64); err != nil { + s.err = err + } else { + *v = uint(i) + } + case *uint8: + if i, err := strconv.ParseUint(s.form.Get(name), 10, 8); err != nil { + s.err = err + } else { + *v = uint8(i) + } + case *uint16: + if i, err := strconv.ParseUint(s.form.Get(name), 10, 16); err != nil { + s.err = err + } else { + *v = uint16(i) + } + case *uint32: + if i, err := strconv.ParseUint(s.form.Get(name), 10, 32); err != nil { + s.err = err + } else { + *v = uint32(i) + } + case *uint64: + if i, err := strconv.ParseUint(s.form.Get(name), 10, 64); err != nil { + s.err = err + } else { + *v = uint64(i) + } + case *float32: + if f, err := strconv.ParseFloat(s.form.Get(name), 32); err != nil { + s.err = err + } else { + *v = float32(f) + } + case *float64: + if f, err := strconv.ParseFloat(s.form.Get(name), 64); err != nil { + s.err = err + } else { + *v = float64(f) + } + default: + s.err = ErrUnsupportedType + } + + return s +} + +func (s *FormScanner) Error() error { + return s.err +}