Skip to content

Commit a62192a

Browse files
authored
sql/errors: Add a new errors package (#390)
* sql/errors: Add a new errors package Unlike the errors defined in pg/errors.go, these should play nicely with errors.As and errors.Is * Remove Already from funcs and types
1 parent 00df4f6 commit a62192a

File tree

2 files changed

+103
-25
lines changed

2 files changed

+103
-25
lines changed

internal/sql/catalog/catalog.go

Lines changed: 14 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55
"fmt"
66

77
"github.com/kyleconroy/sqlc/internal/sql/ast"
8+
sqlerr "github.com/kyleconroy/sqlc/internal/sql/errors"
89
)
910

1011
func Build(stmts []ast.Statement) (*Catalog, error) {
@@ -50,20 +51,13 @@ func stringSlice(list *ast.List) []string {
5051
return items
5152
}
5253

53-
// TODO: This need to be rich error types
54-
var ErrRelationNotFound = errors.New("relation not found")
55-
var ErrRelationAlreadyExists = errors.New("relation already exists")
56-
var ErrSchemaNotFound = errors.New("schema not found")
57-
var ErrColumnNotFound = errors.New("column not found")
58-
var ErrColumnExists = errors.New("column already exists")
59-
6054
func (c *Catalog) getSchema(name string) (*Schema, error) {
6155
for i := range c.Schemas {
6256
if c.Schemas[i].Name == name {
6357
return c.Schemas[i], nil
6458
}
6559
}
66-
return nil, ErrSchemaNotFound
60+
return nil, sqlerr.SchemaNotFound(name)
6761
}
6862

6963
func (c *Catalog) getTable(name *ast.TableName) (*Schema, *Table, error) {
@@ -79,7 +73,7 @@ func (c *Catalog) getTable(name *ast.TableName) (*Schema, *Table, error) {
7973
}
8074
}
8175
if s == nil {
82-
return nil, nil, ErrSchemaNotFound
76+
return nil, nil, sqlerr.SchemaNotFound(ns)
8377
}
8478
t, _, err := s.getTable(name)
8579
if err != nil {
@@ -133,8 +127,7 @@ func (c *Catalog) alterTable(stmt *ast.AlterTableStmt) error {
133127
}
134128
}
135129
if idx < 0 && !cmd.MissingOk {
136-
// return wrap(pg.ErrorColumnDoesNotExist(table.Name, *cmd.Name), raw.StmtLocation)
137-
return ErrColumnNotFound
130+
return sqlerr.ColumnNotFound(table.Rel.Name, *cmd.Name)
138131
}
139132
// If a missing column is allowed, skip this command
140133
if idx < 0 && cmd.MissingOk {
@@ -147,8 +140,7 @@ func (c *Catalog) alterTable(stmt *ast.AlterTableStmt) error {
147140
case ast.AT_AddColumn:
148141
for _, c := range table.Columns {
149142
if c.Name == cmd.Def.Colname {
150-
// return wrap(pg.ErrorColumnAlreadyExists(table.Name, *d.Colname), d.Location)
151-
return ErrColumnExists
143+
return sqlerr.ColumnExists(table.Rel.Name, c.Name)
152144
}
153145
}
154146
table.Columns = append(table.Columns, &Column{
@@ -194,12 +186,10 @@ func (c *Catalog) createEnum(stmt *ast.CreateEnumStmt) error {
194186
Name: stmt.TypeName.Name,
195187
}
196188
if _, _, err := schema.getTable(tbl); err == nil {
197-
// return wrap(pg.ErrorRelationAlreadyExists(fqn.Rel), raw.StmtLocation)
198-
return ErrRelationAlreadyExists
189+
return sqlerr.RelationExists(tbl.Name)
199190
}
200191
if _, err := schema.getType(stmt.TypeName); err == nil {
201-
// return wrap(pg.ErrorTypeAlreadyExists(fqn.Rel), raw.StmtLocation)
202-
return ErrRelationAlreadyExists
192+
return sqlerr.TypeExists(tbl.Name)
203193
}
204194
schema.Types = append(schema.Types, Enum{
205195
Name: stmt.TypeName.Name,
@@ -214,8 +204,7 @@ func (c *Catalog) createSchema(stmt *ast.CreateSchemaStmt) error {
214204
}
215205
if _, err := c.getSchema(*stmt.Name); err == nil {
216206
if !stmt.IfNotExists {
217-
// return wrap(pg.ErrorSchemaAlreadyExists(name), raw.StmtLocation)
218-
return ErrRelationAlreadyExists
207+
return sqlerr.SchemaExists(*stmt.Name)
219208
}
220209
}
221210
c.Schemas = append(c.Schemas, &Schema{Name: *stmt.Name})
@@ -232,7 +221,7 @@ func (c *Catalog) createTable(stmt *ast.CreateTableStmt) error {
232221
return err
233222
}
234223
if _, _, err := schema.getTable(stmt.Name); err != nil {
235-
if !errors.Is(err, ErrRelationNotFound) {
224+
if !errors.Is(err, sqlerr.NotFound) {
236225
return err
237226
}
238227
} else if stmt.IfNotExists {
@@ -263,7 +252,7 @@ func (c *Catalog) dropSchema(stmt *ast.DropSchemaStmt) error {
263252
if stmt.MissingOk {
264253
continue
265254
}
266-
return ErrSchemaNotFound
255+
return sqlerr.SchemaNotFound(name.Str)
267256
}
268257
c.Schemas = append(c.Schemas[:idx], c.Schemas[idx+1:]...)
269258
}
@@ -277,14 +266,14 @@ func (c *Catalog) dropTable(stmt *ast.DropTableStmt) error {
277266
ns = c.DefaultSchema
278267
}
279268
schema, err := c.getSchema(ns)
280-
if errors.Is(err, ErrSchemaNotFound) && stmt.IfExists {
269+
if errors.Is(err, sqlerr.NotFound) && stmt.IfExists {
281270
continue
282271
} else if err != nil {
283272
return err
284273
}
285274

286275
_, idx, err := schema.getTable(name)
287-
if errors.Is(err, ErrRelationNotFound) && stmt.IfExists {
276+
if errors.Is(err, sqlerr.NotFound) && stmt.IfExists {
288277
continue
289278
} else if err != nil {
290279
return err
@@ -319,7 +308,7 @@ func (s *Schema) getType(rel *ast.TypeName) (Type, error) {
319308
}
320309
}
321310
}
322-
return nil, ErrRelationNotFound
311+
return nil, sqlerr.TypeNotFound(rel.Name)
323312
}
324313

325314
func (s *Schema) getTable(rel *ast.TableName) (*Table, int, error) {
@@ -328,7 +317,7 @@ func (s *Schema) getTable(rel *ast.TableName) (*Table, int, error) {
328317
return s.Tables[i], i, nil
329318
}
330319
}
331-
return nil, 0, ErrRelationNotFound
320+
return nil, 0, sqlerr.RelationNotFound(rel.Name)
332321
}
333322

334323
type Table struct {

internal/sql/errors/errors.go

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
package errors
2+
3+
import (
4+
"errors"
5+
"fmt"
6+
)
7+
8+
var Exists = errors.New("already exists")
9+
var NotFound = errors.New("does not exist")
10+
11+
type Error struct {
12+
Err error
13+
Code string
14+
Message string
15+
Location int
16+
// Hint string
17+
}
18+
19+
func (e *Error) Unwrap() error {
20+
return e.Err
21+
}
22+
23+
func (e *Error) Error() string {
24+
return fmt.Sprintf("%s %s", e.Message, e.Err.Error())
25+
}
26+
27+
func ColumnExists(rel, col string) *Error {
28+
return &Error{
29+
Err: Exists,
30+
Code: "42701",
31+
Message: fmt.Sprintf("column \"%s\" of relation \"%s\"", col, rel),
32+
}
33+
}
34+
35+
func ColumnNotFound(rel, col string) *Error {
36+
return &Error{
37+
Err: NotFound,
38+
Code: "42703",
39+
Message: fmt.Sprintf("column \"%s\" of relation \"%s\"", col, rel),
40+
}
41+
}
42+
43+
func RelationExists(rel string) *Error {
44+
return &Error{
45+
Err: Exists,
46+
Code: "42P07",
47+
Message: fmt.Sprintf("relation \"%s\"", rel),
48+
}
49+
}
50+
51+
func RelationNotFound(rel string) *Error {
52+
return &Error{
53+
Err: NotFound,
54+
Code: "42P01",
55+
Message: fmt.Sprintf("relation \"%s\"", rel),
56+
}
57+
}
58+
59+
func SchemaExists(name string) *Error {
60+
return &Error{
61+
Err: Exists,
62+
Code: "42P06",
63+
Message: fmt.Sprintf("schema \"%s\"", name),
64+
}
65+
}
66+
67+
func SchemaNotFound(sch string) *Error {
68+
return &Error{
69+
Err: NotFound,
70+
Code: "3F000",
71+
Message: fmt.Sprintf("schema \"%s\"", sch),
72+
}
73+
}
74+
75+
func TypeExists(typ string) *Error {
76+
return &Error{
77+
Err: Exists,
78+
Code: "42710",
79+
Message: fmt.Sprintf("type \"%s\"", typ),
80+
}
81+
}
82+
83+
func TypeNotFound(typ string) *Error {
84+
return &Error{
85+
Err: NotFound,
86+
Code: "42704",
87+
Message: fmt.Sprintf("type \"%s\"", typ),
88+
}
89+
}

0 commit comments

Comments
 (0)