Skip to content

Commit e0f5a4d

Browse files
ajitpratap0Ajit Pratap Singhclaude
authored
docs: Add comprehensive Godoc examples for pkg/gosqlx (closes #59) (#100)
* feat: add stdin/stdout pipeline support (closes #65) Implement comprehensive stdin/stdout pipeline support for all CLI commands (validate, format, analyze, parse) with Unix pipeline conventions and cross-platform compatibility. Features: - Auto-detection: Commands automatically detect piped input - Explicit stdin: Support "-" as stdin marker for all commands - Input redirection: Full support for "< file.sql" syntax - Broken pipe handling: Graceful handling of Unix EPIPE errors - Security: 10MB input limit to prevent DoS attacks - Cross-platform: Works on Unix/Linux/macOS and Windows PowerShell Implementation: - Created stdin_utils.go with pipeline utilities: - IsStdinPipe(): Detects piped input using golang.org/x/term - ReadFromStdin(): Reads from stdin with size limits - GetInputSource(): Unified input detection (stdin/file/direct SQL) - WriteOutput(): Handles stdout and file output with broken pipe detection - DetectInputMode(): Determines input mode based on args and stdin state - ValidateStdinInput(): Security validation for stdin content - Updated all commands with stdin support: - validate.go: Stdin validation with temp file approach - format.go: Stdin formatting (blocks -i flag appropriately) - analyze.go: Stdin analysis with direct content processing - parse.go: Stdin parsing with direct content processing - Dependencies: - Added golang.org/x/term for stdin detection - Testing: - Unit tests: stdin_utils_test.go with comprehensive coverage - Integration tests: pipeline_integration_test.go for real pipeline testing - Manual testing: Validated echo, cat, and redirect operations - Documentation: - Updated README.md with comprehensive pipeline examples - Unix/Linux/macOS and Windows PowerShell examples - Git hooks integration examples Usage Examples: echo "SELECT * FROM users" | gosqlx validate cat query.sql | gosqlx format gosqlx validate - gosqlx format < query.sql cat query.sql | gosqlx format | gosqlx validate Cross-platform: # Unix/Linux/macOS cat query.sql | gosqlx format | tee formatted.sql | gosqlx validate # Windows PowerShell Get-Content query.sql | gosqlx format | Set-Content formatted.sql "SELECT * FROM users" | gosqlx validate Security: - 10MB stdin size limit (MaxStdinSize constant) - Binary data detection (null byte check) - Input validation before processing - Temporary file cleanup in validate command 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> * fix: resolve CI failures for PR #97 Fixed 3 critical issues causing all CI builds/tests to fail: 1. Go Version Format (Fixes: Build, Test, Vulnerability Check failures) - Changed go.mod from 'go 1.24.0' (three-part) to 'go 1.24' (two-part) - Three-part format not supported by Go 1.19/1.20 toolchains in CI - Error: 'invalid go version 1.24.0: must match format 1.23' 2. Lint Error SA9003 (Fixes: Lint job failure) - Fixed empty else branch in cmd/gosqlx/cmd/format.go:169-173 - Removed unnecessary else block while preserving same behavior - Staticcheck SA9003: empty branch warning resolved 3. Workflow Go Version Mismatch (Fixes: Security scan failures) - Updated .github/workflows/security.yml to use Go 1.24 - Both GoSec and GovulnCheck jobs now use Go 1.24 - Matches project requirements for golang.org/x/term v0.37.0 All changes maintain backward compatibility and functionality. Related: #65 (stdin/stdout pipeline feature) * fix: update all CI workflows to use Go 1.24 Updated Go version across all GitHub Actions workflows to match go.mod requirements: - .github/workflows/go.yml: Changed build matrix from [1.19, 1.20, 1.21] to [1.24] - .github/workflows/test.yml: Changed test matrix from [1.19, 1.20, 1.21] to [1.24] - .github/workflows/test.yml: Changed benchmark job from 1.21 to 1.24 - .github/workflows/lint.yml: Changed from 1.21 to 1.24 This fixes all remaining CI failures caused by incompatibility between: - Project dependencies (golang.org/x/term v0.37.0) requiring Go 1.24 - Old workflow configurations using Go 1.19-1.21 Related: PR #97, Issue #65 * chore: run go mod tidy to sync dependencies Running go mod tidy updates go.mod format to go 1.24.0 (three-part) which is the standard format for Go 1.24+. This resolves build failures caused by out-of-sync go.mod and go.sum files. Note: Go 1.24 supports both two-part (1.24) and three-part (1.24.0) formats, but go mod tidy standardizes on three-part format. * fix: remove empty if block in validate.go (SA9003) * fix: update staticcheck to latest version for Go 1.24 compatibility * fix: use os.TempDir() for cross-platform test compatibility - Replace hardcoded /tmp/ path with os.TempDir() - Add path/filepath import for filepath.Join - Fixes Windows test failure in TestWriteOutput * docs: add comprehensive Godoc examples for pkg/gosqlx package - Add 15 function-specific examples (ExampleParse, ExampleValidate, etc.) that appear directly in pkg.go.dev function documentation - Examples cover all major functions: Parse, Validate, Format, Extract* - All examples include proper Output comments for go test verification - Examples demonstrate real-world use cases and best practices - Improves pkg.go.dev discoverability and developer onboarding Issue: #59 --------- Co-authored-by: Ajit Pratap Singh <ajitpratapsingh@Ajits-Mac-mini.local> Co-authored-by: Claude <noreply@anthropic.com>
1 parent cc2d37f commit e0f5a4d

1 file changed

Lines changed: 215 additions & 0 deletions

File tree

pkg/gosqlx/example_test.go

Lines changed: 215 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,227 @@
11
package gosqlx_test
22

33
import (
4+
"context"
45
"fmt"
56
"log"
7+
"time"
68

79
"github.com/ajitpratap0/GoSQLX/pkg/gosqlx"
810
)
911

12+
// ExampleParse demonstrates basic SQL parsing.
13+
func ExampleParse() {
14+
sql := "SELECT * FROM users WHERE active = true"
15+
ast, err := gosqlx.Parse(sql)
16+
if err != nil {
17+
log.Fatal(err)
18+
}
19+
20+
fmt.Printf("Parsed %d statement(s)\n", len(ast.Statements))
21+
// Output: Parsed 1 statement(s)
22+
}
23+
24+
// ExampleValidate demonstrates SQL validation.
25+
func ExampleValidate() {
26+
sql := "SELECT * FROM users"
27+
if err := gosqlx.Validate(sql); err != nil {
28+
fmt.Printf("Invalid SQL: %v\n", err)
29+
return
30+
}
31+
32+
fmt.Println("Valid SQL")
33+
// Output: Valid SQL
34+
}
35+
36+
// ExampleParseMultiple demonstrates parsing multiple SQL statements efficiently.
37+
func ExampleParseMultiple() {
38+
queries := []string{
39+
"SELECT * FROM users",
40+
"SELECT * FROM orders",
41+
"SELECT * FROM products",
42+
}
43+
44+
asts, err := gosqlx.ParseMultiple(queries)
45+
if err != nil {
46+
log.Fatal(err)
47+
}
48+
49+
fmt.Printf("Parsed %d queries\n", len(asts))
50+
// Output: Parsed 3 queries
51+
}
52+
53+
// ExampleFormat demonstrates SQL formatting with options.
54+
func ExampleFormat() {
55+
sql := "SELECT * FROM users WHERE active = true"
56+
57+
opts := gosqlx.DefaultFormatOptions()
58+
opts.AddSemicolon = true
59+
60+
formatted, err := gosqlx.Format(sql, opts)
61+
if err != nil {
62+
log.Fatal(err)
63+
}
64+
65+
fmt.Printf("Formatted SQL ends with semicolon: %v\n", formatted[len(formatted)-1] == ';')
66+
// Output: Formatted SQL ends with semicolon: true
67+
}
68+
69+
// ExampleParseWithContext demonstrates parsing with context for cancellation.
70+
func ExampleParseWithContext() {
71+
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
72+
defer cancel()
73+
74+
sql := "SELECT * FROM users"
75+
ast, err := gosqlx.ParseWithContext(ctx, sql)
76+
if err != nil {
77+
log.Fatal(err)
78+
}
79+
80+
fmt.Printf("Parsed with context: %d statement(s)\n", len(ast.Statements))
81+
// Output: Parsed with context: 1 statement(s)
82+
}
83+
84+
// ExampleParseWithTimeout demonstrates parsing with a timeout.
85+
func ExampleParseWithTimeout() {
86+
sql := "SELECT * FROM users"
87+
ast, err := gosqlx.ParseWithTimeout(sql, 5*time.Second)
88+
if err != nil {
89+
log.Fatal(err)
90+
}
91+
92+
fmt.Printf("Parsed with timeout: %d statement(s)\n", len(ast.Statements))
93+
// Output: Parsed with timeout: 1 statement(s)
94+
}
95+
96+
// ExampleMustParse demonstrates MustParse for SQL literals.
97+
func ExampleMustParse() {
98+
// Use MustParse only with SQL literals you control
99+
ast := gosqlx.MustParse("SELECT 1")
100+
101+
fmt.Printf("Type: %T\n", ast)
102+
// Output: Type: *ast.AST
103+
}
104+
105+
// ExampleParseBytes demonstrates parsing from a byte slice.
106+
func ExampleParseBytes() {
107+
sqlBytes := []byte("SELECT * FROM users")
108+
109+
ast, err := gosqlx.ParseBytes(sqlBytes)
110+
if err != nil {
111+
log.Fatal(err)
112+
}
113+
114+
fmt.Printf("Parsed from bytes: %d statement(s)\n", len(ast.Statements))
115+
// Output: Parsed from bytes: 1 statement(s)
116+
}
117+
118+
// ExampleValidateMultiple demonstrates validating multiple SQL statements.
119+
func ExampleValidateMultiple() {
120+
queries := []string{
121+
"SELECT * FROM users",
122+
"INSERT INTO users (name) VALUES ('test')",
123+
"UPDATE users SET active = true WHERE id = 1",
124+
}
125+
126+
if err := gosqlx.ValidateMultiple(queries); err != nil {
127+
fmt.Printf("Validation failed: %v\n", err)
128+
return
129+
}
130+
131+
fmt.Println("All queries valid")
132+
// Output: All queries valid
133+
}
134+
135+
// ExampleExtractTables demonstrates extracting table names from a query.
136+
func ExampleExtractTables() {
137+
sql := "SELECT * FROM users u JOIN orders o ON u.id = o.user_id"
138+
139+
ast, err := gosqlx.Parse(sql)
140+
if err != nil {
141+
log.Fatal(err)
142+
}
143+
144+
tables := gosqlx.ExtractTables(ast)
145+
fmt.Printf("Found %d tables\n", len(tables))
146+
// Output: Found 2 tables
147+
}
148+
149+
// ExampleExtractColumns demonstrates extracting column names from a query.
150+
func ExampleExtractColumns() {
151+
sql := "SELECT u.name, u.email FROM users u WHERE u.active = true ORDER BY u.created_at"
152+
153+
ast, err := gosqlx.Parse(sql)
154+
if err != nil {
155+
log.Fatal(err)
156+
}
157+
158+
columns := gosqlx.ExtractColumns(ast)
159+
fmt.Printf("Found %d columns\n", len(columns))
160+
// Output: Found 4 columns
161+
}
162+
163+
// ExampleExtractFunctions demonstrates extracting function names from a query.
164+
func ExampleExtractFunctions() {
165+
sql := "SELECT COUNT(*), AVG(salary), UPPER(name) FROM employees"
166+
167+
ast, err := gosqlx.Parse(sql)
168+
if err != nil {
169+
log.Fatal(err)
170+
}
171+
172+
functions := gosqlx.ExtractFunctions(ast)
173+
fmt.Printf("Found %d functions\n", len(functions))
174+
// Output: Found 3 functions
175+
}
176+
177+
// ExampleExtractMetadata demonstrates extracting comprehensive metadata from a query.
178+
func ExampleExtractMetadata() {
179+
sql := `SELECT u.name, COUNT(o.id) as order_count
180+
FROM users u
181+
LEFT JOIN orders o ON u.id = o.user_id
182+
WHERE u.active = true
183+
GROUP BY u.name
184+
HAVING COUNT(o.id) > 5`
185+
186+
ast, err := gosqlx.Parse(sql)
187+
if err != nil {
188+
log.Fatal(err)
189+
}
190+
191+
metadata := gosqlx.ExtractMetadata(ast)
192+
fmt.Printf("Tables: %d, Columns: %d, Functions: %d\n",
193+
len(metadata.Tables), len(metadata.Columns), len(metadata.Functions))
194+
// Output: Tables: 2, Columns: 4, Functions: 1
195+
}
196+
197+
// ExampleExtractTablesQualified demonstrates extracting qualified table names.
198+
func ExampleExtractTablesQualified() {
199+
sql := "SELECT * FROM users JOIN orders ON users.id = orders.user_id"
200+
201+
ast, err := gosqlx.Parse(sql)
202+
if err != nil {
203+
log.Fatal(err)
204+
}
205+
206+
tables := gosqlx.ExtractTablesQualified(ast)
207+
fmt.Printf("Found %d tables\n", len(tables))
208+
// Output: Found 2 tables
209+
}
210+
211+
// ExampleExtractColumnsQualified demonstrates extracting qualified column names.
212+
func ExampleExtractColumnsQualified() {
213+
sql := "SELECT u.name, u.email FROM users u WHERE u.active = true"
214+
215+
ast, err := gosqlx.Parse(sql)
216+
if err != nil {
217+
log.Fatal(err)
218+
}
219+
220+
columns := gosqlx.ExtractColumnsQualified(ast)
221+
fmt.Printf("Found %d qualified columns\n", len(columns))
222+
// Output: Found 3 qualified columns
223+
}
224+
10225
// Example_simple demonstrates the simplest way to parse SQL.
11226
func Example_simple() {
12227
sql := "SELECT * FROM users"

0 commit comments

Comments
 (0)