mirror of
				https://github.com/go-gitea/gitea.git
				synced 2025-10-26 12:27:06 +00:00 
			
		
		
		
	fix forgot removed records when deleting user (#5429)
* fix forgot removed records when deleting user * fix migration * fix rewritekey lock on sqlite * remove unused codes
This commit is contained in:
		 Lunny Xiao
					Lunny Xiao
				
			
				
					committed by
					
						 techknowlogick
						techknowlogick
					
				
			
			
				
	
			
			
			 techknowlogick
						techknowlogick
					
				
			
						parent
						
							e726e4b828
						
					
				
				
					commit
					fe55ab2a68
				
			
							
								
								
									
										6
									
								
								Gopkg.lock
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										6
									
								
								Gopkg.lock
									
									
									
										generated
									
									
									
								
							| @@ -390,12 +390,12 @@ | |||||||
|   revision = "d523deb1b23d913de5bdada721a6071e71283618" |   revision = "d523deb1b23d913de5bdada721a6071e71283618" | ||||||
|  |  | ||||||
| [[projects]] | [[projects]] | ||||||
|   digest = "1:1397763fd29d5667bcfbacde8a37542ee145416b3acb7e1b149c98fef2567930" |   digest = "1:06d21295033f211588d0ad7ff391cc1b27e72b60cb6d4b7db0d70cffae4cf228" | ||||||
|   name = "github.com/go-xorm/builder" |   name = "github.com/go-xorm/builder" | ||||||
|   packages = ["."] |   packages = ["."] | ||||||
|   pruneopts = "NUT" |   pruneopts = "NUT" | ||||||
|   revision = "dc8bf48f58fab2b4da338ffd25191905fd741b8f" |   revision = "03eb88feccce3e477c318ce7f6f1b386544ab20b" | ||||||
|   version = "v0.3.0" |   version = "v0.3.3" | ||||||
|  |  | ||||||
| [[projects]] | [[projects]] | ||||||
|   digest = "1:c910feae32bcc3cbf068c7263424d9f198da931c0cad909179621835e6f87cb8" |   digest = "1:c910feae32bcc3cbf068c7263424d9f198da931c0cad909179621835e6f87cb8" | ||||||
|   | |||||||
| @@ -40,6 +40,10 @@ ignored = ["google.golang.org/appengine*"] | |||||||
|   name = "github.com/go-xorm/xorm" |   name = "github.com/go-xorm/xorm" | ||||||
|   revision = "401f4ee8ff8cbc40a4754cb12192fbe4f02f3979" |   revision = "401f4ee8ff8cbc40a4754cb12192fbe4f02f3979" | ||||||
|  |  | ||||||
|  | [[override]] | ||||||
|  |   name = "github.com/go-xorm/builder" | ||||||
|  |   version = "0.3.3" | ||||||
|  |  | ||||||
| [[override]] | [[override]] | ||||||
|   name = "github.com/go-sql-driver/mysql" |   name = "github.com/go-sql-driver/mysql" | ||||||
|   revision = "d523deb1b23d913de5bdada721a6071e71283618" |   revision = "d523deb1b23d913de5bdada721a6071e71283618" | ||||||
|   | |||||||
| @@ -202,6 +202,8 @@ var migrations = []Migration{ | |||||||
| 	NewMigration("add must_change_password column for users table", addMustChangePassword), | 	NewMigration("add must_change_password column for users table", addMustChangePassword), | ||||||
| 	// v74 -> v75 | 	// v74 -> v75 | ||||||
| 	NewMigration("add approval whitelists to protected branches", addApprovalWhitelistsToProtectedBranches), | 	NewMigration("add approval whitelists to protected branches", addApprovalWhitelistsToProtectedBranches), | ||||||
|  | 	// v75 -> v76 | ||||||
|  | 	NewMigration("clear nonused data which not deleted when user was deleted", clearNonusedData), | ||||||
| } | } | ||||||
|  |  | ||||||
| // Migrate database to current version | // Migrate database to current version | ||||||
|   | |||||||
							
								
								
									
										33
									
								
								models/migrations/v75.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								models/migrations/v75.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,33 @@ | |||||||
|  | // Copyright 2018 The Gitea Authors. All rights reserved. | ||||||
|  | // Use of this source code is governed by a MIT-style | ||||||
|  | // license that can be found in the LICENSE file. | ||||||
|  |  | ||||||
|  | package migrations | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"github.com/go-xorm/builder" | ||||||
|  | 	"github.com/go-xorm/xorm" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | func clearNonusedData(x *xorm.Engine) error { | ||||||
|  | 	condDelete := func(colName string) builder.Cond { | ||||||
|  | 		return builder.NotIn(colName, builder.Select("id").From("user")) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if _, err := x.Exec(builder.Delete(condDelete("uid")).From("team_user")); err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if _, err := x.Exec(builder.Delete(condDelete("user_id")).From("collaboration")); err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if _, err := x.Exec(builder.Delete(condDelete("user_id")).From("stop_watch")); err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if _, err := x.Exec(builder.Delete(condDelete("owner_id")).From("gpg_key")); err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
| @@ -549,6 +549,7 @@ func DeletePublicKey(doer *User, id int64) (err error) { | |||||||
| 	if err = sess.Commit(); err != nil { | 	if err = sess.Commit(); err != nil { | ||||||
| 		return err | 		return err | ||||||
| 	} | 	} | ||||||
|  | 	sess.Close() | ||||||
|  |  | ||||||
| 	return RewriteAllPublicKeys() | 	return RewriteAllPublicKeys() | ||||||
| } | } | ||||||
| @@ -557,6 +558,10 @@ func DeletePublicKey(doer *User, id int64) (err error) { | |||||||
| // Note: x.Iterate does not get latest data after insert/delete, so we have to call this function | // Note: x.Iterate does not get latest data after insert/delete, so we have to call this function | ||||||
| // outside any session scope independently. | // outside any session scope independently. | ||||||
| func RewriteAllPublicKeys() error { | func RewriteAllPublicKeys() error { | ||||||
|  | 	return rewriteAllPublicKeys(x) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func rewriteAllPublicKeys(e Engine) error { | ||||||
| 	//Don't rewrite key if internal server | 	//Don't rewrite key if internal server | ||||||
| 	if setting.SSH.StartBuiltinServer || !setting.SSH.CreateAuthorizedKeysFile { | 	if setting.SSH.StartBuiltinServer || !setting.SSH.CreateAuthorizedKeysFile { | ||||||
| 		return nil | 		return nil | ||||||
| @@ -583,7 +588,7 @@ func RewriteAllPublicKeys() error { | |||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	err = x.Iterate(new(PublicKey), func(idx int, bean interface{}) (err error) { | 	err = e.Iterate(new(PublicKey), func(idx int, bean interface{}) (err error) { | ||||||
| 		_, err = t.WriteString((bean.(*PublicKey)).AuthorizedString()) | 		_, err = t.WriteString((bean.(*PublicKey)).AuthorizedString()) | ||||||
| 		return err | 		return err | ||||||
| 	}) | 	}) | ||||||
|   | |||||||
| @@ -1015,25 +1015,26 @@ func deleteUser(e *xorm.Session, u *User) error { | |||||||
| 		&EmailAddress{UID: u.ID}, | 		&EmailAddress{UID: u.ID}, | ||||||
| 		&UserOpenID{UID: u.ID}, | 		&UserOpenID{UID: u.ID}, | ||||||
| 		&Reaction{UserID: u.ID}, | 		&Reaction{UserID: u.ID}, | ||||||
|  | 		&TeamUser{UID: u.ID}, | ||||||
|  | 		&Collaboration{UserID: u.ID}, | ||||||
|  | 		&Stopwatch{UserID: u.ID}, | ||||||
| 	); err != nil { | 	); err != nil { | ||||||
| 		return fmt.Errorf("deleteBeans: %v", err) | 		return fmt.Errorf("deleteBeans: %v", err) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	// ***** START: PublicKey ***** | 	// ***** START: PublicKey ***** | ||||||
| 	keys := make([]*PublicKey, 0, 10) | 	if _, err = e.Delete(&PublicKey{OwnerID: u.ID}); err != nil { | ||||||
| 	if err = e.Find(&keys, &PublicKey{OwnerID: u.ID}); err != nil { |  | ||||||
| 		return fmt.Errorf("get all public keys: %v", err) |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	keyIDs := make([]int64, len(keys)) |  | ||||||
| 	for i := range keys { |  | ||||||
| 		keyIDs[i] = keys[i].ID |  | ||||||
| 	} |  | ||||||
| 	if err = deletePublicKeys(e, keyIDs...); err != nil { |  | ||||||
| 		return fmt.Errorf("deletePublicKeys: %v", err) | 		return fmt.Errorf("deletePublicKeys: %v", err) | ||||||
| 	} | 	} | ||||||
|  | 	rewriteAllPublicKeys(e) | ||||||
| 	// ***** END: PublicKey ***** | 	// ***** END: PublicKey ***** | ||||||
|  |  | ||||||
|  | 	// ***** START: GPGPublicKey ***** | ||||||
|  | 	if _, err = e.Delete(&GPGKey{OwnerID: u.ID}); err != nil { | ||||||
|  | 		return fmt.Errorf("deleteGPGKeys: %v", err) | ||||||
|  | 	} | ||||||
|  | 	// ***** END: GPGPublicKey ***** | ||||||
|  |  | ||||||
| 	// Clear assignee. | 	// Clear assignee. | ||||||
| 	if err = clearAssigneeByUserID(e, u.ID); err != nil { | 	if err = clearAssigneeByUserID(e, u.ID); err != nil { | ||||||
| 		return fmt.Errorf("clear assignee: %v", err) | 		return fmt.Errorf("clear assignee: %v", err) | ||||||
| @@ -1084,11 +1085,7 @@ func DeleteUser(u *User) (err error) { | |||||||
| 		return err | 		return err | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if err = sess.Commit(); err != nil { | 	return sess.Commit() | ||||||
| 		return err |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	return RewriteAllPublicKeys() |  | ||||||
| } | } | ||||||
|  |  | ||||||
| // DeleteInactivateUsers deletes all inactivate users and email addresses. | // DeleteInactivateUsers deletes all inactivate users and email addresses. | ||||||
|   | |||||||
							
								
								
									
										289
									
								
								vendor/github.com/go-xorm/builder/builder.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										289
									
								
								vendor/github.com/go-xorm/builder/builder.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -5,7 +5,9 @@ | |||||||
| package builder | package builder | ||||||
|  |  | ||||||
| import ( | import ( | ||||||
|  | 	sql2 "database/sql" | ||||||
| 	"fmt" | 	"fmt" | ||||||
|  | 	"sort" | ||||||
| ) | ) | ||||||
|  |  | ||||||
| type optype byte | type optype byte | ||||||
| @@ -16,6 +18,15 @@ const ( | |||||||
| 	insertType               // insert | 	insertType               // insert | ||||||
| 	updateType               // update | 	updateType               // update | ||||||
| 	deleteType               // delete | 	deleteType               // delete | ||||||
|  | 	unionType                // union | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | const ( | ||||||
|  | 	POSTGRES = "postgres" | ||||||
|  | 	SQLITE   = "sqlite3" | ||||||
|  | 	MYSQL    = "mysql" | ||||||
|  | 	MSSQL    = "mssql" | ||||||
|  | 	ORACLE   = "oracle" | ||||||
| ) | ) | ||||||
|  |  | ||||||
| type join struct { | type join struct { | ||||||
| @@ -24,68 +35,115 @@ type join struct { | |||||||
| 	joinCond  Cond | 	joinCond  Cond | ||||||
| } | } | ||||||
|  |  | ||||||
|  | type union struct { | ||||||
|  | 	unionType string | ||||||
|  | 	builder   *Builder | ||||||
|  | } | ||||||
|  |  | ||||||
|  | type limit struct { | ||||||
|  | 	limitN int | ||||||
|  | 	offset int | ||||||
|  | } | ||||||
|  |  | ||||||
| // Builder describes a SQL statement | // Builder describes a SQL statement | ||||||
| type Builder struct { | type Builder struct { | ||||||
| 	optype | 	optype | ||||||
| 	tableName string | 	dialect    string | ||||||
|  | 	isNested   bool | ||||||
|  | 	into       string | ||||||
|  | 	from       string | ||||||
|  | 	subQuery   *Builder | ||||||
| 	cond       Cond | 	cond       Cond | ||||||
| 	selects    []string | 	selects    []string | ||||||
| 	joins      []join | 	joins      []join | ||||||
| 	inserts   Eq | 	unions     []union | ||||||
|  | 	limitation *limit | ||||||
|  | 	insertCols []string | ||||||
|  | 	insertVals []interface{} | ||||||
| 	updates    []Eq | 	updates    []Eq | ||||||
| 	orderBy    string | 	orderBy    string | ||||||
| 	groupBy    string | 	groupBy    string | ||||||
| 	having     string | 	having     string | ||||||
| } | } | ||||||
|  |  | ||||||
| // Select creates a select Builder | // Dialect sets the db dialect of Builder. | ||||||
| func Select(cols ...string) *Builder { | func Dialect(dialect string) *Builder { | ||||||
| 	builder := &Builder{cond: NewCond()} | 	builder := &Builder{cond: NewCond(), dialect: dialect} | ||||||
| 	return builder.Select(cols...) | 	return builder | ||||||
| } | } | ||||||
|  |  | ||||||
| // Insert creates an insert Builder | // MySQL is shortcut of Dialect(MySQL) | ||||||
| func Insert(eq Eq) *Builder { | func MySQL() *Builder { | ||||||
| 	builder := &Builder{cond: NewCond()} | 	return Dialect(MYSQL) | ||||||
| 	return builder.Insert(eq) |  | ||||||
| } | } | ||||||
|  |  | ||||||
| // Update creates an update Builder | // MsSQL is shortcut of Dialect(MsSQL) | ||||||
| func Update(updates ...Eq) *Builder { | func MsSQL() *Builder { | ||||||
| 	builder := &Builder{cond: NewCond()} | 	return Dialect(MSSQL) | ||||||
| 	return builder.Update(updates...) |  | ||||||
| } | } | ||||||
|  |  | ||||||
| // Delete creates a delete Builder | // Oracle is shortcut of Dialect(Oracle) | ||||||
| func Delete(conds ...Cond) *Builder { | func Oracle() *Builder { | ||||||
| 	builder := &Builder{cond: NewCond()} | 	return Dialect(ORACLE) | ||||||
| 	return builder.Delete(conds...) | } | ||||||
|  |  | ||||||
|  | // Postgres is shortcut of Dialect(Postgres) | ||||||
|  | func Postgres() *Builder { | ||||||
|  | 	return Dialect(POSTGRES) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // SQLite is shortcut of Dialect(SQLITE) | ||||||
|  | func SQLite() *Builder { | ||||||
|  | 	return Dialect(SQLITE) | ||||||
| } | } | ||||||
|  |  | ||||||
| // Where sets where SQL | // Where sets where SQL | ||||||
| func (b *Builder) Where(cond Cond) *Builder { | func (b *Builder) Where(cond Cond) *Builder { | ||||||
|  | 	if b.cond.IsValid() { | ||||||
| 		b.cond = b.cond.And(cond) | 		b.cond = b.cond.And(cond) | ||||||
|  | 	} else { | ||||||
|  | 		b.cond = cond | ||||||
|  | 	} | ||||||
| 	return b | 	return b | ||||||
| } | } | ||||||
|  |  | ||||||
| // From sets the table name | // From sets from subject(can be a table name in string or a builder pointer) and its alias | ||||||
| func (b *Builder) From(tableName string) *Builder { | func (b *Builder) From(subject interface{}, alias ...string) *Builder { | ||||||
| 	b.tableName = tableName | 	switch subject.(type) { | ||||||
|  | 	case *Builder: | ||||||
|  | 		b.subQuery = subject.(*Builder) | ||||||
|  |  | ||||||
|  | 		if len(alias) > 0 { | ||||||
|  | 			b.from = alias[0] | ||||||
|  | 		} else { | ||||||
|  | 			b.isNested = true | ||||||
|  | 		} | ||||||
|  | 	case string: | ||||||
|  | 		b.from = subject.(string) | ||||||
|  |  | ||||||
|  | 		if len(alias) > 0 { | ||||||
|  | 			b.from = b.from + " " + alias[0] | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	return b | 	return b | ||||||
| } | } | ||||||
|  |  | ||||||
| // TableName returns the table name | // TableName returns the table name | ||||||
| func (b *Builder) TableName() string { | func (b *Builder) TableName() string { | ||||||
| 	return b.tableName | 	if b.optype == insertType { | ||||||
|  | 		return b.into | ||||||
|  | 	} | ||||||
|  | 	return b.from | ||||||
| } | } | ||||||
|  |  | ||||||
| // Into sets insert table name | // Into sets insert table name | ||||||
| func (b *Builder) Into(tableName string) *Builder { | func (b *Builder) Into(tableName string) *Builder { | ||||||
| 	b.tableName = tableName | 	b.into = tableName | ||||||
| 	return b | 	return b | ||||||
| } | } | ||||||
|  |  | ||||||
| // Join sets join table and contions | // Join sets join table and conditions | ||||||
| func (b *Builder) Join(joinType, joinTable string, joinCond interface{}) *Builder { | func (b *Builder) Join(joinType, joinTable string, joinCond interface{}) *Builder { | ||||||
| 	switch joinCond.(type) { | 	switch joinCond.(type) { | ||||||
| 	case Cond: | 	case Cond: | ||||||
| @@ -97,6 +155,50 @@ func (b *Builder) Join(joinType, joinTable string, joinCond interface{}) *Builde | |||||||
| 	return b | 	return b | ||||||
| } | } | ||||||
|  |  | ||||||
|  | // Union sets union conditions | ||||||
|  | func (b *Builder) Union(unionTp string, unionCond *Builder) *Builder { | ||||||
|  | 	var builder *Builder | ||||||
|  | 	if b.optype != unionType { | ||||||
|  | 		builder = &Builder{cond: NewCond()} | ||||||
|  | 		builder.optype = unionType | ||||||
|  | 		builder.dialect = b.dialect | ||||||
|  | 		builder.selects = b.selects | ||||||
|  |  | ||||||
|  | 		currentUnions := b.unions | ||||||
|  | 		// erase sub unions (actually append to new Builder.unions) | ||||||
|  | 		b.unions = nil | ||||||
|  |  | ||||||
|  | 		for e := range currentUnions { | ||||||
|  | 			currentUnions[e].builder.dialect = b.dialect | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		builder.unions = append(append(builder.unions, union{"", b}), currentUnions...) | ||||||
|  | 	} else { | ||||||
|  | 		builder = b | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if unionCond != nil { | ||||||
|  | 		if unionCond.dialect == "" && builder.dialect != "" { | ||||||
|  | 			unionCond.dialect = builder.dialect | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		builder.unions = append(builder.unions, union{unionTp, unionCond}) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return builder | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Limit sets limitN condition | ||||||
|  | func (b *Builder) Limit(limitN int, offset ...int) *Builder { | ||||||
|  | 	b.limitation = &limit{limitN: limitN} | ||||||
|  |  | ||||||
|  | 	if len(offset) > 0 { | ||||||
|  | 		b.limitation.offset = offset[0] | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return b | ||||||
|  | } | ||||||
|  |  | ||||||
| // InnerJoin sets inner join | // InnerJoin sets inner join | ||||||
| func (b *Builder) InnerJoin(joinTable string, joinCond interface{}) *Builder { | func (b *Builder) InnerJoin(joinTable string, joinCond interface{}) *Builder { | ||||||
| 	return b.Join("INNER", joinTable, joinCond) | 	return b.Join("INNER", joinTable, joinCond) | ||||||
| @@ -125,7 +227,9 @@ func (b *Builder) FullJoin(joinTable string, joinCond interface{}) *Builder { | |||||||
| // Select sets select SQL | // Select sets select SQL | ||||||
| func (b *Builder) Select(cols ...string) *Builder { | func (b *Builder) Select(cols ...string) *Builder { | ||||||
| 	b.selects = cols | 	b.selects = cols | ||||||
|  | 	if b.optype == condType { | ||||||
| 		b.optype = selectType | 		b.optype = selectType | ||||||
|  | 	} | ||||||
| 	return b | 	return b | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -141,16 +245,70 @@ func (b *Builder) Or(cond Cond) *Builder { | |||||||
| 	return b | 	return b | ||||||
| } | } | ||||||
|  |  | ||||||
|  | type insertColsSorter struct { | ||||||
|  | 	cols []string | ||||||
|  | 	vals []interface{} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (s insertColsSorter) Len() int { | ||||||
|  | 	return len(s.cols) | ||||||
|  | } | ||||||
|  | func (s insertColsSorter) Swap(i, j int) { | ||||||
|  | 	s.cols[i], s.cols[j] = s.cols[j], s.cols[i] | ||||||
|  | 	s.vals[i], s.vals[j] = s.vals[j], s.vals[i] | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (s insertColsSorter) Less(i, j int) bool { | ||||||
|  | 	return s.cols[i] < s.cols[j] | ||||||
|  | } | ||||||
|  |  | ||||||
| // Insert sets insert SQL | // Insert sets insert SQL | ||||||
| func (b *Builder) Insert(eq Eq) *Builder { | func (b *Builder) Insert(eq ...interface{}) *Builder { | ||||||
| 	b.inserts = eq | 	if len(eq) > 0 { | ||||||
|  | 		var paramType = -1 | ||||||
|  | 		for _, e := range eq { | ||||||
|  | 			switch t := e.(type) { | ||||||
|  | 			case Eq: | ||||||
|  | 				if paramType == -1 { | ||||||
|  | 					paramType = 0 | ||||||
|  | 				} | ||||||
|  | 				if paramType != 0 { | ||||||
|  | 					break | ||||||
|  | 				} | ||||||
|  | 				for k, v := range t { | ||||||
|  | 					b.insertCols = append(b.insertCols, k) | ||||||
|  | 					b.insertVals = append(b.insertVals, v) | ||||||
|  | 				} | ||||||
|  | 			case string: | ||||||
|  | 				if paramType == -1 { | ||||||
|  | 					paramType = 1 | ||||||
|  | 				} | ||||||
|  | 				if paramType != 1 { | ||||||
|  | 					break | ||||||
|  | 				} | ||||||
|  | 				b.insertCols = append(b.insertCols, t) | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if len(b.insertCols) == len(b.insertVals) { | ||||||
|  | 		sort.Sort(insertColsSorter{ | ||||||
|  | 			cols: b.insertCols, | ||||||
|  | 			vals: b.insertVals, | ||||||
|  | 		}) | ||||||
|  | 	} | ||||||
| 	b.optype = insertType | 	b.optype = insertType | ||||||
| 	return b | 	return b | ||||||
| } | } | ||||||
|  |  | ||||||
| // Update sets update SQL | // Update sets update SQL | ||||||
| func (b *Builder) Update(updates ...Eq) *Builder { | func (b *Builder) Update(updates ...Eq) *Builder { | ||||||
| 	b.updates = updates | 	b.updates = make([]Eq, 0, len(updates)) | ||||||
|  | 	for _, update := range updates { | ||||||
|  | 		if update.IsValid() { | ||||||
|  | 			b.updates = append(b.updates, update) | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
| 	b.optype = updateType | 	b.optype = updateType | ||||||
| 	return b | 	return b | ||||||
| } | } | ||||||
| @@ -165,8 +323,8 @@ func (b *Builder) Delete(conds ...Cond) *Builder { | |||||||
| // WriteTo implements Writer interface | // WriteTo implements Writer interface | ||||||
| func (b *Builder) WriteTo(w Writer) error { | func (b *Builder) WriteTo(w Writer) error { | ||||||
| 	switch b.optype { | 	switch b.optype { | ||||||
| 	case condType: | 	/*case condType: | ||||||
| 		return b.cond.WriteTo(w) | 	return b.cond.WriteTo(w)*/ | ||||||
| 	case selectType: | 	case selectType: | ||||||
| 		return b.selectWriteTo(w) | 		return b.selectWriteTo(w) | ||||||
| 	case insertType: | 	case insertType: | ||||||
| @@ -175,6 +333,8 @@ func (b *Builder) WriteTo(w Writer) error { | |||||||
| 		return b.updateWriteTo(w) | 		return b.updateWriteTo(w) | ||||||
| 	case deleteType: | 	case deleteType: | ||||||
| 		return b.deleteWriteTo(w) | 		return b.deleteWriteTo(w) | ||||||
|  | 	case unionType: | ||||||
|  | 		return b.unionWriteTo(w) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	return ErrNotSupportType | 	return ErrNotSupportType | ||||||
| @@ -187,43 +347,48 @@ func (b *Builder) ToSQL() (string, []interface{}, error) { | |||||||
| 		return "", nil, err | 		return "", nil, err | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	return w.writer.String(), w.args, nil | 	// in case of sql.NamedArg in args | ||||||
|  | 	for e := range w.args { | ||||||
|  | 		if namedArg, ok := w.args[e].(sql2.NamedArg); ok { | ||||||
|  | 			w.args[e] = namedArg.Value | ||||||
|  | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| // ConvertPlaceholder replaces ? to $1, $2 ... or :1, :2 ... according prefix | 	var sql = w.writer.String() | ||||||
| func ConvertPlaceholder(sql, prefix string) (string, error) { | 	var err error | ||||||
| 	buf := StringBuilder{} |  | ||||||
| 	var j, start = 0, 0 |  | ||||||
| 	for i := 0; i < len(sql); i++ { |  | ||||||
| 		if sql[i] == '?' { |  | ||||||
| 			_, err := buf.WriteString(sql[start:i]) |  | ||||||
| 			if err != nil { |  | ||||||
| 				return "", err |  | ||||||
| 			} |  | ||||||
| 			start = i + 1 |  | ||||||
|  |  | ||||||
| 			_, err = buf.WriteString(prefix) | 	switch b.dialect { | ||||||
| 			if err != nil { | 	case ORACLE, MSSQL: | ||||||
|  | 		// This is for compatibility with different sql drivers | ||||||
|  | 		for e := range w.args { | ||||||
|  | 			w.args[e] = sql2.Named(fmt.Sprintf("p%d", e+1), w.args[e]) | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		var prefix string | ||||||
|  | 		if b.dialect == ORACLE { | ||||||
|  | 			prefix = ":p" | ||||||
|  | 		} else { | ||||||
|  | 			prefix = "@p" | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		if sql, err = ConvertPlaceholder(sql, prefix); err != nil { | ||||||
|  | 			return "", nil, err | ||||||
|  | 		} | ||||||
|  | 	case POSTGRES: | ||||||
|  | 		if sql, err = ConvertPlaceholder(sql, "$"); err != nil { | ||||||
|  | 			return "", nil, err | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return sql, w.args, nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // ToBoundSQL | ||||||
|  | func (b *Builder) ToBoundSQL() (string, error) { | ||||||
|  | 	w := NewWriter() | ||||||
|  | 	if err := b.WriteTo(w); err != nil { | ||||||
| 		return "", err | 		return "", err | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 			j = j + 1 | 	return ConvertToBoundSQL(w.writer.String(), w.args) | ||||||
| 			_, err = buf.WriteString(fmt.Sprintf("%d", j)) |  | ||||||
| 			if err != nil { |  | ||||||
| 				return "", err |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 	return buf.String(), nil |  | ||||||
| } |  | ||||||
|  |  | ||||||
| // ToSQL convert a builder or condtions to SQL and args |  | ||||||
| func ToSQL(cond interface{}) (string, []interface{}, error) { |  | ||||||
| 	switch cond.(type) { |  | ||||||
| 	case Cond: |  | ||||||
| 		return condToSQL(cond.(Cond)) |  | ||||||
| 	case *Builder: |  | ||||||
| 		return cond.(*Builder).ToSQL() |  | ||||||
| 	} |  | ||||||
| 	return "", nil, ErrNotSupportType |  | ||||||
| } | } | ||||||
|   | |||||||
							
								
								
									
										15
									
								
								vendor/github.com/go-xorm/builder/builder_delete.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										15
									
								
								vendor/github.com/go-xorm/builder/builder_delete.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -5,16 +5,21 @@ | |||||||
| package builder | package builder | ||||||
|  |  | ||||||
| import ( | import ( | ||||||
| 	"errors" |  | ||||||
| 	"fmt" | 	"fmt" | ||||||
| ) | ) | ||||||
|  |  | ||||||
| func (b *Builder) deleteWriteTo(w Writer) error { | // Delete creates a delete Builder | ||||||
| 	if len(b.tableName) <= 0 { | func Delete(conds ...Cond) *Builder { | ||||||
| 		return errors.New("no table indicated") | 	builder := &Builder{cond: NewCond()} | ||||||
|  | 	return builder.Delete(conds...) | ||||||
| } | } | ||||||
|  |  | ||||||
| 	if _, err := fmt.Fprintf(w, "DELETE FROM %s WHERE ", b.tableName); err != nil { | func (b *Builder) deleteWriteTo(w Writer) error { | ||||||
|  | 	if len(b.from) <= 0 { | ||||||
|  | 		return ErrNoTableName | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if _, err := fmt.Fprintf(w, "DELETE FROM %s WHERE ", b.from); err != nil { | ||||||
| 		return err | 		return err | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										51
									
								
								vendor/github.com/go-xorm/builder/builder_insert.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										51
									
								
								vendor/github.com/go-xorm/builder/builder_insert.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -6,39 +6,63 @@ package builder | |||||||
|  |  | ||||||
| import ( | import ( | ||||||
| 	"bytes" | 	"bytes" | ||||||
| 	"errors" |  | ||||||
| 	"fmt" | 	"fmt" | ||||||
| ) | ) | ||||||
|  |  | ||||||
| func (b *Builder) insertWriteTo(w Writer) error { | // Insert creates an insert Builder | ||||||
| 	if len(b.tableName) <= 0 { | func Insert(eq ...interface{}) *Builder { | ||||||
| 		return errors.New("no table indicated") | 	builder := &Builder{cond: NewCond()} | ||||||
| 	} | 	return builder.Insert(eq...) | ||||||
| 	if len(b.inserts) <= 0 { |  | ||||||
| 		return errors.New("no column to be insert") |  | ||||||
| } | } | ||||||
|  |  | ||||||
| 	if _, err := fmt.Fprintf(w, "INSERT INTO %s (", b.tableName); err != nil { | func (b *Builder) insertSelectWriteTo(w Writer) error { | ||||||
|  | 	if _, err := fmt.Fprintf(w, "INSERT INTO %s ", b.into); err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if len(b.insertCols) > 0 { | ||||||
|  | 		fmt.Fprintf(w, "(") | ||||||
|  | 		for _, col := range b.insertCols { | ||||||
|  | 			fmt.Fprintf(w, col) | ||||||
|  | 		} | ||||||
|  | 		fmt.Fprintf(w, ") ") | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return b.selectWriteTo(w) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (b *Builder) insertWriteTo(w Writer) error { | ||||||
|  | 	if len(b.into) <= 0 { | ||||||
|  | 		return ErrNoTableName | ||||||
|  | 	} | ||||||
|  | 	if len(b.insertCols) <= 0 && b.from == "" { | ||||||
|  | 		return ErrNoColumnToInsert | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if b.into != "" && b.from != "" { | ||||||
|  | 		return b.insertSelectWriteTo(w) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if _, err := fmt.Fprintf(w, "INSERT INTO %s (", b.into); err != nil { | ||||||
| 		return err | 		return err | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	var args = make([]interface{}, 0) | 	var args = make([]interface{}, 0) | ||||||
| 	var bs []byte | 	var bs []byte | ||||||
| 	var valBuffer = bytes.NewBuffer(bs) | 	var valBuffer = bytes.NewBuffer(bs) | ||||||
| 	var i = 0 |  | ||||||
|  |  | ||||||
| 	for _, col := range b.inserts.sortedKeys() { | 	for i, col := range b.insertCols { | ||||||
| 		value := b.inserts[col] | 		value := b.insertVals[i] | ||||||
| 		fmt.Fprint(w, col) | 		fmt.Fprint(w, col) | ||||||
| 		if e, ok := value.(expr); ok { | 		if e, ok := value.(expr); ok { | ||||||
| 			fmt.Fprint(valBuffer, e.sql) | 			fmt.Fprintf(valBuffer, "(%s)", e.sql) | ||||||
| 			args = append(args, e.args...) | 			args = append(args, e.args...) | ||||||
| 		} else { | 		} else { | ||||||
| 			fmt.Fprint(valBuffer, "?") | 			fmt.Fprint(valBuffer, "?") | ||||||
| 			args = append(args, value) | 			args = append(args, value) | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		if i != len(b.inserts)-1 { | 		if i != len(b.insertCols)-1 { | ||||||
| 			if _, err := fmt.Fprint(w, ","); err != nil { | 			if _, err := fmt.Fprint(w, ","); err != nil { | ||||||
| 				return err | 				return err | ||||||
| 			} | 			} | ||||||
| @@ -46,7 +70,6 @@ func (b *Builder) insertWriteTo(w Writer) error { | |||||||
| 				return err | 				return err | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 		i = i + 1 |  | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if _, err := fmt.Fprint(w, ") Values ("); err != nil { | 	if _, err := fmt.Fprint(w, ") Values ("); err != nil { | ||||||
|   | |||||||
							
								
								
									
										100
									
								
								vendor/github.com/go-xorm/builder/builder_limit.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										100
									
								
								vendor/github.com/go-xorm/builder/builder_limit.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,100 @@ | |||||||
|  | // Copyright 2018 The Xorm Authors. All rights reserved. | ||||||
|  | // Use of this source code is governed by a BSD-style | ||||||
|  | // license that can be found in the LICENSE file. | ||||||
|  |  | ||||||
|  | package builder | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"fmt" | ||||||
|  | 	"strings" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | func (b *Builder) limitWriteTo(w Writer) error { | ||||||
|  | 	if strings.TrimSpace(b.dialect) == "" { | ||||||
|  | 		return ErrDialectNotSetUp | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if b.limitation != nil { | ||||||
|  | 		limit := b.limitation | ||||||
|  | 		if limit.offset < 0 || limit.limitN <= 0 { | ||||||
|  | 			return ErrInvalidLimitation | ||||||
|  | 		} | ||||||
|  | 		// erase limit condition | ||||||
|  | 		b.limitation = nil | ||||||
|  | 		ow := w.(*BytesWriter) | ||||||
|  |  | ||||||
|  | 		switch strings.ToLower(strings.TrimSpace(b.dialect)) { | ||||||
|  | 		case ORACLE: | ||||||
|  | 			if len(b.selects) == 0 { | ||||||
|  | 				b.selects = append(b.selects, "*") | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			var final *Builder | ||||||
|  | 			selects := b.selects | ||||||
|  | 			b.selects = append(selects, "ROWNUM RN") | ||||||
|  |  | ||||||
|  | 			var wb *Builder | ||||||
|  | 			if b.optype == unionType { | ||||||
|  | 				wb = Dialect(b.dialect).Select("at.*", "ROWNUM RN"). | ||||||
|  | 					From(b, "at") | ||||||
|  | 			} else { | ||||||
|  | 				wb = b | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			if limit.offset == 0 { | ||||||
|  | 				final = Dialect(b.dialect).Select(selects...).From(wb, "at"). | ||||||
|  | 					Where(Lte{"at.RN": limit.limitN}) | ||||||
|  | 			} else { | ||||||
|  | 				sub := Dialect(b.dialect).Select("*"). | ||||||
|  | 					From(b, "at").Where(Lte{"at.RN": limit.offset + limit.limitN}) | ||||||
|  |  | ||||||
|  | 				final = Dialect(b.dialect).Select(selects...).From(sub, "att"). | ||||||
|  | 					Where(Gt{"att.RN": limit.offset}) | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			return final.WriteTo(ow) | ||||||
|  | 		case SQLITE, MYSQL, POSTGRES: | ||||||
|  | 			// if type UNION, we need to write previous content back to current writer | ||||||
|  | 			if b.optype == unionType { | ||||||
|  | 				if err := b.WriteTo(ow); err != nil { | ||||||
|  | 					return err | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			if limit.offset == 0 { | ||||||
|  | 				fmt.Fprint(ow, " LIMIT ", limit.limitN) | ||||||
|  | 			} else { | ||||||
|  | 				fmt.Fprintf(ow, " LIMIT %v OFFSET %v", limit.limitN, limit.offset) | ||||||
|  | 			} | ||||||
|  | 		case MSSQL: | ||||||
|  | 			if len(b.selects) == 0 { | ||||||
|  | 				b.selects = append(b.selects, "*") | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			var final *Builder | ||||||
|  | 			selects := b.selects | ||||||
|  | 			b.selects = append(append([]string{fmt.Sprintf("TOP %d %v", limit.limitN+limit.offset, b.selects[0])}, | ||||||
|  | 				b.selects[1:]...), "ROW_NUMBER() OVER (ORDER BY (SELECT 1)) AS RN") | ||||||
|  |  | ||||||
|  | 			var wb *Builder | ||||||
|  | 			if b.optype == unionType { | ||||||
|  | 				wb = Dialect(b.dialect).Select("*", "ROW_NUMBER() OVER (ORDER BY (SELECT 1)) AS RN"). | ||||||
|  | 					From(b, "at") | ||||||
|  | 			} else { | ||||||
|  | 				wb = b | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			if limit.offset == 0 { | ||||||
|  | 				final = Dialect(b.dialect).Select(selects...).From(wb, "at") | ||||||
|  | 			} else { | ||||||
|  | 				final = Dialect(b.dialect).Select(selects...).From(wb, "at").Where(Gt{"at.RN": limit.offset}) | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			return final.WriteTo(ow) | ||||||
|  | 		default: | ||||||
|  | 			return ErrNotSupportType | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
							
								
								
									
										55
									
								
								vendor/github.com/go-xorm/builder/builder_select.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										55
									
								
								vendor/github.com/go-xorm/builder/builder_select.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -5,13 +5,24 @@ | |||||||
| package builder | package builder | ||||||
|  |  | ||||||
| import ( | import ( | ||||||
| 	"errors" |  | ||||||
| 	"fmt" | 	"fmt" | ||||||
| ) | ) | ||||||
|  |  | ||||||
|  | // Select creates a select Builder | ||||||
|  | func Select(cols ...string) *Builder { | ||||||
|  | 	builder := &Builder{cond: NewCond()} | ||||||
|  | 	return builder.Select(cols...) | ||||||
|  | } | ||||||
|  |  | ||||||
| func (b *Builder) selectWriteTo(w Writer) error { | func (b *Builder) selectWriteTo(w Writer) error { | ||||||
| 	if len(b.tableName) <= 0 { | 	if len(b.from) <= 0 && !b.isNested { | ||||||
| 		return errors.New("no table indicated") | 		return ErrNoTableName | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// perform limit before writing to writer when b.dialect between ORACLE and MSSQL | ||||||
|  | 	// this avoid a duplicate writing problem in simple limit query | ||||||
|  | 	if b.limitation != nil && (b.dialect == ORACLE || b.dialect == MSSQL) { | ||||||
|  | 		return b.limitWriteTo(w) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if _, err := fmt.Fprint(w, "SELECT "); err != nil { | 	if _, err := fmt.Fprint(w, "SELECT "); err != nil { | ||||||
| @@ -34,9 +45,39 @@ func (b *Builder) selectWriteTo(w Writer) error { | |||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if _, err := fmt.Fprint(w, " FROM ", b.tableName); err != nil { | 	if b.subQuery == nil { | ||||||
|  | 		if _, err := fmt.Fprint(w, " FROM ", b.from); err != nil { | ||||||
| 			return err | 			return err | ||||||
| 		} | 		} | ||||||
|  | 	} else { | ||||||
|  | 		if b.cond.IsValid() && len(b.from) <= 0 { | ||||||
|  | 			return ErrUnnamedDerivedTable | ||||||
|  | 		} | ||||||
|  | 		if b.subQuery.dialect != "" && b.dialect != b.subQuery.dialect { | ||||||
|  | 			return ErrInconsistentDialect | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		// dialect of sub-query will inherit from the main one (if not set up) | ||||||
|  | 		if b.dialect != "" && b.subQuery.dialect == "" { | ||||||
|  | 			b.subQuery.dialect = b.dialect | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		switch b.subQuery.optype { | ||||||
|  | 		case selectType, unionType: | ||||||
|  | 			fmt.Fprint(w, " FROM (") | ||||||
|  | 			if err := b.subQuery.WriteTo(w); err != nil { | ||||||
|  | 				return err | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			if len(b.from) == 0 { | ||||||
|  | 				fmt.Fprintf(w, ")") | ||||||
|  | 			} else { | ||||||
|  | 				fmt.Fprintf(w, ") %v", b.from) | ||||||
|  | 			} | ||||||
|  | 		default: | ||||||
|  | 			return ErrUnexpectedSubQuery | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	for _, v := range b.joins { | 	for _, v := range b.joins { | ||||||
| 		if _, err := fmt.Fprintf(w, " %s JOIN %s ON ", v.joinType, v.joinTable); err != nil { | 		if _, err := fmt.Fprintf(w, " %s JOIN %s ON ", v.joinType, v.joinTable); err != nil { | ||||||
| @@ -76,6 +117,12 @@ func (b *Builder) selectWriteTo(w Writer) error { | |||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	if b.limitation != nil { | ||||||
|  | 		if err := b.limitWriteTo(w); err != nil { | ||||||
|  | 			return err | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	return nil | 	return nil | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										47
									
								
								vendor/github.com/go-xorm/builder/builder_union.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										47
									
								
								vendor/github.com/go-xorm/builder/builder_union.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,47 @@ | |||||||
|  | // Copyright 2018 The Xorm Authors. All rights reserved. | ||||||
|  | // Use of this source code is governed by a BSD-style | ||||||
|  | // license that can be found in the LICENSE file. | ||||||
|  |  | ||||||
|  | package builder | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"fmt" | ||||||
|  | 	"strings" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | func (b *Builder) unionWriteTo(w Writer) error { | ||||||
|  | 	if b.limitation != nil || b.cond.IsValid() || | ||||||
|  | 		b.orderBy != "" || b.having != "" || b.groupBy != "" { | ||||||
|  | 		return ErrNotUnexpectedUnionConditions | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	for idx, u := range b.unions { | ||||||
|  | 		current := u.builder | ||||||
|  | 		if current.optype != selectType { | ||||||
|  | 			return ErrUnsupportedUnionMembers | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		if len(b.unions) == 1 { | ||||||
|  | 			if err := current.selectWriteTo(w); err != nil { | ||||||
|  | 				return err | ||||||
|  | 			} | ||||||
|  | 		} else { | ||||||
|  | 			if b.dialect != "" && b.dialect != current.dialect { | ||||||
|  | 				return ErrInconsistentDialect | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			if idx != 0 { | ||||||
|  | 				fmt.Fprint(w, fmt.Sprintf(" UNION %v ", strings.ToUpper(u.unionType))) | ||||||
|  | 			} | ||||||
|  | 			fmt.Fprint(w, "(") | ||||||
|  |  | ||||||
|  | 			if err := current.selectWriteTo(w); err != nil { | ||||||
|  | 				return err | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			fmt.Fprint(w, ")") | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
							
								
								
									
										21
									
								
								vendor/github.com/go-xorm/builder/builder_update.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										21
									
								
								vendor/github.com/go-xorm/builder/builder_update.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -5,19 +5,24 @@ | |||||||
| package builder | package builder | ||||||
|  |  | ||||||
| import ( | import ( | ||||||
| 	"errors" |  | ||||||
| 	"fmt" | 	"fmt" | ||||||
| ) | ) | ||||||
|  |  | ||||||
| func (b *Builder) updateWriteTo(w Writer) error { | // Update creates an update Builder | ||||||
| 	if len(b.tableName) <= 0 { | func Update(updates ...Eq) *Builder { | ||||||
| 		return errors.New("no table indicated") | 	builder := &Builder{cond: NewCond()} | ||||||
| 	} | 	return builder.Update(updates...) | ||||||
| 	if len(b.updates) <= 0 { |  | ||||||
| 		return errors.New("no column to be update") |  | ||||||
| } | } | ||||||
|  |  | ||||||
| 	if _, err := fmt.Fprintf(w, "UPDATE %s SET ", b.tableName); err != nil { | func (b *Builder) updateWriteTo(w Writer) error { | ||||||
|  | 	if len(b.from) <= 0 { | ||||||
|  | 		return ErrNoTableName | ||||||
|  | 	} | ||||||
|  | 	if len(b.updates) <= 0 { | ||||||
|  | 		return ErrNoColumnToUpdate | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if _, err := fmt.Fprintf(w, "UPDATE %s SET ", b.from); err != nil { | ||||||
| 		return err | 		return err | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										12
									
								
								vendor/github.com/go-xorm/builder/cond.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										12
									
								
								vendor/github.com/go-xorm/builder/cond.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -72,15 +72,3 @@ func (condEmpty) Or(conds ...Cond) Cond { | |||||||
| func (condEmpty) IsValid() bool { | func (condEmpty) IsValid() bool { | ||||||
| 	return false | 	return false | ||||||
| } | } | ||||||
|  |  | ||||||
| func condToSQL(cond Cond) (string, []interface{}, error) { |  | ||||||
| 	if cond == nil || !cond.IsValid() { |  | ||||||
| 		return "", nil, nil |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	w := NewWriter() |  | ||||||
| 	if err := cond.WriteTo(w); err != nil { |  | ||||||
| 		return "", nil, err |  | ||||||
| 	} |  | ||||||
| 	return w.writer.String(), w.args, nil |  | ||||||
| } |  | ||||||
|   | |||||||
							
								
								
									
										29
									
								
								vendor/github.com/go-xorm/builder/cond_between.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										29
									
								
								vendor/github.com/go-xorm/builder/cond_between.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -17,10 +17,35 @@ var _ Cond = Between{} | |||||||
|  |  | ||||||
| // WriteTo write data to Writer | // WriteTo write data to Writer | ||||||
| func (between Between) WriteTo(w Writer) error { | func (between Between) WriteTo(w Writer) error { | ||||||
| 	if _, err := fmt.Fprintf(w, "%s BETWEEN ? AND ?", between.Col); err != nil { | 	if _, err := fmt.Fprintf(w, "%s BETWEEN ", between.Col); err != nil { | ||||||
| 		return err | 		return err | ||||||
| 	} | 	} | ||||||
| 	w.Append(between.LessVal, between.MoreVal) | 	if lv, ok := between.LessVal.(expr); ok { | ||||||
|  | 		if err := lv.WriteTo(w); err != nil { | ||||||
|  | 			return err | ||||||
|  | 		} | ||||||
|  | 	} else { | ||||||
|  | 		if _, err := fmt.Fprint(w, "?"); err != nil { | ||||||
|  | 			return err | ||||||
|  | 		} | ||||||
|  | 		w.Append(between.LessVal) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if _, err := fmt.Fprint(w, " AND "); err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if mv, ok := between.MoreVal.(expr); ok { | ||||||
|  | 		if err := mv.WriteTo(w); err != nil { | ||||||
|  | 			return err | ||||||
|  | 		} | ||||||
|  | 	} else { | ||||||
|  | 		if _, err := fmt.Fprint(w, "?"); err != nil { | ||||||
|  | 			return err | ||||||
|  | 		} | ||||||
|  | 		w.Append(between.MoreVal) | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	return nil | 	return nil | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										4
									
								
								vendor/github.com/go-xorm/builder/cond_or.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								vendor/github.com/go-xorm/builder/cond_or.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -27,10 +27,12 @@ func (o condOr) WriteTo(w Writer) error { | |||||||
| 	for i, cond := range o { | 	for i, cond := range o { | ||||||
| 		var needQuote bool | 		var needQuote bool | ||||||
| 		switch cond.(type) { | 		switch cond.(type) { | ||||||
| 		case condAnd: | 		case condAnd, expr: | ||||||
| 			needQuote = true | 			needQuote = true | ||||||
| 		case Eq: | 		case Eq: | ||||||
| 			needQuote = (len(cond.(Eq)) > 1) | 			needQuote = (len(cond.(Eq)) > 1) | ||||||
|  | 		case Neq: | ||||||
|  | 			needQuote = (len(cond.(Neq)) > 1) | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		if needQuote { | 		if needQuote { | ||||||
|   | |||||||
							
								
								
									
										26
									
								
								vendor/github.com/go-xorm/builder/error.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										26
									
								
								vendor/github.com/go-xorm/builder/error.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -8,9 +8,33 @@ import "errors" | |||||||
|  |  | ||||||
| var ( | var ( | ||||||
| 	// ErrNotSupportType not supported SQL type error | 	// ErrNotSupportType not supported SQL type error | ||||||
| 	ErrNotSupportType = errors.New("not supported SQL type") | 	ErrNotSupportType = errors.New("Not supported SQL type") | ||||||
| 	// ErrNoNotInConditions no NOT IN params error | 	// ErrNoNotInConditions no NOT IN params error | ||||||
| 	ErrNoNotInConditions = errors.New("No NOT IN conditions") | 	ErrNoNotInConditions = errors.New("No NOT IN conditions") | ||||||
| 	// ErrNoInConditions no IN params error | 	// ErrNoInConditions no IN params error | ||||||
| 	ErrNoInConditions = errors.New("No IN conditions") | 	ErrNoInConditions = errors.New("No IN conditions") | ||||||
|  | 	// ErrNeedMoreArguments need more arguments | ||||||
|  | 	ErrNeedMoreArguments = errors.New("Need more sql arguments") | ||||||
|  | 	// ErrNoTableName no table name | ||||||
|  | 	ErrNoTableName = errors.New("No table indicated") | ||||||
|  | 	// ErrNoColumnToInsert no column to update | ||||||
|  | 	ErrNoColumnToUpdate = errors.New("No column(s) to update") | ||||||
|  | 	// ErrNoColumnToInsert no column to update | ||||||
|  | 	ErrNoColumnToInsert = errors.New("No column(s) to insert") | ||||||
|  | 	// ErrNotSupportDialectType not supported dialect type error | ||||||
|  | 	ErrNotSupportDialectType = errors.New("Not supported dialect type") | ||||||
|  | 	// ErrNotUnexpectedUnionConditions using union in a wrong way | ||||||
|  | 	ErrNotUnexpectedUnionConditions = errors.New("Unexpected conditional fields in UNION query") | ||||||
|  | 	// ErrUnsupportedUnionMembers unexpected members in UNION query | ||||||
|  | 	ErrUnsupportedUnionMembers = errors.New("Unexpected members in UNION query") | ||||||
|  | 	// ErrUnexpectedSubQuery Unexpected sub-query in SELECT query | ||||||
|  | 	ErrUnexpectedSubQuery = errors.New("Unexpected sub-query in SELECT query") | ||||||
|  | 	// ErrDialectNotSetUp dialect is not setup yet | ||||||
|  | 	ErrDialectNotSetUp = errors.New("Dialect is not setup yet, try to use `Dialect(dbType)` at first") | ||||||
|  | 	// ErrInvalidLimitation offset or limit is not correct | ||||||
|  | 	ErrInvalidLimitation = errors.New("Offset or limit is not correct") | ||||||
|  | 	// ErrUnnamedDerivedTable Every derived table must have its own alias | ||||||
|  | 	ErrUnnamedDerivedTable = errors.New("Every derived table must have its own alias") | ||||||
|  | 	// ErrInconsistentDialect Inconsistent dialect in same builder | ||||||
|  | 	ErrInconsistentDialect = errors.New("Inconsistent dialect in same builder") | ||||||
| ) | ) | ||||||
|   | |||||||
							
								
								
									
										156
									
								
								vendor/github.com/go-xorm/builder/sql.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										156
									
								
								vendor/github.com/go-xorm/builder/sql.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,156 @@ | |||||||
|  | // Copyright 2018 The Xorm Authors. All rights reserved. | ||||||
|  | // Use of this source code is governed by a BSD-style | ||||||
|  | // license that can be found in the LICENSE file. | ||||||
|  |  | ||||||
|  | package builder | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	sql2 "database/sql" | ||||||
|  | 	"fmt" | ||||||
|  | 	"reflect" | ||||||
|  | 	"time" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | func condToSQL(cond Cond) (string, []interface{}, error) { | ||||||
|  | 	if cond == nil || !cond.IsValid() { | ||||||
|  | 		return "", nil, nil | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	w := NewWriter() | ||||||
|  | 	if err := cond.WriteTo(w); err != nil { | ||||||
|  | 		return "", nil, err | ||||||
|  | 	} | ||||||
|  | 	return w.writer.String(), w.args, nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func condToBoundSQL(cond Cond) (string, error) { | ||||||
|  | 	if cond == nil || !cond.IsValid() { | ||||||
|  | 		return "", nil | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	w := NewWriter() | ||||||
|  | 	if err := cond.WriteTo(w); err != nil { | ||||||
|  | 		return "", err | ||||||
|  | 	} | ||||||
|  | 	return ConvertToBoundSQL(w.writer.String(), w.args) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // ToSQL convert a builder or conditions to SQL and args | ||||||
|  | func ToSQL(cond interface{}) (string, []interface{}, error) { | ||||||
|  | 	switch cond.(type) { | ||||||
|  | 	case Cond: | ||||||
|  | 		return condToSQL(cond.(Cond)) | ||||||
|  | 	case *Builder: | ||||||
|  | 		return cond.(*Builder).ToSQL() | ||||||
|  | 	} | ||||||
|  | 	return "", nil, ErrNotSupportType | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // ToBoundSQL convert a builder or conditions to parameters bound SQL | ||||||
|  | func ToBoundSQL(cond interface{}) (string, error) { | ||||||
|  | 	switch cond.(type) { | ||||||
|  | 	case Cond: | ||||||
|  | 		return condToBoundSQL(cond.(Cond)) | ||||||
|  | 	case *Builder: | ||||||
|  | 		return cond.(*Builder).ToBoundSQL() | ||||||
|  | 	} | ||||||
|  | 	return "", ErrNotSupportType | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func noSQLQuoteNeeded(a interface{}) bool { | ||||||
|  | 	switch a.(type) { | ||||||
|  | 	case int, int8, int16, int32, int64: | ||||||
|  | 		return true | ||||||
|  | 	case uint, uint8, uint16, uint32, uint64: | ||||||
|  | 		return true | ||||||
|  | 	case float32, float64: | ||||||
|  | 		return true | ||||||
|  | 	case bool: | ||||||
|  | 		return true | ||||||
|  | 	case string: | ||||||
|  | 		return false | ||||||
|  | 	case time.Time, *time.Time: | ||||||
|  | 		return false | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	t := reflect.TypeOf(a) | ||||||
|  | 	switch t.Kind() { | ||||||
|  | 	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: | ||||||
|  | 		return true | ||||||
|  | 	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: | ||||||
|  | 		return true | ||||||
|  | 	case reflect.Float32, reflect.Float64: | ||||||
|  | 		return true | ||||||
|  | 	case reflect.Bool: | ||||||
|  | 		return true | ||||||
|  | 	case reflect.String: | ||||||
|  | 		return false | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return false | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // ConvertToBoundSQL will convert SQL and args to a bound SQL | ||||||
|  | func ConvertToBoundSQL(sql string, args []interface{}) (string, error) { | ||||||
|  | 	buf := StringBuilder{} | ||||||
|  | 	var i, j, start int | ||||||
|  | 	for ; i < len(sql); i++ { | ||||||
|  | 		if sql[i] == '?' { | ||||||
|  | 			_, err := buf.WriteString(sql[start:i]) | ||||||
|  | 			if err != nil { | ||||||
|  | 				return "", err | ||||||
|  | 			} | ||||||
|  | 			start = i + 1 | ||||||
|  |  | ||||||
|  | 			if len(args) == j { | ||||||
|  | 				return "", ErrNeedMoreArguments | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			arg := args[j] | ||||||
|  | 			if namedArg, ok := arg.(sql2.NamedArg); ok { | ||||||
|  | 				arg = namedArg.Value | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			if noSQLQuoteNeeded(arg) { | ||||||
|  | 				_, err = fmt.Fprint(&buf, arg) | ||||||
|  | 			} else { | ||||||
|  | 				_, err = fmt.Fprintf(&buf, "'%v'", arg) | ||||||
|  | 			} | ||||||
|  | 			if err != nil { | ||||||
|  | 				return "", err | ||||||
|  | 			} | ||||||
|  | 			j = j + 1 | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	_, err := buf.WriteString(sql[start:]) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return "", err | ||||||
|  | 	} | ||||||
|  | 	return buf.String(), nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // ConvertPlaceholder replaces ? to $1, $2 ... or :1, :2 ... according prefix | ||||||
|  | func ConvertPlaceholder(sql, prefix string) (string, error) { | ||||||
|  | 	buf := StringBuilder{} | ||||||
|  | 	var i, j, start int | ||||||
|  | 	for ; i < len(sql); i++ { | ||||||
|  | 		if sql[i] == '?' { | ||||||
|  | 			if _, err := buf.WriteString(sql[start:i]); err != nil { | ||||||
|  | 				return "", err | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			start = i + 1 | ||||||
|  | 			j = j + 1 | ||||||
|  |  | ||||||
|  | 			if _, err := buf.WriteString(fmt.Sprintf("%v%d", prefix, j)); err != nil { | ||||||
|  | 				return "", err | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if _, err := buf.WriteString(sql[start:]); err != nil { | ||||||
|  | 		return "", err | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return buf.String(), nil | ||||||
|  | } | ||||||
		Reference in New Issue
	
	Block a user