Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ALTER TABLE support for ADD COLUMN, DROP COLUMN, and RENAME COLUMN #785

Merged
merged 1 commit into from
Oct 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
85 changes: 79 additions & 6 deletions server/ast/alter_table.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,17 +70,25 @@ func nodeAlterTableCmds(

vitessDdlCmds := make([]*vitess.DDL, 0, len(node))
for _, cmd := range node {
var err error
var statement *vitess.DDL
switch cmd := cmd.(type) {
case *tree.AlterTableAddConstraint:
statement, err := nodeAlterTableAddConstraint(cmd, tableName, ifExists)
if err != nil {
return nil, err
}
vitessDdlCmds = append(vitessDdlCmds, statement)

statement, err = nodeAlterTableAddConstraint(cmd, tableName, ifExists)
case *tree.AlterTableAddColumn:
statement, err = nodeAlterTableAddColumn(cmd, tableName, ifExists)
case *tree.AlterTableDropColumn:
statement, err = nodeAlterTableDropColumn(cmd, tableName, ifExists)
case *tree.AlterTableRenameColumn:
statement, err = nodeAlterTableRenameColumn(cmd, tableName, ifExists)
default:
return nil, fmt.Errorf("ALTER TABLE with unsupported command type %T", cmd)
}

if err != nil {
return nil, err
}
vitessDdlCmds = append(vitessDdlCmds, statement)
}

return vitessDdlCmds, nil
Expand Down Expand Up @@ -124,3 +132,68 @@ func nodeAlterTableAddConstraint(
"definition type %T", node)
}
}

// nodeAlterTableAddColumn converts a tree.AlterTableAddColumn instance into an equivalent vitess.DDL instance.
func nodeAlterTableAddColumn(node *tree.AlterTableAddColumn, tableName vitess.TableName, ifExists bool) (*vitess.DDL, error) {
if node.IfNotExists {
return nil, fmt.Errorf("IF NOT EXISTS on a column in an ADD COLUMN statement is not supported yet")
}

vitessColumnDef, err := nodeColumnTableDef(node.ColumnDef)
if err != nil {
return nil, err
}

return &vitess.DDL{
Action: "alter",
ColumnAction: "add",
Table: tableName,
IfExists: ifExists,
Column: vitessColumnDef.Name,
TableSpec: &vitess.TableSpec{
Columns: []*vitess.ColumnDefinition{
{
Name: vitessColumnDef.Name,
Type: vitessColumnDef.Type,
},
},
},
}, nil
}

// nodeAlterTableDropColumn converts a tree.AlterTableDropColumn instance into an equivalent vitess.DDL instance.
func nodeAlterTableDropColumn(node *tree.AlterTableDropColumn, tableName vitess.TableName, ifExists bool) (*vitess.DDL, error) {
if node.IfExists {
return nil, fmt.Errorf("IF EXISTS on a column in a DROP COLUMN statement is not supported yet")
}

switch node.DropBehavior {
case tree.DropDefault:
case tree.DropRestrict:
return nil, fmt.Errorf("ALTER TABLE DROP COLUMN does not support RESTRICT option")
case tree.DropCascade:
return nil, fmt.Errorf("ALTER TABLE DROP COLUMN does not support CASCADE option")
default:
return nil, fmt.Errorf("ALTER TABLE with unsupported drop behavior %v", node.DropBehavior)
}

return &vitess.DDL{
Action: "alter",
ColumnAction: "drop",
Table: tableName,
IfExists: ifExists,
Column: vitess.NewColIdent(node.Column.String()),
}, nil
}

// nodeAlterTableRenameColumn converts a tree.AlterTableRenameColumn instance into an equivalent vitess.DDL instance.
func nodeAlterTableRenameColumn(node *tree.AlterTableRenameColumn, tableName vitess.TableName, ifExists bool) (*vitess.DDL, error) {
return &vitess.DDL{
Action: "alter",
ColumnAction: "rename",
Table: tableName,
IfExists: ifExists,
Column: vitess.NewColIdent(node.Column.String()),
ToColumn: vitess.NewColIdent(node.NewName.String()),
}, nil
}
87 changes: 87 additions & 0 deletions testing/go/alter_table_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -110,3 +110,90 @@ func TestAlterTableAddPrimaryKey(t *testing.T) {
},
})
}

func TestAlterTableAddColumn(t *testing.T) {
RunScripts(t, []ScriptTest{
{
Name: "Add Column",
SetUpScript: []string{
"CREATE TABLE test1 (a INT, b INT);",
"INSERT INTO test1 VALUES (1, 1);",
},
Assertions: []ScriptTestAssertion{
{
Query: "ALTER TABLE test1 ADD COLUMN c INT NOT NULL DEFAULT 42;",
Expected: []sql.Row{},
},
{
Query: "select * from test1;",
Expected: []sql.Row{{1, 1, 42}},
},
},
},
})
}

func TestAlterTableDropColumn(t *testing.T) {
RunScripts(t, []ScriptTest{
{
Name: "Drop Column",
SetUpScript: []string{
"CREATE TABLE test1 (a INT, b INT, c INT, d INT);",
"INSERT INTO test1 VALUES (1, 2, 3, 4);",
},
Assertions: []ScriptTestAssertion{
{
Query: "ALTER TABLE test1 DROP COLUMN c;",
Expected: []sql.Row{},
},
{
Query: "select * from test1;",
Expected: []sql.Row{{1, 2, 4}},
},
{
Query: "ALTER TABLE test1 DROP COLUMN d;",
Expected: []sql.Row{},
},
{
Query: "select * from test1;",
Expected: []sql.Row{{1, 2}},
},
{
// TODO: Skipped until we support conditional execution on existence of column
Skip: true,
Query: "ALTER TABLE test1 DROP COLUMN IF EXISTS zzz;",
Expected: []sql.Row{},
},
{
// TODO: Even though we're setting IF EXISTS, this query still fails with an
// error about the table not existing.
Skip: true,
Query: "ALTER TABLE IF EXISTS doesNotExist DROP COLUMN z;",
Expected: []sql.Row{},
},
},
},
})
}

func TestAlterTableRenameColumn(t *testing.T) {
RunScripts(t, []ScriptTest{
{
Name: "Rename Column",
SetUpScript: []string{
"CREATE TABLE test1 (a INT, b INT, c INT, d INT);",
"INSERT INTO test1 VALUES (1, 2, 3, 4);",
},
Assertions: []ScriptTestAssertion{
{
Query: "ALTER TABLE test1 RENAME COLUMN c to jjj;",
Expected: []sql.Row{},
},
{
Query: "select * from test1 where jjj=3;",
Expected: []sql.Row{{1, 2, 3, 4}},
},
},
},
})
}
Loading