Skip to content

Commit 3fcaa50

Browse files
committed
Merge branch 'fulghum/alter-table' into fulghum-1290f6a9
2 parents 55883a6 + 6aaf629 commit 3fcaa50

File tree

5 files changed

+170
-13
lines changed

5 files changed

+170
-13
lines changed

server/ast/alter_table.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,8 @@ func nodeAlterTableCmds(
7979
statement, err = nodeAlterTableAddColumn(cmd, tableName, ifExists)
8080
case *tree.AlterTableDropColumn:
8181
statement, err = nodeAlterTableDropColumn(cmd, tableName, ifExists)
82+
case *tree.AlterTableDropConstraint:
83+
statement, err = nodeAlterTableDropConstraint(cmd, tableName, ifExists)
8284
case *tree.AlterTableRenameColumn:
8385
statement, err = nodeAlterTableRenameColumn(cmd, tableName, ifExists)
8486
case *tree.AlterTableSetDefault:
@@ -116,6 +118,8 @@ func nodeAlterTableAddConstraint(
116118
}
117119

118120
switch constraintDef := node.ConstraintDef.(type) {
121+
case *tree.CheckConstraintTableDef:
122+
return nodeCheckConstraintTableDef(constraintDef, tableName, ifExists)
119123
case *tree.UniqueConstraintTableDef:
120124
return nodeUniqueConstraintTableDef(constraintDef, tableName, ifExists)
121125
case *tree.ForeignKeyConstraintTableDef:

server/ast/constraint_table_def.go

Lines changed: 80 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,73 @@ import (
2222
"github.com/dolthub/doltgresql/postgres/parser/sem/tree"
2323
)
2424

25+
// nodeCheckConstraintTableDef converts a tree.CheckConstraintTableDef instance
26+
// into a vitess.DDL instance that can be executed by GMS. |tableName| identifies
27+
// the table being altered, and |ifExists| indicates whether the IF EXISTS clause
28+
// was specified.
29+
func nodeCheckConstraintTableDef(
30+
node *tree.CheckConstraintTableDef,
31+
tableName vitess.TableName,
32+
ifExists bool) (*vitess.DDL, error) {
33+
34+
if node.NoInherit {
35+
return nil, fmt.Errorf("NO INHERIT is not yet supported for check constraints")
36+
}
37+
38+
expr, err := nodeExpr(node.Expr)
39+
if err != nil {
40+
return nil, err
41+
}
42+
43+
return &vitess.DDL{
44+
Action: "alter",
45+
Table: tableName,
46+
IfExists: ifExists,
47+
ConstraintAction: "add",
48+
TableSpec: &vitess.TableSpec{
49+
Constraints: []*vitess.ConstraintDefinition{
50+
{
51+
Name: node.Name.String(),
52+
Details: &vitess.CheckConstraintDefinition{
53+
Expr: expr,
54+
Enforced: true,
55+
},
56+
},
57+
},
58+
},
59+
}, nil
60+
}
61+
62+
// nodeAlterTableDropConstraint converts a tree.AlterTableDropConstraint instance
63+
// into a vitess.DDL instance that can be executed by GMS. |tableName| identifies
64+
// the table being altered, and |ifExists| indicates whether the IF EXISTS clause
65+
// was specified.
66+
func nodeAlterTableDropConstraint(
67+
node *tree.AlterTableDropConstraint,
68+
tableName vitess.TableName,
69+
ifExists bool) (*vitess.DDL, error) {
70+
71+
if node.DropBehavior == tree.DropCascade {
72+
return nil, fmt.Errorf("CASCADE is not yet supported for drop constraint")
73+
}
74+
75+
if node.IfExists {
76+
return nil, fmt.Errorf("IF EXISTS is not yet supported for drop constraint")
77+
}
78+
79+
return &vitess.DDL{
80+
Action: "alter",
81+
Table: tableName,
82+
IfExists: ifExists,
83+
ConstraintAction: "drop",
84+
TableSpec: &vitess.TableSpec{
85+
Constraints: []*vitess.ConstraintDefinition{
86+
{Name: node.Constraint.String()},
87+
},
88+
},
89+
}, nil
90+
}
91+
2592
// nodeUniqueConstraintTableDef converts a tree.UniqueConstraintTableDef instance
2693
// into a vitess.DDL instance that can be executed by GMS. |tableName| identifies
2794
// the table being altered, and |ifExists| indicates whether the IF EXISTS clause
@@ -48,18 +115,19 @@ func nodeUniqueConstraintTableDef(
48115
return nil, err
49116
}
50117

118+
indexType := "unique"
51119
if node.PrimaryKey {
52-
return &vitess.DDL{
53-
Action: "alter",
54-
Table: tableName,
55-
IfExists: ifExists,
56-
IndexSpec: &vitess.IndexSpec{
57-
Action: "create",
58-
Type: "primary",
59-
Columns: columns,
60-
},
61-
}, nil
62-
} else {
63-
return nil, fmt.Errorf("Only PRIMARY KEY constraints are supported currently")
120+
indexType = "primary"
64121
}
122+
123+
return &vitess.DDL{
124+
Action: "alter",
125+
Table: tableName,
126+
IfExists: ifExists,
127+
IndexSpec: &vitess.IndexSpec{
128+
Action: "create",
129+
Type: indexType,
130+
Columns: columns,
131+
},
132+
}, nil
65133
}

server/ast/expr.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -719,6 +719,9 @@ func nodeExpr(node tree.Expr) (vitess.Expr, error) {
719719
return retExpr, nil
720720
case *tree.StrVal:
721721
// TODO: determine what to do when node.WasScannedAsBytes() is true
722+
// For string literals, we mark the type as unknown, because Postgres has
723+
// more permissive implicit casting rules for literals than it does for strongly
724+
// typed values from a schema for example.
722725
unknownLiteral := pgexprs.NewUnknownLiteral(node.RawString())
723726
return vitess.InjectedExpr{
724727
Expression: unknownLiteral,

server/ast/select.go

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ package ast
1616

1717
import (
1818
"fmt"
19+
"strings"
1920

2021
vitess "github.com/dolthub/vitess/go/vt/sqlparser"
2122

@@ -157,10 +158,16 @@ func nodeSelectExpr(node tree.SelectExpr) (vitess.SelectExpr, error) {
157158
if ce, ok := expr.(*tree.CastExpr); ok && node.As == "" {
158159
node.As = tree.UnrestrictedName(tree.AsString(ce.Expr))
159160
}
161+
// To be consistent with vitess handling, InputExpression always gets its outer qoutes trimmed
162+
inputExpression := tree.AsString(&node)
163+
if strings.HasPrefix(inputExpression, "'") && strings.HasSuffix(inputExpression, "'") {
164+
inputExpression = inputExpression[1 : len(inputExpression)-1]
165+
}
166+
160167
return &vitess.AliasedExpr{
161168
Expr: vitessExpr,
162169
As: vitess.NewColIdent(string(node.As)),
163-
InputExpression: tree.AsString(&node),
170+
InputExpression: inputExpression,
164171
}, nil
165172
}
166173
}

testing/go/alter_table_test.go

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,81 @@ func TestAlterTable(t *testing.T) {
5757
},
5858
},
5959
},
60+
{
61+
Name: "Add Unique Constraint",
62+
SetUpScript: []string{
63+
"create table t1 (pk int primary key, c1 int);",
64+
"insert into t1 values (1,1);",
65+
"create table t2 (pk int primary key, c1 int);",
66+
"insert into t2 values (1,1);",
67+
},
68+
Assertions: []ScriptTestAssertion{
69+
{
70+
// Add a secondary unique index using create index
71+
Query: "CREATE UNIQUE INDEX ON t1(c1);",
72+
Expected: []sql.Row{},
73+
},
74+
{
75+
// Test that the unique constraint is working
76+
Query: "INSERT INTO t1 VALUES (2, 1);",
77+
ExpectedErr: "unique",
78+
},
79+
{
80+
// Add a secondary unique index using alter table
81+
Query: "ALTER TABLE t2 ADD CONSTRAINT uniq1 UNIQUE (c1);",
82+
Expected: []sql.Row{},
83+
},
84+
{
85+
// Test that the unique constraint is working
86+
Query: "INSERT INTO t2 VALUES (2, 1);",
87+
ExpectedErr: "unique",
88+
},
89+
},
90+
},
91+
{
92+
Name: "Add Check Constraint",
93+
SetUpScript: []string{
94+
"create table t1 (pk int primary key, c1 int);",
95+
"insert into t1 values (1,1);",
96+
},
97+
Assertions: []ScriptTestAssertion{
98+
{
99+
// Add a check constraint that is already violated by the existing data
100+
Query: "ALTER TABLE t1 ADD CONSTRAINT constraint1 CHECK (c1 > 100);",
101+
ExpectedErr: "violated",
102+
},
103+
{
104+
// Add a check constraint
105+
Query: "ALTER TABLE t1 ADD CONSTRAINT constraint1 CHECK (c1 < 100);",
106+
Expected: []sql.Row{},
107+
},
108+
{
109+
Query: "INSERT INTO t1 VALUES (2, 2);",
110+
Expected: []sql.Row{},
111+
},
112+
{
113+
Query: "INSERT INTO t1 VALUES (3, 101);",
114+
ExpectedErr: "violated",
115+
},
116+
},
117+
},
118+
{
119+
Name: "Drop Constraint",
120+
SetUpScript: []string{
121+
"create table t1 (pk int primary key, c1 int);",
122+
"ALTER TABLE t1 ADD CONSTRAINT constraint1 CHECK (c1 > 100);",
123+
},
124+
Assertions: []ScriptTestAssertion{
125+
{
126+
Query: "ALTER TABLE t1 DROP CONSTRAINT constraint1;",
127+
Expected: []sql.Row{},
128+
},
129+
{
130+
Query: "INSERT INTO t1 VALUES (1, 1);",
131+
Expected: []sql.Row{},
132+
},
133+
},
134+
},
60135
{
61136
Name: "Add Primary Key",
62137
SetUpScript: []string{

0 commit comments

Comments
 (0)