WOWSQL

package module
v1.5.0 Latest Latest
Warning

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

Go to latest
Published: Dec 25, 2025 License: Apache-2.0 Imports: 4 Imported by: 0

README ยถ

๐Ÿš€ WOWSQL Go SDK

Official Go SDK for WOWSQL - MySQL Backend-as-a-Service with S3 Storage.

Go Reference Go Report Card

โœจ Features

Database Features
  • ๐Ÿ—„๏ธ Full CRUD operations (Create, Read, Update, Delete)
  • ๐Ÿ” Advanced filtering (eq, neq, gt, gte, lt, lte, like, isNull, in, notIn, between, notBetween)
  • ๐Ÿ”— Logical operators (AND, OR)
  • ๐Ÿ“Š GROUP BY and aggregate functions (COUNT, SUM, AVG, MAX, MIN)
  • ๐ŸŽฏ HAVING clause for filtering aggregated results
  • ๐Ÿ“ˆ Multiple ORDER BY columns
  • ๐Ÿ“… Date/time functions in SELECT and filters
  • ๐Ÿงฎ Expressions in SELECT (e.g., "COUNT(*)", "DATE(created_at) as date")
  • ๐Ÿ“„ Pagination (limit, offset)
  • ๐Ÿ“Š Sorting (orderBy)
  • ๐ŸŽฏ Fluent query builder API
  • ๐Ÿ”’ Type-safe queries
  • ๐Ÿ“ Raw SQL queries
  • ๐Ÿ“‹ Table schema introspection
  • ๐Ÿ›ก๏ธ Comprehensive error handling
Storage Features
  • ๐Ÿ“ฆ S3-compatible storage for file management
  • โฌ†๏ธ File upload with automatic quota validation
  • โฌ‡๏ธ File download (presigned URLs)
  • ๐Ÿ“‚ File listing with metadata
  • ๐Ÿ—‘๏ธ File deletion (single and batch)
  • ๐Ÿ“Š Storage quota management
  • ๐ŸŒ Multi-region S3 support
  • ๐Ÿ›ก๏ธ Client-side limit enforcement

๐Ÿ“ฆ Installation



## ๐Ÿš€ Quick Start

### Database Operations

```go
package main

import (
    "fmt"
    "log"
    
    "github.com/wowsql/wowsql-go/WOWSQL"
)

func main() {
    // Initialize client
    client := WOWSQL.NewClient(
        "https://your-project.wowsql.com",
        "your-api-key",
    )

    // Query data
    users, err := client.Table("users").
        Select("id", "name", "email").
        Eq("status", "active").
        Limit(10).
        Execute()
    
    if err != nil {
        log.Fatal(err)
    }

    fmt.Printf("Found %d users\n", users.Count)
    for _, user := range users.Data {
        fmt.Printf("%s - %s\n", user["name"], user["email"])
    }
}
Storage Operations
package main

import (
    "fmt"
    "log"
    "os"
    
    "github.com/wowsql/wowsql-go/WOWSQL"
)

func main() {
    // Initialize storage client
    storage := WOWSQL.NewStorageClient(
        "https://your-project.wowsql.com",
        "your-api-key",
    )

    // Upload file
    fileData, _ := os.ReadFile("document.pdf")
    result, err := storage.Upload(
        fileData,
        "uploads/document.pdf",
        "application/pdf",
        nil,
    )
    
    if err != nil {
        log.Fatal(err)
    }
    
    fmt.Printf("Uploaded: %s\n", result.URL)

    // Check quota
    quota, err := storage.GetQuota()
    if err != nil {
        log.Fatal(err)
    }
    
    fmt.Printf("Storage used: %.2fGB / %.2fGB\n", 
        quota.StorageUsedGB, 
        quota.StorageQuotaGB)
}
Project Authentication
package main

import (
    "fmt"
    "log"

    "github.com/wowsql/wowsql-go/WOWSQL"
)

func main() {
    auth := WOWSQL.NewAuthClient(WOWSQL.AuthConfig{
        ProjectURL:   "https://your-project.wowsql.com",
        APIKey: "your-anon-key",  // Use anon key for client-side, service key for server-side
    })

    // Sign up an end user
    result, err := auth.SignUp("user@example.com", "SuperSecret123",
        WOWSQL.WithFullName("End User"))
    if err != nil {
        log.Fatal(err)
    }

    fmt.Println("User ID:", result.User.ID)
    fmt.Println("Access token:", result.Session.AccessToken)

    // Fetch the same user via stored session token
    user, err := auth.GetUser(result.Session.AccessToken)
    if err != nil {
        log.Fatal(err)
    }
    fmt.Println("Email verified:", user.EmailVerified)

    // OAuth Authentication
    oauthResp, err := auth.GetOAuthAuthorizationURL("github", "https://app.example.com/auth/callback")
    if err != nil {
        log.Fatal(err)
    }
    fmt.Println("Send user to:", oauthResp.AuthorizationURL)

    // After callback, exchange code for tokens
    redirectURI := "https://app.example.com/auth/callback"
    oauthResult, err := auth.ExchangeOAuthCallback("github", "authorization_code", &redirectURI)
    if err != nil {
        log.Fatal(err)
    }
    fmt.Println("OAuth user:", oauthResult.User.Email)

    // Password Reset
    forgotResult, err := auth.ForgotPassword("user@example.com")
    if err != nil {
        log.Fatal(err)
    }
    fmt.Println(forgotResult["message"])

    resetResult, err := auth.ResetPassword("reset_token", "newSecurePassword123")
    if err != nil {
        log.Fatal(err)
    }
    fmt.Println(resetResult["message"])
}

๐Ÿ“š Usage Examples

Select Queries
client := WOWSQL.NewClient(
    "https://your-project.wowsql.com",
    "your-api-key",
)

// Select all columns
all, err := client.Table("users").Select("*").Execute()

// Select specific columns
users, err := client.Table("users").
    Select("id", "name", "email").
    Execute()

// With filters
active, err := client.Table("users").
    Select("*").
    Eq("status", "active").
    Gt("age", 18).
    Execute()

// With ordering
recent, err := client.Table("users").
    Select("*").
    OrderBy("created_at", WOWSQL.SortDesc).
    Limit(10).
    Execute()

// With pagination
page1, err := client.Table("users").
    Select("*").
    Limit(20).
    Offset(0).
    Execute()

// Pattern matching
gmailUsers, err := client.Table("users").
    Select("*").
    Like("email", "%@gmail.com").
    Execute()

// Get first result
user, err := client.Table("users").
    Eq("email", "john@example.com").
    First()

if user != nil {
    fmt.Printf("Found user: %s\n", user["name"])
}
Insert Data
// Insert single record
result, err := client.Table("users").Insert(map[string]interface{}{
    "name":   "John Doe",
    "email":  "john@example.com",
    "age":    30,
    "status": "active",
})

if err != nil {
    log.Fatal(err)
}

fmt.Printf("New user ID: %v\n", result.ID)
Update Data
// Update by ID
result, err := client.Table("users").UpdateByID(1, map[string]interface{}{
    "name": "Jane Smith",
    "age":  26,
})

fmt.Printf("Updated %d row(s)\n", result.AffectedRows)

// Update with conditions
updated, err := client.Table("users").
    Where().
    Eq("status", "inactive").
    Update(map[string]interface{}{
        "status": "active",
    })
Delete Data
// Delete by ID
result, err := client.Table("users").DeleteByID(1)

fmt.Printf("Deleted %d row(s)\n", result.AffectedRows)

// Delete with conditions
deleted, err := client.Table("users").
    Where().
    Eq("status", "deleted").
    Delete()
Filter Operators
// Equal
.Eq("status", "active")

// Not equal
.Neq("status", "deleted")

// Greater than
.Gt("age", 18)

// Greater than or equal
.Gte("age", 18)

// Less than
.Lt("age", 65)

// Less than or equal
.Lte("age", 65)

// Pattern matching (SQL LIKE)
.Like("email", "%@gmail.com")

// Is null
.IsNull("deleted_at")

// IN operator
.In("category", []interface{}{"electronics", "books", "clothing"})

// NOT IN operator
.NotIn("status", []interface{}{"deleted", "archived"})

// BETWEEN operator
.Between("price", 10, 100)

// NOT BETWEEN operator
.NotBetween("age", 18, 65)

// OR logical operator
.Or("category", "eq", "electronics")

Advanced Query Features

GROUP BY and Aggregates

GROUP BY supports both simple column names and SQL expressions with functions. All expressions are validated for security.

Basic GROUP BY
// Group by single column
result, err := client.Table("products").
    Select("category", "COUNT(*) as count", "AVG(price) as avg_price").
    GroupBy("category").
    Execute()

// Group by multiple columns
result, err := client.Table("sales").
    Select("region", "category", "SUM(amount) as total").
    GroupBy("region", "category").
    Execute()
GROUP BY with Date/Time Functions
// Group by date
result, err := client.Table("orders").
    Select("DATE(created_at) as date", "COUNT(*) as orders", "SUM(total) as revenue").
    GroupBy("DATE(created_at)").
    OrderBy("date", WOWSQL.SortDesc).
    Execute()

// Group by year and month
result, err := client.Table("orders").
    Select("YEAR(created_at) as year", "MONTH(created_at) as month", "SUM(total) as revenue").
    GroupBy("YEAR(created_at)", "MONTH(created_at)").
    Execute()
Supported Functions in GROUP BY

Date/Time: DATE(), YEAR(), MONTH(), DAY(), WEEK(), QUARTER(), HOUR(), MINUTE(), SECOND(), DATE_FORMAT(), DATE_ADD(), DATE_SUB(), DATEDIFF(), NOW(), CURRENT_TIMESTAMP(), etc.

String: CONCAT(), SUBSTRING(), LEFT(), RIGHT(), UPPER(), LOWER(), LENGTH(), TRIM(), etc.

Mathematical: ROUND(), CEIL(), FLOOR(), ABS(), POW(), SQRT(), MOD(), etc.

HAVING Clause

HAVING filters aggregated results after GROUP BY. Supports aggregate functions and comparison operators.

// Filter aggregated results
result, err := client.Table("products").
    Select("category", "COUNT(*) as count").
    GroupBy("category").
    Having("COUNT(*)", "gt", 10).
    Execute()

// Multiple HAVING conditions
result, err := client.Table("orders").
    Select("DATE(created_at) as date", "SUM(total) as revenue").
    GroupBy("DATE(created_at)").
    Having("SUM(total)", "gt", 1000).
    Having("COUNT(*)", "gte", 5).
    Execute()

// HAVING with different aggregate functions
result, err := client.Table("products").
    Select("category", "AVG(price) as avg_price", "COUNT(*) as count").
    GroupBy("category").
    Having("AVG(price)", "gt", 100).
    Having("COUNT(*)", "gte", 5).
    Execute()

Supported HAVING Operators: eq, neq, gt, gte, lt, lte

Supported Aggregate Functions: COUNT(*), SUM(), AVG(), MAX(), MIN(), GROUP_CONCAT(), STDDEV(), VARIANCE()

Multiple ORDER BY
// Order by multiple columns
result, err := client.Table("products").
    Select("*").
    OrderByMultiple([]WOWSQL.OrderByItem{
        {Column: "category", Direction: WOWSQL.SortAsc},
        {Column: "price", Direction: WOWSQL.SortDesc},
        {Column: "created_at", Direction: WOWSQL.SortDesc},
    }).
    Execute()
Date/Time Functions
// Filter by date range using functions
result, err := client.Table("orders").
    Select("*").
    Filter("created_at", "gte", "DATE_SUB(NOW(), INTERVAL 7 DAY)").
    Execute()

// Group by date
result, err := client.Table("orders").
    Select("DATE(created_at) as date", "COUNT(*) as count").
    GroupBy("DATE(created_at)").
    Execute()
Storage Operations
storage := WOWSQL.NewStorageClient(
    "https://your-project.wowsql.com",
    "your-api-key",
)

// Upload file from bytes
fileData, _ := os.ReadFile("document.pdf")
uploadResult, err := storage.Upload(
    fileData,
    "uploads/2024/document.pdf",
    "application/pdf",
    nil,
)
fmt.Printf("Uploaded: %s\n", uploadResult.URL)

// Check if file exists
exists, err := storage.FileExists("uploads/document.pdf")
if exists {
    fmt.Println("File exists!")
}

// Get file information
info, err := storage.GetFileInfo("uploads/document.pdf")
fmt.Printf("Size: %d bytes\n", info.Size)
fmt.Printf("Modified: %s\n", info.LastModified)

// List files with prefix
files, err := storage.ListFiles("uploads/2024/", 0)
for _, file := range files {
    fmt.Printf("%s: %d bytes\n", file.Key, file.Size)
}

// Download file (get presigned URL)
url, err := storage.Download("uploads/document.pdf", 3600)
fmt.Printf("Download URL: %s\n", url)
// URL is valid for 1 hour

// Delete single file
err = storage.DeleteFile("uploads/old-file.pdf")

// Delete multiple files
err = storage.DeleteFiles([]string{
    "uploads/file1.pdf",
    "uploads/file2.pdf",
    "uploads/file3.pdf",
})

// Check quota
quota, err := storage.GetQuota()
fmt.Printf("Used: %.2f GB\n", quota.StorageUsedGB)
fmt.Printf("Available: %.2f GB\n", quota.StorageAvailableGB)
fmt.Printf("Usage: %.1f%%\n", quota.UsagePercentage)

// Check if enough storage before upload
if quota.StorageAvailableBytes < int64(len(fileData)) {
    fmt.Println("Not enough storage!")
} else {
    storage.Upload(fileData, "uploads/large-file.zip", "", nil)
}
Error Handling
import (
    "errors"
    "github.com/wowsql/wowsql-go/WOWSQL"
)

users, err := client.Table("users").Select("*").Execute()
if err != nil {
    var authErr *WOWSQL.AuthenticationError
    var notFoundErr *WOWSQL.NotFoundError
    var rateLimitErr *WOWSQL.RateLimitError
    var networkErr *WOWSQL.NetworkError
    
    switch {
    case errors.As(err, &authErr):
        fmt.Printf("Authentication error: %s\n", authErr.Message)
    case errors.As(err, &notFoundErr):
        fmt.Printf("Not found: %s\n", notFoundErr.Message)
    case errors.As(err, &rateLimitErr):
        fmt.Printf("Rate limit exceeded: %s\n", rateLimitErr.Message)
    case errors.As(err, &networkErr):
        fmt.Printf("Network error: %s\n", err)
    default:
        fmt.Printf("Error: %s\n", err)
    }
}

// Storage errors
_, err = storage.Upload(fileData, "uploads/file.pdf", "", nil)
if err != nil {
    var limitErr *WOWSQL.StorageLimitExceededError
    var storageErr *WOWSQL.StorageError
    
    switch {
    case errors.As(err, &limitErr):
        fmt.Printf("Storage full: %s\n", limitErr.Message)
        fmt.Printf("Required: %d bytes\n", limitErr.RequiredBytes)
        fmt.Printf("Available: %d bytes\n", limitErr.AvailableBytes)
    case errors.As(err, &storageErr):
        fmt.Printf("Storage error: %s\n", storageErr.Message)
    }
}
Utility Methods
// List all tables
tables, err := client.ListTables()
fmt.Printf("Tables: %v\n", tables)

// Get table schema
schema, err := client.GetTableSchema("users")
fmt.Printf("Columns: %d\n", len(schema.Columns))
for _, column := range schema.Columns {
    fmt.Printf("  - %s (%s)\n", column.Name, column.Type)
}

// Raw SQL query
results, err := client.Query("SELECT COUNT(*) as count FROM users WHERE age > 18")
if len(results) > 0 {
    fmt.Printf("Adult users: %v\n", results[0]["count"])
}

// Check API health
health, err := client.Health()
fmt.Printf("Status: %v\n", health["status"])

๐Ÿ”ง Configuration

Custom Timeout
import "time"

// Database client with custom timeout
client := WOWSQL.NewClientWithTimeout(
    "https://your-project.wowsql.com",
    "your-api-key",
    60 * time.Second, // 60 seconds
)

// Storage client with custom timeout
storage := WOWSQL.NewStorageClientWithOptions(
    "https://your-project.wowsql.com",
    "your-api-key",
    120 * time.Second, // 2 minutes for large files
    true, // auto check quota
)
Auto Quota Check
// Disable automatic quota checking
storage := WOWSQL.NewStorageClientWithOptions(
    "https://your-project.wowsql.com",
    "your-api-key",
    60 * time.Second,
    false, // disable auto-check
)

// Manually check quota
quota, err := storage.GetQuota()
if quota.StorageAvailableBytes > int64(len(fileData)) {
    checkQuota := false
    storage.Upload(fileData, "uploads/file.pdf", "", &checkQuota)
}

๐Ÿ”‘ API Keys

WOWSQL uses different API keys for different operations. Understanding which key to use is crucial for proper authentication.

Key Types Overview

๐Ÿ”‘ Unified Authentication

โœจ One Project = One Set of Keys for ALL Operations

WOWSQL uses unified authentication - the same API keys work for both database operations AND authentication operations.

Operation Type Recommended Key Alternative Key Used By
Database Operations (CRUD) Service Role Key (wowsql_service_...) Anonymous Key (wowsql_anon_...) WOWSQLClient
Authentication Operations (OAuth, sign-in) Anonymous Key (wowsql_anon_...) Service Role Key (wowsql_service_...) ProjectAuthClient
Where to Find Your Keys

All keys are found in: WOWSQL Dashboard โ†’ Settings โ†’ API Keys or Authentication โ†’ PROJECT KEYS

  1. Anonymous Key (wowsql_anon_...) โœจ Unified Key

    • Location: "Anonymous Key (Public)"
    • Used for:
      • โœ… Client-side auth operations (signup, login, OAuth)
      • โœ… Public/client-side database operations with limited permissions
    • Safe to expose in frontend code (browser, mobile apps)
  2. Service Role Key (wowsql_service_...) โœจ Unified Key

    • Location: "Service Role Key (keep secret)"
    • Used for:
      • โœ… Server-side auth operations (admin, full access)
      • โœ… Server-side database operations (full access, bypass RLS)
    • NEVER expose in frontend code - server-side only!
Database Operations

Use Service Role Key or Anonymous Key for database operations:

package main

import "github.com/wowsql/wowsql-go/WOWSQL"

// Using Service Role Key (recommended for server-side, full access)
client := WOWSQL.NewClient(
    "https://your-project.wowsql.com",
    "wowsql_service_your-service-key-here",  // Service Role Key
)

// Using Anonymous Key (for public/client-side access with limited permissions)
client := WOWSQL.NewClient(
    "https://your-project.wowsql.com",
    "wowsql_anon_your-anon-key-here",  // Anonymous Key
)

// Query data
users, err := client.Table("users").Execute()
Authentication Operations

โœจ UNIFIED AUTHENTICATION: Use the same keys as database operations!

package main

import "github.com/wowsql/wowsql-go/WOWSQL"

// Using Anonymous Key (recommended for client-side auth operations)
auth := WOWSQL.NewAuthClient(WOWSQL.AuthConfig{
    ProjectURL: "https://your-project.wowsql.com",
    APIKey:     "wowsql_anon_your-anon-key-here",  // Same key as database operations!
})

// Using Service Role Key (for server-side auth operations)
auth := WOWSQL.NewAuthClient(WOWSQL.AuthConfig{
    ProjectURL: "https://your-project.wowsql.com",
    APIKey:     "wowsql_service_your-service-key-here",  // Same key as database operations!
})

// OAuth authentication
oauthResp, err := auth.GetOAuthAuthorizationURL("github", "https://app.example.com/auth/callback")

Note: The PublicAPIKey parameter is deprecated but still works for backward compatibility. Use APIKey instead.

Environment Variables

Best practice: Use environment variables for API keys:

package main

import (
    "os"
    "github.com/wowsql/wowsql-go/WOWSQL"
)

// UNIFIED AUTHENTICATION: Same keys for both operations!

// Database operations - Service Role Key
dbClient := WOWSQL.NewClient(
    os.Getenv("WOWSQL_PROJECT_URL"),
    os.Getenv("WOWSQL_SERVICE_ROLE_KEY"),  // or WOWSQL_ANON_KEY
)

// Authentication operations - Use the SAME key!
authClient := WOWSQL.NewAuthClient(WOWSQL.AuthConfig{
    ProjectURL: os.Getenv("WOWSQL_PROJECT_URL"),
    APIKey:     os.Getenv("WOWSQL_ANON_KEY"),  // Same key for client-side auth
    // Or use WOWSQL_SERVICE_ROLE_KEY for server-side auth
})
Key Usage Summary

โœจ UNIFIED AUTHENTICATION:

  • WOWSQLClient โ†’ Uses Service Role Key or Anonymous Key for database operations
  • ProjectAuthClient โ†’ Uses Anonymous Key (client-side) or Service Role Key (server-side) for authentication operations
  • Same keys work for both database AND authentication operations! ๐ŸŽ‰
  • Anonymous Key (wowsql_anon_...) โ†’ Client-side operations (auth + database)
  • Service Role Key (wowsql_service_...) โ†’ Server-side operations (auth + database)
Security Best Practices
  1. Never expose Service Role Key in client-side code or public repositories
  2. Use Anonymous Key for client-side authentication flows (same key as database operations)
  3. Use Anonymous Key for public database access with limited permissions
  4. Store keys in environment variables, never hardcode them
  5. Rotate keys regularly if compromised

๐Ÿ”ง Schema Management

Programmatically manage your database schema with the WOWSQLSchema client.

โš ๏ธ IMPORTANT: Schema operations require a Service Role Key (service_*). Anonymous keys will return a 403 Forbidden error.

Quick Start
package main

import "github.com/wowsql/wowsql-go/WOWSQL"

func main() {
    // Initialize schema client with SERVICE ROLE KEY
    schema := WOWSQL.NewSchemaClient(
        "https://your-project.wowsql.com",
        "service_xyz789...",  // โš ๏ธ Backend only! Never expose!
    )
}
Create Table
// Create a new table
trueVal := true
err := schema.CreateTable(WOWSQL.CreateTableRequest{
    TableName: "products",
    Columns: []WOWSQL.ColumnDefinition{
        {Name: "id", Type: "INT", AutoIncrement: &trueVal},
        {Name: "name", Type: "VARCHAR(255)", NotNull: &trueVal},
        {Name: "price", Type: "DECIMAL(10,2)", NotNull: &trueVal},
        {Name: "category", Type: "VARCHAR(100)"},
        {Name: "created_at", Type: "TIMESTAMP", Default: WOWSQL.strPtr("CURRENT_TIMESTAMP")},
    },
    PrimaryKey: WOWSQL.strPtr("id"),
    Indexes: []WOWSQL.IndexDefinition{
        {Name: "idx_category", Columns: []string{"category"}},
        {Name: "idx_price", Columns: []string{"price"}},
    },
})

if err != nil {
    log.Fatal(err)
}

fmt.Println("Table created successfully!")
Alter Table
// Add a new column
err := schema.AlterTable(WOWSQL.AlterTableRequest{
    TableName: "products",
    AddColumns: []WOWSQL.ColumnDefinition{
        {Name: "stock_quantity", Type: "INT", Default: WOWSQL.strPtr("0")},
    },
})

// Modify an existing column
err = schema.AlterTable(WOWSQL.AlterTableRequest{
    TableName: "products",
    ModifyColumns: []WOWSQL.ColumnDefinition{
        {Name: "price", Type: "DECIMAL(12,2)"},  // Increase precision
    },
})

// Drop a column
err = schema.AlterTable(WOWSQL.AlterTableRequest{
    TableName: "products",
    DropColumns: []string{"category"},
})

// Rename a column
err = schema.AlterTable(WOWSQL.AlterTableRequest{
    TableName: "products",
    RenameColumns: []WOWSQL.RenameColumn{
        {OldName: "name", NewName: "product_name"},
    },
})
Drop Table
// Drop a table
err := schema.DropTable("old_table", false)

// Drop with CASCADE (removes dependent objects)
err = schema.DropTable("products", true)
Execute Raw SQL
// Execute custom schema SQL
err := schema.ExecuteSQL(`
    CREATE INDEX idx_product_name 
    ON products(product_name);
`)

// Add a foreign key constraint
err = schema.ExecuteSQL(`
    ALTER TABLE orders 
    ADD CONSTRAINT fk_product 
    FOREIGN KEY (product_id) 
    REFERENCES products(id);
`)
Security & Best Practices
โœ… DO:
  • Use service role keys only in backend/server code
  • Store service keys in environment variables
  • Use anonymous keys for client-side data operations
  • Test schema changes in development first
โŒ DON'T:
  • Never expose service role keys in client code
  • Never commit service keys to version control
  • Don't use anonymous keys for schema operations (will fail)
Example: Backend Migration Script
package main

import (
    "fmt"
    "log"
    "os"
    
    "github.com/wowsql/wowsql-go/WOWSQL"
)

func runMigration() error {
    schema := WOWSQL.NewSchemaClient(
        os.Getenv("WOWSQL_PROJECT_URL"),
        os.Getenv("WOWSQL_SERVICE_KEY"),  // From env var
    )
    
    // Create users table
    trueVal := true
    err := schema.CreateTable(WOWSQL.CreateTableRequest{
        TableName: "users",
        Columns: []WOWSQL.ColumnDefinition{
            {Name: "id", Type: "INT", AutoIncrement: &trueVal},
            {Name: "email", Type: "VARCHAR(255)", Unique: &trueVal, NotNull: &trueVal},
            {Name: "name", Type: "VARCHAR(255)", NotNull: &trueVal},
            {Name: "created_at", Type: "TIMESTAMP", Default: WOWSQL.strPtr("CURRENT_TIMESTAMP")},
        },
        PrimaryKey: WOWSQL.strPtr("id"),
        Indexes: []WOWSQL.IndexDefinition{
            {Name: "idx_email", Columns: []string{"email"}},
        },
    })
    
    if err != nil {
        return fmt.Errorf("migration failed: %w", err)
    }
    
    fmt.Println("Migration completed!")
    return nil
}

func main() {
    if err := runMigration(); err != nil {
        log.Fatal(err)
    }
}
Error Handling
import (
    "errors"
    "github.com/wowsql/wowsql-go/WOWSQL"
)

schema := WOWSQL.NewSchemaClient(
    "https://your-project.wowsql.com",
    "service_xyz...",
)

err := schema.CreateTable(WOWSQL.CreateTableRequest{
    TableName: "test",
    Columns: []WOWSQL.ColumnDefinition{
        {Name: "id", Type: "INT"},
    },
})

if err != nil {
    var permErr *WOWSQL.PermissionError
    if errors.As(err, &permErr) {
        fmt.Printf("Permission denied: %s\n", permErr.Message)
        fmt.Println("Make sure you're using a SERVICE ROLE KEY, not an anonymous key!")
    } else {
        fmt.Printf("Error: %s\n", err)
    }
}

Troubleshooting

Error: "Invalid API key for project"

  • Ensure you're using the correct key type for the operation
  • Database operations require Service Role Key or Anonymous Key
  • Authentication operations require Anonymous Key (client-side) or Service Role Key (server-side)
  • Verify the key is copied correctly (no extra spaces)

Error: "Authentication failed"

  • Check that you're using the correct key: Anonymous Key for client-side, Service Role Key for server-side
  • Verify the project URL matches your dashboard
  • Ensure the key hasn't been revoked or expired

๐Ÿ“‹ Requirements

  • Go: 1.21+

๐Ÿ“„ License

MIT License - see LICENSE file for details.

๐Ÿค Contributing

Contributions are welcome! Please open an issue or submit a pull request.

๐Ÿ“ž Support


Made with โค๏ธ by the WOWSQL Team

Documentation ยถ

Index ยถ

Constants ยถ

This section is empty.

Variables ยถ

This section is empty.

Functions ยถ

This section is empty.

Types ยถ

type AlterTableRequest ยถ

type AlterTableRequest struct {
	TableName     string  `json:"table_name"`
	Operation     string  `json:"operation"` // add_column, drop_column, modify_column, rename_column
	ColumnName    *string `json:"column_name,omitempty"`
	ColumnType    *string `json:"column_type,omitempty"`
	NewColumnName *string `json:"new_column_name,omitempty"`
	Nullable      *bool   `json:"nullable,omitempty"`
	Default       *string `json:"default,omitempty"`
}

AlterTableRequest represents a request to alter a table

type ColumnDefinition ยถ

type ColumnDefinition struct {
	Name          string  `json:"name"`
	Type          string  `json:"type"`
	AutoIncrement *bool   `json:"auto_increment,omitempty"`
	Unique        *bool   `json:"unique,omitempty"`
	Nullable      *bool   `json:"nullable,omitempty"`
	Default       *string `json:"default,omitempty"`
}

ColumnDefinition represents a column definition for table creation

type CreateTableRequest ยถ

type CreateTableRequest struct {
	TableName  string             `json:"table_name"`
	Columns    []ColumnDefinition `json:"columns"`
	PrimaryKey *string            `json:"primary_key,omitempty"`
	Indexes    []string           `json:"indexes,omitempty"`
}

CreateTableRequest represents a request to create a table

type SchemaClient ยถ

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

SchemaClient handles schema management operations โš ๏ธ IMPORTANT: Requires SERVICE ROLE key, not anonymous key!

func NewSchemaClient ยถ

func NewSchemaClient(projectURL, serviceKey string) *SchemaClient

NewSchemaClient creates a new schema management client

โš ๏ธ IMPORTANT: Requires SERVICE ROLE key, not anonymous key!

func (*SchemaClient) AlterTable ยถ

func (c *SchemaClient) AlterTable(req AlterTableRequest) (*SchemaResponse, error)

AlterTable alters an existing table

Example:

err := schema.AlterTable(AlterTableRequest{
    TableName: "users",
    Operation: "add_column",
    ColumnName: strPtr("phone"),
    ColumnType: strPtr("VARCHAR(20)"),
})

func (*SchemaClient) CreateTable ยถ

func (c *SchemaClient) CreateTable(req CreateTableRequest) (*SchemaResponse, error)

CreateTable creates a new table in the database

Example:

trueVal := true
falseVal := false
err := schema.CreateTable(CreateTableRequest{
    TableName: "users",
    Columns: []ColumnDefinition{
        {Name: "id", Type: "INT", AutoIncrement: &trueVal},
        {Name: "email", Type: "VARCHAR(255)", Unique: &trueVal, Nullable: &falseVal},
    },
    PrimaryKey: strPtr("id"),
    Indexes: []string{"email"},
})

func (*SchemaClient) DropTable ยถ

func (c *SchemaClient) DropTable(tableName string, cascade bool) (*SchemaResponse, error)

DropTable drops a table from the database

โš ๏ธ WARNING: This operation cannot be undone!

func (*SchemaClient) ExecuteSQL ยถ

func (c *SchemaClient) ExecuteSQL(sql string) (*SchemaResponse, error)

ExecuteSQL executes raw SQL for schema operations

Example:

err := schema.ExecuteSQL(`
    CREATE TABLE products (
        id INT PRIMARY KEY AUTO_INCREMENT,
        name VARCHAR(255) NOT NULL
    )
`)

type SchemaResponse ยถ

type SchemaResponse struct {
	Success      bool   `json:"success"`
	Message      string `json:"message"`
	Table        string `json:"table,omitempty"`
	Operation    string `json:"operation,omitempty"`
	RowsAffected int    `json:"rows_affected,omitempty"`
	Warning      string `json:"warning,omitempty"`
}

SchemaResponse represents a schema operation response

Directories ยถ

Path Synopsis

Jump to

Keyboard shortcuts

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