featurebase/sql3/planner/compileshow.go
David Kagan c10762220a
renamed 2 system tables (#2310)
* renamed 2 system tables

* adding table column for types

* added a type field to fb_database_nodes system table

* updated ClusterNode struct

* adding backwards compatibility

this commit also adds support for ordering systemTables and implements the method

* fixed linting

---------

Co-authored-by: Travis Turner <travis@molecula.com>
2023-03-15 17:43:11 -05:00

271 lines
8.3 KiB
Go

// Copyright 2021 Molecula Corp. All rights reserved.
package planner
import (
"context"
"strings"
pilosa "github.com/featurebasedb/featurebase/v3"
"github.com/featurebasedb/featurebase/v3/dax"
"github.com/featurebasedb/featurebase/v3/sql3"
"github.com/featurebasedb/featurebase/v3/sql3/parser"
"github.com/featurebasedb/featurebase/v3/sql3/planner/types"
"github.com/pkg/errors"
)
func (p *ExecutionPlanner) compileShowDatabasesStatement(ctx context.Context, stmt parser.Statement) (types.PlanOperator, error) {
dbs, err := p.schemaAPI.Databases(ctx)
if err != nil {
return nil, errors.Wrap(err, "getting databases")
}
columns := []types.PlanExpression{
&qualifiedRefPlanExpression{
tableName: "fb_databases",
columnName: string(dax.PrimaryKeyFieldName),
columnIndex: 0,
dataType: parser.NewDataTypeString(),
},
&qualifiedRefPlanExpression{
tableName: "fb_databases",
columnName: "name",
columnIndex: 1,
dataType: parser.NewDataTypeString(),
},
&qualifiedRefPlanExpression{
tableName: "fb_databases",
columnName: "owner",
columnIndex: 2,
dataType: parser.NewDataTypeString(),
},
&qualifiedRefPlanExpression{
tableName: "fb_databases",
columnName: "updated_by",
columnIndex: 3,
dataType: parser.NewDataTypeString(),
},
&qualifiedRefPlanExpression{
tableName: "fb_databases",
columnName: "created_at",
columnIndex: 4,
dataType: parser.NewDataTypeTimestamp(),
},
&qualifiedRefPlanExpression{
tableName: "fb_databases",
columnName: "updated_at",
columnIndex: 5,
dataType: parser.NewDataTypeTimestamp(),
},
&qualifiedRefPlanExpression{
tableName: "fb_databases",
columnName: "units",
columnIndex: 6,
dataType: parser.NewDataTypeInt(),
},
&qualifiedRefPlanExpression{
tableName: "fb_databases",
columnName: "description",
columnIndex: 7,
dataType: parser.NewDataTypeString(),
}}
return NewPlanOpQuery(p, NewPlanOpProjection(columns, NewPlanOpFeatureBaseDatabases(p, dbs)), p.sql), nil
}
func (p *ExecutionPlanner) compileShowTablesStatement(ctx context.Context, stmt parser.Statement) (types.PlanOperator, error) {
tbls, err := p.schemaAPI.Tables(ctx)
if err != nil {
return nil, errors.Wrap(err, "getting tables")
}
columns := []types.PlanExpression{
&qualifiedRefPlanExpression{
tableName: "fb_tables",
columnName: string(dax.PrimaryKeyFieldName),
columnIndex: 0,
dataType: parser.NewDataTypeString(),
},
&qualifiedRefPlanExpression{
tableName: "fb_tables",
columnName: "name",
columnIndex: 1,
dataType: parser.NewDataTypeString(),
},
&qualifiedRefPlanExpression{
tableName: "fb_tables",
columnName: "owner",
columnIndex: 2,
dataType: parser.NewDataTypeString(),
},
&qualifiedRefPlanExpression{
tableName: "fb_tables",
columnName: "updated_by",
columnIndex: 3,
dataType: parser.NewDataTypeString(),
},
&qualifiedRefPlanExpression{
tableName: "fb_tables",
columnName: "created_at",
columnIndex: 4,
dataType: parser.NewDataTypeTimestamp(),
},
&qualifiedRefPlanExpression{
tableName: "fb_tables",
columnName: "updated_at",
columnIndex: 5,
dataType: parser.NewDataTypeTimestamp(),
},
&qualifiedRefPlanExpression{
tableName: "fb_tables",
columnName: "keys",
columnIndex: 6,
dataType: parser.NewDataTypeBool(),
},
&qualifiedRefPlanExpression{
tableName: "fb_tables",
columnName: "space_used",
columnIndex: 7,
dataType: parser.NewDataTypeInt(),
},
&qualifiedRefPlanExpression{
tableName: "fb_tables",
columnName: "description",
columnIndex: 8,
dataType: parser.NewDataTypeString(),
}}
return NewPlanOpQuery(p, NewPlanOpProjection(columns, NewPlanOpFeatureBaseTables(p, pilosa.TablesToIndexInfos(tbls))), p.sql), nil
}
func (p *ExecutionPlanner) compileShowColumnsStatement(ctx context.Context, stmt *parser.ShowColumnsStatement) (_ types.PlanOperator, err error) {
tableName := strings.ToLower(parser.IdentName(stmt.TableName))
tname := dax.TableName(tableName)
tbl, err := p.schemaAPI.TableByName(ctx, tname)
if err != nil {
if isTableNotFoundError(err) {
return nil, sql3.NewErrTableNotFound(stmt.TableName.NamePos.Line, stmt.TableName.NamePos.Column, tableName)
}
return nil, err
}
columns := []types.PlanExpression{&qualifiedRefPlanExpression{
tableName: "fb_table_columns",
columnName: string(dax.PrimaryKeyFieldName),
columnIndex: 0,
dataType: parser.NewDataTypeString(),
}, &qualifiedRefPlanExpression{
tableName: "fb_table_columns",
columnName: "name",
columnIndex: 1,
dataType: parser.NewDataTypeString(),
}, &qualifiedRefPlanExpression{
tableName: "fb_table_columns",
columnName: "type",
columnIndex: 2,
dataType: parser.NewDataTypeString(),
}, &qualifiedRefPlanExpression{
tableName: "fb_table_columns",
columnName: "created_at",
columnIndex: 3,
dataType: parser.NewDataTypeTimestamp(),
}, &qualifiedRefPlanExpression{
tableName: "fb_table_columns",
columnName: "keys",
columnIndex: 4,
dataType: parser.NewDataTypeBool(),
}, &qualifiedRefPlanExpression{
tableName: "fb_table_columns",
columnName: "cache_type",
columnIndex: 5,
dataType: parser.NewDataTypeString(),
}, &qualifiedRefPlanExpression{
tableName: "fb_table_columns",
columnName: "cache_size",
columnIndex: 6,
dataType: parser.NewDataTypeInt(),
}, &qualifiedRefPlanExpression{
tableName: "fb_table_columns",
columnName: "scale",
columnIndex: 7,
dataType: parser.NewDataTypeInt(),
}, &qualifiedRefPlanExpression{
tableName: "fb_table_columns",
columnName: "min",
columnIndex: 8,
dataType: parser.NewDataTypeInt(),
}, &qualifiedRefPlanExpression{
tableName: "fb_table_columns",
columnName: "max",
columnIndex: 9,
dataType: parser.NewDataTypeInt(),
}, &qualifiedRefPlanExpression{
tableName: "fb_table_columns",
columnName: "timeunit",
columnIndex: 10,
dataType: parser.NewDataTypeString(),
}, &qualifiedRefPlanExpression{
tableName: "fb_table_columns",
columnName: "epoch",
columnIndex: 11,
dataType: parser.NewDataTypeInt(),
}, &qualifiedRefPlanExpression{
tableName: "fb_table_columns",
columnName: "timequantum",
columnIndex: 12,
dataType: parser.NewDataTypeString(),
}, &qualifiedRefPlanExpression{
tableName: "fb_table_columns",
columnName: "ttl",
columnIndex: 13,
dataType: parser.NewDataTypeString(),
}}
return NewPlanOpQuery(p, NewPlanOpProjection(columns, NewPlanOpFeatureBaseColumns(tbl)), p.sql), nil
}
func (p *ExecutionPlanner) compileShowCreateTableStatement(ctx context.Context, stmt *parser.ShowCreateTableStatement) (_ types.PlanOperator, err error) {
tableName := strings.ToLower(parser.IdentName(stmt.TableName))
tname := dax.TableName(tableName)
if _, err := p.schemaAPI.TableByName(ctx, tname); err != nil {
if isTableNotFoundError(err) {
return nil, sql3.NewErrTableNotFound(stmt.TableName.NamePos.Line, stmt.TableName.NamePos.Column, tableName)
}
return nil, err
}
// get the system table
systemTable, ok := systemTables.table(fbTableDDL)
if !ok {
return nil, sql3.NewErrInternalf("unable to find system table fb_table_ddl")
}
// make an op for the system table
systemTableScan := NewPlanOpSystemTable(p, systemTable)
// get the columns from the schmema
columns := systemTable.schema
// get the ref name column and build projections
projections := make([]types.PlanExpression, 0)
var nameRef *qualifiedRefPlanExpression
for idx, col := range columns {
if strings.EqualFold(col.ColumnName, "name") {
nameRef = newQualifiedRefPlanExpression(col.RelationName, col.ColumnName, idx, col.Type)
}
if strings.EqualFold(col.ColumnName, "ddl") {
projections = append(projections, newQualifiedRefPlanExpression(col.RelationName, col.ColumnName, idx, col.Type))
}
}
if nameRef == nil || len(projections) == 0 {
return nil, sql3.NewErrInternalf("unable to find system table columns")
}
// make a filter espression
filterExpr := newBinOpPlanExpression(nameRef, parser.EQ, newStringLiteralPlanExpression(tableName), parser.NewDataTypeBool())
// make a filter op
filter := NewPlanOpFilter(p, filterExpr, systemTableScan)
return NewPlanOpQuery(p, NewPlanOpProjection(projections, filter), p.sql), nil
}