import "bitbucket.org/jaybill/sawsij/framework/model"
Provides a simple database access layer and table/field mapping.
The Model package is intended to provide something analagous to a lightweight ORM, though not quite. The general pattern of usage is that you create a struct that represents a row in your table, with the fields mapping to column names. You then pass a pointer to that struct into Model's various methods to perform database operations. At the moment, only postgres is supported.
Struct field names are converted to database column names using sawsij.MakeDbName() and database column names are converted to struct field names using sawsij.MakeFieldName(). Generally, it works as follows:
A struct field called "FirstName" will be mapped to a database column named "first_name". A struct field called "Type" will be mapped to a database column named "type".
Table names are mapped the same way, wherin a struct of type "PersonAddress" would look for a table called "person_address".
If you set the Schema property to a valid schema name, it will be used. If generally only use one schema in your app, you can just set the search path for the database user in postgres and omit the Schema property. (You can specifiy it if you want to use some other schema.) You can generally do this in postgres with the following query:
ALTER USER [db_username] SET search_path to '[app_schema_name]'
As currently implemented, both your table and your struct must have an identity to do anything useful. ("join" tables being the exception)
func MakeDbName(fieldName string) string
MakeDbName converts a struct field name into a database field name. The string will be converted to lowercase, and any capital letters after the first one will be prepended with an underscore. "FirstName" will become "first_name" and so on.
func MakeFieldName(dbName string) string
MakeDbName converts a database column name into a struct field name. The first letter will be made capital, and underscores will be removed and the following letter made capital. "first_name" will become "FirstName", etc.
func ParseDbVersionsFile(dBconfigFilename string) (defaultSchema string, allSchemas []Schema, err error)
Reads dbversions file specified by filename and returns schema information
func RunScript(db *sql.DB, dbscript string) (err error)
RunScript takes a file path to a sql script, reads the file and runs it against the database/schema. Queries will be run one at a time in a transaction. If there's any kind of error, the whole transaction will be rolled back. Queries must be terminated by ";" and you must use C style comments, not --. (This limitation will probably be removed at some point.)
type DbSetup struct {
Db *sql.DB
DefaultSchema string
Schemas []Schema
}A DbSetup is used to store a reference to the database connection and schema information.
type Query struct {
// A where clause, such as fmt.Sprintf("%v = 'Third Post'", MakeDbName("Title"))
Where string
// An order clause, such as fmt.Sprintf("%v DESC", MakeDbName("CreatedOn"))
Order string
// A number of records to limit the results to
Limit int
// The number of rows to offset the returned results by
Offset int
}The Query type is used to construct a SQL query. You should always use MakeDbName() to get column names, as this will ensure cross-RDBMS compatibility later on.
type SawsijDbError struct {
What string
}A struct for returning model error messages
func (e *SawsijDbError) Error() string
Returns the error message defined in What as a string
type SawsijDbVersion struct {
VersionId int64
RanOn time.Time
}DbVersion is a type representing the db_version table, which must exist in any schema you plan to use with "[appserver] [directory] migrate"
type Schema struct {
Name string
Version int64
}A Schema is used to store schema information, like the schema name and what version it is.
type Table struct {
Db *DbSetup
Schema string
}Table is the primary means of interaction with the database. It represents the access to a table, not the table itself. The package figures out what table to use based on the type being passed to the various methods of Table. Using anything but a 'flat' struct as a type will have unpredictable results.
func (m *Table) Delete(data interface{}) (err error)
Delete takes a pointer to a struct and deletes the row where the id in the table is the Id of the struct. Note that you don't need to have acquired this struct from a row, passing in a pointer to something like {Id: 4} will totally work.
func (m *Table) Fetch(data interface{}) (err error)
Fetch returns a single row where the id in the table is the Id of the struct.
func (m *Table) FetchAll(data interface{}, q Query, args ...interface{}) (ents []interface{}, err error)
FetchAll accepts a reference to a struct (generally "blank", though it doesn't matter), a Query and a set of query arguments and returns a set of rows that match the query.
func (m *Table) Insert(data interface{}) (err error)
Insert expects a pointer to a struct that represents a row in your database. The "Id" field of the referenced struct will be populated with the identity value if the row is successfully inserted.
func (m *Table) Update(data interface{}) (err error)
Update expects a pointer to a struct that represents a row in your database. The "Id" field of the struct will be used in the where clause.