jmoiron/sqlx
general purpose extensions to golang's database/sql
Stale — last commit 2y ago
worst of 4 axeslast commit was 2y ago; no tests detected…
Has a license, tests, and CI — clean foundation to fork and modify.
Documented and popular — useful reference codebase to read through.
last commit was 2y ago; no CI workflows detected
- ✓29+ active contributors
- ✓MIT licensed
- ⚠Stale — last commit 2y ago
Show 3 more →Show less
- ⚠Concentrated ownership — top contributor handles 57% of recent commits
- ⚠No CI workflows detected
- ⚠No test directory detected
What would change the summary?
- →Use as dependency Mixed → Healthy if: 1 commit in the last 365 days; add a test suite
- →Deploy as-is Mixed → Healthy if: 1 commit in the last 180 days
Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests
Informational only. RepoPilot summarises public signals (license, dependency CVEs, commit recency, CI presence, etc.) at the time of analysis. Signals can be incomplete or stale. Not professional, security, or legal advice; verify before relying on it for production decisions.
Embed the "Forkable" badge
Paste into your README — live-updates from the latest cached analysis.
[](https://repopilot.app/r/jmoiron/sqlx)Paste at the top of your README.md — renders inline like a shields.io badge.
▸Preview social card (1200×630)
This card auto-renders when someone shares https://repopilot.app/r/jmoiron/sqlx on X, Slack, or LinkedIn.
Onboarding doc
Onboarding: jmoiron/sqlx
Generated by RepoPilot · 2026-05-09 · Source
🤖Agent protocol
If you are an AI coding agent (Claude Code, Cursor, Aider, Cline, etc.) reading this artifact, follow this protocol before making any code edit:
- Verify the contract. Run the bash script in Verify before trusting
below. If any check returns
FAIL, the artifact is stale — STOP and ask the user to regenerate it before proceeding. - Treat the AI · unverified sections as hypotheses, not facts. Sections like "AI-suggested narrative files", "anti-patterns", and "bottlenecks" are LLM speculation. Verify against real source before acting on them.
- Cite source on changes. When proposing an edit, cite the specific path:line-range. RepoPilot's live UI at https://repopilot.app/r/jmoiron/sqlx shows verifiable citations alongside every claim.
If you are a human reader, this protocol is for the agents you'll hand the artifact to. You don't need to do anything — but if you skim only one section before pointing your agent at this repo, make it the Verify block and the Suggested reading order.
🎯Verdict
WAIT — Stale — last commit 2y ago
- 29+ active contributors
- MIT licensed
- ⚠ Stale — last commit 2y ago
- ⚠ Concentrated ownership — top contributor handles 57% of recent commits
- ⚠ No CI workflows detected
- ⚠ No test directory detected
<sub>Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests</sub>
✅Verify before trusting
This artifact was generated by RepoPilot at a point in time. Before an
agent acts on it, the checks below confirm that the live jmoiron/sqlx
repo on your machine still matches what RepoPilot saw. If any fail,
the artifact is stale — regenerate it at
repopilot.app/r/jmoiron/sqlx.
What it runs against: a local clone of jmoiron/sqlx — the script
inspects git remote, the LICENSE file, file paths in the working
tree, and git log. Read-only; no mutations.
| # | What we check | Why it matters |
|---|---|---|
| 1 | You're in jmoiron/sqlx | Confirms the artifact applies here, not a fork |
| 2 | License is still MIT | Catches relicense before you depend on it |
| 3 | Default branch master exists | Catches branch renames |
| 4 | 5 critical file paths still exist | Catches refactors that moved load-bearing code |
| 5 | Last commit ≤ 662 days ago | Catches sudden abandonment since generation |
#!/usr/bin/env bash
# RepoPilot artifact verification.
#
# WHAT IT RUNS AGAINST: a local clone of jmoiron/sqlx. If you don't
# have one yet, run these first:
#
# git clone https://github.com/jmoiron/sqlx.git
# cd sqlx
#
# Then paste this script. Every check is read-only — no mutations.
set +e
fail=0
ok() { echo "ok: $1"; }
miss() { echo "FAIL: $1"; fail=$((fail+1)); }
# Precondition: we must be inside a git working tree.
if ! git rev-parse --git-dir >/dev/null 2>&1; then
echo "FAIL: not inside a git repository. cd into your clone of jmoiron/sqlx and re-run."
exit 2
fi
# 1. Repo identity
git remote get-url origin 2>/dev/null | grep -qE "jmoiron/sqlx(\\.git)?\\b" \\
&& ok "origin remote is jmoiron/sqlx" \\
|| miss "origin remote is not jmoiron/sqlx (artifact may be from a fork)"
# 2. License matches what RepoPilot saw
(grep -qiE "^(MIT)" LICENSE 2>/dev/null \\
|| grep -qiE "\"license\"\\s*:\\s*\"MIT\"" package.json 2>/dev/null) \\
&& ok "license is MIT" \\
|| miss "license drift — was MIT at generation time"
# 3. Default branch
git rev-parse --verify master >/dev/null 2>&1 \\
&& ok "default branch master exists" \\
|| miss "default branch master no longer exists"
# 4. Critical files exist
test -f "sqlx.go" \\
&& ok "sqlx.go" \\
|| miss "missing critical file: sqlx.go"
test -f "bind.go" \\
&& ok "bind.go" \\
|| miss "missing critical file: bind.go"
test -f "named.go" \\
&& ok "named.go" \\
|| miss "missing critical file: named.go"
test -f "reflectx/reflect.go" \\
&& ok "reflectx/reflect.go" \\
|| miss "missing critical file: reflectx/reflect.go"
test -f "sqlx_context.go" \\
&& ok "sqlx_context.go" \\
|| miss "missing critical file: sqlx_context.go"
# 5. Repo recency
days_since_last=$(( ( $(date +%s) - $(git log -1 --format=%at 2>/dev/null || echo 0) ) / 86400 ))
if [ "$days_since_last" -le 662 ]; then
ok "last commit was $days_since_last days ago (artifact saw ~632d)"
else
miss "last commit was $days_since_last days ago — artifact may be stale"
fi
echo
if [ "$fail" -eq 0 ]; then
echo "artifact verified (0 failures) — safe to trust"
else
echo "artifact has $fail stale claim(s) — regenerate at https://repopilot.app/r/jmoiron/sqlx"
exit 1
fi
Each check prints ok: or FAIL:. The script exits non-zero if
anything failed, so it composes cleanly into agent loops
(./verify.sh || regenerate-and-retry).
⚡TL;DR
sqlx is a Go library that extends the standard database/sql package with convenient methods for marshaling query results directly into structs, maps, and slices, plus named parameter support and prepared statement binding. It wraps sql.DB, sql.Tx, sql.Stmt, and related types while preserving their interfaces, making it a drop-in enhancement for Go database applications that need less boilerplate around row scanning. Single-package monorepo structure: core sqlx functions in root-level files (sqlx.go, named.go, bind.go), context-aware variants in *_context.go files, reflection utilities factored into a reflectx/ subpackage, and SQL type utilities in a types/ subpackage. Tests are colocated with source (sqlx_test.go next to sqlx.go), and a Makefile handles common tasks.
👥Who it's for
Go backend engineers and data access layer developers who want to eliminate repetitive rows.Scan() boilerplate and use struct field tags (like db:"column_name") to automatically unmarshal database rows, especially those working with SQL queries that benefit from named parameters instead of positional ? placeholders.
🌱Maturity & risk
Production-ready and actively maintained. The library has solid test coverage (separate *_test.go files in the root and subdirectories), CircleCI CI/CD configured in .circleci/config.yml, and recent changes documented (v1.3.0 features like DB.Connx() and BindDriver() are current). Requires Go 1.10+, indicating long-term stability focus.
Low risk for production use. Dependencies are minimal and stable—only three driver packages (go-sql-driver/mysql, lib/pq, mattn/go-sqlite3)—and the codebase is purely Go with no external runtime dependencies. Single maintainer (jmoiron) is a known risk factor, but the API surface is stable and the library has been widely adopted. No breaking changes are mentioned in recent releases.
Active areas of work
Recent development added context support (sqlx_context.go, named_context.go, named_context_test.go), the ability to control driver-specific bind variable syntax via BindDriver(), batch insertion support for []map[string]interface{}, and performance optimizations in sqlx.In(). The v1.3.0 release introduced DB.Connx() to work with the sql.Conn pooling interface added in Go 1.10.
🚀Get running
git clone https://github.com/jmoiron/sqlx.git
cd sqlx
go mod download
make test
Daily commands:
This is a library, not a runnable application. To verify the build: make test runs the test suite against configured databases. Individual test files (sqlx_test.go, bind_test.go, named_test.go, etc.) can be run with go test ./...
🗺️Map of the codebase
sqlx.go— Core entry point defining DB, TX, Rows, and Stmt wrapper types that extend database/sql with Get/Select functionality.bind.go— Implements named parameter binding and query argument interpolation, essential for the library's parameter substitution feature.named.go— Handles named query parsing and execution without context support, a foundational pattern for the library's query model.reflectx/reflect.go— Core reflection utilities for mapping database columns to struct fields and marshaling rows into Go types.sqlx_context.go— Context-aware variants of core DB operations (QueryContext, ExecContext, etc.) required for modern Go database patterns.types/types.go— Custom type wrappers (NullInt64, NullString, JSONText) for safe nullable and JSON column handling.go.mod— Declares minimal external dependencies (MySQL, PostgreSQL, SQLite drivers) and Go version baseline.
🧩Components & responsibilities
- sqlx.DB / sqlx.TX / sqlx.Stmt (Go reflection, database/sql) — Wrapper types that extend database/sql with Get/Select convenience methods; manage underlying sql.DB/TX/Stmt handles.
- Failure mode: If underlying driver connection fails, queries return driver errors; wrapper is transparent to error handling.
- bind (Parameter Binding Layer) (String parsing, regex) — Parses named parameters (:name) and converts to dialect-specific positional syntax; interpolates arguments into query.
- Failure mode: Malformed named queries (unmatched colons, missing args) cause bind errors; passed through to caller.
- reflectx (Reflection & Mapping) (Go reflect package) — Inspects Go struct tags (db:"columnname"), discovers fields, matches database columns, and scans Rows into struct instances.
- Failure mode: Type mismatch (e.g., string column to int field) causes sql.Scan error; missing columns silently map to zero values.
- types (Custom Nullable Types) (Go interface conformance, JSON marshaling) — Provides NullInt64, NullString, NullTime, JSONText with sql.Scanner and driver.Valuer implementations for NULL-safe operations.
- Failure mode: Invalid JSON in JSONText field causes Scan error; NULL values safely populate Valid=false.
🔀Data flow
Application Code→sqlx.DB— User calls Get/Select with context, query string, struct pointer, and named argssqlx.DB→bind— Query string and args passed to Bind() to interpolate named parameters into driver-specific syntaxbind→sqlx.— undefined
🛠️How to make changes
Add support for a new database driver
- Add driver to go.mod dependencies and import in test files (
go.mod) - Add dialect-specific binding tests in bind_test.go to ensure named parameter syntax matches the new driver (
bind_test.go) - If driver has unique type mapping needs, extend types/types.go with custom Scanner/Valuer implementations (
types/types.go) - Test end-to-end with sqlx_test.go to verify Get/Select work correctly on new driver (
sqlx_test.go)
Add a new custom nullable type
- Define struct type in types/types.go with Valid flag and SQL driver Scanner/Valuer methods (
types/types.go) - Write unit tests in types/types_test.go covering nil, zero, and valid values (
types/types_test.go) - Document usage in types/README.md with examples (
types/README.md)
Add a new query convenience method to DB/TX
- Implement method on sqlx.DB or sqlx.TX in sqlx.go following Get/Select pattern (
sqlx.go) - Add context-aware variant in sqlx_context.go with ...Context suffix (
sqlx_context.go) - Add integration tests in sqlx_test.go and sqlx_context_test.go (
sqlx_test.go)
Improve struct-to-column mapping behavior
- Understand current tag parsing and field discovery in reflectx/reflect.go (
reflectx/reflect.go) - Add test cases in reflectx/reflect_test.go for new mapping scenarios (nested structs, custom types, etc.) (
reflectx/reflect_test.go) - Implement mapping logic in reflectx/reflect.go, then verify with sqlx_test.go Get/Select tests (
reflectx/reflect.go)
🔧Why these technologies
- Go reflection (reflect package + custom reflectx) — Enables automatic marshaling of arbitrary database rows into user-defined structs without code generation at runtime.
- database/sql driver interface extensions — Maintains 100% compatibility with Go's standard database/sql by wrapping rather than replacing, allowing gradual adoption.
- Named parameter interpolation (bind.go) — Provides ergonomic alternative to positional ? or $N parameters; handles dialect differences (MySQL ?, PostgreSQL $1, SQLite ?) transparently.
- Support for multiple SQL drivers (MySQL, PostgreSQL, SQLite) — Library must abstract over driver-specific syntax and type handling to serve as a general-purpose database/sql extension.
⚖️Trade-offs already made
-
Reflection-based marshaling instead of code generation (sqlc-style)
- Why: Avoid build-time complexity and tool overhead; enable dynamic query execution.
- Consequence: Slightly lower runtime performance (~5–10%) but much simpler integration and easier debugging; no DSL or code generator required.
-
Leave underlying sql.DB/TX/Rows/Stmt interfaces untouched; compose rather than inherit
- Why: Ensure sqlx types are a strict superset of database/sql, allowing seamless drop-in replacement.
- Consequence: Must wrap types and duplicate some boilerplate methods, but zero breaking changes or surprise behavior.
-
Named parameters as syntactic sugar over positional arguments via bind layer
- Why: Avoid modifying SQL string semantics; keep queries compatible with raw database/sql.
- Consequence: Slight overhead in query pre-processing, but no dependency on custom SQL parser or type system.
-
Custom nullable types (NullInt64, etc.) in types/ subpackage rather than in core
- Why: Keep core lean; users opt-in to extended type support only if needed.
- Consequence: Requires extra import; not all nullable use cases covered by types/ alone.
🚫Non-goals (don't propose these)
- Does not provide query builder or ORM abstraction—focus is on mapping and convenience, not schema or relationship management.
- Does not handle database migrations or schema versioning.
- Does not provide connection pooling beyond what database/sql offers.
- Does not support non-SQL databases or custom SQL dialects beyond MySQL, PostgreSQL, SQLite.
- Does not provide query validation or static type checking at compile time.
🪤Traps & gotchas
Named parameters require explicit :name syntax; positional ? placeholders are ignored when using Named(). Driver binding type is auto-detected from dsl.Open() but may fail for custom/wrapped drivers—use BindDriver() to register manually. The reflectx tag parser requires exact field names and case sensitivity; misspelled or missing tags silently skip columns. Tests expect SQLX_* environment variables or local SQLite for CI—see .circleci/config.yml for the actual test database setup. Column name ambiguity from duplicate names in joins is a known limitation mentioned in README; use AS aliases or manual Scan().
🏗️Architecture
💡Concepts to learn
- Struct tag reflection and field mapping — sqlx's core value is automating row-to-struct binding via
db:tags; understanding howreflectxcaches and traverses struct fields is essential to using it correctly and diagnosing mapping bugs - Named parameters (
:paramsyntax) and query binding translation — Different SQL drivers use different placeholder syntaxes (?,$1,:1); sqlx abstracts this via theBindtype and driver registry so users write driver-agnostic queries - Type wrapping and interface preservation — sqlx wraps
sql.DB,sql.Tx, etc. without breaking their interfaces—this 'composition over modification' pattern lets you adopt sqlx incrementally in legacydatabase/sqlcodebases - Embedded struct field flattening — sqlx flattens embedded struct fields during scanning (e.g., if
UserembedsAddress, columns map toAddressfields directly); this requires understanding Go's embedding semantics - Prepared statement binding and query parameterization — sqlx's
Named()function converts named parameters to driver-specific placeholders in prepared statements; understanding the binding pipeline is crucial for secure SQL injection prevention - Context-aware database operations (Go 1.10+) — The
*_context.gofiles provideQueryContext(),ExecContext(), etc. for cancellation and timeouts; sqlx mirrors Go's stdlib pattern for graceful query shutdown - Nullable SQL type handling and custom type marshaling — The
types/subpackage providesNullTime,JSONText, etc. to safely handle NULL columns and complex types; understanding these is needed for robust schema design
🔗Related repos
uptrace/bun— Modern Go ORM built on sqlx principles but adds a query builder and relationships; alternative if you need more abstractionupper/db— Similar database abstraction library for Go with struct mapping and query building; direct competitor with similar goalsjmoiron/modl— By the same author; a lightweight ORM that builds on top of sqlx for entities and relationshipslib/pq— PostgreSQL driver for Go used by sqlx in its test suite and a key dependency for PG supportgo-sql-driver/mysql— MySQL driver for Go; another core dependency that sqlx wraps and binds for
🪄PR ideas
To work on one of these in Claude Code or Cursor, paste:
Implement the "<title>" PR idea from CLAUDE.md, working through the checklist as the task list.
Add comprehensive context deadline/timeout handling tests in sqlx_context_test.go
The repo has sqlx_context.go and sqlx_context_test.go for context support, but testing context cancellation and deadline scenarios is critical for production use. This PR would add tests for query timeout handling, connection pool behavior under deadline pressure, and proper context propagation across nested operations—gaps that could cause subtle bugs in real applications.
- [ ] Review existing tests in sqlx_context_test.go and identify missing context deadline scenarios
- [ ] Add test cases for context.WithCancel, context.WithTimeout, and context.WithDeadline across Query, Exec, and transaction methods
- [ ] Add test case for context deadline propagation through nested transactions
- [ ] Verify tests pass against all three database drivers (MySQL, PostgreSQL, SQLite) in Makefile/CircleCI config
Add missing bind parameter validation tests in bind_test.go
The bind.go file handles parameter binding for multiple SQL dialects, but bind_test.go likely lacks comprehensive edge cases. This PR would add tests for malformed queries, invalid parameter counts, SQL injection attempts with named parameters, and edge cases like empty strings or nil values—ensuring robustness across MySQL, PostgreSQL, and SQLite dialects.
- [ ] Audit bind.go for different binding strategies (?, :name, $n, etc.)
- [ ] Add test cases in bind_test.go for mismatched parameter counts vs actual arguments
- [ ] Add test cases for special characters and edge values (nil, empty strings, unicode) in named parameters
- [ ] Add test cases verifying SQL injection is not possible through the binding layer
- [ ] Run tests to verify all three driver variants work correctly
Add reflectx caching and performance benchmark tests in reflectx/reflect_test.go
The reflectx package is core to sqlx's row marshaling, but reflect_test.go may lack benchmarks and caching validation tests. This PR would add BenchmarkScan tests, verify struct field caching is working correctly (avoiding repeated reflection), and test performance with large struct hierarchies—critical for identifying bottlenecks in high-throughput database applications.
- [ ] Review reflectx/reflect.go for any caching mechanisms in place
- [ ] Add Benchmark functions (BenchmarkScan, BenchmarkMapRowToStruct) in reflect_test.go with various struct complexities
- [ ] Add tests verifying reflection cache hits (if applicable) to ensure repeated scans don't re-reflect
- [ ] Add test cases for deeply nested struct hierarchies and struct tags with edge cases
- [ ] Document benchmark baseline and expected performance characteristics in reflectx/README.md
🌿Good first issues
- Add missing tests for context cancellation behavior in
sqlx_context.go—the file exists butsqlx_context_test.gomay have incomplete coverage for deadline exceeded and cancellation scenarios: Context support is a core feature in Go; ensuring it works end-to-end with query timeouts is critical - Expand
bind_test.goto cover Oracle bind syntax (:1,:2positional) if not already present—only MySQL (?) and PostgreSQL ($1) may be fully exercised: TheBindDriver()feature added in v1.3.0 claims to support any driver, but the test suite may not validate all major databases - Document the
reflectx.FieldInfocaching strategy and its interaction with goroutines inreflectx/README.md—clarify whether the cache is safe for concurrent use: Field introspection is called on every struct scan; understanding cache thread-safety is vital for production code
⭐Top contributors
Click to expand
Top contributors
- @jmoiron — 57 commits
- @QuangTung97 — 5 commits
- [@Alan Braithwaite](https://github.com/Alan Braithwaite) — 4 commits
- @dlsniper — 3 commits
- @nussjustin — 3 commits
📝Recent commits
Click to expand
Recent commits
41dac16— Merge pull request #927 from ninjadq/add_azuresql_driver_bind (dlsniper)25a5113— Add azuresql driver bind (Qian Deng)bc91699— Upgrade dependencies (#909) (dlsniper)dcafbc9— Introduce CircleCI (#922) (dlsniper)28212d4— Merge pull request #767 from liftoffio/gpark.sqlx.reset-slice (jmoiron)421d1cd— Make Select reset slice length (gayoungpark)a62bc60— Merge pull request #728 from s7v7nislands/update_mysql_version (jmoiron)92bfa36— Merge pull request #734 from QuangTung97/fix/named-exec-values (jmoiron)e6cd7ae— Merge pull request #731 from 2403905/godror (jmoiron)4b6b69e— Multiline indented query test case (QuangTung97)
🔒Security observations
The sqlx codebase appears to be a well-structured database abstraction library with generally sound security design principles. However, the project uses a Go version from 2018 (1.10), which is a significant concern due to accumulated security patches in newer versions. The library itself promotes parameterized queries which help prevent SQL injection, but developer misuse remains a risk. The absence of a security policy and lack of recent dependency updates are additional minor concerns. Overall security posture is moderate; immediate action should be taken to update the Go version.
- Medium · Outdated Go Version —
go.mod. The project specifies 'go 1.10' in go.mod, which is extremely outdated (released in February 2018). This version lacks numerous security patches and bug fixes from subsequent Go releases, potentially exposing the codebase to known vulnerabilities in the Go standard library. Fix: Update to the latest stable Go version (1.21 or later). Modify 'go 1.10' to 'go 1.21' or the latest available version, and regenerate go.sum with 'go mod tidy'. - Medium · Potential SQL Injection via Dynamic Query Construction —
bind.go, named.go, sqlx.go. As a database abstraction library, sqlx provides functions like bind.go and named.go that handle SQL query construction. Without careful use, developers could construct dynamic SQL queries vulnerable to injection attacks if user input is not properly parameterized. The library itself appears to support parameterized queries, but misuse is possible. Fix: Ensure all documentation emphasizes parameterized queries and prepared statements. Review code examples to demonstrate safe patterns. Consider adding warnings in function documentation about SQL injection risks when building queries dynamically. - Low · Missing Security Policy —
Repository root. No SECURITY.md file is present in the repository to provide security reporting guidelines or vulnerability disclosure procedures. This makes it harder for security researchers to responsibly report vulnerabilities. Fix: Create a SECURITY.md file with clear instructions for reporting security vulnerabilities privately (e.g., via GitHub Security Advisory or email), estimated response times, and supported versions receiving security updates. - Low · Database Driver Dependencies May Have Vulnerabilities —
go.mod. The project depends on specific versions of database drivers (mysql v1.8.1, pq v1.10.9, sqlite3 v1.14.22). While these appear to be reasonably recent versions, they should be regularly scanned for known vulnerabilities. Fix: Regularly run 'go list -json -m all | nancy sleuth' or 'go list -m all | nancy sleuth' to check for known vulnerabilities in dependencies. Consider enabling Dependabot or similar automated dependency scanning on the GitHub repository.
LLM-derived; treat as a starting point, not a security audit.
👉Where to read next
- Open issues — current backlog
- Recent PRs — what's actively shipping
- Source on GitHub
Generated by RepoPilot. Verdict based on maintenance signals — see the live page for receipts. Re-run on a new commit to refresh.