sqldb

package module
v3.0.0 Latest Latest
Warning

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

Go to latest
Published: Feb 28, 2024 License: MIT Imports: 16 Imported by: 0

README

Documentation

Overview

Package sqldb provides tooling to make connecting to, deploying, updating, and using a SQL database easier. This provides some wrapping around the database/sql package.

The initial purpose behind this package was to encapsulate commonly used database connection, schema deploying and updating, and other boilerplate tasks.

Basic Usage

  //Build a config:
  cfg := &sqldb.Config{
	Type:       sqldb.DBTypeSqlite,
	SQLitePath: "/path/to/sqlite.db",
  }

  //Store the config within the sqldb package for future use.
  sqldb.Use(cfg)

  //Connect.
  err := sqldb.Connect()
  if err != nil {
	log.Fatalln(err)
	return
  }

  c := sqldb.Connection()
  err := c.Exec("SELECT * FROM my_table")
  if err != nil {
	log.Fatalln(err)
	return
  }

Global or Local DB Connection

You can use this package via two methods: as a singleton with the database configuration and connection stored within this package in a globally accessible variable, or store the configuration and connection somewhere else in your application. Storing the data yourself allows for connecting to multiple databases at once.

  //Storing the config outside of this package.
  cfg := &sqldb.Config{
	Type:       sqldb.DBTypeSqlite,
	SQLitePath: "/path/to/sqlite.db",
  }

  //Connect. Not calling Connect() directly on the config. No need to call .Use().
  err := cfg.Connect()
  if err != nil {
	log.Fatalln(err)
	return
  }

  c := cfg.Connection()
  err := c.Exec("SELECT * FROM my_table")
  if err != nil {
	log.Fatalln(err)
	return
  }

Deploying a Database

Deployment of a schema is done via DeployQueries and DeployFuncs, along with the associated DeployQueryTranslators and DeployQueryErrorHandlers. DeployQueries are just SQL query strings while DeployFuncs are used for more complicated deployment scenarios (such as INSERTing initial data).

DeployQueryTranslators translate DeployQueries from one database dialect to another (ex: MariaDB to SQLite) since different databases support slightly different SQL dialects. This allows you to write your CREATE TABLE or other deployment related queries in one database dialect, but then modify the query programatically to the dialect required for another database type. This is extremely useful if your application supports multiple database types. Note that DeployQueryTranslators do not apply to DeployFuncs since DeployFuncs are typically more than just a SQL query.

DeployQueryErrorHandlers is a list of functions that are run when any DeployQuery results in an error (as returned by [sql.Exec]). These funcs are used to evaluate, and if appropriate, ignore the error.

DeployQueries and DeployFuncs should be safe to be rerun multiple times, particularly without INSERTing duplicate data. Use IF NOT EXISTS or check if something exists before INSERTing in DeployFuncs.

Updating a Database

Updating an existing database schema is done via UpdateQueries and UpdateFuncs, along with the associated UpdateQueryTranslators and UpdateQueryErrorHandlers. This functionality is similar to the deploy schema tooling.

UpdateQueryErrorHandlers are very useful for handling queries that when run multiple times would result in an error, especially when the IF EXISTS syntax is not available (see SQLite for ALTER TABLE...DROP COLUMN).

SQLite Library

This package support two SQLite libraries, github.com/mattn/go-sqlite3 and gitlab.com/cznic/sqlite. The mattn library requires CGO which can be troublesome for cross-compiling. The modernc library is pure golang, however, it is a translation, not the original SQLite code, and therefore does not have the same level of trustworthiness or extent of testing.

As of now, mattn is the default if no build tags are provided. This is simply due to the longer history of this library being available and the fact that this uses the SQLite C source code.

Use either library with build tags:

go build -tags mattn ...
go build -tags modernc ...
go run -tags mattn ...
go run -tags modernc ...

The mattn library sets some default PRAGMA values, as noted in the source code at https://github.com/mattn/go-sqlite3/blob/ae2a61f847e10e6dd771ecd4e1c55e0421cdc7f9/sqlite3.go#L1086. Some of these are just safe defaults, for example, busy_timeout. In order to treat the mattn and modernc libraries more similarly, some of these mattn PRAGMAs are also set when using the modernc library. This is done to make using both libraries act in the same manner, make them more interchangable with the same result. See DefaultSQLitePragmas.

Notes

This package uses github.com/jmoiron/sqlx instead of the Go standard library database/sql package because sqlx provides some additional tooling which makes using a database a bit easier (i.e.: Get(), Select(), and StructScan()).

Index

Constants

View Source
const (
	LogLevelNone  logLevel = iota //no logging, really should never be used.
	LogLevelError                 //general errors, most typical use.
	LogLevelInfo                  //some info on db connections, deployment, updates.
	LogLevelDebug                 //primarily used during development.

	LogLevelDefault = LogLevelError
)
View Source
const (
	DBTypeMySQL   = dbType("mysql")
	DBTypeMariaDB = dbType("mariadb")
	DBTypeSQLite  = dbType("sqlite")
	DBTypeMSSQL   = dbType("mssql")
)
View Source
const (
	//SQLiteInMemoryFilepathRacy is the path to provide for SQLitePath when you want
	//to use an in-memory database instead of a file on disk. This is racy because
	//each call to Connect() will open a brand new database. If you only call
	//Connect() once then this is safe to use.
	//
	//This is good for running tests since then each test runs with a separate
	//in-memory db.
	SQLiteInMemoryFilepathRacy = ":memory:"

	//SQLiteInMemoryFilepathRaceSafe is the path to provide for SQLitePath when you
	//want to use an in-memory database instead of a file on disk. This is race safe
	//since multiple calls of Connect() will connect to the same in-memory database,
	//although connecting more than once to the same database would be very odd.
	SQLiteInMemoryFilepathRaceSafe = "file::memory:?cache=shared"
)

Variables

View Source
var (
	//ErrNoColumnsGiven is returned when trying to build a column list for a query
	//but no columns were provided.
	ErrNoColumnsGiven = errors.New("sqldb: no columns provided")

	//ErrExtraCommaInColumnString is returned when building a column string for a
	//query but an extra comma exists which would cause the query to run incorrectly.
	//Extra commas are usually due to an empty column name being provided or a comma
	//being added to the column name by mistake.
	ErrExtraCommaInColumnString = errors.New("sqldb: extra comma in column name")
)
View Source
var (
	//ErrConnected is returned when a trying to establish a connection to an already
	//connected-to database.
	ErrConnected = errors.New("sqldb: connection already established")

	//ErrSQLitePathNotProvided is returned SQLitePath is empty.
	ErrSQLitePathNotProvided = errors.New("sqldb: SQLite path not provided")

	//ErrHostNotProvided is returned when no Host IP or FQDN was provided.
	ErrHostNotProvided = errors.New("sqldb: database server host not provided")

	//ErrInvalidPort is returned when no Port was provided or the port was invalid.
	ErrInvalidPort = errors.New("sqldb: database server port invalid")

	//ErrNameNotProvided is returned when no database Name was provided.
	ErrNameNotProvided = errors.New("sqldb: database name not provided")

	//ErrUserNotProvided is returned when no database User was provided.
	ErrUserNotProvided = errors.New("sqldb: database user not provided")

	//ErrPasswordNotProvided is returned when no database Password was provided.
	//Blank passwords are not supported since it is terrible for security.
	ErrPasswordNotProvided = errors.New("sqldb: password for database user not provided")
)
View Source
var DefaultSQLitePragmas = []string{
	"PRAGMA busy_timeout = 5000",
	"PRAGMA synchronous = NORMAL",
}

DefaultSQLitePragmas defines the list of PRAGMA statments to configure SQLite with by default. These PRAGMAs match the values set for the github.com/mattn/go-sqlite3 library since that library is more commonly used.

The github.com/mattn/go-sqlite3 library sets some PRAGMAs by default. The modernc.org/sqlite library does not define any default PRAGMAs. To make switching between the two libraries/drivers easier, we define some of the more impactful/typical PRAGMAs here so that these PRAGMAs are applied when either library is used. See SQLitePragmas in Config.

Reference: https://github.com/mattn/go-sqlite3/blob/ae2a61f847e10e6dd771ecd4e1c55e0421cdc7f9/sqlite3.go#L1086

View Source
var (
	//ErrInvalidLoggingLevel is returned when an invalid logging level is provided.
	ErrInvalidLoggingLevel = errors.New("sqldb: invalid logging level")
)

Functions

func AddConnectionOption

func AddConnectionOption(key, value string)

AddConnectionOption adds a key-value pair to a config's ConnnectionOptions field. Using this func is just easier then calling map[string]string{"key", "value"}. This does not check if the key already exist, it will simply add a duplicate key-value pair.

func Close

func Close() (err error)

Close handles closing the underlying database connection stored in the package level config.

func Connect

func Connect() (err error)

Connect connects to the database using the config stored at the package level. Use this after calling Use().

func Connected

func Connected() bool

Connected returns if the config represents an established connection to a database.

func Connection

func Connection() *sqlx.DB

Connection returns the underlying database connection stored in the package level config for use in running queries.

func DBType

func DBType(s string) dbType

DBType returns a dbType. This is used when parsing a user-provided database type (such as from ann external configuration file) to convert to a dbType defined in this package.

func DefaultMapperFunc

func DefaultMapperFunc(s string) string

DefaultMapperFunc is the default function used for handling column name formatting when retrieving data from the database and matching up to struct field names. No reformatting is done; the column names are returned exactly as they are noted in the database schema. This is unlike sqlx that lowercases all column names and thus requires struct tags to match up against exported struct fields.

See: https://jmoiron.github.io/sqlx/#mapping

func DeploySchema

func DeploySchema(opts *DeploySchemaOptions) (err error)

DeploySchema runs the DeployQueries and DeployFuncs specified in a config against the database noted in the config. Use this to create your tables, create indexes, etc. This will automatically issue a CREATE DATABASE IF NOT EXISTS query.

DeployQueries will be translated via DeployQueryTranslators and any DeployQuery errors will be processed by DeployQueryErrorHandlers. Neither of these steps apply to DeployFuncs.

DeploySchemaOptions is a pointer so that in cases where you do not want to provide any options, using the defaults, you can simply provide nil.

Typically this func is run when a flag, i.e.: --deploy-db, is provided.

func GetSQLiteLibrary

func GetSQLiteLibrary() library

GetSQLiteLibrary returns the SQLite library that was used to build the binary. The library is set at build/run with go build tags.

func GetSQLiteVersion

func GetSQLiteVersion() (version string, err error)

GetSQLiteVersion returns the version of SQLite that is embedded into your app. This works by creating a temporary in-memory SQLite database to run a query against.

A separate database connection is established because you might want to get the SQLite version before you call Connect(). This also just keeps things separate from your own connection.

func IgnoreErrorDropDoesNotExist

func IgnoreErrorDropDoesNotExist(query string, err error) bool

IgnoreErrorDropDoesNotExist checks if an error occured because a column that does not exists is trying to be dropped.

This error usually occurs because UpdateSchema() is being rerun.

func IgnoreErrorDropUnknownColumn

func IgnoreErrorDropUnknownColumn(query string, err error) bool

IgnoreErrorDropUnknownColumn checks if an error occured because a column you are trying to DROP has already been DROPped and does not exist.

This error usually occurs because UpdateSchema() is being rerun.

func IgnoreErrorDuplicateColumn

func IgnoreErrorDuplicateColumn(query string, err error) bool

IgnoreErrorDuplicateColumn checks if an error occured because a column with the same name already exists. This is useful to for running ALTER TABLE ADD COLUMN or RENAME COLUMN.

This error usually occurs because UpdateSchema() is being rerun.

func IgnoreErrorIndexAlreadyExists

func IgnoreErrorIndexAlreadyExists(query string, err error) bool

IgnoreErrorIndexAlreadyExists checks if an error occured because an index with the given name already exists. If you use "IF NOT EXISTS" in your query this error will not occur.

func IgnoreErrorRenameDoesNotExist

func IgnoreErrorRenameDoesNotExist(query string, err error) bool

IgnoreErrorRenameDoesNotExist checks is an error occured because a column or table that does not exist is trying to be renamed.

This error usually occurs because UpdateSchema() is being rerun.

func IgnoreErrorSQLiteModify

func IgnoreErrorSQLiteModify(query string, err error) bool

IgnoreErrorSQLiteModify checks if an error occured becaused a query is attempting to MODIFY a column for a SQLite database. SQLite does not support MODIFY. This is somewhat okay since SQLite allows storing any type of data in any colum (unless STRICT tables are used) and the data read from the database will be read into a Golang type anyway.

To get around this error, you should create a new table with the new schema, copy the old data to the new table, delete the old table, and rename the new table to the old table.

func IsMSSQL

func IsMSSQL() bool

IsMSSQL returns true if a config represents a MS SQL connection.

func IsMariaDB

func IsMariaDB() bool

IsMariaDB returns true if a config represents a MariaDB connection.

func IsMySQL

func IsMySQL() bool

IsMySQL returns true if a config represents a MySQL connection.

func IsSQLite

func IsSQLite() bool

IsSQLite returns true if a config represents a SQLite connection.

func RunDeployQueryTranslators

func RunDeployQueryTranslators(in string) (out string)

RunDeployQueryTranslators runs the list of DeployQueryTranslators on the provided query.

This func is called in DeploySchema() but can also be called manually when you want to translate a DeployQuery (for example, running a specific DeployQuery as part of UpdateSchema).

func RunUpdateQueryTranslators

func RunUpdateQueryTranslators(in string) (out string)

RunUpdateQueryTranslators runs the list of UpdateQueryTranslators on the provided query.

This func is called in UpdateSchema().

func TranslateMariaDBToSQLiteCreateTable

func TranslateMariaDBToSQLiteCreateTable(query string) string

TranslateMariaDBToSQLiteCreateTable translates a CREATE TABLE query from MariaDB or MySQL to SQLite.

func Type

func Type() dbType

Type return the dbType from a Config.

This func is geared toward usage in a switch statement, specifically for when you store your Config in this package's global variable (singleton style). This removes the need to have a bunch of if/else-if blocks calling sqldb.IsMariaDB(), sqldb.IsSQLite(), and so forth. If you store your Config elsewhere, outside of this package, you can just build a switch statement from the Config's Type field.

This func is only defined for the globally-stored Config since if you want to get the type of database from a Config you have stored elsewhere, you can just retrieve it with something like "cfg.Type".

func UpdateSchema

func UpdateSchema(opts *UpdateSchemaOptions) (err error)

UpdateSchema runs the UpdateQueries and UpdateFuncs specified in a config against the database noted in the config. Use this to add columns, add indexes, rename things, perform data changes, etc.

UpdateQueries will be translated via UpdateQueryTranslators and any UpdateQuery errors will be processed by UpdateQueryErrorHandlers. Neither of these steps apply to UpdateFuncs.

UpdateSchemaOptions is a pointer so that in cases where you do not want to provide any options, using the defaults, you can simply provide nil.

Typically this func is run when a flag, i.e.: --update-db, is provided.

func Use

func Use(c *Config)

Use stores a config in the package-level variable when you are using this package in a singleton manner.

This does not check if Use() has previously been called; Use() should only ever be called once unless you are certain you closed an existing database connection.

Types

type Bindvars

type Bindvars []interface{}

Bindvars holds the parameters you want to use in a query. This helps in organizing a query you are building. You can use the values stored in this slice when running a query by providing Bindvars... (ex.: c.Get(&var, q, b...) or stmt.Exec(b...). This is typically used when building complex queries and in conjunction with the Columns type.

type Columns

type Columns []string

Columns is used to hold columns for a query. This helps in organizing a query you are building and is useful for generating the correct placeholders when needed using the ForSelect(), ForUpdate(), ForInsert() funcs.

Example:

cols := Columns{
    "Fname",
    "Birthday",
    "CompanyID",
}
colString, valString, _ := cols.ForInsert()
//colString will be "Fname,Birthday,CompanyID"
//valString will be "?,?,?"
//Use like: "INSERT INTO users (" + colString + ") VALUES (" + valString + ")"

func (Columns) ForInsert

func (cols Columns) ForInsert() (colString, valString string, err error)

ForInsert builds the column string for an INSERT query and also returns the placholder VALUES() string you should use.

func (Columns) ForSelect

func (cols Columns) ForSelect() (colString string, err error)

ForSelect builds the column string for a SELECT query.

func (Columns) ForUpdate

func (cols Columns) ForUpdate() (colString string, err error)

ForUpdate builds the column string for an UPDATE query.

type Config

type Config struct {
	//Type represents the type of database to use.
	Type dbType

	//Connection information for a non-SQLite database.
	Host     string
	Port     uint
	Name     string
	User     string
	Password string

	//ConnectionOptions is a list of key-value pairs of options used when building
	//the connection string used to connect to a database. Each driver/database type
	//will handle these differently. Use AddConnectionOption() instead of having to
	//do Config.ConnectionOptions = map[string]string{"key", "value"}.
	ConnectionOptions map[string]string

	//SQLitePath is the path where the SQLite database file is located.
	SQLitePath string

	//SQLitePragmas is a list of PRAGMAs to apply when connecting to a SQLite
	//database. Typically this is used to set the journal mode or busy timeout.
	//PRAGMAs provided here are in SQLite query format with an equals sign
	//(ex.: PRAGMA busy_timeout=5000).
	//
	//Both the mattn and modernc packages allow setting of PRAGMAs in the database
	//filename path. See the below links. PRAGMA statements here will be appended to
	//the SQLitePath, after translating to the correct library's format, so that the
	//PRAGMAs are set properly for the database upon initially opening it.
	//
	//https://github.com/mattn/go-sqlite3#connection-string)
	//https://pkg.go.dev/modernc.org/sqlite#Driver.Open
	SQLitePragmas []string

	//MapperFunc is used to override the mapping of database column names to struct
	//field names or struct tags. Mapping of column names is used during queries
	//where sqlx's StructScan(), Get(), or Select() is used.
	//
	//By default, column names are not modified in any manner. This is in contrast to
	//the default for sqlx where column names are returned as all lower case which
	//requires your structs to use struct tags for each exported field. By not
	//modifying column names you will not need to use struct tags since column names
	//can exactly match exportable struct field names. This is just a small helper
	//done to reduce the amount of struct tags that are necessary.
	//
	//http://jmoiron.github.io/sqlx/#:~:text=You%20can%20use%20the%20db%20struct%20tag%20to%20specify%20which%20column%20name%20maps%20to%20each%20struct%20field%2C%20or%20set%20a%20new%20default%20mapping%20with%20db.MapperFunc().%20The%20default%20behavior%20is%20to%20use%20strings.Lower%20on%20the%20field%20name%20to%20match%20against%20the%20column%20names.
	MapperFunc func(string) string

	//DeployQueries is a list of SQL queries used to deploy a database schema. These
	//are typically used for CREATE TABLE or CREATE INDEX queries. These queries will
	//be run when DeploySchema() is called.
	//
	//Order matters! Order your queries so that foreign tables for relationships are
	//created before the relationships!
	//
	//Each query should be safe to be rerun multiple times!
	DeployQueries []string

	//DeployFuncs is a list of functions, each containing at least one SQL query,
	//that is used to deploy a database schema. Use these for more complicated schema
	//deployment or initialization steps, such as INSERTing initial data. DeployFuncs
	//should be used more sparingly than DeployQueries. These functions will be run
	//when DeploySchema() is called.
	//
	//These functions are executed after DeployQueries.
	//
	//Each function should be safe to be rerun multiple times!
	DeployFuncs []QueryFunc

	//DeployQueryTranslators is a list of functions that translate a DeployQuery from
	//one database dialect to another. This functionality is provided so that you do
	//not have to rewrite your deployment queries for each database type you want to
	//deploy for.
	//
	//A DeployQueryTranslator function takes a DeployQuery as an input and returns a
	//rewritten query.
	//
	//See predefined translator functions starting with TF.
	DeployQueryTranslators []Translator

	//DeployQueryErrorHandlers is a list of functions that are run when an error
	//results from running a DeployQuery and is used to determine if the error can be
	//ignored. Use this for ignoring expected errors from SQL queries, typically when
	//you rerun DeploySchema() and something already exists but the IS NOT EXISTS
	//term is unavailable.
	//
	//A DeployQueryErrorHandler function takes a DeployQuery and the error resulting
	//from [database/sql.Exec] as an input and returns true if the error should be
	//ignored.
	DeployQueryErrorHandlers []ErrorHandler

	//UpdateQueries is a list of SQL queries used to update a database schema. These
	//are typically used ot add new columns, ALTER a column, or DROP a column. These
	//queries will be run when UpdateSchema() is called.
	//
	//Order matters! Order your queries if they depend on each other (ex.: renamed
	//tables or columns).
	//
	//Each query should be safe to be rerun multiple times!
	UpdateQueries []string

	//UpdateFuncs is a list of functions, each containing at least one SQL query,
	//that is used to update a database schema. Use these for more complicated schema
	//updates, such as reading values before updating. UpdateFuncs should be used
	//more sparingly than UpdateQueries. These functions will be run when
	//UpdateSchema() is called.
	//
	//These functions are executed after UpdateQueries.
	//
	//Each function should be safe to be rerun multiple times!
	UpdateFuncs []QueryFunc

	//UpdateQueryTranslators is a list of functions that translate an UpdateQuery
	//from one database dialect to another.
	//
	//An UpdateQueryTranslator function takes an UpdateQuery as an input and returns
	//a rewritten query.
	UpdateQueryTranslators []Translator

	//UpdateQueryErrorHandlers is a list of functions that are run when an error
	//results from running an UpdateQuery and is used to determine if the error can
	//be ignored.
	//An UpdateQueryErrorHandler function takes an UpdateQuery and the error resulting
	//from Exec as an input and returns true if the error should be ignored.
	UpdateQueryErrorHandlers []ErrorHandler

	//LoggingLevel enables logging at ERROR, INFO, or DEBUG levels.
	LoggingLevel logLevel
	// contains filtered or unexported fields
}

Config is the details used for establishing and using a database connection.

func New

func New() *Config

New returns a Config instance with some defaults set. You would typically call Use() and/or Connect() after New().

func NewMSSQL

func NewMSSQL(host, dbName, user, password string) *Config

NewMSSQL is a shorthand for calling New() and then manually setting the applicable MS SQL Server fields.

func NewMariaDB

func NewMariaDB(host, dbName, user, password string) *Config

NewMariaDB is a shorthand for calling New() and then manually setting the applicable MariaDB fields.

func NewMySQL

func NewMySQL(host, dbName, user, password string) *Config

NewMySQL is a shorthand for calling New() and then manually setting the applicable MySQL fields.

func NewSQLite

func NewSQLite(path string) *Config

NewSQLite is a shorthand for calling New() and then manually setting the applicable SQLite fields.

func (*Config) AddConnectionOption

func (c *Config) AddConnectionOption(key, value string)

AddConnectionOption adds a key-value pair to a config's ConnnectionOptions field. Using this func is just easier then calling map[string]string{"key", "value"}. This does not check if the key already exist, it will simply add a duplicate key-value pair.

Typically this is only needed for connecting to MSSQL databases.

func (*Config) Close

func (c *Config) Close() (err error)

Close handles closing the underlying database connection stored in the config.

func (*Config) Connect

func (c *Config) Connect() (err error)

Connect connects to the database. This establishes the database connection, and saves the connection pool for use in running queries. For SQLite, this also runs any PRAGMA commands when establishing the connection.

func (*Config) Connected

func (c *Config) Connected() bool

Connected returns if the config represents an established connection to a database.

func (*Config) Connection

func (c *Config) Connection() *sqlx.DB

Connection returns the underlying database connection stored in a config for use in running queries.

func (*Config) DeploySchema

func (c *Config) DeploySchema(opts *DeploySchemaOptions) (err error)

DeploySchema runs the DeployQueries and DeployFuncs specified in a config against the database noted in the config. Use this to create your tables, create indexes, etc. This will automatically issue a CREATE DATABASE IF NOT EXISTS query.

DeployQueries will be translated via DeployQueryTranslators and any DeployQuery errors will be processed by DeployQueryErrorHandlers. Neither of these steps apply to DeployFuncs.

DeploySchemaOptions is a pointer so that in cases where you do not want to provide any options, using the defaults, you can simply provide nil.

Typically this func is run when a flag, i.e.: --deploy-db, is provided.

func (*Config) IsMSSQL

func (c *Config) IsMSSQL() bool

IsMSSQL returns true if a config represents a MS SQL connection.

func (*Config) IsMariaDB

func (c *Config) IsMariaDB() bool

IsMariaDB returns true if a config represents a MariaDB connection.

func (*Config) IsMySQL

func (c *Config) IsMySQL() bool

IsMySQL returns true if a config represents a MySQL connection.

func (*Config) IsSQLite

func (c *Config) IsSQLite() bool

IsSQLite returns true if a config represents a SQLite connection.

func (*Config) RunDeployQueryTranslators

func (c *Config) RunDeployQueryTranslators(in string) (out string)

RunDeployQueryTranslators runs the list of DeployQueryTranslators on the provided query.

This func is called in DeploySchema() but can also be called manually when you want to translate a DeployQuery (for example, running a specific DeployQuery as part of UpdateSchema).

func (*Config) RunUpdateQueryTranslators

func (c *Config) RunUpdateQueryTranslators(in string) (out string)

RunUpdateQueryTranslators runs the list of UpdateQueryTranslators on the provided query.

This func is called in UpdateSchema().

func (*Config) UpdateSchema

func (c *Config) UpdateSchema(opts *UpdateSchemaOptions) (err error)

UpdateSchema runs the UpdateQueries and UpdateFuncs specified in a config against the database noted in the config. Use this to add columns, add indexes, rename things, perform data changes, etc.

UpdateQueries will be translated via UpdateQueryTranslators and any UpdateQuery errors will be processed by UpdateQueryErrorHandlers. Neither of these steps apply to UpdateFuncs.

UpdateSchemaOptions is a pointer so that in cases where you do not want to provide any options, using the defaults, you can simply provide nil.

Typically this func is run when a flag, i.e.: --update-db, is provided.

type DeploySchemaOptions

type DeploySchemaOptions struct {
	//CloseConnection determines if the database connection should be closed after
	//running all the DeployQueries and DeployFuncs.//
	//
	//This was added to support deploying and then using a SQLite in-memory databse.
	//Each connection to an in-memory database references a new database, so to run
	//queries against an in-memory database that was just deployed, we need to keep
	//the connection open.
	CloseConnection bool //default true
}

DeploySchemaOptions provides options when deploying a schema.

type ErrorHandler

type ErrorHandler func(string, error) bool

ErrorHandler is a function that determines if an error returned from database/sql.Exec when DeploySchema() is called can be ignored. An error handler is typically used to ignore errors that arise from a query being run multiple times but the result already being applied (think, renaming a table or column).

Error handlers typically have an "is this error handler applicable, if so check if the error should be ignore, and if so, ignore the error"

Ex:

func IgnoreDuplicateColumnError (q query, err error) bool {
  if !strings.Contains(q, "ADD COLUMN") && strings.Contains(err.Error(), "duplicate column") {
	    return true
  }

  return false
 }

type QueryFunc

type QueryFunc func(*sqlx.DB) error

QueryFunc is a function used to perform a deployment or Update task that is more complex than just a SQL query that could be provided in a DeployQuery or UpdateQuery.

type Translator

type Translator func(string) string

Translator is a function that translates a DeployQuery or UpdateQuery from one SQL dialect to another. Translators run when DeploySchema() or UpdateSchame() is called.

Translators typically have an "is this translator applicable, perform the translation" format.

Ex:

func TranslateDatetimeToText (in query) string {
  if !strings.Contains(in, "DATETIME") {
	    return in
  }

  return strings.Replace(in, "DATETIME", "TEXT")
 }

type UpdateSchemaOptions

type UpdateSchemaOptions struct {
	// CloseConnection determines if the database connection should be closed after
	// running all the DeployQueries and DeployFuncs.//
	//
	//This was added to support deploying and then using a SQLite in-memory databse.
	//Each connection to an in-memory database references a new database, so to run
	//queries against an in-memory database that was just deployed, we need to keep
	//the connection open.
	CloseConnection bool //default true
}

UpdateSchemaOptions provides options when updating a schema.

type Where

type Where string

Where is the WHERE statement in a query. This separate type is useful for times when you are passing a WHERE clause into a func and you want a bit more control over what is provided.

func (Where) String

func (w Where) String() string

String converts the Where type into a string type for easier use.

Jump to

Keyboard shortcuts

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