Implements a complete Dolt storage backend that mirrors the SQLite implementation with MySQL-compatible syntax and adds version control capabilities. Key features: - Full Storage interface implementation (~50 methods) - Version control operations: commit, push, pull, branch, merge, checkout - History queries via AS OF and dolt_history_* tables - Cell-level merge instead of line-level JSONL merge - SQL injection protection with input validation Bug fixes applied during implementation: - Added missing quality_score, work_type, source_system to scanIssue - Fixed Status() to properly parse boolean staged column - Added validation to CreateIssues (was missing in batch create) - Made RenameDependencyPrefix transactional - Expanded GetIssueHistory to return more complete data Test coverage: 17 tests covering CRUD, dependencies, labels, search, comments, events, statistics, and SQL injection protection. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
111 lines
3.0 KiB
Go
111 lines
3.0 KiB
Go
package dolt
|
|
|
|
import (
|
|
"context"
|
|
"database/sql"
|
|
"fmt"
|
|
"strings"
|
|
)
|
|
|
|
// SetConfig sets a configuration value
|
|
func (s *DoltStore) SetConfig(ctx context.Context, key, value string) error {
|
|
_, err := s.db.ExecContext(ctx, `
|
|
INSERT INTO config (` + "`key`" + `, value) VALUES (?, ?)
|
|
ON DUPLICATE KEY UPDATE value = VALUES(value)
|
|
`, key, value)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to set config %s: %w", key, err)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// GetConfig retrieves a configuration value
|
|
func (s *DoltStore) GetConfig(ctx context.Context, key string) (string, error) {
|
|
var value string
|
|
err := s.db.QueryRowContext(ctx, "SELECT value FROM config WHERE `key` = ?", key).Scan(&value)
|
|
if err == sql.ErrNoRows {
|
|
return "", nil
|
|
}
|
|
if err != nil {
|
|
return "", fmt.Errorf("failed to get config %s: %w", key, err)
|
|
}
|
|
return value, nil
|
|
}
|
|
|
|
// GetAllConfig retrieves all configuration values
|
|
func (s *DoltStore) GetAllConfig(ctx context.Context) (map[string]string, error) {
|
|
rows, err := s.db.QueryContext(ctx, "SELECT `key`, value FROM config")
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to get all config: %w", err)
|
|
}
|
|
defer rows.Close()
|
|
|
|
config := make(map[string]string)
|
|
for rows.Next() {
|
|
var key, value string
|
|
if err := rows.Scan(&key, &value); err != nil {
|
|
return nil, fmt.Errorf("failed to scan config: %w", err)
|
|
}
|
|
config[key] = value
|
|
}
|
|
return config, rows.Err()
|
|
}
|
|
|
|
// DeleteConfig removes a configuration value
|
|
func (s *DoltStore) DeleteConfig(ctx context.Context, key string) error {
|
|
_, err := s.db.ExecContext(ctx, "DELETE FROM config WHERE `key` = ?", key)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to delete config %s: %w", key, err)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// SetMetadata sets a metadata value
|
|
func (s *DoltStore) SetMetadata(ctx context.Context, key, value string) error {
|
|
_, err := s.db.ExecContext(ctx, `
|
|
INSERT INTO metadata (` + "`key`" + `, value) VALUES (?, ?)
|
|
ON DUPLICATE KEY UPDATE value = VALUES(value)
|
|
`, key, value)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to set metadata %s: %w", key, err)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// GetMetadata retrieves a metadata value
|
|
func (s *DoltStore) GetMetadata(ctx context.Context, key string) (string, error) {
|
|
var value string
|
|
err := s.db.QueryRowContext(ctx, "SELECT value FROM metadata WHERE `key` = ?", key).Scan(&value)
|
|
if err == sql.ErrNoRows {
|
|
return "", nil
|
|
}
|
|
if err != nil {
|
|
return "", fmt.Errorf("failed to get metadata %s: %w", key, err)
|
|
}
|
|
return value, nil
|
|
}
|
|
|
|
// GetCustomStatuses returns custom status values from config
|
|
func (s *DoltStore) GetCustomStatuses(ctx context.Context) ([]string, error) {
|
|
value, err := s.GetConfig(ctx, "status.custom")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if value == "" {
|
|
return nil, nil
|
|
}
|
|
return strings.Split(value, ","), nil
|
|
}
|
|
|
|
// GetCustomTypes returns custom issue type values from config
|
|
func (s *DoltStore) GetCustomTypes(ctx context.Context) ([]string, error) {
|
|
value, err := s.GetConfig(ctx, "types.custom")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if value == "" {
|
|
return nil, nil
|
|
}
|
|
return strings.Split(value, ","), nil
|
|
}
|