Documentation
¶
Index ¶
- Constants
- Variables
- func ApplyMigrations(dialect Dialect, db DBTX, migrations ...Migration) error
- func MakeSQLRepositories(dialect Dialect) ([]interface{}, error)
- func Migrate(dialect Dialect, dbtx DBTX) error
- func MustMakeSQLRepositories(dbtx DBTX) []interface{}
- func MustMigrate(db *sql.DB)
- func MustOpen(opts Opts) *sql.DB
- func NewRepository(dialect Dialect, dst interface{}) error
- func Open(opts Opts) (*sql.DB, error)
- func WithContext(ctx context.Context, db DBTX) context.Context
- func WithTransaction(db *sql.DB) func(Handler) Handler
- type DBTX
- type Dialect
- type DialectStatement
- type Handler
- type KeyValues
- type Migration
- type MigrationStatus
- type MigrationStatusEntry
- type MigrationType
- type NamedParameterStatement
- type Opts
- type Repository
- type SSLMode
Constants ¶
const ( SSLPreferred SSLMode = 0 // mysql: PREFERRED, postgres: prefer SSLDisable = 1 // mysql: DISABLED, postgres: disable SSLRequired = 2 // mysql: REQUIRED, postgres: require SSLVerifyCA = 3 // mysql: VERIFY_CA, postgres: verify-ca SSLVerifyIdentify = 4 // mysql: VERIFY_IDENTITY, postgres: verify-full )
const ( SQL MigrationType = "sql" Success MigrationStatus = "success" Failed MigrationStatus = "failed" Pending MigrationStatus = "pending" Executing MigrationStatus = "executing" )
const ( // returns error Stmt sqlResultType = 0 // returns []T,error List sqlResultType = 1 // returns T,error Single sqlResultType = 2 )
const AnnotationName = "ee.sql.Name"
AnnotationName must be used for field names to define a mapping of sql columns to fields, which is usually required because the notation differs (e.g. camel case vs snake case). This is SQL specific, because other repository providers require a different name-mapping. Example:
type MyEntity struct { ID uuid.UUID `ee.sql.Name:"id"` }
const AnnotationQuery = "ee.sql.Query"
AnnotationQuery defines a named SQL query which is translated into dialect specific positional prepared statement notations. Only one annotation per Method is allowed. Each Method must have exactly one annotation per dialect and all named parameters must be matched to actual method parameters. Queries without dialect are candidates for all dialects, however if a specific dialect is defined, it has a higher priority and will not be considered a duplicate. Example:
@ee.sql.Query("SELECT id FROM myTable WHERE col = :param") //generic named query @ee.sql.Query("dialect":"mysql", "value":"SELECT BIN_TO_UUID(id) FROM myTable WHERE col = :param") // mysql query
const AnnotationRepository = "ee.stereotype.Repository"
AnnotationRepository defines a stereotype and is currently only a marker annotation so that #MakeSQLRepositories() can detect repository interfaces to implement. Actually this annotation is not sql specific and may be shared by different repository providers (e.g. no-sql). Example:
// @ee.stereotype.Repository("myTable") type MyRepository interface { // @ee.sql.Query("SELECT id FROM myTable WHERE id = :id") FindById(ctx context.Context, id uuid.UUID) (MyEntity, error) }
const AnnotationSchema = "ee.sql.Schema"
AnnotationSchema contains generic or dialect specific statements like "CREATE TABLE" statements. They are enumerated by order, if nothing else has been set. Internally, the migration information is kept in the following table:
CREATE TABLE IF NOT EXISTS "migration_schema_history" ( "group" VARCHAR(255) NOT NULL, "version" BIGINT NOT NULL, "script" VARCHAR(255) NOT NULL, "type" VARCHAR(12) NOT NULL, "checksum" CHAR(64) NOT NULL, "applied_at" TIMESTAMP NOT NULL, "execution_duration" BIGINT NOT NULL, "status" VARCHAR(12) NOT NULL, "log" TEXT NOT NULL, PRIMARY KEY ("group", "version") )
Usage examples:
@ee.sql.Schema("CREATE TABLE IF NOT EXISTS `my_table` (`id` BINARY(16), PRIMARY KEY (`id`)") // generic schema @ee.sql.Schema("dialect":"postgresql", "value":"CREATE TABLE `my_table` (`id` UUID, PRIMARY KEY (`id`)") // specific schema
Be careful when mixing specific and non-specific schema declaration: they are just filtered and have no precedence. Migration order is as specified, but can be overloaded. Also each migration belongs to a group, which is by default the name of the stereotype. Complex example:
@ee.sql.Schema(""" "dialect":"mysql", "version":1, "group":"some_name", "value": "CREATE TABLE IF NOT EXISTS `some_table_name` ( `group` VARCHAR(255) NOT NULL, `version` BIGINT NOT NULL, `script` VARCHAR(255) NOT NULL, `type` VARCHAR(12) NOT NULL, `checksum` CHAR(64) NOT NULL, `applied_at` TIMESTAMP NOT NULL, `execution_duration` BIGINT NOT NULL, `status` VARCHAR(12) NOT NULL, `log` TEXT NOT NULL, PRIMARY KEY (`group`, `version`) )" """)
const DialectValue = "dialect"
DialectValue can be used by ee.sql.Schema and ee.sql.Query
const GroupValue = "group"
GroupValue can be used by ee.sql.Schema to override the default group assignment
const VersionValue = "version"
VersionValue can be used by ee.sql.Schema to override the default version assignment (which is its applicable index)
Variables ¶
var ErrEntityNotFound = fmt.Errorf("entity not found")
Functions ¶
func ApplyMigrations ¶
ApplyMigrations calculates which migrations needs to be applied and tries to apply the missing ones.
func MakeSQLRepositories ¶
MakeSQLRepositories scans for @ee.stereotype.Repository annotated interfaces and tries to create a proxy instance for each.
func Migrate ¶
Migrate grabs all @ee.sql.Schema() annotations from all available repositories and tries to apply them. Each schema statement is verified to proof that the migration process is repeatable.
func MustMakeSQLRepositories ¶
func MustMakeSQLRepositories(dbtx DBTX) []interface{}
MustMakeSQLRepositories tries to autodetect and implement all interfaces marked with @ee.stereotype.Repository.
func MustMigrate ¶
MustMigrate panics, if the migrations cannot be applied. Creates a transaction and tries a rollback, before bailing out. Delegates to #Migrate() and auto detects dialect.
func NewRepository ¶
NewRepository tries to instantiate the given interface, so it must be a pointer to a concrete (nil) interface. Example:
var repo MyRepo err := sql.NewRepository(sql.ParseDialect("mysql"), &repo)
func Open ¶
Open is a delegate to #sql.Open() and assembles the correct connection string automatically. You still need to import the driver, you want to support, e.g.
import _ "github.com/go-sql-driver/mysql" // for mysql import _ "github.com/lib/pq" // for postgres
func WithContext ¶
WithContext creates a new context containing the given DBTX. Use this to implement orthogonal requirements like a scoped transaction. To learn more about when and how to use context, take a look at https://tip.golang.org/pkg/context/. It is a performance decision to reuse a repository, instead of creating the entire dependency chain for each request.
Types ¶
type DBTX ¶
type Dialect ¶
type Dialect int
func DetectDialect ¶
DetectDialect tries to auto detect the dialect from the given database connection
func ParseDialect ¶
ParseDialect guestimates the dialect from the given string or returns 0
type DialectStatement ¶
type DialectStatement struct {
// contains filtered or unexported fields
}
func (DialectStatement) ExecContext ¶
func (s DialectStatement) ExecContext(db DBTX, ctx context.Context, args ...interface{}) (sql.Result, error)
Exec executes a statement filling in the arguments in the exact order as defined by prepare
func (DialectStatement) QueryContext ¶
func (DialectStatement) String ¶
func (s DialectStatement) String() string
type MigrationStatus ¶
type MigrationStatus string
type MigrationStatusEntry ¶
type MigrationStatusEntry struct { Group string Version int64 Script string Type MigrationType Checksum string AppliedAt time.Time ExecutionDuration time.Duration Status MigrationStatus Log string }
func SchemaHistory ¶
func SchemaHistory(tx DBTX) ([]MigrationStatusEntry, error)
SchemaStatus returns all applied migration or schema scripts and their according states.
type MigrationType ¶
type MigrationType string
type NamedParameterStatement ¶
type NamedParameterStatement string
A NamedParameterStatement is like a prepared statement but cross SQL dialect capable. Example:
"SELECT * FROM table WHERE x = :myParam AND y = :myParam OR z = :myOtherParam
func (NamedParameterStatement) Names ¶
func (s NamedParameterStatement) Names() []string
func (NamedParameterStatement) Prepare ¶
func (s NamedParameterStatement) Prepare(sql Dialect, argNames []string) (DialectStatement, error)
Prepare creates a dialect specific statement using the given argNames. Later you need to keep the exact same order.
func (NamedParameterStatement) Validate ¶
func (s NamedParameterStatement) Validate(names []string) error
Validate checks if the named parameters and given names are congruent
type Opts ¶
type Repository ¶
type Repository struct {
// contains filtered or unexported fields
}
func (*Repository) HandleQuery ¶
func (r *Repository) HandleQuery(method string, args ...interface{}) []interface{}