Move RETURNING clause to internal/jet so it can be reused for sqlite implementation.

This commit is contained in:
go-jet 2021-10-21 13:31:54 +02:00
parent 6080ae134f
commit 22b2901336
7 changed files with 56 additions and 43 deletions

View file

@ -217,12 +217,13 @@ func (f *ClauseFor) Serialize(statementType StatementType, out *SQLBuilder, opti
// ClauseSetStmtOperator struct // ClauseSetStmtOperator struct
type ClauseSetStmtOperator struct { type ClauseSetStmtOperator struct {
Operator string Operator string
All bool All bool
Selects []SerializerStatement Selects []SerializerStatement
OrderBy ClauseOrderBy OrderBy ClauseOrderBy
Limit ClauseLimit Limit ClauseLimit
Offset ClauseOffset Offset ClauseOffset
SkipSelectWrap bool
} }
// Projections returns set of projections for ClauseSetStmtOperator // Projections returns set of projections for ClauseSetStmtOperator
@ -242,6 +243,10 @@ func (s *ClauseSetStmtOperator) Serialize(statementType StatementType, out *SQLB
for i, selectStmt := range s.Selects { for i, selectStmt := range s.Selects {
out.NewLine() out.NewLine()
if i > 0 { if i > 0 {
if s.SkipSelectWrap {
out.NewLine()
}
out.WriteString(s.Operator) out.WriteString(s.Operator)
if s.All { if s.All {
@ -254,7 +259,11 @@ func (s *ClauseSetStmtOperator) Serialize(statementType StatementType, out *SQLB
panic("jet: select statement of '" + s.Operator + "' is nil") panic("jet: select statement of '" + s.Operator + "' is nil")
} }
selectStmt.serialize(statementType, out, FallTrough(options)...) if s.SkipSelectWrap {
options = append(FallTrough(options), NoWrap)
}
selectStmt.serialize(statementType, out, options...)
} }
s.OrderBy.Serialize(statementType, out) s.OrderBy.Serialize(statementType, out)
@ -360,10 +369,6 @@ type ClauseValuesQuery struct {
// Serialize serializes clause into SQLBuilder // Serialize serializes clause into SQLBuilder
func (v *ClauseValuesQuery) Serialize(statementType StatementType, out *SQLBuilder, options ...SerializeOption) { func (v *ClauseValuesQuery) Serialize(statementType StatementType, out *SQLBuilder, options ...SerializeOption) {
if len(v.Rows) == 0 && v.Query == nil {
panic("jet: VALUES or QUERY has to be specified for INSERT statement")
}
if len(v.Rows) > 0 && v.Query != nil { if len(v.Rows) > 0 && v.Query != nil {
panic("jet: VALUES or QUERY has to be specified for INSERT statement") panic("jet: VALUES or QUERY has to be specified for INSERT statement")
} }
@ -405,7 +410,8 @@ func (v *ClauseValues) Serialize(statementType StatementType, out *SQLBuilder, o
// ClauseQuery struct // ClauseQuery struct
type ClauseQuery struct { type ClauseQuery struct {
Query SerializerStatement Query SerializerStatement
SkipSelectWrap bool
} }
// Serialize serializes clause into SQLBuilder // Serialize serializes clause into SQLBuilder
@ -414,7 +420,11 @@ func (v *ClauseQuery) Serialize(statementType StatementType, out *SQLBuilder, op
return return
} }
v.Query.serialize(statementType, out, FallTrough(options)...) if v.SkipSelectWrap {
options = append(FallTrough(options), NoWrap)
}
v.Query.serialize(statementType, out, options...)
} }
// ClauseDelete struct // ClauseDelete struct
@ -561,3 +571,26 @@ type KeywordClause struct {
func (k KeywordClause) Serialize(statementType StatementType, out *SQLBuilder, options ...SerializeOption) { func (k KeywordClause) Serialize(statementType StatementType, out *SQLBuilder, options ...SerializeOption) {
k.serialize(statementType, out, FallTrough(options)...) k.serialize(statementType, out, FallTrough(options)...)
} }
// ClauseReturning type
type ClauseReturning struct {
ProjectionList []Projection
}
// Serialize for ClauseReturning
func (r *ClauseReturning) Serialize(statementType StatementType, out *SQLBuilder, options ...SerializeOption) {
if len(r.ProjectionList) == 0 {
return
}
out.NewLine()
out.WriteString("RETURNING")
out.IncreaseIdent()
out.WriteProjections(statementType, r.ProjectionList)
out.DecreaseIdent()
}
// Projections for ClauseReturning
func (r ClauseReturning) Projections() ProjectionList {
return r.ProjectionList
}

View file

@ -4,33 +4,10 @@ import (
"github.com/go-jet/jet/v2/internal/jet" "github.com/go-jet/jet/v2/internal/jet"
) )
type clauseReturning struct {
ProjectionList []jet.Projection
}
func (r *clauseReturning) Serialize(statementType jet.StatementType, out *jet.SQLBuilder, options ...jet.SerializeOption) {
if len(r.ProjectionList) == 0 {
return
}
out.NewLine()
out.WriteString("RETURNING")
out.IncreaseIdent()
out.WriteProjections(statementType, r.ProjectionList)
out.DecreaseIdent()
}
func (r clauseReturning) Projections() ProjectionList {
return r.ProjectionList
}
// ========================================== //
type onConflict interface { type onConflict interface {
ON_CONSTRAINT(name string) conflictTarget ON_CONSTRAINT(name string) conflictTarget
WHERE(indexPredicate BoolExpression) conflictTarget WHERE(indexPredicate BoolExpression) conflictTarget
DO_NOTHING() InsertStatement conflictTarget
DO_UPDATE(action conflictAction) InsertStatement
} }
type conflictTarget interface { type conflictTarget interface {

View file

@ -16,7 +16,7 @@ type deleteStatementImpl struct {
Delete jet.ClauseStatementBegin Delete jet.ClauseStatementBegin
Where jet.ClauseWhere Where jet.ClauseWhere
Returning clauseReturning Returning jet.ClauseReturning
} }
func newDeleteStatement(table WritableTable) DeleteStatement { func newDeleteStatement(table WritableTable) DeleteStatement {

View file

@ -22,7 +22,11 @@ type InsertStatement interface {
func newInsertStatement(table WritableTable, columns []jet.Column) InsertStatement { func newInsertStatement(table WritableTable, columns []jet.Column) InsertStatement {
newInsert := &insertStatementImpl{} newInsert := &insertStatementImpl{}
newInsert.SerializerStatement = jet.NewStatementImpl(Dialect, jet.InsertStatementType, newInsert, newInsert.SerializerStatement = jet.NewStatementImpl(Dialect, jet.InsertStatementType, newInsert,
&newInsert.Insert, &newInsert.ValuesQuery, &newInsert.OnConflict, &newInsert.Returning) &newInsert.Insert,
&newInsert.ValuesQuery,
&newInsert.OnConflict,
&newInsert.Returning,
)
newInsert.Insert.Table = table newInsert.Insert.Table = table
newInsert.Insert.Columns = columns newInsert.Insert.Columns = columns
@ -35,7 +39,7 @@ type insertStatementImpl struct {
Insert jet.ClauseInsert Insert jet.ClauseInsert
ValuesQuery jet.ClauseValuesQuery ValuesQuery jet.ClauseValuesQuery
Returning clauseReturning Returning jet.ClauseReturning
OnConflict onConflictClause OnConflict onConflictClause
} }

View file

@ -8,7 +8,6 @@ import (
) )
func TestInvalidInsert(t *testing.T) { func TestInvalidInsert(t *testing.T) {
assertStatementSqlErr(t, table1.INSERT(table1Col1), "jet: VALUES or QUERY has to be specified for INSERT statement")
assertStatementSqlErr(t, table1.INSERT(nil).VALUES(1), "jet: nil column in columns list") assertStatementSqlErr(t, table1.INSERT(nil).VALUES(1), "jet: nil column in columns list")
} }

View file

@ -116,7 +116,7 @@ func INTERVAL(quantityAndUnit ...quantityAndUnit) IntervalExpression {
panic("jet: invalid number of quantity and unit fields") panic("jet: invalid number of quantity and unit fields")
} }
fields := []string{} var fields []string
for i := 0; i < len(quantityAndUnit); i += 2 { for i := 0; i < len(quantityAndUnit); i += 2 {
quantity := strconv.FormatFloat(quantityAndUnit[i], 'f', -1, 64) quantity := strconv.FormatFloat(quantityAndUnit[i], 'f', -1, 64)

View file

@ -22,7 +22,7 @@ type updateStatementImpl struct {
Set clauseSet Set clauseSet
SetNew jet.SetClauseNew SetNew jet.SetClauseNew
Where jet.ClauseWhere Where jet.ClauseWhere
Returning clauseReturning Returning jet.ClauseReturning
} }
func newUpdateStatement(table WritableTable, columns []jet.Column) UpdateStatement { func newUpdateStatement(table WritableTable, columns []jet.Column) UpdateStatement {