...
1 package sqlcon
2
3 import (
4 "fmt"
5 "net/url"
6 "strconv"
7 "strings"
8 "time"
9
10 "github.com/ory/x/logrusx"
11 )
12
13
14
15 func ParseConnectionOptions(l *logrusx.Logger, dsn string) (maxConns int, maxIdleConns int, maxConnLifetime time.Duration, cleanedDSN string) {
16 maxConns = maxParallelism() * 2
17 maxIdleConns = maxParallelism()
18 maxConnLifetime = time.Duration(0)
19 cleanedDSN = dsn
20
21 parts := strings.Split(dsn, "?")
22 if len(parts) != 2 {
23 l.
24 WithField("sql_max_connections", maxConns).
25 WithField("sql_max_idle_connections", maxIdleConns).
26 WithField("sql_max_connection_lifetime", maxConnLifetime).
27 Debugf("No SQL connection options have been defined, falling back to default connection options.")
28 return
29 }
30
31 query, err := url.ParseQuery(parts[1])
32 if err != nil {
33 l.
34 WithField("sql_max_connections", maxConns).
35 WithField("sql_max_idle_connections", maxIdleConns).
36 WithField("sql_max_connection_lifetime", maxConnLifetime).
37 WithError(err).
38 Warnf("Unable to parse SQL DSN query, falling back to default connection options.")
39 return
40 }
41
42 if v := query.Get("max_conns"); v != "" {
43 s, err := strconv.ParseInt(v, 10, 64)
44 if err != nil {
45 l.WithError(err).Warnf(`SQL DSN query parameter "max_conns" value %v could not be parsed to int, falling back to default value %d`, v, maxConns)
46 } else {
47 maxConns = int(s)
48 }
49 query.Del("max_conns")
50 }
51
52 if v := query.Get("max_idle_conns"); v != "" {
53 s, err := strconv.ParseInt(v, 10, 64)
54 if err != nil {
55 l.WithError(err).Warnf(`SQL DSN query parameter "max_idle_conns" value %v could not be parsed to int, falling back to default value %d`, v, maxIdleConns)
56 } else {
57 maxIdleConns = int(s)
58 }
59 query.Del("max_idle_conns")
60 }
61
62 if v := query.Get("max_conn_lifetime"); v != "" {
63 s, err := time.ParseDuration(v)
64 if err != nil {
65 l.WithError(err).Warnf(`SQL DSN query parameter "max_conn_lifetime" value %v could not be parsed to duration, falling back to default value %d`, v, maxConnLifetime)
66 } else {
67 maxConnLifetime = s
68 }
69 query.Del("max_conn_lifetime")
70 }
71 cleanedDSN = fmt.Sprintf("%s?%s", parts[0], query.Encode())
72
73 return
74 }
75
76
77 func FinalizeDSN(l *logrusx.Logger, dsn string) string {
78 if strings.HasPrefix(dsn, "mysql://") {
79 var q url.Values
80 parts := strings.SplitN(dsn, "?", 2)
81
82 if len(parts) == 1 {
83 q = make(url.Values)
84 } else {
85 var err error
86 q, err = url.ParseQuery(parts[1])
87 if err != nil {
88 l.WithError(err).Warnf("Unable to parse SQL DSN query, could not finalize the DSN URI.")
89 return dsn
90 }
91 }
92
93 q.Set("multiStatements", "true")
94 q.Set("parseTime", "true")
95
96 return fmt.Sprintf("%s?%s", parts[0], q.Encode())
97 }
98
99 return dsn
100 }
101
View as plain text