mirror of
https://github.com/chaisql/chai.git
synced 2025-10-21 14:49:26 +08:00
95 lines
2.3 KiB
Go
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, ", "))
|
|
}
|