From d9bbec3795764469b7de5a35cec53125e83e7dcb Mon Sep 17 00:00:00 2001 From: zer0sub Date: Wed, 8 May 2019 12:49:36 +0200 Subject: [PATCH] Order by sql serialization simplified. --- sqlbuilder/alias.go | 2 +- sqlbuilder/clause.go | 15 --------------- sqlbuilder/column.go | 29 +++++++++++++++++++---------- sqlbuilder/expression.go | 5 +++++ sqlbuilder/order_by_clause.go | 14 +++----------- sqlbuilder/utils.go | 2 +- tests/select_test.go | 4 +++- 7 files changed, 32 insertions(+), 39 deletions(-) diff --git a/sqlbuilder/alias.go b/sqlbuilder/alias.go index e7b7c34..13a75ed 100644 --- a/sqlbuilder/alias.go +++ b/sqlbuilder/alias.go @@ -14,7 +14,7 @@ func NewAlias(expression expression, alias string) *Alias { func (a *Alias) serializeForProjection(out *queryData) error { - err := a.expression.serialize(out) + err := a.expression.serializeForProjection(out) if err != nil { return err diff --git a/sqlbuilder/clause.go b/sqlbuilder/clause.go index e2eb61b..c8e1094 100644 --- a/sqlbuilder/clause.go +++ b/sqlbuilder/clause.go @@ -15,7 +15,6 @@ type queryData struct { args []interface{} statementType int - clauseType int } const ( @@ -26,43 +25,29 @@ const ( 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 []groupByClause) error { - q.clauseType = group_by_clause q.WriteString(" GROUP BY ") return serializeGroupByClauseList(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) { diff --git a/sqlbuilder/column.go b/sqlbuilder/column.go index 7aedcf5..c655b6f 100644 --- a/sqlbuilder/column.go +++ b/sqlbuilder/column.go @@ -77,20 +77,33 @@ func (c *baseColumn) DefaultAlias() projection { return c.AS(c.tableName + "." + c.name) } -func (c baseColumn) serialize(out *queryData) error { - - setOrderBy := out.statementType == set_statement && out.clauseType == order_by_clause - - if setOrderBy { +func (c *baseColumn) serializeAsOrderBy(out *queryData) error { + if out.statementType == set_statement { + // set statement (UNION, EXCEPT ...) can reference only select projections in order by clause out.WriteString(`"`) + + if c.tableName != "" { + out.WriteString(c.tableName) + out.WriteString(".") + } + + out.WriteString(c.name) + + out.WriteString(`"`) + + return nil } + return c.serialize(out) +} + +func (c baseColumn) serialize(out *queryData) error { if c.tableName != "" { out.WriteString(c.tableName) out.WriteString(".") } - wrapColumnName := strings.Contains(c.name, ".") && !setOrderBy + wrapColumnName := strings.Contains(c.name, ".") if wrapColumnName { out.WriteString(`"`) @@ -102,9 +115,5 @@ func (c baseColumn) serialize(out *queryData) error { out.WriteString(`"`) } - if setOrderBy { - out.WriteString(`"`) - } - return nil } diff --git a/sqlbuilder/expression.go b/sqlbuilder/expression.go index 5c6db80..f34c4ce 100644 --- a/sqlbuilder/expression.go +++ b/sqlbuilder/expression.go @@ -9,6 +9,7 @@ type expression interface { clause projection groupByClause + orderByClause IN(subQuery selectStatement) boolExpression NOT_IN(subQuery selectStatement) boolExpression @@ -60,6 +61,10 @@ func (e *expressionInterfaceImpl) serializeForProjection(out *queryData) error { return e.parent.serialize(out) } +func (e *expressionInterfaceImpl) serializeAsOrderBy(out *queryData) error { + return e.parent.serialize(out) +} + // Representation of binary operations (e.g. comparisons, arithmetic) type binaryExpression struct { lhs, rhs expression diff --git a/sqlbuilder/order_by_clause.go b/sqlbuilder/order_by_clause.go index fdcfdc5..7e82645 100644 --- a/sqlbuilder/order_by_clause.go +++ b/sqlbuilder/order_by_clause.go @@ -3,28 +3,20 @@ package sqlbuilder import "github.com/dropbox/godropbox/errors" type orderByClause interface { - clause - isOrderByClauseType() -} - -type isOrderByClause struct { -} - -func (o *isOrderByClause) isOrderByClauseType() { + serializeAsOrderBy(out *queryData) error } type orderByClauseImpl struct { - isOrderByClause expression expression ascent bool } -func (o *orderByClauseImpl) serialize(out *queryData) error { +func (o *orderByClauseImpl) serializeAsOrderBy(out *queryData) error { if o.expression == nil { return errors.Newf("nil orderBy by clause.") } - if err := o.expression.serialize(out); err != nil { + if err := o.expression.serializeAsOrderBy(out); err != nil { return err } diff --git a/sqlbuilder/utils.go b/sqlbuilder/utils.go index a68c980..c05a929 100644 --- a/sqlbuilder/utils.go +++ b/sqlbuilder/utils.go @@ -14,7 +14,7 @@ func serializeOrderByClauseList(orderByClauses []orderByClause, out *queryData) out.WriteString(", ") } - err := value.serialize(out) + err := value.serializeAsOrderBy(out) if err != nil { return err diff --git a/tests/select_test.go b/tests/select_test.go index 5dc6b70..81c4c37 100644 --- a/tests/select_test.go +++ b/tests/select_test.go @@ -13,7 +13,9 @@ import ( func TestSelect_ScanToStruct(t *testing.T) { actor := model.Actor{} - query := Actor.SELECT(Actor.AllColumns).ORDER_BY(Actor.ActorID.ASC()) + query := Actor. + SELECT(Actor.AllColumns). + ORDER_BY(Actor.ActorID.ASC()) queryStr, args, err := query.Sql()