db

package
v0.0.2 Latest Latest
Warning

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

Go to latest
Published: Jan 22, 2019 License: MIT Imports: 20 Imported by: 0

Documentation

Index

Constants

View Source
const (
	MYSQL_TYPE_SET  = "Set"
	MYSQL_TYPE_ENUM = "Enum"
)
View Source
const (
	SELECT = "SELECT"
	INSERT = "INSERT"
	UPDATE = "UPDATE"
	DELETE = "DELETE"
)
View Source
const (
	SQL_TYPE_UNKNOWN  = "Unknown"
	SQL_TYPE_BLOB     = "Blob"
	SQL_TYPE_VARCHAR  = "VarChar"
	SQL_TYPE_CHAR     = "Char"
	SQL_TYPE_TEXT     = "Text"
	SQL_TYPE_INTEGER  = "Int"
	SQL_TYPE_DATETIME = "DateTime"
	SQL_TYPE_DATE     = "Date"
	SQL_TYPE_TIME     = "Time"
	SQL_TYPE_FLOAT    = "Float"
	SQL_TYPE_DOUBLE   = "Double"
	SQL_TYPE_BOOL     = "Bool"
	SQL_TYPE_DECIMAL  = "Decimal" // a fixed point type
)

Variables

This section is empty.

Functions

func AddDatabase

func AddDatabase(d DatabaseI, key string)

func AnalyzeDatabases

func AnalyzeDatabases()

func GetDatabases

func GetDatabases() map[string]DatabaseI

func IsProfiling

func IsProfiling(ctx context.Context) bool

func NewSqlBuilder

func NewSqlBuilder(db SqlDbI) *sqlBuilder

* NewsqlBuilder creates a new sqlBuilder object.

func ReceiveRows

func ReceiveRows(rows *sql.Rows, columnTypes []GoColumnType, columnNames []string) (values []map[string]interface{})

ReceiveRows gets data from a sql result set and returns it as a slice of maps. Each row is mapped to its table name. If you provide table names, those will be used in the map. Otherwise it will get the table names out of the result set provided

Types

type ColumnDescription

type ColumnDescription struct {
	DbName                string // name in database. Blank if this is a "virtual" table for sql tables. i.e. an association or virtual attribute query
	GoName                string
	NativeType            string       // type of table based on native description of table
	GoType                GoColumnType // represents a basic go type
	MaxCharLength         uint64       // To help fields limit the number of characters or bytes they will accept, when its known
	DefaultValue          interface{}  // gets cast to the goType
	MaxValue              interface{}
	MinValue              interface{}
	IsId                  bool // Is this a unique identifier that is generated by the database system?
	IsPk                  bool // A primary key. Could be generated by us.
	IsNullable            bool
	IsIndexed             bool // Does it have a single index on itself. Will generate a LoadBy function
	IsUnique              bool
	IsAutoUpdateTimestamp bool // Database is auto updating this timestamp, or
	ShouldUpdateTimestamp bool // We should generate code to auto update this timestamp.
	Comment               string

	// Filled in by analyzer
	Options    *maps.SliceMap
	ForeignKey *ForeignKeyType
	ModelName  string // code generating convenience. The internal name in the model corresponding to this column.
}

ColumnDescription describes a database column for the purpose of code generation. Most of the information is either gleaned from the structure of the database, or is taken from a file that describes the relationships between different record types. Some of the information is filled in after analysis. Some of the information can be provided through information embedded in database comments.

func (*ColumnDescription) DefaultConstantName

func (cd *ColumnDescription) DefaultConstantName(tableName string) string

func (*ColumnDescription) DefaultValueAsConstant

func (cd *ColumnDescription) DefaultValueAsConstant() string

Returns the default

func (*ColumnDescription) DefaultValueAsValue

func (cd *ColumnDescription) DefaultValueAsValue() string

func (*ColumnDescription) IsReference

func (cd *ColumnDescription) IsReference() bool

type Copier

type Copier interface {
	Copy() interface{}
}

Copier implements the copy interface, that returns a deep copy of an object.

type DatabaseDescription

type DatabaseDescription struct {
	// The database key corresponding to its key in the global database cluster
	DbKey  string
	Tables []*TableDescription
	// Type tables contain a description of an enumerated type
	TypeTables []*TypeTableDescription
	// The prefix for related objects.
	AssociatedObjectPrefix string

	// Text to strip off the end of foreign key references when converting to names. Defaults to "_id"
	ForeignKeySuffix string
	// contains filtered or unexported fields
}

The DatabaseDescription is the top level struct that contains a complete description of a database for purposes of generating and creating queries

func NewDatabaseDescription

func NewDatabaseDescription(dbKey string, objectPrefix string, fkSuffix string) *DatabaseDescription

func (*DatabaseDescription) IsTypeTable

func (dd *DatabaseDescription) IsTypeTable(name string) bool

func (*DatabaseDescription) TableDescription

func (dd *DatabaseDescription) TableDescription(name string) *TableDescription

func (*DatabaseDescription) TypeTableDescription

func (dd *DatabaseDescription) TypeTableDescription(name string) *TypeTableDescription

type DatabaseI

type DatabaseI interface {
	Describe() *DatabaseDescription

	// For codegen
	GoStructPrefix() string
	AssociatedObjectPrefix() string

	// Aid to build queries and deletes
	NewBuilder() QueryBuilderI

	Update(ctx context.Context, table string, fields map[string]interface{}, pkName string, pkValue string)
	Insert(ctx context.Context, table string, fields map[string]interface{}) string
	Delete(ctx context.Context, table string, pkName string, pkValue interface{})

	Begin(ctx context.Context) TransactionID
	Commit(ctx context.Context, txid TransactionID)
	Rollback(ctx context.Context, txid TransactionID)
}

The dataStore is the central database collection used in codegeneration and the orm.

func GetDatabase

func GetDatabase(key string) DatabaseI

type Describer

type Describer interface {
	Describe() *DatabaseDescription
}

type FKAction

type FKAction int
const (
	FK_ACTION_NONE FKAction = iota // In a typical database, this is the same as Restrict. For OUR purposes, it means we should deal with it ourselves.
	// This would be the situation when we are emulating foreign key constraints for databases that don't support them.
	FK_ACTION_SET_NULL
	FK_ACTION_SET_DEFAULT // Not supported in MySQL!
	FK_ACTION_CASCADE     //
	FK_ACTION_RESTRICT    // The database is going to choke on this. We will try to error before something like this happens.
)

The foreign key actions tell us what the database will do automatically if a foreign key object is changed. This allows us to do the appropriate thing when we detect in the ORM that a linked object is changing.

type ForeignKeyDescription

type ForeignKeyDescription struct {
	KeyName        string
	Columns        []string
	RelationSchema string
	RelationTable  string
	// contains filtered or unexported fields
}

Describes a foreign key relationship between columns in one table and columns in a different table We currently allow the collection of multi-table and cross-database fk data, but we don't currently support them in codegen.

type ForeignKeyType

type ForeignKeyType struct {
	//DbKey string	// We don't support cross database foreign keys yet. Someday maybe.
	TableName    string
	ColumnName   string
	UpdateAction FKAction
	DeleteAction FKAction
	GoName       string // The name we should use to refer to the related object
	GoType       string // The type of the related object
	IsType       bool
	RR           *ReverseReference // Filled in by analyzer, the corresponding
}

func (*ForeignKeyType) GoVarName

func (fk *ForeignKeyType) GoVarName() string

type IndexDescription

type IndexDescription struct {
	KeyName     string
	IsUnique    bool
	IsPrimary   bool
	ColumnNames []string
}

type LoaderFunc

type LoaderFunc func(QueryBuilderI, map[string]interface{})

type ManyManyReference

type ManyManyReference struct {
	// NoSQL: The originating table. SQL: The association table
	AssnTableName string
	// NoSQL: The table storing the array of ids on the other end. SQL: the table in the association table pointing towards us.
	AssnColumnName string

	// NoSQL & SQL: The table we are joining to
	AssociatedTableName string
	// NoSQL: table point backwards to us. SQL: Column in association table pointing forwards to refTable
	AssociatedColumnName string

	AssociatedObjectName string

	// The virtual table names used to describe the objects on the other end of the association
	GoName   string
	GoPlural string

	IsTypeAssociation bool
	Options           maps.SliceMap

	MM *ManyManyReference // ManyManyReference pointing back towards this one
}

The ManyManyReference structure is used by the templates during the codegen process to describe a many-to-any relationship.

type Mysql5

type Mysql5 struct {
	SqlDb
	// contains filtered or unexported fields
}

Mysql5 is the goradd driver for mysql databases. It works through the excellent go-sql-driver driver, to supply functionality above go's built in driver. To use it, call NewMysql5, but afterwards, work through the DB parent interface so that the underlying database can be swapped out later if needed.

Timezones Timezones are always tricky. Mysql has some interesting quirks:

  • Datetime types are internally stored in the timezone of the server, and then returned based on the

timezone of the client.

  • Timestamp types are internally stored in UTC and returned in the timezone of the client.

The benefit of this is that you can move your database to a server in another timezone, and the times will automatically change to the correct timezone.

  • The mysql-go-driver has the ability to set a default timezone in the Loc configuration parameter

It appears to convert all times to this timezone before sending them to the database, and then when receiving times, it will set this as the timezone of the date.

These issues are further compounded by the fact that MYSQL can initialize date and time values to what it believes is the current date and time in its server's timezone, but will not save the timezone itself.

So, as a general rule, use Datetime types to represent a date combined with a time, like an appointment in a calendar or a recurring event that happens in whatever the current timezone is. Use Timestamp types to store data that records when an event happened.

Also, set the Loc configuration parameter to be the same as the server's timezone. By default its UTC. That will make it so all dates and times are in the same timezone as those automatically generated by MYSQL. It is best to set this and your database to UTC, as this will make your database portable to other timezones.

Set the ParseTime configuration paramater to TRUE so that the driver will parse the times into the correct timezone, navigating the GO server and database server timezones. Otherwise, we can only assume that the database is in UTC time, since we will not get any timezone info from the server.

Since the driver will return times in the timezone of the mysql server, our own sql driver will convert these to local time. This will mean that you can save data in local time, and you will receive data in local time in your app, but you need to be aware that when you view the data in the SQL, it will appear in whatever timezone the MYSQL server is set to.

func NewMysql5

func NewMysql5(dbKey string, params string, config *mysql.Config) *Mysql5

New Mysql5 creates a new Mysql5 object and returns its matching interface

func (*Mysql5) Delete

func (m *Mysql5) Delete(ctx context.Context, table string, pkName string, pkValue interface{})

func (*Mysql5) Describe

func (m *Mysql5) Describe() *DatabaseDescription

func (*Mysql5) Insert

func (m *Mysql5) Insert(ctx context.Context, table string, fields map[string]interface{}) string

func (*Mysql5) NewBuilder

func (m *Mysql5) NewBuilder() QueryBuilderI

func (*Mysql5) Update

func (m *Mysql5) Update(ctx context.Context, table string, fields map[string]interface{}, pkName string, pkValue string)

type Option

type Option struct {
	// contains filtered or unexported fields
}

type ProfileEntry

type ProfileEntry struct {
	DbKey     string
	BeginTime time.Time
	EndTime   time.Time
	Typ       string
	Sql       string
}

ProfileEntry contains the data collected during sql profiling

func GetProfiles

func GetProfiles(ctx context.Context) []ProfileEntry

TODO: Move profiles to a session variable so we can access ajax queries too

type ReverseReference

type ReverseReference struct {
	DbTable              string
	DbColumn             string
	AssociatedTableName  string
	AssociatedColumnName string
	GoName               string
	GoPlural             string
	GoType               string
	IsUnique             bool
}

type SqlContext

type SqlContext struct {
	// contains filtered or unexported fields
}

SqlContext is what is stored in the current context to keep track of queries. You must save a copy of this in the current context with the SqlContext key before calling database functions in order to use transactions or database profiling, or anything else the context is required for. The framework does this for you, but you will need to do this yourself if using the orm without the framework.

type SqlDb

type SqlDb struct {
	// contains filtered or unexported fields
}

func NewSqlDb

func NewSqlDb(dbKey string) SqlDb

func (*SqlDb) AssociatedObjectPrefix

func (s *SqlDb) AssociatedObjectPrefix() string

func (*SqlDb) AssociationTableSuffix

func (s *SqlDb) AssociationTableSuffix() string

func (*SqlDb) Begin

func (s *SqlDb) Begin(ctx context.Context) (txid TransactionID)

Begin starts a transaction. You should immediately defer a Rollback using the returned transaction id. If you Commit before the Rollback happens, no Rollback will occur.

func (*SqlDb) Commit

func (s *SqlDb) Commit(ctx context.Context, txid TransactionID)

Commit commits the transaction, and if an error occurs, will panic with the error.

func (*SqlDb) DbKey

func (s *SqlDb) DbKey() string

func (*SqlDb) Exec

func (s *SqlDb) Exec(ctx context.Context, sql string, args ...interface{}) (r sql.Result, err error)

func (*SqlDb) GoStructPrefix

func (s *SqlDb) GoStructPrefix() string

func (*SqlDb) IdSuffix

func (s *SqlDb) IdSuffix() string

func (*SqlDb) Prepare

func (s *SqlDb) Prepare(ctx context.Context, sql string) (r *sql.Stmt, err error)

func (*SqlDb) Query

func (s *SqlDb) Query(ctx context.Context, sql string, args ...interface{}) (r *sql.Rows, err error)

func (*SqlDb) Rollback

func (s *SqlDb) Rollback(ctx context.Context, txid TransactionID)

Rollback will rollback the transaction if the transaction is still pointing to the given txid. This gives the effect that if you call Rollback on a transaction that has already been committed, no Rollback will happen. This makes it easier to implement a transaction management scheme, because you simply always defer a Rollback after a Begin. Pass the txid that you got from the Begin to the Rollback

func (*SqlDb) SetAssociatedObjectPrefix

func (s *SqlDb) SetAssociatedObjectPrefix(prefix string)

func (*SqlDb) SetAssociationTableSuffix

func (s *SqlDb) SetAssociationTableSuffix(suffix string)

func (*SqlDb) SetGoStructPrefix

func (s *SqlDb) SetGoStructPrefix(prefix string)

func (*SqlDb) SetTypeTableSuffix

func (s *SqlDb) SetTypeTableSuffix(suffix string)

func (*SqlDb) StartProfiling

func (s *SqlDb) StartProfiling()

func (*SqlDb) TypeTableSuffix

func (s *SqlDb) TypeTableSuffix() string

type SqlDbI

type SqlDbI interface {
	Exec(ctx context.Context, sql string, args ...interface{}) (r sql.Result, err error)
	Query(ctx context.Context, sql string, args ...interface{}) (r *sql.Rows, err error)
	TypeTableSuffix() string
	AssociationTableSuffix() string
	// contains filtered or unexported methods
}

type SqlReceiver

type SqlReceiver struct {
	R interface{}
}

SqlReceiver is an encapsulation of a way of receiving data from sql queries as interface{} pointers. This allows you to get data without knowing the type of data you are asking for ahead of time, and is easier for dealing with NULL fields. Some database drivers (MySql for one), return different results in fields depending on how you call the query (using a prepared statement can return different results than without one), or if the data does not quite fit (UInt64 in particular will return a string if the returned value is bigger than MaxInt64, but smaller than MaxUint64.)

Pass the address of the R member to the sql.Scan method when using an object of this type. IsRequired because there are some idiosyncracies with how Go treats return values that would prevent returning an address of R from a function

func (SqlReceiver) BoolI

func (r SqlReceiver) BoolI() interface{}

func (SqlReceiver) DoubleI

func (r SqlReceiver) DoubleI() interface{}

func (SqlReceiver) FloatI

func (r SqlReceiver) FloatI() interface{}

func (SqlReceiver) Int64I

func (r SqlReceiver) Int64I() interface{}

func (SqlReceiver) IntI

func (r SqlReceiver) IntI() interface{}

func (SqlReceiver) StringI

func (r SqlReceiver) StringI() interface{}

func (SqlReceiver) TimeI

func (r SqlReceiver) TimeI() interface{}

func (SqlReceiver) Uint64I

func (r SqlReceiver) Uint64I() interface{}

Some drivers (like MySQL) return all integers as Int64. This converts to uint64. Its up to you to make sure you only use this on 64-bit uints or smaller.

func (SqlReceiver) UintI

func (r SqlReceiver) UintI() interface{}

Some drivers (like MySQL) return all integers as Int64. This converts to basic golang uint. Its up to you to make sure you only use this on 32-bit uints or smaller

func (SqlReceiver) Unpack

func (r SqlReceiver) Unpack(typ GoColumnType) interface{}

Convert an SqlReceiver to a type corresponding to the given GoColumnType

type TableDescription

type TableDescription struct {
	// Key used to find database in the global database cluster
	DbKey string
	// The name of the database table or object
	DbName string
	// The literal name of the object when describing it to the world. Use the "literalName" option in the comment to override the default. Should be lower case.
	LiteralName string
	// The plural name of the object. Use the "literalPlural" option in the comment to override the default. Should be lower case.
	LiteralPlural string
	// The name of the struct when referring to it in go code. Use the "goName" option in the comment to override the default.
	GoName string
	// The name of a collection of these objects when referring to them in go code. Use the "goPlural" option in the comment to override the default.
	GoPlural string
	// same as GoName, but with first letter lower case
	LcGoName string
	Columns  []*ColumnDescription

	Indexes       []IndexDescription // Creates LoadBy functions. Mapped by index name.
	Options       maps.SliceMap
	IsType        bool
	IsAssociation bool
	Comment       string

	// The following items are filled in by the analyze process
	ManyManyReferences []*ManyManyReference
	ReverseReferences  []*ReverseReference
	HasDateTime        bool
	PrimaryKeyColumn   *ColumnDescription

	// Do not process this table
	Skip bool
	// contains filtered or unexported fields
}

func GetTableDescription

func GetTableDescription(key string, goTypeName string) *TableDescription

func NewTableDescription

func NewTableDescription(tableName string) *TableDescription

func (*TableDescription) GetColumn

func (td *TableDescription) GetColumn(name string) *ColumnDescription

type TransactionID

type TransactionID int

type TypeTableDescription

type TypeTableDescription struct {
	// Key used to find database in the global database cluster
	DbKey string
	// Name in the database
	DbName string
	// The english name of the object when describing it to the world. Use the "literalName" option in the comment to override the default.
	EnglishName string
	// The plural english name of the object. Use the "literalPlural" option in the comment to override the default.
	EnglishPlural string
	// The name of the item as a go type name.
	GoName     string
	GoPlural   string
	LcGoName   string
	FieldNames []string // The first field name MUST be the name of the id field, and 2nd MUST be the name of the name field, the others are optional extra fields
	FieldTypes map[string]GoColumnType
	Values     []map[string]interface{}

	PkField string

	// Filled in by analyzer
	Constants map[uint]string
}

Type tables essentially define enumerated types. In the SQL world, they are a table with an integer key (starting index 1) and a "name" value, though they can have other values associated with them too. Goradd will maintain the relationships in SQL, but in a No-SQL situation, it will embed all the ids and values.

func GetTypeTableDescription

func GetTypeTableDescription(key string, goTypeName string) *TypeTableDescription

func (*TypeTableDescription) FieldGoName

func (tt *TypeTableDescription) FieldGoName(i int) string

Return the go name corresponding to the given field offset

func (*TypeTableDescription) FieldGoType

func (tt *TypeTableDescription) FieldGoType(i int) string

Return the go type corresponding to the given field offset

type ValueMap

type ValueMap map[string]interface{}

func NewValueMap

func NewValueMap() ValueMap

func (ValueMap) Copy

func (m ValueMap) Copy() interface{}

Support the deep copy interface

Jump to

Keyboard shortcuts

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