2015-01-20 21:15:48 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								package  migrator  
						 
					
						
							
								
									
										
										
										
											2015-01-19 17:44:16 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-03-28 20:34:53 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								import  (  
						 
					
						
							
								
									
										
										
										
											2020-07-09 13:14:35 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									"fmt" 
							 
						 
					
						
							
								
									
										
										
										
											2017-03-28 20:34:53 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									"strconv" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									"strings" 
							 
						 
					
						
							
								
									
										
										
										
											2018-05-10 22:54:21 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-09-27 18:07:43 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									"github.com/VividCortex/mysqlerr" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									"github.com/go-sql-driver/mysql" 
							 
						 
					
						
							
								
									
										
										
										
											2020-04-01 21:57:21 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									"xorm.io/xorm" 
							 
						 
					
						
							
								
									
										
										
										
											2017-03-28 20:34:53 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								)  
						 
					
						
							
								
									
										
										
										
											2015-01-19 17:44:16 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								type  Mysql  struct  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									BaseDialect 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-05-10 22:54:21 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								func  NewMysqlDialect ( engine  * xorm . Engine )  * Mysql  {  
						 
					
						
							
								
									
										
										
										
											2015-01-19 17:44:16 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									d  :=  Mysql { } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									d . BaseDialect . dialect  =  & d 
							 
						 
					
						
							
								
									
										
										
										
											2018-05-10 22:54:21 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									d . BaseDialect . engine  =  engine 
							 
						 
					
						
							
								
									
										
										
										
											2015-01-19 17:44:16 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									d . BaseDialect . driverName  =  MYSQL 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  & d 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2015-01-20 21:44:37 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								func  ( db  * Mysql )  SupportEngine ( )  bool  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  true 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2015-01-19 17:44:16 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								func  ( db  * Mysql )  Quote ( name  string )  string  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  "`"  +  name  +  "`" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  ( db  * Mysql )  AutoIncrStr ( )  string  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  "AUTO_INCREMENT" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2016-09-23 14:07:14 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								func  ( db  * Mysql )  BooleanStr ( value  bool )  string  {  
						 
					
						
							
								
									
										
										
										
											2016-10-25 20:52:20 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  value  { 
							 
						 
					
						
							
								
									
										
										
										
											2016-12-14 11:15:35 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return  "1" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  "0" 
							 
						 
					
						
							
								
									
										
										
										
											2016-09-23 14:07:14 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2015-01-19 17:44:16 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								func  ( db  * Mysql )  SqlType ( c  * Column )  string  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									var  res  string 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									switch  c . Type  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  DB_Bool : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										res  =  DB_TinyInt 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										c . Length  =  1 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  DB_Serial : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										c . IsAutoIncrement  =  true 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										c . IsPrimaryKey  =  true 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										c . Nullable  =  false 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										res  =  DB_Int 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  DB_BigSerial : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										c . IsAutoIncrement  =  true 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										c . IsPrimaryKey  =  true 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										c . Nullable  =  false 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										res  =  DB_BigInt 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  DB_Bytea : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										res  =  DB_Blob 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  DB_TimeStampz : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										res  =  DB_Char 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										c . Length  =  64 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  DB_NVarchar : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										res  =  DB_Varchar 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									default : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										res  =  c . Type 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-04-28 04:14:36 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									var  hasLen1  =  ( c . Length  >  0 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									var  hasLen2  =  ( c . Length2  >  0 ) 
							 
						 
					
						
							
								
									
										
										
										
											2015-01-19 17:44:16 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  res  ==  DB_BigInt  &&  ! hasLen1  &&  ! hasLen2  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										c . Length  =  20 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										hasLen1  =  true 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  hasLen2  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										res  +=  "("  +  strconv . Itoa ( c . Length )  +  ","  +  strconv . Itoa ( c . Length2 )  +  ")" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									}  else  if  hasLen1  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										res  +=  "("  +  strconv . Itoa ( c . Length )  +  ")" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2017-03-28 20:34:53 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									switch  c . Type  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  DB_Char ,  DB_Varchar ,  DB_NVarchar ,  DB_TinyText ,  DB_Text ,  DB_MediumText ,  DB_LongText : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										res  +=  " CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2015-01-19 17:44:16 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									return  res 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-03-28 20:34:53 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								func  ( db  * Mysql )  UpdateTableSql ( tableName  string ,  columns  [ ] * Column )  string  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									var  statements  =  [ ] string { } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									statements  =  append ( statements ,  "DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									for  _ ,  col  :=  range  columns  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										statements  =  append ( statements ,  "MODIFY " + col . StringNoPk ( db ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  "ALTER TABLE "  +  db . Quote ( tableName )  +  " "  +  strings . Join ( statements ,  ", " )  +  ";" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
									
										
										
										
											2018-05-10 22:54:21 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-12-19 04:47:45 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								func  ( db  * Mysql )  IndexCheckSql ( tableName ,  indexName  string )  ( string ,  [ ] interface { } )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									args  :=  [ ] interface { } { tableName ,  indexName } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									sql  :=  "SELECT 1 FROM "  +  db . Quote ( "INFORMATION_SCHEMA" )  +  "."  +  db . Quote ( "STATISTICS" )  +  " WHERE "  +  db . Quote ( "TABLE_SCHEMA" )  +  " = DATABASE() AND "  +  db . Quote ( "TABLE_NAME" )  +  "=? AND "  +  db . Quote ( "INDEX_NAME" )  +  "=?" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  sql ,  args 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-12-19 06:02:08 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								func  ( db  * Mysql )  ColumnCheckSql ( tableName ,  columnName  string )  ( string ,  [ ] interface { } )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									args  :=  [ ] interface { } { tableName ,  columnName } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									sql  :=  "SELECT 1 FROM "  +  db . Quote ( "INFORMATION_SCHEMA" )  +  "."  +  db . Quote ( "COLUMNS" )  +  " WHERE "  +  db . Quote ( "TABLE_SCHEMA" )  +  " = DATABASE() AND "  +  db . Quote ( "TABLE_NAME" )  +  "=? AND "  +  db . Quote ( "COLUMN_NAME" )  +  "=?" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  sql ,  args 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-05-10 22:54:21 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								func  ( db  * Mysql )  CleanDB ( )  error  {  
						 
					
						
							
								
									
										
										
										
											2020-07-09 13:14:35 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									tables ,  _  :=  db . engine . DBMetas ( ) 
							 
						 
					
						
							
								
									
										
										
										
											2018-05-10 22:54:21 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									sess  :=  db . engine . NewSession ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									defer  sess . Close ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									for  _ ,  table  :=  range  tables  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  _ ,  err  :=  sess . Exec ( "set foreign_key_checks = 0" ) ;  err  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2020-07-09 13:14:35 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											return  fmt . Errorf ( "failed to disable foreign key checks" ) 
							 
						 
					
						
							
								
									
										
										
										
											2018-05-10 22:54:21 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  _ ,  err  :=  sess . Exec ( "drop table "  +  table . Name  +  " ;" ) ;  err  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2020-07-09 13:14:35 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											return  fmt . Errorf ( "failed to delete table: %v, err: %v" ,  table . Name ,  err ) 
							 
						 
					
						
							
								
									
										
										
										
											2018-05-10 22:54:21 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  _ ,  err  :=  sess . Exec ( "set foreign_key_checks = 1" ) ;  err  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2020-07-09 13:14:35 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											return  fmt . Errorf ( "failed to disable foreign key checks" ) 
							 
						 
					
						
							
								
									
										
										
										
											2018-05-10 22:54:21 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
									
										
										
										
											2018-09-27 18:07:43 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2019-06-13 21:36:09 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								func  ( db  * Mysql )  isThisError ( err  error ,  errcode  uint16 )  bool  {  
						 
					
						
							
								
									
										
										
										
											2018-09-27 18:07:43 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  driverErr ,  ok  :=  err . ( * mysql . MySQLError ) ;  ok  { 
							 
						 
					
						
							
								
									
										
										
										
											2019-06-13 21:36:09 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  driverErr . Number  ==  errcode  { 
							 
						 
					
						
							
								
									
										
										
										
											2018-09-27 18:07:43 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											return  true 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  false 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
									
										
										
										
											2019-06-13 21:36:09 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  ( db  * Mysql )  IsUniqueConstraintViolation ( err  error )  bool  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  db . isThisError ( err ,  mysqlerr . ER_DUP_ENTRY ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-04-20 21:48:38 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								func  ( db  * Mysql )  ErrorMessage ( err  error )  string  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  driverErr ,  ok  :=  err . ( * mysql . MySQLError ) ;  ok  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  driverErr . Message 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  "" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2019-06-13 21:36:09 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								func  ( db  * Mysql )  IsDeadlock ( err  error )  bool  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  db . isThisError ( err ,  mysqlerr . ER_LOCK_DEADLOCK ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}