// Copyright (c) 2012-2015 The upper.io/db authors. All rights reserved. // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. package result import ( builder "upper.io/builder/meta" "upper.io/db" ) type Result struct { b builder.QueryBuilder table string iter builder.Iterator limit int offset int fields []interface{} columns []interface{} orderBy []interface{} groupBy []interface{} conds []interface{} } // NewResult creates and results a new result set on the given table, this set // is limited by the given sqlgen.Where conditions. func NewResult(b builder.QueryBuilder, table string, conds []interface{}) *Result { return &Result{ b: b, table: table, conds: conds, } } // Sets conditions for reducing the working set. func (r *Result) Where(conds ...interface{}) db.Result { r.conds = conds return r } // Determines the maximum limit of results to be returned. func (r *Result) Limit(n uint) db.Result { r.limit = int(n) return r } // Determines how many documents will be skipped before starting to grab // results. func (r *Result) Skip(n uint) db.Result { r.offset = int(n) return r } // Used to group results that have the same value in the same column or // columns. func (r *Result) Group(fields ...interface{}) db.Result { r.groupBy = fields return r } // Determines sorting of results according to the provided names. Fields may be // prefixed by - (minus) which means descending order, ascending order would be // used otherwise. func (r *Result) Sort(fields ...interface{}) db.Result { r.orderBy = fields return r } // Retrieves only the given fields. func (r *Result) Select(fields ...interface{}) db.Result { r.fields = fields return r } // Dumps all results into a pointer to an slice of structs or maps. func (r *Result) All(dst interface{}) error { return r.buildSelect().Iterator().All(dst) } // Fetches only one result from the resultset. func (r *Result) One(dst interface{}) error { return r.buildSelect().Iterator().One(dst) } // Fetches the next result from the resultset. func (r *Result) Next(dst interface{}) (err error) { if r.iter == nil { r.iter = r.buildSelect().Iterator() } if !r.iter.Next(dst) { return r.iter.Err() } return nil } // Removes the matching items from the collection. func (r *Result) Remove() error { q := r.b.DeleteFrom(r.table). Where(r.conds...). Limit(r.limit) _, err := q.Exec() return err } // Closes the result set. func (r *Result) Close() error { if r.iter != nil { return r.iter.Close() } return nil } // Updates matching items from the collection with values of the given map or // struct. func (r *Result) Update(values interface{}) error { q := r.b.Update(r.table). Set(values). Where(r.conds...). Limit(r.limit) _, err := q.Exec() return err } // Counts the elements within the main conditions of the set. func (r *Result) Count() (uint64, error) { counter := struct { Count uint64 `db:"_t"` }{} q := r.buildSelect() q.Columns(db.Raw{"count(1) AS _t"}).Limit(1) if err := q.Iterator().One(&counter); err != nil { return 0, err } return counter.Count, nil } func (r *Result) buildSelect() builder.Selector { q := r.b.Select(r.fields...) q.From(r.table) q.Where(r.conds...) q.Limit(r.limit) q.Offset(r.offset) q.GroupBy(r.groupBy...) q.OrderBy(r.orderBy...) return q }