// MakeColumnDefDescs creates the column descriptor for a column, as well as the // index descriptor if the column is a primary key or unique. func MakeColumnDefDescs(d *parser.ColumnTableDef) (*ColumnDescriptor, *IndexDescriptor, error) { col := &ColumnDescriptor{ Name: string(d.Name), Nullable: d.Nullable != parser.NotNull && !d.PrimaryKey, } var colDatumType parser.Datum switch t := d.Type.(type) { case *parser.BoolColType: col.Type.Kind = ColumnType_BOOL colDatumType = parser.TypeBool case *parser.IntColType: col.Type.Kind = ColumnType_INT col.Type.Width = int32(t.N) colDatumType = parser.TypeInt case *parser.FloatColType: col.Type.Kind = ColumnType_FLOAT col.Type.Precision = int32(t.Prec) colDatumType = parser.TypeFloat case *parser.DecimalColType: col.Type.Kind = ColumnType_DECIMAL col.Type.Width = int32(t.Scale) col.Type.Precision = int32(t.Prec) colDatumType = parser.TypeDecimal case *parser.DateColType: col.Type.Kind = ColumnType_DATE colDatumType = parser.TypeDate case *parser.TimestampColType: col.Type.Kind = ColumnType_TIMESTAMP colDatumType = parser.TypeTimestamp case *parser.TimestampTZColType: col.Type.Kind = ColumnType_TIMESTAMPTZ colDatumType = parser.TypeTimestampTZ case *parser.IntervalColType: col.Type.Kind = ColumnType_INTERVAL colDatumType = parser.TypeInterval case *parser.StringColType: col.Type.Kind = ColumnType_STRING col.Type.Width = int32(t.N) colDatumType = parser.TypeString case *parser.BytesColType: col.Type.Kind = ColumnType_BYTES colDatumType = parser.TypeBytes default: return nil, nil, util.Errorf("unexpected type %T", t) } if col.Type.Kind == ColumnType_DECIMAL { switch { case col.Type.Precision == 0 && col.Type.Width > 0: // TODO (seif): Find right range for error message. return nil, nil, errors.New("invalid NUMERIC precision 0") case col.Type.Precision < col.Type.Width: return nil, nil, fmt.Errorf("NUMERIC scale %d must be between 0 and precision %d", col.Type.Width, col.Type.Precision) } } if d.DefaultExpr != nil { // Verify the default expression type is compatible with the column type. if err := SanitizeDefaultExpr(d.DefaultExpr, colDatumType); err != nil { return nil, nil, err } s := d.DefaultExpr.String() col.DefaultExpr = &s } // CHECK expressions seem to vary across databases. Wikipedia's entry on // Check_constraint (https://en.wikipedia.org/wiki/Check_constraint) says // that if the constraint refers to a single column only, it is possible to // specify the constraint as part of the column definition. Postgres allows // specifying them anywhere about any columns, but it moves all constraints to // the table level (i.e., columns never have a check constraint themselves). We // will adhere to the stricter definition. if d.CheckExpr != nil { s := d.CheckExpr.String() col.CheckExpr = &s preFn := func(expr parser.Expr) (err error, recurse bool, newExpr parser.Expr) { qname, ok := expr.(*parser.QualifiedName) if !ok { // Not a qname, don't do anything to this node. return nil, true, expr } if err := qname.NormalizeColumnName(); err != nil { return err, false, nil } if qname.IsStar() || qname.Base != "" || qname.Column() != col.Name { err := fmt.Errorf("argument of CHECK cannot refer to other columns: \"%s\"", qname) return err, false, nil } // Convert to a dummy datum of the correct type. return nil, false, colDatumType } expr, err := parser.SimpleVisit(d.CheckExpr, preFn) if err != nil { return nil, nil, err } if typedExpr, err := expr.TypeCheck(nil, parser.TypeBool); err != nil { return nil, nil, err } else if typ := typedExpr.ReturnType(); !typ.TypeEqual(parser.TypeBool) { return nil, nil, fmt.Errorf("argument of CHECK must be type bool, not type %s", typ.Type()) } } var idx *IndexDescriptor if d.PrimaryKey || d.Unique { idx = &IndexDescriptor{ Unique: true, ColumnNames: []string{string(d.Name)}, ColumnDirections: []IndexDescriptor_Direction{IndexDescriptor_ASC}, } } return col, idx, nil }
// MakeTableDesc creates a table descriptor from a CreateTable statement. func MakeTableDesc(p *parser.CreateTable, parentID ID) (TableDescriptor, error) { desc := TableDescriptor{} if err := p.Table.NormalizeTableName(""); err != nil { return desc, err } desc.Name = p.Table.Table() desc.ParentID = parentID desc.FormatVersion = FamilyFormatVersion // We don't use version 0. desc.Version = 1 var primaryIndexColumnSet map[parser.Name]struct{} for _, def := range p.Defs { switch d := def.(type) { case *parser.ColumnTableDef: col, idx, err := MakeColumnDefDescs(d) if err != nil { return desc, err } desc.AddColumn(*col) if idx != nil { if err := desc.AddIndex(*idx, d.PrimaryKey); err != nil { return desc, err } } case *parser.IndexTableDef: idx := IndexDescriptor{ Name: string(d.Name), StoreColumnNames: d.Storing, } if err := idx.FillColumns(d.Columns); err != nil { return desc, err } if err := desc.AddIndex(idx, false); err != nil { return desc, err } if d.Interleave != nil { return desc, util.UnimplementedWithIssueErrorf(2972, "interleaving is not yet supported") } case *parser.UniqueConstraintTableDef: idx := IndexDescriptor{ Name: string(d.Name), Unique: true, StoreColumnNames: d.Storing, } if err := idx.FillColumns(d.Columns); err != nil { return desc, err } if err := desc.AddIndex(idx, d.PrimaryKey); err != nil { return desc, err } if d.PrimaryKey { primaryIndexColumnSet = make(map[parser.Name]struct{}) for _, c := range d.Columns { primaryIndexColumnSet[c.Column] = struct{}{} } } if d.Interleave != nil { return desc, util.UnimplementedWithIssueErrorf(2972, "interleaving is not yet supported") } case *parser.CheckConstraintTableDef: // CHECK expressions seem to vary across databases. Wikipedia's entry on // Check_constraint (https://en.wikipedia.org/wiki/Check_constraint) says // that if the constraint refers to a single column only, it is possible to // specify the constraint as part of the column definition. Postgres allows // specifying them anywhere about any columns, but it moves all constraints to // the table level (i.e., columns never have a check constraint themselves). We // will adhere to the stricter definition. preFn := func(expr parser.Expr) (err error, recurse bool, newExpr parser.Expr) { qname, ok := expr.(*parser.QualifiedName) if !ok { // Not a qname, don't do anything to this node. return nil, true, expr } if err := qname.NormalizeColumnName(); err != nil { return err, false, nil } if qname.IsStar() { return fmt.Errorf("* not allowed in constraint %q", d.Expr.String()), false, nil } col, err := desc.FindActiveColumnByName(qname.Column()) if err != nil { return fmt.Errorf("column %q not found for constraint %q", qname.String(), d.Expr.String()), false, nil } // Convert to a dummy datum of the correct type. return nil, false, col.Type.ToDatumType() } expr, err := parser.SimpleVisit(d.Expr, preFn) if err != nil { return desc, err } if err := SanitizeVarFreeExpr(expr, parser.TypeBool, "CHECK"); err != nil { return desc, err } var p parser.Parser if p.AggregateInExpr(expr) { return desc, fmt.Errorf("Aggregate functions are not allowed in CHECK expressions") } check := &TableDescriptor_CheckConstraint{Expr: d.Expr.String()} if len(d.Name) > 0 { check.Name = string(d.Name) } desc.Checks = append(desc.Checks, check) case *parser.FamilyTableDef: names := make([]string, len(d.Columns)) for i, col := range d.Columns { names[i] = string(col.Column) } fam := ColumnFamilyDescriptor{ Name: string(d.Name), ColumnNames: names, } desc.AddFamily(fam) default: return desc, errors.Errorf("unsupported table def: %T", def) } } if primaryIndexColumnSet != nil { // Primary index columns are not nullable. for i := range desc.Columns { if _, ok := primaryIndexColumnSet[parser.Name(desc.Columns[i].Name)]; ok { desc.Columns[i].Nullable = false } } } return desc, nil }
// RenameColumn renames the column. // Privileges: CREATE on table. // notes: postgres requires CREATE on the table. // mysql requires ALTER, CREATE, INSERT on the table. func (p *planner) RenameColumn(n *parser.RenameColumn) (planNode, error) { newColName := string(n.NewName) if newColName == "" { return nil, errEmptyColumnName } if err := n.Table.NormalizeTableName(p.session.Database); err != nil { return nil, err } dbDesc, err := p.getDatabaseDesc(n.Table.Database()) if err != nil { return nil, err } if dbDesc == nil { return nil, sqlbase.NewUndefinedDatabaseError(n.Table.Database()) } // Check if table exists. tbKey := tableKey{dbDesc.ID, n.Table.Table()}.Key() gr, err := p.txn.Get(tbKey) if err != nil { return nil, err } if !gr.Exists() { if n.IfExists { // Noop. return &emptyNode{}, nil } // Key does not exist, but we want it to: error out. return nil, fmt.Errorf("table %q does not exist", n.Table.Table()) } tableDesc, err := p.getTableDesc(n.Table) if err != nil { return nil, err } if tableDesc == nil { return nil, sqlbase.NewUndefinedTableError(n.Table.String()) } colName := string(n.Name) status, i, err := tableDesc.FindColumnByName(colName) // n.IfExists only applies to table, no need to check here. if err != nil { return nil, err } var column *sqlbase.ColumnDescriptor if status == sqlbase.DescriptorActive { column = &tableDesc.Columns[i] } else { column = tableDesc.Mutations[i].GetColumn() } if err := p.checkPrivilege(tableDesc, privilege.CREATE); err != nil { return nil, err } if sqlbase.EqualName(colName, newColName) { // Noop. return &emptyNode{}, nil } if _, _, err := tableDesc.FindColumnByName(newColName); err == nil { return nil, fmt.Errorf("column name %q already exists", newColName) } preFn := func(expr parser.Expr) (err error, recurse bool, newExpr parser.Expr) { if qname, ok := expr.(*parser.QualifiedName); ok { if err := qname.NormalizeColumnName(); err != nil { return err, false, nil } if qname.Column() == colName { qname.Indirect[0] = parser.NameIndirection(newColName) qname.ClearString() } return nil, false, qname } return nil, true, expr } exprStrings := make([]string, len(tableDesc.Checks)) for i, check := range tableDesc.Checks { exprStrings[i] = check.Expr } exprs, err := parser.ParseExprsTraditional(exprStrings) if err != nil { return nil, err } for i := range tableDesc.Checks { expr, err := parser.SimpleVisit(exprs[i], preFn) if err != nil { return nil, err } if after := expr.String(); after != tableDesc.Checks[i].Expr { tableDesc.Checks[i].Expr = after } } // Rename the column in the indexes. tableDesc.RenameColumn(column.ID, newColName) column.Name = newColName if err := tableDesc.SetUpVersion(); err != nil { return nil, err } descKey := sqlbase.MakeDescMetadataKey(tableDesc.GetID()) if err := tableDesc.Validate(); err != nil { return nil, err } if err := p.txn.Put(descKey, sqlbase.WrapDescriptor(tableDesc)); err != nil { return nil, err } p.notifySchemaChange(tableDesc.ID, sqlbase.InvalidMutationID) return &emptyNode{}, nil }
// RenameColumn renames the column. // Privileges: CREATE on table. // notes: postgres requires CREATE on the table. // mysql requires ALTER, CREATE, INSERT on the table. func (p *planner) RenameColumn(n *parser.RenameColumn) (planNode, error) { // Check if table exists. tn, err := n.Table.NormalizeWithDatabaseName(p.session.Database) if err != nil { return nil, err } tableDesc, err := p.getTableDesc(tn) if err != nil { return nil, err } if tableDesc == nil { if n.IfExists { // Noop. return &emptyNode{}, nil } // Key does not exist, but we want it to: error out. return nil, fmt.Errorf("table %q does not exist", tn.Table()) } if err := p.checkPrivilege(tableDesc, privilege.CREATE); err != nil { return nil, err } if n.NewName == "" { return nil, errEmptyColumnName } normNewColName := sqlbase.NormalizeName(n.NewName) normColName := sqlbase.NormalizeName(n.Name) status, i, err := tableDesc.FindColumnByNormalizedName(normColName) // n.IfExists only applies to table, no need to check here. if err != nil { return nil, err } var column *sqlbase.ColumnDescriptor if status == sqlbase.DescriptorActive { column = &tableDesc.Columns[i] } else { column = tableDesc.Mutations[i].GetColumn() } if normColName == normNewColName { // Noop. return &emptyNode{}, nil } if _, _, err := tableDesc.FindColumnByNormalizedName(normNewColName); err == nil { return nil, fmt.Errorf("column name %q already exists", n.NewName) } preFn := func(expr parser.Expr) (err error, recurse bool, newExpr parser.Expr) { if vBase, ok := expr.(parser.VarName); ok { v, err := vBase.NormalizeVarName() if err != nil { return err, false, nil } if c, ok := v.(*parser.ColumnItem); ok { if sqlbase.NormalizeName(c.ColumnName) == normColName { c.ColumnName = n.NewName } } return nil, false, v } return nil, true, expr } exprStrings := make([]string, len(tableDesc.Checks)) for i, check := range tableDesc.Checks { exprStrings[i] = check.Expr } exprs, err := parser.ParseExprsTraditional(exprStrings) if err != nil { return nil, err } for i := range tableDesc.Checks { expr, err := parser.SimpleVisit(exprs[i], preFn) if err != nil { return nil, err } if after := expr.String(); after != tableDesc.Checks[i].Expr { tableDesc.Checks[i].Expr = after } } // Rename the column in the indexes. tableDesc.RenameColumnNormalized(column.ID, normNewColName) column.Name = normNewColName if err := tableDesc.SetUpVersion(); err != nil { return nil, err } descKey := sqlbase.MakeDescMetadataKey(tableDesc.GetID()) if err := tableDesc.Validate(p.txn); err != nil { return nil, err } if err := p.txn.Put(descKey, sqlbase.WrapDescriptor(tableDesc)); err != nil { return nil, err } p.notifySchemaChange(tableDesc.ID, sqlbase.InvalidMutationID) return &emptyNode{}, nil }