diff --git a/postgresql/collection.go b/postgresql/collection.go index 5af922023ef99079ce82b7453d4a48dc4d059f26..3f71764f10c449e4786ce484af03795cbc713bc5 100644 --- a/postgresql/collection.go +++ b/postgresql/collection.go @@ -30,27 +30,20 @@ import ( "upper.io/db" "upper.io/db/util/sqlgen" "upper.io/db/util/sqlutil" + "upper.io/db/util/sqlutil/result" ) -const defaultOperator = `=` - type table struct { sqlutil.T - source *source + *source primaryKey string names []string } +// Find creates a result set with the given conditions. func (t *table) Find(terms ...interface{}) db.Result { where, arguments := sqlutil.ToWhereWithArguments(terms) - - result := &result{ - table: t, - where: where, - arguments: arguments, - } - - return result + return result.NewResult(t, where, arguments) } func (t *table) tableN(i int) string { @@ -63,9 +56,9 @@ func (t *table) tableN(i int) string { return "" } -// Deletes all the rows within the collection. +// Truncate deletes all rows within the table. func (t *table) Truncate() error { - _, err := t.source.doExec(sqlgen.Statement{ + _, err := t.source.Exec(sqlgen.Statement{ Type: sqlgen.Truncate, Table: sqlgen.TableWithName(t.tableN(0)), }) @@ -77,7 +70,7 @@ func (t *table) Truncate() error { return nil } -// Appends an item (map or struct) into the collection. +// Append inserts an item (map or struct) into the collection. func (t *table) Append(item interface{}) (interface{}, error) { cols, vals, err := t.FieldValues(item) @@ -134,7 +127,7 @@ func (t *table) Append(item interface{}) (interface{}, error) { if len(pKey) == 0 { var res sql.Result - if res, err = t.source.doExec(stmt, arguments...); err != nil { + if res, err = t.source.Exec(stmt, arguments...); err != nil { return nil, err } @@ -149,7 +142,7 @@ func (t *table) Append(item interface{}) (interface{}, error) { // A primary key was found. stmt.Extra = sqlgen.Extra(fmt.Sprintf(`RETURNING "%s"`, strings.Join(pKey, `", "`))) - if rows, err = t.source.doQuery(stmt, arguments...); err != nil { + if rows, err = t.source.Query(stmt, arguments...); err != nil { return nil, err } @@ -196,7 +189,7 @@ func (t *table) Append(item interface{}) (interface{}, error) { return keyMap, nil } -// Returns true if the collection exists. +// Exists returns true if the collection exists. func (t *table) Exists() bool { if err := t.source.tableExists(t.names...); err != nil { return false @@ -204,6 +197,7 @@ func (t *table) Exists() bool { return true } +// Name returns the name of the table or tables that form the collection. func (t *table) Name() string { return strings.Join(t.names, `, `) } diff --git a/postgresql/connection.go b/postgresql/connection.go index b1d6ab909f1a42a678e13e50b8084ce53bbfeb3f..451383ce96af9a707eb03d9e354405127da4aeca 100644 --- a/postgresql/connection.go +++ b/postgresql/connection.go @@ -37,8 +37,8 @@ type scanner struct { i int } -// Next returns the next rune. -// It returns 0, false if the end of the text has been reached. +// Next returns the next rune. It returns 0, false if the end of the text has +// been reached. func (s *scanner) Next() (rune, bool) { if s.i >= len(s.s) { return 0, false @@ -48,8 +48,8 @@ func (s *scanner) Next() (rune, bool) { return r, true } -// SkipSpaces returns the next non-whitespace rune. -// It returns 0, false if the end of the text has been reached. +// SkipSpaces returns the next non-whitespace rune. It returns 0, false if the +// end of the text has been reached. func (s *scanner) SkipSpaces() (rune, bool) { r, ok := s.Next() for unicode.IsSpace(r) && ok { diff --git a/postgresql/database.go b/postgresql/database.go index 401dd31b6ab448a053728bf2b48fa3dddd8dbf5a..f4d51bc185e1a414a438cc3a6d7640e1a46344e7 100644 --- a/postgresql/database.go +++ b/postgresql/database.go @@ -30,34 +30,30 @@ import ( "time" "github.com/jmoiron/sqlx" - _ "github.com/lib/pq" // PostgreSQL driver. - "upper.io/cache" + _ "github.com/lib/pq" // Go PostgreSQL driver. "upper.io/db" "upper.io/db/util/schema" "upper.io/db/util/sqlgen" "upper.io/db/util/sqlutil" -) - -const ( - // Adapter is the public name of the adapter. - Adapter = `postgresql` + "upper.io/db/util/sqlutil/tx" ) var ( - // Query template - template *sqlgen.Template - - // Query statement placeholder sqlPlaceholder = sqlgen.RawValue(`?`) ) type source struct { connURL db.ConnectionURL session *sqlx.DB - tx *tx + tx *sqltx.Tx schema *schema.DatabaseSchema } +type tx struct { + *sqltx.Tx + *source +} + type columnSchemaT struct { Name string `db:"column_name"` DataType string `db:"data_type"` @@ -77,12 +73,12 @@ func debugLog(query string, args []interface{}, err error, start int64, end int6 } } -// Returns the underlying *sqlx.DB instance. +// Driver returns the underlying *sqlx.DB instance. func (s *source) Driver() interface{} { return s.session } -// Attempts to connect to a database using the stored settings. +// Open attempts to connect to the PostgreSQL server using the stored settings. func (s *source) Open() error { var err error @@ -90,8 +86,6 @@ func (s *source) Open() error { // condition checks for that type and provides backwards compatibility. if settings, ok := s.connURL.(db.Settings); ok { - // User is providing a db.Settings struct, let's translate it into a - // ConnectionURL{}. conn := ConnectionURL{ User: settings.User, Password: settings.Password, @@ -102,7 +96,6 @@ func (s *source) Open() error { }, } - // Replace original s.connURL s.connURL = conn } @@ -119,6 +112,7 @@ func (s *source) Open() error { return nil } +// Clone returns a cloned db.Database session. func (s *source) Clone() (db.Database, error) { return s.clone() } @@ -134,13 +128,13 @@ func (s *source) clone() (*source, error) { return src, nil } -// Ping verifies a connection to the database is still alive, -// establishing a connection if necessary. +// Ping checks whether a connection to the database is still alive by pinging +// it, establishing a connection if necessary. func (s *source) Ping() error { return s.session.Ping() } -// Closes the current database session. +// Close terminates the current database session. func (s *source) Close() error { if s.session != nil { return s.session.Close() @@ -148,7 +142,7 @@ func (s *source) Close() error { return nil } -// Returns a collection instance by name. +// Collection returns a table by name. func (s *source) Collection(names ...string) (db.Collection, error) { var err error @@ -157,7 +151,7 @@ func (s *source) Collection(names ...string) (db.Collection, error) { } if s.tx != nil { - if s.tx.done { + if s.tx.Done() { return nil, sql.ErrTxDone } } @@ -188,8 +182,7 @@ func (s *source) Collection(names ...string) (db.Collection, error) { return col, nil } -// Collections() Returns a list of non-system tables/collections contained -// within the currently active database. +// Collections returns a list of non-system tables within the database. func (s *source) Collections() (collections []string, err error) { tablesInSchema := len(s.schema.Tables) @@ -220,7 +213,7 @@ func (s *source) Collections() (collections []string, err error) { // Executing statement. var rows *sqlx.Rows - if rows, err = s.doQuery(stmt); err != nil { + if rows, err = s.Query(stmt); err != nil { return nil, err } @@ -246,7 +239,7 @@ func (s *source) Collections() (collections []string, err error) { return collections, nil } -// Changes the active database. +// Use changes the active database. func (s *source) Use(database string) (err error) { var conn ConnectionURL @@ -261,26 +254,28 @@ func (s *source) Use(database string) (err error) { return s.Open() } -// Drops the currently active database. +// Drop removes all tables within the current database. func (s *source) Drop() error { - _, err := s.doQuery(sqlgen.Statement{ + _, err := s.Query(sqlgen.Statement{ Type: sqlgen.DropDatabase, Database: sqlgen.DatabaseWithName(s.schema.Name), }) return err } -// Stores database settings. +// Setup stores database settings. func (s *source) Setup(connURL db.ConnectionURL) error { s.connURL = connURL return s.Open() } -// Returns the string name of the database. +// Name returns the name of the database. func (s *source) Name() string { return s.schema.Name } +// Transaction starts a transaction block and returns a db.Tx struct that can +// be used to issue transactional queries. func (s *source) Transaction() (db.Tx, error) { var err error var clone *source @@ -294,14 +289,12 @@ func (s *source) Transaction() (db.Tx, error) { return nil, err } - tx := &tx{source: clone, sqlTx: sqlTx} - - clone.tx = tx + clone.tx = sqltx.New(sqlTx) - return tx, nil + return tx{Tx: clone.tx, source: clone}, nil } -func (s *source) doExec(stmt sqlgen.Statement, args ...interface{}) (sql.Result, error) { +func (s *source) Exec(stmt sqlgen.Statement, args ...interface{}) (sql.Result, error) { var query string var res sql.Result var err error @@ -326,7 +319,7 @@ func (s *source) doExec(stmt sqlgen.Statement, args ...interface{}) (sql.Result, } if s.tx != nil { - res, err = s.tx.sqlTx.Exec(query, args...) + res, err = s.tx.Exec(query, args...) } else { res, err = s.session.Exec(query, args...) } @@ -334,7 +327,7 @@ func (s *source) doExec(stmt sqlgen.Statement, args ...interface{}) (sql.Result, return res, err } -func (s *source) doQuery(stmt sqlgen.Statement, args ...interface{}) (*sqlx.Rows, error) { +func (s *source) Query(stmt sqlgen.Statement, args ...interface{}) (*sqlx.Rows, error) { var rows *sqlx.Rows var query string var err error @@ -359,7 +352,7 @@ func (s *source) doQuery(stmt sqlgen.Statement, args ...interface{}) (*sqlx.Rows } if s.tx != nil { - rows, err = s.tx.sqlTx.Queryx(query, args...) + rows, err = s.tx.Queryx(query, args...) } else { rows, err = s.session.Queryx(query, args...) } @@ -367,7 +360,7 @@ func (s *source) doQuery(stmt sqlgen.Statement, args ...interface{}) (*sqlx.Rows return rows, err } -func (s *source) doQueryRow(stmt sqlgen.Statement, args ...interface{}) (*sqlx.Row, error) { +func (s *source) QueryRow(stmt sqlgen.Statement, args ...interface{}) (*sqlx.Row, error) { var query string var row *sqlx.Row var err error @@ -392,7 +385,7 @@ func (s *source) doQueryRow(stmt sqlgen.Statement, args ...interface{}) (*sqlx.R } if s.tx != nil { - row = s.tx.sqlTx.QueryRowx(query, args...) + row = s.tx.QueryRowx(query, args...) } else { row = s.session.QueryRowx(query, args...) } @@ -415,7 +408,7 @@ func (s *source) populateSchema() (err error) { var row *sqlx.Row - if row, err = s.doQueryRow(stmt); err != nil { + if row, err = s.QueryRow(stmt); err != nil { return err } @@ -470,7 +463,7 @@ func (s *source) tableExists(names ...string) error { ), } - if rows, err = s.doQuery(stmt, s.schema.Name, names[i]); err != nil { + if rows, err = s.Query(stmt, s.schema.Name, names[i]); err != nil { return db.ErrCollectionDoesNotExist } @@ -517,7 +510,7 @@ func (s *source) tableColumns(tableName string) ([]string, error) { var rows *sqlx.Rows var err error - if rows, err = s.doQuery(stmt, s.schema.Name, tableName); err != nil { + if rows, err = s.Query(stmt, s.schema.Name, tableName); err != nil { return nil, err } @@ -572,7 +565,7 @@ func (s *source) getPrimaryKey(tableName string) ([]string, error) { var rows *sqlx.Rows var err error - if rows, err = s.doQuery(stmt); err != nil { + if rows, err = s.Query(stmt); err != nil { return nil, err } @@ -588,39 +581,3 @@ func (s *source) getPrimaryKey(tableName string) ([]string, error) { return tableSchema.PrimaryKey, nil } - -func init() { - template = &sqlgen.Template{ - pgsqlColumnSeparator, - pgsqlIdentifierSeparator, - pgsqlIdentifierQuote, - pgsqlValueSeparator, - pgsqlValueQuote, - pgsqlAndKeyword, - pgsqlOrKeyword, - pgsqlNotKeyword, - pgsqlDescKeyword, - pgsqlAscKeyword, - pgsqlDefaultOperator, - pgsqlClauseGroup, - pgsqlClauseOperator, - pgsqlColumnValue, - pgsqlTableAliasLayout, - pgsqlColumnAliasLayout, - pgsqlSortByColumnLayout, - pgsqlWhereLayout, - pgsqlOrderByLayout, - pgsqlInsertLayout, - pgsqlSelectLayout, - pgsqlUpdateLayout, - pgsqlDeleteLayout, - pgsqlTruncateLayout, - pgsqlDropDatabaseLayout, - pgsqlDropTableLayout, - pgsqlSelectCountLayout, - pgsqlGroupByLayout, - cache.NewCache(), - } - - db.Register(Adapter, &source{}) -} diff --git a/postgresql/postgresql.go b/postgresql/postgresql.go new file mode 100644 index 0000000000000000000000000000000000000000..8aa0d45d0ef900a76c2545fcba5140c55b8863cb --- /dev/null +++ b/postgresql/postgresql.go @@ -0,0 +1,74 @@ +// Copyright (c) 2012-2015 José Carlos Nieto, https://menteslibres.net/xiam +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +package postgresql + +import ( + "upper.io/cache" + "upper.io/db" + "upper.io/db/util/sqlgen" +) + +// Adapter is the public name of the adapter. +const Adapter = `postgresql` + +var ( + _ = db.Database(&source{}) + _ = db.Collection(&table{}) +) + +var template *sqlgen.Template + +func init() { + template = &sqlgen.Template{ + ColumnSeparator: pgsqlColumnSeparator, + IdentifierSeparator: pgsqlIdentifierSeparator, + IdentifierQuote: pgsqlIdentifierQuote, + ValueSeparator: pgsqlValueSeparator, + ValueQuote: pgsqlValueQuote, + AndKeyword: pgsqlAndKeyword, + OrKeyword: pgsqlOrKeyword, + NotKeyword: pgsqlNotKeyword, + DescKeyword: pgsqlDescKeyword, + AscKeyword: pgsqlAscKeyword, + DefaultOperator: pgsqlDefaultOperator, + ClauseGroup: pgsqlClauseGroup, + ClauseOperator: pgsqlClauseOperator, + ColumnValue: pgsqlColumnValue, + TableAliasLayout: pgsqlTableAliasLayout, + ColumnAliasLayout: pgsqlColumnAliasLayout, + SortByColumnLayout: pgsqlSortByColumnLayout, + WhereLayout: pgsqlWhereLayout, + OrderByLayout: pgsqlOrderByLayout, + InsertLayout: pgsqlInsertLayout, + SelectLayout: pgsqlSelectLayout, + UpdateLayout: pgsqlUpdateLayout, + DeleteLayout: pgsqlDeleteLayout, + TruncateLayout: pgsqlTruncateLayout, + DropDatabaseLayout: pgsqlDropDatabaseLayout, + DropTableLayout: pgsqlDropTableLayout, + CountLayout: pgsqlSelectCountLayout, + GroupByLayout: pgsqlGroupByLayout, + Cache: cache.NewCache(), + } + + db.Register(Adapter, &source{}) +} diff --git a/postgresql/layout.go b/postgresql/template.go similarity index 100% rename from postgresql/layout.go rename to postgresql/template.go diff --git a/postgresql/result.go b/util/sqlutil/result/result.go similarity index 83% rename from postgresql/result.go rename to util/sqlutil/result/result.go index f289f229f15bdf9a51b344d5d2e4118fb29ba30d..9616c9bb9d4b5ab214440883476445c6d885dec3 100644 --- a/postgresql/result.go +++ b/util/sqlutil/result/result.go @@ -19,7 +19,7 @@ // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -package postgresql +package result import ( "fmt" @@ -31,12 +31,16 @@ import ( "upper.io/db/util/sqlutil" ) +var ( + sqlPlaceholder = sqlgen.RawValue(`?`) +) + type counter struct { Total uint64 `db:"_t"` } -type result struct { - table *table +type Result struct { + table DataProvider cursor *sqlx.Rows // This is the main query cursor. It starts as a nil value. limit sqlgen.Limit offset sqlgen.Offset @@ -47,12 +51,22 @@ type result struct { arguments []interface{} } +// NewResult creates and results a new result set on the given table, this set +// is limited by the given sqlgen.Where conditions. +func NewResult(p DataProvider, where sqlgen.Where, arguments []interface{}) *Result { + return &Result{ + table: p, + where: where, + arguments: arguments, + } +} + // Executes a SELECT statement that can feed Next(), All() or One(). -func (r *result) setCursor() error { +func (r *Result) setCursor() error { var err error // We need a cursor, if the cursor does not exists yet then we create one. if r.cursor == nil { - r.cursor, err = r.table.source.doQuery(sqlgen.Statement{ + r.cursor, err = r.table.Query(sqlgen.Statement{ Type: sqlgen.Select, Table: sqlgen.TableWithName(r.table.Name()), Columns: &r.columns, @@ -67,27 +81,27 @@ func (r *result) setCursor() error { } // Sets conditions for reducing the working set. -func (r *result) Where(terms ...interface{}) db.Result { +func (r *Result) Where(terms ...interface{}) db.Result { r.where, r.arguments = sqlutil.ToWhereWithArguments(terms) return r } // Determines the maximum limit of results to be returned. -func (r *result) Limit(n uint) db.Result { +func (r *Result) Limit(n uint) db.Result { r.limit = sqlgen.Limit(n) return r } // Determines how many documents will be skipped before starting to grab // results. -func (r *result) Skip(n uint) db.Result { +func (r *Result) Skip(n uint) db.Result { r.offset = sqlgen.Offset(n) return r } // Used to group results that have the same value in the same column or // columns. -func (r *result) Group(fields ...interface{}) db.Result { +func (r *Result) Group(fields ...interface{}) db.Result { var columns []sqlgen.Fragment for i := range fields { @@ -107,7 +121,7 @@ func (r *result) Group(fields ...interface{}) db.Result { // Determines sorting of results according to the provided names. Fields may be // prefixed by - (minus) which means descending order, ascending order would be // used otherwise. -func (r *result) Sort(fields ...interface{}) db.Result { +func (r *Result) Sort(fields ...interface{}) db.Result { var sortColumns sqlgen.SortColumns @@ -144,7 +158,7 @@ func (r *result) Sort(fields ...interface{}) db.Result { } // Retrieves only the given fields. -func (r *result) Select(fields ...interface{}) db.Result { +func (r *Result) Select(fields ...interface{}) db.Result { r.columns = sqlgen.Columns{} @@ -176,7 +190,7 @@ func (r *result) Select(fields ...interface{}) db.Result { } // Dumps all results into a pointer to an slice of structs or maps. -func (r *result) All(dst interface{}) error { +func (r *Result) All(dst interface{}) error { var err error if r.cursor != nil { @@ -199,7 +213,7 @@ func (r *result) All(dst interface{}) error { } // Fetches only one result from the resultset. -func (r *result) One(dst interface{}) error { +func (r *Result) One(dst interface{}) error { var err error if r.cursor != nil { @@ -214,7 +228,7 @@ func (r *result) One(dst interface{}) error { } // Fetches the next result from the resultset. -func (r *result) Next(dst interface{}) (err error) { +func (r *Result) Next(dst interface{}) (err error) { if err = r.setCursor(); err != nil { r.Close() @@ -230,10 +244,10 @@ func (r *result) Next(dst interface{}) (err error) { } // Removes the matching items from the collection. -func (r *result) Remove() error { +func (r *Result) Remove() error { var err error - _, err = r.table.source.doExec(sqlgen.Statement{ + _, err = r.table.Exec(sqlgen.Statement{ Type: sqlgen.Delete, Table: sqlgen.TableWithName(r.table.Name()), Where: &r.where, @@ -245,7 +259,7 @@ func (r *result) Remove() error { // Updates matching items from the collection with values of the given map or // struct. -func (r *result) Update(values interface{}) error { +func (r *Result) Update(values interface{}) error { ff, vv, err := r.table.FieldValues(values) if err != nil { @@ -260,7 +274,7 @@ func (r *result) Update(values interface{}) error { vv = append(vv, r.arguments...) - _, err = r.table.source.doExec(sqlgen.Statement{ + _, err = r.table.Exec(sqlgen.Statement{ Type: sqlgen.Update, Table: sqlgen.TableWithName(r.table.Name()), ColumnValues: cvs, @@ -271,7 +285,7 @@ func (r *result) Update(values interface{}) error { } // Closes the result set. -func (r *result) Close() (err error) { +func (r *Result) Close() (err error) { if r.cursor != nil { err = r.cursor.Close() r.cursor = nil @@ -280,10 +294,10 @@ func (r *result) Close() (err error) { } // Counts the elements within the main conditions of the set. -func (r *result) Count() (uint64, error) { +func (r *Result) Count() (uint64, error) { var count counter - row, err := r.table.source.doQueryRow(sqlgen.Statement{ + row, err := r.table.QueryRow(sqlgen.Statement{ Type: sqlgen.Count, Table: sqlgen.TableWithName(r.table.Name()), Where: &r.where, diff --git a/util/sqlutil/result/table.go b/util/sqlutil/result/table.go new file mode 100644 index 0000000000000000000000000000000000000000..57ec42ac1bdf8abe90ea0667e7b8177089820c8d --- /dev/null +++ b/util/sqlutil/result/table.go @@ -0,0 +1,15 @@ +package result + +import ( + "database/sql" + "github.com/jmoiron/sqlx" + "upper.io/db/util/sqlgen" +) + +type DataProvider interface { + Name() string + Query(sqlgen.Statement, ...interface{}) (*sqlx.Rows, error) + QueryRow(sqlgen.Statement, ...interface{}) (*sqlx.Row, error) + Exec(sqlgen.Statement, ...interface{}) (sql.Result, error) + FieldValues(interface{}) ([]string, []interface{}, error) +} diff --git a/postgresql/tx.go b/util/sqlutil/tx/tx.go similarity index 84% rename from postgresql/tx.go rename to util/sqlutil/tx/tx.go index 70b979d74e3763a57941e60e13e261083236778a..533c54058f9f855dbc3004e8fad03f5f3022e0bb 100644 --- a/postgresql/tx.go +++ b/util/sqlutil/tx/tx.go @@ -19,26 +19,28 @@ // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -package postgresql +package sqltx import ( "github.com/jmoiron/sqlx" ) -type tx struct { - *source - sqlTx *sqlx.Tx - done bool +type Tx struct { + *sqlx.Tx + done bool } -func (t *tx) Commit() (err error) { - err = t.sqlTx.Commit() - if err == nil { +func New(tx *sqlx.Tx) *Tx { + return &Tx{Tx: tx} +} + +func (t *Tx) Done() bool { + return t.done +} + +func (t *Tx) Commit() (err error) { + if err = t.Tx.Commit(); err == nil { t.done = true } return err } - -func (t *tx) Rollback() error { - return t.sqlTx.Rollback() -}