mysql

package
v0.0.0-...-14a125a Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 21, 2025 License: MIT Imports: 14 Imported by: 0

README

MySQL Package / MySQL 패키지

Extreme simplicity MySQL/MariaDB client with zero-downtime credential rotation.

무중단 자격 증명 순환을 갖춘 극도로 간단한 MySQL/MariaDB 클라이언트.

Features / 특징

Core Features / 핵심 기능

Extreme Simplicity: 30 lines → 2 lines of code / 극도의 간결함: 30줄 → 2줄 코드 ✅ Auto Everything: Connection management, retry, cleanup / 모든 것 자동: 연결 관리, 재시도, 정리 ✅ Zero-Downtime Credential Rotation: Multiple connection pools with rolling rotation / 무중단 자격 증명 순환 ✅ SQL-Like API: Close to actual SQL syntax / SQL 문법에 가까운 API ✅ No defer rows.Close(): Automatic resource cleanup / 자동 리소스 정리 ✅ Auto Retry: Transient errors are retried automatically / 일시적 에러 자동 재시도 ✅ Health Check: Automatic connection monitoring / 자동 연결 모니터링

Advanced Features / 고급 기능

Batch Operations: BatchInsert, BatchUpdate, BatchDelete, BatchSelectByIDs / 배치 작업 ✅ Upsert Operations: Upsert, UpsertBatch, Replace (ON DUPLICATE KEY) / Upsert 작업 ✅ Pagination: Easy pagination with metadata (Paginate, PaginateQuery) / 페이지네이션 ✅ Soft Delete: SoftDelete, Restore, SelectAllWithTrashed / 소프트 삭제 ✅ Query Statistics: Performance monitoring, slow query logging / 쿼리 통계 ✅ Pool Metrics: Connection pool health monitoring / 풀 메트릭 ✅ Schema Inspector: Database schema introspection / 스키마 검사 ✅ Migration Helpers: CreateTable, AddColumn, AddIndex, etc. / 마이그레이션 헬퍼 ✅ CSV Export/Import: Export and import data in CSV format / CSV 내보내기/가져오기

Installation / 설치

go get github.com/arkd0ng/go-utils/database/mysql

Quick Start / 빠른 시작

Basic Usage / 기본 사용법
package main

import (
    "context"
    "fmt"
    "log"

    "github.com/arkd0ng/go-utils/database/mysql"
)

func main() {
    // Create client / 클라이언트 생성
    db, err := mysql.New(
        mysql.WithDSN("user:password@tcp(localhost:3306)/dbname?parseTime=true"),
    )
    if err != nil {
        log.Fatal(err)
    }
    defer db.Close()

    ctx := context.Background()

    // Insert / 삽입
    result, err := db.Insert(ctx, "users", map[string]interface{}{
        "name":  "John Doe",
        "email": "john@example.com",
        "age":   30,
    })
    if err != nil {
        log.Fatal(err)
    }

    userID, _ := result.LastInsertId()
    fmt.Printf("Inserted user with ID: %d\n", userID)

    // Select all / 모두 선택
    users, err := db.SelectAll(ctx, "users", "age > ?", 18)
    if err != nil {
        log.Fatal(err)
    }

    for _, user := range users {
        fmt.Printf("User: %+v\n", user)
    }

    // Update / 업데이트
    _, err = db.Update(ctx, "users",
        map[string]interface{}{"age": 31},
        "id = ?", userID)
    if err != nil {
        log.Fatal(err)
    }

    // Delete / 삭제
    _, err = db.Delete(ctx, "users", "id = ?", userID)
    if err != nil {
        log.Fatal(err)
    }
}
Dynamic Credentials (Vault, AWS Secrets Manager, etc.) / 동적 자격 증명
// User-provided function to get DSN / DSN을 가져오는 사용자 제공 함수
func getDSN() (string, error) {
    // Fetch from Vault, file, environment variable, etc.
    // Vault, 파일, 환경 변수 등에서 가져오기
    user := os.Getenv("DB_USER")
    pass := os.Getenv("DB_PASS")
    return fmt.Sprintf("%s:%s@tcp(localhost:3306)/mydb", user, pass), nil
}

// Create client with credential rotation / 자격 증명 순환으로 클라이언트 생성
db, err := mysql.New(
    mysql.WithCredentialRefresh(
        getDSN,        // User function / 사용자 함수
        3,             // 3 connection pools / 3개 연결 풀
        1*time.Hour,   // Rotate one per hour / 1시간마다 하나씩 교체
    ),
    mysql.WithLogger(logger),
)

// Result: Zero-downtime credential rotation!
// 결과: 무중단 자격 증명 순환!
// - Time 0:00: [Pool0, Pool1, Pool2] (Credential A)
// - Time 1:00: [Pool0, Pool1, Pool2-NEW] (Credential B)
// - Time 2:00: [Pool0, Pool1-NEW, Pool2-NEW] (Credential B)
//   → Credential A expires, but Pool1 & Pool2 still work!

API Reference / API 참조

Simple API / 간단한 API
SelectAll - Select all rows / 모든 행 선택
// Select all / 모두 선택
users, err := db.SelectAll(ctx, "users")

// With condition / 조건 포함
users, err := db.SelectAll(ctx, "users", "age > ?", 18)
adults, err := db.SelectAll(ctx, "users", "age > ? AND city = ?", 18, "Seoul")
SelectOne - Select single row / 단일 행 선택
user, err := db.SelectOne(ctx, "users", "id = ?", 123)
Insert - Insert new row / 새 행 삽입
result, err := db.Insert(ctx, "users", map[string]interface{}{
    "name":  "John",
    "email": "john@example.com",
    "age":   30,
})
Update - Update rows / 행 업데이트
result, err := db.Update(ctx, "users",
    map[string]interface{}{"name": "Jane", "age": 31},
    "id = ?", 123)
Delete - Delete rows / 행 삭제
result, err := db.Delete(ctx, "users", "id = ?", 123)
Count - Count rows / 행 개수
count, err := db.Count(ctx, "users")
count, err := db.Count(ctx, "users", "age > ?", 18)
Exists - Check existence / 존재 확인
exists, err := db.Exists(ctx, "users", "email = ?", "john@example.com")
Transaction API / 트랜잭션 API
err := db.Transaction(ctx, func(tx *mysql.Tx) error {
    // Insert user / 사용자 삽입
    result, err := tx.Insert(ctx, "users", map[string]interface{}{
        "name": "John",
        "email": "john@example.com",
    })
    if err != nil {
        return err // Auto rollback / 자동 롤백
    }

    userID, _ := result.LastInsertId()

    // Insert profile / 프로필 삽입
    _, err = tx.Insert(ctx, "profiles", map[string]interface{}{
        "user_id": userID,
        "bio": "Hello world",
    })
    if err != nil {
        return err // Auto rollback / 자동 롤백
    }

    return nil // Auto commit / 자동 커밋
})
Raw SQL API / Raw SQL API
// Query / 쿼리
rows, err := db.Query(ctx, "SELECT * FROM users WHERE age > ?", 18)

// QueryRow / 단일 행 쿼리
row := db.QueryRow(ctx, "SELECT * FROM users WHERE id = ?", 123)

// Exec / 실행
result, err := db.Exec(ctx, "UPDATE users SET name = ? WHERE id = ?", "John", 123)

Configuration Options / 설정 옵션

db, err := mysql.New(
    // Connection / 연결
    mysql.WithDSN("user:pass@tcp(localhost:3306)/db"),
    mysql.WithMaxOpenConns(50),
    mysql.WithMaxIdleConns(10),
    mysql.WithConnMaxLifetime(5*time.Minute),

    // Credential Rotation / 자격 증명 순환
    mysql.WithCredentialRefresh(getDSN, 3, 1*time.Hour),

    // Timeout / 타임아웃
    mysql.WithConnectTimeout(10*time.Second),
    mysql.WithQueryTimeout(30*time.Second),

    // Retry / 재시도
    mysql.WithMaxRetries(3),
    mysql.WithRetryDelay(100*time.Millisecond),

    // Logging / 로깅
    mysql.WithLogger(logger),
    mysql.WithQueryLogging(true),
    mysql.WithSlowQueryLogging(true),
    mysql.WithSlowQueryThreshold(1*time.Second),

    // Health Check / 헬스 체크
    mysql.WithHealthCheck(true),
    mysql.WithHealthCheckInterval(30*time.Second),

    // Security / 보안
    mysql.WithTLS(tlsConfig),
)

Why This Package? / 왜 이 패키지인가?

Standard database/sql / 표준 database/sql
// ❌ 30+ lines of boilerplate code / 30줄 이상의 보일러플레이트 코드
db, err := sql.Open("mysql", dsn)
if err != nil {
    return err
}
defer db.Close()

if err := db.Ping(); err != nil {
    // Manual reconnect logic / 수동 재연결 로직
}

rows, err := db.Query("SELECT * FROM users WHERE age > ?", 18)
if err != nil {
    return err
}
defer rows.Close() // ← Must remember! / 기억해야 함!

var users []User
for rows.Next() {
    var u User
    err := rows.Scan(&u.ID, &u.Name, &u.Email, &u.Age)
    if err != nil {
        return err
    }
    users = append(users, u)
}
if err := rows.Err(); err != nil {
    return err
}
This Package / 이 패키지
// ✅ 2 lines / 2줄
db, _ := mysql.New(mysql.WithDSN(dsn))
users, _ := db.SelectAll(ctx, "users", "age > ?", 18)

// That's it! Everything else is automatic:
// 끝! 나머지는 모두 자동:
// ✓ Auto connection management / 자동 연결 관리
// ✓ Auto reconnect / 자동 재연결
// ✓ Auto retry / 자동 재시도
// ✓ Auto rows.Close() / 자동 rows.Close()
// ✓ Auto error handling / 자동 에러 처리

Advanced Features / 고급 기능

Batch Operations / 배치 작업

Perform bulk operations for better performance / 더 나은 성능을 위한 대량 작업:

// BatchInsert - Insert multiple rows in one query / 한 쿼리로 여러 행 삽입
data := []map[string]interface{}{
    {"name": "John", "age": 30, "email": "john@example.com"},
    {"name": "Jane", "age": 25, "email": "jane@example.com"},
    {"name": "Bob", "age": 35, "email": "bob@example.com"},
}
result, err := db.BatchInsert(ctx, "users", data)

// BatchUpdate - Update multiple rows with different values / 다른 값으로 여러 행 업데이트
updates := []map[string]interface{}{
    {"id": 1, "name": "John Updated", "age": 31},
    {"id": 2, "name": "Jane Updated", "age": 26},
}
results, err := db.BatchUpdate(ctx, "users", updates, "id")

// BatchDelete - Delete multiple rows by IDs / ID로 여러 행 삭제
ids := []interface{}{1, 2, 3, 4, 5}
result, err := db.BatchDelete(ctx, "users", "id", ids)

// BatchSelectByIDs - Select multiple rows by IDs / ID로 여러 행 선택
ids := []interface{}{1, 2, 3}
users, err := db.BatchSelectByIDs(ctx, "users", "id", ids)
Upsert Operations / Upsert 작업

Insert or update with ON DUPLICATE KEY UPDATE / ON DUPLICATE KEY UPDATE로 삽입 또는 업데이트:

// Upsert - Insert or update on duplicate key / 중복 키 시 삽입 또는 업데이트
data := map[string]interface{}{
    "email": "john@example.com",  // Unique key / 고유 키
    "name": "John Doe",
    "age": 30,
}
updateColumns := []string{"name", "age"}  // Columns to update on duplicate / 중복 시 업데이트할 컬럼
result, err := db.Upsert(ctx, "users", data, updateColumns)

// UpsertBatch - Batch upsert / 배치 Upsert
data := []map[string]interface{}{
    {"email": "john@example.com", "name": "John", "age": 30},
    {"email": "jane@example.com", "name": "Jane", "age": 25},
}
result, err := db.UpsertBatch(ctx, "users", data, []string{"name", "age"})

// Replace - Replace row (DELETE + INSERT) / 행 교체 (DELETE + INSERT)
result, err := db.Replace(ctx, "users", map[string]interface{}{
    "id": 1,
    "name": "John Replaced",
    "email": "john@example.com",
})
Pagination / 페이지네이션

Easy pagination with metadata / 메타데이터와 함께 쉬운 페이지네이션:

// Paginate - Simple pagination / 간단한 페이지네이션
result, err := db.Paginate(ctx, "users", 1, 10)  // Page 1, 10 items per page
fmt.Printf("Page %d of %d (Total: %d rows)\n", result.Page, result.TotalPages, result.TotalRows)
fmt.Printf("HasNext: %v, HasPrev: %v\n", result.HasNext, result.HasPrev)

// With conditions and ordering / 조건 및 정렬 포함
result, err := db.Paginate(ctx, "users", 2, 20,
    "age > ?", 18,  // WHERE condition / WHERE 조건
    mysql.WithOrderBy("created_at DESC"))

// PaginateQuery - Paginate custom query / 커스텀 쿼리 페이지네이션
query := "SELECT * FROM users WHERE age > ?"
result, err := db.PaginateQuery(ctx, query, 1, 10, 18)
Soft Delete / 소프트 삭제

Soft delete with automatic restoration / 자동 복원과 함께 소프트 삭제:

// SoftDelete - Mark as deleted / 삭제로 표시
result, err := db.SoftDelete(ctx, "users", "id = ?", 1)

// Restore - Restore soft-deleted row / 소프트 삭제된 행 복원
result, err := db.Restore(ctx, "users", "id = ?", 1)

// SelectAllWithTrashed - Include soft-deleted rows / 소프트 삭제된 행 포함
users, err := db.SelectAllWithTrashed(ctx, "users")

// SelectAllOnlyTrashed - Only soft-deleted rows / 소프트 삭제된 행만
users, err := db.SelectAllOnlyTrashed(ctx, "users")

// PermanentDelete - Permanently delete / 영구 삭제
result, err := db.PermanentDelete(ctx, "users", "id = ?", 1)

Note: Soft delete requires a deleted_at column (TIMESTAMP NULL) in your table.

참고: 소프트 삭제는 테이블에 deleted_at 컬럼(TIMESTAMP NULL)이 필요합니다.

Query Statistics / 쿼리 통계

Monitor query performance / 쿼리 성능 모니터링:

// GetQueryStats - Get query statistics / 쿼리 통계 가져오기
stats := db.GetQueryStats()
fmt.Printf("Total Queries: %d\n", stats.TotalQueries)
fmt.Printf("Average Duration: %v\n", stats.AverageDuration)
fmt.Printf("Slowest Query: %v (%s)\n", stats.SlowestQuery, stats.SlowestQuerySQL)

// EnableSlowQueryLog - Enable slow query logging / 느린 쿼리 로깅 활성화
db.EnableSlowQueryLog(1 * time.Second)  // Log queries slower than 1s

// GetSlowQueries - Get slow query list / 느린 쿼리 목록 가져오기
slowQueries := db.GetSlowQueries()
for _, q := range slowQueries {
    fmt.Printf("Slow query: %s (took %v)\n", q.SQL, q.Duration)
}

// ResetQueryStats - Reset statistics / 통계 초기화
db.ResetQueryStats()
Pool Metrics / 풀 메트릭

Monitor connection pool health / 연결 풀 상태 모니터링:

// GetPoolMetrics - Get connection pool metrics / 연결 풀 메트릭 가져오기
metrics := db.GetPoolMetrics()
fmt.Printf("Open Connections: %d / %d\n", metrics.OpenConnections, metrics.MaxOpenConnections)
fmt.Printf("Idle Connections: %d / %d\n", metrics.IdleConnections, metrics.MaxIdleConnections)
fmt.Printf("Wait Count: %d (Duration: %v)\n", metrics.WaitCount, metrics.WaitDuration)

// GetPoolHealthInfo - Get pool health status / 풀 상태 정보 가져오기
health := db.GetPoolHealthInfo()
fmt.Printf("Status: %s\n", health.Status)
fmt.Printf("Healthy: %v\n", health.Healthy)
fmt.Printf("Message: %s\n", health.Message)

// GetConnectionUtilization - Get connection utilization percentage / 연결 사용률 가져오기
utilization := db.GetConnectionUtilization()
fmt.Printf("Utilization: %.2f%%\n", utilization)
Schema Inspector / 스키마 검사

Inspect database schema / 데이터베이스 스키마 검사:

// GetTables - List all tables / 모든 테이블 목록
tables, err := db.GetTables(ctx)
for _, table := range tables {
    fmt.Printf("Table: %s\n", table)
}

// GetColumns - Get table columns / 테이블 컬럼 가져오기
columns, err := db.GetColumns(ctx, "users")
for _, col := range columns {
    fmt.Printf("%s: %s (Nullable: %v)\n", col.Name, col.Type, col.Nullable)
}

// GetIndexes - Get table indexes / 테이블 인덱스 가져오기
indexes, err := db.GetIndexes(ctx, "users")
for _, idx := range indexes {
    fmt.Printf("Index: %s on %v (Unique: %v)\n", idx.Name, idx.Columns, idx.Unique)
}

// TableExists - Check if table exists / 테이블 존재 확인
exists, err := db.TableExists(ctx, "users")

// InspectTable - Get complete table info / 전체 테이블 정보 가져오기
info, err := db.InspectTable(ctx, "users")
fmt.Printf("Table: %s (%d columns, %d indexes)\n",
    info.Name, len(info.Columns), len(info.Indexes))
Migration Helpers / 마이그레이션 헬퍼

Database migration utilities / 데이터베이스 마이그레이션 유틸리티:

// CreateTable - Create table with schema / 스키마로 테이블 생성
schema := map[string]string{
    "id": "INT AUTO_INCREMENT PRIMARY KEY",
    "name": "VARCHAR(100) NOT NULL",
    "email": "VARCHAR(255) UNIQUE",
    "created_at": "TIMESTAMP DEFAULT CURRENT_TIMESTAMP",
}
err := db.CreateTable(ctx, "users", schema)

// DropTable - Drop table / 테이블 삭제
err := db.DropTable(ctx, "users")

// TruncateTable - Truncate table / 테이블 초기화
err := db.TruncateTable(ctx, "users")

// AddColumn - Add column to table / 테이블에 컬럼 추가
err := db.AddColumn(ctx, "users", "phone", "VARCHAR(20)")

// DropColumn - Drop column from table / 테이블에서 컬럼 삭제
err := db.DropColumn(ctx, "users", "phone")

// AddIndex - Add index to table / 테이블에 인덱스 추가
err := db.AddIndex(ctx, "users", "idx_email", []string{"email"}, false)

// AddForeignKey - Add foreign key constraint / 외래 키 제약 조건 추가
err := db.AddForeignKey(ctx, "profiles", "fk_user", "user_id", "users", "id",
    mysql.FKOnDeleteCascade, mysql.FKOnUpdateCascade)
CSV Export/Import / CSV 내보내기/가져오기

Export and import data in CSV format / CSV 형식으로 데이터 내보내기 및 가져오기:

// ExportTableToCSV - Export entire table to CSV / 전체 테이블을 CSV로 내보내기
err := db.ExportTableToCSV(ctx, "users", "users.csv")

// ExportQueryToCSV - Export query results to CSV / 쿼리 결과를 CSV로 내보내기
query := "SELECT id, name, email FROM users WHERE age > ?"
err := db.ExportQueryToCSV(ctx, query, "active_users.csv", 18)

// ImportFromCSV - Import CSV to table / CSV를 테이블로 가져오기
rowsImported, err := db.ImportFromCSV(ctx, "users.csv", "users")
fmt.Printf("Imported %d rows\n", rowsImported)

// Import with column mapping / 컬럼 매핑과 함께 가져오기
columnMap := map[string]string{
    "FullName": "name",
    "EmailAddress": "email",
}
rowsImported, err := db.ImportFromCSV(ctx, "users.csv", "users", mysql.WithColumnMapping(columnMap))

Best Practices / 모범 사례

  1. Always use context: Pass context for timeout control / 타임아웃 제어를 위해 항상 context 전달
  2. Use transactions for multi-step operations: Ensure atomicity / 다단계 작업에는 트랜잭션 사용
  3. Enable query logging in development: Debug slow queries / 개발 중 쿼리 로깅 활성화
  4. Use credential rotation for production: Enhanced security / 프로덕션에는 자격 증명 순환 사용
  5. Monitor health checks: Track connection status / 헬스 체크 모니터링
  6. Use batch operations: For bulk inserts/updates/deletes / 대량 삽입/업데이트/삭제에는 배치 작업 사용
  7. Monitor query statistics: Identify slow queries / 느린 쿼리 식별
  8. Use pagination for large datasets: Avoid loading all rows / 모든 행 로드 방지
  9. Use soft delete when needed: Preserve data history / 데이터 히스토리 보존
  10. Check pool metrics: Monitor connection pool health / 연결 풀 상태 모니터링

License / 라이선스

MIT

Contributing / 기여

Contributions are welcome! Please follow the project's coding standards.

기여를 환영합니다! 프로젝트의 코딩 표준을 따라주세요.

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	ErrConnectionFailed  = errors.New("database connection failed")
	ErrQueryFailed       = errors.New("query execution failed")
	ErrTransactionFailed = errors.New("transaction failed")
	ErrTimeout           = errors.New("operation timeout")
	ErrClosed            = errors.New("database connection closed")
	ErrInvalidDSN        = errors.New("invalid DSN format")
	ErrNoRows            = errors.New("no rows in result set")
	ErrInvalidConfig     = errors.New("invalid configuration")
)

Predefined errors 사전 정의된 에러

Functions

This section is empty.

Types

type BatchUpdateItem

type BatchUpdateItem struct {
	// Data holds column/value pairs to set during the update / Data에는 갱신 시 설정할 컬럼과 값의 쌍이 저장됩니다.
	Data map[string]interface{}
	// ConditionAndArgs keeps the WHERE clause string followed by placeholder arguments / ConditionAndArgs에는 WHERE 절 문자열과 해당 플레이스홀더 인자가 순서대로 들어 있습니다.
	ConditionAndArgs []interface{}
}

BatchUpdateItem describes one UPDATE statement entry consisting of the SET map and the WHERE clause / BatchUpdateItem은 SET에 사용할 데이터 맵과 WHERE 절 조건으로 구성된 단일 UPDATE 항목을 표현합니다.

type CSVExportOptions

type CSVExportOptions struct {
	// Include column headers in the first row
	// 첫 번째 행에 컬럼 헤더 포함
	IncludeHeaders bool

	// Delimiter character (default: comma)
	// 구분 문자 (기본값: 쉼표)
	Delimiter rune

	// Columns to export (empty means all)
	// 내보낼 컬럼 (비어 있으면 전체)
	Columns []string

	// WHERE clause filter (without WHERE keyword)
	// WHERE 절 필터 (WHERE 키워드 제외)
	Where string

	// Arguments for WHERE clause
	// WHERE 절 인자
	WhereArgs []interface{}

	// ORDER BY clause
	// ORDER BY 절
	OrderBy string

	// LIMIT number of rows
	// 행 수 제한
	Limit int

	// NULL value representation
	// NULL 값 표현
	NullValue string
}

CSVExportOptions represents options for CSV export CSVExportOptions는 CSV 내보내기 옵션을 나타냅니다

func DefaultCSVExportOptions

func DefaultCSVExportOptions() CSVExportOptions

DefaultCSVExportOptions returns default export options DefaultCSVExportOptions는 기본 내보내기 옵션을 반환합니다

type CSVImportOptions

type CSVImportOptions struct {
	// First row contains headers
	// 첫 번째 행에 헤더 포함
	HasHeaders bool

	// Delimiter character (default: comma)
	// 구분 문자 (기본값: 쉼표)
	Delimiter rune

	// Columns to import (must match CSV column order if no headers)
	// 가져올 컬럼 (헤더가 없으면 CSV 컬럼 순서와 일치해야 함)
	Columns []string

	// Skip first N rows (after headers if present)
	// 첫 N개 행 건너뛰기 (헤더가 있는 경우 헤더 다음)
	SkipRows int

	// Batch size for bulk insert
	// 대량 삽입을 위한 배치 크기
	BatchSize int

	// If true, ignore duplicate key errors
	// true면 중복 키 에러 무시
	IgnoreDuplicates bool

	// If true, replace existing rows on duplicate keys
	// true면 중복 키에서 기존 행 교체
	ReplaceOnDuplicate bool

	// NULL value representation in CSV
	// CSV의 NULL 값 표현
	NullValue string
}

CSVImportOptions represents options for CSV import CSVImportOptions는 CSV 가져오기 옵션을 나타냅니다

func DefaultCSVImportOptions

func DefaultCSVImportOptions() CSVImportOptions

DefaultCSVImportOptions returns default import options DefaultCSVImportOptions는 기본 가져오기 옵션을 반환합니다

type Client

type Client struct {
	// contains filtered or unexported fields
}

Client represents a MySQL database client with auto-management features Client는 자동 관리 기능을 갖춘 MySQL 데이터베이스 클라이언트를 나타냅니다

func New

func New(opts ...Option) (*Client, error)

New creates a new MySQL client with the given options New는 주어진 옵션으로 새 MySQL 클라이언트를 생성합니다

Example (static credentials) 예제 (정적 자격 증명):

db, err := mysql.New(
    mysql.WithDSN("user:pass@tcp(localhost:3306)/dbname"),
)

Example (dynamic credentials) 예제 (동적 자격 증명):

db, err := mysql.New(
    mysql.WithCredentialRefresh(
        func() (string, error) {
            return "user:pass@tcp(localhost:3306)/db", nil
        },
        3,            // 3 connection pools
        1*time.Hour,  // Rotate one per hour
    ),
    mysql.WithLogger(logger),
)

func (*Client) AddColumn

func (c *Client) AddColumn(ctx context.Context, table string, column string, definition string) error

AddColumn adds a new column to a table AddColumn은 테이블에 새 컬럼을 추가합니다

Example 예제:

ctx := context.Background()
err := client.AddColumn(ctx, "users", "phone", "VARCHAR(20)")
if err != nil {
    log.Fatal(err)
}

Example with position 위치 지정 예제:

// Add column after 'email' 'email' 뒤에 컬럼 추가

err := client.AddColumn(ctx, "users", "phone", "VARCHAR(20) AFTER email")

// Add column at the beginning 처음에 컬럼 추가

err := client.AddColumn(ctx, "users", "status", "ENUM('active','inactive') FIRST")

func (*Client) AddForeignKey

func (c *Client) AddForeignKey(ctx context.Context, table string, constraintName string,
	column string, refTable string, refColumn string, onDelete string, onUpdate string) error

AddForeignKey adds a foreign key constraint to a table AddForeignKey는 테이블에 외래 키 제약 조건을 추가합니다

Example 예제:

ctx := context.Background()
err := client.AddForeignKey(ctx,
    "orders",           // table
    "fk_user",          // constraint name
    "user_id",          // column
    "users",            // referenced table
    "id",               // referenced column
    "CASCADE",          // on delete
    "CASCADE")          // on update
if err != nil {
    log.Fatal(err)
}

func (*Client) AddIndex

func (c *Client) AddIndex(ctx context.Context, table string, indexName string, columns []string, unique bool) error

AddIndex adds an index to a table AddIndex는 테이블에 인덱스를 추가합니다

Example 예제:

ctx := context.Background() Add simple index 단순 인덱스 추가

err := client.AddIndex(ctx, "users", "idx_email", []string{"email"}, false)

// Add unique index 유니크 인덱스 추가

err := client.AddIndex(ctx, "users", "idx_username", []string{"username"}, true)

// Add composite index 복합 인덱스 추가

err := client.AddIndex(ctx, "orders", "idx_user_date",
    []string{"user_id", "created_at"}, false)

func (*Client) AlterTableCharset

func (c *Client) AlterTableCharset(ctx context.Context, table string, charset string, collate string) error

AlterTableCharset changes the character set and collation of a table AlterTableCharset는 테이블의 문자 집합과 collation을 변경합니다

Example 예제:

ctx := context.Background()
err := client.AlterTableCharset(ctx, "users", "utf8mb4", "utf8mb4_unicode_ci")
if err != nil {
    log.Fatal(err)
}

func (*Client) AlterTableEngine

func (c *Client) AlterTableEngine(ctx context.Context, table string, engine string) error

AlterTableEngine changes the storage engine of a table AlterTableEngine은 테이블의 스토리지 엔진을 변경합니다

Example 예제:

ctx := context.Background()
err := client.AlterTableEngine(ctx, "users", "InnoDB")
if err != nil {
    log.Fatal(err)
}

func (*Client) BatchDelete

func (c *Client) BatchDelete(ctx context.Context, table string, idColumn string, ids []interface{}) (sql.Result, error)

BatchDelete removes every row whose identifier appears in ids by issuing a single DELETE ... IN (...) clause / BatchDelete는 IDs에 포함된 식별자를 가진 모든 행을 DELETE ... IN (...) 구문 한 번으로 제거합니다.

Example / 예제:

ids := []interface{}{1, 2, 3, 4, 5}                           // 삭제할 ID 목록
result, err := db.BatchDelete(ctx, "users", "id", ids)         // BatchDelete 실행

func (*Client) BatchInsert

func (c *Client) BatchInsert(ctx context.Context, table string, data []map[string]interface{}) (sql.Result, error)

BatchInsert collapses multiple rows into a single INSERT statement while preserving column order and retrying transient faults / BatchInsert는 여러 행을 하나의 INSERT 문으로 묶되 컬럼 순서를 유지하고 일시적 장애가 발생하면 재시도합니다.

Example / 예제:

data := []map[string]interface{}{{"name": "John", "age": 30, "email": "john@example.com"}} // 예제 데이터 행
result, err := db.BatchInsert(ctx, "users", data)                                         // BatchInsert 호출

The generated SQL looks like: / 생성되는 SQL 예시는 다음과 같습니다:

INSERT INTO users (name, age, email) VALUES (?,?,?),(?,?,?),(?,?,?) // 생성되는 SQL 예시

func (*Client) BatchSelectByIDs

func (c *Client) BatchSelectByIDs(ctx context.Context, table string, idColumn string, ids []interface{}) ([]map[string]interface{}, error)

BatchSelectByIDs fetches every row whose identifier is listed, returning the results as a slice of column maps / BatchSelectByIDs는 전달된 식별자 목록에 해당하는 모든 행을 조회하여 컬럼 맵 슬라이스로 반환합니다.

Example / 예제:

ids := []interface{}{1, 2, 3, 4, 5}                        // 조회할 ID 목록
users, err := db.BatchSelectByIDs(ctx, "users", "id", ids) // BatchSelectByIDs 실행

func (*Client) BatchUpdate

func (c *Client) BatchUpdate(ctx context.Context, table string, updates []BatchUpdateItem) error

BatchUpdate applies every supplied BatchUpdateItem inside a single transaction to guarantee atomic writes / BatchUpdate는 전달된 모든 BatchUpdateItem을 하나의 트랜잭션 안에서 실행하여 원자적 쓰기를 보장합니다.

Example / 예제:

updates := []mysql.BatchUpdateItem{ // 업데이트 항목 슬라이스
    {
        Data: map[string]interface{}{"age": 31},       // 첫 번째 SET 값
        ConditionAndArgs: []interface{}{"id = ?", 1}, // 첫 번째 WHERE 조건
    },
    {
        Data: map[string]interface{}{"age": 26},       // 두 번째 SET 값
        ConditionAndArgs: []interface{}{"id = ?", 2}, // 두 번째 WHERE 조건
    },
}
err := db.BatchUpdate(ctx, "users", updates) // BatchUpdate 호출

func (*Client) Begin

func (c *Client) Begin(ctx context.Context) (*Tx, error)

Begin starts a new transaction Begin은 새 트랜잭션을 시작합니다

func (*Client) Close

func (c *Client) Close() error

Close closes all database connections and stops background tasks Close는 모든 데이터베이스 연결을 닫고 백그라운드 작업을 중지합니다

func (*Client) CopyTable

func (c *Client) CopyTable(ctx context.Context, sourceTable string, destTable string, withData bool) error

CopyTable creates a copy of a table with a new name CopyTable은 새 이름으로 테이블의 복사본을 생성합니다

Example 예제:

ctx := context.Background() Copy structure and data 구조와 데이터 복사

err := client.CopyTable(ctx, "users", "users_backup", true)

// Copy only structure 구조만 복사

err := client.CopyTable(ctx, "users", "users_template", false)

func (*Client) Count

func (c *Client) Count(table string, conditionAndArgs ...interface{}) (int64, error)

Count counts rows in a table with optional conditions Count는 선택적 조건으로 테이블의 행 수를 계산합니다

Example 예제:

count, err := db.Count("users")
count, err := db.Count("users", "age > ?", 18)

func (*Client) CountContext

func (c *Client) CountContext(ctx context.Context, table string, conditionAndArgs ...interface{}) (int64, error)

CountContext counts rows in a table with optional conditions CountContext는 선택적 조건으로 테이블의 행 수를 계산합니다

func (*Client) CountOnlyTrashed

func (c *Client) CountOnlyTrashed(ctx context.Context, table string, conditionAndArgs ...interface{}) (int64, error)

CountOnlyTrashed counts only soft-deleted rows CountOnlyTrashed는 소프트 삭제된 행만 계산합니다

func (*Client) CountWithTrashed

func (c *Client) CountWithTrashed(ctx context.Context, table string, conditionAndArgs ...interface{}) (int64, error)

CountWithTrashed counts all rows including soft-deleted ones CountWithTrashed는 소프트 삭제된 것을 포함하여 모든 행을 계산합니다

func (*Client) CreateTable

func (c *Client) CreateTable(ctx context.Context, table string, schema string) error

CreateTable creates a new table with the given schema CreateTable은 주어진 스키마로 새 테이블을 생성합니다

Example 예제:

ctx := context.Background()
schema := `
    id INT AUTO_INCREMENT PRIMARY KEY,
    name VARCHAR(255) NOT NULL,
    email VARCHAR(255) UNIQUE NOT NULL,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
`
err := client.CreateTable(ctx, "users", schema)
if err != nil {
    log.Fatal(err)
}

Example with table options 테이블 옵션 예제:

schema := `
    id BIGINT AUTO_INCREMENT PRIMARY KEY,
    data JSON,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    INDEX idx_created (created_at)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci`
err := client.CreateTable(ctx, "events", schema)

func (*Client) CreateTableIfNotExists

func (c *Client) CreateTableIfNotExists(ctx context.Context, table string, schema string) error

CreateTableIfNotExists creates a table only if it doesn't already exist CreateTableIfNotExists는 테이블이 존재하지 않는 경우에만 생성합니다

Example 예제:

ctx := context.Background()
schema := `
    id INT AUTO_INCREMENT PRIMARY KEY,
    name VARCHAR(255) NOT NULL
`
err := client.CreateTableIfNotExists(ctx, "users", schema)
if err != nil {
    log.Fatal(err)
}

func (*Client) Delete

func (c *Client) Delete(table string, conditionAndArgs ...interface{}) (sql.Result, error)

Delete deletes rows from a table Delete는 테이블에서 행을 삭제합니다

Example 예제:

result, err := db.Delete("users", "id = ?", 123)

func (*Client) DeleteContext

func (c *Client) DeleteContext(ctx context.Context, table string, conditionAndArgs ...interface{}) (sql.Result, error)

DeleteContext deletes rows from a table DeleteContext는 테이블에서 행을 삭제합니다

func (*Client) DisableQueryStats

func (c *Client) DisableQueryStats()

DisableQueryStats disables query statistics tracking DisableQueryStats는 쿼리 통계 추적을 비활성화합니다

Existing statistics are preserved but no new queries will be tracked. 기존 통계는 보존되지만 새 쿼리는 추적되지 않습니다.

Example 예제:

// Temporarily disable stats tracking 일시적으로 통계 추적 비활성화

client.DisableQueryStats()
// ... perform operations ...
client.EnableQueryStats()

func (*Client) DropColumn

func (c *Client) DropColumn(ctx context.Context, table string, column string) error

DropColumn removes a column from a table DropColumn은 테이블에서 컬럼을 제거합니다

Example 예제:

ctx := context.Background()
err := client.DropColumn(ctx, "users", "old_field")
if err != nil {
    log.Fatal(err)
}

func (*Client) DropForeignKey

func (c *Client) DropForeignKey(ctx context.Context, table string, constraintName string) error

DropForeignKey removes a foreign key constraint from a table DropForeignKey는 테이블에서 외래 키 제약 조건을 제거합니다

Example 예제:

ctx := context.Background()
err := client.DropForeignKey(ctx, "orders", "fk_user")
if err != nil {
    log.Fatal(err)
}

func (*Client) DropIndex

func (c *Client) DropIndex(ctx context.Context, table string, indexName string) error

DropIndex removes an index from a table DropIndex는 테이블에서 인덱스를 제거합니다

Example 예제:

ctx := context.Background()
err := client.DropIndex(ctx, "users", "idx_email")
if err != nil {
    log.Fatal(err)
}

func (*Client) DropTable

func (c *Client) DropTable(ctx context.Context, table string, ifExists bool) error

DropTable drops a table from the database DropTable은 데이터베이스에서 테이블을 삭제합니다

Example 예제:

ctx := context.Background()
err := client.DropTable(ctx, "old_users", false)
if err != nil {
    log.Fatal(err)
}

func (*Client) EnableQueryStats

func (c *Client) EnableQueryStats()

EnableQueryStats enables query statistics tracking EnableQueryStats는 쿼리 통계 추적을 활성화합니다

This must be called before any queries are executed to track statistics. 통계를 추적하려면 쿼리가 실행되기 전에 호출해야 합니다.

Example 예제:

client, _ := mysql.New(mysql.WithDSN("..."))
client.EnableQueryStats()

// Execute queries... 쿼리 실행...

// Check statistics 통계 확인

stats := client.GetQueryStats()
fmt.Printf("Total queries: %d\n", stats.TotalQueries)

func (*Client) EnableSlowQueryLog

func (c *Client) EnableSlowQueryLog(threshold time.Duration, handler SlowQueryHandler)

EnableSlowQueryLog enables slow query logging with a threshold and optional handler EnableSlowQueryLog는 임계값과 선택적 핸들러로 느린 쿼리 로깅을 활성화합니다

The handler function is called asynchronously for each slow query. 핸들러 함수는 각 느린 쿼리에 대해 비동기적으로 호출됩니다.

Example 예제:

// Log queries that take longer than 1 second 1초 이상 걸리는 쿼리 로깅

client.EnableSlowQueryLog(1*time.Second, func(info mysql.SlowQueryInfo) {
    log.Printf("Slow query detected: %s (took %v)", info.Query, info.Duration)
})

Example with custom handling 커스텀 처리 예제:

client.EnableSlowQueryLog(500*time.Millisecond, func(info mysql.SlowQueryInfo) { Send to monitoring system 모니터링 시스템으로 전송

metrics.RecordSlowQuery(info.Query, info.Duration)

// Log with details 세부 정보와 함께 로깅

    logger.Warn("Slow query",
        "query", info.Query,
        "args", info.Args,
        "duration", info.Duration,
        "timestamp", info.Timestamp)
})

func (*Client) Exec

func (c *Client) Exec(ctx context.Context, query string, args ...interface{}) (sql.Result, error)

Exec executes a query that doesn't return rows Exec는 행을 반환하지 않는 쿼리를 실행합니다

func (*Client) Exists

func (c *Client) Exists(table string, conditionAndArgs ...interface{}) (bool, error)

Exists checks if at least one row exists with the given conditions Exists는 주어진 조건으로 최소한 하나의 행이 존재하는지 확인합니다

Example 예제:

exists, err := db.Exists("users", "email = ?", "john@example.com")

func (*Client) ExistsContext

func (c *Client) ExistsContext(ctx context.Context, table string, conditionAndArgs ...interface{}) (bool, error)

ExistsContext checks if at least one row exists with the given conditions ExistsContext는 주어진 조건으로 최소한 하나의 행이 존재하는지 확인합니다

func (*Client) ExportQueryToCSV

func (c *Client) ExportQueryToCSV(ctx context.Context, query string, args []interface{},
	filePath string, opts CSVExportOptions) error

ExportQueryToCSV exports the result of a query to a CSV file ExportQueryToCSV는 쿼리 결과를 CSV 파일로 내보냅니다

Example 예제:

ctx := context.Background()
query := `
    SELECT u.id, u.name, COUNT(o.id) as order_count
    FROM users u
    LEFT JOIN orders o ON u.id = o.user_id
    GROUP BY u.id, u.name
    HAVING order_count > 10
`
opts := mysql.DefaultCSVExportOptions()
err := client.ExportQueryToCSV(ctx, query, nil, "/path/to/report.csv", opts)
if err != nil {
    log.Fatal(err)
}

func (*Client) ExportTableToCSV

func (c *Client) ExportTableToCSV(ctx context.Context, table string, filePath string, opts CSVExportOptions) error

ExportTableToCSV exports a table to a CSV file ExportTableToCSV는 테이블을 CSV 파일로 내보냅니다

Example 예제:

ctx := context.Background()
opts := mysql.DefaultCSVExportOptions()
opts.Columns = []string{"id", "name", "email"}
opts.Where = "created_at >= ?"
opts.WhereArgs = []interface{}{"2024-01-01"}

err := client.ExportTableToCSV(ctx, "users", "/path/to/users.csv", opts)
if err != nil {
    log.Fatal(err)
}

func (*Client) GetColumns

func (c *Client) GetColumns(ctx context.Context, table string) ([]ColumnInfo, error)

GetColumns returns information about all columns in a table GetColumns는 테이블의 모든 컬럼에 대한 정보를 반환합니다

Example 예제:

ctx := context.Background()
columns, err := client.GetColumns(ctx, "users")
if err != nil {
    log.Fatal(err)
}

for _, col := range columns {
    nullable := "NOT NULL"
    if col.Nullable {
        nullable = "NULL"
    }
    fmt.Printf("%s %s %s\n", col.Name, col.Type, nullable)
    if col.Default.Valid {
        fmt.Printf("  DEFAULT: %s\n", col.Default.String)
    }
}

func (*Client) GetConnectionUtilization

func (c *Client) GetConnectionUtilization() []float64

GetConnectionUtilization returns connection utilization percentage for each pool GetConnectionUtilization은 각 풀의 연결 사용률을 반환합니다

Returns a slice of utilization percentages (0-100) for each pool. 각 풀의 사용률 백분율(0-100)을 포함하는 슬라이스를 반환합니다.

Example 예제:

utilization := client.GetConnectionUtilization()
for i, util := range utilization {
    fmt.Printf("Pool %d utilization: %.2f%%\n", i, util)
    if util > 80 {
        fmt.Printf("  WARNING: High utilization on pool %d\n", i)
    }
}

func (*Client) GetCurrentConnectionIndex

func (c *Client) GetCurrentConnectionIndex() int

GetCurrentConnectionIndex returns the current connection index (for round-robin) GetCurrentConnectionIndex는 현재 연결 인덱스를 반환합니다(round-robin용)

Example 예제:

idx := client.GetCurrentConnectionIndex()
fmt.Printf("Next query will use pool %d\n", idx)

func (*Client) GetDatabaseSize

func (c *Client) GetDatabaseSize(ctx context.Context) (int64, error)

GetDatabaseSize returns the total size of the current database in bytes GetDatabaseSize는 현재 데이터베이스의 총 크기를 바이트 단위로 반환합니다

Example 예제:

ctx := context.Background()
size, err := client.GetDatabaseSize(ctx)
if err != nil {
    log.Fatal(err)
}
fmt.Printf("Database size: %.2f MB\n", float64(size)/(1024*1024))

func (*Client) GetForeignKeys

func (c *Client) GetForeignKeys(ctx context.Context, table string) ([]ForeignKeyInfo, error)

GetForeignKeys returns information about foreign keys for a table GetForeignKeys는 테이블의 외래 키에 대한 정보를 반환합니다

Example 예제:

ctx := context.Background()
fks, err := client.GetForeignKeys(ctx, "orders")
if err != nil {
    log.Fatal(err)
}

for _, fk := range fks {
    fmt.Printf("FK: %s.%s -> %s.%s\n",
        fk.TableName, fk.ColumnName,
        fk.ReferencedTable, fk.ReferencedColumn)
}

func (*Client) GetIndexes

func (c *Client) GetIndexes(ctx context.Context, table string) ([]IndexInfo, error)

GetIndexes returns information about all indexes on a table GetIndexes는 테이블의 모든 인덱스에 대한 정보를 반환합니다

Example 예제:

ctx := context.Background()
indexes, err := client.GetIndexes(ctx, "users")
if err != nil {
    log.Fatal(err)
}

for _, idx := range indexes {
    uniqueStr := ""
    if idx.Unique {
        uniqueStr = "UNIQUE"
    }
    fmt.Printf("%s %s INDEX %s (%s)\n",
        uniqueStr, idx.IndexType, idx.Name, strings.Join(idx.Columns, ", "))
}

func (*Client) GetPoolHealthInfo

func (c *Client) GetPoolHealthInfo(ctx context.Context) PoolHealthInfo

GetPoolHealthInfo performs a health check on all connection pools GetPoolHealthInfo는 모든 연결 풀에 대한 헬스 체크를 수행합니다

Example 예제:

ctx := context.Background()
health := client.GetPoolHealthInfo(ctx)

if !health.Healthy {
    fmt.Printf("Unhealthy pools: %v\n", health.UnhealthyPool)
    for _, detail := range health.Details {
        if !detail.Healthy {
            fmt.Printf("Pool %d error: %v\n", detail.Index, detail.Error)
        }
    }
}

func (*Client) GetPoolMetrics

func (c *Client) GetPoolMetrics() PoolMetrics

GetPoolMetrics returns connection pool metrics GetPoolMetrics는 연결 풀 메트릭을 반환합니다

Example 예제:

metrics := client.GetPoolMetrics()
fmt.Printf("Total pools: %d\n", metrics.PoolCount)
fmt.Printf("Total connections: %d\n", metrics.TotalConnections)

for _, pool := range metrics.PoolStats {
    fmt.Printf("Pool %d: %d in use, %d idle\n",
        pool.Index, pool.InUse, pool.Idle)
}

func (*Client) GetPoolStats

func (c *Client) GetPoolStats() []sql.DBStats

GetPoolStats returns raw database statistics for all pools GetPoolStats는 모든 풀의 원시 데이터베이스 통계를 반환합니다

This is an alias for the Stats() method for backward compatibility. 이것은 하위 호환성을 위한 Stats() 메서드의 별칭입니다.

Example 예제:

stats := client.GetPoolStats()
for i, stat := range stats {
    fmt.Printf("Pool %d:\n", i)
    fmt.Printf("  Open: %d, InUse: %d, Idle: %d\n",
        stat.OpenConnections, stat.InUse, stat.Idle)
}

func (*Client) GetPrimaryKey

func (c *Client) GetPrimaryKey(ctx context.Context, table string) ([]string, error)

GetPrimaryKey returns the primary key columns for a table GetPrimaryKey는 테이블의 기본 키 컬럼을 반환합니다

Example 예제:

ctx := context.Background()
pkCols, err := client.GetPrimaryKey(ctx, "users")
if err != nil {
    log.Fatal(err)
}

if len(pkCols) > 0 {
    fmt.Printf("Primary key: %s\n", strings.Join(pkCols, ", "))
} else {
    fmt.Println("No primary key defined")
}

func (*Client) GetQueryStats

func (c *Client) GetQueryStats() QueryStats

GetQueryStats returns query execution statistics GetQueryStats는 쿼리 실행 통계를 반환합니다

Example 예제:

stats := client.GetQueryStats()
fmt.Printf("Total queries: %d\n", stats.TotalQueries)
fmt.Printf("Success rate: %.2f%%\n",
    float64(stats.SuccessQueries)/float64(stats.TotalQueries)*100)
fmt.Printf("Average duration: %v\n", stats.AvgDuration)

func (*Client) GetRotationIndex

func (c *Client) GetRotationIndex() int

GetRotationIndex returns the current rotation index GetRotationIndex는 현재 순환 인덱스를 반환합니다

This is only relevant when credential rotation is enabled. 이것은 자격 증명 순환이 활성화된 경우에만 관련이 있습니다.

Example 예제:

rotIdx := client.GetRotationIndex()
fmt.Printf("Next rotation will replace pool %d\n", rotIdx)

func (*Client) GetSlowQueries

func (c *Client) GetSlowQueries(limit int) []SlowQueryInfo

GetSlowQueries returns recent slow queries GetSlowQueries는 최근 느린 쿼리를 반환합니다

The limit parameter specifies how many recent slow queries to return. limit 매개변수는 반환할 최근 느린 쿼리의 수를 지정합니다.

Example 예제:

// Get last 10 slow queries 최근 10개의 느린 쿼리 가져오기

slowQueries := client.GetSlowQueries(10)
for _, sq := range slowQueries {
    fmt.Printf("Query: %s\n", sq.Query)
    fmt.Printf("Duration: %v\n", sq.Duration)
    fmt.Printf("Timestamp: %v\n", sq.Timestamp)
    fmt.Println("---")
}

Example with analysis 분석 예제:

slowQueries := client.GetSlowQueries(50)
if len(slowQueries) > 0 {
    var totalDuration time.Duration
    for _, sq := range slowQueries {
        totalDuration += sq.Duration
    }

avgDuration := totalDuration time.Duration(len(slowQueries))

    fmt.Printf("Average slow query duration: %v\n", avgDuration)
}

func (*Client) GetTableSchema

func (c *Client) GetTableSchema(ctx context.Context, table string) (string, error)

GetTableSchema returns the CREATE TABLE statement for a table GetTableSchema는 테이블의 CREATE TABLE 문을 반환합니다

Example 예제:

ctx := context.Background()
schema, err := client.GetTableSchema(ctx, "users")
if err != nil {
    log.Fatal(err)
}
fmt.Println(schema)

func (*Client) GetTableSize

func (c *Client) GetTableSize(ctx context.Context, table string) (int64, error)

GetTableSize returns the size of a table in bytes GetTableSize는 테이블의 크기를 바이트 단위로 반환합니다

Example 예제:

ctx := context.Background()
size, err := client.GetTableSize(ctx, "users")
if err != nil {
    log.Fatal(err)
}
fmt.Printf("Table size: %.2f MB\n", float64(size)/(1024*1024))

func (*Client) GetTables

func (c *Client) GetTables(ctx context.Context) ([]TableInfo, error)

GetTables returns a list of all tables in the current database GetTables는 현재 데이터베이스의 모든 테이블 목록을 반환합니다

Example 예제:

ctx := context.Background()
tables, err := client.GetTables(ctx)
if err != nil {
    log.Fatal(err)
}

for _, table := range tables {
    fmt.Printf("Table: %s (Engine: %s, Rows: %d)\n",
        table.Name, table.Engine, table.Rows)
}

func (*Client) GetWaitStatistics

func (c *Client) GetWaitStatistics() []WaitStatistic

GetWaitStatistics returns wait statistics for all pools GetWaitStatistics는 모든 풀의 대기 통계를 반환합니다

Returns wait count and average wait duration for each pool. 각 풀의 대기 횟수와 평균 대기 시간을 반환합니다.

Example 예제:

type WaitStat struct {
    PoolIndex   int
    WaitCount   int64
    AvgWaitTime time.Duration
}

waitStats := client.GetWaitStatistics()
for _, ws := range waitStats {
    if ws.WaitCount > 0 {
        fmt.Printf("Pool %d: %d waits, avg %v\n",
            ws.PoolIndex, ws.WaitCount, ws.AvgWaitTime)
    }
}

func (*Client) ImportFromCSV

func (c *Client) ImportFromCSV(ctx context.Context, table string, filePath string, opts CSVImportOptions) error

ImportFromCSV imports data from a CSV file into a table ImportFromCSV는 CSV 파일에서 테이블로 데이터를 가져옵니다

Example 예제:

ctx := context.Background()
opts := mysql.DefaultCSVImportOptions()
opts.Columns = []string{"id", "name", "email"}
opts.BatchSize = 500
opts.IgnoreDuplicates = true

err := client.ImportFromCSV(ctx, "users", "/path/to/users.csv", opts)
if err != nil {
    log.Fatal(err)
}

func (*Client) Insert

func (c *Client) Insert(table string, data map[string]interface{}) (sql.Result, error)

Insert inserts a new row into a table Insert는 테이블에 새 행을 삽입합니다

Example 예제:

result, err := db.Insert("users", map[string]interface{}{
    "name":  "John",
    "email": "john@example.com",
    "age":   30,
})

func (*Client) InsertContext

func (c *Client) InsertContext(ctx context.Context, table string, data map[string]interface{}) (sql.Result, error)

InsertContext inserts a new row into a table InsertContext는 테이블에 새 행을 삽입합니다

func (*Client) InspectTable

func (c *Client) InspectTable(ctx context.Context, table string) (*TableInspection, error)

InspectTable returns comprehensive information about a table InspectTable은 테이블에 대한 종합적인 정보를 반환합니다

Example 예제:

ctx := context.Background()
inspection, err := client.InspectTable(ctx, "users")
if err != nil {
    log.Fatal(err)
}

fmt.Printf("Table: %s\n", inspection.Info.Name)
fmt.Printf("Columns: %d\n", len(inspection.Columns))
fmt.Printf("Indexes: %d\n", len(inspection.Indexes))
fmt.Printf("Size: %.2f MB\n", float64(inspection.Size)/(1024*1024))

func (*Client) IsHealthy

func (c *Client) IsHealthy(ctx context.Context) bool

IsHealthy checks if the database connection is healthy IsHealthy는 데이터베이스 연결이 정상인지 확인합니다

func (*Client) ModifyColumn

func (c *Client) ModifyColumn(ctx context.Context, table string, column string, definition string) error

ModifyColumn modifies the definition of an existing column ModifyColumn은 기존 컬럼의 정의를 수정합니다

Example 예제:

ctx := context.Background() Change column type 컬럼 타입 변경

err := client.ModifyColumn(ctx, "users", "age", "SMALLINT UNSIGNED")
if err != nil {
    log.Fatal(err)
}

func (*Client) Paginate

func (c *Client) Paginate(ctx context.Context, table string, page, pageSize int, conditionAndArgs ...interface{}) (*PaginationResult, error)

Paginate performs paginated query on a table Paginate는 테이블에 대해 페이지네이션 쿼리를 수행합니다

Example 예제:

// Get page 1 with 10 items per page 페이지 1을 페이지당 10개 항목으로 가져오기

result, err := db.Paginate(ctx, "users", 1, 10)

// With WHERE condition and ORDER BY WHERE 조건 및 ORDER BY와 함께

result, err := db.Paginate(ctx, "users", 2, 20,
    mysql.WithColumns("id", "name", "email"),
    mysql.WithWhere("age > ?", 18),
    mysql.WithOrderBy("created_at DESC"))

func (*Client) PaginateQuery

func (c *Client) PaginateQuery(ctx context.Context, baseQuery, countQuery string, page, pageSize int, args ...interface{}) (*PaginationResult, error)

PaginateQuery performs paginated query using a custom query PaginateQuery는 사용자 정의 쿼리를 사용하여 페이지네이션 쿼리를 수행합니다

Example 예제:

baseQuery := "SELECT u.*, COUNT(o.id) as order_count FROM users u LEFT JOIN orders o ON u.id = o.user_id GROUP BY u.id"
countQuery := "SELECT COUNT(*) FROM users"
result, err := db.PaginateQuery(ctx, baseQuery, countQuery, 1, 10)

func (*Client) PermanentDelete

func (c *Client) PermanentDelete(ctx context.Context, table string, conditionAndArgs ...interface{}) (sql.Result, error)

PermanentDelete performs actual deletion (physical delete) from database PermanentDelete는 데이터베이스에서 실제 삭제(물리적 삭제)를 수행합니다

Example 예제:

result, err := db.PermanentDelete(ctx, "users", "id = ?", 1)

func (*Client) Ping

func (c *Client) Ping(ctx context.Context) error

Ping verifies a connection to the database is still alive Ping은 데이터베이스 연결이 여전히 활성 상태인지 확인합니다

func (*Client) Query

func (c *Client) Query(ctx context.Context, query string, args ...interface{}) (*sql.Rows, error)

Query executes a query that returns rows Query는 행을 반환하는 쿼리를 실행합니다

func (*Client) QueryRow

func (c *Client) QueryRow(ctx context.Context, query string, args ...interface{}) *sql.Row

QueryRow executes a query that returns a single row QueryRow는 단일 행을 반환하는 쿼리를 실행합니다

func (*Client) RenameColumn

func (c *Client) RenameColumn(ctx context.Context, table string, oldName string, newName string, definition string) error

RenameColumn renames a column RenameColumn은 컬럼의 이름을 변경합니다

Example 예제:

ctx := context.Background()
err := client.RenameColumn(ctx, "users", "old_name", "new_name", "VARCHAR(255)")
if err != nil {
    log.Fatal(err)
}

func (*Client) RenameTable

func (c *Client) RenameTable(ctx context.Context, oldName string, newName string) error

RenameTable renames a table RenameTable은 테이블의 이름을 변경합니다

Example 예제:

ctx := context.Background()
err := client.RenameTable(ctx, "old_users", "users")
if err != nil {
    log.Fatal(err)
}

func (*Client) Replace

func (c *Client) Replace(ctx context.Context, table string, data map[string]interface{}) (sql.Result, error)

Replace performs a REPLACE operation (delete + insert) Replace는 REPLACE 작업을 수행합니다 (삭제 + 삽입)

Note: REPLACE deletes the old row and inserts a new one, which can have side effects with foreign keys and auto-increment values. 주의: REPLACE는 기존 행을 삭제하고 새 행을 삽입하므로 외래 키 및 auto_increment 값에 부작용이 있을 수 있습니다.

Example 예제:

data := map[string]interface{}{
    "id": 1,
    "name": "John Doe",
    "age": 30,
}
result, err := db.Replace(ctx, "users", data)

This generates: REPLACE INTO users (id, name, age) VALUES (?,?,?)

func (*Client) ResetQueryStats

func (c *Client) ResetQueryStats()

ResetQueryStats resets query execution statistics ResetQueryStats는 쿼리 실행 통계를 재설정합니다

Example 예제:

// Reset stats to start fresh 새로 시작하기 위해 통계 재설정

client.ResetQueryStats()

func (*Client) Restore

func (c *Client) Restore(ctx context.Context, table string, conditionAndArgs ...interface{}) (sql.Result, error)

Restore restores soft-deleted rows by setting deleted_at to NULL Restore는 deleted_at을 NULL로 설정하여 소프트 삭제된 행을 복구합니다

Example 예제:

result, err := db.Restore(ctx, "users", "id = ?", 1)

func (*Client) RotateNow

func (c *Client) RotateNow() error

RotateNow immediately rotates one connection (for testing or manual rotation) RotateNow는 즉시 하나의 연결을 순환합니다 (테스트 또는 수동 순환용)

func (*Client) Select

func (c *Client) Select(cols ...string) *QueryBuilder

Select initiates a query builder with specified columns Select는 지정된 컬럼으로 쿼리 빌더를 시작합니다

func (*Client) SelectAll

func (c *Client) SelectAll(table string, conditionAndArgs ...interface{}) ([]map[string]interface{}, error)

SelectAll selects all rows from a table with optional conditions Uses context.Background() internally. For timeout/cancellation control, use SelectAllContext.

SelectAll은 선택적 조건으로 테이블의 모든 행을 선택합니다 내부적으로 context.Background()를 사용합니다. timeout/cancellation 제어가 필요하면 SelectAllContext를 사용하세요.

Example 예제:

// Select all users 모든 사용자 선택

users, err := db.SelectAll("users")

// Select with condition (use placeholder for safety) 조건과 함께 선택 (안전을 위해 placeholder 사용)

users, err := db.SelectAll("users", "age > ?", 18)
users, err := db.SelectAll("users", "age > ? AND city = ?", 18, "Seoul")

func (*Client) SelectAllContext

func (c *Client) SelectAllContext(ctx context.Context, table string, conditionAndArgs ...interface{}) ([]map[string]interface{}, error)

SelectAllContext selects all rows from a table with optional conditions SelectAllContext는 선택적 조건으로 테이블의 모든 행을 선택합니다

Example 예제:

ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
users, err := db.SelectAllContext(ctx, "users", "age > ?", 18)

func (*Client) SelectAllOnlyTrashed

func (c *Client) SelectAllOnlyTrashed(ctx context.Context, table string, conditionAndArgs ...interface{}) ([]map[string]interface{}, error)

SelectAllOnlyTrashed selects only soft-deleted rows SelectAllOnlyTrashed는 소프트 삭제된 행만 선택합니다

Example 예제:

users, err := db.SelectAllOnlyTrashed(ctx, "users")
users, err := db.SelectAllOnlyTrashed(ctx, "users", "age > ?", 18)

func (*Client) SelectAllWithTrashed

func (c *Client) SelectAllWithTrashed(ctx context.Context, table string, conditionAndArgs ...interface{}) ([]map[string]interface{}, error)

SelectAllWithTrashed selects all rows including soft-deleted ones SelectAllWithTrashed는 소프트 삭제된 것을 포함하여 모든 행을 선택합니다

Example 예제:

users, err := db.SelectAllWithTrashed(ctx, "users")
users, err := db.SelectAllWithTrashed(ctx, "users", "age > ?", 18)

func (*Client) SelectColumn

func (c *Client) SelectColumn(table string, column string, conditionAndArgs ...interface{}) ([]map[string]interface{}, error)

SelectColumn selects all rows with a single column from a table SelectColumn은 테이블에서 단일 컬럼으로 모든 행을 선택합니다

Example 예제:

// Select all emails 모든 이메일 선택

emails, err := db.SelectColumn("users", "email")

// Select with condition 조건과 함께 선택

emails, err := db.SelectColumn("users", "email", "age > ?", 18)

func (*Client) SelectColumnContext

func (c *Client) SelectColumnContext(ctx context.Context, table string, column string, conditionAndArgs ...interface{}) ([]map[string]interface{}, error)

SelectColumnContext selects all rows with a single column from a table SelectColumnContext는 테이블에서 단일 컬럼으로 모든 행을 선택합니다

func (*Client) SelectColumns

func (c *Client) SelectColumns(table string, columns []string, conditionAndArgs ...interface{}) ([]map[string]interface{}, error)

SelectColumns selects all rows with multiple columns from a table SelectColumns는 테이블에서 여러 컬럼으로 모든 행을 선택합니다

Example 예제:

// Select multiple columns 여러 컬럼 선택

users, err := db.SelectColumns("users", []string{"name", "email", "age"})

// Select with condition 조건과 함께 선택

users, err := db.SelectColumns("users", []string{"name", "email"}, "age > ?", 18)

func (*Client) SelectColumnsContext

func (c *Client) SelectColumnsContext(ctx context.Context, table string, columns []string, conditionAndArgs ...interface{}) ([]map[string]interface{}, error)

SelectColumnsContext selects all rows with multiple columns from a table SelectColumnsContext는 테이블에서 여러 컬럼으로 모든 행을 선택합니다

func (*Client) SelectOne

func (c *Client) SelectOne(table string, conditionAndArgs ...interface{}) (map[string]interface{}, error)

SelectOne selects a single row from a table with conditions SelectOne은 조건과 함께 테이블에서 단일 행을 선택합니다

Example 예제:

user, err := db.SelectOne("users", "id = ?", 123)

func (*Client) SelectOneContext

func (c *Client) SelectOneContext(ctx context.Context, table string, conditionAndArgs ...interface{}) (map[string]interface{}, error)

SelectOneContext selects a single row from a table with conditions SelectOneContext는 조건과 함께 테이블에서 단일 행을 선택합니다

func (*Client) SelectOneWhere

func (c *Client) SelectOneWhere(ctx context.Context, table string, conditionAndArgs ...interface{}) (map[string]interface{}, error)

SelectOneWhere selects a single row with optional WHERE condition and options SelectOneWhere는 선택적 WHERE 조건과 옵션으로 단일 행을 선택합니다

Example 예제:

user, _ := db.SelectOneWhere(ctx, "users", "email = ?", "john@example.com",
  WithColumns("name", "age", "city"))

func (*Client) SelectWhere

func (c *Client) SelectWhere(ctx context.Context, table string, conditionAndArgs ...interface{}) ([]map[string]interface{}, error)

SelectWhere selects rows with optional WHERE condition and options SelectWhere는 선택적 WHERE 조건과 옵션으로 행을 선택합니다

Example 예제:

// Simple query with columns 컬럼 지정 간단 쿼리

users, _ := db.SelectWhere(ctx, "users", "age > ?", 18,
  WithColumns("name", "email"),
  WithOrderBy("age DESC"),
  WithLimit(10))

// GROUP BY query GROUP BY 쿼리

results, _ := db.SelectWhere(ctx, "users", "",
  WithColumns("city", "COUNT(*) as count"),
  WithGroupBy("city"),
  WithHaving("COUNT(*) > ?", 2),
  WithOrderBy("count DESC"))

// JOIN query JOIN 쿼리

results, _ := db.SelectWhere(ctx, "users u", "u.age > ?", 25,
  WithJoin("orders o", "u.id = o.user_id"),
  WithColumns("u.name", "o.total"),
  WithOrderBy("o.total DESC"))

func (*Client) SoftDelete

func (c *Client) SoftDelete(ctx context.Context, table string, conditionAndArgs ...interface{}) (sql.Result, error)

SoftDelete marks rows as deleted by setting deleted_at timestamp SoftDelete는 deleted_at 타임스탬프를 설정하여 행을 삭제된 것으로 표시합니다

Example 예제:

result, err := db.SoftDelete(ctx, "users", "id = ?", 1)

func (*Client) Stats

func (c *Client) Stats() []sql.DBStats

Stats returns database statistics Stats는 데이터베이스 통계를 반환합니다

func (*Client) TableExists

func (c *Client) TableExists(ctx context.Context, table string) (bool, error)

TableExists checks if a table exists in the database TableExists는 데이터베이스에 테이블이 존재하는지 확인합니다

Example 예제:

ctx := context.Background()
exists, err := client.TableExists(ctx, "users")
if err != nil {
    log.Fatal(err)
}

if exists {
    fmt.Println("Table 'users' exists")
} else {
    fmt.Println("Table 'users' does not exist")
}

func (*Client) Transaction

func (c *Client) Transaction(ctx context.Context, fn func(*Tx) error) error

Transaction executes a function within a database transaction Transaction은 데이터베이스 트랜잭션 내에서 함수를 실행합니다

If the function returns an error, the transaction is rolled back. If the function succeeds, the transaction is committed.

함수가 에러를 반환하면 트랜잭션이 롤백됩니다. 함수가 성공하면 트랜잭션이 커밋됩니다.

Example 예제:

err := db.Transaction(ctx, func(tx *Tx) error { Insert user 사용자 삽입

result, err := tx.Insert(ctx, "users", map[string]interface{}{
    "name": "John",
    "email": "john@example.com",
})

if err != nil { return err // Will rollback 롤백됨

}

userID, _ := result.LastInsertId()

// Insert profile 프로필 삽입

_, err = tx.Insert(ctx, "profiles", map[string]interface{}{
    "user_id": userID,
    "bio": "Hello world",
})

if err != nil { return err // Will rollback 롤백됨

}

return nil // Will commit 커밋됨

})

func (*Client) TruncateTable

func (c *Client) TruncateTable(ctx context.Context, table string) error

TruncateTable removes all rows from a table TruncateTable은 테이블의 모든 행을 제거합니다

Warning: This operation cannot be rolled back. 경고: 이 작업은 롤백할 수 없습니다.

Example 예제:

ctx := context.Background()
err := client.TruncateTable(ctx, "temp_data")
if err != nil {
    log.Fatal(err)
}

func (*Client) Update

func (c *Client) Update(table string, data map[string]interface{}, conditionAndArgs ...interface{}) (sql.Result, error)

Update updates rows in a table Update는 테이블의 행을 업데이트합니다

Example 예제:

result, err := db.Update("users",
    map[string]interface{}{"name": "Jane", "age": 31},
    "id = ?", 123)

func (*Client) UpdateContext

func (c *Client) UpdateContext(ctx context.Context, table string, data map[string]interface{}, conditionAndArgs ...interface{}) (sql.Result, error)

UpdateContext updates rows in a table UpdateContext는 테이블의 행을 업데이트합니다

func (*Client) Upsert

func (c *Client) Upsert(ctx context.Context, table string, data map[string]interface{}, updateColumns []string) (sql.Result, error)

Upsert inserts a row or updates it if it already exists (INSERT ... ON DUPLICATE KEY UPDATE) Upsert는 행을 삽입하거나 이미 존재하면 업데이트합니다 (INSERT ... ON DUPLICATE KEY UPDATE)

Example 예제:

data := map[string]interface{}{
    "email": "john@example.com",  // Unique key
    "name": "John Doe",
    "age": 30,
}
updateColumns := []string{"name", "age"}  // Columns to update on duplicate
result, err := db.Upsert(ctx, "users", data, updateColumns)

This generates: INSERT INTO users (email, name, age) VALUES (?,?,?)

ON DUPLICATE KEY UPDATE name=VALUES(name), age=VALUES(age)

func (*Client) UpsertBatch

func (c *Client) UpsertBatch(ctx context.Context, table string, data []map[string]interface{}, updateColumns []string) (sql.Result, error)

UpsertBatch performs multiple upsert operations in a single query UpsertBatch는 단일 쿼리로 여러 upsert 작업을 수행합니다

Example 예제:

data := []map[string]interface{}{
    {"email": "john@example.com", "name": "John", "age": 30},
    {"email": "jane@example.com", "name": "Jane", "age": 25},
}
updateColumns := []string{"name", "age"}
err := db.UpsertBatch(ctx, "users", data, updateColumns)

This generates: INSERT INTO users (email, name, age) VALUES (?,?,?),(?,?,?)

ON DUPLICATE KEY UPDATE name=VALUES(name), age=VALUES(age)

type ColumnInfo

type ColumnInfo struct {
	// Column name
	// 컬럼 이름
	Name string
	// Column type
	// 컬럼 타입
	Type string
	// Whether NULL is allowed
	// NULL 허용 여부
	Nullable bool
	// Default value
	// 기본값
	Default sql.NullString
	// Key type (PRI, UNI, MUL)
	// 키 타입
	Key string
	// Extra information (auto_increment, etc.)
	// 추가 정보
	Extra string
}

ColumnInfo represents information about a table column ColumnInfo는 테이블 컬럼에 대한 정보를 나타냅니다

type CredentialRefreshFunc

type CredentialRefreshFunc func() (dsn string, err error)

CredentialRefreshFunc is a user-provided function that returns a new DSN CredentialRefreshFunc는 새 DSN을 반환하는 사용자 제공 함수입니다

Users can implement this function to fetch credentials from: - HashiCorp Vault - AWS Secrets Manager - Environment variables - Configuration files - Any other credential store

사용자는 다음에서 자격 증명을 가져오기 위해 이 함수를 구현할 수 있습니다: - HashiCorp Vault - AWS Secrets Manager - 환경 변수 - 설정 파일 - 기타 자격 증명 저장소

Example 예제:

func getDSN() (string, error) {
    user := os.Getenv("DB_USER")
    pass := os.Getenv("DB_PASS")
    return fmt.Sprintf("%s:%s@tcp(localhost:3306)/mydb", user, pass), nil
}

type DBError

type DBError struct {
	// Operation name
	// 작업 이름
	Op string
	// SQL query
	// SQL 쿼리
	Query string
	// Query arguments
	// 쿼리 인자
	Args []interface{}
	// Original error
	// 원본 에러
	Err error
	// Error timestamp
	// 에러 타임스탬프
	Time time.Time
	// Operation duration
	// 작업 소요 시간
	Duration time.Duration
}

DBError represents a database operation error DBError는 데이터베이스 작업 에러를 나타냅니다

func (*DBError) Error

func (e *DBError) Error() string

Error implements error interface Error는 error 인터페이스를 구현합니다

func (*DBError) Unwrap

func (e *DBError) Unwrap() error

Unwrap returns the underlying error Unwrap은 기본 에러를 반환합니다

type ForeignKeyInfo

type ForeignKeyInfo struct {
	// Foreign key constraint name
	// 외래 키 제약 조건 이름
	ConstraintName string
	// Table name
	// 테이블 이름
	TableName string
	// Column name
	// 컬럼 이름
	ColumnName string
	// Referenced table name
	// 참조된 테이블 이름
	ReferencedTable string
	// Referenced column name
	// 참조된 컬럼 이름
	ReferencedColumn string
}

ForeignKeyInfo represents information about a foreign key ForeignKeyInfo는 외래 키에 대한 정보를 나타냅니다

type IndexInfo

type IndexInfo struct {
	// Index name
	// 인덱스 이름
	Name string
	// Indexed columns
	// 인덱싱된 컬럼
	Columns []string
	// Whether index is unique
	// 유니크 인덱스 여부
	Unique bool
	// Index type (BTREE, HASH, etc.)
	// 인덱스 타입
	IndexType string
}

IndexInfo represents information about a table index IndexInfo는 테이블 인덱스에 대한 정보를 나타냅니다

type Option

type Option func(*config) error

Option is a function that configures the MySQL client Option은 MySQL 클라이언트를 설정하는 함수입니다

func WithConnMaxIdleTime

func WithConnMaxIdleTime(d time.Duration) Option

WithConnMaxIdleTime sets the maximum idle time of a connection WithConnMaxIdleTime은 연결의 최대 유휴 시간을 설정합니다

Example 예제:

mysql.WithConnMaxIdleTime(2 * time.Minute)

func WithConnMaxLifetime

func WithConnMaxLifetime(d time.Duration) Option

WithConnMaxLifetime sets the maximum lifetime of a connection WithConnMaxLifetime은 연결의 최대 수명을 설정합니다

Example 예제:

mysql.WithConnMaxLifetime(5 * time.Minute)

func WithConnectTimeout

func WithConnectTimeout(d time.Duration) Option

WithConnectTimeout sets the connection timeout WithConnectTimeout은 연결 타임아웃을 설정합니다

Example 예제:

mysql.WithConnectTimeout(10 * time.Second)

func WithCredentialRefresh

func WithCredentialRefresh(fn CredentialRefreshFunc, poolCount int, interval time.Duration) Option

WithCredentialRefresh sets up dynamic credential rotation WithCredentialRefresh는 동적 자격 증명 순환을 설정합니다

Parameters 매개변수: - fn: User function that returns new DSN 새 DSN을 반환하는 사용자 함수 - poolCount: Number of connection pools to maintain 유지할 연결 풀 개수 - interval: How often to rotate one connection 하나의 연결을 순환할 주기

Example 예제:

func getDSN() (string, error) {
    // Fetch from Vault, file, env var, etc.
    return "user:pass@tcp(localhost:3306)/db", nil
}

mysql.WithCredentialRefresh(getDSN, 3, 1*time.Hour)
// Result: 3 pools, rotate 1 per hour

func WithDSN

func WithDSN(dsn string) Option

WithDSN sets the data source name (connection string) WithDSN은 데이터 소스 이름(연결 문자열)을 설정합니다

Example 예제:

mysql.WithDSN("user:password@tcp(localhost:3306)/dbname?parseTime=true")

func WithHealthCheck

func WithHealthCheck(enable bool) Option

WithHealthCheck enables or disables automatic health checks WithHealthCheck는 자동 헬스 체크를 활성화하거나 비활성화합니다

Example 예제:

mysql.WithHealthCheck(true)

func WithHealthCheckInterval

func WithHealthCheckInterval(d time.Duration) Option

WithHealthCheckInterval sets the health check interval WithHealthCheckInterval은 헬스 체크 주기를 설정합니다

Example 예제:

mysql.WithHealthCheckInterval(60 * time.Second)

func WithLogger

func WithLogger(logger *logging.Logger) Option

WithLogger sets the logger instance WithLogger는 로거 인스턴스를 설정합니다

Example 예제:

logger, _ := logging.New(logging.WithFilePath("./logs/mysql.log"))
mysql.WithLogger(logger)

func WithMaxIdleConns

func WithMaxIdleConns(n int) Option

WithMaxIdleConns sets the maximum number of idle connections WithMaxIdleConns는 최대 유휴 연결 수를 설정합니다

Example 예제:

mysql.WithMaxIdleConns(10)

func WithMaxOpenConns

func WithMaxOpenConns(n int) Option

WithMaxOpenConns sets the maximum number of open connections to the database WithMaxOpenConns는 데이터베이스에 대한 최대 오픈 연결 수를 설정합니다

Example 예제:

mysql.WithMaxOpenConns(50)

func WithMaxRetries

func WithMaxRetries(n int) Option

WithMaxRetries sets the maximum number of retry attempts WithMaxRetries는 최대 재시도 횟수를 설정합니다

Example 예제:

mysql.WithMaxRetries(5)

func WithQueryLogging

func WithQueryLogging(enable bool) Option

WithQueryLogging enables or disables query logging WithQueryLogging은 쿼리 로깅을 활성화하거나 비활성화합니다

Example 예제:

mysql.WithQueryLogging(true)

func WithQueryStats

func WithQueryStats(enable bool) Option

WithQueryStats enables or disables query statistics tracking WithQueryStats는 쿼리 통계 추적을 활성화하거나 비활성화합니다

Example 예제:

mysql.WithQueryStats(true)

func WithQueryTimeout

func WithQueryTimeout(d time.Duration) Option

WithQueryTimeout sets the query execution timeout WithQueryTimeout은 쿼리 실행 타임아웃을 설정합니다

Example 예제:

mysql.WithQueryTimeout(30 * time.Second)

func WithRetryDelay

func WithRetryDelay(d time.Duration) Option

WithRetryDelay sets the delay between retry attempts WithRetryDelay는 재시도 간 지연 시간을 설정합니다

Example 예제:

mysql.WithRetryDelay(200 * time.Millisecond)

func WithSlowQueryLogging

func WithSlowQueryLogging(enable bool) Option

WithSlowQueryLogging enables or disables slow query logging WithSlowQueryLogging은 느린 쿼리 로깅을 활성화하거나 비활성화합니다

Example 예제:

mysql.WithSlowQueryLogging(true)

func WithSlowQueryThreshold

func WithSlowQueryThreshold(d time.Duration) Option

WithSlowQueryThreshold sets the threshold for slow query logging WithSlowQueryThreshold는 느린 쿼리 로깅 임계값을 설정합니다

Example 예제:

mysql.WithSlowQueryThreshold(500 * time.Millisecond)

func WithTLS

func WithTLS(tlsConfig *tls.Config) Option

WithTLS enables TLS with the provided configuration WithTLS는 제공된 설정으로 TLS를 활성화합니다

Example 예제:

tlsConfig := &tls.Config{InsecureSkipVerify: false}
mysql.WithTLS(tlsConfig)

type PaginationResult

type PaginationResult struct {
	// Current page data
	// 현재 페이지 데이터
	Data []map[string]interface{}
	// Total number of rows
	// 전체 행 수
	TotalRows int64
	// Total number of pages
	// 전체 페이지 수
	TotalPages int
	// Current page number (1-indexed)
	// 현재 페이지 번호 (1부터 시작)
	Page int
	// Number of rows per page
	// 페이지당 행 수
	PageSize int
	// Whether there is a next page
	// 다음 페이지 존재 여부
	HasNext bool
	// Whether there is a previous page
	// 이전 페이지 존재 여부
	HasPrev bool
}

PaginationResult represents the result of a paginated query PaginationResult는 페이지네이션 쿼리의 결과를 나타냅니다

func (*PaginationResult) GetPage

func (pr *PaginationResult) GetPage() int

GetPage returns a specific page number (1-indexed) GetPage는 특정 페이지 번호를 반환합니다 (1부터 시작)

func (*PaginationResult) GetTotalPages

func (pr *PaginationResult) GetTotalPages() int

GetTotalPages returns the total number of pages GetTotalPages는 전체 페이지 수를 반환합니다

func (*PaginationResult) GetTotalRows

func (pr *PaginationResult) GetTotalRows() int64

GetTotalRows returns the total number of rows GetTotalRows는 전체 행 수를 반환합니다

func (*PaginationResult) IsFirstPage

func (pr *PaginationResult) IsFirstPage() bool

IsFirstPage returns true if this is the first page IsFirstPage는 첫 번째 페이지인 경우 true를 반환합니다

func (*PaginationResult) IsLastPage

func (pr *PaginationResult) IsLastPage() bool

IsLastPage returns true if this is the last page IsLastPage는 마지막 페이지인 경우 true를 반환합니다

func (*PaginationResult) NextPage

func (pr *PaginationResult) NextPage() int

NextPage returns the next page number, or 0 if there is no next page NextPage는 다음 페이지 번호를 반환하거나, 다음 페이지가 없으면 0을 반환합니다

func (*PaginationResult) PrevPage

func (pr *PaginationResult) PrevPage() int

PrevPage returns the previous page number, or 0 if there is no previous page PrevPage는 이전 페이지 번호를 반환하거나, 이전 페이지가 없으면 0을 반환합니다

type PoolHealth

type PoolHealth struct {
	// Pool index
	// 풀 인덱스
	Index int
	// Health status
	// 상태
	Healthy bool
	// Ping response time
	// Ping 응답 시간
	PingTime time.Duration
	// Error if unhealthy
	// 비정상인 경우 에러
	Error error
}

PoolHealth represents health status for a single pool PoolHealth는 단일 풀의 상태를 나타냅니다

type PoolHealthInfo

type PoolHealthInfo struct {
	// Whether all pools are healthy
	// 모든 풀이 정상인지
	Healthy bool
	// Indices of unhealthy pools
	// 비정상 풀의 인덱스
	UnhealthyPool []int
	// Last health check time
	// 마지막 헬스 체크 시간
	LastCheck time.Time
	// Duration of last health check
	// 마지막 헬스 체크 소요 시간
	CheckDuration time.Duration
	// Health details per pool
	// 풀별 상태 세부 정보
	Details []PoolHealth
}

PoolHealthInfo represents health information for connection pools PoolHealthInfo는 연결 풀의 상태 정보를 나타냅니다

type PoolMetrics

type PoolMetrics struct {
	// Number of connection pools
	// 연결 풀 수
	PoolCount int
	// Total connections across all pools
	// 모든 풀의 총 연결 수
	TotalConnections int
	// Individual pool statistics
	// 개별 풀 통계
	PoolStats []PoolStat
	// Overall health status
	// 전체 상태
	Healthy bool
	// Last health check time
	// 마지막 헬스 체크 시간
	LastChecked time.Time
}

PoolMetrics represents connection pool metrics PoolMetrics는 연결 풀 메트릭을 나타냅니다

type PoolStat

type PoolStat struct {
	// Pool index
	// 풀 인덱스
	Index int
	// Maximum open connections
	// 최대 열린 연결 수
	MaxOpenConns int
	// Currently open connections
	// 현재 열린 연결 수
	OpenConnections int
	// Connections in use
	// 사용 중인 연결 수
	InUse int
	// Idle connections
	// 유휴 연결 수
	Idle int
	// Total number of connections waited for
	// 대기한 총 연결 수
	WaitCount int64
	// Total time blocked waiting for connections
	// 연결 대기로 차단된 총 시간
	WaitDuration time.Duration
	// Total connections closed due to max idle
	// 최대 유휴로 인해 닫힌 총 연결 수
	MaxIdleClosed int64
	// Total connections closed due to max idle time
	// 최대 유휴 시간으로 인해 닫힌 총 연결 수
	MaxIdleTimeClosed int64
	// Total connections closed due to max lifetime
	// 최대 수명으로 인해 닫힌 총 연결 수
	MaxLifetimeClosed int64
}

PoolStat represents statistics for a single connection pool PoolStat는 단일 연결 풀의 통계를 나타냅니다

type QueryBuilder

type QueryBuilder struct {
	// contains filtered or unexported fields
}

QueryBuilder provides a fluent API for building complex SQL queries QueryBuilder는 복잡한 SQL 쿼리를 빌드하기 위한 Fluent API를 제공합니다

func (*QueryBuilder) All

func (qb *QueryBuilder) All(ctx context.Context) ([]map[string]interface{}, error)

All executes the query and returns all matching rows All은 쿼리를 실행하고 일치하는 모든 행을 반환합니다

func (*QueryBuilder) From

func (qb *QueryBuilder) From(table string) *QueryBuilder

From specifies the table to query from From은 쿼리할 테이블을 지정합니다

func (*QueryBuilder) GroupBy

func (qb *QueryBuilder) GroupBy(cols ...string) *QueryBuilder

GroupBy adds GROUP BY columns GroupBy는 GROUP BY 컬럼을 추가합니다

func (*QueryBuilder) Having

func (qb *QueryBuilder) Having(condition string, args ...interface{}) *QueryBuilder

Having adds a HAVING condition (used with GROUP BY) Having은 HAVING 조건을 추가합니다 (GROUP BY와 함께 사용)

func (*QueryBuilder) InnerJoin

func (qb *QueryBuilder) InnerJoin(table, condition string) *QueryBuilder

InnerJoin adds an INNER JOIN clause (alias for Join) InnerJoin은 INNER JOIN 절을 추가합니다 (Join의 별칭)

func (*QueryBuilder) Join

func (qb *QueryBuilder) Join(table, condition string) *QueryBuilder

Join adds an INNER JOIN clause Join은 INNER JOIN 절을 추가합니다

func (*QueryBuilder) LeftJoin

func (qb *QueryBuilder) LeftJoin(table, condition string) *QueryBuilder

LeftJoin adds a LEFT JOIN clause LeftJoin은 LEFT JOIN 절을 추가합니다

func (*QueryBuilder) Limit

func (qb *QueryBuilder) Limit(n int) *QueryBuilder

Limit sets the LIMIT clause Limit은 LIMIT 절을 설정합니다

func (*QueryBuilder) Offset

func (qb *QueryBuilder) Offset(n int) *QueryBuilder

Offset sets the OFFSET clause Offset은 OFFSET 절을 설정합니다

func (*QueryBuilder) One

func (qb *QueryBuilder) One(ctx context.Context) (map[string]interface{}, error)

One executes the query and returns a single row One은 쿼리를 실행하고 단일 행을 반환합니다

func (*QueryBuilder) OrderBy

func (qb *QueryBuilder) OrderBy(order string) *QueryBuilder

OrderBy adds an ORDER BY clause OrderBy는 ORDER BY 절을 추가합니다

func (*QueryBuilder) RightJoin

func (qb *QueryBuilder) RightJoin(table, condition string) *QueryBuilder

RightJoin adds a RIGHT JOIN clause RightJoin은 RIGHT JOIN 절을 추가합니다

func (*QueryBuilder) Where

func (qb *QueryBuilder) Where(condition string, args ...interface{}) *QueryBuilder

Where adds a WHERE condition Where는 WHERE 조건을 추가합니다

type QueryStats

type QueryStats struct {
	// Total number of queries executed
	// 실행된 총 쿼리 수
	TotalQueries int64
	// Number of successful queries
	// 성공한 쿼리 수
	SuccessQueries int64
	// Number of failed queries
	// 실패한 쿼리 수
	FailedQueries int64
	// Total execution time
	// 총 실행 시간
	TotalDuration time.Duration
	// Average execution time
	// 평균 실행 시간
	AvgDuration time.Duration
	// Number of slow queries
	// 느린 쿼리 수
	SlowQueries int64
}

QueryStats represents query execution statistics QueryStats는 쿼리 실행 통계를 나타냅니다

type SelectOption

type SelectOption func(*selectConfig)

SelectOption is a functional option for customizing SELECT queries SelectOption은 SELECT 쿼리를 커스터마이징하기 위한 함수형 옵션입니다

func WithColumns

func WithColumns(cols ...string) SelectOption

WithColumns specifies which columns to select WithColumns는 선택할 컬럼을 지정합니다

Example 예제:

db.SelectWhere(ctx, "users", "age > ?", 18, WithColumns("name", "email"))

func WithDistinct

func WithDistinct() SelectOption

WithDistinct adds DISTINCT keyword WithDistinct는 DISTINCT 키워드를 추가합니다

Example 예제:

db.SelectWhere(ctx, "users", "", WithColumns("city"), WithDistinct())

func WithGroupBy

func WithGroupBy(cols ...string) SelectOption

WithGroupBy adds GROUP BY clause WithGroupBy는 GROUP BY 절을 추가합니다

Example 예제:

db.SelectWhere(ctx, "users", "", WithGroupBy("city"), WithColumns("city", "COUNT(*) as count"))

func WithHaving

func WithHaving(condition string, args ...interface{}) SelectOption

WithHaving adds HAVING clause (used with GROUP BY) WithHaving은 HAVING 절을 추가합니다 (GROUP BY와 함께 사용)

Example 예제:

db.SelectWhere(ctx, "users", "",
  WithColumns("city", "COUNT(*) as count"),
  WithGroupBy("city"),
  WithHaving("COUNT(*) > ?", 2))

func WithJoin

func WithJoin(table, condition string) SelectOption

WithJoin adds INNER JOIN clause WithJoin은 INNER JOIN 절을 추가합니다

Example 예제:

db.SelectWhere(ctx, "users u", "u.age > ?", 18,
  WithJoin("orders o", "u.id = o.user_id"),
  WithColumns("u.name", "o.total"))

func WithLeftJoin

func WithLeftJoin(table, condition string) SelectOption

WithLeftJoin adds LEFT JOIN clause WithLeftJoin은 LEFT JOIN 절을 추가합니다

Example 예제:

db.SelectWhere(ctx, "users u", "",
  WithLeftJoin("orders o", "u.id = o.user_id"),
  WithColumns("u.name", "COUNT(o.id) as order_count"),
  WithGroupBy("u.id", "u.name"))

func WithLimit

func WithLimit(n int) SelectOption

WithLimit adds LIMIT clause WithLimit은 LIMIT 절을 추가합니다

Example 예제:

db.SelectWhere(ctx, "users", "age > ?", 18, WithLimit(10))

func WithOffset

func WithOffset(n int) SelectOption

WithOffset adds OFFSET clause WithOffset은 OFFSET 절을 추가합니다

Example 예제:

db.SelectWhere(ctx, "users", "age > ?", 18, WithLimit(10), WithOffset(20))

func WithOrderBy

func WithOrderBy(order string) SelectOption

WithOrderBy adds ORDER BY clause WithOrderBy는 ORDER BY 절을 추가합니다

Example 예제:

db.SelectWhere(ctx, "users", "age > ?", 18, WithOrderBy("age DESC"))

func WithRightJoin

func WithRightJoin(table, condition string) SelectOption

WithRightJoin adds RIGHT JOIN clause WithRightJoin은 RIGHT JOIN 절을 추가합니다

type SlowQueryHandler

type SlowQueryHandler func(info SlowQueryInfo)

SlowQueryHandler is a callback function for handling slow queries SlowQueryHandler는 느린 쿼리를 처리하기 위한 콜백 함수입니다

type SlowQueryInfo

type SlowQueryInfo struct {
	// SQL query
	// SQL 쿼리
	Query string
	// Query arguments
	// 쿼리 인자
	Args []interface{}
	// Execution time
	// 실행 시간
	Duration time.Duration
	// When the query was executed
	// 쿼리 실행 시간
	Timestamp time.Time
}

SlowQueryInfo represents information about a slow query SlowQueryInfo는 느린 쿼리에 대한 정보를 나타냅니다

type TableInfo

type TableInfo struct {
	// Table name
	// 테이블 이름
	Name string
	// Storage engine
	// 스토리지 엔진
	Engine string
	// Approximate row count
	// 대략적인 행 수
	Rows int64
	// Table comment
	// 테이블 주석
	Comment string
}

TableInfo represents information about a table TableInfo는 테이블에 대한 정보를 나타냅니다

type TableInspection

type TableInspection struct {
	// Basic table info
	// 기본 테이블 정보
	Info TableInfo
	// Column information
	// 컬럼 정보
	Columns []ColumnInfo
	// Index information
	// 인덱스 정보
	Indexes []IndexInfo
	// Primary key columns
	// 기본 키 컬럼
	PrimaryKey []string
	// Foreign key information
	// 외래 키 정보
	ForeignKeys []ForeignKeyInfo
	// Table size in bytes
	// 테이블 크기 (바이트)
	Size int64
}

TableInspection represents comprehensive table information TableInspection은 종합적인 테이블 정보를 나타냅니다

func (*TableInspection) String

func (ti *TableInspection) String() string

String returns a formatted string representation of the inspection String은 검사의 포맷된 문자열 표현을 반환합니다

type Tx

type Tx struct {
	// contains filtered or unexported fields
}

Tx represents a database transaction Tx는 데이터베이스 트랜잭션을 나타냅니다

func (*Tx) Commit

func (t *Tx) Commit() error

Commit commits the transaction Commit은 트랜잭션을 커밋합니다

func (*Tx) Delete

func (t *Tx) Delete(table string, conditionAndArgs ...interface{}) (sql.Result, error)

Delete deletes rows within the transaction Delete는 트랜잭션 내에서 행을 삭제합니다

func (*Tx) DeleteContext

func (t *Tx) DeleteContext(ctx context.Context, table string, conditionAndArgs ...interface{}) (sql.Result, error)

DeleteContext deletes rows within the transaction DeleteContext는 트랜잭션 내에서 행을 삭제합니다

func (*Tx) Exec

func (t *Tx) Exec(ctx context.Context, query string, args ...interface{}) (sql.Result, error)

Exec executes a query without returning rows within the transaction Exec는 트랜잭션 내에서 행을 반환하지 않는 쿼리를 실행합니다

func (*Tx) Insert

func (t *Tx) Insert(table string, data map[string]interface{}) (sql.Result, error)

Insert inserts a new row within the transaction Insert는 트랜잭션 내에서 새 행을 삽입합니다

func (*Tx) InsertContext

func (t *Tx) InsertContext(ctx context.Context, table string, data map[string]interface{}) (sql.Result, error)

InsertContext inserts a new row within the transaction InsertContext는 트랜잭션 내에서 새 행을 삽입합니다

func (*Tx) Query

func (t *Tx) Query(ctx context.Context, query string, args ...interface{}) (*sql.Rows, error)

Query executes a query within the transaction Query는 트랜잭션 내에서 쿼리를 실행합니다

func (*Tx) QueryRow

func (t *Tx) QueryRow(ctx context.Context, query string, args ...interface{}) *sql.Row

QueryRow executes a query that returns a single row within the transaction QueryRow는 트랜잭션 내에서 단일 행을 반환하는 쿼리를 실행합니다

func (*Tx) Rollback

func (t *Tx) Rollback() error

Rollback rolls back the transaction Rollback은 트랜잭션을 롤백합니다

func (*Tx) Select

func (tx *Tx) Select(cols ...string) *QueryBuilder

Select initiates a query builder within a transaction Select는 트랜잭션 내에서 쿼리 빌더를 시작합니다

func (*Tx) SelectAll

func (t *Tx) SelectAll(table string, conditionAndArgs ...interface{}) ([]map[string]interface{}, error)

SelectAll selects all rows within the transaction SelectAll은 트랜잭션 내에서 모든 행을 선택합니다

func (*Tx) SelectAllContext

func (t *Tx) SelectAllContext(ctx context.Context, table string, conditionAndArgs ...interface{}) ([]map[string]interface{}, error)

SelectAllContext selects all rows within the transaction SelectAllContext는 트랜잭션 내에서 모든 행을 선택합니다

func (*Tx) SelectColumn

func (t *Tx) SelectColumn(table string, column string, conditionAndArgs ...interface{}) ([]map[string]interface{}, error)

SelectColumn selects all rows with a single column within the transaction SelectColumn은 트랜잭션 내에서 단일 컬럼으로 모든 행을 선택합니다

func (*Tx) SelectColumnContext

func (t *Tx) SelectColumnContext(ctx context.Context, table string, column string, conditionAndArgs ...interface{}) ([]map[string]interface{}, error)

SelectColumnContext selects all rows with a single column within the transaction SelectColumnContext는 트랜잭션 내에서 단일 컬럼으로 모든 행을 선택합니다

func (*Tx) SelectColumns

func (t *Tx) SelectColumns(table string, columns []string, conditionAndArgs ...interface{}) ([]map[string]interface{}, error)

SelectColumns selects all rows with multiple columns within the transaction SelectColumns는 트랜잭션 내에서 여러 컬럼으로 모든 행을 선택합니다

func (*Tx) SelectColumnsContext

func (t *Tx) SelectColumnsContext(ctx context.Context, table string, columns []string, conditionAndArgs ...interface{}) ([]map[string]interface{}, error)

SelectColumnsContext selects all rows with multiple columns within the transaction SelectColumnsContext는 트랜잭션 내에서 여러 컬럼으로 모든 행을 선택합니다

func (*Tx) SelectOne

func (t *Tx) SelectOne(table string, conditionAndArgs ...interface{}) (map[string]interface{}, error)

SelectOne selects a single row within the transaction SelectOne은 트랜잭션 내에서 단일 행을 선택합니다

func (*Tx) SelectOneContext

func (t *Tx) SelectOneContext(ctx context.Context, table string, conditionAndArgs ...interface{}) (map[string]interface{}, error)

SelectOneContext selects a single row within the transaction SelectOneContext는 트랜잭션 내에서 단일 행을 선택합니다

func (*Tx) SelectOneWhere

func (tx *Tx) SelectOneWhere(ctx context.Context, table string, conditionAndArgs ...interface{}) (map[string]interface{}, error)

SelectOneWhere for transactions 트랜잭션용 SelectOneWhere

func (*Tx) SelectWhere

func (tx *Tx) SelectWhere(ctx context.Context, table string, conditionAndArgs ...interface{}) ([]map[string]interface{}, error)

SelectWhere for transactions 트랜잭션용 SelectWhere

func (*Tx) Update

func (t *Tx) Update(table string, data map[string]interface{}, conditionAndArgs ...interface{}) (sql.Result, error)

Update updates rows within the transaction Update는 트랜잭션 내에서 행을 업데이트합니다

func (*Tx) UpdateContext

func (t *Tx) UpdateContext(ctx context.Context, table string, data map[string]interface{}, conditionAndArgs ...interface{}) (sql.Result, error)

UpdateContext updates rows within the transaction UpdateContext는 트랜잭션 내에서 행을 업데이트합니다

type WaitStatistic

type WaitStatistic struct {
	// Pool index
	// 풀 인덱스
	PoolIndex int
	// Number of waits
	// 대기 횟수
	WaitCount int64
	// Average wait time
	// 평균 대기 시간
	AvgWaitTime time.Duration
}

WaitStatistic represents wait statistics for a connection pool WaitStatistic는 연결 풀의 대기 통계를 나타냅니다

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL