func NewDSNConnector(dsn string) (*Connector, error) {
	c := newConnector()

	url, err := url.Parse(dsn)
	if err != nil {
		return nil, err
	}

	c.host = url.Host

	if url.User != nil {
		c.username = url.User.Username()
		c.password, _ = url.User.Password()
	}

	var certPool *x509.CertPool

	for k, v := range url.Query() {
		switch k {

		default:
			return nil, fmt.Errorf("URL parameter %s is not supported", k)

		case DSNFetchSize:
			if len(v) == 0 {
				continue
			}
			fetchSize, err := strconv.Atoi(v[0])
			if err != nil {
				return nil, fmt.Errorf("failed to parse fetchSize: %s", v[0])
			}
			if fetchSize < minFetchSize {
				c.fetchSize = minFetchSize
			} else {
				c.fetchSize = fetchSize
			}

		case DSNTimeout:
			if len(v) == 0 {
				continue
			}
			timeout, err := strconv.Atoi(v[0])
			if err != nil {
				return nil, fmt.Errorf("failed to parse timeout: %s", v[0])
			}
			if timeout < minTimeout {
				c.timeout = minTimeout
			} else {
				c.timeout = timeout
			}

		case DSNLocale:
			if len(v) == 0 {
				continue
			}
			c.locale = v[0]

		case DSNTLSServerName:
			if len(v) == 0 {
				continue
			}
			if c.tlsConfig == nil {
				c.tlsConfig = &tls.Config{}
			}
			c.tlsConfig.ServerName = v[0]

		case DSNTLSInsecureSkipVerify:
			if len(v) == 0 {
				continue
			}
			var err error
			b := true
			if v[0] != "" {
				b, err = strconv.ParseBool(v[0])
				if err != nil {
					return nil, fmt.Errorf("failed to parse InsecureSkipVerify (bool): %s", v[0])
				}
			}
			if c.tlsConfig == nil {
				c.tlsConfig = &tls.Config{}
			}
			c.tlsConfig.InsecureSkipVerify = b

		case DSNTLSRootCAFile:
			for _, fn := range v {
				rootPEM, err := ioutil.ReadFile(fn)
				if err != nil {
					return nil, err
				}
				if certPool == nil {
					certPool = x509.NewCertPool()
				}
				if ok := certPool.AppendCertsFromPEM(rootPEM); !ok {
					return nil, fmt.Errorf("failed to parse root certificate - filename: %s", fn)
				}
			}
			if certPool != nil {
				if c.tlsConfig == nil {
					c.tlsConfig = &tls.Config{}
				}
				c.tlsConfig.RootCAs = certPool
			}
		}
	}
	return c, nil
}
func NewDSNConnector(dsn string) (*Connector, error) {
	c := newConnector()

	url, err := url.Parse(dsn)
	if err != nil {
		return nil, err
	}

	c.host = url.Host

	if url.User != nil {
		c.username = url.User.Username()
		c.password, _ = url.User.Password()
	}

	var certPool *x509.CertPool

	for k, v := range url.Query() {
		switch k {

		default:
			return nil, fmt.Errorf("URL parameter %s is not supported", k)

		case DSNFetchSize:
			if len(v) == 0 {
				continue
			}
			fetchSize, err := strconv.Atoi(v[0])
			if err != nil {
				return nil, fmt.Errorf("failed to parse fetchSize: %s", v[0])
			}
			if fetchSize < minFetchSize {
				c.fetchSize = minFetchSize
			} else {
				c.fetchSize = fetchSize
			}

		case DSNTimeout:
			if len(v) == 0 {
				continue
			}
			timeout, err := strconv.Atoi(v[0])
			if err != nil {
				return nil, fmt.Errorf("failed to parse timeout: %s", v[0])
			}
			if timeout < minTimeout {
				c.timeout = minTimeout
			} else {
				c.timeout = timeout
			}

		case DSNLocale:
			if len(v) == 0 {
				continue
			}
			c.locale = v[0]

		case DSNTLSServerName:
			if len(v) == 0 {
				continue
			}
			if c.tlsConfig == nil {
				c.tlsConfig = &tls.Config{}
			}
			c.tlsConfig.ServerName = v[0]

		case DSNTLSInsecureSkipVerify:
			if len(v) == 0 {
				continue
			}
			var err error
			b := true
			if v[0] != "" {
				b, err = strconv.ParseBool(v[0])
				if err != nil {
					return nil, fmt.Errorf("failed to parse InsecureSkipVerify (bool): %s", v[0])
				}
			}
			if c.tlsConfig == nil {
				c.tlsConfig = &tls.Config{}
			}
			c.tlsConfig.InsecureSkipVerify = b

		case DSNTLSRootCAFile:
			for _, fn := range v {
				rootPEM, err := ioutil.ReadFile(fn)
				if err != nil {
					return nil, err
				}
				if certPool == nil {
					certPool = x509.NewCertPool()
				}
				if ok := certPool.AppendCertsFromPEM(rootPEM); !ok {
					return nil, fmt.Errorf("failed to parse root certificate - filename: %s", fn)
				}
			}
			if certPool != nil {
				if c.tlsConfig == nil {
					c.tlsConfig = &tls.Config{}
				}
				c.tlsConfig.RootCAs = certPool
			}
		}
	}
	return c, nil
}
// NewDSNConnector creates a connector from a data source name.