mirror of https://github.com/jlelse/GoBlog
You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
52 lines
1.3 KiB
Go
52 lines
1.3 KiB
Go
package main
|
|
|
|
import (
|
|
"database/sql"
|
|
"errors"
|
|
|
|
"github.com/mattn/go-sqlite3"
|
|
)
|
|
|
|
func (db *database) shortenPath(p string) (string, error) {
|
|
if p == "" {
|
|
return "", errors.New("empty path")
|
|
}
|
|
spi, err, _ := db.sp.Do(p, func() (any, error) {
|
|
// Check if already cached
|
|
if spi, ok := db.spc.Get(p); ok {
|
|
return spi.(string), nil
|
|
}
|
|
// Insert in case it isn't shortened yet
|
|
_, err := db.Exec(`
|
|
insert or rollback into shortpath (id, path)
|
|
values (
|
|
-- next available id (reuse skipped ids due to bug)
|
|
(select min(id) + 1 from (select id from shortpath union all select 0) where id + 1 not in (select id from shortpath)),
|
|
@path
|
|
)`, sql.Named("path", p))
|
|
if err != nil {
|
|
if no, ok := err.(sqlite3.Error); !ok || sqlite3.ErrNo(no.ExtendedCode) != sqlite3.ErrNo(sqlite3.ErrConstraintUnique) {
|
|
// Some other error than unique constraint violation because path is already shortened
|
|
return nil, err
|
|
}
|
|
}
|
|
// Query short path
|
|
row, err := db.QueryRow("select printf('/s/%x', id) from shortpath where path = @path", sql.Named("path", p))
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
var sp string
|
|
err = row.Scan(&sp)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
// Cache result
|
|
db.spc.Set(p, sp, 1)
|
|
return sp, nil
|
|
})
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
return spi.(string), nil
|
|
}
|