Header image

Quality | Xdumpgo Tutorial Extra

./xdumpgo --version

Extra Quality Tip: Use Go 1.20+ to avoid memory alignment bugs.


We need a writer that handles escaping and SQL formatting on the fly.

package main

import ( "database/sql" "fmt" "io" "os" "strings" xdumpgo tutorial extra quality

_ "github.com/lib/pq" // Example using PostgreSQL

)

// SQLDumper handles the streaming dump process type SQLDumper struct db *sql.DB output io.Writer

func NewSQLDumper(db *sql.DB, output io.Writer) *SQLDumper return &SQLDumperdb: db, output: output Extra Quality Tip : Use Go 1

// DumpTable streams a specific table to the output writer func (d *SQLDumper) DumpTable(tableName string) error { // 1. Setup the streaming query // We use a transaction with READ ONLY to ensure consistency tx, err := d.db.Begin() if err != nil return fmt.Errorf("failed to begin transaction: %w", err) defer tx.Rollback() // Safe to rollback read-only tx

// 2. Execute Query
// For true "extra quality", you would implement cursor/pagination here
// for massive datasets, but Rows() is a streaming iterator in Go.
rows, err := tx.Query(fmt.Sprintf("SELECT * FROM %s", tableName))
if err != nil 
	return fmt.Errorf("query failed: %w", err)
defer rows.Close()
columns, err := rows.Columns()
if err != nil 
	return err
// 3. Write Header
header := fmt.Sprintf("\n-- Dumping data for table: %s\n", tableName)
d.output.Write([]byte(header))
// 4. Stream Processing
// We create a slice of empty interfaces to hold raw pointers
values := make([]interface{}, len(columns))
valuePtrs := make([]interface{}, len(columns))
for i := range columns 
	valuePtrs[i] = &values[i]
for rows.Next() 
	// Scan into pointers
	if err := rows.Scan(valuePtrs...); err != nil 
		return err
// Build the INSERT statement dynamically
	if err := d.writeInsert(tableName, columns, valuePtrs); err != nil 
		return err
return rows.Err()

}

// writeInsert constructs and writes a single INSERT statement func (d *SQLDumper) writeInsert(table string, cols []string, vals []interface{}) error var sb strings.Builder We need a writer that handles escaping and

sb.WriteString(fmt.Sprintf("INSERT INTO %s (", table))
for i, col := range cols 
	if i > 0 
		sb.WriteString(", ")
sb.WriteString(col)
sb.WriteString(") VALUES (")
for i, val := range vals 
	if i > 0 
		sb.WriteString(", ")
// Type switching for proper SQL escaping
	switch v := val.(type) 
	case *string:
		// In production, use proper escaping libraries to prevent SQL injection in dumps
		sb.WriteString(fmt.Sprintf("'%s'", *v)) 
	case *int, *int64, *float64:
		sb.WriteString(fmt.Sprintf("%v", v))
	case *bool:
		if *v 
			sb.WriteString("TRUE")
		 else 
			sb.WriteString("FALSE")
case nil:
		sb.WriteString("NULL")
	default:
		// Handle byte arrays or unknown types
		sb.WriteString(fmt.Sprintf("'%v'", v))
sb.WriteString(");\n")
_, err := d.output.Write([]byte(sb.String()))
return err

func main() connStr := "user=postgres dbname=mydb sslmode=disable" db, err := sql.Open("postgres", connStr) if err != nil panic(err) defer db.Close()

// Create output file
f, err := os.Create("dump.sql")
if err != nil 
	panic(err)
defer f.Close()
dumper := NewSQLDumper(db, f)
fmt.Println("Starting Extra Quality Dump...")
if err := dumper.DumpTable("users"); err != nil 
	panic(err)
fmt.Println("Dump completed successfully.")


./xdumpgo dump \
  --pid 1234 \
  --output high_quality.dump \
  --full-page \
  --ignore-paged \
  --preserve-perms \
  --verify-checksum \
  --thread-sync

| Flag | Purpose | |------|---------| | --full-page | Dump entire pages, not just requested ranges | | --ignore-paged | Skip swapped-out pages (prevents corrupted data) | | --preserve-perms | Store original memory permissions | | --verify-checksum | Calculate SHA256 after dump | | --thread-sync | Suspend threads during dump (atomic snapshot) |


./xdumpgo --version

Extra Quality Tip: Use Go 1.20+ to avoid memory alignment bugs.


We need a writer that handles escaping and SQL formatting on the fly.

package main

import ( "database/sql" "fmt" "io" "os" "strings"

_ "github.com/lib/pq" // Example using PostgreSQL

)

// SQLDumper handles the streaming dump process type SQLDumper struct db *sql.DB output io.Writer

func NewSQLDumper(db *sql.DB, output io.Writer) *SQLDumper return &SQLDumperdb: db, output: output

// DumpTable streams a specific table to the output writer func (d *SQLDumper) DumpTable(tableName string) error { // 1. Setup the streaming query // We use a transaction with READ ONLY to ensure consistency tx, err := d.db.Begin() if err != nil return fmt.Errorf("failed to begin transaction: %w", err) defer tx.Rollback() // Safe to rollback read-only tx

// 2. Execute Query
// For true "extra quality", you would implement cursor/pagination here
// for massive datasets, but Rows() is a streaming iterator in Go.
rows, err := tx.Query(fmt.Sprintf("SELECT * FROM %s", tableName))
if err != nil 
	return fmt.Errorf("query failed: %w", err)
defer rows.Close()
columns, err := rows.Columns()
if err != nil 
	return err
// 3. Write Header
header := fmt.Sprintf("\n-- Dumping data for table: %s\n", tableName)
d.output.Write([]byte(header))
// 4. Stream Processing
// We create a slice of empty interfaces to hold raw pointers
values := make([]interface{}, len(columns))
valuePtrs := make([]interface{}, len(columns))
for i := range columns 
	valuePtrs[i] = &values[i]
for rows.Next() 
	// Scan into pointers
	if err := rows.Scan(valuePtrs...); err != nil 
		return err
// Build the INSERT statement dynamically
	if err := d.writeInsert(tableName, columns, valuePtrs); err != nil 
		return err
return rows.Err()

}

// writeInsert constructs and writes a single INSERT statement func (d *SQLDumper) writeInsert(table string, cols []string, vals []interface{}) error var sb strings.Builder

sb.WriteString(fmt.Sprintf("INSERT INTO %s (", table))
for i, col := range cols 
	if i > 0 
		sb.WriteString(", ")
sb.WriteString(col)
sb.WriteString(") VALUES (")
for i, val := range vals 
	if i > 0 
		sb.WriteString(", ")
// Type switching for proper SQL escaping
	switch v := val.(type) 
	case *string:
		// In production, use proper escaping libraries to prevent SQL injection in dumps
		sb.WriteString(fmt.Sprintf("'%s'", *v)) 
	case *int, *int64, *float64:
		sb.WriteString(fmt.Sprintf("%v", v))
	case *bool:
		if *v 
			sb.WriteString("TRUE")
		 else 
			sb.WriteString("FALSE")
case nil:
		sb.WriteString("NULL")
	default:
		// Handle byte arrays or unknown types
		sb.WriteString(fmt.Sprintf("'%v'", v))
sb.WriteString(");\n")
_, err := d.output.Write([]byte(sb.String()))
return err

func main() connStr := "user=postgres dbname=mydb sslmode=disable" db, err := sql.Open("postgres", connStr) if err != nil panic(err) defer db.Close()

// Create output file
f, err := os.Create("dump.sql")
if err != nil 
	panic(err)
defer f.Close()
dumper := NewSQLDumper(db, f)
fmt.Println("Starting Extra Quality Dump...")
if err := dumper.DumpTable("users"); err != nil 
	panic(err)
fmt.Println("Dump completed successfully.")


./xdumpgo dump \
  --pid 1234 \
  --output high_quality.dump \
  --full-page \
  --ignore-paged \
  --preserve-perms \
  --verify-checksum \
  --thread-sync

| Flag | Purpose | |------|---------| | --full-page | Dump entire pages, not just requested ranges | | --ignore-paged | Skip swapped-out pages (prevents corrupted data) | | --preserve-perms | Store original memory permissions | | --verify-checksum | Calculate SHA256 after dump | | --thread-sync | Suspend threads during dump (atomic snapshot) |