github.com/ddev/ddev@v1.23.2-0.20240519125000-d824ffe36ff3/pkg/ddevapp/db.go (about)

     1  package ddevapp
     2  
     3  import (
     4  	"github.com/ddev/ddev/pkg/dockerutil"
     5  	"github.com/ddev/ddev/pkg/nodeps"
     6  	"github.com/ddev/ddev/pkg/util"
     7  	"github.com/ddev/ddev/pkg/versionconstants"
     8  	"regexp"
     9  	"strings"
    10  )
    11  
    12  // GetExistingDBType returns type/version like mariadb:10.11 or postgres:13 or "" if no existing volume
    13  // This has to make a Docker container run so is fairly costly.
    14  func (app *DdevApp) GetExistingDBType() (string, error) {
    15  	_, out, err := dockerutil.RunSimpleContainer(versionconstants.BusyboxImage, "GetExistingDBType-"+app.Name+"-"+util.RandString(6), []string{"sh", "-c", "( test -f /var/tmp/mysql/db_mariadb_version.txt && cat /var/tmp/mysql/db_mariadb_version.txt ) || ( test -f /var/tmp/postgres/PG_VERSION && cat /var/tmp/postgres/PG_VERSION) || true"}, []string{}, []string{}, []string{app.GetMariaDBVolumeName() + ":/var/tmp/mysql", app.GetPostgresVolumeName() + ":/var/tmp/postgres"}, "", true, false, map[string]string{`com.ddev.site-name`: ""}, nil, nil)
    16  
    17  	if err != nil {
    18  		util.Failed("Failed to RunSimpleContainer to inspect database version/type: %v, output=%s", err, out)
    19  	}
    20  
    21  	out = strings.Trim(out, " \n\r\t")
    22  	// If it was empty, OK to return nothing found, even though the volume was there
    23  	if out == "" {
    24  		return "", nil
    25  	}
    26  
    27  	return dbTypeVersionFromString(out), nil
    28  }
    29  
    30  // dbTypeVersionFromString takes an input string and derives the info from the uses
    31  // There are 3 possible cases here:
    32  // 1. It has an _, meaning it's a current MySQL or MariaDB version. Easy to parse.
    33  // 2. It has N+.N, meaning it's a pre-v1.19 MariaDB or MySQL version
    34  // 3. It has N+, meaning it's PostgreSQL
    35  func dbTypeVersionFromString(in string) string {
    36  
    37  	idType := ""
    38  
    39  	postgresStyle := regexp.MustCompile(`^[0-9]+$`)
    40  	postgresV9Style := regexp.MustCompile(`^9\.?`)
    41  	oldStyle := regexp.MustCompile(`^[0-9]+\.[0-9]$`)
    42  	newStyleV119 := regexp.MustCompile(`^(mysql|mariadb)_[0-9]+\.[0-9][0-9]?$`)
    43  
    44  	if newStyleV119.MatchString(in) {
    45  		idType = "current"
    46  	} else if postgresStyle.MatchString(in) || postgresV9Style.MatchString(in) {
    47  		idType = "postgres"
    48  	} else if oldStyle.MatchString(in) {
    49  		idType = "old_pre_v1.19"
    50  	}
    51  
    52  	dbType := ""
    53  	dbVersion := ""
    54  
    55  	switch idType {
    56  	case "current": // Current representation, <type>_version
    57  		res := strings.Split(in, "_")
    58  		dbType = res[0]
    59  		dbVersion = res[1]
    60  
    61  	// PostgreSQL: value is an int
    62  	case "postgres":
    63  		dbType = nodeps.Postgres
    64  		parts := strings.Split(in, `.`)
    65  		dbVersion = parts[0]
    66  
    67  	case "old_pre_v1.19":
    68  		dbType = nodeps.MariaDB
    69  
    70  		// Both MariaDB and MySQL have 5.5, but we'll give the win to MariaDB here.
    71  		if in == "5.6" || in == "5.7" || in == "8.0" {
    72  			dbType = nodeps.MySQL
    73  		}
    74  		dbVersion = in
    75  
    76  	default: // Punt and assume it's an old default db
    77  		dbType = nodeps.MariaDB
    78  		dbVersion = "10.3"
    79  	}
    80  	return dbType + ":" + dbVersion
    81  }