prep

package module
v0.0.0-...-029cd91 Latest Latest
Warning

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

Go to latest
Published: Dec 19, 2017 License: Apache-2.0 Imports: 6 Imported by: 0

README

Prep License Build Status Coverage Status Go Report Card GoDoc

Prep finds all SQL statements in a Go package and instruments db connection with prepared statements. It allows you to benefit from the prepared SQL statements almost without any changes to your code.

Prep consists of two parts:

  • A command line tool that finds all SQL statements in your code
  • A package that instruments your code with prepared SQL statements using the found ones

Usage

Generate a list of SQL statements used in your application

$ cat example.go

func main() {
	db, err := sql.Open("mysql", "user:pass@tcp(localhost:3306)/mysql")
	if err != nil {
		panic(err)
	}
	const query = `SELECT CONCAT("Hello ", ?, "!")`
	var s string
	if err := db.QueryRow(query, "World").Scan(&s); err != nil {
		panic(err)
	}
	fmt.Println(s)
}

Let's generate a list of the SQL statements used in your package:

$ prep -f github.com/hexdigest/prepdemo
$ cat prepared_statements.go
//go:generate prep -f github.com/hexdigest/prepdemo

package main

var prepStatements = []string{
	"SELECT CONCAT(\"Hello \", ?, \"!\")",
}

Using prepared statements

func main() {
	sqlDB, err := sql.Open("mysql", "root:root@tcp(localhost:3306)/mysql")
	if err != nil {
		panic(err)
	}

	db, err := prep.NewConnection(sqlDB, prepStatements)
	if err != nil {
		panic(err)
	}

	const query = `SELECT CONCAT("Hello ", ?, "!")`
	var s string
	if err := db.QueryRow(query, "World").Scan(&s); err != nil {
		panic(err)
	}
	fmt.Println(s)
}

Take a look at the line:

db, err := prep.NewConnection(sqlDB, prepStatements)

It instruments your connection with prepared statements found by the generator. The generated code already contains //go:generate instruction, so in order to update the statements list you can simply run:

$ go generate

Some synthetic benchmarks

$ go test -bench=.
BenchmarkPostgresWithoutPreparedStatements-4   	   20000	     59941 ns/op	    1183 B/op	      32 allocs/op
BenchmarkPostgresWithPreparedStatements-4      	   50000	     41560 ns/op	    1021 B/op	      26 allocs/op
BenchmarkMySQLWithoutPreparedStatements-4      	   50000	     26454 ns/op	     827 B/op	      23 allocs/op
BenchmarkMySQLWithPreparedStatements-4         	  200000	      9509 ns/op	     634 B/op	      19 allocs/op
PASS
ok  	github.com/hexdigest/prep	7.884s

Documentation

Overview

Package prep instruments instruments db connection with prepared statements. It allows you to benefit from the prepared SQL statements almost without any changes to your code.

Prep consists of two parts:

1. A command line tool that finds all SQL statements in your code

2. A package that instruments your code with prepared SQL statements using the found ones

Firstly you should generate a list of SQL statements used in your application

$ cat github.com/hexdigest/prepdemo/example.go
func main() {
	db, err := sql.Open("mysql", "user:pass@tcp(localhost:3306)/mysql")
	if err != nil {
		panic(err)
	}
	const query = `SELECT CONCAT("Hello ", ?, "!")`
	var s string
	if err := db.QueryRow(query, "World").Scan(&s); err != nil {
		panic(err)
	}
	fmt.Println(s)
}

Let's generate a list of the SQL statements used in your package:

$ prep -f github.com/hexdigest/prepdemo
$ cat prepared_statements.go
//go:generate prep -f github.com/hexdigest/prepdemo

package main

var prepStatements = []string{
	"SELECT CONCAT(\"Hello \", ?, \"!\")",
}

Using prepared statements:

func main() {
	sqlDB, err := sql.Open("mysql", "root:root@tcp(localhost:3306)/mysql")
	if err != nil {
		panic(err)
	}

	db, err := prep.NewConnection(sqlDB, prepStatements)
	if err != nil {
		panic(err)
	}

	const query = `SELECT CONCAT("Hello ", ?, "!")`
	var s string
	if err := db.QueryRow(query, "World").Scan(&s); err != nil {
		panic(err)
	}
	fmt.Println(s)
}

Take a look at the line:

db, err := prep.NewConnection(sqlDB, prepStatements)

It instruments your connection with prepared statements found by the generator. The generated code already contains //go:generate instruction, so in order to update the statements list you can simply run:

$ go generate

Some synthetic benchmarks:

$ go test -bench=.
BenchmarkPostgresWithoutPreparedStatements-4   	   20000	     59941 ns/op	    1183 B/op	      32 allocs/op
BenchmarkPostgresWithPreparedStatements-4      	   50000	     41560 ns/op	    1021 B/op	      26 allocs/op
BenchmarkMySQLWithoutPreparedStatements-4      	   50000	     26454 ns/op	     827 B/op	      23 allocs/op
BenchmarkMySQLWithPreparedStatements-4         	  200000	      9509 ns/op	     634 B/op	      19 allocs/op
PASS
ok  	github.com/hexdigest/prep	7.884s

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Connection

type Connection struct {
	Querier
	// contains filtered or unexported fields
}

Connection is a wrapper for Connector instrumented with prepared SQL statements

func NewConnection

func NewConnection(c Connector, statements []string) (*Connection, error)

NewConnection creates prepared statements for all statements in the given list and returns an implementation of the Connector interface instrumented with prepared statements

func (*Connection) Exec

func (c *Connection) Exec(query string, args ...interface{}) (sql.Result, error)

Exec implements executer

func (*Connection) ExecContext

func (c *Connection) ExecContext(ctx context.Context, query string, args ...interface{}) (sql.Result, error)

ExecContext implements executerWithContext

func (*Connection) Prepare

func (c *Connection) Prepare(query string) (*sql.Stmt, error)

Prepare implements preparer

func (*Connection) PrepareContext

func (c *Connection) PrepareContext(ctx context.Context, query string) (*sql.Stmt, error)

PrepareContext implements preparerWithContext

func (*Connection) Query

func (c *Connection) Query(query string, args ...interface{}) (*sql.Rows, error)

Query implements querier

func (*Connection) QueryContext

func (c *Connection) QueryContext(ctx context.Context, query string, args ...interface{}) (*sql.Rows, error)

QueryContext implements querierWithContext

func (*Connection) QueryRow

func (c *Connection) QueryRow(query string, args ...interface{}) *sql.Row

QueryRow implements rowQuerier

func (*Connection) QueryRowContext

func (c *Connection) QueryRowContext(ctx context.Context, query string, args ...interface{}) *sql.Row

QueryRowContext implements querierWithContext

type Connector

type Connector interface {
	Querier
	// contains filtered or unexported methods
}

Connector contains all exportable methods of the database/sql.DB

type PreparedStatement

type PreparedStatement interface {
	Exec(args ...interface{}) (sql.Result, error)
	ExecContext(ctx context.Context, args ...interface{}) (sql.Result, error)
	QueryRow(args ...interface{}) *sql.Row
	QueryRowContext(ctx context.Context, args ...interface{}) *sql.Row
	Query(args ...interface{}) (*sql.Rows, error)
	QueryContext(ctx context.Context, args ...interface{}) (*sql.Rows, error)
}

PreparedStatement is implemented by *sql.Stmt

type Querier

type Querier interface {
	// contains filtered or unexported methods
}

Querier contains methods of the database/sql.DB that sending queries to the database

Directories

Path Synopsis
cmd

Jump to

Keyboard shortcuts

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