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
+}