后端初步完成
This commit is contained in:
5
go.mod
Normal file
5
go.mod
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
module msw-open-music
|
||||||
|
|
||||||
|
go 1.16
|
||||||
|
|
||||||
|
require github.com/mattn/go-sqlite3 v1.14.7 // indirect
|
||||||
2
go.sum
Normal file
2
go.sum
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
github.com/mattn/go-sqlite3 v1.14.7 h1:fxWBnXkxfM6sRiuH3bqJ4CfzZojMOLVc0UTsTglEghA=
|
||||||
|
github.com/mattn/go-sqlite3 v1.14.7/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
|
||||||
300
internal/pkg/api/api.go
Normal file
300
internal/pkg/api/api.go
Normal file
@@ -0,0 +1,300 @@
|
|||||||
|
package api
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
|
"io"
|
||||||
|
"log"
|
||||||
|
"msw-open-music/internal/pkg/database"
|
||||||
|
"net/http"
|
||||||
|
"os"
|
||||||
|
)
|
||||||
|
|
||||||
|
type API struct {
|
||||||
|
Db *database.Database
|
||||||
|
Server http.Server
|
||||||
|
token string
|
||||||
|
}
|
||||||
|
|
||||||
|
type Status struct {
|
||||||
|
Status string `json:"status,omitempty"`
|
||||||
|
}
|
||||||
|
var ok Status = Status{
|
||||||
|
Status: "OK",
|
||||||
|
}
|
||||||
|
|
||||||
|
type WalkRequest struct {
|
||||||
|
Token string `json:"token"`
|
||||||
|
Root string `json:"root"`
|
||||||
|
Pattern []string `json:"pattern"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type ResetRequest struct {
|
||||||
|
Token string `json:"token"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type SearchFilesRequest struct {
|
||||||
|
Filename string `json:"filename"`
|
||||||
|
Limit int64 `json:"limit"`
|
||||||
|
Offest int64 `json:"offest"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type SearchFoldersRequest struct {
|
||||||
|
Foldername string `json:"foldername"`
|
||||||
|
Limit int64 `json:"limit"`
|
||||||
|
Offest int64 `json:"offest"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type SearchFilesRespond struct {
|
||||||
|
Files []database.File `json:"files"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type SearchFoldersRespond struct {
|
||||||
|
Folders []database.Folder `json:"folders"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (api *API) CheckToken(token string) (error) {
|
||||||
|
if token != api.token {
|
||||||
|
return errors.New("token not matched")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (api *API) HandleTokenNotMatch(w http.ResponseWriter, r *http.Request) {
|
||||||
|
api.HandleErrorStringCode(w, r, "token not match", 403)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (api *API) HandleError(w http.ResponseWriter, r *http.Request, err error) {
|
||||||
|
api.HandleErrorString(w, r, err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (api *API) HandleErrorCode(w http.ResponseWriter, r *http.Request, err error, code int) {
|
||||||
|
api.HandleErrorStringCode(w, r, err.Error(), code)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (api *API) HandleErrorString(w http.ResponseWriter, r *http.Request, errorString string) {
|
||||||
|
api.HandleErrorStringCode(w, r, errorString, 500)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (api *API) HandleErrorStringCode(w http.ResponseWriter, r *http.Request, errorString string, code int) {
|
||||||
|
log.Println("Handle Error", errorString)
|
||||||
|
errStatus := &Status{
|
||||||
|
Status: errorString,
|
||||||
|
}
|
||||||
|
w.WriteHeader(code)
|
||||||
|
json.NewEncoder(w).Encode(errStatus)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (api *API) HandleReset(w http.ResponseWriter, r *http.Request) {
|
||||||
|
resetRequest := &ResetRequest{}
|
||||||
|
err := json.NewDecoder(r.Body).Decode(resetRequest)
|
||||||
|
if err != nil {
|
||||||
|
api.HandleError(w, r, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// check token
|
||||||
|
err = api.CheckToken(resetRequest.Token)
|
||||||
|
if err != nil {
|
||||||
|
api.HandleTokenNotMatch(w, r)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// reset
|
||||||
|
err = api.Db.ResetFiles()
|
||||||
|
if err != nil {
|
||||||
|
api.HandleError(w, r, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
err = api.Db.ResetFolder()
|
||||||
|
if err != nil {
|
||||||
|
api.HandleError(w, r, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
api.HandleStatus(w, r, "Database reseted")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (api *API) HandleWalk(w http.ResponseWriter, r *http.Request) {
|
||||||
|
walkRequest := &WalkRequest{}
|
||||||
|
err := json.NewDecoder(r.Body).Decode(walkRequest)
|
||||||
|
if err != nil {
|
||||||
|
api.HandleError(w, r, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// check token match
|
||||||
|
err = api.CheckToken(walkRequest.Token)
|
||||||
|
if err != nil {
|
||||||
|
api.HandleTokenNotMatch(w, r)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// check root empty
|
||||||
|
if walkRequest.Root == "" {
|
||||||
|
api.HandleErrorString(w, r, `key "root" can't be empty`)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// check pattern empty
|
||||||
|
if len(walkRequest.Pattern) == 0 {
|
||||||
|
api.HandleErrorString(w, r, `"[]pattern" can't be empty`)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// walk
|
||||||
|
err = api.Db.Walk(walkRequest.Root, walkRequest.Pattern)
|
||||||
|
if err != nil {
|
||||||
|
api.HandleError(w, r, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
api.HandleStatus(w, r, "Database udpated")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (api *API) HandleOK(w http.ResponseWriter, r *http.Request) {
|
||||||
|
json.NewEncoder(w).Encode(&ok)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (api *API) HandleStatus(w http.ResponseWriter, r *http.Request, status string) {
|
||||||
|
s := &Status{
|
||||||
|
Status: status,
|
||||||
|
}
|
||||||
|
|
||||||
|
json.NewEncoder(w).Encode(s)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (api *API) HandleSearchFiles(w http.ResponseWriter, r *http.Request) {
|
||||||
|
searchFilesRequest := &SearchFilesRequest{}
|
||||||
|
err := json.NewDecoder(r.Body).Decode(searchFilesRequest)
|
||||||
|
if err != nil {
|
||||||
|
api.HandleError(w, r, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// check empty
|
||||||
|
if searchFilesRequest.Filename == "" {
|
||||||
|
api.HandleErrorString(w, r, `"filename" can't be empty`)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if searchFilesRequest.Limit == 0 {
|
||||||
|
api.HandleErrorString(w, r, `"limit" can't be zero`)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
searchFilesRespond := &SearchFilesRespond{}
|
||||||
|
|
||||||
|
searchFilesRespond.Files, err = api.Db.SearchFiles(searchFilesRequest.Filename, searchFilesRequest.Limit, searchFilesRequest.Limit)
|
||||||
|
if err != nil {
|
||||||
|
api.HandleError(w, r, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
json.NewEncoder(w).Encode(searchFilesRespond)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (api *API) HandleSearchFolders(w http.ResponseWriter, r *http.Request) {
|
||||||
|
searchFoldersRequest := &SearchFoldersRequest{}
|
||||||
|
err := json.NewDecoder(r.Body).Decode(searchFoldersRequest)
|
||||||
|
if err != nil {
|
||||||
|
api.HandleError(w, r, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// check empty
|
||||||
|
if searchFoldersRequest.Foldername == "" {
|
||||||
|
api.HandleErrorString(w, r, `"foldername" can't be empty`)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if searchFoldersRequest.Limit == 0 {
|
||||||
|
api.HandleErrorString(w, r, `"limit" can't be zero`)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
searchFoldersRespond := &SearchFoldersRespond{}
|
||||||
|
|
||||||
|
searchFoldersRespond.Folders, err = api.Db.SearchFolders(searchFoldersRequest.Foldername, searchFoldersRequest.Limit, searchFoldersRequest.Limit)
|
||||||
|
if err != nil {
|
||||||
|
api.HandleError(w, r, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
json.NewEncoder(w).Encode(searchFoldersRespond)
|
||||||
|
}
|
||||||
|
|
||||||
|
type GetFileRequest struct {
|
||||||
|
ID int64 `json:"id"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (api *API) HandleGetFile(w http.ResponseWriter, r *http.Request) {
|
||||||
|
getFilesRequest := &GetFileRequest{
|
||||||
|
ID: -1,
|
||||||
|
}
|
||||||
|
|
||||||
|
err := json.NewDecoder(r.Body).Decode(getFilesRequest)
|
||||||
|
if err != nil {
|
||||||
|
api.HandleError(w, r, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// check empty
|
||||||
|
if getFilesRequest.ID < 0 {
|
||||||
|
api.HandleErrorString(w, r, `"id" can't be none or negative`)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
file, err := api.Db.GetFile(getFilesRequest.ID)
|
||||||
|
if err != nil {
|
||||||
|
api.HandleError(w, r, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
path, err := file.Path()
|
||||||
|
if err != nil {
|
||||||
|
api.HandleError(w, r, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
src, err := os.Open(path)
|
||||||
|
if err != nil {
|
||||||
|
api.HandleError(w, r, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer src.Close()
|
||||||
|
io.Copy(w, src)
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewAPI(dbName string, Addr string) (*API, error) {
|
||||||
|
var err error
|
||||||
|
|
||||||
|
db, err := database.NewDatabase(dbName)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
mux := http.NewServeMux()
|
||||||
|
apiMux := http.NewServeMux()
|
||||||
|
|
||||||
|
api := &API{
|
||||||
|
Db: db,
|
||||||
|
Server: http.Server{
|
||||||
|
Addr: Addr,
|
||||||
|
Handler: mux,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
// mount api
|
||||||
|
apiMux.HandleFunc("/hello", api.HandleOK)
|
||||||
|
apiMux.HandleFunc("/get_file", api.HandleGetFile)
|
||||||
|
apiMux.HandleFunc("/search_files", api.HandleSearchFiles)
|
||||||
|
apiMux.HandleFunc("/search_folders", api.HandleSearchFolders)
|
||||||
|
// below needs token
|
||||||
|
apiMux.HandleFunc("/walk", api.HandleWalk)
|
||||||
|
apiMux.HandleFunc("/reset", api.HandleReset)
|
||||||
|
|
||||||
|
mux.Handle("/api/v1/", http.StripPrefix("/api/v1", apiMux))
|
||||||
|
|
||||||
|
api.token = "pwd"
|
||||||
|
|
||||||
|
return api, nil
|
||||||
|
}
|
||||||
11
internal/pkg/api/api_test.go
Normal file
11
internal/pkg/api/api_test.go
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
package api
|
||||||
|
|
||||||
|
import "testing"
|
||||||
|
|
||||||
|
func TestAPI(t *testing.T) {
|
||||||
|
api, err := NewAPI("/tmp/test.sqlite3", ":8080")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err.Error())
|
||||||
|
}
|
||||||
|
t.Fatal(api.Server.ListenAndServe())
|
||||||
|
}
|
||||||
349
internal/pkg/database/database.go
Normal file
349
internal/pkg/database/database.go
Normal file
@@ -0,0 +1,349 @@
|
|||||||
|
package database
|
||||||
|
|
||||||
|
import (
|
||||||
|
"database/sql"
|
||||||
|
"errors"
|
||||||
|
"log"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
|
||||||
|
_ "github.com/mattn/go-sqlite3"
|
||||||
|
)
|
||||||
|
|
||||||
|
var initFilesTableQuery = `CREATE TABLE IF NOT EXISTS files (
|
||||||
|
id INTEGER PRIMARY KEY,
|
||||||
|
folder_id INTEGER NOT NULL,
|
||||||
|
filename TEXT NOT NULL
|
||||||
|
);`
|
||||||
|
var initFoldersTableQuery = `CREATE TABLE IF NOT EXISTS folders (
|
||||||
|
id INTEGER PRIMARY KEY,
|
||||||
|
folder TEXT NOT NULL,
|
||||||
|
foldername TEXT NOT NULL
|
||||||
|
);`
|
||||||
|
var insertFolderQuery = `INSERT INTO folders (folder, foldername) VALUES (?, ?);`
|
||||||
|
var findFolderQuery = `SELECT id FROM folders WHERE folder = ? LIMIT 1;`
|
||||||
|
var insertFileQuery = `INSERT INTO files (folder_id, filename) VALUES (?, ?);`
|
||||||
|
var searchFilesQuery = `SELECT files.id, files.folder_id, files.filename, folders.foldername FROM files JOIN folders ON files.folder_id = folders.id WHERE filename LIKE ? LIMIT ? OFFSET ?;`
|
||||||
|
var getFolderQuery = `SELECT folder FROM folders WHERE id = ? LIMIT 1;`
|
||||||
|
var dropFilesQuery = `DROP TABLE files;`
|
||||||
|
var dropFolderQuery = `DROP TABLE folders;`
|
||||||
|
var getFileQuery = `SELECT files.id, files.folder_id, files.filename, folders.foldername FROM files JOIN folders ON files.folder_id = folders.id WHERE files.id = ? LIMIT 1;`
|
||||||
|
var searchFoldersQuery = `SELECT id, folder, foldername FROM folders WHERE foldername LIKE ? LIMIT ? OFFSET ?;`
|
||||||
|
|
||||||
|
type Database struct {
|
||||||
|
sqlConn *sql.DB
|
||||||
|
stmt *Stmt
|
||||||
|
}
|
||||||
|
|
||||||
|
type Stmt struct {
|
||||||
|
initFilesTable *sql.Stmt
|
||||||
|
initFoldersTable *sql.Stmt
|
||||||
|
insertFolder *sql.Stmt
|
||||||
|
insertFile *sql.Stmt
|
||||||
|
findFolder *sql.Stmt
|
||||||
|
searchFiles *sql.Stmt
|
||||||
|
getFolder *sql.Stmt
|
||||||
|
dropFiles *sql.Stmt
|
||||||
|
dropFolder *sql.Stmt
|
||||||
|
getFile *sql.Stmt
|
||||||
|
searchFolders *sql.Stmt
|
||||||
|
}
|
||||||
|
|
||||||
|
type File struct {
|
||||||
|
Db *Database `json:"-"`
|
||||||
|
ID int64 `json:"id"`
|
||||||
|
Folder_id int64 `json:"folder_id"`
|
||||||
|
Foldername string `json:"foldername"`
|
||||||
|
Filename string `json:"filename"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Folder struct {
|
||||||
|
Db *Database `json:"-"`
|
||||||
|
ID int64 `json:"id"`
|
||||||
|
Folder string `json:"folder"`
|
||||||
|
Foldername string `json:"foldername"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (database *Database) SearchFolders(foldername string, limit int64, offset int64) ([]Folder, error) {
|
||||||
|
rows, err := database.stmt.searchFolders.Query("%"+foldername+"%", limit, offset)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.New("Error searching folders at query " + err.Error())
|
||||||
|
}
|
||||||
|
defer rows.Close()
|
||||||
|
folders := make([]Folder, 0)
|
||||||
|
for rows.Next() {
|
||||||
|
folder := Folder{
|
||||||
|
Db: database,
|
||||||
|
}
|
||||||
|
err = rows.Scan(&folder.ID, &folder.Folder, &folder.Foldername)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.New("Error scanning SearchFolders" + err.Error())
|
||||||
|
}
|
||||||
|
folders = append(folders, folder)
|
||||||
|
}
|
||||||
|
return folders, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (database *Database) GetFile(id int64) (*File, error) {
|
||||||
|
file := &File{
|
||||||
|
Db: database,
|
||||||
|
}
|
||||||
|
err := database.stmt.getFile.QueryRow(id).Scan(&file.ID, &file.Folder_id, &file.Filename, &file.Foldername)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return file, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (database *Database) ResetFiles() (error) {
|
||||||
|
var err error
|
||||||
|
_, err = database.stmt.dropFiles.Exec()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
_, err = database.stmt.initFilesTable.Exec()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (database *Database) ResetFolder() (error) {
|
||||||
|
var err error
|
||||||
|
_, err = database.stmt.dropFolder.Exec()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
_, err = database.stmt.initFoldersTable.Exec()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (database *Database) Walk(root string, pattern []string) (error) {
|
||||||
|
patternDict := make(map[string]bool)
|
||||||
|
for _, v := range pattern {
|
||||||
|
patternDict[v] = true
|
||||||
|
}
|
||||||
|
log.Println(patternDict)
|
||||||
|
return filepath.Walk(root, func (path string, info os.FileInfo, err error) (error) {
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if info.IsDir() {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// check pattern
|
||||||
|
ext := filepath.Ext(info.Name())
|
||||||
|
if _, ok := patternDict[ext]; !ok {
|
||||||
|
log.Println("False", ext, info.Name())
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
log.Println("True", ext, info.Name())
|
||||||
|
|
||||||
|
// insert file, folder will aut created
|
||||||
|
err = database.Insert(path)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *File) Path() (string, error) {
|
||||||
|
folder, err := f.Db.GetFolder(f.Folder_id)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
return filepath.Join(folder.Folder, f.Filename), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (database *Database) GetFolder(folderId int64) (*Folder, error) {
|
||||||
|
folder := &Folder{
|
||||||
|
Db: database,
|
||||||
|
}
|
||||||
|
err := database.stmt.getFolder.QueryRow(folderId).Scan(&folder.Folder)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return folder, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (database *Database) SearchFiles(filename string, limit int64, offset int64) ([]File, error) {
|
||||||
|
rows, err := database.stmt.searchFiles.Query("%"+filename+"%", limit, offset)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.New("Error searching files at query " + err.Error())
|
||||||
|
}
|
||||||
|
defer rows.Close()
|
||||||
|
files := make([]File, 0)
|
||||||
|
for rows.Next() {
|
||||||
|
var file File = File{
|
||||||
|
Db: database,
|
||||||
|
}
|
||||||
|
err = rows.Scan(&file.ID, &file.Folder_id, &file.Filename, &file.Foldername)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.New("Error scanning SearchFiles " + err.Error())
|
||||||
|
}
|
||||||
|
files = append(files, file)
|
||||||
|
}
|
||||||
|
if err = rows.Err(); err != nil {
|
||||||
|
return nil, errors.New("Error scanning SearchFiles exit without full result" + err.Error())
|
||||||
|
}
|
||||||
|
return files, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (database *Database) FindFolder(folder string) (int64, error) {
|
||||||
|
var id int64
|
||||||
|
err := database.stmt.findFolder.QueryRow(folder).Scan(&id)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
return id, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (database *Database) InsertFolder(folder string) (int64, error) {
|
||||||
|
result, err := database.stmt.insertFolder.Exec(folder, filepath.Base(folder))
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
lastInsertId, err := result.LastInsertId()
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
return lastInsertId, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (database *Database) InsertFile(folderId int64, filename string) (error) {
|
||||||
|
_, err := database.stmt.insertFile.Exec(folderId, filename)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (database *Database) Insert(path string) (error) {
|
||||||
|
folder, filename := filepath.Split(path)
|
||||||
|
folderId, err := database.FindFolder(folder)
|
||||||
|
if err != nil {
|
||||||
|
folderId, err = database.InsertFolder(folder)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
err = database.InsertFile(folderId, filename)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewPreparedStatement(sqlConn *sql.DB) (*Stmt, error) {
|
||||||
|
var err error
|
||||||
|
|
||||||
|
stmt := &Stmt{}
|
||||||
|
|
||||||
|
// init files table
|
||||||
|
stmt.initFilesTable, err = sqlConn.Prepare(initFilesTableQuery)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// init folders table
|
||||||
|
stmt.initFoldersTable, err = sqlConn.Prepare(initFoldersTableQuery)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// run init statement
|
||||||
|
_, err = stmt.initFilesTable.Exec()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
_, err = stmt.initFoldersTable.Exec()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// init insert folder statement
|
||||||
|
stmt.insertFolder, err = sqlConn.Prepare(insertFolderQuery)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// init findFolder statement
|
||||||
|
stmt.findFolder, err = sqlConn.Prepare(findFolderQuery)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// init insertFile stmt
|
||||||
|
stmt.insertFile, err = sqlConn.Prepare(insertFileQuery)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// init searchFile stmt
|
||||||
|
stmt.searchFiles, err = sqlConn.Prepare(searchFilesQuery)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// init getFolder stmt
|
||||||
|
stmt.getFolder, err = sqlConn.Prepare(getFolderQuery)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// init dropFolder stmt
|
||||||
|
stmt.dropFolder, err = sqlConn.Prepare(dropFolderQuery)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// init dropFiles stmt
|
||||||
|
stmt.dropFiles, err = sqlConn.Prepare(dropFilesQuery)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// init getFile stmt
|
||||||
|
stmt.getFile, err = sqlConn.Prepare(getFileQuery)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// init searchFolder stmt
|
||||||
|
stmt.searchFolders, err = sqlConn.Prepare(searchFoldersQuery)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return stmt, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewDatabase(dbName string) (*Database, error) {
|
||||||
|
var err error
|
||||||
|
|
||||||
|
// open database
|
||||||
|
sqlConn, err := sql.Open("sqlite3", dbName)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// prepare statement
|
||||||
|
stmt, err := NewPreparedStatement(sqlConn)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// new database
|
||||||
|
database := &Database{
|
||||||
|
sqlConn: sqlConn,
|
||||||
|
stmt: stmt,
|
||||||
|
}
|
||||||
|
|
||||||
|
return database, nil
|
||||||
|
}
|
||||||
55
internal/pkg/database/database_test.go
Normal file
55
internal/pkg/database/database_test.go
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
package database
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestDatabase(t *testing.T) {
|
||||||
|
db, err := NewDatabase("/tmp/test.sqlite3")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal("Error creating database" + err.Error())
|
||||||
|
}
|
||||||
|
t.Log("database open successfully")
|
||||||
|
|
||||||
|
_, err = db.InsertFolder("testfolder")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err.Error())
|
||||||
|
}
|
||||||
|
t.Log("insertFolders successfully")
|
||||||
|
|
||||||
|
id, err := db.FindFolder("testfolder")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err.Error())
|
||||||
|
}
|
||||||
|
t.Log("folder found", id)
|
||||||
|
|
||||||
|
err = db.Insert("/home/hmsy/go/bin/typora-image-ffmpeg")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
files, err := db.SearchFiles("ffmpeg", 100, 0)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err.Error())
|
||||||
|
}
|
||||||
|
t.Log(files)
|
||||||
|
|
||||||
|
file := files[0]
|
||||||
|
t.Log(file.Path())
|
||||||
|
|
||||||
|
err = db.Walk("/home/hmsy/dsa/")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
//err = db.ResetFiles()
|
||||||
|
//if err != nil {
|
||||||
|
// t.Fatal(err.Error())
|
||||||
|
//}
|
||||||
|
|
||||||
|
//err = db.ResetFolder()
|
||||||
|
//if err != nil {
|
||||||
|
// t.Fatal(err.Error())
|
||||||
|
//}
|
||||||
|
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user