package simql import ( "fmt" "strings" ) // https://www.sqlite.org/lang_select.html type SelectQuery struct { distinct bool columns []Column tables []SelectTable where []Where args []any // group // TODO // having // TODO orderBy []OrderBy limit int offset int } func (s *SelectQuery) Args() []any { return s.args } func (s *SelectQuery) Columns(defs ...string) *SelectQuery { for _, def := range defs { s.columns = append(s.columns, Column(def)) } return s } func (s *SelectQuery) Distinct(distinct bool) *SelectQuery { s.distinct = distinct return s } func (s *SelectQuery) IsValid() bool { for _, c := range s.columns { if !c.IsValid() { return false } } for _, t := range s.tables { if !t.IsValid() { return false } } for _, w := range s.where { if !w.IsValid() { return false } } return false } func (s *SelectQuery) LeftJoin(def string) *SelectQuery { s.tables = append(s.tables, LeftJoin(def)) return s } func (s *SelectQuery) Limit(limit int) *SelectQuery { s.limit = limit return s } func (s *SelectQuery) InnerJoin(def string) *SelectQuery { s.tables = append(s.tables, InnerJoin(def)) return s } func (s *SelectQuery) RightJoin(def string) *SelectQuery { s.tables = append(s.tables, RightJoin(def)) return s } func (s *SelectQuery) Offset(limit int) *SelectQuery { s.limit = limit return s } func (s *SelectQuery) OrderBy(defs ...string) *SelectQuery { if s.orderBy == nil { s.orderBy = []OrderBy{} } for _, def := range defs { s.orderBy = append(s.orderBy, OrderBy(def)) } return s } func (s *SelectQuery) String() string { strs := []string{"select"} if s.distinct { strs = append(strs, "distinct") } if len(s.columns) > 0 { for i, column := range s.columns { if i < len(s.columns)-1 { strs = append(strs, fmt.Sprintf("%s,", column)) } else { strs = append(strs, column.String()) } } } else { strs = append(strs, "*") } for _, table := range s.tables { strs = append(strs, table.String()) } if len(s.where) > 0 { strs = append(strs, "where") for _, w := range s.where { strs = append(strs, w.String()) } } if len(s.orderBy) > 0 { strs = append(strs, "order by") for i, o := range s.orderBy { if i < len(s.orderBy)-1 { strs = append(strs, fmt.Sprintf("%s,", o)) } else { strs = append(strs, o.String()) } } } if s.limit > 0 { if s.offset > 0 { strs = append(strs, fmt.Sprintf("limit %d offset %d", s.offset, s.limit)) } else { strs = append(strs, fmt.Sprintf("limit %d", s.limit)) } } return strings.Join(strs, " ") } func (s *SelectQuery) Where(def string, args ...any) *SelectQuery { s.where = append(s.where, Where(def)) if len(args) > 0 { if s.args == nil { s.args = []any{} } s.args = append(s.args, args...) } return s } func Select(from string) *SelectQuery { s := &SelectQuery{ columns: []Column{}, tables: []SelectTable{From(from)}, where: []Where{}, } return s }