diff --git a/api.go b/api.go index ccc984558..74dd32532 100644 --- a/api.go +++ b/api.go @@ -3377,6 +3377,7 @@ func (n *NopSchemaAPI) DeleteField(ctx context.Context, tname dax.TableName, fna type ClusterNode struct { ID string + Type string State string URI string GRPCURI string diff --git a/sql3/planner/compileselect.go b/sql3/planner/compileselect.go index ddecdfd20..168f9401c 100644 --- a/sql3/planner/compileselect.go +++ b/sql3/planner/compileselect.go @@ -406,7 +406,7 @@ func (p *ExecutionPlanner) compileSource(scope *PlanOpQuery, source parser.Sourc tableName := strings.ToLower(parser.IdentName(sourceExpr.Name)) // doing this check here because we don't have a 'system' flag that exists in the FB schema - st, ok := systemTables[tableName] + st, ok := systemTables.table(tableName) if ok { var op types.PlanOperator op = NewPlanOpSystemTable(p, st) diff --git a/sql3/planner/compileshow.go b/sql3/planner/compileshow.go index 5fd14bbd0..b70aa6129 100644 --- a/sql3/planner/compileshow.go +++ b/sql3/planner/compileshow.go @@ -235,7 +235,7 @@ func (p *ExecutionPlanner) compileShowCreateTableStatement(ctx context.Context, } // get the system table - systemTable, ok := systemTables[fbTableDDL] + systemTable, ok := systemTables.table(fbTableDDL) if !ok { return nil, sql3.NewErrInternalf("unable to find system table fb_table_ddl") } diff --git a/sql3/planner/executionplannersystemtables.go b/sql3/planner/executionplannersystemtables.go index db263ce57..da8338047 100644 --- a/sql3/planner/executionplannersystemtables.go +++ b/sql3/planner/executionplannersystemtables.go @@ -50,7 +50,7 @@ func (s *systemTableDefinitionsWrapper) TableByName(ctx context.Context, tname d tbl, err := s.schemaAPI.TableByName(ctx, tname) if err != nil { if isTableNotFoundError(err) { - st, ok := systemTables[string(tname)] + st, ok := systemTables.table(string(tname)) if !ok { return nil, dax.NewErrTableNameDoesNotExist(tname) } @@ -73,10 +73,10 @@ func (s *systemTableDefinitionsWrapper) Tables(ctx context.Context) ([]*dax.Tabl } // Append the system tables. - for tblName, st := range systemTables { + for _, st := range systemTables.ordered() { ii, err := indexInfoFromSystemTable(st) if err != nil { - return nil, errors.Wrapf(err, "converting system table to table: %s", tblName) + return nil, errors.Wrapf(err, "converting system table to table: %s", st.name) } tbls = append(tbls, pilosa.IndexInfoToTable(ii)) } diff --git a/sql3/planner/opfeaturebasetables.go b/sql3/planner/opfeaturebasetables.go index 0e439f0f0..00ea42b98 100644 --- a/sql3/planner/opfeaturebasetables.go +++ b/sql3/planner/opfeaturebasetables.go @@ -130,7 +130,7 @@ func (i *showTablesRowIter) Next(ctx context.Context) (types.Row, error) { var err error var spaceUsed pilosa.DiskUsage switch strings.ToLower(indexName) { - case "fb_cluster_info", "fb_cluster_nodes", "fb_performance_counters", "fb_exec_requests", "fb_table_ddl": + case fbDatabaseInfo, fbDatabaseNodes, fbPerformanceCounters, fbExecRequests, fbTableDDL: spaceUsed = pilosa.DiskUsage{ Usage: 0, } diff --git a/sql3/planner/opsystemtable.go b/sql3/planner/opsystemtable.go index 2f5c0f91c..c6c2c74f4 100644 --- a/sql3/planner/opsystemtable.go +++ b/sql3/planner/opsystemtable.go @@ -6,6 +6,7 @@ import ( "bytes" "context" "fmt" + "sort" pilosa "github.com/featurebasedb/featurebase/v3" "github.com/featurebasedb/featurebase/v3/pql" @@ -17,11 +18,14 @@ import ( // exclude this file from SonarCloud dupe eval const ( - fbClusterInfo = "fb_cluster_info" - fbClusterNodes = "fb_cluster_nodes" + fbDatabaseInfo = "fb_database_info" + fbDatabaseNodes = "fb_database_nodes" fbExecRequests = "fb_exec_requests" fbPerformanceCounters = "fb_performance_counters" + fbClusterInfo = "fb_cluster_info" + fbClusterNodes = "fb_cluster_nodes" + fbTableDDL = "fb_table_ddl" ) @@ -31,83 +35,117 @@ type systemTable struct { requiresFanout bool } -var systemTables = map[string]*systemTable{ - fbClusterInfo: { - name: fbClusterInfo, +type systemTableMap map[string]*systemTable + +// table enables backwards compatibility with changing the system table names +// from fb_cluster_nodes and fb_cluster_info to fb_database_nodes and fb_database_info +// respectively. +func (s systemTableMap) table(name string) (*systemTable, bool) { + switch name { + case fbClusterInfo: + name = fbDatabaseInfo + case fbClusterNodes: + name = fbDatabaseNodes + } + + t, ok := s[name] + return t, ok +} + +// ordered returns the map as an ordered slice of systemTable. +func (s systemTableMap) ordered() []*systemTable { + out := make([]*systemTable, 0, len(s)) + for _, v := range s { + out = append(out, v) + } + sort.Slice(out, func(i, j int) bool { + return out[i].name < out[j].name + }) + return out +} + +var systemTables = systemTableMap{ + fbDatabaseInfo: { + name: fbDatabaseInfo, schema: types.Schema{ &types.PlannerColumn{ - RelationName: fbClusterInfo, + RelationName: fbDatabaseInfo, ColumnName: "id", Type: parser.NewDataTypeString(), }, &types.PlannerColumn{ - RelationName: fbClusterInfo, + RelationName: fbDatabaseInfo, ColumnName: "name", Type: parser.NewDataTypeString(), }, &types.PlannerColumn{ - RelationName: fbClusterInfo, + RelationName: fbDatabaseInfo, ColumnName: "platform", Type: parser.NewDataTypeString(), }, &types.PlannerColumn{ - RelationName: fbClusterInfo, + RelationName: fbDatabaseInfo, ColumnName: "platform_version", Type: parser.NewDataTypeString(), }, &types.PlannerColumn{ - RelationName: fbClusterInfo, + RelationName: fbDatabaseInfo, ColumnName: "db_version", Type: parser.NewDataTypeString(), }, &types.PlannerColumn{ - RelationName: fbClusterInfo, + RelationName: fbDatabaseInfo, ColumnName: "state", Type: parser.NewDataTypeString(), }, &types.PlannerColumn{ - RelationName: fbClusterInfo, + RelationName: fbDatabaseInfo, ColumnName: "node_count", Type: parser.NewDataTypeInt(), }, &types.PlannerColumn{ - RelationName: fbClusterInfo, + RelationName: fbDatabaseInfo, ColumnName: "replica_count", Type: parser.NewDataTypeInt(), }, }, requiresFanout: false, }, - fbClusterNodes: { - name: fbClusterNodes, + fbDatabaseNodes: { + name: fbDatabaseNodes, schema: types.Schema{ &types.PlannerColumn{ - RelationName: fbClusterNodes, + RelationName: fbDatabaseNodes, ColumnName: "id", Type: parser.NewDataTypeString(), }, &types.PlannerColumn{ - RelationName: fbClusterNodes, + RelationName: fbDatabaseNodes, + ColumnName: "type", + Type: parser.NewDataTypeString(), + }, + &types.PlannerColumn{ + RelationName: fbDatabaseNodes, ColumnName: "state", Type: parser.NewDataTypeString(), }, &types.PlannerColumn{ - RelationName: fbClusterNodes, + RelationName: fbDatabaseNodes, ColumnName: "uri", Type: parser.NewDataTypeString(), }, &types.PlannerColumn{ - RelationName: fbClusterNodes, + RelationName: fbDatabaseNodes, ColumnName: "grpc_uri", Type: parser.NewDataTypeString(), }, &types.PlannerColumn{ - RelationName: fbClusterNodes, + RelationName: fbDatabaseNodes, ColumnName: "is_primary", Type: parser.NewDataTypeBool(), }, &types.PlannerColumn{ - RelationName: fbClusterNodes, + RelationName: fbDatabaseNodes, ColumnName: "space_used", Type: parser.NewDataTypeInt(), }, @@ -311,12 +349,12 @@ func (p *PlanOpSystemTable) Children() []types.PlanOperator { func (p *PlanOpSystemTable) Iterator(ctx context.Context, row types.Row) (types.RowIterator, error) { switch p.table.name { - case fbClusterInfo: - return &fbClusterInfoRowIter{ + case fbDatabaseInfo: + return &fbDatabaseInfoRowIter{ planner: p.planner, }, nil - case fbClusterNodes: - return &fbClusterNodesRowIter{ + case fbDatabaseNodes: + return &fbDatabaseNodesRowIter{ planner: p.planner, }, nil case fbExecRequests: @@ -343,14 +381,14 @@ func (p *PlanOpSystemTable) WithChildren(children ...types.PlanOperator) (types. return NewPlanOpSystemTable(p.planner, p.table), nil } -type fbClusterInfoRowIter struct { +type fbDatabaseInfoRowIter struct { planner *ExecutionPlanner rowIndex int } -var _ types.RowIterator = (*fbClusterInfoRowIter)(nil) +var _ types.RowIterator = (*fbDatabaseInfoRowIter)(nil) -func (i *fbClusterInfoRowIter) Next(ctx context.Context) (types.Row, error) { +func (i *fbDatabaseInfoRowIter) Next(ctx context.Context) (types.Row, error) { if i.rowIndex < 1 { row := []interface{}{ i.planner.systemAPI.ClusterName(), @@ -368,14 +406,14 @@ func (i *fbClusterInfoRowIter) Next(ctx context.Context) (types.Row, error) { return nil, types.ErrNoMoreRows } -type fbClusterNodesRowIter struct { +type fbDatabaseNodesRowIter struct { planner *ExecutionPlanner result []pilosa.ClusterNode } -var _ types.RowIterator = (*fbClusterNodesRowIter)(nil) +var _ types.RowIterator = (*fbDatabaseNodesRowIter)(nil) -func (i *fbClusterNodesRowIter) Next(ctx context.Context) (types.Row, error) { +func (i *fbDatabaseNodesRowIter) Next(ctx context.Context) (types.Row, error) { if i.result == nil { i.result = i.planner.systemAPI.ClusterNodes() } @@ -390,6 +428,7 @@ func (i *fbClusterNodesRowIter) Next(ctx context.Context) (types.Row, error) { n := i.result[0] row := []interface{}{ n.ID, + n.Type, n.State, n.URI, n.GRPCURI, diff --git a/sql3/planner/wireprotocol.go b/sql3/planner/wireprotocol.go index b43a90fb2..888342996 100644 --- a/sql3/planner/wireprotocol.go +++ b/sql3/planner/wireprotocol.go @@ -105,7 +105,7 @@ func newMessagePlanOp(p *ExecutionPlanner, reader io.Reader) (*messagePlanOp, er } name := string(bname) - st, ok := systemTables[name] + st, ok := systemTables.table(name) if !ok { return nil, sql3.NewErrInternalf("unexpected system table name %s", name) } diff --git a/sql3/sql_complex_test.go b/sql3/sql_complex_test.go index ab9568895..5700fafcf 100644 --- a/sql3/sql_complex_test.go +++ b/sql3/sql_complex_test.go @@ -156,7 +156,7 @@ func TestPlanner_Show(t *testing.T) { } t.Run("SystemTablesInfo", func(t *testing.T) { - results, columns, _, err := sql_test.MustQueryRows(t, c.GetNode(0).Server, `select name, platform, platform_version, db_version, state, node_count, replica_count from fb_cluster_info`) + results, columns, _, err := sql_test.MustQueryRows(t, c.GetNode(0).Server, `select name, platform, platform_version, db_version, state, node_count, replica_count from fb_database_info`) if err != nil { t.Fatal(err) } @@ -178,13 +178,14 @@ func TestPlanner_Show(t *testing.T) { }) t.Run("SystemTablesNode", func(t *testing.T) { - _, columns, _, err := sql_test.MustQueryRows(t, c.GetNode(0).Server, `select * from fb_cluster_nodes`) + _, columns, _, err := sql_test.MustQueryRows(t, c.GetNode(0).Server, `select * from fb_database_nodes`) if err != nil { t.Fatal(err) } if diff := cmp.Diff([]*pilosa.WireQueryField{ wireQueryFieldString("id"), + wireQueryFieldString("type"), wireQueryFieldString("state"), wireQueryFieldString("uri"), wireQueryFieldString("grpc_uri"),