1/* 2** Zabbix 3** Copyright (C) 2001-2021 Zabbix SIA 4** 5** This program is free software; you can redistribute it and/or modify 6** it under the terms of the GNU General Public License as published by 7** the Free Software Foundation; either version 2 of the License, or 8** (at your option) any later version. 9** 10** This program is distributed in the hope that it will be useful, 11** but WITHOUT ANY WARRANTY; without even the implied warranty of 12** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13** GNU General Public License for more details. 14** 15** You should have received a copy of the GNU General Public License 16** along with this program; if not, write to the Free Software 17** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 18**/ 19 20package postgres 21 22import ( 23 "context" 24 "encoding/json" 25 "errors" 26 "strings" 27 28 "github.com/jackc/pgx/v4" 29 "zabbix.com/pkg/zbxerr" 30) 31 32// customQueryHandler executes custom user queries from *.sql files. 33func customQueryHandler(ctx context.Context, conn PostgresClient, 34 _ string, params map[string]string, extraParams ...string) (interface{}, error) { 35 queryName := params["QueryName"] 36 37 queryArgs := make([]interface{}, len(extraParams)) 38 for i, v := range extraParams { 39 queryArgs[i] = v 40 } 41 42 rows, err := conn.QueryByName(ctx, queryName, queryArgs...) 43 if err != nil { 44 return nil, zbxerr.ErrorCannotFetchData.Wrap(err) 45 } 46 defer rows.Close() 47 48 // JSON marshaling 49 var data []string 50 51 columns, err := rows.Columns() 52 if err != nil { 53 return nil, zbxerr.ErrorCannotFetchData.Wrap(err) 54 } 55 56 values := make([]interface{}, len(columns)) 57 valuePointers := make([]interface{}, len(values)) 58 59 for i := range values { 60 valuePointers[i] = &values[i] 61 } 62 63 results := make(map[string]interface{}) 64 65 for rows.Next() { 66 err = rows.Scan(valuePointers...) 67 if err != nil { 68 if errors.Is(err, pgx.ErrNoRows) { 69 return nil, zbxerr.ErrorEmptyResult.Wrap(err) 70 } 71 72 return nil, zbxerr.ErrorCannotFetchData.Wrap(err) 73 } 74 75 for i, value := range values { 76 results[columns[i]] = value 77 } 78 79 jsonRes, _ := json.Marshal(results) 80 data = append(data, strings.TrimSpace(string(jsonRes))) 81 } 82 83 // Any errors encountered by rows.Next or rows.Scan will be returned here 84 if rows.Err() != nil { 85 return nil, err 86 } 87 88 return "[" + strings.Join(data, ",") + "]", nil 89} 90