github.com/netdata/go.d.plugin@v0.58.1/modules/postgres/do_query_misc.go (about) 1 // SPDX-License-Identifier: GPL-3.0-or-later 2 3 package postgres 4 5 import ( 6 "database/sql" 7 "strconv" 8 9 "github.com/jackc/pgx/v4/stdlib" 10 ) 11 12 func (p *Postgres) doQueryServerVersion() (int, error) { 13 q := queryServerVersion() 14 15 var s string 16 if err := p.doQueryRow(q, &s); err != nil { 17 return 0, err 18 } 19 20 return strconv.Atoi(s) 21 } 22 23 func (p *Postgres) doQueryIsSuperUser() (bool, error) { 24 q := queryIsSuperUser() 25 26 var v bool 27 if err := p.doQueryRow(q, &v); err != nil { 28 return false, err 29 } 30 31 return v, nil 32 } 33 34 func (p *Postgres) doQueryPGIsInRecovery() (bool, error) { 35 q := queryPGIsInRecovery() 36 37 var v bool 38 if err := p.doQueryRow(q, &v); err != nil { 39 return false, err 40 } 41 42 return v, nil 43 } 44 45 func (p *Postgres) doQuerySettingsMaxConnections() (int64, error) { 46 q := querySettingsMaxConnections() 47 48 var s string 49 if err := p.doQueryRow(q, &s); err != nil { 50 return 0, err 51 } 52 53 return strconv.ParseInt(s, 10, 64) 54 } 55 56 func (p *Postgres) doQuerySettingsMaxLocksHeld() (int64, error) { 57 q := querySettingsMaxLocksHeld() 58 59 var s string 60 if err := p.doQueryRow(q, &s); err != nil { 61 return 0, err 62 } 63 64 return strconv.ParseInt(s, 10, 64) 65 } 66 67 const connErrMax = 3 68 69 func (p *Postgres) doQueryQueryableDatabases() error { 70 q := queryQueryableDatabaseList() 71 72 var dbs []string 73 err := p.doQuery(q, func(_, value string, _ bool) { 74 if p.dbSr != nil && p.dbSr.MatchString(value) { 75 dbs = append(dbs, value) 76 } 77 }) 78 if err != nil { 79 return err 80 } 81 82 seen := make(map[string]bool, len(dbs)) 83 84 for _, dbname := range dbs { 85 seen[dbname] = true 86 87 conn, ok := p.dbConns[dbname] 88 if !ok { 89 conn = &dbConn{} 90 p.dbConns[dbname] = conn 91 } 92 93 if conn.db != nil || conn.connErrors >= connErrMax { 94 continue 95 } 96 97 db, connStr, err := p.openSecondaryConnection(dbname) 98 if err != nil { 99 p.Warning(err) 100 conn.connErrors++ 101 continue 102 } 103 104 tables, err := p.doDBQueryUserTablesCount(db) 105 if err != nil { 106 p.Warning(err) 107 conn.connErrors++ 108 _ = db.Close() 109 stdlib.UnregisterConnConfig(connStr) 110 continue 111 } 112 113 indexes, err := p.doDBQueryUserIndexesCount(db) 114 if err != nil { 115 p.Warning(err) 116 conn.connErrors++ 117 _ = db.Close() 118 stdlib.UnregisterConnConfig(connStr) 119 continue 120 } 121 122 if (p.MaxDBTables != 0 && tables > p.MaxDBTables) || (p.MaxDBIndexes != 0 && indexes > p.MaxDBIndexes) { 123 p.Warningf("database '%s' has too many user tables(%d/%d)/indexes(%d/%d), skipping it", 124 dbname, tables, p.MaxDBTables, indexes, p.MaxDBIndexes) 125 conn.connErrors = connErrMax 126 _ = db.Close() 127 stdlib.UnregisterConnConfig(connStr) 128 continue 129 } 130 131 conn.db, conn.connStr = db, connStr 132 } 133 134 for dbname, conn := range p.dbConns { 135 if seen[dbname] { 136 continue 137 } 138 delete(p.dbConns, dbname) 139 if conn.connStr != "" { 140 stdlib.UnregisterConnConfig(conn.connStr) 141 } 142 if conn.db != nil { 143 _ = conn.db.Close() 144 } 145 } 146 147 return nil 148 } 149 150 func (p *Postgres) doDBQueryUserTablesCount(db *sql.DB) (int64, error) { 151 q := queryUserTablesCount() 152 153 var v string 154 if err := p.doDBQueryRow(db, q, &v); err != nil { 155 return 0, err 156 } 157 158 return parseInt(v), nil 159 } 160 161 func (p *Postgres) doDBQueryUserIndexesCount(db *sql.DB) (int64, error) { 162 q := queryUserIndexesCount() 163 164 var v string 165 if err := p.doDBQueryRow(db, q, &v); err != nil { 166 return 0, err 167 } 168 169 return parseInt(v), nil 170 }