Default aliasing refactoring.
This commit is contained in:
parent
22426c8cad
commit
5ad213885f
16 changed files with 198 additions and 124 deletions
|
|
@ -11,6 +11,7 @@ type serializeOption int
|
||||||
const (
|
const (
|
||||||
SKIP_DEFAULT_ALIASING = iota
|
SKIP_DEFAULT_ALIASING = iota
|
||||||
FOR_PROJECTION
|
FOR_PROJECTION
|
||||||
|
UNION_ORDER_BY
|
||||||
NO_TABLE_NAME
|
NO_TABLE_NAME
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -21,6 +22,56 @@ type Clause interface {
|
||||||
type queryData struct {
|
type queryData struct {
|
||||||
buff bytes.Buffer
|
buff bytes.Buffer
|
||||||
args []interface{}
|
args []interface{}
|
||||||
|
|
||||||
|
statementType int
|
||||||
|
clauseType int
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
select_statement = iota
|
||||||
|
insert_statement
|
||||||
|
update_statement
|
||||||
|
delete_statement
|
||||||
|
set_statement
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
projection_clause = iota
|
||||||
|
where_clause
|
||||||
|
order_by_clause
|
||||||
|
group_by_clause
|
||||||
|
having_clause
|
||||||
|
)
|
||||||
|
|
||||||
|
func (q *queryData) WriteProjection(projections []Projection) error {
|
||||||
|
q.clauseType = projection_clause
|
||||||
|
return serializeProjectionList(projections, q)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (q *queryData) WriteWhere(where Expression) error {
|
||||||
|
q.clauseType = where_clause
|
||||||
|
q.WriteString(" WHERE ")
|
||||||
|
return where.Serialize(q)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (q *queryData) WriteGroupBy(groupBy []Clause) error {
|
||||||
|
q.clauseType = group_by_clause
|
||||||
|
q.WriteString(" GROUP BY ")
|
||||||
|
|
||||||
|
return serializeClauseList(groupBy, q)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (q *queryData) WriteOrderBy(orderBy []OrderByClause) error {
|
||||||
|
q.clauseType = order_by_clause
|
||||||
|
q.WriteString(" ORDER BY ")
|
||||||
|
return serializeOrderByClauseList(orderBy, q)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (q *queryData) WriteHaving(having Expression) error {
|
||||||
|
q.clauseType = having_clause
|
||||||
|
q.WriteString(" HAVING ")
|
||||||
|
return having.Serialize(q)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (q *queryData) Write(data []byte) {
|
func (q *queryData) Write(data []byte) {
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,8 @@ type Column interface {
|
||||||
|
|
||||||
Name() string
|
Name() string
|
||||||
TableName() string
|
TableName() string
|
||||||
|
|
||||||
|
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) error
|
||||||
|
|
@ -72,26 +74,41 @@ func (c *baseColumn) setTableName(table string) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *baseColumn) DefaultAlias() Projection {
|
||||||
|
return c.As(c.tableName + "." + c.name)
|
||||||
|
}
|
||||||
|
|
||||||
func (c baseColumn) Serialize(out *queryData, options ...serializeOption) error {
|
func (c baseColumn) Serialize(out *queryData, options ...serializeOption) error {
|
||||||
if c.tableName != "" && !contains(options, NO_TABLE_NAME) {
|
|
||||||
|
setOrderBy := out.statementType == set_statement && out.clauseType == order_by_clause
|
||||||
|
|
||||||
|
if setOrderBy {
|
||||||
|
out.WriteString(`"`)
|
||||||
|
}
|
||||||
|
|
||||||
|
if c.tableName != "" {
|
||||||
out.WriteString(c.tableName)
|
out.WriteString(c.tableName)
|
||||||
out.WriteString(".")
|
out.WriteString(".")
|
||||||
}
|
}
|
||||||
|
|
||||||
containsDot := strings.Contains(c.name, ".")
|
wrapColumnName := strings.Contains(c.name, ".") && !setOrderBy
|
||||||
|
|
||||||
if containsDot {
|
if wrapColumnName {
|
||||||
out.WriteString(`"`)
|
out.WriteString(`"`)
|
||||||
}
|
}
|
||||||
|
|
||||||
out.WriteString(c.name)
|
out.WriteString(c.name)
|
||||||
|
|
||||||
if containsDot {
|
if wrapColumnName {
|
||||||
out.WriteString(`"`)
|
out.WriteString(`"`)
|
||||||
}
|
}
|
||||||
|
|
||||||
if contains(options, FOR_PROJECTION) && !contains(options, SKIP_DEFAULT_ALIASING) && c.tableName != "" {
|
//if contains(options, FOR_PROJECTION) && !contains(options, SKIP_DEFAULT_ALIASING) && c.tableName != "" {
|
||||||
out.WriteString(" AS \"" + c.tableName + "." + c.name + "\"")
|
// out.WriteString(" AS \"" + c.tableName + "." + c.name + `"`)
|
||||||
|
//}
|
||||||
|
|
||||||
|
if setOrderBy {
|
||||||
|
out.WriteString(`"`)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|
|
||||||
|
|
@ -93,3 +93,15 @@ func NewTimeColumn(name string, nullable NullableColumn) *TimeColumn {
|
||||||
|
|
||||||
return stringColumn
|
return stringColumn
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------//
|
||||||
|
type refColumn struct {
|
||||||
|
baseColumn
|
||||||
|
}
|
||||||
|
|
||||||
|
func RefColumn(name string) *refColumn {
|
||||||
|
refColumn := &refColumn{}
|
||||||
|
refColumn.baseColumn = newBaseColumn(name, false, "", refColumn)
|
||||||
|
|
||||||
|
return refColumn
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,7 @@ func TestNewBoolColumn(t *testing.T) {
|
||||||
out.Reset()
|
out.Reset()
|
||||||
err = boolColumn.setTableName("table1")
|
err = boolColumn.setTableName("table1")
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
err = boolColumn.Serialize(&out, FOR_PROJECTION)
|
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"`)
|
||||||
|
|
||||||
|
|
@ -52,7 +52,7 @@ func TestNewIntColumn(t *testing.T) {
|
||||||
out.Reset()
|
out.Reset()
|
||||||
err = integerColumn.setTableName("table1")
|
err = integerColumn.setTableName("table1")
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
err = integerColumn.Serialize(&out, FOR_PROJECTION)
|
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"`)
|
||||||
|
|
||||||
|
|
@ -82,7 +82,7 @@ func TestNewNumericColumnColumn(t *testing.T) {
|
||||||
out.Reset()
|
out.Reset()
|
||||||
err = numericColumn.setTableName("table1")
|
err = numericColumn.setTableName("table1")
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
err = numericColumn.Serialize(&out, FOR_PROJECTION)
|
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"`)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -21,15 +21,6 @@ func newDeleteStatement(table WritableTable) DeleteStatement {
|
||||||
type deleteStatementImpl struct {
|
type deleteStatementImpl struct {
|
||||||
table WritableTable
|
table WritableTable
|
||||||
where BoolExpression
|
where BoolExpression
|
||||||
order *listClause
|
|
||||||
}
|
|
||||||
|
|
||||||
func (u *deleteStatementImpl) Query(db types.Db, destination interface{}) error {
|
|
||||||
return Query(u, db, destination)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (u *deleteStatementImpl) Execute(db types.Db) (res sql.Result, err error) {
|
|
||||||
return Execute(u, db)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *deleteStatementImpl) WHERE(expression BoolExpression) DeleteStatement {
|
func (d *deleteStatementImpl) WHERE(expression BoolExpression) DeleteStatement {
|
||||||
|
|
@ -39,6 +30,7 @@ func (d *deleteStatementImpl) WHERE(expression BoolExpression) DeleteStatement {
|
||||||
|
|
||||||
func (d *deleteStatementImpl) Sql() (query string, args []interface{}, err error) {
|
func (d *deleteStatementImpl) Sql() (query string, args []interface{}, err error) {
|
||||||
queryData := &queryData{}
|
queryData := &queryData{}
|
||||||
|
queryData.statementType = delete_statement
|
||||||
|
|
||||||
queryData.WriteString("DELETE FROM ")
|
queryData.WriteString("DELETE FROM ")
|
||||||
|
|
||||||
|
|
@ -54,18 +46,17 @@ func (d *deleteStatementImpl) Sql() (query string, args []interface{}, err error
|
||||||
return "", nil, errors.New("Deleting without a WHERE clause.")
|
return "", nil, errors.New("Deleting without a WHERE clause.")
|
||||||
}
|
}
|
||||||
|
|
||||||
queryData.WriteString(" WHERE ")
|
if err = queryData.WriteWhere(d.where); err != nil {
|
||||||
|
|
||||||
if err = d.where.Serialize(queryData); err != nil {
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if d.order != nil {
|
|
||||||
queryData.WriteString(" ORDER BY ")
|
|
||||||
if err = d.order.Serialize(queryData); err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return queryData.buff.String() + ";", queryData.args, nil
|
return queryData.buff.String() + ";", queryData.args, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (u *deleteStatementImpl) Query(db types.Db, destination interface{}) error {
|
||||||
|
return Query(u, db, destination)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u *deleteStatementImpl) Execute(db types.Db) (res sql.Result, err error) {
|
||||||
|
return Execute(u, db)
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -67,7 +67,7 @@ func isSimpleOperand(expression Expression) bool {
|
||||||
if _, ok := expression.(Column); ok {
|
if _, ok := expression.(Column); ok {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
if _, ok := expression.(FuncExpression); ok {
|
if _, ok := expression.(*numericFunc); ok {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
package sqlbuilder
|
package sqlbuilder
|
||||||
|
|
||||||
type FuncExpression interface {
|
//type FuncExpression interface {
|
||||||
Expression
|
// Expression
|
||||||
}
|
//}
|
||||||
|
|
||||||
type numericFunc struct {
|
type numericFunc struct {
|
||||||
expressionInterfaceImpl
|
expressionInterfaceImpl
|
||||||
|
|
|
||||||
|
|
@ -111,7 +111,7 @@ func (i *insertStatementImpl) VALUES_MAPPING(data interface{}) InsertStatement {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i *insertStatementImpl) RETURNING(projections ...Projection) InsertStatement {
|
func (i *insertStatementImpl) RETURNING(projections ...Projection) InsertStatement {
|
||||||
i.returning = projections
|
i.returning = defaultProjectionAliasing(projections)
|
||||||
|
|
||||||
return i
|
return i
|
||||||
}
|
}
|
||||||
|
|
@ -132,6 +132,7 @@ func (s *insertStatementImpl) Sql() (sql string, args []interface{}, err error)
|
||||||
}
|
}
|
||||||
|
|
||||||
queryData := &queryData{}
|
queryData := &queryData{}
|
||||||
|
queryData.statementType = insert_statement
|
||||||
queryData.WriteString("INSERT INTO ")
|
queryData.WriteString("INSERT INTO ")
|
||||||
|
|
||||||
if s.table == nil {
|
if s.table == nil {
|
||||||
|
|
@ -147,18 +148,6 @@ func (s *insertStatementImpl) Sql() (sql string, args []interface{}, err error)
|
||||||
if len(s.columns) > 0 {
|
if len(s.columns) > 0 {
|
||||||
queryData.WriteString(" (")
|
queryData.WriteString(" (")
|
||||||
|
|
||||||
//for i, col := range s.columns {
|
|
||||||
// if i > 0 {
|
|
||||||
// queryData.WriteByte(',')
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// if col == nil {
|
|
||||||
// return "", nil, errors.New("nil column in columns list.")
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// queryData.WriteString(col.Name())
|
|
||||||
//}
|
|
||||||
|
|
||||||
err = serializeColumnList(s.columns, queryData)
|
err = serializeColumnList(s.columns, queryData)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -193,19 +182,6 @@ func (s *insertStatementImpl) Sql() (sql string, args []interface{}, err error)
|
||||||
return "", nil, err
|
return "", nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
//for col_i, value := range row {
|
|
||||||
// if col_i > 0 {
|
|
||||||
// queryData.WriteByte(',')
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// if value == nil {
|
|
||||||
// return "", nil, errors.Newf("nil value in row %d col %d.", row_i, col_i)
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// if err = value.Serialize(queryData); err != nil {
|
|
||||||
// return
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
queryData.WriteByte(')')
|
queryData.WriteByte(')')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -221,7 +197,7 @@ func (s *insertStatementImpl) Sql() (sql string, args []interface{}, err error)
|
||||||
if len(s.returning) > 0 {
|
if len(s.returning) > 0 {
|
||||||
queryData.WriteString(" RETURNING ")
|
queryData.WriteString(" RETURNING ")
|
||||||
|
|
||||||
err = serializeProjectionList(s.returning, queryData)
|
err = queryData.WriteProjection(s.returning)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,15 @@ type isOrderByClause struct {
|
||||||
func (o *isOrderByClause) isOrderByClauseType() {
|
func (o *isOrderByClause) isOrderByClauseType() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type ColumnNameOrderBy string
|
||||||
|
|
||||||
|
func (o *ColumnNameOrderBy) isOrderByClauseType() {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *ColumnNameOrderBy) Serialize(out *queryData, options ...serializeOption) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
type orderByClause struct {
|
type orderByClause struct {
|
||||||
isOrderByClause
|
isOrderByClause
|
||||||
expression Expression
|
expression Expression
|
||||||
|
|
@ -24,7 +33,7 @@ func (o *orderByClause) Serialize(out *queryData, options ...serializeOption) er
|
||||||
return errors.Newf("nil orderBy by clause.")
|
return errors.Newf("nil orderBy by clause.")
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := o.expression.Serialize(out); err != nil {
|
if err := o.expression.Serialize(out, UNION_ORDER_BY); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -22,3 +22,14 @@ func (cl ColumnList) SerializeForProjection(out *queryData) error {
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (cl ColumnList) DefaultAlias() []Projection {
|
||||||
|
newColumnList := []Projection{}
|
||||||
|
|
||||||
|
for _, column := range cl {
|
||||||
|
newColumn := column.DefaultAlias()
|
||||||
|
newColumnList = append(newColumnList, newColumn)
|
||||||
|
}
|
||||||
|
|
||||||
|
return newColumnList
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,7 @@ type selectStatementImpl struct {
|
||||||
distinct bool
|
distinct bool
|
||||||
projections []Projection
|
projections []Projection
|
||||||
where BoolExpression
|
where BoolExpression
|
||||||
groupBy []Clause
|
groupBy []Clause //can be ROLLUP, ... so clause for now
|
||||||
having BoolExpression
|
having BoolExpression
|
||||||
orderBy []OrderByClause
|
orderBy []OrderByClause
|
||||||
|
|
||||||
|
|
@ -42,13 +42,27 @@ type selectStatementImpl struct {
|
||||||
forUpdate bool
|
forUpdate bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func newSelectStatement(
|
func defaultProjectionAliasing(projections []Projection) []Projection {
|
||||||
table ReadableTable,
|
aliasedProjections := []Projection{}
|
||||||
projections []Projection) SelectStatement {
|
|
||||||
|
for _, projection := range projections {
|
||||||
|
if column, ok := projection.(Column); ok {
|
||||||
|
aliasedProjections = append(aliasedProjections, column.DefaultAlias())
|
||||||
|
} else if columnList, ok := projection.(ColumnList); ok {
|
||||||
|
aliasedProjections = append(aliasedProjections, columnList.DefaultAlias()...)
|
||||||
|
} else {
|
||||||
|
aliasedProjections = append(aliasedProjections, projection)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return aliasedProjections
|
||||||
|
}
|
||||||
|
|
||||||
|
func newSelectStatement(table ReadableTable, projections []Projection) SelectStatement {
|
||||||
|
|
||||||
return &selectStatementImpl{
|
return &selectStatementImpl{
|
||||||
table: table,
|
table: table,
|
||||||
projections: projections,
|
projections: defaultProjectionAliasing(projections),
|
||||||
limit: -1,
|
limit: -1,
|
||||||
offset: -1,
|
offset: -1,
|
||||||
forUpdate: false,
|
forUpdate: false,
|
||||||
|
|
@ -74,6 +88,7 @@ func (s *selectStatementImpl) Serialize(out *queryData, options ...serializeOpti
|
||||||
func (s *selectStatementImpl) serializeImpl(out *queryData, options ...serializeOption) error {
|
func (s *selectStatementImpl) serializeImpl(out *queryData, options ...serializeOption) error {
|
||||||
|
|
||||||
out.WriteString("SELECT ")
|
out.WriteString("SELECT ")
|
||||||
|
out.statementType = select_statement
|
||||||
|
|
||||||
if s.distinct {
|
if s.distinct {
|
||||||
out.WriteString("DISTINCT ")
|
out.WriteString("DISTINCT ")
|
||||||
|
|
@ -83,7 +98,7 @@ func (s *selectStatementImpl) serializeImpl(out *queryData, options ...serialize
|
||||||
return errors.New("No column selected for projection.")
|
return errors.New("No column selected for projection.")
|
||||||
}
|
}
|
||||||
|
|
||||||
err := serializeProjectionList(s.projections, out)
|
err := out.WriteProjection(s.projections)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
|
@ -100,16 +115,15 @@ func (s *selectStatementImpl) serializeImpl(out *queryData, options ...serialize
|
||||||
}
|
}
|
||||||
|
|
||||||
if s.where != nil {
|
if s.where != nil {
|
||||||
out.WriteString(" WHERE ")
|
err := out.WriteWhere(s.where)
|
||||||
if err := s.where.Serialize(out); err != nil {
|
|
||||||
return err
|
if err != nil {
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if s.groupBy != nil && len(s.groupBy) > 0 {
|
if s.groupBy != nil && len(s.groupBy) > 0 {
|
||||||
out.WriteString(" GROUP BY ")
|
err := out.WriteGroupBy(s.groupBy)
|
||||||
|
|
||||||
err := serializeClauseList(s.groupBy, out)
|
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
|
@ -117,15 +131,17 @@ func (s *selectStatementImpl) serializeImpl(out *queryData, options ...serialize
|
||||||
}
|
}
|
||||||
|
|
||||||
if s.having != nil {
|
if s.having != nil {
|
||||||
out.WriteString(" HAVING ")
|
err := out.WriteHaving(s.having)
|
||||||
if err = s.having.Serialize(out); err != nil {
|
|
||||||
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if s.orderBy != nil {
|
if s.orderBy != nil {
|
||||||
out.WriteString(" ORDER BY ")
|
err := out.WriteOrderBy(s.orderBy)
|
||||||
if err := serializeOrderByClauseList(s.orderBy, out); err != nil {
|
|
||||||
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -48,7 +48,7 @@ func EXCEPT_ALL(selects ...SelectStatement) SetStatement {
|
||||||
type setStatementImpl struct {
|
type setStatementImpl struct {
|
||||||
operator string
|
operator string
|
||||||
selects []SelectStatement
|
selects []SelectStatement
|
||||||
order *listClause
|
orderBy []OrderByClause
|
||||||
limit, offset int64
|
limit, offset int64
|
||||||
// True if results of the union should be deduped.
|
// True if results of the union should be deduped.
|
||||||
all bool
|
all bool
|
||||||
|
|
@ -64,9 +64,9 @@ func newSetStatementImpl(operator string, all bool, selects ...SelectStatement)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (us *setStatementImpl) ORDER_BY(clauses ...OrderByClause) SetStatement {
|
func (us *setStatementImpl) ORDER_BY(orderBy ...OrderByClause) SetStatement {
|
||||||
|
|
||||||
us.order = newOrderByListClause(clauses...)
|
us.orderBy = orderBy
|
||||||
return us
|
return us
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -80,18 +80,19 @@ func (us *setStatementImpl) OFFSET(offset int64) SetStatement {
|
||||||
return us
|
return us
|
||||||
}
|
}
|
||||||
|
|
||||||
func (us *setStatementImpl) Serialize(out *queryData, options ...serializeOption) error {
|
func (s *setStatementImpl) Serialize(out *queryData, options ...serializeOption) error {
|
||||||
if len(us.selects) < 2 {
|
|
||||||
|
if len(s.selects) < 2 {
|
||||||
return errors.Newf("UNION statement must have at least two SELECT statements.")
|
return errors.Newf("UNION statement must have at least two SELECT statements.")
|
||||||
}
|
}
|
||||||
|
|
||||||
out.WriteString("(")
|
out.WriteString("(")
|
||||||
|
|
||||||
for i, selectStmt := range us.selects {
|
for i, selectStmt := range s.selects {
|
||||||
if i > 0 {
|
if i > 0 {
|
||||||
out.WriteString(" " + us.operator + " ")
|
out.WriteString(" " + s.operator + " ")
|
||||||
|
|
||||||
if us.all {
|
if s.all {
|
||||||
out.WriteString(" ALL ")
|
out.WriteString(" ALL ")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -105,21 +106,23 @@ func (us *setStatementImpl) Serialize(out *queryData, options ...serializeOption
|
||||||
|
|
||||||
out.WriteString(")")
|
out.WriteString(")")
|
||||||
|
|
||||||
if us.order != nil {
|
out.statementType = set_statement
|
||||||
out.WriteString(" ORDER BY ")
|
|
||||||
if err := us.order.Serialize(out, NO_TABLE_NAME); err != nil {
|
if s.orderBy != nil {
|
||||||
|
err := out.WriteOrderBy(s.orderBy)
|
||||||
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if us.limit >= 0 {
|
if s.limit >= 0 {
|
||||||
out.WriteString(" LIMIT ")
|
out.WriteString(" LIMIT ")
|
||||||
out.InsertArgument(us.limit)
|
out.InsertArgument(s.limit)
|
||||||
}
|
}
|
||||||
|
|
||||||
if us.offset >= 0 {
|
if s.offset >= 0 {
|
||||||
out.WriteString(" OFFSET ")
|
out.WriteString(" OFFSET ")
|
||||||
out.InsertArgument(us.offset)
|
out.InsertArgument(s.offset)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|
|
||||||
|
|
@ -7,11 +7,11 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestUnionNoSelect(t *testing.T) {
|
func TestUnionNoSelect(t *testing.T) {
|
||||||
query, args, err := UNION().Sql()
|
_, _, err := UNION().Sql()
|
||||||
|
|
||||||
assert.Assert(t, err != nil)
|
assert.Assert(t, err != nil)
|
||||||
//fmt.Println(err.Error())
|
//fmt.Println(err.Error())
|
||||||
fmt.Print(query, args)
|
//fmt.Print(query, args)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestUnionOneSelect(t *testing.T) {
|
func TestUnionOneSelect(t *testing.T) {
|
||||||
|
|
@ -55,7 +55,7 @@ func TestUnionWithOrderBy(t *testing.T) {
|
||||||
).ORDER_BY(table1Col1.Asc()).Sql()
|
).ORDER_BY(table1Col1.Asc()).Sql()
|
||||||
|
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
assert.Equal(t, query, `((SELECT table1.col1 AS "table1.col1" FROM db.table1) UNION (SELECT table2.col3 AS "table2.col3" FROM db.table2)) ORDER BY table1.col1 ASC`)
|
assert.Equal(t, query, `((SELECT table1.col1 AS "table1.col1" FROM db.table1) UNION (SELECT table2.col3 AS "table2.col3" FROM db.table2)) ORDER BY "table1.col1" ASC`)
|
||||||
assert.Equal(t, len(args), 0)
|
assert.Equal(t, len(args), 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -29,14 +29,6 @@ type updateStatementImpl struct {
|
||||||
returning []Projection
|
returning []Projection
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *updateStatementImpl) Query(db types.Db, destination interface{}) error {
|
|
||||||
return Query(u, db, destination)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (u *updateStatementImpl) Execute(db types.Db) (res sql.Result, err error) {
|
|
||||||
return Execute(u, db)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (u *updateStatementImpl) SET(values ...interface{}) UpdateStatement {
|
func (u *updateStatementImpl) SET(values ...interface{}) UpdateStatement {
|
||||||
|
|
||||||
for _, value := range values {
|
for _, value := range values {
|
||||||
|
|
@ -56,12 +48,14 @@ func (u *updateStatementImpl) WHERE(expression BoolExpression) UpdateStatement {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *updateStatementImpl) RETURNING(projections ...Projection) UpdateStatement {
|
func (u *updateStatementImpl) RETURNING(projections ...Projection) UpdateStatement {
|
||||||
u.returning = projections
|
u.returning = defaultProjectionAliasing(projections)
|
||||||
return u
|
return u
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *updateStatementImpl) Sql() (sql string, args []interface{}, err error) {
|
func (u *updateStatementImpl) Sql() (sql string, args []interface{}, err error) {
|
||||||
out := &queryData{}
|
out := &queryData{}
|
||||||
|
out.statementType = update_statement
|
||||||
|
|
||||||
out.WriteString("UPDATE ")
|
out.WriteString("UPDATE ")
|
||||||
|
|
||||||
if u.table == nil {
|
if u.table == nil {
|
||||||
|
|
@ -84,18 +78,6 @@ func (u *updateStatementImpl) Sql() (sql string, args []interface{}, err error)
|
||||||
out.WriteString(" ")
|
out.WriteString(" ")
|
||||||
}
|
}
|
||||||
|
|
||||||
//for i, column := range u.columns {
|
|
||||||
// if i > 0 {
|
|
||||||
// out.WriteString(", ")
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// out.WriteString(column.Name())
|
|
||||||
//
|
|
||||||
// if err != nil {
|
|
||||||
// return
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
|
|
||||||
err = serializeColumnList(u.columns, out)
|
err = serializeColumnList(u.columns, out)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -132,8 +114,7 @@ func (u *updateStatementImpl) Sql() (sql string, args []interface{}, err error)
|
||||||
return "", nil, errors.New("Updating without a WHERE clause.")
|
return "", nil, errors.New("Updating without a WHERE clause.")
|
||||||
}
|
}
|
||||||
|
|
||||||
out.WriteString(" WHERE ")
|
if err = out.WriteWhere(u.where); err != nil {
|
||||||
if err = u.where.Serialize(out); err != nil {
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -149,3 +130,11 @@ func (u *updateStatementImpl) Sql() (sql string, args []interface{}, err error)
|
||||||
|
|
||||||
return out.buff.String(), out.args, nil
|
return out.buff.String(), out.args, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (u *updateStatementImpl) Query(db types.Db, destination interface{}) error {
|
||||||
|
return Query(u, db, destination)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u *updateStatementImpl) Execute(db types.Db) (res sql.Result, err error) {
|
||||||
|
return Execute(u, db)
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -63,7 +63,7 @@ func serializeExpressionList(expressions []Expression, separator string, out *qu
|
||||||
func serializeProjectionList(projections []Projection, out *queryData) error {
|
func serializeProjectionList(projections []Projection, out *queryData) error {
|
||||||
for i, col := range projections {
|
for i, col := range projections {
|
||||||
if i > 0 {
|
if i > 0 {
|
||||||
out.WriteByte(',')
|
out.WriteString(", ")
|
||||||
}
|
}
|
||||||
if col == nil {
|
if col == nil {
|
||||||
return errors.New("Projection expression is nil.")
|
return errors.New("Projection expression is nil.")
|
||||||
|
|
|
||||||
|
|
@ -102,7 +102,7 @@ func TestJoinQuerySlice(t *testing.T) {
|
||||||
|
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
fmt.Println(queryStr)
|
fmt.Println(queryStr)
|
||||||
assert.Equal(t, queryStr, `SELECT language.language_id AS "language.language_id", language.name AS "language.name", language.last_update AS "language.last_update",film.film_id AS "film.film_id", film.title AS "film.title", film.description AS "film.description", film.release_year AS "film.release_year", film.language_id AS "film.language_id", film.rental_duration AS "film.rental_duration", film.rental_rate AS "film.rental_rate", film.length AS "film.length", film.replacement_cost AS "film.replacement_cost", film.rating AS "film.rating", film.last_update AS "film.last_update", film.special_features AS "film.special_features", film.fulltext AS "film.fulltext" FROM dvds.film JOIN dvds.language ON film.language_id = language.language_id WHERE film.rating = $1 LIMIT $2`)
|
assert.Equal(t, queryStr, `SELECT language.language_id AS "language.language_id", language.name AS "language.name", language.last_update AS "language.last_update", film.film_id AS "film.film_id", film.title AS "film.title", film.description AS "film.description", film.release_year AS "film.release_year", film.language_id AS "film.language_id", film.rental_duration AS "film.rental_duration", film.rental_rate AS "film.rental_rate", film.length AS "film.length", film.replacement_cost AS "film.replacement_cost", film.rating AS "film.rating", film.last_update AS "film.last_update", film.special_features AS "film.special_features", film.fulltext AS "film.fulltext" FROM dvds.film JOIN dvds.language ON film.language_id = language.language_id WHERE film.rating = $1 LIMIT $2`)
|
||||||
|
|
||||||
assert.Equal(t, len(args), 2)
|
assert.Equal(t, len(args), 2)
|
||||||
assert.Equal(t, args[0], string(model.MpaaRating_NC17))
|
assert.Equal(t, args[0], string(model.MpaaRating_NC17))
|
||||||
|
|
@ -228,7 +228,7 @@ func TestSelectFullJoin(t *testing.T) {
|
||||||
|
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
|
|
||||||
assert.Equal(t, queryStr, `SELECT customer.customer_id AS "customer.customer_id", customer.store_id AS "customer.store_id", customer.first_name AS "customer.first_name", customer.last_name AS "customer.last_name", customer.email AS "customer.email", customer.address_id AS "customer.address_id", customer.activebool AS "customer.activebool", customer.create_date AS "customer.create_date", customer.last_update AS "customer.last_update", customer.active AS "customer.active",address.address_id AS "address.address_id", address.address AS "address.address", address.address2 AS "address.address2", address.district AS "address.district", address.city_id AS "address.city_id", address.postal_code AS "address.postal_code", address.phone AS "address.phone", address.last_update AS "address.last_update" FROM dvds.customer FULL JOIN dvds.address ON customer.address_id = address.address_id ORDER BY customer.customer_id ASC`)
|
assert.Equal(t, queryStr, `SELECT customer.customer_id AS "customer.customer_id", customer.store_id AS "customer.store_id", customer.first_name AS "customer.first_name", customer.last_name AS "customer.last_name", customer.email AS "customer.email", customer.address_id AS "customer.address_id", customer.activebool AS "customer.activebool", customer.create_date AS "customer.create_date", customer.last_update AS "customer.last_update", customer.active AS "customer.active", address.address_id AS "address.address_id", address.address AS "address.address", address.address2 AS "address.address2", address.district AS "address.district", address.city_id AS "address.city_id", address.postal_code AS "address.postal_code", address.phone AS "address.phone", address.last_update AS "address.last_update" FROM dvds.customer FULL JOIN dvds.address ON customer.address_id = address.address_id ORDER BY customer.customer_id ASC`)
|
||||||
assert.Equal(t, len(args), 0)
|
assert.Equal(t, len(args), 0)
|
||||||
|
|
||||||
allCustomersAndAddress := []struct {
|
allCustomersAndAddress := []struct {
|
||||||
|
|
@ -261,7 +261,7 @@ func TestSelectFullCrossJoin(t *testing.T) {
|
||||||
queryStr, args, err := query.Sql()
|
queryStr, args, err := query.Sql()
|
||||||
|
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
assert.Equal(t, queryStr, `SELECT customer.customer_id AS "customer.customer_id", customer.store_id AS "customer.store_id", customer.first_name AS "customer.first_name", customer.last_name AS "customer.last_name", customer.email AS "customer.email", customer.address_id AS "customer.address_id", customer.activebool AS "customer.activebool", customer.create_date AS "customer.create_date", customer.last_update AS "customer.last_update", customer.active AS "customer.active",address.address_id AS "address.address_id", address.address AS "address.address", address.address2 AS "address.address2", address.district AS "address.district", address.city_id AS "address.city_id", address.postal_code AS "address.postal_code", address.phone AS "address.phone", address.last_update AS "address.last_update" FROM dvds.customer CROSS JOIN dvds.address ORDER BY customer.customer_id ASC LIMIT $1`)
|
assert.Equal(t, queryStr, `SELECT customer.customer_id AS "customer.customer_id", customer.store_id AS "customer.store_id", customer.first_name AS "customer.first_name", customer.last_name AS "customer.last_name", customer.email AS "customer.email", customer.address_id AS "customer.address_id", customer.activebool AS "customer.activebool", customer.create_date AS "customer.create_date", customer.last_update AS "customer.last_update", customer.active AS "customer.active", address.address_id AS "address.address_id", address.address AS "address.address", address.address2 AS "address.address2", address.district AS "address.district", address.city_id AS "address.city_id", address.postal_code AS "address.postal_code", address.phone AS "address.phone", address.last_update AS "address.last_update" FROM dvds.customer CROSS JOIN dvds.address ORDER BY customer.customer_id ASC LIMIT $1`)
|
||||||
assert.Equal(t, len(args), 1)
|
assert.Equal(t, len(args), 1)
|
||||||
|
|
||||||
customerAddresCrosJoined := []model.Customer{}
|
customerAddresCrosJoined := []model.Customer{}
|
||||||
|
|
@ -328,10 +328,9 @@ func TestSelectAliasColumn(t *testing.T) {
|
||||||
LIMIT(1000)
|
LIMIT(1000)
|
||||||
|
|
||||||
queryStr, args, err := query.Sql()
|
queryStr, args, err := query.Sql()
|
||||||
assert.Equal(t, len(args), 1)
|
|
||||||
|
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
|
assert.Equal(t, len(args), 1)
|
||||||
fmt.Println(queryStr)
|
fmt.Println(queryStr)
|
||||||
|
|
||||||
films := []thesameLengthFilms{}
|
films := []thesameLengthFilms{}
|
||||||
|
|
@ -497,7 +496,7 @@ func TestSelectGroupByHaving(t *testing.T) {
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
fmt.Println(queryStr)
|
fmt.Println(queryStr)
|
||||||
assert.Equal(t, len(args), 1)
|
assert.Equal(t, len(args), 1)
|
||||||
assert.Equal(t, queryStr, `SELECT payment.customer_id AS "customer_payment_sum.customer_id",SUM(payment.amount) AS "customer_payment_sum.amount_sum" FROM dvds.payment GROUP BY payment.customer_id HAVING SUM(payment.amount)>$1 ORDER BY SUM(payment.amount) ASC`)
|
assert.Equal(t, queryStr, `SELECT payment.customer_id AS "customer_payment_sum.customer_id", SUM(payment.amount) AS "customer_payment_sum.amount_sum" FROM dvds.payment GROUP BY payment.customer_id HAVING SUM(payment.amount)>$1 ORDER BY SUM(payment.amount) ASC`)
|
||||||
|
|
||||||
type CustomerPaymentSum struct {
|
type CustomerPaymentSum struct {
|
||||||
CustomerID int16
|
CustomerID int16
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue