Files
chaisql/internal/stream/path/rename.go
2024-02-17 17:56:41 +04:00

95 lines
2.3 KiB
Go

package path
import (
"fmt"
"strings"
"github.com/chaisql/chai/internal/database"
"github.com/chaisql/chai/internal/environment"
"github.com/chaisql/chai/internal/row"
"github.com/chaisql/chai/internal/stream"
"github.com/chaisql/chai/internal/types"
"github.com/cockroachdb/errors"
)
// An RenameOperator iterates over all columns of the incoming row in order and renames them.
type RenameOperator struct {
stream.BaseOperator
ColumnNames []string
}
// PathsRename iterates over all columns of the incoming row in order and renames them.
// If the number of columns of the incoming row doesn't match the number of expected columns,
// it returns an error.
func PathsRename(columnNames ...string) *RenameOperator {
return &RenameOperator{
ColumnNames: columnNames,
}
}
func (op *RenameOperator) Clone() stream.Operator {
return &RenameOperator{
BaseOperator: op.BaseOperator.Clone(),
// No need to clone the column names, they are immutable.
ColumnNames: op.ColumnNames,
}
}
// Iterate implements the Operator interface.
func (op *RenameOperator) Iterate(in *environment.Environment, f func(out *environment.Environment) error) error {
var cb row.ColumnBuffer
var newEnv environment.Environment
var br database.BasicRow
return op.Prev.Iterate(in, func(out *environment.Environment) error {
cb.Reset()
r, ok := out.GetRow()
if !ok {
return errors.New("missing row")
}
var i int
err := r.Iterate(func(field string, value types.Value) error {
// if there are too many columns in the incoming row
if i >= len(op.ColumnNames) {
n, err := row.Length(r)
if err != nil {
return err
}
return fmt.Errorf("%d values for %d columns", n, len(op.ColumnNames))
}
cb.Add(op.ColumnNames[i], value)
i++
return nil
})
if err != nil {
return err
}
// if there are too few columns in the incoming row
if i < len(op.ColumnNames) {
n, err := row.Length(r)
if err != nil {
return err
}
return fmt.Errorf("%d values for %d columns", n, len(op.ColumnNames))
}
newEnv.SetOuter(out)
if dr, ok := r.(database.Row); ok {
br.ResetWith(dr.TableName(), dr.Key(), &cb)
newEnv.SetRow(&br)
} else {
newEnv.SetRow(&cb)
}
return f(&newEnv)
})
}
func (op *RenameOperator) String() string {
return fmt.Sprintf("paths.Rename(%s)", strings.Join(op.ColumnNames, ", "))
}