package repository import ( "context" "database/sql" "fmt" "rag/file-system/internal/domain/model" ) type FileMetaRepoImpl struct { db *sql.DB } func NewFileMetaRepository(db *sql.DB) *FileMetaRepoImpl { return &FileMetaRepoImpl{db: db} } func (r *FileMetaRepoImpl) Create(ctx context.Context, file *model.FileMeta) error { _, err := r.db.ExecContext(ctx, `INSERT INTO files (id, folder_id, name, s3_key, s3_bucket, size, content_type, owner_id, created_at, updated_at) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)`, file.ID, file.FolderID, file.Name, file.S3Key, file.S3Bucket, file.Size, file.ContentType, file.OwnerID, file.CreatedAt, file.UpdatedAt) if err != nil { return fmt.Errorf("failed to create file meta: %w", err) } return nil } func (r *FileMetaRepoImpl) GetByID(ctx context.Context, id string) (*model.FileMeta, error) { var f model.FileMeta err := r.db.QueryRowContext(ctx, `SELECT id, folder_id, name, s3_key, s3_bucket, size, content_type, owner_id, created_at, updated_at FROM files WHERE id = $1`, id). Scan(&f.ID, &f.FolderID, &f.Name, &f.S3Key, &f.S3Bucket, &f.Size, &f.ContentType, &f.OwnerID, &f.CreatedAt, &f.UpdatedAt) if err == sql.ErrNoRows { return nil, nil } if err != nil { return nil, fmt.Errorf("failed to get file meta: %w", err) } return &f, nil } func (r *FileMetaRepoImpl) GetByFolder(ctx context.Context, folderID string) ([]model.FileMeta, error) { rows, err := r.db.QueryContext(ctx, `SELECT id, folder_id, name, s3_key, s3_bucket, size, content_type, owner_id, created_at, updated_at FROM files WHERE folder_id = $1 ORDER BY name`, folderID) if err != nil { return nil, fmt.Errorf("failed to get files by folder: %w", err) } defer rows.Close() return scanFiles(rows) } func (r *FileMetaRepoImpl) Move(ctx context.Context, fileID string, targetFolderID string, ownerID string) error { result, err := r.db.ExecContext(ctx, `UPDATE files SET folder_id = $1, updated_at = now() WHERE id = $2 AND owner_id = $3`, targetFolderID, fileID, ownerID) if err != nil { return fmt.Errorf("failed to move file: %w", err) } rows, _ := result.RowsAffected() if rows == 0 { return fmt.Errorf("file not found or not owned by user") } return nil } func (r *FileMetaRepoImpl) Delete(ctx context.Context, id string, ownerID string) error { result, err := r.db.ExecContext(ctx, `DELETE FROM files WHERE id = $1 AND owner_id = $2`, id, ownerID) if err != nil { return fmt.Errorf("failed to delete file meta: %w", err) } rows, _ := result.RowsAffected() if rows == 0 { return fmt.Errorf("file not found or not owned by user") } return nil } func scanFiles(rows *sql.Rows) ([]model.FileMeta, error) { var files []model.FileMeta for rows.Next() { var f model.FileMeta if err := rows.Scan(&f.ID, &f.FolderID, &f.Name, &f.S3Key, &f.S3Bucket, &f.Size, &f.ContentType, &f.OwnerID, &f.CreatedAt, &f.UpdatedAt); err != nil { return nil, fmt.Errorf("failed to scan file: %w", err) } files = append(files, f) } return files, rows.Err() }