refactor: Flatten directory structure
Move project files from uzdb/ subdirectory to root directory for cleaner project structure.
Changes:
- Move frontend/ to root
- Move internal/ to root
- Move build/ to root
- Move all config files (go.mod, wails.json, etc.) to root
- Remove redundant uzdb/ subdirectory nesting
Project structure is now:
├── frontend/ # React application
├── internal/ # Go backend
├── build/ # Wails build assets
├── doc/ # Design documentation
├── main.go # Entry point
└── ...
🤖 Generated with Qoder
This commit is contained in:
236
internal/services/query.go
Normal file
236
internal/services/query.go
Normal file
@@ -0,0 +1,236 @@
|
||||
package services
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"go.uber.org/zap"
|
||||
"gorm.io/gorm"
|
||||
|
||||
"uzdb/internal/config"
|
||||
"uzdb/internal/models"
|
||||
)
|
||||
|
||||
// QueryService handles query-related operations
|
||||
type QueryService struct {
|
||||
db *gorm.DB
|
||||
}
|
||||
|
||||
// NewQueryService creates a new query service
|
||||
func NewQueryService(db *gorm.DB) *QueryService {
|
||||
return &QueryService{
|
||||
db: db,
|
||||
}
|
||||
}
|
||||
|
||||
// GetQueryHistory returns query history with pagination
|
||||
func (s *QueryService) GetQueryHistory(
|
||||
ctx context.Context,
|
||||
connectionID string,
|
||||
page, pageSize int,
|
||||
) ([]models.QueryHistory, int64, error) {
|
||||
if page <= 0 {
|
||||
page = 1
|
||||
}
|
||||
if pageSize <= 0 || pageSize > 100 {
|
||||
pageSize = 20
|
||||
}
|
||||
|
||||
var total int64
|
||||
var history []models.QueryHistory
|
||||
|
||||
query := s.db.WithContext(ctx).Model(&models.QueryHistory{})
|
||||
|
||||
if connectionID != "" {
|
||||
query = query.Where("connection_id = ?", connectionID)
|
||||
}
|
||||
|
||||
// Get total count
|
||||
if err := query.Count(&total).Error; err != nil {
|
||||
return nil, 0, fmt.Errorf("failed to count history: %w", err)
|
||||
}
|
||||
|
||||
// Get paginated results
|
||||
offset := (page - 1) * pageSize
|
||||
if err := query.Order("executed_at DESC").
|
||||
Offset(offset).
|
||||
Limit(pageSize).
|
||||
Find(&history).Error; err != nil {
|
||||
return nil, 0, fmt.Errorf("failed to get history: %w", err)
|
||||
}
|
||||
|
||||
config.GetLogger().Debug("retrieved query history",
|
||||
zap.String("connection_id", connectionID),
|
||||
zap.Int("page", page),
|
||||
zap.Int("page_size", pageSize),
|
||||
zap.Int64("total", total))
|
||||
|
||||
return history, total, nil
|
||||
}
|
||||
|
||||
// GetSavedQueries returns all saved queries
|
||||
func (s *QueryService) GetSavedQueries(
|
||||
ctx context.Context,
|
||||
connectionID string,
|
||||
) ([]models.SavedQuery, error) {
|
||||
var queries []models.SavedQuery
|
||||
|
||||
query := s.db.WithContext(ctx)
|
||||
if connectionID != "" {
|
||||
query = query.Where("connection_id = ?", connectionID)
|
||||
}
|
||||
|
||||
result := query.Order("name ASC").Find(&queries)
|
||||
if result.Error != nil {
|
||||
return nil, fmt.Errorf("failed to get saved queries: %w", result.Error)
|
||||
}
|
||||
|
||||
return queries, nil
|
||||
}
|
||||
|
||||
// GetSavedQueryByID returns a saved query by ID
|
||||
func (s *QueryService) GetSavedQueryByID(ctx context.Context, id uint) (*models.SavedQuery, error) {
|
||||
var query models.SavedQuery
|
||||
|
||||
result := s.db.WithContext(ctx).First(&query, "id = ?", id)
|
||||
if result.Error != nil {
|
||||
if result.Error == gorm.ErrRecordNotFound {
|
||||
return nil, models.ErrNotFound
|
||||
}
|
||||
return nil, fmt.Errorf("failed to get saved query: %w", result.Error)
|
||||
}
|
||||
|
||||
return &query, nil
|
||||
}
|
||||
|
||||
// CreateSavedQuery creates a new saved query
|
||||
func (s *QueryService) CreateSavedQuery(
|
||||
ctx context.Context,
|
||||
req *models.CreateSavedQueryRequest,
|
||||
) (*models.SavedQuery, error) {
|
||||
query := &models.SavedQuery{
|
||||
Name: req.Name,
|
||||
Description: req.Description,
|
||||
SQL: req.SQL,
|
||||
ConnectionID: req.ConnectionID,
|
||||
Tags: req.Tags,
|
||||
}
|
||||
|
||||
result := s.db.WithContext(ctx).Create(query)
|
||||
if result.Error != nil {
|
||||
return nil, fmt.Errorf("failed to create saved query: %w", result.Error)
|
||||
}
|
||||
|
||||
config.GetLogger().Info("saved query created",
|
||||
zap.Uint("id", query.ID),
|
||||
zap.String("name", query.Name))
|
||||
|
||||
return query, nil
|
||||
}
|
||||
|
||||
// UpdateSavedQuery updates an existing saved query
|
||||
func (s *QueryService) UpdateSavedQuery(
|
||||
ctx context.Context,
|
||||
id uint,
|
||||
req *models.UpdateSavedQueryRequest,
|
||||
) (*models.SavedQuery, error) {
|
||||
// Get existing query
|
||||
existing, err := s.GetSavedQueryByID(ctx, id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Update fields
|
||||
if req.Name != "" {
|
||||
existing.Name = req.Name
|
||||
}
|
||||
if req.Description != "" {
|
||||
existing.Description = req.Description
|
||||
}
|
||||
if req.SQL != "" {
|
||||
existing.SQL = req.SQL
|
||||
}
|
||||
if req.ConnectionID != "" {
|
||||
existing.ConnectionID = req.ConnectionID
|
||||
}
|
||||
if req.Tags != "" {
|
||||
existing.Tags = req.Tags
|
||||
}
|
||||
|
||||
result := s.db.WithContext(ctx).Save(existing)
|
||||
if result.Error != nil {
|
||||
return nil, fmt.Errorf("failed to update saved query: %w", result.Error)
|
||||
}
|
||||
|
||||
config.GetLogger().Info("saved query updated",
|
||||
zap.Uint("id", id),
|
||||
zap.String("name", existing.Name))
|
||||
|
||||
return existing, nil
|
||||
}
|
||||
|
||||
// DeleteSavedQuery deletes a saved query
|
||||
func (s *QueryService) DeleteSavedQuery(ctx context.Context, id uint) error {
|
||||
// Check if exists
|
||||
if _, err := s.GetSavedQueryByID(ctx, id); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
result := s.db.WithContext(ctx).Delete(&models.SavedQuery{}, "id = ?", id)
|
||||
if result.Error != nil {
|
||||
return fmt.Errorf("failed to delete saved query: %w", result.Error)
|
||||
}
|
||||
|
||||
config.GetLogger().Info("saved query deleted", zap.Uint("id", id))
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// ClearOldHistory clears query history older than specified days
|
||||
func (s *QueryService) ClearOldHistory(ctx context.Context, days int) (int64, error) {
|
||||
if days <= 0 {
|
||||
days = 30 // Default to 30 days
|
||||
}
|
||||
|
||||
cutoffTime := time.Now().AddDate(0, 0, -days)
|
||||
|
||||
result := s.db.WithContext(ctx).
|
||||
Where("executed_at < ?", cutoffTime).
|
||||
Delete(&models.QueryHistory{})
|
||||
|
||||
if result.Error != nil {
|
||||
return 0, fmt.Errorf("failed to clear old history: %w", result.Error)
|
||||
}
|
||||
|
||||
config.GetLogger().Info("cleared old query history",
|
||||
zap.Int64("deleted_count", result.RowsAffected),
|
||||
zap.Int("days", days))
|
||||
|
||||
return result.RowsAffected, nil
|
||||
}
|
||||
|
||||
// GetRecentQueries returns recent queries for quick access
|
||||
func (s *QueryService) GetRecentQueries(
|
||||
ctx context.Context,
|
||||
connectionID string,
|
||||
limit int,
|
||||
) ([]models.QueryHistory, error) {
|
||||
if limit <= 0 || limit > 50 {
|
||||
limit = 10
|
||||
}
|
||||
|
||||
var queries []models.QueryHistory
|
||||
|
||||
query := s.db.WithContext(ctx).
|
||||
Where("connection_id = ? AND success = ?", connectionID, true).
|
||||
Order("executed_at DESC").
|
||||
Limit(limit).
|
||||
Find(&queries)
|
||||
|
||||
if query.Error != nil {
|
||||
return nil, fmt.Errorf("failed to get recent queries: %w", query.Error)
|
||||
}
|
||||
|
||||
return queries, nil
|
||||
}
|
||||
Reference in New Issue
Block a user