From c4a808bbd44a1de2603bbbd331a46a0e2c7f52a6 Mon Sep 17 00:00:00 2001
From: Songa Ogutu <songabarry@gmail.com>
Date: Sat, 7 May 2022 12:35:43 +0300
Subject: [PATCH 1/7] Refactor catalog to self document

---
 internal/sql/catalog/catalog.go | 247 --------------------------------
 internal/sql/catalog/func.go    |  41 ++++++
 internal/sql/catalog/schema.go  |  83 +++++++++++
 internal/sql/catalog/table.go   |  45 ++++++
 internal/sql/catalog/types.go   |  76 ++++++++++
 5 files changed, 245 insertions(+), 247 deletions(-)

diff --git a/internal/sql/catalog/catalog.go b/internal/sql/catalog/catalog.go
index e6095c2405..642dab44fb 100644
--- a/internal/sql/catalog/catalog.go
+++ b/internal/sql/catalog/catalog.go
@@ -1,22 +1,9 @@
 package catalog
 
 import (
-	"strings"
-
 	"github.com/kyleconroy/sqlc/internal/sql/ast"
-	"github.com/kyleconroy/sqlc/internal/sql/sqlerr"
 )
 
-func stringSlice(list *ast.List) []string {
-	items := []string{}
-	for _, item := range list.Items {
-		if n, ok := item.(*ast.String); ok {
-			items = append(items, n.Str)
-		}
-	}
-	return items
-}
-
 type Catalog struct {
 	Comment       string
 	DefaultSchema string
@@ -29,233 +16,6 @@ type Catalog struct {
 	Extensions map[string]struct{}
 }
 
-func (c *Catalog) getSchema(name string) (*Schema, error) {
-	for i := range c.Schemas {
-		if c.Schemas[i].Name == name {
-			return c.Schemas[i], nil
-		}
-	}
-	return nil, sqlerr.SchemaNotFound(name)
-}
-
-func (c *Catalog) getFunc(rel *ast.FuncName, tns []*ast.TypeName) (*Function, int, error) {
-	ns := rel.Schema
-	if ns == "" {
-		ns = c.DefaultSchema
-	}
-	s, err := c.getSchema(ns)
-	if err != nil {
-		return nil, -1, err
-	}
-	return s.getFunc(rel, tns)
-}
-
-func (c *Catalog) getTable(name *ast.TableName) (*Schema, *Table, error) {
-	ns := name.Schema
-	if ns == "" {
-		ns = c.DefaultSchema
-	}
-	var s *Schema
-	for i := range c.Schemas {
-		if c.Schemas[i].Name == ns {
-			s = c.Schemas[i]
-			break
-		}
-	}
-	if s == nil {
-		return nil, nil, sqlerr.SchemaNotFound(ns)
-	}
-	t, _, err := s.getTable(name)
-	if err != nil {
-		return nil, nil, err
-	}
-	return s, t, nil
-}
-
-func (c *Catalog) getType(rel *ast.TypeName) (Type, int, error) {
-	ns := rel.Schema
-	if ns == "" {
-		ns = c.DefaultSchema
-	}
-	s, err := c.getSchema(ns)
-	if err != nil {
-		return nil, -1, err
-	}
-	return s.getType(rel)
-}
-
-type Schema struct {
-	Name   string
-	Tables []*Table
-	Types  []Type
-	Funcs  []*Function
-
-	Comment string
-}
-
-func sameType(a, b *ast.TypeName) bool {
-	if a.Catalog != b.Catalog {
-		return false
-	}
-	// The pg_catalog schema is searched by default, so take that into
-	// account when comparing schemas
-	aSchema := a.Schema
-	bSchema := b.Schema
-	if aSchema == "pg_catalog" {
-		aSchema = ""
-	}
-	if bSchema == "pg_catalog" {
-		bSchema = ""
-	}
-	if aSchema != bSchema {
-		return false
-	}
-	if a.Name != b.Name {
-		return false
-	}
-	return true
-}
-
-func (s *Schema) getFunc(rel *ast.FuncName, tns []*ast.TypeName) (*Function, int, error) {
-	for i := range s.Funcs {
-		if strings.ToLower(s.Funcs[i].Name) != strings.ToLower(rel.Name) {
-			continue
-		}
-
-		args := s.Funcs[i].InArgs()
-		if len(args) != len(tns) {
-			continue
-		}
-		found := true
-		for j := range args {
-			if !sameType(s.Funcs[i].Args[j].Type, tns[j]) {
-				found = false
-				break
-			}
-		}
-		if !found {
-			continue
-		}
-		return s.Funcs[i], i, nil
-	}
-	return nil, -1, sqlerr.RelationNotFound(rel.Name)
-}
-
-func (s *Schema) getFuncByName(rel *ast.FuncName) (*Function, int, error) {
-	idx := -1
-	name := strings.ToLower(rel.Name)
-	for i := range s.Funcs {
-		lowered := strings.ToLower(s.Funcs[i].Name)
-		if lowered == name && idx >= 0 {
-			return nil, -1, sqlerr.FunctionNotUnique(rel.Name)
-		}
-		if lowered == name {
-			idx = i
-		}
-	}
-	if idx < 0 {
-		return nil, -1, sqlerr.RelationNotFound(rel.Name)
-	}
-	return s.Funcs[idx], idx, nil
-}
-
-func (s *Schema) getTable(rel *ast.TableName) (*Table, int, error) {
-	for i := range s.Tables {
-		if s.Tables[i].Rel.Name == rel.Name {
-			return s.Tables[i], i, nil
-		}
-	}
-	return nil, -1, sqlerr.RelationNotFound(rel.Name)
-}
-
-func (s *Schema) getType(rel *ast.TypeName) (Type, int, error) {
-	for i := range s.Types {
-		switch typ := s.Types[i].(type) {
-		case *Enum:
-			if typ.Name == rel.Name {
-				return s.Types[i], i, nil
-			}
-		}
-	}
-	return nil, -1, sqlerr.TypeNotFound(rel.Name)
-}
-
-type Table struct {
-	Rel     *ast.TableName
-	Columns []*Column
-	Comment string
-}
-
-// TODO: Should this just be ast Nodes?
-type Column struct {
-	Name      string
-	Type      ast.TypeName
-	IsNotNull bool
-	IsArray   bool
-	Comment   string
-	Length    *int
-}
-
-type Type interface {
-	isType()
-
-	SetComment(string)
-}
-
-type Enum struct {
-	Name    string
-	Vals    []string
-	Comment string
-}
-
-func (e *Enum) SetComment(c string) {
-	e.Comment = c
-}
-
-func (e *Enum) isType() {
-}
-
-type CompositeType struct {
-	Name    string
-	Comment string
-}
-
-func (ct *CompositeType) isType() {
-}
-
-func (ct *CompositeType) SetComment(c string) {
-	ct.Comment = c
-}
-
-type Function struct {
-	Name               string
-	Args               []*Argument
-	ReturnType         *ast.TypeName
-	Comment            string
-	Desc               string
-	ReturnTypeNullable bool
-}
-
-func (f *Function) InArgs() []*Argument {
-	var args []*Argument
-	for _, a := range f.Args {
-		switch a.Mode {
-		case ast.FuncParamTable, ast.FuncParamOut:
-			continue
-		default:
-			args = append(args, a)
-		}
-	}
-	return args
-}
-
-type Argument struct {
-	Name       string
-	Type       *ast.TypeName
-	HasDefault bool
-	Mode       ast.FuncParamMode
-}
-
 func New(def string) *Catalog {
 	return &Catalog{
 		DefaultSchema: def,
@@ -275,13 +35,6 @@ func (c *Catalog) Build(stmts []ast.Statement) error {
 	return nil
 }
 
-// An interface is used to resolve a circular import between the catalog and compiler packages.
-// The createView function requires access to functions in the compiler package to parse the SELECT
-// statement that defines the view.
-type columnGenerator interface {
-	OutputColumns(node ast.Node) ([]*Column, error)
-}
-
 func (c *Catalog) Update(stmt ast.Statement, colGen columnGenerator) error {
 	if stmt.Raw == nil {
 		return nil
diff --git a/internal/sql/catalog/func.go b/internal/sql/catalog/func.go
index 760144c135..dacc8c9955 100644
--- a/internal/sql/catalog/func.go
+++ b/internal/sql/catalog/func.go
@@ -7,6 +7,47 @@ import (
 	"github.com/kyleconroy/sqlc/internal/sql/sqlerr"
 )
 
+type Function struct {
+	Name               string
+	Args               []*Argument
+	ReturnType         *ast.TypeName
+	Comment            string
+	Desc               string
+	ReturnTypeNullable bool
+}
+
+type Argument struct {
+	Name       string
+	Type       *ast.TypeName
+	HasDefault bool
+	Mode       ast.FuncParamMode
+}
+
+func (f *Function) InArgs() []*Argument {
+	var args []*Argument
+	for _, a := range f.Args {
+		switch a.Mode {
+		case ast.FuncParamTable, ast.FuncParamOut:
+			continue
+		default:
+			args = append(args, a)
+		}
+	}
+	return args
+}
+
+func (c *Catalog) getFunc(rel *ast.FuncName, tns []*ast.TypeName) (*Function, int, error) {
+	ns := rel.Schema
+	if ns == "" {
+		ns = c.DefaultSchema
+	}
+	s, err := c.getSchema(ns)
+	if err != nil {
+		return nil, -1, err
+	}
+	return s.getFunc(rel, tns)
+}
+
 func (c *Catalog) createFunction(stmt *ast.CreateFunctionStmt) error {
 	ns := stmt.Func.Schema
 	if ns == "" {
diff --git a/internal/sql/catalog/schema.go b/internal/sql/catalog/schema.go
index a0189c6c05..4cb11b961e 100644
--- a/internal/sql/catalog/schema.go
+++ b/internal/sql/catalog/schema.go
@@ -2,11 +2,94 @@ package catalog
 
 import (
 	"fmt"
+	"strings"
 
 	"github.com/kyleconroy/sqlc/internal/sql/ast"
 	"github.com/kyleconroy/sqlc/internal/sql/sqlerr"
 )
 
+type Schema struct {
+	Name   string
+	Tables []*Table
+	Types  []Type
+	Funcs  []*Function
+
+	Comment string
+}
+
+func (s *Schema) getFunc(rel *ast.FuncName, tns []*ast.TypeName) (*Function, int, error) {
+	for i := range s.Funcs {
+		if strings.ToLower(s.Funcs[i].Name) != strings.ToLower(rel.Name) {
+			continue
+		}
+
+		args := s.Funcs[i].InArgs()
+		if len(args) != len(tns) {
+			continue
+		}
+		found := true
+		for j := range args {
+			if !sameType(s.Funcs[i].Args[j].Type, tns[j]) {
+				found = false
+				break
+			}
+		}
+		if !found {
+			continue
+		}
+		return s.Funcs[i], i, nil
+	}
+	return nil, -1, sqlerr.RelationNotFound(rel.Name)
+}
+
+func (s *Schema) getFuncByName(rel *ast.FuncName) (*Function, int, error) {
+	idx := -1
+	name := strings.ToLower(rel.Name)
+	for i := range s.Funcs {
+		lowered := strings.ToLower(s.Funcs[i].Name)
+		if lowered == name && idx >= 0 {
+			return nil, -1, sqlerr.FunctionNotUnique(rel.Name)
+		}
+		if lowered == name {
+			idx = i
+		}
+	}
+	if idx < 0 {
+		return nil, -1, sqlerr.RelationNotFound(rel.Name)
+	}
+	return s.Funcs[idx], idx, nil
+}
+
+func (s *Schema) getTable(rel *ast.TableName) (*Table, int, error) {
+	for i := range s.Tables {
+		if s.Tables[i].Rel.Name == rel.Name {
+			return s.Tables[i], i, nil
+		}
+	}
+	return nil, -1, sqlerr.RelationNotFound(rel.Name)
+}
+
+func (s *Schema) getType(rel *ast.TypeName) (Type, int, error) {
+	for i := range s.Types {
+		switch typ := s.Types[i].(type) {
+		case *Enum:
+			if typ.Name == rel.Name {
+				return s.Types[i], i, nil
+			}
+		}
+	}
+	return nil, -1, sqlerr.TypeNotFound(rel.Name)
+}
+
+func (c *Catalog) getSchema(name string) (*Schema, error) {
+	for i := range c.Schemas {
+		if c.Schemas[i].Name == name {
+			return c.Schemas[i], nil
+		}
+	}
+	return nil, sqlerr.SchemaNotFound(name)
+}
+
 func (c *Catalog) createSchema(stmt *ast.CreateSchemaStmt) error {
 	if stmt.Name == nil {
 		return fmt.Errorf("create schema: empty name")
diff --git a/internal/sql/catalog/table.go b/internal/sql/catalog/table.go
index 70c99d0111..2029a8bc13 100644
--- a/internal/sql/catalog/table.go
+++ b/internal/sql/catalog/table.go
@@ -8,6 +8,51 @@ import (
 	"github.com/kyleconroy/sqlc/internal/sql/sqlerr"
 )
 
+type Table struct {
+	Rel     *ast.TableName
+	Columns []*Column
+	Comment string
+}
+
+// TODO: Should this just be ast Nodes?
+type Column struct {
+	Name      string
+	Type      ast.TypeName
+	IsNotNull bool
+	IsArray   bool
+	Comment   string
+	Length    *int
+}
+
+// An interface is used to resolve a circular import between the catalog and compiler packages.
+// The createView function requires access to functions in the compiler package to parse the SELECT
+// statement that defines the view.
+type columnGenerator interface {
+	OutputColumns(node ast.Node) ([]*Column, error)
+}
+
+func (c *Catalog) getTable(name *ast.TableName) (*Schema, *Table, error) {
+	ns := name.Schema
+	if ns == "" {
+		ns = c.DefaultSchema
+	}
+	var s *Schema
+	for i := range c.Schemas {
+		if c.Schemas[i].Name == ns {
+			s = c.Schemas[i]
+			break
+		}
+	}
+	if s == nil {
+		return nil, nil, sqlerr.SchemaNotFound(ns)
+	}
+	t, _, err := s.getTable(name)
+	if err != nil {
+		return nil, nil, err
+	}
+	return s, t, nil
+}
+
 func (c *Catalog) alterTable(stmt *ast.AlterTableStmt) error {
 	var implemented bool
 	for _, item := range stmt.Cmds.Items {
diff --git a/internal/sql/catalog/types.go b/internal/sql/catalog/types.go
index 7156466a75..74f6389f58 100644
--- a/internal/sql/catalog/types.go
+++ b/internal/sql/catalog/types.go
@@ -8,6 +8,60 @@ import (
 	"github.com/kyleconroy/sqlc/internal/sql/sqlerr"
 )
 
+type Type interface {
+	isType()
+
+	SetComment(string)
+}
+
+type Enum struct {
+	Name    string
+	Vals    []string
+	Comment string
+}
+
+func (e *Enum) SetComment(c string) {
+	e.Comment = c
+}
+
+func (e *Enum) isType() {
+}
+
+type CompositeType struct {
+	Name    string
+	Comment string
+}
+
+func (ct *CompositeType) isType() {
+}
+
+func (ct *CompositeType) SetComment(c string) {
+	ct.Comment = c
+}
+
+func sameType(a, b *ast.TypeName) bool {
+	if a.Catalog != b.Catalog {
+		return false
+	}
+	// The pg_catalog schema is searched by default, so take that into
+	// account when comparing schemas
+	aSchema := a.Schema
+	bSchema := b.Schema
+	if aSchema == "pg_catalog" {
+		aSchema = ""
+	}
+	if bSchema == "pg_catalog" {
+		bSchema = ""
+	}
+	if aSchema != bSchema {
+		return false
+	}
+	if a.Name != b.Name {
+		return false
+	}
+	return true
+}
+
 func (c *Catalog) createEnum(stmt *ast.CreateEnumStmt) error {
 	ns := stmt.TypeName.Schema
 	if ns == "" {
@@ -37,6 +91,28 @@ func (c *Catalog) createEnum(stmt *ast.CreateEnumStmt) error {
 	return nil
 }
 
+func stringSlice(list *ast.List) []string {
+	items := []string{}
+	for _, item := range list.Items {
+		if n, ok := item.(*ast.String); ok {
+			items = append(items, n.Str)
+		}
+	}
+	return items
+}
+
+func (c *Catalog) getType(rel *ast.TypeName) (Type, int, error) {
+	ns := rel.Schema
+	if ns == "" {
+		ns = c.DefaultSchema
+	}
+	s, err := c.getSchema(ns)
+	if err != nil {
+		return nil, -1, err
+	}
+	return s.getType(rel)
+}
+
 func (c *Catalog) createCompositeType(stmt *ast.CompositeTypeStmt) error {
 	ns := stmt.TypeName.Schema
 	if ns == "" {

From 8fc27ce0d78dafb6bdf1bc0c58d76adedbe9a484 Mon Sep 17 00:00:00 2001
From: Songa Ogutu <songabarry@gmail.com>
Date: Sun, 8 May 2022 18:32:22 +0300
Subject: [PATCH 2/7] Add comments and tests to pkg catalog

---
 internal/sql/catalog/catalog.go      |  10 +-
 internal/sql/catalog/catalog_test.go |  30 ++
 internal/sql/catalog/func.go         |   3 +
 internal/sql/catalog/func_test.go    |   1 +
 internal/sql/catalog/schema.go       |   1 +
 internal/sql/catalog/schema_test.go  | 758 +++++++++++++++++++++++++++
 internal/sql/catalog/table.go        |   4 +
 internal/sql/catalog/table_test.go   |  40 ++
 8 files changed, 843 insertions(+), 4 deletions(-)
 create mode 100644 internal/sql/catalog/catalog_test.go
 create mode 100644 internal/sql/catalog/func_test.go
 create mode 100644 internal/sql/catalog/schema_test.go
 create mode 100644 internal/sql/catalog/table_test.go

diff --git a/internal/sql/catalog/catalog.go b/internal/sql/catalog/catalog.go
index 642dab44fb..699865c74a 100644
--- a/internal/sql/catalog/catalog.go
+++ b/internal/sql/catalog/catalog.go
@@ -4,6 +4,7 @@ import (
 	"github.com/kyleconroy/sqlc/internal/sql/ast"
 )
 
+// Catalog describes a database instance consisting of metadata in which database objects are defined
 type Catalog struct {
 	Comment       string
 	DefaultSchema string
@@ -16,13 +17,14 @@ type Catalog struct {
 	Extensions map[string]struct{}
 }
 
-func New(def string) *Catalog {
+// New creates a new catalog
+func New(defaultSchema string) *Catalog {
 	return &Catalog{
-		DefaultSchema: def,
+		DefaultSchema: defaultSchema,
 		Schemas: []*Schema{
-			{Name: def},
+			{Name: defaultSchema},
 		},
-		Extensions: map[string]struct{}{},
+		Extensions: make(map[string]struct{}),
 	}
 }
 
diff --git a/internal/sql/catalog/catalog_test.go b/internal/sql/catalog/catalog_test.go
new file mode 100644
index 0000000000..3595d7cb63
--- /dev/null
+++ b/internal/sql/catalog/catalog_test.go
@@ -0,0 +1,30 @@
+package catalog
+
+import "testing"
+
+func TestNew(t *testing.T) {
+
+	const defaultSchema = "default"
+
+	newCatalog := New(defaultSchema)
+
+	if newCatalog.DefaultSchema == "" {
+		t.Errorf("newCatalog.DefaultSchema: want %s, got %s", defaultSchema, newCatalog.DefaultSchema)
+	}
+
+	if newCatalog.Schemas == nil {
+		t.Error("newCatalog.Schemas should not be nil")
+	}
+
+	if len(newCatalog.Schemas) != 1 {
+		t.Errorf("newCatalog.Schemas length want 1, got %d", len(newCatalog.Schemas))
+	}
+
+	if newCatalog.Schemas[0].Name != defaultSchema {
+		t.Error("newCatalog.Schemas should have the default schema")
+	}
+
+	if newCatalog.Extensions == nil {
+		t.Error("newCatalog.Extensions should be empty")
+	}
+}
diff --git a/internal/sql/catalog/func.go b/internal/sql/catalog/func.go
index dacc8c9955..d2891b773c 100644
--- a/internal/sql/catalog/func.go
+++ b/internal/sql/catalog/func.go
@@ -7,6 +7,9 @@ import (
 	"github.com/kyleconroy/sqlc/internal/sql/sqlerr"
 )
 
+// Function describes a database function
+//
+// A database function is a method written to performs specific operation on data within the database.
 type Function struct {
 	Name               string
 	Args               []*Argument
diff --git a/internal/sql/catalog/func_test.go b/internal/sql/catalog/func_test.go
new file mode 100644
index 0000000000..e571e24c61
--- /dev/null
+++ b/internal/sql/catalog/func_test.go
@@ -0,0 +1 @@
+package catalog
diff --git a/internal/sql/catalog/schema.go b/internal/sql/catalog/schema.go
index 4cb11b961e..3cdfeb5bb8 100644
--- a/internal/sql/catalog/schema.go
+++ b/internal/sql/catalog/schema.go
@@ -8,6 +8,7 @@ import (
 	"github.com/kyleconroy/sqlc/internal/sql/sqlerr"
 )
 
+// Schema describes how the data in a relational database may relate to other tables or other data models
 type Schema struct {
 	Name   string
 	Tables []*Table
diff --git a/internal/sql/catalog/schema_test.go b/internal/sql/catalog/schema_test.go
new file mode 100644
index 0000000000..be76e6adf3
--- /dev/null
+++ b/internal/sql/catalog/schema_test.go
@@ -0,0 +1,758 @@
+package catalog
+
+import (
+	"strings"
+	"testing"
+
+	"github.com/kyleconroy/sqlc/internal/sql/ast"
+)
+
+func TestSchemaGetFunc(t *testing.T) {
+
+	testCases := []struct {
+		name    string
+		rel     *ast.FuncName
+		tns     []*ast.TypeName
+		outStub func(t *testing.T, schema *Schema, schemaFunc *Function, funcIndex int, err error)
+	}{
+		{
+			name: "FunctionFound",
+			rel: &ast.FuncName{
+				Name:   "func1",
+				Schema: "schema1",
+			},
+			tns: []*ast.TypeName{
+				{
+					Name:    "type1",
+					Catalog: "catalog1",
+					Schema:  "schema1",
+				},
+			},
+			outStub: func(t *testing.T, schema *Schema, schemaFunc *Function, funcIndex int, err error) {
+
+				if funcIndex < 0 {
+					t.Errorf("invalid funcIndex want greater than 0 got: %d", funcIndex)
+				}
+
+				if schema.Funcs[funcIndex].Name != schemaFunc.Name {
+					t.Errorf("schema function want: %s, got %s", schema.Funcs[funcIndex].Name, schemaFunc.Name)
+				}
+
+				if err != nil {
+					t.Errorf("err should be nil got %v", err)
+				}
+			},
+		},
+		{
+			name: "FunctionAgumentMismatch",
+			rel: &ast.FuncName{
+				Name:   "func1",
+				Schema: "schema1",
+			},
+			tns: []*ast.TypeName{
+				{
+					Name:    "type1",
+					Catalog: "catalog1",
+					Schema:  "schema1",
+				},
+				{
+					Name:    "type2",
+					Catalog: "catalog1",
+					Schema:  "schema1",
+				},
+			},
+			outStub: func(t *testing.T, schema *Schema, schemaFunc *Function, funcIndex int, err error) {
+
+				if funcIndex > -1 {
+					t.Errorf("invalid funcIndex want less than 0 got: %d", funcIndex)
+				}
+
+				if schemaFunc != nil {
+					t.Error("schema function should be nil")
+				}
+
+				if err == nil {
+					t.Error("err should not be nil")
+				}
+			},
+		},
+		{
+			name: "FunctionNameMismatch",
+			rel: &ast.FuncName{
+				Name:   "func",
+				Schema: "schema1",
+			},
+			tns: []*ast.TypeName{
+				{
+					Name:    "type1",
+					Catalog: "catalog1",
+					Schema:  "schema1",
+				},
+			},
+			outStub: func(t *testing.T, schema *Schema, schemaFunc *Function, funcIndex int, err error) {
+
+				if funcIndex > -1 {
+					t.Errorf("invalid funcIndex want less than 0 got: %d", funcIndex)
+				}
+
+				if schemaFunc != nil {
+					t.Error("schema function should be nil")
+				}
+
+				if err == nil {
+					t.Error("err should not be nil")
+				}
+			},
+		},
+		{
+			name: "SchemaNameMismatch",
+			rel: &ast.FuncName{
+				Name:   "func1",
+				Schema: "schema2",
+			},
+			tns: []*ast.TypeName{
+				{
+					Name:    "type1",
+					Catalog: "catalog1",
+					Schema:  "schema2",
+				},
+			},
+			outStub: func(t *testing.T, schema *Schema, schemaFunc *Function, funcIndex int, err error) {
+
+				if funcIndex > -1 {
+					t.Errorf("invalid funcIndex want less than 0 got: %d", funcIndex)
+				}
+
+				if schemaFunc != nil {
+					t.Error("schema function should be nil")
+				}
+
+				if err == nil {
+					t.Error("err should not be nil")
+				}
+			},
+		},
+	}
+
+	schema := &Schema{
+		Name: "schema1",
+		Funcs: []*Function{
+			{
+				Name: "func1",
+				Args: []*Argument{
+					{
+						Name: "arg1",
+						Type: &ast.TypeName{
+							Name:    "type1",
+							Catalog: "catalog1",
+							Schema:  "schema1",
+						},
+						Mode: ast.FuncParamIn,
+					},
+				},
+			},
+			{
+				Name: "func2",
+				Args: []*Argument{
+					{
+						Name: "arg1",
+						Type: &ast.TypeName{
+							Name:    "type1",
+							Catalog: "catalog1",
+							Schema:  "schema1",
+						},
+						Mode: ast.FuncParamIn,
+					},
+				},
+			},
+		},
+	}
+
+	for i := range testCases {
+
+		tc := testCases[i]
+
+		t.Run(tc.name, func(t *testing.T) {
+			outFunc, outIndex, err := schema.getFunc(tc.rel, tc.tns)
+			tc.outStub(t, schema, outFunc, outIndex, err)
+		})
+	}
+}
+
+func TestSchemaGetFuncByName(t *testing.T) {
+
+	schema := &Schema{
+		Name: "schema1",
+		Funcs: []*Function{
+			{
+				Name: "func1",
+				Args: []*Argument{
+					{
+						Name: "arg1",
+						Type: &ast.TypeName{
+							Name:    "type1",
+							Catalog: "catalog1",
+							Schema:  "schema1",
+						},
+						Mode: ast.FuncParamIn,
+					},
+				},
+			},
+			{
+				Name: "func2",
+				Args: []*Argument{
+					{
+						Name: "arg1",
+						Type: &ast.TypeName{
+							Name:    "type1",
+							Catalog: "catalog1",
+							Schema:  "schema1",
+						},
+						Mode: ast.FuncParamIn,
+					},
+				},
+			},
+		},
+	}
+
+	testCases := []struct {
+		name    string
+		schema  *Schema
+		rel     *ast.FuncName
+		outStub func(t *testing.T, schema *Schema, schemaFunc *Function, funcIndex int, err error)
+	}{
+		{
+			name:   "FunctionFound",
+			schema: schema,
+			rel: &ast.FuncName{
+				Name:   "func1",
+				Schema: "schema1",
+			},
+			outStub: func(t *testing.T, schema *Schema, schemaFunc *Function, funcIndex int, err error) {
+
+				if funcIndex < 0 {
+					t.Errorf("invalid funcIndex want greater than 0 got: %d", funcIndex)
+				}
+
+				if schema.Funcs[funcIndex].Name != schemaFunc.Name {
+					t.Errorf("schema function want: %s, got %s", schema.Funcs[funcIndex].Name, schemaFunc.Name)
+				}
+
+				if err != nil {
+					t.Errorf("err should be nil got %v", err)
+				}
+			},
+		},
+		{
+			name: "FunctionNotUnique",
+			schema: func() *Schema {
+
+				// Create a new schema
+
+				newSchema := Schema{}
+				newSchema = *schema
+
+				// Add a duplicate func for test
+				newSchema.Funcs = append(newSchema.Funcs, &Function{
+					Name: "func1",
+					Args: []*Argument{
+						{
+							Name: "arg1",
+							Type: &ast.TypeName{
+								Name:    "type1",
+								Catalog: "catalog1",
+								Schema:  "schema1",
+							},
+							Mode: ast.FuncParamIn,
+						},
+					},
+				})
+
+				return &newSchema
+			}(),
+			rel: &ast.FuncName{
+				Name:   "func1",
+				Schema: "schema1",
+			},
+			outStub: func(t *testing.T, schema *Schema, schemaFunc *Function, funcIndex int, err error) {
+
+				if funcIndex > -1 {
+					t.Errorf("invalid funcIndex want less than 0 got: %d", funcIndex)
+				}
+
+				if schemaFunc != nil {
+					t.Error("schema function should be nil")
+				}
+
+				if err == nil {
+					t.Error("err should not be nil")
+				}
+			},
+		},
+		{
+			name:   "FunctionNotFound",
+			schema: schema,
+			rel: &ast.FuncName{
+				Name:   "func",
+				Schema: "schema1",
+			},
+			outStub: func(t *testing.T, schema *Schema, schemaFunc *Function, funcIndex int, err error) {
+
+				if funcIndex > -1 {
+					t.Errorf("invalid funcIndex want less than 0 got: %d", funcIndex)
+				}
+
+				if schemaFunc != nil {
+					t.Error("schema function should be nil")
+				}
+
+				if err == nil {
+					t.Error("err should not be nil")
+				}
+			},
+		},
+	}
+
+	for i := range testCases {
+
+		tc := testCases[i]
+
+		t.Run(tc.name, func(t *testing.T) {
+			outFunc, outIndex, err := tc.schema.getFuncByName(tc.rel)
+			tc.outStub(t, tc.schema, outFunc, outIndex, err)
+		})
+	}
+}
+
+func TestSchemaGetTable(t *testing.T) {
+
+	schema := &Schema{
+		Name: "schema1",
+		Tables: []*Table{
+			{
+				Rel: &ast.TableName{
+					Name: "table1",
+				},
+			},
+			{
+				Rel: &ast.TableName{
+					Name: "table2",
+				},
+			},
+		},
+	}
+
+	testCases := []struct {
+		name    string
+		rel     *ast.TableName
+		outStub func(t *testing.T, schema *Schema, schemaFunc *Table, tableIndex int, err error)
+	}{
+		{
+			name: "TableFound",
+			rel: &ast.TableName{
+				Name: "table2",
+			},
+			outStub: func(t *testing.T, schema *Schema, schemaTable *Table, tableIndex int, err error) {
+
+				if tableIndex < 0 {
+					t.Errorf("invalid tableIndex want greater than 0 got: %d", tableIndex)
+				}
+
+				if schema.Tables[tableIndex].Rel.Name != schemaTable.Rel.Name {
+					t.Errorf("schema table want: %s, got %s", schema.Tables[tableIndex].Rel.Name, schemaTable.Rel.Name)
+				}
+
+				if err != nil {
+					t.Errorf("err should be nil got %v", err)
+				}
+			},
+		},
+		{
+			name: "TableNotFound",
+			rel: &ast.TableName{
+				Name: "table",
+			},
+			outStub: func(t *testing.T, schema *Schema, schemaTable *Table, tableIndex int, err error) {
+
+				if tableIndex > -1 {
+					t.Errorf("invalid tableIndex want less than 0 got: %d", tableIndex)
+				}
+
+				if schemaTable != nil {
+					t.Error("schema table should be nil")
+				}
+
+				if err == nil {
+					t.Error("err should not be nil")
+				}
+			},
+		},
+	}
+
+	for i := range testCases {
+
+		tc := testCases[i]
+
+		t.Run(tc.name, func(t *testing.T) {
+			outTable, outIndex, err := schema.getTable(tc.rel)
+			tc.outStub(t, schema, outTable, outIndex, err)
+		})
+	}
+}
+
+func TestSchemaGetType(t *testing.T) {
+
+	schema := &Schema{
+		Name: "schema1",
+		Types: []Type{
+			&Enum{
+				Name: "emum1",
+			},
+			&Enum{
+				Name: "emum2",
+			},
+			&CompositeType{
+				Name: "compositeType1",
+			},
+		},
+	}
+
+	testCases := []struct {
+		name    string
+		rel     *ast.TypeName
+		outStub func(t *testing.T, schema *Schema, schemaEnum Type, typeIndex int, err error)
+	}{
+		{
+			name: "TypeFound",
+			rel: &ast.TypeName{
+				Name: "emum1",
+			},
+			outStub: func(t *testing.T, schema *Schema, schemaType Type, typeIndex int, err error) {
+
+				if typeIndex < 0 {
+					t.Errorf("invalid typeIndex want greater than 0 got: %d", typeIndex)
+				}
+
+				if schemaType == nil {
+					t.Error("schema type should not be nil")
+				}
+
+				if err != nil {
+					t.Errorf("err should be nil got %v", err)
+				}
+			},
+		},
+		{
+			name: "TypeNotFound",
+			rel: &ast.TypeName{
+				Name: "enum",
+			},
+			outStub: func(t *testing.T, schema *Schema, schemaType Type, typeIndex int, err error) {
+
+				if typeIndex > -1 {
+					t.Errorf("invalid typeIndex want greater than 0 got: %d", typeIndex)
+				}
+
+				if schemaType != nil {
+					t.Error("schema type should not be nil")
+				}
+
+				if err == nil {
+					t.Error("err should not be nil")
+				}
+			},
+		},
+		{
+			name: "TypeInvalid",
+			rel: &ast.TypeName{
+				Name: "compositeType1",
+			},
+			outStub: func(t *testing.T, schema *Schema, schemaType Type, typeIndex int, err error) {
+
+				if typeIndex > -1 {
+					t.Errorf("invalid typeIndex want greater than 0 got: %d", typeIndex)
+				}
+
+				if schemaType != nil {
+					t.Error("schema type should not be nil")
+				}
+
+				if err == nil {
+					t.Error("err should not be nil")
+				}
+			},
+		},
+	}
+
+	for i := range testCases {
+
+		tc := testCases[i]
+
+		t.Run(tc.name, func(t *testing.T) {
+			outType, outIndex, err := schema.getType(tc.rel)
+			tc.outStub(t, schema, outType, outIndex, err)
+		})
+	}
+}
+
+func TestGetSchema(t *testing.T) {
+
+	testCases := []struct {
+		name       string
+		schemaName string
+		outStub    func(t *testing.T, outSchema *Schema, err error)
+	}{
+		{
+			name:       "Schema Found",
+			schemaName: "default",
+			outStub: func(t *testing.T, schema *Schema, err error) {
+
+				if schema.Name != "default" {
+					t.Errorf("schema name want default got %s", schema.Name)
+				}
+
+				if err != nil {
+					t.Errorf("err should be nil got %v", err)
+				}
+			},
+		},
+		{
+			name:       "Schema Not Found",
+			schemaName: "wrongSchema",
+			outStub: func(t *testing.T, schema *Schema, err error) {
+
+				if schema != nil {
+					t.Error("should be nil")
+				}
+
+				if err == nil {
+					t.Error("err should not be nil")
+				}
+			},
+		},
+	}
+
+	newCatalog := New("default")
+
+	for i := range testCases {
+
+		tc := testCases[i]
+
+		t.Run(tc.name, func(t *testing.T) {
+			outSchema, err := newCatalog.getSchema(tc.schemaName)
+			tc.outStub(t, outSchema, err)
+		})
+	}
+}
+
+func TestCreteSchema(t *testing.T) {
+
+	testCases := []struct {
+		name    string
+		stmt    *ast.CreateSchemaStmt
+		outStub func(t *testing.T, newCatalog *Catalog, err error)
+	}{
+		{
+			name: "No Schema Name",
+			stmt: func() *ast.CreateSchemaStmt {
+				return &ast.CreateSchemaStmt{
+					Name: nil,
+				}
+			}(),
+			outStub: func(t *testing.T, newCatalog *Catalog, err error) {
+
+				if !strings.Contains(err.Error(), "empty name") {
+					t.Errorf("should contain phrase: empty name, got: %s", err.Error())
+				}
+
+				if len(newCatalog.Schemas) != 1 {
+					t.Errorf("catalog schema length: want 1, got: %d", len(newCatalog.Schemas))
+				}
+			},
+		},
+		{
+			name: "Schema Name Exists",
+			stmt: func() *ast.CreateSchemaStmt {
+
+				schemaName := "default"
+
+				return &ast.CreateSchemaStmt{
+					Name: &schemaName,
+				}
+			}(),
+			outStub: func(t *testing.T, newCatalog *Catalog, err error) {
+
+				if err == nil {
+					t.Error("should not be nil")
+				}
+
+				if len(newCatalog.Schemas) != 1 {
+					t.Errorf("catalog schema length: want 1, got: %d", len(newCatalog.Schemas))
+				}
+			},
+		},
+		{
+			name: "Schema Created",
+			stmt: func() *ast.CreateSchemaStmt {
+
+				schemaName := "new_schema"
+
+				return &ast.CreateSchemaStmt{
+					Name: &schemaName,
+				}
+			}(),
+			outStub: func(t *testing.T, newCatalog *Catalog, err error) {
+
+				if err != nil {
+					t.Errorf("should be nil got: %v", err)
+				}
+
+				if len(newCatalog.Schemas) != 2 {
+					t.Errorf("catalog schema length: want 2, got: %d", len(newCatalog.Schemas))
+				}
+			},
+		},
+	}
+
+	newCatalog := New("default")
+
+	for i := range testCases {
+
+		tc := testCases[i]
+
+		t.Run(tc.name, func(t *testing.T) {
+			err := newCatalog.createSchema(tc.stmt)
+			tc.outStub(t, newCatalog, err)
+		})
+	}
+}
+
+func TestDropSchema(t *testing.T) {
+
+	testCases := []struct {
+		name    string
+		stmt    *ast.DropSchemaStmt
+		outStub func(t *testing.T, newCatalog *Catalog, err error)
+	}{
+		{
+			name: "NoSchemaProvided",
+			stmt: &ast.DropSchemaStmt{
+				Schemas: nil,
+			},
+			outStub: func(t *testing.T, newCatalog *Catalog, err error) {
+
+				if err != nil {
+					t.Errorf("err should be nil, got: %v", err)
+				}
+
+				if len(newCatalog.Schemas) != 5 {
+					t.Errorf("catalog schema length: want 5, got: %d", len(newCatalog.Schemas))
+				}
+			},
+		},
+		{
+			name: "DeleteOneSchema",
+			stmt: &ast.DropSchemaStmt{
+				Schemas: []*ast.String{
+					{
+						Str: "schema1",
+					},
+				},
+			},
+			outStub: func(t *testing.T, newCatalog *Catalog, err error) {
+
+				if err != nil {
+					t.Errorf("err should be nil, got: %v", err)
+				}
+
+				if len(newCatalog.Schemas) != 4 {
+					t.Errorf("catalog schema length: want 4, got: %d", len(newCatalog.Schemas))
+				}
+			},
+		},
+		{
+			name: "DeleteMultipleSchema",
+			stmt: &ast.DropSchemaStmt{
+				Schemas: []*ast.String{
+					{
+						Str: "schema1",
+					},
+					{
+						Str: "schema3",
+					},
+				},
+			},
+			outStub: func(t *testing.T, newCatalog *Catalog, err error) {
+
+				if err != nil {
+					t.Errorf("err should be nil, got: %v", err)
+				}
+
+				if len(newCatalog.Schemas) != 3 {
+					t.Errorf("catalog schema length: want 3, got: %d", len(newCatalog.Schemas))
+				}
+			},
+		},
+		{
+			name: "AllowedMissingSchema",
+			stmt: &ast.DropSchemaStmt{
+				Schemas: []*ast.String{
+					{
+						Str: "schema10",
+					},
+				},
+				MissingOk: true,
+			},
+			outStub: func(t *testing.T, newCatalog *Catalog, err error) {
+
+				if err != nil {
+					t.Errorf("err should be nil, got: %v", err)
+				}
+
+				if len(newCatalog.Schemas) != 5 {
+					t.Errorf("catalog schema length: want 5, got: %d", len(newCatalog.Schemas))
+				}
+			},
+		},
+		{
+			name: "SchemaNotFound",
+			stmt: &ast.DropSchemaStmt{
+				Schemas: []*ast.String{
+					{
+						Str: "missing_schema",
+					},
+				},
+			},
+			outStub: func(t *testing.T, newCatalog *Catalog, err error) {
+
+				if err == nil {
+					t.Error("err should not nil")
+				}
+
+				if len(newCatalog.Schemas) != 5 {
+					t.Errorf("catalog schema length: want 5, got: %d", len(newCatalog.Schemas))
+				}
+			},
+		},
+	}
+
+	for i := range testCases {
+
+		tc := testCases[i]
+
+		t.Run(tc.name, func(t *testing.T) {
+
+			newCatalog := New("default")
+
+			newCatalog.Schemas = append(
+				newCatalog.Schemas,
+				&Schema{Name: "schema1"},
+				&Schema{Name: "schema2"},
+				&Schema{Name: "schema3"},
+				&Schema{Name: "schema4"})
+
+			err := newCatalog.dropSchema(tc.stmt)
+			tc.outStub(t, newCatalog, err)
+		})
+	}
+}
diff --git a/internal/sql/catalog/table.go b/internal/sql/catalog/table.go
index 2029a8bc13..780b718f5f 100644
--- a/internal/sql/catalog/table.go
+++ b/internal/sql/catalog/table.go
@@ -8,6 +8,10 @@ import (
 	"github.com/kyleconroy/sqlc/internal/sql/sqlerr"
 )
 
+// Table describes a relational database table
+//
+// A database table is a collection of related data held in a table format within a database.
+// It consists of columns and rows.
 type Table struct {
 	Rel     *ast.TableName
 	Columns []*Column
diff --git a/internal/sql/catalog/table_test.go b/internal/sql/catalog/table_test.go
new file mode 100644
index 0000000000..ecffd3e37e
--- /dev/null
+++ b/internal/sql/catalog/table_test.go
@@ -0,0 +1,40 @@
+package catalog
+
+import (
+	"testing"
+
+	"github.com/kyleconroy/sqlc/internal/sql/ast"
+)
+
+func TestGetTable(t *testing.T) {
+
+	testCases := []struct {
+		name      string
+		tableName *ast.TableName
+		outStub   func(t *testing.T, outSchema *Schema, outTable *Table, err error)
+	}{
+		{
+			name: "Use Catalog Default Schema",
+			tableName: &ast.TableName{
+				Catalog: "catalog1",
+				Schema:  "",
+				Name:    "table1",
+			},
+			outStub: func(t *testing.T, outSchema *Schema, outTable *Table, err error) {
+
+			},
+		},
+	}
+
+	newCatalog := New("default")
+
+	for i := range testCases {
+
+		tc := testCases[i]
+
+		outSchema, outTable, err := newCatalog.getTable(tc.tableName)
+
+		tc.outStub(t, outSchema, outTable, err)
+
+	}
+}

From 71d434769a5d372fbcb5ebd331cb0018e0fbdc80 Mon Sep 17 00:00:00 2001
From: Songa Ogutu <songabarry@gmail.com>
Date: Thu, 12 May 2022 07:51:05 +0300
Subject: [PATCH 3/7] Remove all unit test in favor of endtoend tests

---
 internal/sql/catalog/catalog_test.go |  30 --
 internal/sql/catalog/func_test.go    |   1 -
 internal/sql/catalog/schema_test.go  | 758 ---------------------------
 internal/sql/catalog/table_test.go   |  40 --
 4 files changed, 829 deletions(-)
 delete mode 100644 internal/sql/catalog/catalog_test.go
 delete mode 100644 internal/sql/catalog/func_test.go
 delete mode 100644 internal/sql/catalog/schema_test.go
 delete mode 100644 internal/sql/catalog/table_test.go

diff --git a/internal/sql/catalog/catalog_test.go b/internal/sql/catalog/catalog_test.go
deleted file mode 100644
index 3595d7cb63..0000000000
--- a/internal/sql/catalog/catalog_test.go
+++ /dev/null
@@ -1,30 +0,0 @@
-package catalog
-
-import "testing"
-
-func TestNew(t *testing.T) {
-
-	const defaultSchema = "default"
-
-	newCatalog := New(defaultSchema)
-
-	if newCatalog.DefaultSchema == "" {
-		t.Errorf("newCatalog.DefaultSchema: want %s, got %s", defaultSchema, newCatalog.DefaultSchema)
-	}
-
-	if newCatalog.Schemas == nil {
-		t.Error("newCatalog.Schemas should not be nil")
-	}
-
-	if len(newCatalog.Schemas) != 1 {
-		t.Errorf("newCatalog.Schemas length want 1, got %d", len(newCatalog.Schemas))
-	}
-
-	if newCatalog.Schemas[0].Name != defaultSchema {
-		t.Error("newCatalog.Schemas should have the default schema")
-	}
-
-	if newCatalog.Extensions == nil {
-		t.Error("newCatalog.Extensions should be empty")
-	}
-}
diff --git a/internal/sql/catalog/func_test.go b/internal/sql/catalog/func_test.go
deleted file mode 100644
index e571e24c61..0000000000
--- a/internal/sql/catalog/func_test.go
+++ /dev/null
@@ -1 +0,0 @@
-package catalog
diff --git a/internal/sql/catalog/schema_test.go b/internal/sql/catalog/schema_test.go
deleted file mode 100644
index be76e6adf3..0000000000
--- a/internal/sql/catalog/schema_test.go
+++ /dev/null
@@ -1,758 +0,0 @@
-package catalog
-
-import (
-	"strings"
-	"testing"
-
-	"github.com/kyleconroy/sqlc/internal/sql/ast"
-)
-
-func TestSchemaGetFunc(t *testing.T) {
-
-	testCases := []struct {
-		name    string
-		rel     *ast.FuncName
-		tns     []*ast.TypeName
-		outStub func(t *testing.T, schema *Schema, schemaFunc *Function, funcIndex int, err error)
-	}{
-		{
-			name: "FunctionFound",
-			rel: &ast.FuncName{
-				Name:   "func1",
-				Schema: "schema1",
-			},
-			tns: []*ast.TypeName{
-				{
-					Name:    "type1",
-					Catalog: "catalog1",
-					Schema:  "schema1",
-				},
-			},
-			outStub: func(t *testing.T, schema *Schema, schemaFunc *Function, funcIndex int, err error) {
-
-				if funcIndex < 0 {
-					t.Errorf("invalid funcIndex want greater than 0 got: %d", funcIndex)
-				}
-
-				if schema.Funcs[funcIndex].Name != schemaFunc.Name {
-					t.Errorf("schema function want: %s, got %s", schema.Funcs[funcIndex].Name, schemaFunc.Name)
-				}
-
-				if err != nil {
-					t.Errorf("err should be nil got %v", err)
-				}
-			},
-		},
-		{
-			name: "FunctionAgumentMismatch",
-			rel: &ast.FuncName{
-				Name:   "func1",
-				Schema: "schema1",
-			},
-			tns: []*ast.TypeName{
-				{
-					Name:    "type1",
-					Catalog: "catalog1",
-					Schema:  "schema1",
-				},
-				{
-					Name:    "type2",
-					Catalog: "catalog1",
-					Schema:  "schema1",
-				},
-			},
-			outStub: func(t *testing.T, schema *Schema, schemaFunc *Function, funcIndex int, err error) {
-
-				if funcIndex > -1 {
-					t.Errorf("invalid funcIndex want less than 0 got: %d", funcIndex)
-				}
-
-				if schemaFunc != nil {
-					t.Error("schema function should be nil")
-				}
-
-				if err == nil {
-					t.Error("err should not be nil")
-				}
-			},
-		},
-		{
-			name: "FunctionNameMismatch",
-			rel: &ast.FuncName{
-				Name:   "func",
-				Schema: "schema1",
-			},
-			tns: []*ast.TypeName{
-				{
-					Name:    "type1",
-					Catalog: "catalog1",
-					Schema:  "schema1",
-				},
-			},
-			outStub: func(t *testing.T, schema *Schema, schemaFunc *Function, funcIndex int, err error) {
-
-				if funcIndex > -1 {
-					t.Errorf("invalid funcIndex want less than 0 got: %d", funcIndex)
-				}
-
-				if schemaFunc != nil {
-					t.Error("schema function should be nil")
-				}
-
-				if err == nil {
-					t.Error("err should not be nil")
-				}
-			},
-		},
-		{
-			name: "SchemaNameMismatch",
-			rel: &ast.FuncName{
-				Name:   "func1",
-				Schema: "schema2",
-			},
-			tns: []*ast.TypeName{
-				{
-					Name:    "type1",
-					Catalog: "catalog1",
-					Schema:  "schema2",
-				},
-			},
-			outStub: func(t *testing.T, schema *Schema, schemaFunc *Function, funcIndex int, err error) {
-
-				if funcIndex > -1 {
-					t.Errorf("invalid funcIndex want less than 0 got: %d", funcIndex)
-				}
-
-				if schemaFunc != nil {
-					t.Error("schema function should be nil")
-				}
-
-				if err == nil {
-					t.Error("err should not be nil")
-				}
-			},
-		},
-	}
-
-	schema := &Schema{
-		Name: "schema1",
-		Funcs: []*Function{
-			{
-				Name: "func1",
-				Args: []*Argument{
-					{
-						Name: "arg1",
-						Type: &ast.TypeName{
-							Name:    "type1",
-							Catalog: "catalog1",
-							Schema:  "schema1",
-						},
-						Mode: ast.FuncParamIn,
-					},
-				},
-			},
-			{
-				Name: "func2",
-				Args: []*Argument{
-					{
-						Name: "arg1",
-						Type: &ast.TypeName{
-							Name:    "type1",
-							Catalog: "catalog1",
-							Schema:  "schema1",
-						},
-						Mode: ast.FuncParamIn,
-					},
-				},
-			},
-		},
-	}
-
-	for i := range testCases {
-
-		tc := testCases[i]
-
-		t.Run(tc.name, func(t *testing.T) {
-			outFunc, outIndex, err := schema.getFunc(tc.rel, tc.tns)
-			tc.outStub(t, schema, outFunc, outIndex, err)
-		})
-	}
-}
-
-func TestSchemaGetFuncByName(t *testing.T) {
-
-	schema := &Schema{
-		Name: "schema1",
-		Funcs: []*Function{
-			{
-				Name: "func1",
-				Args: []*Argument{
-					{
-						Name: "arg1",
-						Type: &ast.TypeName{
-							Name:    "type1",
-							Catalog: "catalog1",
-							Schema:  "schema1",
-						},
-						Mode: ast.FuncParamIn,
-					},
-				},
-			},
-			{
-				Name: "func2",
-				Args: []*Argument{
-					{
-						Name: "arg1",
-						Type: &ast.TypeName{
-							Name:    "type1",
-							Catalog: "catalog1",
-							Schema:  "schema1",
-						},
-						Mode: ast.FuncParamIn,
-					},
-				},
-			},
-		},
-	}
-
-	testCases := []struct {
-		name    string
-		schema  *Schema
-		rel     *ast.FuncName
-		outStub func(t *testing.T, schema *Schema, schemaFunc *Function, funcIndex int, err error)
-	}{
-		{
-			name:   "FunctionFound",
-			schema: schema,
-			rel: &ast.FuncName{
-				Name:   "func1",
-				Schema: "schema1",
-			},
-			outStub: func(t *testing.T, schema *Schema, schemaFunc *Function, funcIndex int, err error) {
-
-				if funcIndex < 0 {
-					t.Errorf("invalid funcIndex want greater than 0 got: %d", funcIndex)
-				}
-
-				if schema.Funcs[funcIndex].Name != schemaFunc.Name {
-					t.Errorf("schema function want: %s, got %s", schema.Funcs[funcIndex].Name, schemaFunc.Name)
-				}
-
-				if err != nil {
-					t.Errorf("err should be nil got %v", err)
-				}
-			},
-		},
-		{
-			name: "FunctionNotUnique",
-			schema: func() *Schema {
-
-				// Create a new schema
-
-				newSchema := Schema{}
-				newSchema = *schema
-
-				// Add a duplicate func for test
-				newSchema.Funcs = append(newSchema.Funcs, &Function{
-					Name: "func1",
-					Args: []*Argument{
-						{
-							Name: "arg1",
-							Type: &ast.TypeName{
-								Name:    "type1",
-								Catalog: "catalog1",
-								Schema:  "schema1",
-							},
-							Mode: ast.FuncParamIn,
-						},
-					},
-				})
-
-				return &newSchema
-			}(),
-			rel: &ast.FuncName{
-				Name:   "func1",
-				Schema: "schema1",
-			},
-			outStub: func(t *testing.T, schema *Schema, schemaFunc *Function, funcIndex int, err error) {
-
-				if funcIndex > -1 {
-					t.Errorf("invalid funcIndex want less than 0 got: %d", funcIndex)
-				}
-
-				if schemaFunc != nil {
-					t.Error("schema function should be nil")
-				}
-
-				if err == nil {
-					t.Error("err should not be nil")
-				}
-			},
-		},
-		{
-			name:   "FunctionNotFound",
-			schema: schema,
-			rel: &ast.FuncName{
-				Name:   "func",
-				Schema: "schema1",
-			},
-			outStub: func(t *testing.T, schema *Schema, schemaFunc *Function, funcIndex int, err error) {
-
-				if funcIndex > -1 {
-					t.Errorf("invalid funcIndex want less than 0 got: %d", funcIndex)
-				}
-
-				if schemaFunc != nil {
-					t.Error("schema function should be nil")
-				}
-
-				if err == nil {
-					t.Error("err should not be nil")
-				}
-			},
-		},
-	}
-
-	for i := range testCases {
-
-		tc := testCases[i]
-
-		t.Run(tc.name, func(t *testing.T) {
-			outFunc, outIndex, err := tc.schema.getFuncByName(tc.rel)
-			tc.outStub(t, tc.schema, outFunc, outIndex, err)
-		})
-	}
-}
-
-func TestSchemaGetTable(t *testing.T) {
-
-	schema := &Schema{
-		Name: "schema1",
-		Tables: []*Table{
-			{
-				Rel: &ast.TableName{
-					Name: "table1",
-				},
-			},
-			{
-				Rel: &ast.TableName{
-					Name: "table2",
-				},
-			},
-		},
-	}
-
-	testCases := []struct {
-		name    string
-		rel     *ast.TableName
-		outStub func(t *testing.T, schema *Schema, schemaFunc *Table, tableIndex int, err error)
-	}{
-		{
-			name: "TableFound",
-			rel: &ast.TableName{
-				Name: "table2",
-			},
-			outStub: func(t *testing.T, schema *Schema, schemaTable *Table, tableIndex int, err error) {
-
-				if tableIndex < 0 {
-					t.Errorf("invalid tableIndex want greater than 0 got: %d", tableIndex)
-				}
-
-				if schema.Tables[tableIndex].Rel.Name != schemaTable.Rel.Name {
-					t.Errorf("schema table want: %s, got %s", schema.Tables[tableIndex].Rel.Name, schemaTable.Rel.Name)
-				}
-
-				if err != nil {
-					t.Errorf("err should be nil got %v", err)
-				}
-			},
-		},
-		{
-			name: "TableNotFound",
-			rel: &ast.TableName{
-				Name: "table",
-			},
-			outStub: func(t *testing.T, schema *Schema, schemaTable *Table, tableIndex int, err error) {
-
-				if tableIndex > -1 {
-					t.Errorf("invalid tableIndex want less than 0 got: %d", tableIndex)
-				}
-
-				if schemaTable != nil {
-					t.Error("schema table should be nil")
-				}
-
-				if err == nil {
-					t.Error("err should not be nil")
-				}
-			},
-		},
-	}
-
-	for i := range testCases {
-
-		tc := testCases[i]
-
-		t.Run(tc.name, func(t *testing.T) {
-			outTable, outIndex, err := schema.getTable(tc.rel)
-			tc.outStub(t, schema, outTable, outIndex, err)
-		})
-	}
-}
-
-func TestSchemaGetType(t *testing.T) {
-
-	schema := &Schema{
-		Name: "schema1",
-		Types: []Type{
-			&Enum{
-				Name: "emum1",
-			},
-			&Enum{
-				Name: "emum2",
-			},
-			&CompositeType{
-				Name: "compositeType1",
-			},
-		},
-	}
-
-	testCases := []struct {
-		name    string
-		rel     *ast.TypeName
-		outStub func(t *testing.T, schema *Schema, schemaEnum Type, typeIndex int, err error)
-	}{
-		{
-			name: "TypeFound",
-			rel: &ast.TypeName{
-				Name: "emum1",
-			},
-			outStub: func(t *testing.T, schema *Schema, schemaType Type, typeIndex int, err error) {
-
-				if typeIndex < 0 {
-					t.Errorf("invalid typeIndex want greater than 0 got: %d", typeIndex)
-				}
-
-				if schemaType == nil {
-					t.Error("schema type should not be nil")
-				}
-
-				if err != nil {
-					t.Errorf("err should be nil got %v", err)
-				}
-			},
-		},
-		{
-			name: "TypeNotFound",
-			rel: &ast.TypeName{
-				Name: "enum",
-			},
-			outStub: func(t *testing.T, schema *Schema, schemaType Type, typeIndex int, err error) {
-
-				if typeIndex > -1 {
-					t.Errorf("invalid typeIndex want greater than 0 got: %d", typeIndex)
-				}
-
-				if schemaType != nil {
-					t.Error("schema type should not be nil")
-				}
-
-				if err == nil {
-					t.Error("err should not be nil")
-				}
-			},
-		},
-		{
-			name: "TypeInvalid",
-			rel: &ast.TypeName{
-				Name: "compositeType1",
-			},
-			outStub: func(t *testing.T, schema *Schema, schemaType Type, typeIndex int, err error) {
-
-				if typeIndex > -1 {
-					t.Errorf("invalid typeIndex want greater than 0 got: %d", typeIndex)
-				}
-
-				if schemaType != nil {
-					t.Error("schema type should not be nil")
-				}
-
-				if err == nil {
-					t.Error("err should not be nil")
-				}
-			},
-		},
-	}
-
-	for i := range testCases {
-
-		tc := testCases[i]
-
-		t.Run(tc.name, func(t *testing.T) {
-			outType, outIndex, err := schema.getType(tc.rel)
-			tc.outStub(t, schema, outType, outIndex, err)
-		})
-	}
-}
-
-func TestGetSchema(t *testing.T) {
-
-	testCases := []struct {
-		name       string
-		schemaName string
-		outStub    func(t *testing.T, outSchema *Schema, err error)
-	}{
-		{
-			name:       "Schema Found",
-			schemaName: "default",
-			outStub: func(t *testing.T, schema *Schema, err error) {
-
-				if schema.Name != "default" {
-					t.Errorf("schema name want default got %s", schema.Name)
-				}
-
-				if err != nil {
-					t.Errorf("err should be nil got %v", err)
-				}
-			},
-		},
-		{
-			name:       "Schema Not Found",
-			schemaName: "wrongSchema",
-			outStub: func(t *testing.T, schema *Schema, err error) {
-
-				if schema != nil {
-					t.Error("should be nil")
-				}
-
-				if err == nil {
-					t.Error("err should not be nil")
-				}
-			},
-		},
-	}
-
-	newCatalog := New("default")
-
-	for i := range testCases {
-
-		tc := testCases[i]
-
-		t.Run(tc.name, func(t *testing.T) {
-			outSchema, err := newCatalog.getSchema(tc.schemaName)
-			tc.outStub(t, outSchema, err)
-		})
-	}
-}
-
-func TestCreteSchema(t *testing.T) {
-
-	testCases := []struct {
-		name    string
-		stmt    *ast.CreateSchemaStmt
-		outStub func(t *testing.T, newCatalog *Catalog, err error)
-	}{
-		{
-			name: "No Schema Name",
-			stmt: func() *ast.CreateSchemaStmt {
-				return &ast.CreateSchemaStmt{
-					Name: nil,
-				}
-			}(),
-			outStub: func(t *testing.T, newCatalog *Catalog, err error) {
-
-				if !strings.Contains(err.Error(), "empty name") {
-					t.Errorf("should contain phrase: empty name, got: %s", err.Error())
-				}
-
-				if len(newCatalog.Schemas) != 1 {
-					t.Errorf("catalog schema length: want 1, got: %d", len(newCatalog.Schemas))
-				}
-			},
-		},
-		{
-			name: "Schema Name Exists",
-			stmt: func() *ast.CreateSchemaStmt {
-
-				schemaName := "default"
-
-				return &ast.CreateSchemaStmt{
-					Name: &schemaName,
-				}
-			}(),
-			outStub: func(t *testing.T, newCatalog *Catalog, err error) {
-
-				if err == nil {
-					t.Error("should not be nil")
-				}
-
-				if len(newCatalog.Schemas) != 1 {
-					t.Errorf("catalog schema length: want 1, got: %d", len(newCatalog.Schemas))
-				}
-			},
-		},
-		{
-			name: "Schema Created",
-			stmt: func() *ast.CreateSchemaStmt {
-
-				schemaName := "new_schema"
-
-				return &ast.CreateSchemaStmt{
-					Name: &schemaName,
-				}
-			}(),
-			outStub: func(t *testing.T, newCatalog *Catalog, err error) {
-
-				if err != nil {
-					t.Errorf("should be nil got: %v", err)
-				}
-
-				if len(newCatalog.Schemas) != 2 {
-					t.Errorf("catalog schema length: want 2, got: %d", len(newCatalog.Schemas))
-				}
-			},
-		},
-	}
-
-	newCatalog := New("default")
-
-	for i := range testCases {
-
-		tc := testCases[i]
-
-		t.Run(tc.name, func(t *testing.T) {
-			err := newCatalog.createSchema(tc.stmt)
-			tc.outStub(t, newCatalog, err)
-		})
-	}
-}
-
-func TestDropSchema(t *testing.T) {
-
-	testCases := []struct {
-		name    string
-		stmt    *ast.DropSchemaStmt
-		outStub func(t *testing.T, newCatalog *Catalog, err error)
-	}{
-		{
-			name: "NoSchemaProvided",
-			stmt: &ast.DropSchemaStmt{
-				Schemas: nil,
-			},
-			outStub: func(t *testing.T, newCatalog *Catalog, err error) {
-
-				if err != nil {
-					t.Errorf("err should be nil, got: %v", err)
-				}
-
-				if len(newCatalog.Schemas) != 5 {
-					t.Errorf("catalog schema length: want 5, got: %d", len(newCatalog.Schemas))
-				}
-			},
-		},
-		{
-			name: "DeleteOneSchema",
-			stmt: &ast.DropSchemaStmt{
-				Schemas: []*ast.String{
-					{
-						Str: "schema1",
-					},
-				},
-			},
-			outStub: func(t *testing.T, newCatalog *Catalog, err error) {
-
-				if err != nil {
-					t.Errorf("err should be nil, got: %v", err)
-				}
-
-				if len(newCatalog.Schemas) != 4 {
-					t.Errorf("catalog schema length: want 4, got: %d", len(newCatalog.Schemas))
-				}
-			},
-		},
-		{
-			name: "DeleteMultipleSchema",
-			stmt: &ast.DropSchemaStmt{
-				Schemas: []*ast.String{
-					{
-						Str: "schema1",
-					},
-					{
-						Str: "schema3",
-					},
-				},
-			},
-			outStub: func(t *testing.T, newCatalog *Catalog, err error) {
-
-				if err != nil {
-					t.Errorf("err should be nil, got: %v", err)
-				}
-
-				if len(newCatalog.Schemas) != 3 {
-					t.Errorf("catalog schema length: want 3, got: %d", len(newCatalog.Schemas))
-				}
-			},
-		},
-		{
-			name: "AllowedMissingSchema",
-			stmt: &ast.DropSchemaStmt{
-				Schemas: []*ast.String{
-					{
-						Str: "schema10",
-					},
-				},
-				MissingOk: true,
-			},
-			outStub: func(t *testing.T, newCatalog *Catalog, err error) {
-
-				if err != nil {
-					t.Errorf("err should be nil, got: %v", err)
-				}
-
-				if len(newCatalog.Schemas) != 5 {
-					t.Errorf("catalog schema length: want 5, got: %d", len(newCatalog.Schemas))
-				}
-			},
-		},
-		{
-			name: "SchemaNotFound",
-			stmt: &ast.DropSchemaStmt{
-				Schemas: []*ast.String{
-					{
-						Str: "missing_schema",
-					},
-				},
-			},
-			outStub: func(t *testing.T, newCatalog *Catalog, err error) {
-
-				if err == nil {
-					t.Error("err should not nil")
-				}
-
-				if len(newCatalog.Schemas) != 5 {
-					t.Errorf("catalog schema length: want 5, got: %d", len(newCatalog.Schemas))
-				}
-			},
-		},
-	}
-
-	for i := range testCases {
-
-		tc := testCases[i]
-
-		t.Run(tc.name, func(t *testing.T) {
-
-			newCatalog := New("default")
-
-			newCatalog.Schemas = append(
-				newCatalog.Schemas,
-				&Schema{Name: "schema1"},
-				&Schema{Name: "schema2"},
-				&Schema{Name: "schema3"},
-				&Schema{Name: "schema4"})
-
-			err := newCatalog.dropSchema(tc.stmt)
-			tc.outStub(t, newCatalog, err)
-		})
-	}
-}
diff --git a/internal/sql/catalog/table_test.go b/internal/sql/catalog/table_test.go
deleted file mode 100644
index ecffd3e37e..0000000000
--- a/internal/sql/catalog/table_test.go
+++ /dev/null
@@ -1,40 +0,0 @@
-package catalog
-
-import (
-	"testing"
-
-	"github.com/kyleconroy/sqlc/internal/sql/ast"
-)
-
-func TestGetTable(t *testing.T) {
-
-	testCases := []struct {
-		name      string
-		tableName *ast.TableName
-		outStub   func(t *testing.T, outSchema *Schema, outTable *Table, err error)
-	}{
-		{
-			name: "Use Catalog Default Schema",
-			tableName: &ast.TableName{
-				Catalog: "catalog1",
-				Schema:  "",
-				Name:    "table1",
-			},
-			outStub: func(t *testing.T, outSchema *Schema, outTable *Table, err error) {
-
-			},
-		},
-	}
-
-	newCatalog := New("default")
-
-	for i := range testCases {
-
-		tc := testCases[i]
-
-		outSchema, outTable, err := newCatalog.getTable(tc.tableName)
-
-		tc.outStub(t, outSchema, outTable, err)
-
-	}
-}

From 3db8cbbda88df0eaf80a85053e594467dce1768d Mon Sep 17 00:00:00 2001
From: Songa Ogutu <songabarry@gmail.com>
Date: Thu, 12 May 2022 08:13:30 +0300
Subject: [PATCH 4/7] Refactor catalog getTable to improve readability

---
 internal/sql/catalog/catalog.go |  15 ++-
 internal/sql/catalog/table.go   | 209 ++++++++++++++++++++------------
 2 files changed, 139 insertions(+), 85 deletions(-)

diff --git a/internal/sql/catalog/catalog.go b/internal/sql/catalog/catalog.go
index 699865c74a..798a636d8c 100644
--- a/internal/sql/catalog/catalog.go
+++ b/internal/sql/catalog/catalog.go
@@ -19,13 +19,18 @@ type Catalog struct {
 
 // New creates a new catalog
 func New(defaultSchema string) *Catalog {
-	return &Catalog{
+
+	newCatalog := &Catalog{
 		DefaultSchema: defaultSchema,
-		Schemas: []*Schema{
-			{Name: defaultSchema},
-		},
-		Extensions: make(map[string]struct{}),
+		Schemas:       make([]*Schema, 0),
+		Extensions:    make(map[string]struct{}),
+	}
+
+	if newCatalog.DefaultSchema != "" {
+		newCatalog.Schemas = append(newCatalog.Schemas, &Schema{Name: defaultSchema})
 	}
+
+	return newCatalog
 }
 
 func (c *Catalog) Build(stmts []ast.Statement) error {
diff --git a/internal/sql/catalog/table.go b/internal/sql/catalog/table.go
index 780b718f5f..2b9df6597e 100644
--- a/internal/sql/catalog/table.go
+++ b/internal/sql/catalog/table.go
@@ -18,6 +18,100 @@ type Table struct {
 	Comment string
 }
 
+func (table *Table) isExistColumn(cmd *ast.AlterTableCmd) (int, error) {
+
+	for i, c := range table.Columns {
+		if c.Name == *cmd.Name {
+			return i, nil
+		}
+	}
+
+	if !cmd.MissingOk {
+		return -1, sqlerr.ColumnNotFound(table.Rel.Name, *cmd.Name)
+	}
+
+	// Missing column is allowed
+	return -1, nil
+}
+
+func (table *Table) addColumn(cmd *ast.AlterTableCmd) error {
+
+	for _, c := range table.Columns {
+		if c.Name == cmd.Def.Colname {
+			return sqlerr.ColumnExists(table.Rel.Name, c.Name)
+		}
+	}
+
+	table.Columns = append(table.Columns, &Column{
+		Name:      cmd.Def.Colname,
+		Type:      *cmd.Def.TypeName,
+		IsNotNull: cmd.Def.IsNotNull,
+		IsArray:   cmd.Def.IsArray,
+		Length:    cmd.Def.Length,
+	})
+
+	return nil
+}
+
+func (table *Table) alterColumnType(cmd *ast.AlterTableCmd) error {
+
+	index, err := table.isExistColumn(cmd)
+	if err != nil {
+		return err
+	}
+
+	if index >= 0 {
+		table.Columns[index].Type = *cmd.Def.TypeName
+		table.Columns[index].IsArray = cmd.Def.IsArray
+	}
+
+	return nil
+}
+
+func (table *Table) dropColumn(cmd *ast.AlterTableCmd) error {
+
+	index, err := table.isExistColumn(cmd)
+	if err != nil {
+		return err
+	}
+
+	if index >= 0 {
+		table.Columns = append(table.Columns[:index], table.Columns[index+1:]...)
+	}
+
+	return nil
+}
+
+func (table *Table) dropNotNull(cmd *ast.AlterTableCmd) error {
+
+	index, err := table.isExistColumn(cmd)
+	if err != nil {
+		return err
+	}
+
+	if index >= 0 {
+		table.Columns[index].IsNotNull = false
+	}
+
+	return nil
+}
+
+func (table *Table) setNotNull(cmd *ast.AlterTableCmd) error {
+
+	index, err := table.isExistColumn(cmd)
+	if err != nil {
+		return err
+	}
+
+	if index >= 0 {
+		table.Columns[index].IsNotNull = true
+	}
+
+	return nil
+}
+
+// Column describes a set of data values of a particular type in a relational database table
+//
 // TODO: Should this just be ast Nodes?
 type Column struct {
 	Name      string
@@ -35,114 +129,69 @@ type columnGenerator interface {
 	OutputColumns(node ast.Node) ([]*Column, error)
 }
 
-func (c *Catalog) getTable(name *ast.TableName) (*Schema, *Table, error) {
-	ns := name.Schema
-	if ns == "" {
-		ns = c.DefaultSchema
+func (c *Catalog) getTable(tableName *ast.TableName) (*Schema, *Table, error) {
+
+	schemaName := tableName.Schema
+
+	if schemaName == "" {
+		schemaName = c.DefaultSchema
 	}
-	var s *Schema
+
+	var schema *Schema
+
 	for i := range c.Schemas {
-		if c.Schemas[i].Name == ns {
-			s = c.Schemas[i]
+		if c.Schemas[i].Name == schemaName {
+			schema = c.Schemas[i]
 			break
 		}
 	}
-	if s == nil {
-		return nil, nil, sqlerr.SchemaNotFound(ns)
+
+	if schema == nil {
+		return nil, nil, sqlerr.SchemaNotFound(schemaName)
 	}
-	t, _, err := s.getTable(name)
+
+	table, _, err := schema.getTable(tableName)
 	if err != nil {
 		return nil, nil, err
 	}
-	return s, t, nil
+
+	return schema, table, nil
 }
 
 func (c *Catalog) alterTable(stmt *ast.AlterTableStmt) error {
-	var implemented bool
-	for _, item := range stmt.Cmds.Items {
-		switch cmd := item.(type) {
-		case *ast.AlterTableCmd:
-			switch cmd.Subtype {
-			case ast.AT_AddColumn:
-				implemented = true
-			case ast.AT_AlterColumnType:
-				implemented = true
-			case ast.AT_DropColumn:
-				implemented = true
-			case ast.AT_DropNotNull:
-				implemented = true
-			case ast.AT_SetNotNull:
-				implemented = true
-			}
-		}
-	}
-	if !implemented {
-		return nil
-	}
+
 	_, table, err := c.getTable(stmt.Table)
 	if err != nil {
 		return err
 	}
 
-	for _, cmd := range stmt.Cmds.Items {
-		switch cmd := cmd.(type) {
+	for _, item := range stmt.Cmds.Items {
+		switch cmd := item.(type) {
 		case *ast.AlterTableCmd:
-			idx := -1
-
-			// Lookup column names for column-related commands
 			switch cmd.Subtype {
-			case ast.AT_AlterColumnType,
-				ast.AT_DropColumn,
-				ast.AT_DropNotNull,
-				ast.AT_SetNotNull:
-				for i, c := range table.Columns {
-					if c.Name == *cmd.Name {
-						idx = i
-						break
-					}
-				}
-				if idx < 0 && !cmd.MissingOk {
-					return sqlerr.ColumnNotFound(table.Rel.Name, *cmd.Name)
-				}
-				// If a missing column is allowed, skip this command
-				if idx < 0 && cmd.MissingOk {
-					continue
-				}
-			}
-
-			switch cmd.Subtype {
-
 			case ast.AT_AddColumn:
-				for _, c := range table.Columns {
-					if c.Name == cmd.Def.Colname {
-						return sqlerr.ColumnExists(table.Rel.Name, c.Name)
-					}
+				if err := table.addColumn(cmd); err != nil {
+					return err
 				}
-				table.Columns = append(table.Columns, &Column{
-					Name:      cmd.Def.Colname,
-					Type:      *cmd.Def.TypeName,
-					IsNotNull: cmd.Def.IsNotNull,
-					IsArray:   cmd.Def.IsArray,
-					Length:    cmd.Def.Length,
-				})
-
 			case ast.AT_AlterColumnType:
-				table.Columns[idx].Type = *cmd.Def.TypeName
-				table.Columns[idx].IsArray = cmd.Def.IsArray
-
+				if err := table.alterColumnType(cmd); err != nil {
+					return err
+				}
 			case ast.AT_DropColumn:
-				table.Columns = append(table.Columns[:idx], table.Columns[idx+1:]...)
-
+				if err := table.dropColumn(cmd); err != nil {
+					return err
+				}
 			case ast.AT_DropNotNull:
-				table.Columns[idx].IsNotNull = false
-
+				if err := table.dropNotNull(cmd); err != nil {
+					return err
+				}
 			case ast.AT_SetNotNull:
-				table.Columns[idx].IsNotNull = true
-
+				if err := table.setNotNull(cmd); err != nil {
+					return err
+				}
 			}
 		}
 	}
-
 	return nil
 }
 

From 19a4eb3bbd36abb9588de99a54886d53b751647e Mon Sep 17 00:00:00 2001
From: Songa Ogutu <songabarry@gmail.com>
Date: Fri, 13 May 2022 12:53:40 +0300
Subject: [PATCH 5/7] Add endtoend test data for add table column

---
 .../ddl_alter_table_add_column/mysql/go/db.go | 31 ++++++++++++++++++
 .../mysql/go/models.go                        | 15 +++++++++
 .../mysql/go/query.sql.go                     | 19 +++++++++++
 .../mysql/query.sql                           |  2 ++
 .../mysql/schema.sql                          |  3 ++
 .../mysql/sqlc.json                           | 12 +++++++
 .../postgresql/pgx/go/db.go                   | 32 +++++++++++++++++++
 .../postgresql/pgx/go/models.go               | 15 +++++++++
 .../postgresql/pgx/go/query.sql.go            | 19 +++++++++++
 .../postgresql/pgx/query.sql                  |  2 ++
 .../postgresql/pgx/schema.sql                 |  3 ++
 .../postgresql/pgx/sqlc.json                  | 13 ++++++++
 .../postgresql/stdlib/go/db.go                | 31 ++++++++++++++++++
 .../postgresql/stdlib/go/models.go            | 15 +++++++++
 .../postgresql/stdlib/go/query.sql.go         | 19 +++++++++++
 .../postgresql/stdlib/query.sql               |  2 ++
 .../postgresql/stdlib/schema.sql              |  3 ++
 .../postgresql/stdlib/sqlc.json               | 12 +++++++
 18 files changed, 248 insertions(+)
 create mode 100644 internal/endtoend/testdata/ddl_alter_table_add_column/mysql/go/db.go
 create mode 100644 internal/endtoend/testdata/ddl_alter_table_add_column/mysql/go/models.go
 create mode 100644 internal/endtoend/testdata/ddl_alter_table_add_column/mysql/go/query.sql.go
 create mode 100644 internal/endtoend/testdata/ddl_alter_table_add_column/mysql/query.sql
 create mode 100644 internal/endtoend/testdata/ddl_alter_table_add_column/mysql/schema.sql
 create mode 100644 internal/endtoend/testdata/ddl_alter_table_add_column/mysql/sqlc.json
 create mode 100644 internal/endtoend/testdata/ddl_alter_table_add_column/postgresql/pgx/go/db.go
 create mode 100644 internal/endtoend/testdata/ddl_alter_table_add_column/postgresql/pgx/go/models.go
 create mode 100644 internal/endtoend/testdata/ddl_alter_table_add_column/postgresql/pgx/go/query.sql.go
 create mode 100644 internal/endtoend/testdata/ddl_alter_table_add_column/postgresql/pgx/query.sql
 create mode 100644 internal/endtoend/testdata/ddl_alter_table_add_column/postgresql/pgx/schema.sql
 create mode 100644 internal/endtoend/testdata/ddl_alter_table_add_column/postgresql/pgx/sqlc.json
 create mode 100644 internal/endtoend/testdata/ddl_alter_table_add_column/postgresql/stdlib/go/db.go
 create mode 100644 internal/endtoend/testdata/ddl_alter_table_add_column/postgresql/stdlib/go/models.go
 create mode 100644 internal/endtoend/testdata/ddl_alter_table_add_column/postgresql/stdlib/go/query.sql.go
 create mode 100644 internal/endtoend/testdata/ddl_alter_table_add_column/postgresql/stdlib/query.sql
 create mode 100644 internal/endtoend/testdata/ddl_alter_table_add_column/postgresql/stdlib/schema.sql
 create mode 100644 internal/endtoend/testdata/ddl_alter_table_add_column/postgresql/stdlib/sqlc.json

diff --git a/internal/endtoend/testdata/ddl_alter_table_add_column/mysql/go/db.go b/internal/endtoend/testdata/ddl_alter_table_add_column/mysql/go/db.go
new file mode 100644
index 0000000000..36ef5f4f45
--- /dev/null
+++ b/internal/endtoend/testdata/ddl_alter_table_add_column/mysql/go/db.go
@@ -0,0 +1,31 @@
+// Code generated by sqlc. DO NOT EDIT.
+// versions:
+//   sqlc v1.13.0
+
+package querytest
+
+import (
+	"context"
+	"database/sql"
+)
+
+type DBTX interface {
+	ExecContext(context.Context, string, ...interface{}) (sql.Result, error)
+	PrepareContext(context.Context, string) (*sql.Stmt, error)
+	QueryContext(context.Context, string, ...interface{}) (*sql.Rows, error)
+	QueryRowContext(context.Context, string, ...interface{}) *sql.Row
+}
+
+func New(db DBTX) *Queries {
+	return &Queries{db: db}
+}
+
+type Queries struct {
+	db DBTX
+}
+
+func (q *Queries) WithTx(tx *sql.Tx) *Queries {
+	return &Queries{
+		db: tx,
+	}
+}
diff --git a/internal/endtoend/testdata/ddl_alter_table_add_column/mysql/go/models.go b/internal/endtoend/testdata/ddl_alter_table_add_column/mysql/go/models.go
new file mode 100644
index 0000000000..771d118790
--- /dev/null
+++ b/internal/endtoend/testdata/ddl_alter_table_add_column/mysql/go/models.go
@@ -0,0 +1,15 @@
+// Code generated by sqlc. DO NOT EDIT.
+// versions:
+//   sqlc v1.13.0
+
+package querytest
+
+import (
+	"database/sql"
+)
+
+type Foo struct {
+	Bar string
+	Baz sql.NullInt32
+	Bio sql.NullInt32
+}
diff --git a/internal/endtoend/testdata/ddl_alter_table_add_column/mysql/go/query.sql.go b/internal/endtoend/testdata/ddl_alter_table_add_column/mysql/go/query.sql.go
new file mode 100644
index 0000000000..6070d0b2f4
--- /dev/null
+++ b/internal/endtoend/testdata/ddl_alter_table_add_column/mysql/go/query.sql.go
@@ -0,0 +1,19 @@
+// Code generated by sqlc. DO NOT EDIT.
+// versions:
+//   sqlc v1.13.0
+// source: query.sql
+
+package querytest
+
+import (
+	"context"
+)
+
+const placeholder = `-- name: Placeholder :exec
+SELECT 1
+`
+
+func (q *Queries) Placeholder(ctx context.Context) error {
+	_, err := q.db.ExecContext(ctx, placeholder)
+	return err
+}
diff --git a/internal/endtoend/testdata/ddl_alter_table_add_column/mysql/query.sql b/internal/endtoend/testdata/ddl_alter_table_add_column/mysql/query.sql
new file mode 100644
index 0000000000..bb628f9251
--- /dev/null
+++ b/internal/endtoend/testdata/ddl_alter_table_add_column/mysql/query.sql
@@ -0,0 +1,2 @@
+/* name: Placeholder :exec */
+SELECT 1;
diff --git a/internal/endtoend/testdata/ddl_alter_table_add_column/mysql/schema.sql b/internal/endtoend/testdata/ddl_alter_table_add_column/mysql/schema.sql
new file mode 100644
index 0000000000..0019a393a2
--- /dev/null
+++ b/internal/endtoend/testdata/ddl_alter_table_add_column/mysql/schema.sql
@@ -0,0 +1,3 @@
+CREATE TABLE foo (bar text NOT NULL);
+ALTER TABLE foo ADD COLUMN baz integer;
+ALTER TABLE foo ADD bio integer;
\ No newline at end of file
diff --git a/internal/endtoend/testdata/ddl_alter_table_add_column/mysql/sqlc.json b/internal/endtoend/testdata/ddl_alter_table_add_column/mysql/sqlc.json
new file mode 100644
index 0000000000..e41c39e8b3
--- /dev/null
+++ b/internal/endtoend/testdata/ddl_alter_table_add_column/mysql/sqlc.json
@@ -0,0 +1,12 @@
+{
+  "version": "1",
+  "packages": [
+    {
+      "path": "go",
+      "engine": "mysql",
+      "name": "querytest",
+      "schema": "schema.sql",
+      "queries": "query.sql"
+    }
+  ]
+}
diff --git a/internal/endtoend/testdata/ddl_alter_table_add_column/postgresql/pgx/go/db.go b/internal/endtoend/testdata/ddl_alter_table_add_column/postgresql/pgx/go/db.go
new file mode 100644
index 0000000000..b0157bd009
--- /dev/null
+++ b/internal/endtoend/testdata/ddl_alter_table_add_column/postgresql/pgx/go/db.go
@@ -0,0 +1,32 @@
+// Code generated by sqlc. DO NOT EDIT.
+// versions:
+//   sqlc v1.13.0
+
+package querytest
+
+import (
+	"context"
+
+	"github.com/jackc/pgconn"
+	"github.com/jackc/pgx/v4"
+)
+
+type DBTX interface {
+	Exec(context.Context, string, ...interface{}) (pgconn.CommandTag, error)
+	Query(context.Context, string, ...interface{}) (pgx.Rows, error)
+	QueryRow(context.Context, string, ...interface{}) pgx.Row
+}
+
+func New(db DBTX) *Queries {
+	return &Queries{db: db}
+}
+
+type Queries struct {
+	db DBTX
+}
+
+func (q *Queries) WithTx(tx pgx.Tx) *Queries {
+	return &Queries{
+		db: tx,
+	}
+}
diff --git a/internal/endtoend/testdata/ddl_alter_table_add_column/postgresql/pgx/go/models.go b/internal/endtoend/testdata/ddl_alter_table_add_column/postgresql/pgx/go/models.go
new file mode 100644
index 0000000000..771d118790
--- /dev/null
+++ b/internal/endtoend/testdata/ddl_alter_table_add_column/postgresql/pgx/go/models.go
@@ -0,0 +1,15 @@
+// Code generated by sqlc. DO NOT EDIT.
+// versions:
+//   sqlc v1.13.0
+
+package querytest
+
+import (
+	"database/sql"
+)
+
+type Foo struct {
+	Bar string
+	Baz sql.NullInt32
+	Bio sql.NullInt32
+}
diff --git a/internal/endtoend/testdata/ddl_alter_table_add_column/postgresql/pgx/go/query.sql.go b/internal/endtoend/testdata/ddl_alter_table_add_column/postgresql/pgx/go/query.sql.go
new file mode 100644
index 0000000000..98f12b1d40
--- /dev/null
+++ b/internal/endtoend/testdata/ddl_alter_table_add_column/postgresql/pgx/go/query.sql.go
@@ -0,0 +1,19 @@
+// Code generated by sqlc. DO NOT EDIT.
+// versions:
+//   sqlc v1.13.0
+// source: query.sql
+
+package querytest
+
+import (
+	"context"
+)
+
+const placeholder = `-- name: Placeholder :exec
+SELECT 1
+`
+
+func (q *Queries) Placeholder(ctx context.Context) error {
+	_, err := q.db.Exec(ctx, placeholder)
+	return err
+}
diff --git a/internal/endtoend/testdata/ddl_alter_table_add_column/postgresql/pgx/query.sql b/internal/endtoend/testdata/ddl_alter_table_add_column/postgresql/pgx/query.sql
new file mode 100644
index 0000000000..6520aef4b6
--- /dev/null
+++ b/internal/endtoend/testdata/ddl_alter_table_add_column/postgresql/pgx/query.sql
@@ -0,0 +1,2 @@
+-- name: Placeholder :exec
+SELECT 1;
diff --git a/internal/endtoend/testdata/ddl_alter_table_add_column/postgresql/pgx/schema.sql b/internal/endtoend/testdata/ddl_alter_table_add_column/postgresql/pgx/schema.sql
new file mode 100644
index 0000000000..01c3f60d0f
--- /dev/null
+++ b/internal/endtoend/testdata/ddl_alter_table_add_column/postgresql/pgx/schema.sql
@@ -0,0 +1,3 @@
+CREATE TABLE foo (bar text NOT NULL);
+ALTER TABLE foo ADD COLUMN baz int;
+ALTER TABLE foo ADD bio int;
diff --git a/internal/endtoend/testdata/ddl_alter_table_add_column/postgresql/pgx/sqlc.json b/internal/endtoend/testdata/ddl_alter_table_add_column/postgresql/pgx/sqlc.json
new file mode 100644
index 0000000000..d1244c9e7a
--- /dev/null
+++ b/internal/endtoend/testdata/ddl_alter_table_add_column/postgresql/pgx/sqlc.json
@@ -0,0 +1,13 @@
+{
+  "version": "1",
+  "packages": [
+    {
+      "path": "go",
+      "engine": "postgresql",
+      "sql_package": "pgx/v4",
+      "name": "querytest",
+      "schema": "schema.sql",
+      "queries": "query.sql"
+    }
+  ]
+}
diff --git a/internal/endtoend/testdata/ddl_alter_table_add_column/postgresql/stdlib/go/db.go b/internal/endtoend/testdata/ddl_alter_table_add_column/postgresql/stdlib/go/db.go
new file mode 100644
index 0000000000..36ef5f4f45
--- /dev/null
+++ b/internal/endtoend/testdata/ddl_alter_table_add_column/postgresql/stdlib/go/db.go
@@ -0,0 +1,31 @@
+// Code generated by sqlc. DO NOT EDIT.
+// versions:
+//   sqlc v1.13.0
+
+package querytest
+
+import (
+	"context"
+	"database/sql"
+)
+
+type DBTX interface {
+	ExecContext(context.Context, string, ...interface{}) (sql.Result, error)
+	PrepareContext(context.Context, string) (*sql.Stmt, error)
+	QueryContext(context.Context, string, ...interface{}) (*sql.Rows, error)
+	QueryRowContext(context.Context, string, ...interface{}) *sql.Row
+}
+
+func New(db DBTX) *Queries {
+	return &Queries{db: db}
+}
+
+type Queries struct {
+	db DBTX
+}
+
+func (q *Queries) WithTx(tx *sql.Tx) *Queries {
+	return &Queries{
+		db: tx,
+	}
+}
diff --git a/internal/endtoend/testdata/ddl_alter_table_add_column/postgresql/stdlib/go/models.go b/internal/endtoend/testdata/ddl_alter_table_add_column/postgresql/stdlib/go/models.go
new file mode 100644
index 0000000000..771d118790
--- /dev/null
+++ b/internal/endtoend/testdata/ddl_alter_table_add_column/postgresql/stdlib/go/models.go
@@ -0,0 +1,15 @@
+// Code generated by sqlc. DO NOT EDIT.
+// versions:
+//   sqlc v1.13.0
+
+package querytest
+
+import (
+	"database/sql"
+)
+
+type Foo struct {
+	Bar string
+	Baz sql.NullInt32
+	Bio sql.NullInt32
+}
diff --git a/internal/endtoend/testdata/ddl_alter_table_add_column/postgresql/stdlib/go/query.sql.go b/internal/endtoend/testdata/ddl_alter_table_add_column/postgresql/stdlib/go/query.sql.go
new file mode 100644
index 0000000000..6070d0b2f4
--- /dev/null
+++ b/internal/endtoend/testdata/ddl_alter_table_add_column/postgresql/stdlib/go/query.sql.go
@@ -0,0 +1,19 @@
+// Code generated by sqlc. DO NOT EDIT.
+// versions:
+//   sqlc v1.13.0
+// source: query.sql
+
+package querytest
+
+import (
+	"context"
+)
+
+const placeholder = `-- name: Placeholder :exec
+SELECT 1
+`
+
+func (q *Queries) Placeholder(ctx context.Context) error {
+	_, err := q.db.ExecContext(ctx, placeholder)
+	return err
+}
diff --git a/internal/endtoend/testdata/ddl_alter_table_add_column/postgresql/stdlib/query.sql b/internal/endtoend/testdata/ddl_alter_table_add_column/postgresql/stdlib/query.sql
new file mode 100644
index 0000000000..6520aef4b6
--- /dev/null
+++ b/internal/endtoend/testdata/ddl_alter_table_add_column/postgresql/stdlib/query.sql
@@ -0,0 +1,2 @@
+-- name: Placeholder :exec
+SELECT 1;
diff --git a/internal/endtoend/testdata/ddl_alter_table_add_column/postgresql/stdlib/schema.sql b/internal/endtoend/testdata/ddl_alter_table_add_column/postgresql/stdlib/schema.sql
new file mode 100644
index 0000000000..01c3f60d0f
--- /dev/null
+++ b/internal/endtoend/testdata/ddl_alter_table_add_column/postgresql/stdlib/schema.sql
@@ -0,0 +1,3 @@
+CREATE TABLE foo (bar text NOT NULL);
+ALTER TABLE foo ADD COLUMN baz int;
+ALTER TABLE foo ADD bio int;
diff --git a/internal/endtoend/testdata/ddl_alter_table_add_column/postgresql/stdlib/sqlc.json b/internal/endtoend/testdata/ddl_alter_table_add_column/postgresql/stdlib/sqlc.json
new file mode 100644
index 0000000000..f717ca2e66
--- /dev/null
+++ b/internal/endtoend/testdata/ddl_alter_table_add_column/postgresql/stdlib/sqlc.json
@@ -0,0 +1,12 @@
+{
+  "version": "1",
+  "packages": [
+    {
+      "path": "go",
+      "engine": "postgresql",
+      "name": "querytest",
+      "schema": "schema.sql",
+      "queries": "query.sql"
+    }
+  ]
+}

From 434eba3764777307d769110d1a0f7d739e281192 Mon Sep 17 00:00:00 2001
From: Songa Ogutu <songabarry@gmail.com>
Date: Fri, 13 May 2022 13:21:36 +0300
Subject: [PATCH 6/7] Add endtoend test for mysql alter column type

---
 .../ddl_alter_table_alter_type/mysql/go/db.go | 31 +++++++++++++++++++
 .../mysql/go/models.go                        | 14 +++++++++
 .../mysql/go/query.sql.go                     | 19 ++++++++++++
 .../mysql/query.sql                           |  2 ++
 .../mysql/schema.sql                          |  3 ++
 .../mysql/sqlc.json                           | 12 +++++++
 6 files changed, 81 insertions(+)
 create mode 100644 internal/endtoend/testdata/ddl_alter_table_alter_type/mysql/go/db.go
 create mode 100644 internal/endtoend/testdata/ddl_alter_table_alter_type/mysql/go/models.go
 create mode 100644 internal/endtoend/testdata/ddl_alter_table_alter_type/mysql/go/query.sql.go
 create mode 100644 internal/endtoend/testdata/ddl_alter_table_alter_type/mysql/query.sql
 create mode 100644 internal/endtoend/testdata/ddl_alter_table_alter_type/mysql/schema.sql
 create mode 100644 internal/endtoend/testdata/ddl_alter_table_alter_type/mysql/sqlc.json

diff --git a/internal/endtoend/testdata/ddl_alter_table_alter_type/mysql/go/db.go b/internal/endtoend/testdata/ddl_alter_table_alter_type/mysql/go/db.go
new file mode 100644
index 0000000000..36ef5f4f45
--- /dev/null
+++ b/internal/endtoend/testdata/ddl_alter_table_alter_type/mysql/go/db.go
@@ -0,0 +1,31 @@
+// Code generated by sqlc. DO NOT EDIT.
+// versions:
+//   sqlc v1.13.0
+
+package querytest
+
+import (
+	"context"
+	"database/sql"
+)
+
+type DBTX interface {
+	ExecContext(context.Context, string, ...interface{}) (sql.Result, error)
+	PrepareContext(context.Context, string) (*sql.Stmt, error)
+	QueryContext(context.Context, string, ...interface{}) (*sql.Rows, error)
+	QueryRowContext(context.Context, string, ...interface{}) *sql.Row
+}
+
+func New(db DBTX) *Queries {
+	return &Queries{db: db}
+}
+
+type Queries struct {
+	db DBTX
+}
+
+func (q *Queries) WithTx(tx *sql.Tx) *Queries {
+	return &Queries{
+		db: tx,
+	}
+}
diff --git a/internal/endtoend/testdata/ddl_alter_table_alter_type/mysql/go/models.go b/internal/endtoend/testdata/ddl_alter_table_alter_type/mysql/go/models.go
new file mode 100644
index 0000000000..7c85bddf45
--- /dev/null
+++ b/internal/endtoend/testdata/ddl_alter_table_alter_type/mysql/go/models.go
@@ -0,0 +1,14 @@
+// Code generated by sqlc. DO NOT EDIT.
+// versions:
+//   sqlc v1.13.0
+
+package querytest
+
+import (
+	"database/sql"
+)
+
+type Foo struct {
+	Bar sql.NullInt32
+	Baz sql.NullInt32
+}
diff --git a/internal/endtoend/testdata/ddl_alter_table_alter_type/mysql/go/query.sql.go b/internal/endtoend/testdata/ddl_alter_table_alter_type/mysql/go/query.sql.go
new file mode 100644
index 0000000000..6070d0b2f4
--- /dev/null
+++ b/internal/endtoend/testdata/ddl_alter_table_alter_type/mysql/go/query.sql.go
@@ -0,0 +1,19 @@
+// Code generated by sqlc. DO NOT EDIT.
+// versions:
+//   sqlc v1.13.0
+// source: query.sql
+
+package querytest
+
+import (
+	"context"
+)
+
+const placeholder = `-- name: Placeholder :exec
+SELECT 1
+`
+
+func (q *Queries) Placeholder(ctx context.Context) error {
+	_, err := q.db.ExecContext(ctx, placeholder)
+	return err
+}
diff --git a/internal/endtoend/testdata/ddl_alter_table_alter_type/mysql/query.sql b/internal/endtoend/testdata/ddl_alter_table_alter_type/mysql/query.sql
new file mode 100644
index 0000000000..bb628f9251
--- /dev/null
+++ b/internal/endtoend/testdata/ddl_alter_table_alter_type/mysql/query.sql
@@ -0,0 +1,2 @@
+/* name: Placeholder :exec */
+SELECT 1;
diff --git a/internal/endtoend/testdata/ddl_alter_table_alter_type/mysql/schema.sql b/internal/endtoend/testdata/ddl_alter_table_alter_type/mysql/schema.sql
new file mode 100644
index 0000000000..a81bc00990
--- /dev/null
+++ b/internal/endtoend/testdata/ddl_alter_table_alter_type/mysql/schema.sql
@@ -0,0 +1,3 @@
+CREATE TABLE foo (bar text NOT NULL, baz text NOT NULL);
+ALTER TABLE foo MODIFY COLUMN bar integer;
+ALTER TABLE foo MODIFY baz integer;
diff --git a/internal/endtoend/testdata/ddl_alter_table_alter_type/mysql/sqlc.json b/internal/endtoend/testdata/ddl_alter_table_alter_type/mysql/sqlc.json
new file mode 100644
index 0000000000..e41c39e8b3
--- /dev/null
+++ b/internal/endtoend/testdata/ddl_alter_table_alter_type/mysql/sqlc.json
@@ -0,0 +1,12 @@
+{
+  "version": "1",
+  "packages": [
+    {
+      "path": "go",
+      "engine": "mysql",
+      "name": "querytest",
+      "schema": "schema.sql",
+      "queries": "query.sql"
+    }
+  ]
+}

From 7b98e978f9ac4899a4657f985cf14194fa698268 Mon Sep 17 00:00:00 2001
From: Songa Ogutu <songabarry@gmail.com>
Date: Fri, 13 May 2022 13:28:03 +0300
Subject: [PATCH 7/7] Add endtoend testdata for postgresql rename column

---
 .../postgresql/pgx/go/db.go                   | 32 +++++++++++++++++++
 .../postgresql/pgx/go/models.go               | 11 +++++++
 .../postgresql/pgx/go/query.sql.go            | 19 +++++++++++
 .../postgresql/pgx/query.sql                  |  2 ++
 .../postgresql/pgx/schema.sql                 |  2 ++
 .../postgresql/pgx/sqlc.json                  | 13 ++++++++
 .../postgresql/stdlib/go/db.go                | 31 ++++++++++++++++++
 .../postgresql/stdlib/go/models.go            | 11 +++++++
 .../postgresql/stdlib/go/query.sql.go         | 19 +++++++++++
 .../postgresql/stdlib/query.sql               |  2 ++
 .../postgresql/stdlib/schema.sql              |  2 ++
 .../postgresql/stdlib/sqlc.json               | 12 +++++++
 12 files changed, 156 insertions(+)
 create mode 100644 internal/endtoend/testdata/ddl_alter_table_change_column/postgresql/pgx/go/db.go
 create mode 100644 internal/endtoend/testdata/ddl_alter_table_change_column/postgresql/pgx/go/models.go
 create mode 100644 internal/endtoend/testdata/ddl_alter_table_change_column/postgresql/pgx/go/query.sql.go
 create mode 100644 internal/endtoend/testdata/ddl_alter_table_change_column/postgresql/pgx/query.sql
 create mode 100644 internal/endtoend/testdata/ddl_alter_table_change_column/postgresql/pgx/schema.sql
 create mode 100644 internal/endtoend/testdata/ddl_alter_table_change_column/postgresql/pgx/sqlc.json
 create mode 100644 internal/endtoend/testdata/ddl_alter_table_change_column/postgresql/stdlib/go/db.go
 create mode 100644 internal/endtoend/testdata/ddl_alter_table_change_column/postgresql/stdlib/go/models.go
 create mode 100644 internal/endtoend/testdata/ddl_alter_table_change_column/postgresql/stdlib/go/query.sql.go
 create mode 100644 internal/endtoend/testdata/ddl_alter_table_change_column/postgresql/stdlib/query.sql
 create mode 100644 internal/endtoend/testdata/ddl_alter_table_change_column/postgresql/stdlib/schema.sql
 create mode 100644 internal/endtoend/testdata/ddl_alter_table_change_column/postgresql/stdlib/sqlc.json

diff --git a/internal/endtoend/testdata/ddl_alter_table_change_column/postgresql/pgx/go/db.go b/internal/endtoend/testdata/ddl_alter_table_change_column/postgresql/pgx/go/db.go
new file mode 100644
index 0000000000..b0157bd009
--- /dev/null
+++ b/internal/endtoend/testdata/ddl_alter_table_change_column/postgresql/pgx/go/db.go
@@ -0,0 +1,32 @@
+// Code generated by sqlc. DO NOT EDIT.
+// versions:
+//   sqlc v1.13.0
+
+package querytest
+
+import (
+	"context"
+
+	"github.com/jackc/pgconn"
+	"github.com/jackc/pgx/v4"
+)
+
+type DBTX interface {
+	Exec(context.Context, string, ...interface{}) (pgconn.CommandTag, error)
+	Query(context.Context, string, ...interface{}) (pgx.Rows, error)
+	QueryRow(context.Context, string, ...interface{}) pgx.Row
+}
+
+func New(db DBTX) *Queries {
+	return &Queries{db: db}
+}
+
+type Queries struct {
+	db DBTX
+}
+
+func (q *Queries) WithTx(tx pgx.Tx) *Queries {
+	return &Queries{
+		db: tx,
+	}
+}
diff --git a/internal/endtoend/testdata/ddl_alter_table_change_column/postgresql/pgx/go/models.go b/internal/endtoend/testdata/ddl_alter_table_change_column/postgresql/pgx/go/models.go
new file mode 100644
index 0000000000..d4b8977f56
--- /dev/null
+++ b/internal/endtoend/testdata/ddl_alter_table_change_column/postgresql/pgx/go/models.go
@@ -0,0 +1,11 @@
+// Code generated by sqlc. DO NOT EDIT.
+// versions:
+//   sqlc v1.13.0
+
+package querytest
+
+import ()
+
+type Foo struct {
+	Baz string
+}
diff --git a/internal/endtoend/testdata/ddl_alter_table_change_column/postgresql/pgx/go/query.sql.go b/internal/endtoend/testdata/ddl_alter_table_change_column/postgresql/pgx/go/query.sql.go
new file mode 100644
index 0000000000..98f12b1d40
--- /dev/null
+++ b/internal/endtoend/testdata/ddl_alter_table_change_column/postgresql/pgx/go/query.sql.go
@@ -0,0 +1,19 @@
+// Code generated by sqlc. DO NOT EDIT.
+// versions:
+//   sqlc v1.13.0
+// source: query.sql
+
+package querytest
+
+import (
+	"context"
+)
+
+const placeholder = `-- name: Placeholder :exec
+SELECT 1
+`
+
+func (q *Queries) Placeholder(ctx context.Context) error {
+	_, err := q.db.Exec(ctx, placeholder)
+	return err
+}
diff --git a/internal/endtoend/testdata/ddl_alter_table_change_column/postgresql/pgx/query.sql b/internal/endtoend/testdata/ddl_alter_table_change_column/postgresql/pgx/query.sql
new file mode 100644
index 0000000000..6520aef4b6
--- /dev/null
+++ b/internal/endtoend/testdata/ddl_alter_table_change_column/postgresql/pgx/query.sql
@@ -0,0 +1,2 @@
+-- name: Placeholder :exec
+SELECT 1;
diff --git a/internal/endtoend/testdata/ddl_alter_table_change_column/postgresql/pgx/schema.sql b/internal/endtoend/testdata/ddl_alter_table_change_column/postgresql/pgx/schema.sql
new file mode 100644
index 0000000000..501fc0c0f4
--- /dev/null
+++ b/internal/endtoend/testdata/ddl_alter_table_change_column/postgresql/pgx/schema.sql
@@ -0,0 +1,2 @@
+CREATE TABLE foo (bar text NOT NULL);
+ALTER TABLE foo RENAME COLUMN bar TO baz;
diff --git a/internal/endtoend/testdata/ddl_alter_table_change_column/postgresql/pgx/sqlc.json b/internal/endtoend/testdata/ddl_alter_table_change_column/postgresql/pgx/sqlc.json
new file mode 100644
index 0000000000..d1244c9e7a
--- /dev/null
+++ b/internal/endtoend/testdata/ddl_alter_table_change_column/postgresql/pgx/sqlc.json
@@ -0,0 +1,13 @@
+{
+  "version": "1",
+  "packages": [
+    {
+      "path": "go",
+      "engine": "postgresql",
+      "sql_package": "pgx/v4",
+      "name": "querytest",
+      "schema": "schema.sql",
+      "queries": "query.sql"
+    }
+  ]
+}
diff --git a/internal/endtoend/testdata/ddl_alter_table_change_column/postgresql/stdlib/go/db.go b/internal/endtoend/testdata/ddl_alter_table_change_column/postgresql/stdlib/go/db.go
new file mode 100644
index 0000000000..36ef5f4f45
--- /dev/null
+++ b/internal/endtoend/testdata/ddl_alter_table_change_column/postgresql/stdlib/go/db.go
@@ -0,0 +1,31 @@
+// Code generated by sqlc. DO NOT EDIT.
+// versions:
+//   sqlc v1.13.0
+
+package querytest
+
+import (
+	"context"
+	"database/sql"
+)
+
+type DBTX interface {
+	ExecContext(context.Context, string, ...interface{}) (sql.Result, error)
+	PrepareContext(context.Context, string) (*sql.Stmt, error)
+	QueryContext(context.Context, string, ...interface{}) (*sql.Rows, error)
+	QueryRowContext(context.Context, string, ...interface{}) *sql.Row
+}
+
+func New(db DBTX) *Queries {
+	return &Queries{db: db}
+}
+
+type Queries struct {
+	db DBTX
+}
+
+func (q *Queries) WithTx(tx *sql.Tx) *Queries {
+	return &Queries{
+		db: tx,
+	}
+}
diff --git a/internal/endtoend/testdata/ddl_alter_table_change_column/postgresql/stdlib/go/models.go b/internal/endtoend/testdata/ddl_alter_table_change_column/postgresql/stdlib/go/models.go
new file mode 100644
index 0000000000..d4b8977f56
--- /dev/null
+++ b/internal/endtoend/testdata/ddl_alter_table_change_column/postgresql/stdlib/go/models.go
@@ -0,0 +1,11 @@
+// Code generated by sqlc. DO NOT EDIT.
+// versions:
+//   sqlc v1.13.0
+
+package querytest
+
+import ()
+
+type Foo struct {
+	Baz string
+}
diff --git a/internal/endtoend/testdata/ddl_alter_table_change_column/postgresql/stdlib/go/query.sql.go b/internal/endtoend/testdata/ddl_alter_table_change_column/postgresql/stdlib/go/query.sql.go
new file mode 100644
index 0000000000..6070d0b2f4
--- /dev/null
+++ b/internal/endtoend/testdata/ddl_alter_table_change_column/postgresql/stdlib/go/query.sql.go
@@ -0,0 +1,19 @@
+// Code generated by sqlc. DO NOT EDIT.
+// versions:
+//   sqlc v1.13.0
+// source: query.sql
+
+package querytest
+
+import (
+	"context"
+)
+
+const placeholder = `-- name: Placeholder :exec
+SELECT 1
+`
+
+func (q *Queries) Placeholder(ctx context.Context) error {
+	_, err := q.db.ExecContext(ctx, placeholder)
+	return err
+}
diff --git a/internal/endtoend/testdata/ddl_alter_table_change_column/postgresql/stdlib/query.sql b/internal/endtoend/testdata/ddl_alter_table_change_column/postgresql/stdlib/query.sql
new file mode 100644
index 0000000000..6520aef4b6
--- /dev/null
+++ b/internal/endtoend/testdata/ddl_alter_table_change_column/postgresql/stdlib/query.sql
@@ -0,0 +1,2 @@
+-- name: Placeholder :exec
+SELECT 1;
diff --git a/internal/endtoend/testdata/ddl_alter_table_change_column/postgresql/stdlib/schema.sql b/internal/endtoend/testdata/ddl_alter_table_change_column/postgresql/stdlib/schema.sql
new file mode 100644
index 0000000000..501fc0c0f4
--- /dev/null
+++ b/internal/endtoend/testdata/ddl_alter_table_change_column/postgresql/stdlib/schema.sql
@@ -0,0 +1,2 @@
+CREATE TABLE foo (bar text NOT NULL);
+ALTER TABLE foo RENAME COLUMN bar TO baz;
diff --git a/internal/endtoend/testdata/ddl_alter_table_change_column/postgresql/stdlib/sqlc.json b/internal/endtoend/testdata/ddl_alter_table_change_column/postgresql/stdlib/sqlc.json
new file mode 100644
index 0000000000..f717ca2e66
--- /dev/null
+++ b/internal/endtoend/testdata/ddl_alter_table_change_column/postgresql/stdlib/sqlc.json
@@ -0,0 +1,12 @@
+{
+  "version": "1",
+  "packages": [
+    {
+      "path": "go",
+      "engine": "postgresql",
+      "name": "querytest",
+      "schema": "schema.sql",
+      "queries": "query.sql"
+    }
+  ]
+}