Mercurial > gemma
diff pkg/xlsx/sql.go @ 5321:0919946f624b extented-report
Added a report controller.
author | Sascha L. Teichmann <sascha.teichmann@intevation.de> |
---|---|
date | Thu, 27 May 2021 01:22:10 +0200 |
parents | |
children | 6c0f40676984 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pkg/xlsx/sql.go Thu May 27 01:22:10 2021 +0200 @@ -0,0 +1,109 @@ +// This is Free Software under GNU Affero General Public License v >= 3.0 +// without warranty, see README.md and license for details. +// +// SPDX-License-Identifier: AGPL-3.0-or-later +// License-Filename: LICENSES/AGPL-3.0.txt +// +// Copyright (C) 2021 by via donau +// – Österreichische Wasserstraßen-Gesellschaft mbH +// Software engineering by Intevation GmbH +// +// Author(s): +// * Sascha L. Teichmann <sascha.teichmann@intevation.de> + +package xlsx + +import ( + "context" + "database/sql" + "strconv" + "strings" +) + +type sqlResult struct { + columns []string + rows [][]interface{} +} + +func (sr *sqlResult) find(column string) int { + for i, name := range sr.columns { + if name == column { + return i + } + } + return -1 +} + +func replaceStmt(stmt string) (string, []string) { + + var names []string + + add := func(name string) int { + for i, n := range names { + if n == name { + return i + } + } + names = append(names, name) + return len(names) + } + + replace := func(s string) string { + n := add(strings.TrimSpace(s)) + return "$" + strconv.Itoa(n) + } + + out := handlebars(stmt, replace) + return out, names +} + +func query( + ctx context.Context, + db *sql.Conn, + stmt string, + eval func(string) (interface{}, error), +) (*sqlResult, error) { + + nstmt, nargs := replaceStmt(stmt) + args := make([]interface{}, len(nargs)) + for i, n := range nargs { + var err error + if args[i], err = eval(n); err != nil { + return nil, err + } + } + + rs, err := db.QueryContext(ctx, nstmt, args...) + if err != nil { + return nil, err + } + defer rs.Close() + + columns, err := rs.Columns() + if err != nil { + return nil, err + } + var rows [][]interface{} + + ptrs := make([]interface{}, len(columns)) + + for rs.Next() { + row := make([]interface{}, len(columns)) + for i := range row { + ptrs[i] = &row[i] + } + if err := rs.Scan(ptrs...); err != nil { + return nil, err + } + rows = append(rows, row) + } + + if err := rs.Err(); err != nil { + return nil, err + } + + return &sqlResult{ + columns: columns, + rows: rows, + }, nil +}