Create and drop view (#6097)
* create view * add comment * fix test * check param and add comment
This commit is contained in:
		
							parent
							
								
									391c961c7f
								
							
						
					
					
						commit
						a80707de9e
					
				| @ -23,6 +23,8 @@ var ( | ||||
| 	ErrModelValueRequired = errors.New("model value required") | ||||
| 	// ErrModelAccessibleFieldsRequired model accessible fields required
 | ||||
| 	ErrModelAccessibleFieldsRequired = errors.New("model accessible fields required") | ||||
| 	// ErrSubQueryRequired sub query required
 | ||||
| 	ErrSubQueryRequired = errors.New("sub query required") | ||||
| 	// ErrInvalidData unsupported data
 | ||||
| 	ErrInvalidData = errors.New("unsupported data") | ||||
| 	// ErrUnsupportedDriver unsupported driver
 | ||||
|  | ||||
| @ -30,9 +30,9 @@ func (db *DB) AutoMigrate(dst ...interface{}) error { | ||||
| 
 | ||||
| // ViewOption view option
 | ||||
| type ViewOption struct { | ||||
| 	Replace     bool | ||||
| 	CheckOption string | ||||
| 	Query       *DB | ||||
| 	Replace     bool   // If true, exec `CREATE`. If false, exec `CREATE OR REPLACE`
 | ||||
| 	CheckOption string // optional. e.g. `WITH [ CASCADED | LOCAL ] CHECK OPTION`
 | ||||
| 	Query       *DB    // required subquery.
 | ||||
| } | ||||
| 
 | ||||
| // ColumnType column type interface
 | ||||
|  | ||||
| @ -557,14 +557,44 @@ func (m Migrator) ColumnTypes(value interface{}) ([]gorm.ColumnType, error) { | ||||
| 	return columnTypes, execErr | ||||
| } | ||||
| 
 | ||||
| // CreateView create view
 | ||||
| // CreateView create view from Query in gorm.ViewOption.
 | ||||
| // Query in gorm.ViewOption is a [subquery]
 | ||||
| //
 | ||||
| //	// CREATE VIEW `user_view` AS SELECT * FROM `users` WHERE age > 20
 | ||||
| //	q := DB.Model(&User{}).Where("age > ?", 20)
 | ||||
| //	DB.Debug().Migrator().CreateView("user_view", gorm.ViewOption{Query: q})
 | ||||
| //
 | ||||
| //	// CREATE OR REPLACE VIEW `users_view` AS SELECT * FROM `users` WITH CHECK OPTION
 | ||||
| //	q := DB.Model(&User{})
 | ||||
| //	DB.Debug().Migrator().CreateView("user_view", gorm.ViewOption{Query: q, Replace: true, CheckOption: "WITH CHECK OPTION"})
 | ||||
| //
 | ||||
| // [subquery]: https://gorm.io/docs/advanced_query.html#SubQuery
 | ||||
| func (m Migrator) CreateView(name string, option gorm.ViewOption) error { | ||||
| 	return gorm.ErrNotImplemented | ||||
| 	if option.Query == nil { | ||||
| 		return gorm.ErrSubQueryRequired | ||||
| 	} | ||||
| 
 | ||||
| 	sql := new(strings.Builder) | ||||
| 	sql.WriteString("CREATE ") | ||||
| 	if option.Replace { | ||||
| 		sql.WriteString("OR REPLACE ") | ||||
| 	} | ||||
| 	sql.WriteString("VIEW ") | ||||
| 	m.QuoteTo(sql, name) | ||||
| 	sql.WriteString(" AS ") | ||||
| 
 | ||||
| 	m.DB.Statement.AddVar(sql, option.Query) | ||||
| 
 | ||||
| 	if option.CheckOption != "" { | ||||
| 		sql.WriteString(" ") | ||||
| 		sql.WriteString(option.CheckOption) | ||||
| 	} | ||||
| 	return m.DB.Exec(m.Explain(sql.String(), m.DB.Statement.Vars...)).Error | ||||
| } | ||||
| 
 | ||||
| // DropView drop view
 | ||||
| func (m Migrator) DropView(name string) error { | ||||
| 	return gorm.ErrNotImplemented | ||||
| 	return m.DB.Exec("DROP VIEW IF EXISTS ?", clause.Table{Name: name}).Error | ||||
| } | ||||
| 
 | ||||
| func buildConstraint(constraint *schema.Constraint) (sql string, results []interface{}) { | ||||
|  | ||||
| @ -1509,3 +1509,36 @@ func TestMigrateIgnoreRelations(t *testing.T) { | ||||
| 		t.Errorf("RelationModel2 should not be migrated") | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func TestMigrateView(t *testing.T) { | ||||
| 	DB.Save(GetUser("joins-args-db", Config{Pets: 2})) | ||||
| 
 | ||||
| 	if err := DB.Migrator().CreateView("invalid_users_pets", gorm.ViewOption{Query: nil}); err != gorm.ErrSubQueryRequired { | ||||
| 		t.Fatalf("no view should be created, got %v", err) | ||||
| 	} | ||||
| 
 | ||||
| 	query := DB.Model(&User{}). | ||||
| 		Select("users.id as users_id, users.name as users_name, pets.id as pets_id, pets.name as pets_name"). | ||||
| 		Joins("inner join pets on pets.user_id = users.id") | ||||
| 
 | ||||
| 	if err := DB.Migrator().CreateView("users_pets", gorm.ViewOption{Query: query}); err != nil { | ||||
| 		t.Fatalf("Failed to crate view, got %v", err) | ||||
| 	} | ||||
| 
 | ||||
| 	var count int64 | ||||
| 	if err := DB.Table("users_pets").Count(&count).Error; err != nil { | ||||
| 		t.Fatalf("should found created view") | ||||
| 	} | ||||
| 
 | ||||
| 	if err := DB.Migrator().DropView("users_pets"); err != nil { | ||||
| 		t.Fatalf("Failed to drop view, got %v", err) | ||||
| 	} | ||||
| 
 | ||||
| 	query = DB.Model(&User{}).Where("age > ?", 20) | ||||
| 	if err := DB.Migrator().CreateView("users_view", gorm.ViewOption{Query: query}); err != nil { | ||||
| 		t.Fatalf("Failed to crate view, got %v", err) | ||||
| 	} | ||||
| 	if err := DB.Migrator().DropView("users_view"); err != nil { | ||||
| 		t.Fatalf("Failed to drop view, got %v", err) | ||||
| 	} | ||||
| } | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 black-06
						black-06