mirror of
https://github.com/featurebasedb/featurebase.git
synced 2026-08-28 02:44:59 +00:00
The attempt to set the TrackExistence option for fields happened before checking whether the field was created successfully or not. Credit to Rachith for spotting this. Bug was introduced with the TrackExistence stuff, but we apparently never had a test case for invalid min/max values.
118 lines
3 KiB
Go
118 lines
3 KiB
Go
// Copyright 2021 Molecula Corp. All rights reserved.
|
|
|
|
package planner
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
|
|
pilosa "github.com/featurebasedb/featurebase/v3"
|
|
"github.com/featurebasedb/featurebase/v3/dax"
|
|
"github.com/featurebasedb/featurebase/v3/sql3"
|
|
"github.com/featurebasedb/featurebase/v3/sql3/planner/types"
|
|
)
|
|
|
|
// PlanOpAlterTable plan operator to alter a table.
|
|
type PlanOpAlterTable struct {
|
|
planner *ExecutionPlanner
|
|
tableName string
|
|
operation alterOperation
|
|
oldColumnName string
|
|
newColumnName string
|
|
columnDef *createTableField
|
|
warnings []string
|
|
}
|
|
|
|
func NewPlanOpAlterTable(p *ExecutionPlanner, tableName string, operation alterOperation, oldColumnName string, newColumnName string, columnDef *createTableField) *PlanOpAlterTable {
|
|
return &PlanOpAlterTable{
|
|
planner: p,
|
|
tableName: tableName,
|
|
operation: operation,
|
|
oldColumnName: oldColumnName,
|
|
newColumnName: newColumnName,
|
|
columnDef: columnDef,
|
|
warnings: make([]string, 0),
|
|
}
|
|
}
|
|
|
|
func (p *PlanOpAlterTable) Plan() map[string]interface{} {
|
|
result := make(map[string]interface{})
|
|
result["_op"] = fmt.Sprintf("%T", p)
|
|
result["tableName"] = p.tableName
|
|
return result
|
|
}
|
|
|
|
func (p *PlanOpAlterTable) AddWarning(warning string) {
|
|
p.warnings = append(p.warnings, warning)
|
|
}
|
|
|
|
func (p *PlanOpAlterTable) Warnings() []string {
|
|
return p.warnings
|
|
}
|
|
|
|
func (p *PlanOpAlterTable) String() string {
|
|
return ""
|
|
}
|
|
|
|
func (p *PlanOpAlterTable) Schema() types.Schema {
|
|
return types.Schema{}
|
|
}
|
|
|
|
func (p *PlanOpAlterTable) Children() []types.PlanOperator {
|
|
return []types.PlanOperator{}
|
|
}
|
|
|
|
func (p *PlanOpAlterTable) Iterator(ctx context.Context, row types.Row) (types.RowIterator, error) {
|
|
return &alterTableRowIter{
|
|
planner: p.planner,
|
|
operation: p.operation,
|
|
tableName: p.tableName,
|
|
columnDef: p.columnDef,
|
|
oldColumnName: p.oldColumnName,
|
|
}, nil
|
|
}
|
|
|
|
func (p *PlanOpAlterTable) WithChildren(children ...types.PlanOperator) (types.PlanOperator, error) {
|
|
return nil, nil
|
|
}
|
|
|
|
type alterTableRowIter struct {
|
|
planner *ExecutionPlanner
|
|
operation alterOperation
|
|
tableName string
|
|
columnDef *createTableField
|
|
oldColumnName string
|
|
}
|
|
|
|
var _ types.RowIterator = (*alterTableRowIter)(nil)
|
|
|
|
func (i *alterTableRowIter) Next(ctx context.Context) (types.Row, error) {
|
|
switch i.operation {
|
|
case alterOpAdd:
|
|
tname := dax.TableName(i.tableName)
|
|
fname := dax.FieldName(i.columnDef.name)
|
|
fos := i.columnDef.fos
|
|
|
|
fld, err := pilosa.FieldFromFieldOptions(fname, fos...)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
// all newly created fields unconditionally have TrackExistence turned on.
|
|
fld.Options.TrackExistence = true
|
|
|
|
if err := i.planner.schemaAPI.CreateField(ctx, tname, fld); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
case alterOpDrop:
|
|
err := i.planner.schemaAPI.DeleteField(ctx, dax.TableName(i.tableName), dax.FieldName(i.oldColumnName))
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
case alterOpRename:
|
|
return nil, sql3.NewErrInternal("column rename is unimplemented")
|
|
|
|
}
|
|
return nil, types.ErrNoMoreRows
|
|
}
|