Skip to content

Commit

Permalink
Merge pull request #34 from chuckpreslar/v0.4
Browse files Browse the repository at this point in the history
v0.4
  • Loading branch information
chuckpreslar committed Aug 15, 2013
2 parents f210bc8 + 490bba3 commit 44e8237
Show file tree
Hide file tree
Showing 8 changed files with 261 additions and 99 deletions.
27 changes: 26 additions & 1 deletion managers/alter_manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,13 @@ import (
"github.com/chuckpreslar/codex/sql"
)

// AlterManager manages a tree that compiles to SQL for create and alter statement.
type AlterManager struct {
Tree *nodes.AlterStatementNode // The AST for the SQL CREATE/ALTER TABLE statements.
adapter interface{} // The SQL adapter.
}

// AddColumn adds a UnexistingColumn from the nodes package to the AST for creation.
func (self *AlterManager) AddColumn(name interface{}, typ sql.Type) *AlterManager {
if _, ok := name.(string); ok {
name = nodes.UnqualifiedColumn(name)
Expand All @@ -20,15 +22,36 @@ func (self *AlterManager) AddColumn(name interface{}, typ sql.Type) *AlterManage
return self
}

// AddColumn adds a ConstraintNode from the nodes package to the AST to apply to a column.
func (self *AlterManager) AddConstraint(column interface{}, kind sql.Constraint, options ...interface{}) *AlterManager {
if _, ok := column.(string); ok {
column = nodes.UnqualifiedColumn(column)
}

self.Tree.Constraints = append(self.Tree.Constraints, nodes.Constraint(column, kind, options...))
var node interface{}

switch kind {
case sql.NOT_NULL:
node = nodes.NotNull(column, options...)
case sql.UNIQUE:
node = nodes.Unique(column, options...)
case sql.PRIMARY_KEY:
node = nodes.PrimaryKey(column, options...)
case sql.FOREIGN_KEY:
node = nodes.ForeignKey(column, options...)
case sql.CHECK:
node = nodes.Check(column, options...)
case sql.DEFAULT:
node = nodes.Default(column, options...)
default:
node = nodes.Constraint(column, options...)
}

self.Tree.Constraints = append(self.Tree.Constraints, node)
return self
}

// SetEngine sets the AST's Engine field, used for table creation.
func (self *AlterManager) SetEngine(engine interface{}) *AlterManager {
if _, ok := engine.(*nodes.EngineNode); !ok {
engine = nodes.Engine(engine)
Expand All @@ -38,11 +61,13 @@ func (self *AlterManager) SetEngine(engine interface{}) *AlterManager {
return self
}

// Sets the SQL Adapter.
func (self *AlterManager) SetAdapter(adapter interface{}) *AlterManager {
self.adapter = adapter
return self
}

// ToSql calls a visitor's Accept method based on the manager's SQL adapter.
func (self *AlterManager) ToSql() (string, error) {
if nil == self.adapter {
self.adapter = "to_sql"
Expand Down
2 changes: 1 addition & 1 deletion managers/delete_manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ func (self *DeleteManager) Delete(expr interface{}) *DeleteManager {
return self
}

// Sets the SQL Enginge.
// Sets the SQL Adapter.
func (self *DeleteManager) SetAdapter(adapter interface{}) *DeleteManager {
self.adapter = adapter
return self
Expand Down
13 changes: 7 additions & 6 deletions nodes/alter_statement.go
Original file line number Diff line number Diff line change
@@ -1,20 +1,21 @@
// Package nodes provides nodes to use in codex AST's.
package nodes

// AlterStatement is the base node for SQL Create and Alter Statements.
type AlterStatementNode struct {
Relation *RelationNode
Columns []*UnexistingColumnNode
Constraints []*ConstraintNode
Engine *EngineNode
Create bool
Relation *RelationNode // The RelationNode the AlterStatementNode affects.
Columns []*UnexistingColumnNode // Columns to create with the alteration.
Constraints []interface{} // Constraints to apply with the alteration.
Engine *EngineNode // Engine the table uses if created.
Create bool // Is the AlterStatementNode creating a table based on the RelationNode.
}

// AlterStatementNode factory method.
func AlterStatement(relation *RelationNode, create bool) (statement *AlterStatementNode) {
statement = new(AlterStatementNode)
statement.Relation = relation
statement.Columns = make([]*UnexistingColumnNode, 0)
statement.Constraints = make([]*ConstraintNode, 0)
statement.Constraints = make([]interface{}, 0)
statement.Create = create
return
}
69 changes: 59 additions & 10 deletions nodes/constraint_node.go
Original file line number Diff line number Diff line change
@@ -1,22 +1,71 @@
// Package nodes provides nodes to use in codex AST's.
package nodes

import (
"github.com/chuckpreslar/codex/sql"
)

// ConstraintNode is a Nary node.
// ConstraintNode is a specific Binary node.
type ConstraintNode struct {
Column interface{}
Kind sql.Constraint
Options []interface{}
Column interface{} // Column the ConstraintNode affects.
Options []interface{} // Options to apply to the ConstraintNode.
}

type NotNullNode ConstraintNode // NotNullNode is a ConstraintNode struct.
type UniqueNode ConstraintNode // UniqueNode is a ConstraintNode struct.
type PrimaryKeyNode ConstraintNode // PrimaryKeyNode is a ConstraintNode struct.
type ForeignKeyNode ConstraintNode // ForeignKeyNode is a ConstraintNode struct.
type CheckNode ConstraintNode // CheckNode is a ConstraintNode struct.
type DefaultNode ConstraintNode // DefaultNode is a ConstraintNode struct.

// ConstraintNode factory method.
func Constraint(column interface{}, kind sql.Constraint, options ...interface{}) (constraint *ConstraintNode) {
func Constraint(column interface{}, options ...interface{}) (constraint *ConstraintNode) {
constraint = new(ConstraintNode)
constraint.Column = column
constraint.Kind = kind
constraint.Options = options
return
}

// NotNullNode factory method.
func NotNull(column interface{}, options ...interface{}) (nnull *NotNullNode) {
nnull = new(NotNullNode)
nnull.Column = column
nnull.Options = options
return
}

// UniqueNode factory method.
func Unique(column interface{}, options ...interface{}) (unique *UniqueNode) {
unique = new(UniqueNode)
unique.Column = column
unique.Options = options
return
}

// PrimaryKeyNode factory method.
func PrimaryKey(column interface{}, options ...interface{}) (pkey *PrimaryKeyNode) {
pkey = new(PrimaryKeyNode)
pkey.Column = column
pkey.Options = options
return
}

// ForeignKeyNode factory method.
func ForeignKey(column interface{}, options ...interface{}) (fkey *ForeignKeyNode) {
fkey = new(ForeignKeyNode)
fkey.Column = column
fkey.Options = options
return
}

// CheckNode factory method.
func Check(column interface{}, options ...interface{}) (check *CheckNode) {
check = new(CheckNode)
check.Column = column
check.Options = options
return
}

// DefaultNode factory method.
func Default(column interface{}, options ...interface{}) (def *DefaultNode) {
def = new(DefaultNode)
def.Column = column
def.Options = options
return
}
23 changes: 23 additions & 0 deletions test/managers/alter_manager_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package managers

import (
"github.com/chuckpreslar/codex/managers"
"github.com/chuckpreslar/codex/nodes"
"github.com/chuckpreslar/codex/sql"
"testing"
)

func TestAlterManager(t *testing.T) {
relation := nodes.Relation("table")
mgr := managers.Alteration(relation, true)

// The following struct members should exist.
_ = mgr.Tree

// The following receiver methods should exist.
_ = mgr.AddColumn(1, sql.STRING)
_ = mgr.AddConstraint(1, sql.UNIQUE, 1, 2, 3)
_ = mgr.SetEngine(1)
_ = mgr.SetAdapter(1)
_, _ = mgr.ToSql()
}
40 changes: 40 additions & 0 deletions test/visitors/to_sql_visitors_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -420,6 +420,46 @@ func TestUnqualifiedColumn(t *testing.T) {
}
}

func TestVisitNotNull(t *testing.T) {
nnull := nodes.NotNull("column")
expected := `ALTER 'column' SET NOT NULL`
if got, _ := sql.Accept(nnull); expected != got {
t.Errorf("TestVisitNotNull was expected to return %s, got %s", expected, got)
}
}

func TestVisitUnique(t *testing.T) {
unique := nodes.Unique("column")
expected := `ADD UNIQUE('column')`
if got, _ := sql.Accept(unique); expected != got {
t.Errorf("TestVisitUnique was expected to return %s, got %s", expected, got)
}
}

func TestVisitPrimaryKey(t *testing.T) {
pkey := nodes.PrimaryKey("column")
expected := `ADD PRIMARY KEY('column')`
if got, _ := sql.Accept(pkey); expected != got {
t.Errorf("TestVisitPrimaryKey was expected to return %s, got %s", expected, got)
}
}

func TestVisitForeignKey(t *testing.T) {
fkey := nodes.ForeignKey("column")
expected := `ADD FOREIGN KEY('column')`
if got, _ := sql.Accept(fkey); expected != got {
t.Errorf("TestVisitForeignKey was expected to return %s, got %s", expected, got)
}
}

func TestVisitDefault(t *testing.T) {
def := nodes.Default("column")
expected := `ALTER 'column' SET DEFAULT`
if got, _ := sql.Accept(def); expected != got {
t.Errorf("TestVisitDefault was expected to return %s, got %s", expected, got)
}
}

func TestVisitString(t *testing.T) {
value, expected := `test`, `'test'`
if got, _ := sql.Accept(value); expected != got {
Expand Down
Loading

0 comments on commit 44e8237

Please sign in to comment.