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  }