func Parse(urlstr string) (*URL, error) {
	// parse url
	u, err := url.Parse(urlstr)
	if err != nil {
		return nil, err
	}
	if u.Scheme == "" {
		return nil, ErrInvalidDatabaseScheme
	}

	// create url
	v := &URL{URL: *u, OriginalScheme: urlstr[:len(u.Scheme)], Proto: "tcp"}

	// check for +protocol in scheme
	var checkProto bool
	if i := strings.IndexRune(v.Scheme, '+'); i != -1 {
		v.Proto = urlstr[i+1 : len(u.Scheme)]
		v.Scheme = v.Scheme[:i]
		checkProto = true
	}

	// get dsn generator
	scheme, ok := schemeMap[v.Scheme]
	if !ok {
		return nil, ErrUnknownDatabaseScheme
	}

	// if scheme does not understand opaque URLs, retry parsing after making a fully
	// qualified URL
	if !scheme.Opaque && v.Opaque != "" {
		q := ""
		if v.RawQuery != "" {
			q = "?" + v.RawQuery
		}
		f := ""
		if v.Fragment != "" {
			f = "#" + v.Fragment
		}

		return Parse(v.OriginalScheme + "://" + v.Opaque + q + f)
	}

	if scheme.Opaque && v.Opaque == "" {
		// force Opaque
		v.Opaque, v.Host, v.Path, v.RawPath = v.Host+v.Path, "", "", ""
	} else if v.Host == "." || (v.Host == "" && strings.TrimPrefix(v.Path, "/") != "") {
		// force unix proto
		v.Proto = "unix"
	}

	// check proto
	if checkProto || v.Proto != "tcp" {
		if scheme.Proto == ProtoNone {
			return nil, ErrInvalidTransportProtocol
		}

		switch {
		case scheme.Proto&ProtoAny != 0 && v.Proto != "":
		case scheme.Proto&ProtoTCP != 0 && v.Proto == "tcp":
		case scheme.Proto&ProtoUDP != 0 && v.Proto == "udp":
		case scheme.Proto&ProtoUnix != 0 && v.Proto == "unix":

		default:
			return nil, ErrInvalidTransportProtocol
		}
	}

	// set driver
	v.Driver = scheme.Driver
	v.Unaliased = scheme.Driver
	if scheme.Override != "" {
		v.Driver = scheme.Override
	}

	// generate dsn
	v.DSN, err = scheme.Generator(v)
	if err != nil {
		return nil, err
	}

	return v, nil
}
func Parse(urlstr string) (*URL, error) {
	
	u, err := url.Parse(urlstr)
	if err != nil {
		return nil, err
	}
	if u.Scheme == "" {
		return nil, ErrInvalidDatabaseScheme
	}

	
	v := &URL{URL: *u, OriginalScheme: urlstr[:len(u.Scheme)], Proto: "tcp"}

	
	var checkProto bool
	if i := strings.IndexRune(v.Scheme, '+'); i != -1 {
		v.Proto = urlstr[i+1 : len(u.Scheme)]
		v.Scheme = v.Scheme[:i]
		checkProto = true
	}

	
	scheme, ok := schemeMap[v.Scheme]
	if !ok {
		return nil, ErrUnknownDatabaseScheme
	}

	
	
	if !scheme.Opaque && v.Opaque != "" {
		q := ""
		if v.RawQuery != "" {
			q = "?" + v.RawQuery
		}
		f := ""
		if v.Fragment != "" {
			f = "#" + v.Fragment
		}

		return Parse(v.OriginalScheme + ":
	}

	if scheme.Opaque && v.Opaque == "" {
		
		v.Opaque, v.Host, v.Path, v.RawPath = v.Host+v.Path, "", "", ""
	} else if v.Host == "." || (v.Host == "" && strings.TrimPrefix(v.Path, "/") != "") {
		
		v.Proto = "unix"
	}

	
	if checkProto || v.Proto != "tcp" {
		if scheme.Proto == ProtoNone {
			return nil, ErrInvalidTransportProtocol
		}

		switch {
		case scheme.Proto&ProtoAny != 0 && v.Proto != "":
		case scheme.Proto&ProtoTCP != 0 && v.Proto == "tcp":
		case scheme.Proto&ProtoUDP != 0 && v.Proto == "udp":
		case scheme.Proto&ProtoUnix != 0 && v.Proto == "unix":

		default:
			return nil, ErrInvalidTransportProtocol
		}
	}

	
	v.Driver = scheme.Driver
	v.Unaliased = scheme.Driver
	if scheme.Override != "" {
		v.Driver = scheme.Override
	}

	
	v.DSN, err = scheme.Generator(v)
	if err != nil {
		return nil, err
	}

	return v, nil
}
func Parse ( urlstr string ) ( * URL , error ) { // parse url u , err := url . Parse ( urlstr ) if err != nil { return nil , err } if u . Scheme == " " { return nil , ErrInvalidDatabaseScheme } // create url v := & URL { URL : * u , OriginalScheme : urlstr [ : len ( u . Scheme ) ] , Proto : " " } // check for +protocol in scheme var checkProto bool if i := strings . IndexRune ( v . Scheme , '+' ) ; i != - 1 { v . Proto = urlstr [ i + 1 : len ( u . Scheme ) ] v . Scheme = v . Scheme [ : i ] checkProto = true } // get dsn generator scheme , ok := schemeMap [ v . Scheme ] if ! ok { return nil , ErrUnknownDatabaseScheme } // if scheme does not understand opaque URLs, retry parsing after making a fully // qualified URL if ! scheme . Opaque && v . Opaque != " " { q := " " if v . RawQuery != " " { q = " " + v . RawQuery } f := " " if v . Fragment != " " { f = " " + v . Fragment } return Parse ( v . OriginalScheme + " " + v . Opaque + q + f ) } if scheme . Opaque && v . Opaque == " " { // force Opaque v . Opaque , v . Host , v . Path , v . RawPath = v . Host + v . Path , " " , " " , " " } else if v . Host == " " || ( v . Host == " " && strings . TrimPrefix ( v . Path , " " ) != " " ) { // force unix proto v . Proto = " " } // check proto if checkProto || v . Proto != " " { if scheme . Proto == ProtoNone { return nil , ErrInvalidTransportProtocol } switch { case scheme . Proto & ProtoAny != 0 && v . Proto != " " : case scheme . Proto & ProtoTCP != 0 && v . Proto == " " : case scheme . Proto & ProtoUDP != 0 && v . Proto == " " : case scheme . Proto & ProtoUnix != 0 && v . Proto == " " : default : return nil , ErrInvalidTransportProtocol } } // set driver v . Driver = scheme . Driver v . Unaliased = scheme . Driver if scheme . Override != " " { v . Driver = scheme . Override } // generate dsn v . DSN , err = scheme . Generator ( v ) if err != nil { return nil , err } return v , nil }
// Parse parses urlstr, returning a URL with the OriginalScheme, Proto, Driver,
// Unaliased, and DSN fields populated.
//
// Note: if urlstr has a Opaque component (ie, URLs not specified as "scheme://"
// but "scheme:"), and the database scheme does not support opaque components,
// then Parse will attempt to re-process the URL as "scheme://<opaque>" using
// the OriginalScheme.
Parse parses urlstr returning a URL with the OriginalScheme Proto Driver Unaliased and DSN fields populated . Note : if urlstr has a Opaque component ( ie URLs not specified as scheme : // but scheme : ) and the database scheme does not support opaque components then Parse will attempt to re - process the URL as scheme : // <opaque > using the OriginalScheme .