176 lines
3.6 KiB
Go
176 lines
3.6 KiB
Go
|
package exql
|
||
|
|
||
|
import (
|
||
|
"strings"
|
||
|
|
||
|
"git.hexq.cn/tiglog/mydb/internal/cache"
|
||
|
)
|
||
|
|
||
|
// Order represents the order in which SQL results are sorted.
|
||
|
type Order uint8
|
||
|
|
||
|
// Possible values for Order
|
||
|
const (
|
||
|
Order_Default Order = iota
|
||
|
|
||
|
Order_Ascendent
|
||
|
Order_Descendent
|
||
|
)
|
||
|
|
||
|
func (o Order) Hash() uint64 {
|
||
|
return cache.NewHash(FragmentType_Order, uint8(o))
|
||
|
}
|
||
|
|
||
|
// SortColumn represents the column-order relation in an ORDER BY clause.
|
||
|
type SortColumn struct {
|
||
|
Column Fragment
|
||
|
Order
|
||
|
}
|
||
|
|
||
|
var _ = Fragment(&SortColumn{})
|
||
|
|
||
|
type sortColumnT struct {
|
||
|
Column string
|
||
|
Order string
|
||
|
}
|
||
|
|
||
|
var _ = Fragment(&SortColumn{})
|
||
|
|
||
|
// SortColumns represents the columns in an ORDER BY clause.
|
||
|
type SortColumns struct {
|
||
|
Columns []Fragment
|
||
|
}
|
||
|
|
||
|
var _ = Fragment(&SortColumns{})
|
||
|
|
||
|
// OrderBy represents an ORDER BY clause.
|
||
|
type OrderBy struct {
|
||
|
SortColumns Fragment
|
||
|
}
|
||
|
|
||
|
var _ = Fragment(&OrderBy{})
|
||
|
|
||
|
type orderByT struct {
|
||
|
SortColumns string
|
||
|
}
|
||
|
|
||
|
// JoinSortColumns creates and returns an array of column-order relations.
|
||
|
func JoinSortColumns(values ...Fragment) *SortColumns {
|
||
|
return &SortColumns{Columns: values}
|
||
|
}
|
||
|
|
||
|
// JoinWithOrderBy creates an returns an OrderBy using the given SortColumns.
|
||
|
func JoinWithOrderBy(sc *SortColumns) *OrderBy {
|
||
|
return &OrderBy{SortColumns: sc}
|
||
|
}
|
||
|
|
||
|
// Hash returns a unique identifier for the struct.
|
||
|
func (s *SortColumn) Hash() uint64 {
|
||
|
if s == nil {
|
||
|
return cache.NewHash(FragmentType_SortColumn, nil)
|
||
|
}
|
||
|
return cache.NewHash(FragmentType_SortColumn, s.Column, s.Order)
|
||
|
}
|
||
|
|
||
|
// Compile transforms the SortColumn into an equivalent SQL representation.
|
||
|
func (s *SortColumn) Compile(layout *Template) (compiled string, err error) {
|
||
|
|
||
|
if c, ok := layout.Read(s); ok {
|
||
|
return c, nil
|
||
|
}
|
||
|
|
||
|
column, err := s.Column.Compile(layout)
|
||
|
if err != nil {
|
||
|
return "", err
|
||
|
}
|
||
|
|
||
|
orderBy, err := s.Order.Compile(layout)
|
||
|
if err != nil {
|
||
|
return "", err
|
||
|
}
|
||
|
|
||
|
data := sortColumnT{Column: column, Order: orderBy}
|
||
|
|
||
|
compiled = layout.MustCompile(layout.SortByColumnLayout, data)
|
||
|
|
||
|
layout.Write(s, compiled)
|
||
|
|
||
|
return
|
||
|
}
|
||
|
|
||
|
// Hash returns a unique identifier for the struct.
|
||
|
func (s *SortColumns) Hash() uint64 {
|
||
|
if s == nil {
|
||
|
return cache.NewHash(FragmentType_SortColumns, nil)
|
||
|
}
|
||
|
h := cache.InitHash(FragmentType_SortColumns)
|
||
|
for i := range s.Columns {
|
||
|
h = cache.AddToHash(h, s.Columns[i])
|
||
|
}
|
||
|
return h
|
||
|
}
|
||
|
|
||
|
// Compile transforms the SortColumns into an equivalent SQL representation.
|
||
|
func (s *SortColumns) Compile(layout *Template) (compiled string, err error) {
|
||
|
if z, ok := layout.Read(s); ok {
|
||
|
return z, nil
|
||
|
}
|
||
|
|
||
|
z := make([]string, len(s.Columns))
|
||
|
|
||
|
for i := range s.Columns {
|
||
|
z[i], err = s.Columns[i].Compile(layout)
|
||
|
if err != nil {
|
||
|
return "", err
|
||
|
}
|
||
|
}
|
||
|
|
||
|
compiled = strings.Join(z, layout.IdentifierSeparator)
|
||
|
|
||
|
layout.Write(s, compiled)
|
||
|
|
||
|
return
|
||
|
}
|
||
|
|
||
|
// Hash returns a unique identifier for the struct.
|
||
|
func (s *OrderBy) Hash() uint64 {
|
||
|
if s == nil {
|
||
|
return cache.NewHash(FragmentType_OrderBy, nil)
|
||
|
}
|
||
|
return cache.NewHash(FragmentType_OrderBy, s.SortColumns)
|
||
|
}
|
||
|
|
||
|
// Compile transforms the SortColumn into an equivalent SQL representation.
|
||
|
func (s *OrderBy) Compile(layout *Template) (compiled string, err error) {
|
||
|
if z, ok := layout.Read(s); ok {
|
||
|
return z, nil
|
||
|
}
|
||
|
|
||
|
if s.SortColumns != nil {
|
||
|
sortColumns, err := s.SortColumns.Compile(layout)
|
||
|
if err != nil {
|
||
|
return "", err
|
||
|
}
|
||
|
|
||
|
data := orderByT{
|
||
|
SortColumns: sortColumns,
|
||
|
}
|
||
|
compiled = layout.MustCompile(layout.OrderByLayout, data)
|
||
|
}
|
||
|
|
||
|
layout.Write(s, compiled)
|
||
|
|
||
|
return
|
||
|
}
|
||
|
|
||
|
// Compile transforms the SortColumn into an equivalent SQL representation.
|
||
|
func (s Order) Compile(layout *Template) (string, error) {
|
||
|
switch s {
|
||
|
case Order_Ascendent:
|
||
|
return layout.AscKeyword, nil
|
||
|
case Order_Descendent:
|
||
|
return layout.DescKeyword, nil
|
||
|
}
|
||
|
return "", nil
|
||
|
}
|