view pkg/xlsx/sql.go @ 5415:4ad68ab239b7 marking-single-beam

Factored creation of default class breaks in SR import to be reused with markings, too.
author Sascha L. Teichmann <sascha.teichmann@intevation.de>
date Wed, 07 Jul 2021 12:01:28 +0200
parents 979f139cde4d
children 6270951dda28
line wrap: on
line source

// 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"
	"fmt"
	"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 + 1
			}
		}
		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,
	tx *sql.Tx,
	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 := tx.QueryContext(ctx, nstmt, args...)
	if err != nil {
		return nil, fmt.Errorf("SQL failed: '%s': %v", nstmt, 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
}