Documentation
¶
Overview ¶
Package sqlt defines an extension over text/templates for producing safe SQL.
Like package `html/template`, this package parses normal text templates and then modifies the syntax tree to alter potentially unsafe components.
By default, any value interpolation gets a special internal formatter function applied to it that map the value to a named parameter to prevent SQL injection vulnerabilities.
Index ¶
- Variables
- type Sanitizer
- type SanitizerFunc
- type SanitizerMap
- type Template
- func (t *Template) Clone() (*Template, error)
- func (t *Template) Execute(data any) (query string, params pgx.NamedArgs, err error)
- func (t *Template) ExecuteTemplate(name string, data any) (query string, params pgx.NamedArgs, err error)
- func (t *Template) Funcs(funcMap template.FuncMap) *Template
- func (t *Template) Parse(templateStr string) (*Template, error)
- func (t *Template) ParseFS(fsys fs.FS, patterns ...string) (*Template, error)
- func (t *Template) Sanitizers(sanitizers SanitizerMap) *Template
Constants ¶
This section is empty.
Variables ¶
var ErrAlreadyUsed = errors.New("cannot parse template after first use")
ErrAlreadyUsed occurs when a program calls Parse or ParseFS on a template after its first use.
Templates lazily escape template sequences on first use, so parsing more templates after first use would allow an undefined state where the template has unescaped nodes.
var ErrUnexpectedNode = errors.New("unexpected node while escaping template")
ErrUnexpectedNode indicates that the escaper failed to escape the template.
This error should never occur, and if it does, it indicates a bug in this package.
Functions ¶
This section is empty.
Types ¶
type Sanitizer ¶
type Sanitizer interface {
// Format must output a safe SQL string associated with an argument.
//
// A Sanitizer must convert any untrusted inputs into named parameters
// and store the associated values for later retrieval via Args.
//
// A Template may invoke `Format` any number of times during its execution.
Format(arg any) string
// Args must output the collected parameter bindings associated with all
// calls to `Format` before calling Args.
//
// A Template calls args after it finishes executing the template to
// retrieve all bound parameters created in the course of template execution.
Args() pgx.NamedArgs
}
Sanitizer formats data for safe SQL escaping.
This package provides a default formatter that converts variable or function pipelines in the template to parameter bindings by default.
Callers may define their own Sanitizers to support other functions that generate safe SQL and parameter mappings.
type SanitizerFunc ¶
type SanitizerFunc func() Sanitizer
SanitizerFunc defines a function that returns a new instance of a Sanitizer.
A Template invokes a SanitizerFunc once per execution, and the SanitizerFunc must return "clean" instance of the Sanitizer each time.
The Template generates a new Sanitizer for each execution because the Sanitizer stores state related to the parameter bindings generated by the execution.
type SanitizerMap ¶
type SanitizerMap map[string]SanitizerFunc
SanitizerMap represents a binding from sanitizers to the names by which templates may access them.
A Template doesn't automatically escape a function pipeline ending with a sanitizer, and assumes the sanitizer produces trusted output.
This package reserves the namespace prefix `_sqlt_*` for function names. Callers shouldn't define functions having that prefix in a FuncMap or a SanitizerMap.
type Template ¶
type Template struct {
// contains filtered or unexported fields
}
Template wraps `template.Template` providing SQL parameter substitution to avoid directly constructing SQL with string interpolation.
Branches get interpreted as normal, resulting in literal strings within the query, but variable substitutions instead bind named parameters, and executing the query returns a parameter map containing these named parameters.
func (*Template) Execute ¶
Execute executes the template and returns a query, a `pgx.NamedArgs` containing any parameter bindings generated by the template, and an error.
If the error has a nil value, this method guarantees the validity of the other retur values.
Example:
pool, err := pgxpool.New(context.TODO(), os.Getenv("DATABASE_URL"))
if err != nil {
panic(err)
}
tpl, err := sqlt.New("")
if err != nil {
panic(err)
}
tpl, err = tpl.Parse("SELECT * FROM table WHERE id={{ .id }}")
if err != nil {
panic(err)
}
query, args, err := tpl.Execute(map[string]int{"id": 3}
if err != nil {
panic(err)
}
rows, err := pool.Query(context.TODO(), query, args)
func (*Template) ExecuteTemplate ¶
func (t *Template) ExecuteTemplate(name string, data any) (query string, params pgx.NamedArgs, err error)
ExecuteTemplate executes a named subtemplate within this template.
This method especially helps when you load templates using `ParseFS`. Other than the extra argument for the template name, its behavor matches the preceding Execute method.
func (*Template) Funcs ¶
Funcs passes new functions into the `Funcs` of the underlying text/template.
func (*Template) Sanitizers ¶
func (t *Template) Sanitizers(sanitizers SanitizerMap) *Template
Sanitizers extends the behavior of `Funcs` to support adding SQL sanitizing functions that emit safe SQL strings and generate parameter bindings.
The caller has the responsibility of ensuring that the parameter bindings generated by each Sanitizer don't have namespace conflicts with one another.
This package reserves the prefix "sqlt" for its own bindings.