package mysqldialect

import (
	
	
	
	
	
	

	

	
	
	
	
)

const datetimeType = "DATETIME"

type Dialect struct {
	tables   *schema.Tables
	features feature.Feature

	appenderMap sync.Map
	scannerMap  sync.Map
}

func () *Dialect {
	 := new(Dialect)
	.tables = schema.NewTables()
	.features = feature.AutoIncrement |
		feature.DefaultPlaceholder |
		feature.UpdateMultiTable |
		feature.ValuesRow |
		feature.TableTruncate |
		feature.OnDuplicateKey
	return 
}

func ( *Dialect) ( *sql.DB) {
	var  string
	if  := .QueryRow("SELECT version()").Scan(&);  != nil {
		log.Printf("can't discover MySQL version: %s", )
		return
	}

	if strings.Contains(, "MariaDB") {
		return
	}

	 = semver.MajorMinor("v" + cleanupVersion())
	if semver.Compare(, "v8.0") >= 0 {
		.features |= feature.CTE | feature.DeleteTableAlias
	}
}

func ( string) string {
	if  := strings.IndexByte(, '-');  >= 0 {
		return [:]
	}
	return 
}

func ( *Dialect) () dialect.Name {
	return dialect.MySQL
}

func ( *Dialect) () feature.Feature {
	return .features
}

func ( *Dialect) () *schema.Tables {
	return .tables
}

func ( *Dialect) ( *schema.Table) {
	for ,  := range .FieldMap {
		.DiscoveredSQLType = sqlType()
	}
}

func ( *Dialect) () byte {
	return '`'
}

func ( *Dialect) ( schema.Formatter,  []byte,  interface{}) []byte {
	switch v := .(type) {
	case time.Time:
		return appendTime(, )
	default:
		return schema.Append(, , , customAppender)
	}
}

func ( *Dialect) ( reflect.Type) schema.AppenderFunc {
	if ,  := .appenderMap.Load();  {
		return .(schema.AppenderFunc)
	}

	 := appender()

	if ,  := .appenderMap.LoadOrStore(, );  {
		return .(schema.AppenderFunc)
	}
	return 
}

func ( *Dialect) ( *schema.Field) schema.AppenderFunc {
	switch strings.ToUpper(.UserSQLType) {
	case sqltype.JSON:
		return appendJSONValue
	}

	return schema.FieldAppender(, )
}

func ( *Dialect) ( reflect.Type) schema.ScannerFunc {
	if ,  := .scannerMap.Load();  {
		return .(schema.ScannerFunc)
	}

	 := scanner()

	if ,  := .scannerMap.LoadOrStore(, );  {
		return .(schema.ScannerFunc)
	}
	return 
}

func ( *schema.Field) string {
	switch .DiscoveredSQLType {
	case sqltype.VarChar:
		return .DiscoveredSQLType + "(255)"
	case sqltype.Timestamp:
		return datetimeType
	}
	return .DiscoveredSQLType
}