Analyzer: helps uncover bugs by reporting a diagnostic for mistakes of *sql.Rows usage.

Overview

sqlrows

CircleCI

sqlrows is a static code analyzer which helps uncover bugs by reporting a diagnostic for mistakes of sql.Rows usage.

Install

You can get sqlrows by go get command.

$ go get -u github.com/gostaticanalysis/sqlrows

QuickStart

sqlrows run with go vet as below when Go is 1.12 and higher.

$ go vet -vettool=$(which sqlrows) github.com/you/sample_api/...

When Go is lower than 1.12, just run sqlrows command with the package name (import path).

But it cannot accept some options such as --tags.

$ sqlrows github.com/you/sample_api/...

Analyzer

sqlrows checks a common mistake when using *sql.Rows.

At first, you must call rows.Close() in a defer function. A connection will not be reused if you unexpectedly failed to scan records and forgot to close *sql.Rows.

rows, err := db.QueryContext(ctx, "SELECT * FROM users")
if err != nil {
    return nil, err
}

for rows.Next() {
	err = rows.Scan(...)
	if err != nil {
		return nil, err // NG: this return will not release a connection.
	}
}

And, if you defer a function call to close the *sql.Rows before checking the error that determines whether the return is valid, it will mean you dually call rows.Close().

rows, err := db.QueryContext(ctx, "SELECT * FROM users")
defer rows.Close() // NG: using rows before checking for errors
if err != nil {
    return nil, err
}

It may cause panic and nil-pointer reference but it won't clearly teach you that is due to them.

You might also like...
Write your SQL queries in raw files with all benefits of modern IDEs, use them in an easy way inside your application with all the profit of compile time constants

About qry is a general purpose library for storing your raw database queries in .sql files with all benefits of modern IDEs, instead of strings and co

Type safe SQL query builder and struct mapper for Go

sq (Structured Query) 🎯 🏆 sq is a code-generated, type safe query builder and struct mapper for Go. 🏆 🎯 Documentation • Reference • Examples This

Fast SQL query builder for Go

sqlf A fast SQL query builder for Go. sqlf statement builder provides a way to: Combine SQL statements from fragments of raw SQL and arguments that ma

Fluent SQL generation for golang

sqrl - fat-free version of squirrel - fluent SQL generator for Go Non thread safe fork of squirrel. The same handy fluffy helper, but with extra lette

Fluent SQL generation for golang

Squirrel is "complete". Bug fixes will still be merged (slowly). Bug reports are welcome, but I will not necessarily respond to them. If another fork

GraphJin - Build APIs in 5 minutes with GraphQL. An instant GraphQL to SQL compiler.
GraphJin - Build APIs in 5 minutes with GraphQL. An instant GraphQL to SQL compiler.

GraphJin - Build APIs in 5 minutes GraphJin gives you a high performance GraphQL API without you having to write any code. GraphQL is automagically co

golang orm and sql builder

gosql gosql is a easy ORM library for Golang. Style: var userList []UserModel err := db.FetchAll(&userList, gosql.Columns("id","name"), gosql.

LBADD: An experimental, distributed SQL database
LBADD: An experimental, distributed SQL database

LBADD Let's build a distributed database. LBADD is an experimental distributed SQL database, written in Go. The goal of this project is to build a dat

A Go library for collecting sql.DBStats in Prometheus format

sqlstats A Go library for collecting sql.DBStats and exporting them in Prometheus format. A sql.DB object represents a pool of zero or more underlying

Comments
  • False positives and false negatives

    False positives and false negatives

    I believe the program does not function like it should. It only works if I put rows.Close directly under the line of the query (which is not good). If I make that a defer rows.Close() I get: ./main.go:16:8: using rows before checking for errors which you should expect

            rows, err := readDB.Query("SELECT 1")
            if err != nil {
                    panic(err)
            }
            defer rows.Close()
    

    $ go vet -vettool=$(which sqlrows) ./... #./main.go:15:27: rows.Close must be called

    Source code

    package main
      
    import (
            "database/sql"
            _ "github.com/go-sql-driver/mysql"
    )
    
    func main(){
            
            readDB, err := sql.Open("mysql", "root:[email protected](localhost:3306)/mysql?parseTime=true&charset=utf8mb4")
            if err != nil {
                    panic(err.Error()) 
            }       
            
            rows, err := readDB.Query("SELECT 1")
            // rows.Close() // no warnings, which is incorrect
            // defer rows.Close() // gives ./main.go:16:8: using rows before checking for errors
            if err != nil {
                    panic(err)
            }
            defer rows.Close() // correct but does not get noticed
    
    }
    
    opened by jtorvald 1
  • panic: *ssa.Phi during rows declaration without assignment

    panic: *ssa.Phi during rows declaration without assignment

    sqlrows panics when parsing the following code:

    var rows *sql.Rows
    if foo {
        rows, err = queryFoo()
    } else {
        rows, err = queryBar()
    }
    if err != nil { return err }
    defer rows.Close()
    

    After digging in, it seems this is because var rows *sql.Rows comes in as an *ssa.Phi rather than an *ssa.Extract.

    opened by nelsam 0
  • panic: *ssa.UnOp during rows.Close()

    panic: *ssa.UnOp during rows.Close()

    The following code seems to cause sqlrows to panic:

    rows, err := db.Query(a, b, c)
    if err != nil {
        return err
    }
    func() {
        defer rows.Close()
    
        // read from rows...
    }()
    

    After digging in some, it seems that the deferred rows.Close() call inside of the closure is dereferencing the *sql.Rows value, because it comes out as an *ssa.UnOp instead of an *ssa.Extract.

    opened by nelsam 0
  • Add ability to check closing of transactions

    Add ability to check closing of transactions

    Hi, thanks for creating this. I would love to use this tool if this supports checking transactions too. Usually, rows.Close() is something that is not missed. But I miss closing transactions often.

    I would want to check that transactions are always either committed or rolled back before the function returns.

    Something like

    tx, err := db.Begin()
    if err != nil {
    	return err
    }
    err = doSomething()
    if err != nil {
    	tx.Rollback()
    	return err
    }
    return nil // error !! We are not doing tx.Commit() before returning.
    

    Will it be possible to add something like this ? Thanks.

    opened by agnivade 3
Owner
GoStaticAnalysis
Static Analysis Tools for Go
GoStaticAnalysis
💥 A lightweight DSL & ORM which helps you to write SQL in Go.

sqlingo is a SQL DSL (a.k.a. SQL Builder or ORM) library in Go. It generates code from the database and lets you write SQL queries in an elegant way.

Qishuai Liu 269 Nov 21, 2022
Command line tool to generate idiomatic Go code for SQL databases supporting PostgreSQL, MySQL, SQLite, Oracle, and Microsoft SQL Server

About xo xo is a command-line tool to generate Go code based on a database schema or a custom query. xo works by using database metadata and SQL intro

XO 3.3k Nov 24, 2022
Go fearless SQL. Sqlvet performs static analysis on raw SQL queries in your Go code base.

Sqlvet Sqlvet performs static analysis on raw SQL queries in your Go code base to surface potential runtime errors at build time. Feature highlights:

QP Hou 457 Nov 9, 2022
A Golang library for using SQL.

dotsql A Golang library for using SQL. It is not an ORM, it is not a query builder. Dotsql is a library that helps you keep sql files in one place and

Gustavo Chaín 650 Nov 20, 2022
a golang library for sql builder

Gendry gendry is a Go library that helps you operate database. Based on go-sql-driver/mysql, it provides a series of simple but useful tools to prepar

DiDi 1.4k Nov 21, 2022
Database Abstraction Layer (dbal) for Go. Support SQL builder and get result easily (now only support mysql)

godbal Database Abstraction Layer (dbal) for go (now only support mysql) Motivation I wanted a DBAL that No ORM、No Reflect、Concurrency Save, support S

徐佳军 56 Nov 17, 2022
SQL builder and query library for golang

__ _ ___ __ _ _ _ / _` |/ _ \ / _` | | | | | (_| | (_) | (_| | |_| | \__, |\___/ \__, |\__,_| |___/ |_| goqu is an expressive SQL bu

Doug Martin 1.7k Nov 18, 2022
SQL query builder for Go

GoSQL Query builder with some handy utility functions. Documentation For full documentation see the pkg.go.dev or GitBook. Examples // Open database a

Travis Harmon 26 Sep 26, 2022
Type safe SQL builder with code generation and automatic query result data mapping

Jet Jet is a complete solution for efficient and high performance database access, consisting of type-safe SQL builder with code generation and automa

null 886 Nov 21, 2022
A Go (golang) package that enhances the standard database/sql package by providing powerful data retrieval methods as well as DB-agnostic query building capabilities.

ozzo-dbx Summary Description Requirements Installation Supported Databases Getting Started Connecting to Database Executing Queries Binding Parameters

Ozzo Framework 586 Nov 24, 2022