package database import ( "errors" "log" "os" "path/filepath" ) func (database *Database) GetRandomFiles(limit int64) ([]File, error) { database.singleThreadLock.Lock() defer database.singleThreadLock.Unlock() rows, err := database.stmt.getRandomFiles.Query(limit) if err != nil { return nil, err } defer rows.Close() files := make([]File, 0) for rows.Next() { file := File{ Db: database, } err = rows.Scan(&file.ID, &file.Folder_id, &file.Filename, &file.Foldername, &file.Filesize) if err != nil { return nil, err } files = append(files, file) } return files, nil } func (database *Database) GetRandomFilesWithTag(tagID, limit int64) ([]File, error) { database.singleThreadLock.Lock() defer database.singleThreadLock.Unlock() rows, err := database.stmt.getRandomFilesWithTag.Query(tagID, limit) if err != nil { return nil, err } defer rows.Close() files := make([]File, 0) for rows.Next() { file := File{ Db: database, } err = rows.Scan(&file.ID, &file.Folder_id, &file.Filename, &file.Foldername, &file.Filesize) if err != nil { return nil, err } files = append(files, file) } return files, nil } func (database *Database) GetFilesInFolder(folder_id int64, limit int64, offset int64) ([]File, string, error) { database.singleThreadLock.Lock() defer database.singleThreadLock.Unlock() rows, err := database.stmt.getFilesInFolder.Query(folder_id, limit, offset) if err != nil { return nil, "", err } defer rows.Close() files := make([]File, 0) folder := "" for rows.Next() { file := File{ Db: database, Folder_id: folder_id, } err = rows.Scan(&file.ID, &file.Filename, &file.Filesize, &file.Foldername, &folder) if err != nil { return nil, "", err } files = append(files, file) } return files, folder, nil } func (database *Database) SearchFolders(foldername string, limit int64, offset int64) ([]Folder, error) { database.singleThreadLock.Lock() defer database.singleThreadLock.Unlock() 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, } database.singleThreadLock.Lock() defer database.singleThreadLock.Unlock() err := database.stmt.getFile.QueryRow(id).Scan(&file.ID, &file.Folder_id, &file.Realname, &file.Filename, &file.Foldername, &file.Filesize) if err != nil { return nil, err } return file, nil } func (database *Database) ResetFiles() error { log.Println("[db] Reset files") 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 { log.Println("[db] Reset folders") 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, tagIDs []int64, userID int64) error { patternDict := make(map[string]bool) for _, v := range pattern { patternDict[v] = true } log.Println("[db] Walk", root, patternDict) tags := make([]*Tag, 0) for _, tagID := range tagIDs { tag, err := database.GetTag(tagID) if err != nil { return err } tags = append(tags, tag) } tx, err := database.sqlConn.Begin() if err != nil { log.Fatal(err) } insertFolderStmt := tx.Stmt(database.stmt.insertFolder) insertFileStmt := tx.Stmt(database.stmt.insertFile) putTagOnFileStmt := tx.Stmt(database.stmt.putTagOnFile) findFolderStmt := tx.Stmt(database.stmt.findFolder) err = 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 { return nil } // insert file and folder // fileID, err := database.Insert(path, info.Size()) // if err != nil { // return err // } var folderID int64 folder, filename := filepath.Split(path) err = findFolderStmt.QueryRow(folder).Scan(&folderID) if err != nil { result, err := insertFolderStmt.Exec(folder, filepath.Base(folder)) if err != nil { return err } folderID, err = result.LastInsertId() if err != nil { return err } } result, err := insertFileStmt.Exec(folderID, filename, filename, info.Size()) if err != nil { return err } fileID, err := result.LastInsertId() if err != nil { return err } for _, tag := range tags { _, err := putTagOnFileStmt.Exec(tag.ID, fileID, userID) if err != nil { return err } } return nil }) if err != nil { return err } return tx.Commit() } func (database *Database) GetFolder(folderId int64) (*Folder, error) { folder := &Folder{ Db: database, } database.singleThreadLock.Lock() defer database.singleThreadLock.Unlock() 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) { database.singleThreadLock.Lock() defer database.singleThreadLock.Unlock() 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, &file.Filesize) 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 database.singleThreadLock.Lock() defer database.singleThreadLock.Unlock() err := database.stmt.findFolder.QueryRow(folder).Scan(&id) if err != nil { return 0, err } return id, nil } func (database *Database) FindFile(folderId int64, filename string) (int64, error) { var id int64 database.singleThreadLock.Lock() defer database.singleThreadLock.Unlock() err := database.stmt.findFile.QueryRow(folderId, filename).Scan(&id) if err != nil { return 0, err } return id, nil } func (database *Database) InsertFolder(folder string) (int64, error) { database.singleThreadLock.Lock() defer database.singleThreadLock.Unlock() 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, filesize int64) (int64, error) { database.singleThreadLock.Lock() defer database.singleThreadLock.Unlock() result, err := database.stmt.insertFile.Exec(folderId, filename, filename, filesize) if err != nil { return 0, err } lastInsertId, err := result.LastInsertId() if err != nil { return 0, err } return lastInsertId, nil } func (database *Database) Insert(path string, filesize int64) (int64, error) { folder, filename := filepath.Split(path) folderId, err := database.FindFolder(folder) if err != nil { folderId, err = database.InsertFolder(folder) if err != nil { return 0, err } } // if file exists, skip it lastInsertId, err := database.FindFile(folderId, filename) if err == nil { return lastInsertId, nil } lastInsertId, err = database.InsertFile(folderId, filename, filesize) if err != nil { return 0, err } return lastInsertId, nil } func (database *Database) UpdateFoldername(folderId int64, foldername string) error { database.singleThreadLock.Lock() defer database.singleThreadLock.Unlock() _, err := database.stmt.updateFoldername.Exec(foldername, folderId) if err != nil { return err } return nil } func (database *Database) DeleteFile(fileId int64) error { database.singleThreadLock.Lock() defer database.singleThreadLock.Unlock() // begin transaction tx, err := database.sqlConn.Begin() if err != nil { return err } // delete file _, err = tx.Stmt(database.stmt.deleteFile).Exec(fileId) if err != nil { tx.Rollback() return err } // delete tag on file _, err = tx.Stmt(database.stmt.deleteFileReferenceInFileHasTag).Exec(fileId) if err != nil { tx.Rollback() return err } // delete reviews on file _, err = tx.Stmt(database.stmt.deleteFileReferenceInReviews).Exec(fileId) if err != nil { tx.Rollback() return err } // commit transaction err = tx.Commit() if err != nil { return err } return nil } func (database *Database) UpdateFilename(fileId int64, filename string) error { database.singleThreadLock.Lock() defer database.singleThreadLock.Unlock() _, err := database.stmt.updateFilename.Exec(filename, fileId) if err != nil { return err } return nil } func (database *Database) ResetFilename(fileId int64) error { database.singleThreadLock.Lock() defer database.singleThreadLock.Unlock() _, err := database.stmt.resetFilename.Exec(fileId) if err != nil { return err } return nil } func (database *Database) ResetFoldername(folderId int64) error { folder, err := database.GetFolder(folderId) if err != nil { return err } foldername := filepath.Base(folder.Folder) err = database.UpdateFoldername(folderId, foldername) if err != nil { return err } return nil }