Column reference from sub queries.
This commit is contained in:
parent
e727fc3d4f
commit
e772768180
13 changed files with 507 additions and 470 deletions
|
|
@ -17,27 +17,27 @@ type ColumnInfo struct {
|
||||||
func (c ColumnInfo) SqlBuilderColumnType() string {
|
func (c ColumnInfo) SqlBuilderColumnType() string {
|
||||||
switch c.DataType {
|
switch c.DataType {
|
||||||
case "boolean":
|
case "boolean":
|
||||||
return "BoolColumn"
|
return "Bool"
|
||||||
case "smallint", "integer", "bigint":
|
case "smallint", "integer", "bigint":
|
||||||
return "IntegerColumn"
|
return "Integer"
|
||||||
case "date":
|
case "date":
|
||||||
return "DateColumn"
|
return "Date"
|
||||||
case "timestamp without time zone":
|
case "timestamp without time zone":
|
||||||
return "TimestampColumn"
|
return "Timestamp"
|
||||||
case "timestamp with time zone":
|
case "timestamp with time zone":
|
||||||
return "TimestampzColumn"
|
return "Timestampz"
|
||||||
case "time without time zone":
|
case "time without time zone":
|
||||||
return "TimeColumn"
|
return "Time"
|
||||||
case "time with time zone":
|
case "time with time zone":
|
||||||
return "TimezColumn"
|
return "Timez"
|
||||||
case "USER-DEFINED", "text", "character", "character varying", "bytea", "uuid",
|
case "USER-DEFINED", "text", "character", "character varying", "bytea", "uuid",
|
||||||
"tsvector", "bit", "bit varying", "money", "json", "jsonb", "xml", "point", "interval", "line", "ARRAY":
|
"tsvector", "bit", "bit varying", "money", "json", "jsonb", "xml", "point", "interval", "line", "ARRAY":
|
||||||
return "StringColumn"
|
return "String"
|
||||||
case "real", "numeric", "decimal", "double precision":
|
case "real", "numeric", "decimal", "double precision":
|
||||||
return "FloatColumn"
|
return "Float"
|
||||||
default:
|
default:
|
||||||
fmt.Println("Unknown sql type: " + c.DataType + ", using string column instead for sql builder.")
|
fmt.Println("Unknown sql type: " + c.DataType + ", using string column instead for sql builder.")
|
||||||
return "StringColumn"
|
return "String"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,7 @@ type {{.GoStructName}} struct {
|
||||||
|
|
||||||
//Columns
|
//Columns
|
||||||
{{- range .Columns}}
|
{{- range .Columns}}
|
||||||
{{camelize .Name}} *sqlbuilder.{{.SqlBuilderColumnType}}
|
{{camelize .Name}} sqlbuilder.Column{{.SqlBuilderColumnType}}
|
||||||
{{- end}}
|
{{- end}}
|
||||||
|
|
||||||
AllColumns sqlbuilder.ColumnList
|
AllColumns sqlbuilder.ColumnList
|
||||||
|
|
@ -42,7 +42,7 @@ var {{camelize .Name}} = new{{.GoStructName}}()
|
||||||
func new{{.GoStructName}}() *{{.GoStructName}} {
|
func new{{.GoStructName}}() *{{.GoStructName}} {
|
||||||
var (
|
var (
|
||||||
{{- range .Columns}}
|
{{- range .Columns}}
|
||||||
{{camelize .Name}}Column = sqlbuilder.New{{.SqlBuilderColumnType}}("{{.Name}}", {{.IsNullable}})
|
{{camelize .Name}}Column = sqlbuilder.{{.SqlBuilderColumnType}}Column("{{.Name}}")
|
||||||
{{- end}}
|
{{- end}}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,31 +6,33 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Column interface {
|
type column interface {
|
||||||
Expression
|
|
||||||
|
|
||||||
Name() string
|
Name() string
|
||||||
TableName() string
|
TableName() string
|
||||||
IsNullable() bool
|
|
||||||
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)
|
setTableName(table string)
|
||||||
|
defaultAlias() string
|
||||||
|
defaultAliasProjection() projection
|
||||||
|
}
|
||||||
|
|
||||||
|
type Column interface {
|
||||||
|
Expression
|
||||||
|
column
|
||||||
}
|
}
|
||||||
|
|
||||||
// The base type for real materialized columns.
|
// The base type for real materialized columns.
|
||||||
type baseColumn struct {
|
type columnImpl struct {
|
||||||
expressionInterfaceImpl
|
expressionInterfaceImpl
|
||||||
|
|
||||||
name string
|
name string
|
||||||
isNullable bool
|
|
||||||
tableName string
|
tableName string
|
||||||
}
|
}
|
||||||
|
|
||||||
func newBaseColumn(name string, isNullable bool, tableName string, parent Column) baseColumn {
|
func newColumn(name string, tableName string, parent Column) columnImpl {
|
||||||
bc := baseColumn{
|
bc := columnImpl{
|
||||||
name: name,
|
name: name,
|
||||||
isNullable: isNullable,
|
|
||||||
tableName: tableName,
|
tableName: tableName,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -39,27 +41,31 @@ func newBaseColumn(name string, isNullable bool, tableName string, parent Column
|
||||||
return bc
|
return bc
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *baseColumn) Name() string {
|
func (c *columnImpl) Name() string {
|
||||||
return c.name
|
return c.name
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *baseColumn) TableName() string {
|
func (c *columnImpl) TableName() string {
|
||||||
return c.tableName
|
return c.tableName
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *baseColumn) setTableName(table string) {
|
func (c *columnImpl) setTableName(table string) {
|
||||||
c.tableName = table
|
c.tableName = table
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *baseColumn) IsNullable() bool {
|
func (c *columnImpl) defaultAlias() string {
|
||||||
return c.isNullable
|
if c.tableName != "" {
|
||||||
|
return c.tableName + "." + c.name
|
||||||
|
}
|
||||||
|
|
||||||
|
return c.name
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *baseColumn) DefaultAlias() projection {
|
func (c *columnImpl) defaultAliasProjection() projection {
|
||||||
return c.AS(c.tableName + "." + c.name)
|
return c.AS(c.defaultAlias())
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *baseColumn) serializeAsOrderBy(statement statementType, out *queryData) error {
|
func (c *columnImpl) serializeAsOrderBy(statement statementType, out *queryData) error {
|
||||||
if statement == set_statement {
|
if statement == set_statement {
|
||||||
// set Statement (UNION, EXCEPT ...) can reference only select projections in order by clause
|
// set Statement (UNION, EXCEPT ...) can reference only select projections in order by clause
|
||||||
columnRef := ""
|
columnRef := ""
|
||||||
|
|
@ -78,7 +84,7 @@ func (c *baseColumn) serializeAsOrderBy(statement statementType, out *queryData)
|
||||||
return c.serialize(statement, out)
|
return c.serialize(statement, out)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c baseColumn) serialize(statement statementType, out *queryData, options ...serializeOption) error {
|
func (c columnImpl) serialize(statement statementType, out *queryData, options ...serializeOption) error {
|
||||||
|
|
||||||
columnRef := ""
|
columnRef := ""
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,210 +1,14 @@
|
||||||
// +build disabled
|
|
||||||
|
|
||||||
package sqlbuilder
|
package sqlbuilder
|
||||||
|
|
||||||
import (
|
import "testing"
|
||||||
"bytes"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
gc "gopkg.in/check.v1"
|
func TestColumn(t *testing.T) {
|
||||||
)
|
column := newColumn("col", "", nil)
|
||||||
|
column.expressionInterfaceImpl.parent = &column
|
||||||
|
|
||||||
func Test(t *testing.T) {
|
assertClauseSerialize(t, column, "col")
|
||||||
gc.TestingT(t)
|
column.setTableName("table1")
|
||||||
}
|
assertClauseSerialize(t, column, "table1.col")
|
||||||
|
assertProjectionSerialize(t, column.defaultAliasProjection(), `table1.col AS "table1.col"`)
|
||||||
type ColumnSuite struct {
|
assertProjectionSerialize(t, column.AS("alias1"), `table1.col AS "alias1"`)
|
||||||
}
|
|
||||||
|
|
||||||
var _ = gc.Suite(&ColumnSuite{})
|
|
||||||
|
|
||||||
//
|
|
||||||
// tests for baseColumn and columns that extends baseColumn
|
|
||||||
//
|
|
||||||
|
|
||||||
func (s *ColumnSuite) TestRealColumnName(c *gc.C) {
|
|
||||||
col := IntColumn("col", Nullable)
|
|
||||||
|
|
||||||
c.Assert(col.Name(), gc.Equals, "col")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *ColumnSuite) TestRealColumnSerializeSqlForColumnList(c *gc.C) {
|
|
||||||
col := IntColumn("col", Nullable)
|
|
||||||
|
|
||||||
// Without tableName name
|
|
||||||
buf := &bytes.Buffer{}
|
|
||||||
|
|
||||||
err := col.SerializeSqlForColumnList(buf)
|
|
||||||
c.Assert(err, gc.IsNil)
|
|
||||||
|
|
||||||
sql := buf.String()
|
|
||||||
c.Assert(sql, gc.Equals, "col")
|
|
||||||
|
|
||||||
// With tableName name
|
|
||||||
err = col.setTableName("foo")
|
|
||||||
c.Assert(err, gc.IsNil)
|
|
||||||
|
|
||||||
buf = &bytes.Buffer{}
|
|
||||||
|
|
||||||
err = col.SerializeSqlForColumnList(buf)
|
|
||||||
c.Assert(err, gc.IsNil)
|
|
||||||
|
|
||||||
sql = buf.String()
|
|
||||||
c.Assert(sql, gc.Equals, "foo.col")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *ColumnSuite) TestRealColumnSerializeSql(c *gc.C) {
|
|
||||||
col := IntColumn("col", Nullable)
|
|
||||||
|
|
||||||
// Without tableName name
|
|
||||||
buf := &bytes.Buffer{}
|
|
||||||
|
|
||||||
err := col.SerializeSql(buf)
|
|
||||||
c.Assert(err, gc.IsNil)
|
|
||||||
|
|
||||||
sql := buf.String()
|
|
||||||
c.Assert(sql, gc.Equals, "col")
|
|
||||||
|
|
||||||
// With tableName name
|
|
||||||
err = col.setTableName("foo")
|
|
||||||
c.Assert(err, gc.IsNil)
|
|
||||||
|
|
||||||
buf = &bytes.Buffer{}
|
|
||||||
|
|
||||||
err = col.SerializeSql(buf)
|
|
||||||
c.Assert(err, gc.IsNil)
|
|
||||||
|
|
||||||
sql = buf.String()
|
|
||||||
c.Assert(sql, gc.Equals, "foo.col")
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// tests for AliasCoulmns
|
|
||||||
//
|
|
||||||
|
|
||||||
func (s *ColumnSuite) TestAliasColumnName(c *gc.C) {
|
|
||||||
col := Alias("foo", SqlFunc("max", table1Col1))
|
|
||||||
|
|
||||||
c.Assert(col.Name(), gc.Equals, "foo")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *ColumnSuite) TestAliasColumnSerializeSqlForColumnList(c *gc.C) {
|
|
||||||
col := Alias("foo", SqlFunc("max", table1Col1))
|
|
||||||
|
|
||||||
buf := &bytes.Buffer{}
|
|
||||||
err := col.SerializeSqlForColumnList(buf)
|
|
||||||
c.Assert(err, gc.IsNil)
|
|
||||||
|
|
||||||
sql := buf.String()
|
|
||||||
c.Assert(err, gc.IsNil)
|
|
||||||
|
|
||||||
c.Assert(sql, gc.Equals, "(max(table1.col1)) AS \"foo\"")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *ColumnSuite) TestAliasColumnSerializeSqlForColumnListNilExpr(c *gc.C) {
|
|
||||||
col := Alias("foo", nil)
|
|
||||||
|
|
||||||
buf := &bytes.Buffer{}
|
|
||||||
err := col.SerializeSqlForColumnList(buf)
|
|
||||||
c.Assert(err, gc.NotNil)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *ColumnSuite) TestAliasColumnSerializeSqlForColumnListInvalidAlias(
|
|
||||||
c *gc.C) {
|
|
||||||
|
|
||||||
col := Alias("1234", SqlFunc("max", table1Col1))
|
|
||||||
|
|
||||||
buf := &bytes.Buffer{}
|
|
||||||
err := col.SerializeSqlForColumnList(buf)
|
|
||||||
c.Assert(err, gc.NotNil)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *ColumnSuite) TestAliasColumnSerializeSql(c *gc.C) {
|
|
||||||
col := Alias("foo", SqlFunc("max", table1Col1))
|
|
||||||
|
|
||||||
buf := &bytes.Buffer{}
|
|
||||||
err := col.SerializeSql(buf)
|
|
||||||
c.Assert(err, gc.IsNil)
|
|
||||||
|
|
||||||
sql := buf.String()
|
|
||||||
c.Assert(sql, gc.Equals, "`foo`")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *ColumnSuite) TestAliasColumnSetTableName(c *gc.C) {
|
|
||||||
col := Alias("foo", SqlFunc("max", table1Col1))
|
|
||||||
|
|
||||||
// should always error
|
|
||||||
err := col.setTableName("test")
|
|
||||||
c.Assert(err, gc.NotNil)
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// tests for deferredLookkupColumnName
|
|
||||||
//
|
|
||||||
|
|
||||||
func (s *ColumnSuite) TestDeferredLookupColumnName(c *gc.C) {
|
|
||||||
col := table1.C("foo")
|
|
||||||
|
|
||||||
c.Assert(col.Name(), gc.Equals, "foo")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *ColumnSuite) TestDeferredLookupColumnSerializeSqlForColumnList(
|
|
||||||
c *gc.C) {
|
|
||||||
|
|
||||||
col := table1.C("col1")
|
|
||||||
|
|
||||||
buf := &bytes.Buffer{}
|
|
||||||
|
|
||||||
err := col.SerializeSql(buf)
|
|
||||||
c.Assert(err, gc.IsNil)
|
|
||||||
|
|
||||||
sql := buf.String()
|
|
||||||
c.Assert(sql, gc.Equals, "table1.col1")
|
|
||||||
|
|
||||||
// check cached lookup
|
|
||||||
buf = &bytes.Buffer{}
|
|
||||||
|
|
||||||
err = col.SerializeSql(buf)
|
|
||||||
c.Assert(err, gc.IsNil)
|
|
||||||
|
|
||||||
sql = buf.String()
|
|
||||||
c.Assert(sql, gc.Equals, "table1.col1")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *ColumnSuite) TestDeferredLookupColumnSerializeSqlForColumnListInvalidName(
|
|
||||||
c *gc.C) {
|
|
||||||
col := table1.C("foo")
|
|
||||||
|
|
||||||
buf := &bytes.Buffer{}
|
|
||||||
|
|
||||||
err := col.SerializeSql(buf)
|
|
||||||
c.Assert(err, gc.NotNil)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *ColumnSuite) TestDeferredLookupColumnSerializeSql(c *gc.C) {
|
|
||||||
col := table1.C("col1")
|
|
||||||
|
|
||||||
buf := &bytes.Buffer{}
|
|
||||||
|
|
||||||
err := col.SerializeSql(buf)
|
|
||||||
c.Assert(err, gc.IsNil)
|
|
||||||
|
|
||||||
sql := buf.String()
|
|
||||||
c.Assert(sql, gc.Equals, "table1.col1")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *ColumnSuite) TestDeferredLookupColumnSerializeSqlInvalidName(c *gc.C) {
|
|
||||||
col := table1.C("foo")
|
|
||||||
|
|
||||||
buf := &bytes.Buffer{}
|
|
||||||
|
|
||||||
err := col.SerializeSql(buf)
|
|
||||||
c.Assert(err, gc.NotNil)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *ColumnSuite) TestDeferredLookupColumnSetTableName(c *gc.C) {
|
|
||||||
col := table1.C("col1")
|
|
||||||
|
|
||||||
err := col.setTableName("foo")
|
|
||||||
c.Assert(err, gc.NotNil)
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
210
sqlbuilder/column_test_old.go
Normal file
210
sqlbuilder/column_test_old.go
Normal file
|
|
@ -0,0 +1,210 @@
|
||||||
|
// +build disabled
|
||||||
|
|
||||||
|
package sqlbuilder
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
gc "gopkg.in/check.v1"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Test(t *testing.T) {
|
||||||
|
gc.TestingT(t)
|
||||||
|
}
|
||||||
|
|
||||||
|
type ColumnSuite struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ = gc.Suite(&ColumnSuite{})
|
||||||
|
|
||||||
|
//
|
||||||
|
// tests for columnImpl and columns that extends columnImpl
|
||||||
|
//
|
||||||
|
|
||||||
|
func (s *ColumnSuite) TestRealColumnName(c *gc.C) {
|
||||||
|
col := IntColumn("col", Nullable)
|
||||||
|
|
||||||
|
c.Assert(col.Name(), gc.Equals, "col")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *ColumnSuite) TestRealColumnSerializeSqlForColumnList(c *gc.C) {
|
||||||
|
col := IntColumn("col", Nullable)
|
||||||
|
|
||||||
|
// Without tableName name
|
||||||
|
buf := &bytes.Buffer{}
|
||||||
|
|
||||||
|
err := col.SerializeSqlForColumnList(buf)
|
||||||
|
c.Assert(err, gc.IsNil)
|
||||||
|
|
||||||
|
sql := buf.String()
|
||||||
|
c.Assert(sql, gc.Equals, "col")
|
||||||
|
|
||||||
|
// With tableName name
|
||||||
|
err = col.setTableName("foo")
|
||||||
|
c.Assert(err, gc.IsNil)
|
||||||
|
|
||||||
|
buf = &bytes.Buffer{}
|
||||||
|
|
||||||
|
err = col.SerializeSqlForColumnList(buf)
|
||||||
|
c.Assert(err, gc.IsNil)
|
||||||
|
|
||||||
|
sql = buf.String()
|
||||||
|
c.Assert(sql, gc.Equals, "foo.col")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *ColumnSuite) TestRealColumnSerializeSql(c *gc.C) {
|
||||||
|
col := IntColumn("col", Nullable)
|
||||||
|
|
||||||
|
// Without tableName name
|
||||||
|
buf := &bytes.Buffer{}
|
||||||
|
|
||||||
|
err := col.SerializeSql(buf)
|
||||||
|
c.Assert(err, gc.IsNil)
|
||||||
|
|
||||||
|
sql := buf.String()
|
||||||
|
c.Assert(sql, gc.Equals, "col")
|
||||||
|
|
||||||
|
// With tableName name
|
||||||
|
err = col.setTableName("foo")
|
||||||
|
c.Assert(err, gc.IsNil)
|
||||||
|
|
||||||
|
buf = &bytes.Buffer{}
|
||||||
|
|
||||||
|
err = col.SerializeSql(buf)
|
||||||
|
c.Assert(err, gc.IsNil)
|
||||||
|
|
||||||
|
sql = buf.String()
|
||||||
|
c.Assert(sql, gc.Equals, "foo.col")
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// tests for AliasCoulmns
|
||||||
|
//
|
||||||
|
|
||||||
|
func (s *ColumnSuite) TestAliasColumnName(c *gc.C) {
|
||||||
|
col := Alias("foo", SqlFunc("max", table1Col1))
|
||||||
|
|
||||||
|
c.Assert(col.Name(), gc.Equals, "foo")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *ColumnSuite) TestAliasColumnSerializeSqlForColumnList(c *gc.C) {
|
||||||
|
col := Alias("foo", SqlFunc("max", table1Col1))
|
||||||
|
|
||||||
|
buf := &bytes.Buffer{}
|
||||||
|
err := col.SerializeSqlForColumnList(buf)
|
||||||
|
c.Assert(err, gc.IsNil)
|
||||||
|
|
||||||
|
sql := buf.String()
|
||||||
|
c.Assert(err, gc.IsNil)
|
||||||
|
|
||||||
|
c.Assert(sql, gc.Equals, "(max(table1.col1)) AS \"foo\"")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *ColumnSuite) TestAliasColumnSerializeSqlForColumnListNilExpr(c *gc.C) {
|
||||||
|
col := Alias("foo", nil)
|
||||||
|
|
||||||
|
buf := &bytes.Buffer{}
|
||||||
|
err := col.SerializeSqlForColumnList(buf)
|
||||||
|
c.Assert(err, gc.NotNil)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *ColumnSuite) TestAliasColumnSerializeSqlForColumnListInvalidAlias(
|
||||||
|
c *gc.C) {
|
||||||
|
|
||||||
|
col := Alias("1234", SqlFunc("max", table1Col1))
|
||||||
|
|
||||||
|
buf := &bytes.Buffer{}
|
||||||
|
err := col.SerializeSqlForColumnList(buf)
|
||||||
|
c.Assert(err, gc.NotNil)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *ColumnSuite) TestAliasColumnSerializeSql(c *gc.C) {
|
||||||
|
col := Alias("foo", SqlFunc("max", table1Col1))
|
||||||
|
|
||||||
|
buf := &bytes.Buffer{}
|
||||||
|
err := col.SerializeSql(buf)
|
||||||
|
c.Assert(err, gc.IsNil)
|
||||||
|
|
||||||
|
sql := buf.String()
|
||||||
|
c.Assert(sql, gc.Equals, "`foo`")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *ColumnSuite) TestAliasColumnSetTableName(c *gc.C) {
|
||||||
|
col := Alias("foo", SqlFunc("max", table1Col1))
|
||||||
|
|
||||||
|
// should always error
|
||||||
|
err := col.setTableName("test")
|
||||||
|
c.Assert(err, gc.NotNil)
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// tests for deferredLookkupColumnName
|
||||||
|
//
|
||||||
|
|
||||||
|
func (s *ColumnSuite) TestDeferredLookupColumnName(c *gc.C) {
|
||||||
|
col := table1.C("foo")
|
||||||
|
|
||||||
|
c.Assert(col.Name(), gc.Equals, "foo")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *ColumnSuite) TestDeferredLookupColumnSerializeSqlForColumnList(
|
||||||
|
c *gc.C) {
|
||||||
|
|
||||||
|
col := table1.C("col1")
|
||||||
|
|
||||||
|
buf := &bytes.Buffer{}
|
||||||
|
|
||||||
|
err := col.SerializeSql(buf)
|
||||||
|
c.Assert(err, gc.IsNil)
|
||||||
|
|
||||||
|
sql := buf.String()
|
||||||
|
c.Assert(sql, gc.Equals, "table1.col1")
|
||||||
|
|
||||||
|
// check cached lookup
|
||||||
|
buf = &bytes.Buffer{}
|
||||||
|
|
||||||
|
err = col.SerializeSql(buf)
|
||||||
|
c.Assert(err, gc.IsNil)
|
||||||
|
|
||||||
|
sql = buf.String()
|
||||||
|
c.Assert(sql, gc.Equals, "table1.col1")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *ColumnSuite) TestDeferredLookupColumnSerializeSqlForColumnListInvalidName(
|
||||||
|
c *gc.C) {
|
||||||
|
col := table1.C("foo")
|
||||||
|
|
||||||
|
buf := &bytes.Buffer{}
|
||||||
|
|
||||||
|
err := col.SerializeSql(buf)
|
||||||
|
c.Assert(err, gc.NotNil)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *ColumnSuite) TestDeferredLookupColumnSerializeSql(c *gc.C) {
|
||||||
|
col := table1.C("col1")
|
||||||
|
|
||||||
|
buf := &bytes.Buffer{}
|
||||||
|
|
||||||
|
err := col.SerializeSql(buf)
|
||||||
|
c.Assert(err, gc.IsNil)
|
||||||
|
|
||||||
|
sql := buf.String()
|
||||||
|
c.Assert(sql, gc.Equals, "table1.col1")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *ColumnSuite) TestDeferredLookupColumnSerializeSqlInvalidName(c *gc.C) {
|
||||||
|
col := table1.C("foo")
|
||||||
|
|
||||||
|
buf := &bytes.Buffer{}
|
||||||
|
|
||||||
|
err := col.SerializeSql(buf)
|
||||||
|
c.Assert(err, gc.NotNil)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *ColumnSuite) TestDeferredLookupColumnSetTableName(c *gc.C) {
|
||||||
|
col := table1.C("col1")
|
||||||
|
|
||||||
|
err := col.setTableName("foo")
|
||||||
|
c.Assert(err, gc.NotNil)
|
||||||
|
}
|
||||||
|
|
@ -1,16 +1,29 @@
|
||||||
package sqlbuilder
|
package sqlbuilder
|
||||||
|
|
||||||
//------------------------------------------------------//
|
//------------------------------------------------------//
|
||||||
type BoolColumn struct {
|
type ColumnBool interface {
|
||||||
boolInterfaceImpl
|
BoolExpression
|
||||||
|
column
|
||||||
|
|
||||||
baseColumn
|
From(table ExpressionTable) ColumnBool
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewBoolColumn(name string, isNullable bool) *BoolColumn {
|
type boolColumnImpl struct {
|
||||||
|
boolInterfaceImpl
|
||||||
|
|
||||||
boolColumn := &BoolColumn{}
|
columnImpl
|
||||||
boolColumn.baseColumn = newBaseColumn(name, isNullable, "", boolColumn)
|
}
|
||||||
|
|
||||||
|
func (i *boolColumnImpl) From(table ExpressionTable) ColumnBool {
|
||||||
|
newBoolColumn := BoolColumn(i.defaultAlias())
|
||||||
|
newBoolColumn.setTableName(table.Alias())
|
||||||
|
return newBoolColumn
|
||||||
|
}
|
||||||
|
|
||||||
|
func BoolColumn(name string) ColumnBool {
|
||||||
|
|
||||||
|
boolColumn := &boolColumnImpl{}
|
||||||
|
boolColumn.columnImpl = newColumn(name, "", boolColumn)
|
||||||
|
|
||||||
boolColumn.boolInterfaceImpl.parent = boolColumn
|
boolColumn.boolInterfaceImpl.parent = boolColumn
|
||||||
|
|
||||||
|
|
@ -18,164 +31,241 @@ func NewBoolColumn(name string, isNullable bool) *BoolColumn {
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------//
|
//------------------------------------------------------//
|
||||||
type FloatColumn struct {
|
type ColumnFloat interface {
|
||||||
floatInterfaceImpl
|
FloatExpression
|
||||||
baseColumn
|
column
|
||||||
|
|
||||||
|
From(table ExpressionTable) ColumnFloat
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewFloatColumn(name string, isNullable bool) *FloatColumn {
|
type floatColumnImpl struct {
|
||||||
|
floatInterfaceImpl
|
||||||
|
columnImpl
|
||||||
|
}
|
||||||
|
|
||||||
floatColumn := &FloatColumn{}
|
func (i *floatColumnImpl) From(table ExpressionTable) ColumnFloat {
|
||||||
|
newFloatColumn := FloatColumn(i.defaultAlias())
|
||||||
|
newFloatColumn.setTableName(table.Alias())
|
||||||
|
return newFloatColumn
|
||||||
|
}
|
||||||
|
|
||||||
|
func FloatColumn(name string) ColumnFloat {
|
||||||
|
|
||||||
|
floatColumn := &floatColumnImpl{}
|
||||||
|
|
||||||
floatColumn.floatInterfaceImpl.parent = floatColumn
|
floatColumn.floatInterfaceImpl.parent = floatColumn
|
||||||
|
floatColumn.columnImpl = newColumn(name, "", floatColumn)
|
||||||
floatColumn.baseColumn = newBaseColumn(name, isNullable, "", floatColumn)
|
|
||||||
|
|
||||||
return floatColumn
|
return floatColumn
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------//
|
//------------------------------------------------------//
|
||||||
type IntegerColumn struct {
|
type ColumnInteger interface {
|
||||||
integerInterfaceImpl
|
IntegerExpression
|
||||||
|
column
|
||||||
|
|
||||||
baseColumn
|
From(table ExpressionTable) ColumnInteger
|
||||||
}
|
}
|
||||||
|
|
||||||
// Representation of any integer column
|
type integerColumnImpl struct {
|
||||||
// This function will panic if name is not valid
|
integerInterfaceImpl
|
||||||
func NewIntegerColumn(name string, isNullable bool) *IntegerColumn {
|
|
||||||
integerColumn := &IntegerColumn{}
|
columnImpl
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i *integerColumnImpl) From(table ExpressionTable) ColumnInteger {
|
||||||
|
newIntColumn := IntegerColumn(i.defaultAlias())
|
||||||
|
newIntColumn.setTableName(table.Alias())
|
||||||
|
return newIntColumn
|
||||||
|
}
|
||||||
|
|
||||||
|
func IntegerColumn(name string) ColumnInteger {
|
||||||
|
integerColumn := &integerColumnImpl{}
|
||||||
|
|
||||||
integerColumn.integerInterfaceImpl.parent = integerColumn
|
integerColumn.integerInterfaceImpl.parent = integerColumn
|
||||||
|
integerColumn.columnImpl = newColumn(name, "", integerColumn)
|
||||||
integerColumn.baseColumn = newBaseColumn(name, isNullable, "", integerColumn)
|
|
||||||
|
|
||||||
return integerColumn
|
return integerColumn
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------//
|
//------------------------------------------------------//
|
||||||
type StringColumn struct {
|
type ColumnString interface {
|
||||||
stringInterfaceImpl
|
StringExpression
|
||||||
|
column
|
||||||
|
|
||||||
baseColumn
|
From(table ExpressionTable) ColumnString
|
||||||
}
|
}
|
||||||
|
|
||||||
// Representation of any integer column
|
type stringColumnImpl struct {
|
||||||
// This function will panic if name is not valid
|
stringInterfaceImpl
|
||||||
func NewStringColumn(name string, isNullable bool) *StringColumn {
|
|
||||||
|
|
||||||
stringColumn := &StringColumn{}
|
columnImpl
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i *stringColumnImpl) From(table ExpressionTable) ColumnString {
|
||||||
|
newStrColumn := StringColumn(i.defaultAlias())
|
||||||
|
newStrColumn.setTableName(table.Alias())
|
||||||
|
return newStrColumn
|
||||||
|
}
|
||||||
|
|
||||||
|
func StringColumn(name string) ColumnString {
|
||||||
|
|
||||||
|
stringColumn := &stringColumnImpl{}
|
||||||
|
|
||||||
stringColumn.stringInterfaceImpl.parent = stringColumn
|
stringColumn.stringInterfaceImpl.parent = stringColumn
|
||||||
|
|
||||||
stringColumn.baseColumn = newBaseColumn(name, isNullable, "", stringColumn)
|
stringColumn.columnImpl = newColumn(name, "", stringColumn)
|
||||||
|
|
||||||
return stringColumn
|
return stringColumn
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------//
|
//------------------------------------------------------//
|
||||||
type TimeColumn struct {
|
type ColumnTime interface {
|
||||||
timeInterfaceImpl
|
TimeExpression
|
||||||
|
column
|
||||||
|
|
||||||
baseColumn
|
From(table ExpressionTable) ColumnTime
|
||||||
}
|
}
|
||||||
|
|
||||||
// Representation of any integer column
|
type timeColumnImpl struct {
|
||||||
// This function will panic if name is not valid
|
timeInterfaceImpl
|
||||||
func NewTimeColumn(name string, isNullable bool) *TimeColumn {
|
|
||||||
timeColumn := &TimeColumn{}
|
columnImpl
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i *timeColumnImpl) From(table ExpressionTable) ColumnTime {
|
||||||
|
newTimeColumn := TimeColumn(i.defaultAlias())
|
||||||
|
newTimeColumn.setTableName(table.Alias())
|
||||||
|
return newTimeColumn
|
||||||
|
}
|
||||||
|
|
||||||
|
func TimeColumn(name string) ColumnTime {
|
||||||
|
timeColumn := &timeColumnImpl{}
|
||||||
|
|
||||||
timeColumn.timeInterfaceImpl.parent = timeColumn
|
timeColumn.timeInterfaceImpl.parent = timeColumn
|
||||||
|
|
||||||
timeColumn.baseColumn = newBaseColumn(name, isNullable, "", timeColumn)
|
timeColumn.columnImpl = newColumn(name, "", timeColumn)
|
||||||
|
|
||||||
return timeColumn
|
return timeColumn
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------//
|
//------------------------------------------------------//
|
||||||
type TimezColumn struct {
|
|
||||||
timezInterfaceImpl
|
|
||||||
|
|
||||||
baseColumn
|
type ColumnTimez interface {
|
||||||
|
TimezExpression
|
||||||
|
column
|
||||||
|
|
||||||
|
From(table ExpressionTable) ColumnTimez
|
||||||
}
|
}
|
||||||
|
|
||||||
// Representation of any integer column
|
type timezColumnImpl struct {
|
||||||
// This function will panic if name is not valid
|
timezInterfaceImpl
|
||||||
func NewTimezColumn(name string, isNullable bool) *TimezColumn {
|
|
||||||
timezColumn := &TimezColumn{}
|
columnImpl
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i *timezColumnImpl) From(table ExpressionTable) ColumnTimez {
|
||||||
|
newTimezColumn := TimezColumn(i.defaultAlias())
|
||||||
|
newTimezColumn.setTableName(table.Alias())
|
||||||
|
return newTimezColumn
|
||||||
|
}
|
||||||
|
|
||||||
|
func TimezColumn(name string) ColumnTimez {
|
||||||
|
timezColumn := &timezColumnImpl{}
|
||||||
|
|
||||||
timezColumn.timezInterfaceImpl.parent = timezColumn
|
timezColumn.timezInterfaceImpl.parent = timezColumn
|
||||||
|
|
||||||
timezColumn.baseColumn = newBaseColumn(name, isNullable, "", timezColumn)
|
timezColumn.columnImpl = newColumn(name, "", timezColumn)
|
||||||
|
|
||||||
return timezColumn
|
return timezColumn
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------//
|
//------------------------------------------------------//
|
||||||
type TimestampColumn struct {
|
type ColumnTimestamp interface {
|
||||||
timestampInterfaceImpl
|
TimestampExpression
|
||||||
|
column
|
||||||
|
|
||||||
baseColumn
|
From(table ExpressionTable) ColumnTimestamp
|
||||||
}
|
}
|
||||||
|
|
||||||
// Representation of any integer column
|
type timestampColumnImpl struct {
|
||||||
// This function will panic if name is not valid
|
timestampInterfaceImpl
|
||||||
func NewTimestampColumn(name string, isNullable bool) *TimestampColumn {
|
|
||||||
timestampColumn := &TimestampColumn{}
|
columnImpl
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i *timestampColumnImpl) From(table ExpressionTable) ColumnTimestamp {
|
||||||
|
newTimestampColumn := TimestampColumn(i.defaultAlias())
|
||||||
|
newTimestampColumn.setTableName(table.Alias())
|
||||||
|
return newTimestampColumn
|
||||||
|
}
|
||||||
|
|
||||||
|
func TimestampColumn(name string) ColumnTimestamp {
|
||||||
|
timestampColumn := ×tampColumnImpl{}
|
||||||
|
|
||||||
timestampColumn.timestampInterfaceImpl.parent = timestampColumn
|
timestampColumn.timestampInterfaceImpl.parent = timestampColumn
|
||||||
|
|
||||||
timestampColumn.baseColumn = newBaseColumn(name, isNullable, "", timestampColumn)
|
timestampColumn.columnImpl = newColumn(name, "", timestampColumn)
|
||||||
|
|
||||||
return timestampColumn
|
return timestampColumn
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------//
|
//------------------------------------------------------//
|
||||||
type TimestampzColumn struct {
|
type ColumnTimestampz interface {
|
||||||
timestampzInterfaceImpl
|
TimestampzExpression
|
||||||
|
column
|
||||||
|
|
||||||
baseColumn
|
From(table ExpressionTable) ColumnTimestampz
|
||||||
}
|
}
|
||||||
|
|
||||||
// Representation of any integer column
|
type timestampzColumnImpl struct {
|
||||||
// This function will panic if name is not valid
|
timestampzInterfaceImpl
|
||||||
func NewTimestampzColumn(name string, isNullable bool) *TimestampzColumn {
|
|
||||||
timestampzColumn := &TimestampzColumn{}
|
columnImpl
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i *timestampzColumnImpl) From(table ExpressionTable) ColumnTimestampz {
|
||||||
|
newTimestampzColumn := TimestampzColumn(i.defaultAlias())
|
||||||
|
newTimestampzColumn.setTableName(table.Alias())
|
||||||
|
return newTimestampzColumn
|
||||||
|
}
|
||||||
|
|
||||||
|
func TimestampzColumn(name string) ColumnTimestampz {
|
||||||
|
timestampzColumn := ×tampzColumnImpl{}
|
||||||
|
|
||||||
timestampzColumn.timestampzInterfaceImpl.parent = timestampzColumn
|
timestampzColumn.timestampzInterfaceImpl.parent = timestampzColumn
|
||||||
|
|
||||||
timestampzColumn.baseColumn = newBaseColumn(name, isNullable, "", timestampzColumn)
|
timestampzColumn.columnImpl = newColumn(name, "", timestampzColumn)
|
||||||
|
|
||||||
return timestampzColumn
|
return timestampzColumn
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------//
|
//------------------------------------------------------//
|
||||||
type DateColumn struct {
|
type ColumnDate interface {
|
||||||
dateInterfaceImpl
|
DateExpression
|
||||||
|
column
|
||||||
|
|
||||||
baseColumn
|
From(table ExpressionTable) ColumnDate
|
||||||
}
|
}
|
||||||
|
|
||||||
// Representation of any integer column
|
type dateColumnImpl struct {
|
||||||
// This function will panic if name is not valid
|
dateInterfaceImpl
|
||||||
func NewDateColumn(name string, isNullable bool) *DateColumn {
|
|
||||||
dateColumn := &DateColumn{}
|
columnImpl
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i *dateColumnImpl) From(table ExpressionTable) ColumnDate {
|
||||||
|
newDateColumn := DateColumn(i.defaultAlias())
|
||||||
|
newDateColumn.setTableName(table.Alias())
|
||||||
|
return newDateColumn
|
||||||
|
}
|
||||||
|
|
||||||
|
func DateColumn(name string) ColumnDate {
|
||||||
|
dateColumn := &dateColumnImpl{}
|
||||||
|
|
||||||
dateColumn.dateInterfaceImpl.parent = dateColumn
|
dateColumn.dateInterfaceImpl.parent = dateColumn
|
||||||
|
|
||||||
dateColumn.baseColumn = newBaseColumn(name, isNullable, "", dateColumn)
|
dateColumn.columnImpl = newColumn(name, "", dateColumn)
|
||||||
|
|
||||||
return dateColumn
|
return dateColumn
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------//
|
|
||||||
type refColumn struct {
|
|
||||||
baseColumn
|
|
||||||
}
|
|
||||||
|
|
||||||
func RefColumn(name string) *refColumn {
|
|
||||||
refColumn := &refColumn{}
|
|
||||||
refColumn.baseColumn = newBaseColumn(name, false, "", refColumn)
|
|
||||||
|
|
||||||
return refColumn
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -1,90 +1,45 @@
|
||||||
package sqlbuilder
|
package sqlbuilder
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"gotest.tools/assert"
|
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var subQuery = table1.SELECT(table1ColFloat, table1ColInt).AsTable("sub_query")
|
||||||
|
|
||||||
func TestNewBoolColumn(t *testing.T) {
|
func TestNewBoolColumn(t *testing.T) {
|
||||||
boolColumn := NewBoolColumn("col", false)
|
boolColumn := BoolColumn("colBool").From(subQuery)
|
||||||
|
assertClauseSerialize(t, boolColumn, "sub_query.colBool")
|
||||||
|
assertClauseSerialize(t, boolColumn.EQ(Bool(true)), "(sub_query.colBool = $1)", true)
|
||||||
|
assertProjectionSerialize(t, boolColumn.defaultAliasProjection(), `sub_query.colBool AS "sub_query.colBool"`)
|
||||||
|
|
||||||
out := queryData{}
|
boolColumn2 := table1ColBool.From(subQuery)
|
||||||
err := boolColumn.serialize(select_statement, &out)
|
assertClauseSerialize(t, boolColumn2, `sub_query."table1.colBool"`)
|
||||||
|
assertClauseSerialize(t, boolColumn2.EQ(Bool(true)), `(sub_query."table1.colBool" = $1)`, true)
|
||||||
assert.NilError(t, err)
|
assertProjectionSerialize(t, boolColumn2.defaultAliasProjection(), `sub_query."table1.colBool" AS "sub_query.table1.colBool"`)
|
||||||
assert.Equal(t, out.buff.String(), "col")
|
|
||||||
|
|
||||||
out.reset()
|
|
||||||
err = boolColumn.serialize(select_statement, &out)
|
|
||||||
assert.NilError(t, err)
|
|
||||||
assert.Equal(t, out.buff.String(), "col")
|
|
||||||
|
|
||||||
out.reset()
|
|
||||||
boolColumn.setTableName("table1")
|
|
||||||
err = boolColumn.DefaultAlias().serializeForProjection(select_statement, &out)
|
|
||||||
assert.NilError(t, err)
|
|
||||||
assert.Equal(t, out.buff.String(), `table1.col AS "table1.col"`)
|
|
||||||
|
|
||||||
out.reset()
|
|
||||||
boolColumn.setTableName("table1")
|
|
||||||
aliasedBoolColumn := boolColumn.AS("alias1")
|
|
||||||
err = aliasedBoolColumn.serializeForProjection(select_statement, &out)
|
|
||||||
assert.NilError(t, err)
|
|
||||||
assert.Equal(t, out.buff.String(), `table1.col AS "alias1"`)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNewIntColumn(t *testing.T) {
|
func TestNewIntColumn(t *testing.T) {
|
||||||
integerColumn := NewIntegerColumn("col", false)
|
intColumn := IntegerColumn("colInt").From(subQuery)
|
||||||
|
assertClauseSerialize(t, intColumn, "sub_query.colInt")
|
||||||
|
assertClauseSerialize(t, intColumn.EQ(Int(12)), "(sub_query.colInt = $1)", int64(12))
|
||||||
|
assertProjectionSerialize(t, intColumn.defaultAliasProjection(), `sub_query.colInt AS "sub_query.colInt"`)
|
||||||
|
|
||||||
out := queryData{}
|
intColumn2 := table1ColInt.From(subQuery)
|
||||||
err := integerColumn.serialize(select_statement, &out)
|
assertClauseSerialize(t, intColumn2, `sub_query."table1.colInt"`)
|
||||||
|
assertClauseSerialize(t, intColumn2.EQ(Int(14)), `(sub_query."table1.colInt" = $1)`, int64(14))
|
||||||
|
assertProjectionSerialize(t, intColumn2.defaultAliasProjection(), `sub_query."table1.colInt" AS "sub_query.table1.colInt"`)
|
||||||
|
|
||||||
assert.NilError(t, err)
|
|
||||||
assert.Equal(t, out.buff.String(), "col")
|
|
||||||
|
|
||||||
out.reset()
|
|
||||||
err = integerColumn.serialize(select_statement, &out)
|
|
||||||
assert.NilError(t, err)
|
|
||||||
assert.Equal(t, out.buff.String(), "col")
|
|
||||||
|
|
||||||
out.reset()
|
|
||||||
integerColumn.setTableName("table1")
|
|
||||||
err = integerColumn.DefaultAlias().serializeForProjection(select_statement, &out)
|
|
||||||
assert.NilError(t, err)
|
|
||||||
assert.Equal(t, out.buff.String(), `table1.col AS "table1.col"`)
|
|
||||||
|
|
||||||
out.reset()
|
|
||||||
integerColumn.setTableName("table1")
|
|
||||||
aliasedBoolColumn := integerColumn.AS("alias1")
|
|
||||||
err = aliasedBoolColumn.serializeForProjection(select_statement, &out)
|
|
||||||
assert.NilError(t, err)
|
|
||||||
assert.Equal(t, out.buff.String(), `table1.col AS "alias1"`)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNewNumericColumnColumn(t *testing.T) {
|
func TestNewFloatColumnColumn(t *testing.T) {
|
||||||
numericColumn := NewFloatColumn("col", false)
|
floatColumn := FloatColumn("colFloat").From(subQuery)
|
||||||
|
assertClauseSerialize(t, floatColumn, "sub_query.colFloat")
|
||||||
|
assertClauseSerialize(t, floatColumn.EQ(Float(1.11)), "(sub_query.colFloat = $1)", float64(1.11))
|
||||||
|
assertProjectionSerialize(t, floatColumn.defaultAliasProjection(), `sub_query.colFloat AS "sub_query.colFloat"`)
|
||||||
|
|
||||||
out := queryData{}
|
floatColumn2 := table1ColFloat.From(subQuery)
|
||||||
err := numericColumn.serialize(select_statement, &out)
|
assertClauseSerialize(t, floatColumn2, `sub_query."table1.colFloat"`)
|
||||||
|
assertClauseSerialize(t, floatColumn2.EQ(Float(2.22)), `(sub_query."table1.colFloat" = $1)`, float64(2.22))
|
||||||
|
assertProjectionSerialize(t, floatColumn2.defaultAliasProjection(), `sub_query."table1.colFloat" AS "sub_query.table1.colFloat"`)
|
||||||
|
|
||||||
assert.NilError(t, err)
|
|
||||||
assert.Equal(t, out.buff.String(), "col")
|
|
||||||
|
|
||||||
out.reset()
|
|
||||||
err = numericColumn.serialize(select_statement, &out)
|
|
||||||
assert.NilError(t, err)
|
|
||||||
assert.Equal(t, out.buff.String(), "col")
|
|
||||||
|
|
||||||
out.reset()
|
|
||||||
numericColumn.setTableName("table1")
|
|
||||||
err = numericColumn.DefaultAlias().serializeForProjection(select_statement, &out)
|
|
||||||
assert.NilError(t, err)
|
|
||||||
assert.Equal(t, out.buff.String(), `table1.col AS "table1.col"`)
|
|
||||||
|
|
||||||
out.reset()
|
|
||||||
numericColumn.setTableName("table1")
|
|
||||||
aliasedBoolColumn := numericColumn.AS("alias1")
|
|
||||||
err = aliasedBoolColumn.serializeForProjection(select_statement, &out)
|
|
||||||
assert.NilError(t, err)
|
|
||||||
assert.Equal(t, out.buff.String(), `table1.col AS "alias1"`)
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,12 +2,10 @@ package sqlbuilder
|
||||||
|
|
||||||
import "errors"
|
import "errors"
|
||||||
|
|
||||||
type expressionTable interface {
|
type ExpressionTable interface {
|
||||||
ReadableTable
|
ReadableTable
|
||||||
|
|
||||||
RefIntColumnName(name string) *IntegerColumn
|
Alias() string
|
||||||
RefIntColumn(column Column) *IntegerColumn
|
|
||||||
RefStringColumn(column Column) *StringColumn
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type expressionTableImpl struct {
|
type expressionTableImpl struct {
|
||||||
|
|
@ -16,7 +14,7 @@ type expressionTableImpl struct {
|
||||||
alias string
|
alias string
|
||||||
}
|
}
|
||||||
|
|
||||||
func newExpressionTable(expression Expression, alias string) expressionTable {
|
func newExpressionTable(expression Expression, alias string) ExpressionTable {
|
||||||
expTable := &expressionTableImpl{expression: expression, alias: alias}
|
expTable := &expressionTableImpl{expression: expression, alias: alias}
|
||||||
|
|
||||||
expTable.readableTableInterfaceImpl.parent = expTable
|
expTable.readableTableInterfaceImpl.parent = expTable
|
||||||
|
|
@ -24,40 +22,15 @@ func newExpressionTable(expression Expression, alias string) expressionTable {
|
||||||
return expTable
|
return expTable
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns the tableName's name in the database
|
func (e *expressionTableImpl) Alias() string {
|
||||||
func (e *expressionTableImpl) SchemaName() string {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *expressionTableImpl) TableName() string {
|
|
||||||
return e.alias
|
return e.alias
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *expressionTableImpl) RefIntColumnName(name string) *IntegerColumn {
|
|
||||||
intColumn := NewIntegerColumn(name, false)
|
|
||||||
intColumn.setTableName(e.alias)
|
|
||||||
|
|
||||||
return intColumn
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *expressionTableImpl) RefIntColumn(column Column) *IntegerColumn {
|
|
||||||
intColumn := NewIntegerColumn(column.TableName()+"."+column.Name(), false)
|
|
||||||
intColumn.setTableName(e.alias)
|
|
||||||
|
|
||||||
return intColumn
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *expressionTableImpl) RefStringColumn(column Column) *StringColumn {
|
|
||||||
strColumn := NewStringColumn(column.TableName()+"."+column.Name(), false)
|
|
||||||
strColumn.setTableName(e.alias)
|
|
||||||
return strColumn
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *expressionTableImpl) serialize(statement statementType, out *queryData, options ...serializeOption) error {
|
func (e *expressionTableImpl) serialize(statement statementType, out *queryData, options ...serializeOption) error {
|
||||||
if e == nil {
|
if e == nil {
|
||||||
return errors.New("Expression table is nil. ")
|
return errors.New("Expression table is nil. ")
|
||||||
}
|
}
|
||||||
//out.writeString("( ")
|
|
||||||
err := e.expression.serialize(statement, out)
|
err := e.expression.serialize(statement, out)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,7 @@ func (cl ColumnList) DefaultAlias() []projection {
|
||||||
newColumnList := []projection{}
|
newColumnList := []projection{}
|
||||||
|
|
||||||
for _, column := range cl {
|
for _, column := range cl {
|
||||||
newColumn := column.DefaultAlias()
|
newColumn := column.defaultAliasProjection()
|
||||||
newColumnList = append(newColumnList, newColumn)
|
newColumnList = append(newColumnList, newColumn)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,7 @@ type SelectStatement interface {
|
||||||
|
|
||||||
FOR_UPDATE() SelectStatement
|
FOR_UPDATE() SelectStatement
|
||||||
|
|
||||||
AsTable(alias string) expressionTable
|
AsTable(alias string) ExpressionTable
|
||||||
}
|
}
|
||||||
|
|
||||||
func SELECT(projection ...projection) SelectStatement {
|
func SELECT(projection ...projection) SelectStatement {
|
||||||
|
|
@ -54,7 +54,7 @@ func defaultProjectionAliasing(projections []projection) []projection {
|
||||||
|
|
||||||
for _, projection := range projections {
|
for _, projection := range projections {
|
||||||
if column, ok := projection.(Column); ok {
|
if column, ok := projection.(Column); ok {
|
||||||
aliasedProjections = append(aliasedProjections, column.DefaultAlias())
|
aliasedProjections = append(aliasedProjections, column.defaultAliasProjection())
|
||||||
} else if columnList, ok := projection.(ColumnList); ok {
|
} else if columnList, ok := projection.(ColumnList); ok {
|
||||||
aliasedProjections = append(aliasedProjections, columnList.DefaultAlias()...)
|
aliasedProjections = append(aliasedProjections, columnList.DefaultAlias()...)
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -204,7 +204,7 @@ func (s *selectStatementImpl) DebugSql() (query string, err error) {
|
||||||
return DebugSql(s)
|
return DebugSql(s)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *selectStatementImpl) AsTable(alias string) expressionTable {
|
func (s *selectStatementImpl) AsTable(alias string) ExpressionTable {
|
||||||
return newExpressionTable(s.parent, alias)
|
return newExpressionTable(s.parent, alias)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ type SetStatement interface {
|
||||||
LIMIT(limit int64) SetStatement
|
LIMIT(limit int64) SetStatement
|
||||||
OFFSET(offset int64) SetStatement
|
OFFSET(offset int64) SetStatement
|
||||||
|
|
||||||
AsTable(alias string) expressionTable
|
AsTable(alias string) ExpressionTable
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
|
@ -91,7 +91,7 @@ func (us *setStatementImpl) OFFSET(offset int64) SetStatement {
|
||||||
return us
|
return us
|
||||||
}
|
}
|
||||||
|
|
||||||
func (us *setStatementImpl) AsTable(alias string) expressionTable {
|
func (us *setStatementImpl) AsTable(alias string) ExpressionTable {
|
||||||
return newExpressionTable(us.parent, alias)
|
return newExpressionTable(us.parent, alias)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,12 +6,12 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
var table1Col1 = NewIntegerColumn("col1", true)
|
var table1Col1 = IntegerColumn("col1")
|
||||||
var table1ColInt = NewIntegerColumn("colInt", true)
|
var table1ColInt = IntegerColumn("colInt")
|
||||||
var table1ColFloat = NewFloatColumn("colFloat", true)
|
var table1ColFloat = FloatColumn("colFloat")
|
||||||
var table1Col3 = NewIntegerColumn("col3", true)
|
var table1Col3 = IntegerColumn("col3")
|
||||||
var table1ColTime = NewTimeColumn("colTime", true)
|
var table1ColTime = TimeColumn("colTime")
|
||||||
var table1ColBool = NewBoolColumn("colBool", true)
|
var table1ColBool = BoolColumn("colBool")
|
||||||
|
|
||||||
var table1 = NewTable(
|
var table1 = NewTable(
|
||||||
"db",
|
"db",
|
||||||
|
|
@ -23,13 +23,13 @@ var table1 = NewTable(
|
||||||
table1ColTime,
|
table1ColTime,
|
||||||
table1ColBool)
|
table1ColBool)
|
||||||
|
|
||||||
var table2Col3 = NewIntegerColumn("col3", true)
|
var table2Col3 = IntegerColumn("col3")
|
||||||
var table2Col4 = NewIntegerColumn("col4", true)
|
var table2Col4 = IntegerColumn("col4")
|
||||||
var table2ColInt = NewIntegerColumn("colInt", true)
|
var table2ColInt = IntegerColumn("colInt")
|
||||||
var table2ColFloat = NewFloatColumn("colFloat", true)
|
var table2ColFloat = FloatColumn("colFloat")
|
||||||
var table2ColStr = NewStringColumn("colStr", true)
|
var table2ColStr = StringColumn("colStr")
|
||||||
var table2ColBool = NewBoolColumn("colBool", true)
|
var table2ColBool = BoolColumn("colBool")
|
||||||
var table2ColTime = NewTimeColumn("colTime", true)
|
var table2ColTime = TimeColumn("colTime")
|
||||||
|
|
||||||
var table2 = NewTable(
|
var table2 = NewTable(
|
||||||
"db",
|
"db",
|
||||||
|
|
@ -42,9 +42,9 @@ var table2 = NewTable(
|
||||||
table2ColBool,
|
table2ColBool,
|
||||||
table2ColTime)
|
table2ColTime)
|
||||||
|
|
||||||
var table3Col1 = NewIntegerColumn("col1", true)
|
var table3Col1 = IntegerColumn("col1")
|
||||||
var table3ColInt = NewIntegerColumn("colInt", true)
|
var table3ColInt = IntegerColumn("colInt")
|
||||||
var table3StrCol = NewStringColumn("col2", true)
|
var table3StrCol = StringColumn("col2")
|
||||||
var table3 = NewTable(
|
var table3 = NewTable(
|
||||||
"db",
|
"db",
|
||||||
"table3",
|
"table3",
|
||||||
|
|
|
||||||
|
|
@ -203,7 +203,7 @@ FROM dvds.film_actor
|
||||||
INNER JOIN dvds.inventory ON (inventory.film_id = film.film_id)
|
INNER JOIN dvds.inventory ON (inventory.film_id = film.film_id)
|
||||||
INNER JOIN dvds.rental ON (rental.inventory_id = inventory.inventory_id)
|
INNER JOIN dvds.rental ON (rental.inventory_id = inventory.inventory_id)
|
||||||
ORDER BY film.film_id ASC
|
ORDER BY film.film_id ASC
|
||||||
LIMIT 50;
|
LIMIT 500;
|
||||||
`
|
`
|
||||||
for i := 0; i < 1; i++ {
|
for i := 0; i < 1; i++ {
|
||||||
query := FilmActor.
|
query := FilmActor.
|
||||||
|
|
@ -222,9 +222,9 @@ LIMIT 50;
|
||||||
).
|
).
|
||||||
//WHERE(FilmActor.ActorID.GtEqL(1).AND(FilmActor.ActorID.LtEqL(2))).
|
//WHERE(FilmActor.ActorID.GtEqL(1).AND(FilmActor.ActorID.LtEqL(2))).
|
||||||
ORDER_BY(Film.FilmID.ASC()).
|
ORDER_BY(Film.FilmID.ASC()).
|
||||||
LIMIT(50)
|
LIMIT(500)
|
||||||
|
|
||||||
assertQuery(t, query, expectedSql, int64(50))
|
assertQuery(t, query, expectedSql, int64(500))
|
||||||
|
|
||||||
var languageActorFilm []struct {
|
var languageActorFilm []struct {
|
||||||
model.Language
|
model.Language
|
||||||
|
|
@ -247,7 +247,7 @@ LIMIT 50;
|
||||||
|
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
assert.Equal(t, len(languageActorFilm), 1)
|
assert.Equal(t, len(languageActorFilm), 1)
|
||||||
assert.Equal(t, len(languageActorFilm[0].Films), 1)
|
assert.Equal(t, len(languageActorFilm[0].Films), 6)
|
||||||
assert.Equal(t, len(languageActorFilm[0].Films[0].Actors), 10)
|
assert.Equal(t, len(languageActorFilm[0].Films[0].Actors), 10)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -708,8 +708,7 @@ SELECT actor.actor_id AS "actor.actor_id",
|
||||||
film_actor.actor_id AS "film_actor.actor_id",
|
film_actor.actor_id AS "film_actor.actor_id",
|
||||||
film_actor.film_id AS "film_actor.film_id",
|
film_actor.film_id AS "film_actor.film_id",
|
||||||
film_actor.last_update AS "film_actor.last_update",
|
film_actor.last_update AS "film_actor.last_update",
|
||||||
films."film.title" AS "film.title",
|
rfilms."film.title" AS "film.title"
|
||||||
films."film.rating" AS "film.rating"
|
|
||||||
FROM dvds.actor
|
FROM dvds.actor
|
||||||
INNER JOIN dvds.film_actor ON (actor.actor_id = film_actor.film_id)
|
INNER JOIN dvds.film_actor ON (actor.actor_id = film_actor.film_id)
|
||||||
INNER JOIN (
|
INNER JOIN (
|
||||||
|
|
@ -718,28 +717,28 @@ FROM dvds.actor
|
||||||
film.rating AS "film.rating"
|
film.rating AS "film.rating"
|
||||||
FROM dvds.film
|
FROM dvds.film
|
||||||
WHERE film.rating = 'R'
|
WHERE film.rating = 'R'
|
||||||
) AS films ON (film_actor.film_id = films."film.film_id");
|
) AS rfilms ON (film_actor.film_id = rfilms."film.film_id");
|
||||||
`
|
`
|
||||||
|
|
||||||
rFilmsOnly := Film.
|
rRatingFilms := Film.
|
||||||
SELECT(
|
SELECT(
|
||||||
Film.FilmID,
|
Film.FilmID,
|
||||||
Film.Title,
|
Film.Title,
|
||||||
Film.Rating,
|
Film.Rating,
|
||||||
).
|
).
|
||||||
WHERE(Film.Rating.EQ(enum.MpaaRating.R)).
|
WHERE(Film.Rating.EQ(enum.MpaaRating.R)).
|
||||||
AsTable("films")
|
AsTable("rfilms")
|
||||||
|
|
||||||
rFilmId := rFilmsOnly.RefIntColumn(Film.FilmID)
|
rFilmId := Film.FilmID.From(rRatingFilms)
|
||||||
|
rTitle := Film.Title.From(rRatingFilms)
|
||||||
|
|
||||||
query := Actor.
|
query := Actor.
|
||||||
INNER_JOIN(FilmActor, Actor.ActorID.EQ(FilmActor.FilmID)).
|
INNER_JOIN(FilmActor, Actor.ActorID.EQ(FilmActor.FilmID)).
|
||||||
INNER_JOIN(rFilmsOnly, FilmActor.FilmID.EQ(rFilmId)).
|
INNER_JOIN(rRatingFilms, FilmActor.FilmID.EQ(rFilmId)).
|
||||||
SELECT(
|
SELECT(
|
||||||
Actor.AllColumns,
|
Actor.AllColumns,
|
||||||
FilmActor.AllColumns,
|
FilmActor.AllColumns,
|
||||||
rFilmsOnly.RefStringColumn(Film.Title).AS("film.title"),
|
rTitle.AS("film.title"),
|
||||||
rFilmsOnly.RefStringColumn(Film.Rating).AS("film.rating"),
|
|
||||||
)
|
)
|
||||||
|
|
||||||
fmt.Println(query.Sql())
|
fmt.Println(query.Sql())
|
||||||
|
|
@ -914,24 +913,24 @@ FROM dvds.customer
|
||||||
ORDER BY customer_payment_sum.amount_sum ASC;
|
ORDER BY customer_payment_sum.amount_sum ASC;
|
||||||
`
|
`
|
||||||
|
|
||||||
customersPaymentSubQuery := Payment.
|
customersPayments := Payment.
|
||||||
SELECT(
|
SELECT(
|
||||||
Payment.CustomerID,
|
Payment.CustomerID,
|
||||||
SUMf(Payment.Amount).AS("amount_sum"),
|
SUMf(Payment.Amount).AS("amount_sum"),
|
||||||
).
|
).
|
||||||
GROUP_BY(Payment.CustomerID)
|
GROUP_BY(Payment.CustomerID).
|
||||||
|
AsTable("customer_payment_sum")
|
||||||
|
|
||||||
customersPaymentTable := customersPaymentSubQuery.AsTable("customer_payment_sum")
|
customerId := Payment.CustomerID.From(customersPayments)
|
||||||
amountSumColumn := customersPaymentTable.RefIntColumnName("amount_sum")
|
amountSum := FloatColumn("amount_sum").From(customersPayments)
|
||||||
customerId := customersPaymentTable.RefIntColumn(Payment.CustomerID)
|
|
||||||
|
|
||||||
query := Customer.
|
query := Customer.
|
||||||
INNER_JOIN(customersPaymentTable, Customer.CustomerID.EQ(customerId)).
|
INNER_JOIN(customersPayments, Customer.CustomerID.EQ(customerId)).
|
||||||
SELECT(
|
SELECT(
|
||||||
Customer.AllColumns,
|
Customer.AllColumns,
|
||||||
amountSumColumn.AS("customer_with_amounts.amount_sum"),
|
amountSum.AS("customer_with_amounts.amount_sum"),
|
||||||
).
|
).
|
||||||
ORDER_BY(amountSumColumn.ASC())
|
ORDER_BY(amountSum.ASC())
|
||||||
|
|
||||||
assertQuery(t, query, expectedSql)
|
assertQuery(t, query, expectedSql)
|
||||||
|
|
||||||
|
|
@ -1039,7 +1038,7 @@ OFFSET 20;
|
||||||
SELECT(Payment.PaymentID, Payment.Amount).
|
SELECT(Payment.PaymentID, Payment.Amount).
|
||||||
WHERE(Payment.Amount.GT_EQ(Float(200))),
|
WHERE(Payment.Amount.GT_EQ(Float(200))),
|
||||||
).
|
).
|
||||||
ORDER_BY(RefColumn("payment.payment_id").ASC(), Payment.Amount.DESC()).
|
ORDER_BY(IntegerColumn("payment.payment_id").ASC(), Payment.Amount.DESC()).
|
||||||
LIMIT(10).
|
LIMIT(10).
|
||||||
OFFSET(20)
|
OFFSET(20)
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue