github.com/mithrandie/csvq@v1.18.1/lib/action/calc.go (about)

     1  package action
     2  
     3  import (
     4  	"context"
     5  	"errors"
     6  	"strings"
     7  
     8  	"github.com/mithrandie/csvq/lib/option"
     9  	"github.com/mithrandie/csvq/lib/parser"
    10  	"github.com/mithrandie/csvq/lib/query"
    11  )
    12  
    13  func Calc(ctx context.Context, proc *query.Processor, expr string) error {
    14  	_ = proc.Tx.SetFlag(option.NoHeaderFlag, true)
    15  	q := "SELECT " + expr + " FROM STDIN"
    16  
    17  	program, _, err := parser.Parse(q, "", false, proc.Tx.Flags.AnsiQuotes)
    18  	if err != nil {
    19  		e := err.(*parser.SyntaxError)
    20  		e.SourceFile = ""
    21  		e.Line = 0
    22  		e.Char = 0
    23  		e.Message = "syntax error"
    24  		return query.NewSyntaxError(e)
    25  	}
    26  	selectEntity, _ := program[0].(parser.SelectQuery).SelectEntity.(parser.SelectEntity)
    27  
    28  	scope := query.NewReferenceScope(proc.Tx)
    29  	queryScope := scope.CreateNode()
    30  
    31  	view, err := query.LoadView(ctx, queryScope, selectEntity.FromClause.(parser.FromClause).Tables, false, false)
    32  	if err != nil {
    33  		if appErr, ok := err.(query.Error); ok {
    34  			err = errors.New(appErr.Message())
    35  		}
    36  		return err
    37  	}
    38  
    39  	clause := selectEntity.SelectClause.(parser.SelectClause)
    40  
    41  	recordScope := scope.CreateScopeForRecordEvaluation(view, 0)
    42  	values := make([]string, len(clause.Fields))
    43  	for i, v := range clause.Fields {
    44  		field := v.(parser.Field)
    45  		p, err := query.Evaluate(ctx, recordScope, field.Object)
    46  		if err != nil {
    47  			if appErr, ok := err.(query.Error); ok {
    48  				err = errors.New(appErr.Message())
    49  			}
    50  			return err
    51  		}
    52  		values[i], _, _ = query.ConvertFieldContents(p, true, proc.Tx.Flags.ExportOptions.ScientificNotation)
    53  	}
    54  
    55  	return proc.Tx.Session.WriteToStdout(strings.Join(values, string(proc.Tx.Flags.ExportOptions.Delimiter)))
    56  }