Add support for SELECT_JSON statements.
This commit is contained in:
parent
7047de44a9
commit
7b16e432ff
46 changed files with 2732 additions and 307 deletions
131
postgres/select_json.go
Normal file
131
postgres/select_json.go
Normal file
|
|
@ -0,0 +1,131 @@
|
|||
package postgres
|
||||
|
||||
import (
|
||||
"github.com/go-jet/jet/v2/internal/jet"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// SELECT_JSON_ARR creates a new SelectJsonStatement with a list of projections.
|
||||
func SELECT_JSON_ARR(projections ...Projection) SelectStatement {
|
||||
return newSelectStatementJson(projections, jet.SelectJsonArrStatementType)
|
||||
}
|
||||
|
||||
// SELECT_JSON_OBJ creates a new SelectJsonStatement with a list of projections.
|
||||
func SELECT_JSON_OBJ(projections ...Projection) SelectStatement {
|
||||
return newSelectStatementJson(projections, jet.SelectJsonObjStatementType)
|
||||
}
|
||||
|
||||
type selectJsonStatement struct {
|
||||
*selectStatementImpl
|
||||
|
||||
subQuery *selectStatementImpl
|
||||
statementType jet.StatementType
|
||||
}
|
||||
|
||||
func (s *selectJsonStatement) AS(alias string) Projection {
|
||||
s.setSubQueryAlias(strings.ToLower(alias) + "_")
|
||||
|
||||
return s.selectStatementImpl.AS(alias)
|
||||
}
|
||||
|
||||
func (s *selectJsonStatement) FROM(table ...ReadableTable) SelectStatement {
|
||||
s.subQuery.From.Tables = readableTablesToSerializerList(table)
|
||||
|
||||
return s
|
||||
}
|
||||
|
||||
func (s *selectJsonStatement) DISTINCT(on ...jet.ColumnExpression) SelectStatement {
|
||||
s.subQuery.Select.Distinct = true
|
||||
s.subQuery.Select.DistinctOnColumns = on
|
||||
return s
|
||||
}
|
||||
|
||||
func (s *selectJsonStatement) WHERE(condition BoolExpression) SelectStatement {
|
||||
s.subQuery.Where.Condition = condition
|
||||
return s
|
||||
}
|
||||
|
||||
func (s *selectJsonStatement) GROUP_BY(groupByClauses ...GroupByClause) SelectStatement {
|
||||
s.subQuery.GroupBy.List = groupByClauses
|
||||
return s
|
||||
}
|
||||
|
||||
func (s *selectJsonStatement) HAVING(boolExpression BoolExpression) SelectStatement {
|
||||
s.subQuery.Having.Condition = boolExpression
|
||||
return s
|
||||
}
|
||||
|
||||
func (s *selectJsonStatement) WINDOW(name string) windowExpand {
|
||||
s.subQuery.Window.Definitions = append(s.subQuery.Window.Definitions, jet.WindowDefinition{Name: name})
|
||||
return windowExpand{
|
||||
selectStatement: s.subQuery,
|
||||
rootStmt: s,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *selectJsonStatement) ORDER_BY(orderByClauses ...OrderByClause) SelectStatement {
|
||||
s.subQuery.OrderBy.List = orderByClauses
|
||||
return s
|
||||
}
|
||||
|
||||
func (s *selectJsonStatement) LIMIT(limit int64) SelectStatement {
|
||||
s.subQuery.Limit.Count = limit
|
||||
return s
|
||||
}
|
||||
|
||||
func (s *selectJsonStatement) OFFSET(offset int64) SelectStatement {
|
||||
s.subQuery.Offset.Count = Int(offset)
|
||||
return s
|
||||
}
|
||||
|
||||
func (s *selectJsonStatement) OFFSET_e(offset IntegerExpression) SelectStatement {
|
||||
s.subQuery.Offset.Count = offset
|
||||
return s
|
||||
}
|
||||
|
||||
func (s *selectJsonStatement) FETCH_FIRST(count IntegerExpression) fetchExpand {
|
||||
s.subQuery.Fetch.Count = count
|
||||
|
||||
return fetchExpand{
|
||||
selectStatement: s.subQuery,
|
||||
rootStmt: s,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *selectJsonStatement) FOR(lock RowLock) SelectStatement {
|
||||
s.subQuery.For.Lock = lock
|
||||
return s
|
||||
}
|
||||
|
||||
func newSelectStatementJson(projections []Projection, statementType jet.StatementType) SelectStatement {
|
||||
newSelectJson := &selectJsonStatement{
|
||||
selectStatementImpl: newSelectStatement(statementType, nil, nil),
|
||||
subQuery: newSelectStatement(statementType, nil, projections),
|
||||
statementType: statementType,
|
||||
}
|
||||
|
||||
newSelectJson.setOperatorsImpl.stmtRoot = newSelectJson
|
||||
|
||||
newSelectJson.setSubQueryAlias("")
|
||||
|
||||
return newSelectJson
|
||||
}
|
||||
|
||||
func (s *selectJsonStatement) setSubQueryAlias(alias string) {
|
||||
subQueryAlias := alias + "records"
|
||||
jsonAlias := alias + "json"
|
||||
|
||||
s.Select.ProjectionList = ProjectionList{constructJsonFunc(s.statementType, subQueryAlias).AS(jsonAlias)}
|
||||
|
||||
s.From.Tables = []jet.Serializer{newSelectTable(s.subQuery, subQueryAlias, nil)}
|
||||
}
|
||||
|
||||
func constructJsonFunc(statementType jet.StatementType, subQueryAlias string) Expression {
|
||||
rowToJson := Func("row_to_json", CustomExpression(Token(subQueryAlias)))
|
||||
|
||||
if statementType == jet.SelectJsonArrStatementType {
|
||||
return Func("json_agg", rowToJson)
|
||||
}
|
||||
|
||||
return rowToJson
|
||||
}
|
||||
|
|
@ -70,12 +70,12 @@ type SelectStatement interface {
|
|||
|
||||
// SELECT creates new SelectStatement with list of projections
|
||||
func SELECT(projection Projection, projections ...Projection) SelectStatement {
|
||||
return newSelectStatement(nil, append([]Projection{projection}, projections...))
|
||||
return newSelectStatement(jet.SelectStatementType, nil, append([]Projection{projection}, projections...))
|
||||
}
|
||||
|
||||
func newSelectStatement(table ReadableTable, projections []Projection) SelectStatement {
|
||||
func newSelectStatement(stmtType jet.StatementType, table ReadableTable, projections []Projection) *selectStatementImpl {
|
||||
newSelect := &selectStatementImpl{}
|
||||
newSelect.ExpressionStatement = jet.NewExpressionStatementImpl(Dialect, jet.SelectStatementType, newSelect,
|
||||
newSelect.ExpressionStatement = jet.NewExpressionStatementImpl(Dialect, stmtType, newSelect,
|
||||
&newSelect.Select,
|
||||
&newSelect.From,
|
||||
&newSelect.Where,
|
||||
|
|
@ -94,7 +94,7 @@ func newSelectStatement(table ReadableTable, projections []Projection) SelectSta
|
|||
}
|
||||
newSelect.Limit.Count = -1
|
||||
|
||||
newSelect.setOperatorsImpl.parent = newSelect
|
||||
newSelect.setOperatorsImpl.stmtRoot = newSelect
|
||||
|
||||
return newSelect
|
||||
}
|
||||
|
|
@ -144,7 +144,10 @@ func (s *selectStatementImpl) HAVING(boolExpression BoolExpression) SelectStatem
|
|||
|
||||
func (s *selectStatementImpl) WINDOW(name string) windowExpand {
|
||||
s.Window.Definitions = append(s.Window.Definitions, jet.WindowDefinition{Name: name})
|
||||
return windowExpand{selectStatement: s}
|
||||
return windowExpand{
|
||||
selectStatement: s,
|
||||
rootStmt: s,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *selectStatementImpl) ORDER_BY(orderByClauses ...OrderByClause) SelectStatement {
|
||||
|
|
@ -172,6 +175,7 @@ func (s *selectStatementImpl) FETCH_FIRST(count IntegerExpression) fetchExpand {
|
|||
|
||||
return fetchExpand{
|
||||
selectStatement: s,
|
||||
rootStmt: s,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -188,6 +192,7 @@ func (s *selectStatementImpl) AsTable(alias string) SelectTable {
|
|||
|
||||
type windowExpand struct {
|
||||
selectStatement *selectStatementImpl
|
||||
rootStmt SelectStatement
|
||||
}
|
||||
|
||||
func (w windowExpand) AS(window ...jet.Window) SelectStatement {
|
||||
|
|
@ -196,7 +201,7 @@ func (w windowExpand) AS(window ...jet.Window) SelectStatement {
|
|||
}
|
||||
windowsDefinition := w.selectStatement.Window.Definitions
|
||||
windowsDefinition[len(windowsDefinition)-1].Window = window[0]
|
||||
return w.selectStatement
|
||||
return w.rootStmt
|
||||
}
|
||||
|
||||
func toJetFrameOffset(offset int64) jet.Serializer {
|
||||
|
|
@ -216,16 +221,17 @@ func readableTablesToSerializerList(tables []ReadableTable) []jet.Serializer {
|
|||
|
||||
type fetchExpand struct {
|
||||
selectStatement *selectStatementImpl
|
||||
rootStmt SelectStatement
|
||||
}
|
||||
|
||||
func (f fetchExpand) ROWS_ONLY() SelectStatement {
|
||||
f.selectStatement.Fetch.WithTies = false
|
||||
|
||||
return f.selectStatement
|
||||
return f.rootStmt
|
||||
}
|
||||
|
||||
func (f fetchExpand) ROWS_WITH_TIES() SelectStatement {
|
||||
f.selectStatement.Fetch.WithTies = true
|
||||
|
||||
return f.selectStatement
|
||||
return f.rootStmt
|
||||
}
|
||||
|
|
|
|||
|
|
@ -65,31 +65,31 @@ type setOperators interface {
|
|||
}
|
||||
|
||||
type setOperatorsImpl struct {
|
||||
parent setOperators
|
||||
stmtRoot setOperators
|
||||
}
|
||||
|
||||
func (s *setOperatorsImpl) UNION(rhs SelectStatement) setStatement {
|
||||
return UNION(s.parent, rhs)
|
||||
return UNION(s.stmtRoot, rhs)
|
||||
}
|
||||
|
||||
func (s *setOperatorsImpl) UNION_ALL(rhs SelectStatement) setStatement {
|
||||
return UNION_ALL(s.parent, rhs)
|
||||
return UNION_ALL(s.stmtRoot, rhs)
|
||||
}
|
||||
|
||||
func (s *setOperatorsImpl) INTERSECT(rhs SelectStatement) setStatement {
|
||||
return INTERSECT(s.parent, rhs)
|
||||
return INTERSECT(s.stmtRoot, rhs)
|
||||
}
|
||||
|
||||
func (s *setOperatorsImpl) INTERSECT_ALL(rhs SelectStatement) setStatement {
|
||||
return INTERSECT_ALL(s.parent, rhs)
|
||||
return INTERSECT_ALL(s.stmtRoot, rhs)
|
||||
}
|
||||
|
||||
func (s *setOperatorsImpl) EXCEPT(rhs SelectStatement) setStatement {
|
||||
return EXCEPT(s.parent, rhs)
|
||||
return EXCEPT(s.stmtRoot, rhs)
|
||||
}
|
||||
|
||||
func (s *setOperatorsImpl) EXCEPT_ALL(rhs SelectStatement) setStatement {
|
||||
return EXCEPT_ALL(s.parent, rhs)
|
||||
return EXCEPT_ALL(s.stmtRoot, rhs)
|
||||
}
|
||||
|
||||
type setStatementImpl struct {
|
||||
|
|
@ -110,7 +110,7 @@ func newSetStatementImpl(operator string, all bool, selects []jet.SerializerStat
|
|||
newSetStatement.setOperator.Selects = selects
|
||||
newSetStatement.setOperator.Limit.Count = -1
|
||||
|
||||
newSetStatement.setOperatorsImpl.parent = newSetStatement
|
||||
newSetStatement.setOperatorsImpl.stmtRoot = newSetStatement
|
||||
|
||||
return newSetStatement
|
||||
}
|
||||
|
|
|
|||
|
|
@ -55,7 +55,7 @@ type readableTableInterfaceImpl struct {
|
|||
|
||||
// Generates a select query on the current tableName.
|
||||
func (r readableTableInterfaceImpl) SELECT(projection1 Projection, projections ...Projection) SelectStatement {
|
||||
return newSelectStatement(r.parent, append([]Projection{projection1}, projections...))
|
||||
return newSelectStatement(jet.SelectStatementType, r.parent, append([]Projection{projection1}, projections...))
|
||||
}
|
||||
|
||||
// Creates a inner join tableName Expression using onCondition.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue