Table interface cleanup.
This commit is contained in:
parent
5de001d7e0
commit
0643768673
4 changed files with 38 additions and 85 deletions
|
|
@ -15,7 +15,7 @@ type Column interface {
|
||||||
DefaultAlias() Projection
|
DefaultAlias() Projection
|
||||||
// Internal function for tracking tableName that a column belongs to
|
// Internal function for tracking tableName that a column belongs to
|
||||||
// for the purpose of serialization
|
// for the purpose of serialization
|
||||||
setTableName(table string) error
|
setTableName(table string)
|
||||||
}
|
}
|
||||||
|
|
||||||
type NullableColumn bool
|
type NullableColumn bool
|
||||||
|
|
@ -69,9 +69,8 @@ func (c *baseColumn) TableName() string {
|
||||||
return c.tableName
|
return c.tableName
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *baseColumn) setTableName(table string) error {
|
func (c *baseColumn) setTableName(table string) {
|
||||||
c.tableName = table
|
c.tableName = table
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *baseColumn) DefaultAlias() Projection {
|
func (c *baseColumn) DefaultAlias() Projection {
|
||||||
|
|
|
||||||
|
|
@ -20,15 +20,13 @@ func TestNewBoolColumn(t *testing.T) {
|
||||||
assert.Equal(t, out.buff.String(), "col")
|
assert.Equal(t, out.buff.String(), "col")
|
||||||
|
|
||||||
out.Reset()
|
out.Reset()
|
||||||
err = boolColumn.setTableName("table1")
|
boolColumn.setTableName("table1")
|
||||||
assert.NilError(t, err)
|
|
||||||
err = boolColumn.DefaultAlias().SerializeForProjection(&out)
|
err = boolColumn.DefaultAlias().SerializeForProjection(&out)
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
assert.Equal(t, out.buff.String(), `table1.col AS "table1.col"`)
|
assert.Equal(t, out.buff.String(), `table1.col AS "table1.col"`)
|
||||||
|
|
||||||
out.Reset()
|
out.Reset()
|
||||||
err = boolColumn.setTableName("table1")
|
boolColumn.setTableName("table1")
|
||||||
assert.NilError(t, err)
|
|
||||||
aliasedBoolColumn := boolColumn.As("alias1")
|
aliasedBoolColumn := boolColumn.As("alias1")
|
||||||
err = aliasedBoolColumn.SerializeForProjection(&out)
|
err = aliasedBoolColumn.SerializeForProjection(&out)
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
|
|
@ -50,15 +48,13 @@ func TestNewIntColumn(t *testing.T) {
|
||||||
assert.Equal(t, out.buff.String(), "col")
|
assert.Equal(t, out.buff.String(), "col")
|
||||||
|
|
||||||
out.Reset()
|
out.Reset()
|
||||||
err = integerColumn.setTableName("table1")
|
integerColumn.setTableName("table1")
|
||||||
assert.NilError(t, err)
|
|
||||||
err = integerColumn.DefaultAlias().SerializeForProjection(&out)
|
err = integerColumn.DefaultAlias().SerializeForProjection(&out)
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
assert.Equal(t, out.buff.String(), `table1.col AS "table1.col"`)
|
assert.Equal(t, out.buff.String(), `table1.col AS "table1.col"`)
|
||||||
|
|
||||||
out.Reset()
|
out.Reset()
|
||||||
err = integerColumn.setTableName("table1")
|
integerColumn.setTableName("table1")
|
||||||
assert.NilError(t, err)
|
|
||||||
aliasedBoolColumn := integerColumn.As("alias1")
|
aliasedBoolColumn := integerColumn.As("alias1")
|
||||||
err = aliasedBoolColumn.SerializeForProjection(&out)
|
err = aliasedBoolColumn.SerializeForProjection(&out)
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
|
|
@ -80,15 +76,13 @@ func TestNewNumericColumnColumn(t *testing.T) {
|
||||||
assert.Equal(t, out.buff.String(), "col")
|
assert.Equal(t, out.buff.String(), "col")
|
||||||
|
|
||||||
out.Reset()
|
out.Reset()
|
||||||
err = numericColumn.setTableName("table1")
|
numericColumn.setTableName("table1")
|
||||||
assert.NilError(t, err)
|
|
||||||
err = numericColumn.DefaultAlias().SerializeForProjection(&out)
|
err = numericColumn.DefaultAlias().SerializeForProjection(&out)
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
assert.Equal(t, out.buff.String(), `table1.col AS "table1.col"`)
|
assert.Equal(t, out.buff.String(), `table1.col AS "table1.col"`)
|
||||||
|
|
||||||
out.Reset()
|
out.Reset()
|
||||||
err = numericColumn.setTableName("table1")
|
numericColumn.setTableName("table1")
|
||||||
assert.NilError(t, err)
|
|
||||||
aliasedBoolColumn := numericColumn.As("alias1")
|
aliasedBoolColumn := numericColumn.As("alias1")
|
||||||
err = aliasedBoolColumn.SerializeForProjection(&out)
|
err = aliasedBoolColumn.SerializeForProjection(&out)
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
|
|
|
||||||
|
|
@ -3,24 +3,22 @@
|
||||||
package sqlbuilder
|
package sqlbuilder
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"github.com/dropbox/godropbox/errors"
|
"github.com/dropbox/godropbox/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
type TableInterface interface {
|
type tableInterface interface {
|
||||||
SchemaName() string
|
SchemaName() string
|
||||||
TableName() string
|
TableName() string
|
||||||
// Returns the list of columns that are in the current tableName expression.
|
|
||||||
Columns() []Column
|
Columns() []Column
|
||||||
// Generates the sql string for the current tableName expression. Note: the
|
// Generates the sql string for the current tableName expression.
|
||||||
// generated string may not be a valid/executable sql statement.
|
|
||||||
SerializeSql(out *queryData) error
|
SerializeSql(out *queryData) error
|
||||||
}
|
}
|
||||||
|
|
||||||
// The sql tableName read interface. NOTE: NATURAL JOINs, and join "USING" clause
|
// The sql tableName read interface. NOTE: NATURAL JOINs, and join "USING" clause
|
||||||
// are not supported.
|
// are not supported.
|
||||||
type ReadableTable interface {
|
type ReadableTable interface {
|
||||||
TableInterface
|
tableInterface
|
||||||
|
|
||||||
// Generates a select query on the current tableName.
|
// Generates a select query on the current tableName.
|
||||||
SELECT(projections ...Projection) SelectStatement
|
SELECT(projections ...Projection) SelectStatement
|
||||||
|
|
@ -41,7 +39,7 @@ type ReadableTable interface {
|
||||||
|
|
||||||
// The sql tableName write interface.
|
// The sql tableName write interface.
|
||||||
type WritableTable interface {
|
type WritableTable interface {
|
||||||
TableInterface
|
tableInterface
|
||||||
|
|
||||||
INSERT(columns ...Column) InsertStatement
|
INSERT(columns ...Column) InsertStatement
|
||||||
UPDATE(columns ...Column) UpdateStatement
|
UPDATE(columns ...Column) UpdateStatement
|
||||||
|
|
@ -53,44 +51,26 @@ type WritableTable interface {
|
||||||
func NewTable(schemaName, name string, columns ...Column) *Table {
|
func NewTable(schemaName, name string, columns ...Column) *Table {
|
||||||
|
|
||||||
t := &Table{
|
t := &Table{
|
||||||
schemaName: schemaName,
|
schemaName: schemaName,
|
||||||
name: name,
|
name: name,
|
||||||
columns: columns,
|
columns: columns,
|
||||||
columnLookup: make(map[string]Column),
|
|
||||||
}
|
}
|
||||||
for _, c := range columns {
|
for _, c := range columns {
|
||||||
err := c.setTableName(name)
|
c.setTableName(name)
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
t.columnLookup[c.TableName()] = c
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(columns) == 0 {
|
|
||||||
panic(fmt.Sprintf("Table %s has no columns", name))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return t
|
return t
|
||||||
}
|
}
|
||||||
|
|
||||||
type Table struct {
|
type Table struct {
|
||||||
schemaName string
|
schemaName string
|
||||||
name string
|
name string
|
||||||
alias string
|
alias string
|
||||||
columns []Column
|
columns []Column
|
||||||
columnLookup map[string]Column
|
|
||||||
// If not empty, the name of the index to force
|
// If not empty, the name of the index to force
|
||||||
forcedIndex string
|
forcedIndex string
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns the specified column, or errors if it doesn't exist in the tableName
|
|
||||||
func (t *Table) getColumn(name string) (Column, error) {
|
|
||||||
if c, ok := t.columnLookup[name]; ok {
|
|
||||||
return c, nil
|
|
||||||
}
|
|
||||||
return nil, errors.Newf("No such column '%s' in tableName '%s'", name, t.name)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t *Table) Column(name string) Column {
|
func (t *Table) Column(name string) Column {
|
||||||
return &baseColumn{
|
return &baseColumn{
|
||||||
name: name,
|
name: name,
|
||||||
|
|
@ -99,26 +79,11 @@ func (t *Table) Column(name string) Column {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns all expresssion for a tableName as a slice of projections
|
|
||||||
func (t *Table) Projections() []Expression {
|
|
||||||
result := make([]Expression, 0)
|
|
||||||
|
|
||||||
for _, col := range t.columns {
|
|
||||||
col.Asc()
|
|
||||||
result = append(result, col)
|
|
||||||
}
|
|
||||||
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t *Table) SetAlias(alias string) {
|
func (t *Table) SetAlias(alias string) {
|
||||||
t.alias = alias
|
t.alias = alias
|
||||||
|
|
||||||
for _, c := range t.columns {
|
for _, c := range t.columns {
|
||||||
err := c.setTableName(alias)
|
c.setTableName(alias)
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -180,14 +145,6 @@ func (t *Table) INNER_JOIN(
|
||||||
return InnerJoinOn(t, table, onCondition)
|
return InnerJoinOn(t, table, onCondition)
|
||||||
}
|
}
|
||||||
|
|
||||||
//func (t *Table) InnerJoinUsing(
|
|
||||||
// table ReadableTable,
|
|
||||||
// col1 Column,
|
|
||||||
// col2 Column) ReadableTable {
|
|
||||||
//
|
|
||||||
// return INNER_JOIN(t, table, col1.Eq(col2))
|
|
||||||
//}
|
|
||||||
|
|
||||||
// Creates a left join tableName expression using onCondition.
|
// Creates a left join tableName expression using onCondition.
|
||||||
func (t *Table) LEFT_JOIN(
|
func (t *Table) LEFT_JOIN(
|
||||||
table ReadableTable,
|
table ReadableTable,
|
||||||
|
|
@ -312,7 +269,10 @@ func (t *joinTable) Columns() []Column {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *joinTable) Column(name string) Column {
|
func (t *joinTable) Column(name string) Column {
|
||||||
panic("Not implemented")
|
return &baseColumn{
|
||||||
|
name: name,
|
||||||
|
nullable: NotNullable,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *joinTable) SerializeSql(out *queryData) (err error) {
|
func (t *joinTable) SerializeSql(out *queryData) (err error) {
|
||||||
|
|
|
||||||
|
|
@ -143,18 +143,18 @@ func (s *TableSuite) TestRightJoin(c *gc.C) {
|
||||||
"ON table1.col3=table2.col3")
|
"ON table1.col3=table2.col3")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *TableSuite) TestJoinColumns(c *gc.C) {
|
//func (s *TableSuite) TestJoinColumns(c *gc.C) {
|
||||||
join := table1.RIGHT_JOIN(table2, Eq(table1Col3, table2Col3))
|
// join := table1.RIGHT_JOIN(table2, Eq(table1Col3, table2Col3))
|
||||||
|
//
|
||||||
cols := join.Columns()
|
// cols := join.Columns()
|
||||||
c.Assert(len(cols), gc.Equals, 6)
|
// c.Assert(len(cols), gc.Equals, 6)
|
||||||
c.Assert(cols[0], gc.Equals, table1Col1)
|
// c.Assert(cols[0], gc.Equals, table1Col1)
|
||||||
c.Assert(cols[1], gc.Equals, table1Col2)
|
// c.Assert(cols[1], gc.Equals, table1Col2)
|
||||||
c.Assert(cols[2], gc.Equals, table1Col3)
|
// c.Assert(cols[2], gc.Equals, table1Col3)
|
||||||
c.Assert(cols[3], gc.Equals, table1Col4)
|
// c.Assert(cols[3], gc.Equals, table1Col4)
|
||||||
c.Assert(cols[4], gc.Equals, table2Col3)
|
// c.Assert(cols[4], gc.Equals, table2Col3)
|
||||||
c.Assert(cols[5], gc.Equals, table2Col4)
|
// c.Assert(cols[5], gc.Equals, table2Col4)
|
||||||
}
|
//}
|
||||||
|
|
||||||
func (s *TableSuite) TestNestedInnerJoin(c *gc.C) {
|
func (s *TableSuite) TestNestedInnerJoin(c *gc.C) {
|
||||||
join1 := table1.InnerJoinOn(table2, Eq(table1Col3, table2Col3))
|
join1 := table1.InnerJoinOn(table2, Eq(table1Col3, table2Col3))
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue