// ShowUsers returns all the users. // Privileges: SELECT on system.users. func (p *planner) ShowUsers(n *parser.ShowUsers) (planNode, error) { stmt, err := parser.ParseOneTraditional(`SELECT username FROM system.users`) if err != nil { return nil, err } return p.newPlan(stmt, nil, true) }
func initVirtualTableDesc(p *planner, t virtualSchemaTable) (sqlbase.TableDescriptor, error) { stmt, err := parser.ParseOneTraditional(t.schema) if err != nil { return sqlbase.TableDescriptor{}, err } create := stmt.(*parser.CreateTable) return p.makeTableDesc(create, 0, keys.VirtualDescriptorID, emptyPrivileges, nil) }
// query initializes a planNode from a SQL statement string. Close() must be // called on the returned planNode after use. func (p *planner) query(sql string, args ...interface{}) (planNode, error) { stmt, err := parser.ParseOneTraditional(sql) if err != nil { return nil, err } golangFillQueryArguments(p.semaCtx.Placeholders, args) return p.makePlan(stmt, false) }
// ShowDatabases returns all the databases. // Privileges: None. // Notes: postgres does not have a "show databases" // mysql has a "SHOW DATABASES" permission, but we have no system-level permissions. func (p *planner) ShowDatabases(n *parser.ShowDatabases) (planNode, error) { const getDatabases = `SELECT SCHEMA_NAME AS "Database" FROM information_schema.schemata ORDER BY "Database"` stmt, err := parser.ParseOneTraditional(getDatabases) if err != nil { return nil, err } return p.newPlan(stmt, nil, true) }
func TestMakeDatabaseDesc(t *testing.T) { defer leaktest.AfterTest(t)() stmt, err := parser.ParseOneTraditional("CREATE DATABASE test") if err != nil { t.Fatal(err) } desc := makeDatabaseDesc(stmt.(*parser.CreateDatabase)) if desc.Name != "test" { t.Fatalf("expected Name == test, got %s", desc.Name) } // ID is not set yet. if desc.ID != 0 { t.Fatalf("expected ID == 0, got %d", desc.ID) } if len(desc.GetPrivileges().Users) != 1 { t.Fatalf("wrong number of privilege users, expected 1, got: %d", len(desc.GetPrivileges().Users)) } }
// getViewPlan builds a planDataSource for the view specified by the // table name and descriptor, expanding out its subquery plan. func (p *planner) getViewPlan( tn *parser.TableName, desc *sqlbase.TableDescriptor, ) (planDataSource, error) { // Parse the query as Traditional syntax because we know the query was // saved in the descriptor by printing it with parser.Format. stmt, err := parser.ParseOneTraditional(desc.ViewQuery) if err != nil { return planDataSource{}, errors.Wrapf(err, "failed to parse underlying query from view %q", tn) } sel, ok := stmt.(*parser.Select) if !ok { return planDataSource{}, errors.Errorf("failed to parse underlying query from view %q as a select", tn) } // When constructing the subquery plan, we don't want to check for the SELECT // privilege on the underlying tables, just on the view itself. Checking on // the underlying tables as well would defeat the purpose of having separate // SELECT privileges on the view, which is intended to allow for exposing // some subset of a restricted table's data to less privileged users. if !p.skipSelectPrivilegeChecks { if err := p.checkPrivilege(desc, privilege.SELECT); err != nil { return planDataSource{}, err } p.skipSelectPrivilegeChecks = true defer func() { p.skipSelectPrivilegeChecks = false }() } // TODO(a-robinson): Support ORDER BY and LIMIT in views. Is it as simple as // just passing the entire select here or will inserting an ORDER BY in the // middle of a query plan break things? plan, err := p.getSubqueryPlan(sel.Select, makeResultColumns(desc.Columns)) if err != nil { return plan, err } plan.info.viewDesc = desc return plan, nil }
// ShowCreateView returns a CREATE VIEW statement for the specified view in // Traditional syntax. // Privileges: Any privilege on view. func (p *planner) ShowCreateView(n *parser.ShowCreateView) (planNode, error) { tn, err := n.View.NormalizeWithDatabaseName(p.session.Database) if err != nil { return nil, err } desc, err := p.mustGetViewDesc(tn) if err != nil { return nil, err } if err := p.anyPrivilege(desc); err != nil { return nil, err } columns := ResultColumns{ {Name: "View", Typ: parser.TypeString}, {Name: "CreateView", Typ: parser.TypeString}, } return &delayedNode{ p: p, name: "SHOW CREATE VIEW " + tn.String(), columns: columns, constructor: func(p *planner) (planNode, error) { v := p.newContainerValuesNode(columns, 0) var buf bytes.Buffer fmt.Fprintf(&buf, "CREATE VIEW %s ", quoteNames(n.View.String())) // Determine whether custom column names were specified when the view // was created, and include them if so. customColNames := false stmt, err := parser.ParseOneTraditional(desc.ViewQuery) if err != nil { return nil, errors.Wrapf(err, "failed to parse underlying query from view %q", tn) } sel, ok := stmt.(*parser.Select) if !ok { return nil, errors.Errorf("failed to parse underlying query from view %q as a select", tn) } // When constructing the Select plan, make sure we don't require any // privileges on the underlying tables. p.skipSelectPrivilegeChecks = true defer func() { p.skipSelectPrivilegeChecks = false }() sourcePlan, err := p.Select(sel, []parser.Type{}, false) if err != nil { return nil, err } for i, col := range sourcePlan.Columns() { if col.Name != desc.Columns[i].Name { customColNames = true break } } if customColNames { colNames := make([]string, 0, len(desc.Columns)) for _, col := range desc.Columns { colNames = append(colNames, col.Name) } fmt.Fprintf(&buf, "(%s) ", strings.Join(colNames, ", ")) } fmt.Fprintf(&buf, "AS %s", desc.ViewQuery) if _, err := v.rows.AddRow(parser.DTuple{ parser.NewDString(n.View.String()), parser.NewDString(buf.String()), }); err != nil { v.rows.Close() return nil, err } return v, nil }, }, nil }