func (s *Store) runQuerySort(source BucketSource, dataType interface{}, query *Query, action func(r *record) error) error {
	// Validate sort fields
	for _, field := range query.sort {
		fields := strings.Split(field, ".")

		current := query.dataType
		for i := range fields {
			var structField reflect.StructField
			found := false
			if current.Kind() == reflect.Ptr {
				structField, found = current.Elem().FieldByName(fields[i])
			} else {
				structField, found = current.FieldByName(fields[i])
			}

			if !found {
				return fmt.Errorf("The field %s does not exist in the type %s", field, query.dataType)
			}
			current = structField.Type
		}
	}

	// Run query without sort, skip or limit
	// apply sort, skip and limit to entire dataset
	qCopy := *query
	qCopy.sort = nil
	qCopy.limit = 0
	qCopy.skip = 0

	var records []*record
	err := s.runQuery(source, dataType, &qCopy, nil, 0,
		func(r *record) error {
			records = append(records, r)

			return nil
		})

	if err != nil {
		return err
	}

	sort.Slice(records, func(i, j int) bool {
		for _, field := range query.sort {
			value, err := fieldValue(records[i].value.Elem(), field)
			if err != nil {
				panic(err.Error()) // shouldn't happen due to field check above
			}

			other, err := fieldValue(records[j].value.Elem(), field)
			if err != nil {
				panic(err.Error()) // shouldn't happen due to field check above
			}

			if query.reverse {
				value, other = other, value
			}

			cmp, cerr := compare(value, other)
			if cerr != nil {
				// if for some reason there is an error on compare, fallback to a lexicographic compare
				valS := fmt.Sprintf("%s", value)
				otherS := fmt.Sprintf("%s", other)
				if valS < otherS {
					return true
				} else if valS == otherS {
					continue
				}
				return false
			}

			if cmp == -1 {
				return true
			} else if cmp == 0 {
				continue
			}
			return false
		}
		return false
	})

	// apply skip and limit
	limit := query.limit
	skip := query.skip

	if skip > len(records) {
		records = records[0:0]
	} else {
		records = records[skip:]
	}

	if limit > 0 && limit <= len(records) {
		records = records[:limit]
	}

	for i := range records {
		err = action(records[i])
		if err != nil {
			return err
		}
	}

	return nil

}
// runQuerySort runs the query without sort, skip, or limit, then applies them to the entire result set
runQuerySort runs the query without sort, skip, or limit, then applies them to the entire result set
// runQuerySort runs the query without sort skip or limit then applies them to the entire result set
func (s *Store) runQuerySort(source BucketSource, dataType interface{}, query *Query, action func(r *record) error) error {
	for _, field := range query.sort {
		fields := strings.Split(field, ".")
		current := query.dataType
		for i := range fields {
			var structField reflect.StructField
			found := false
			if current.Kind() == reflect.Ptr {
				structField, found = current.Elem().FieldByName(fields[i])
			} else {
				structField, found = current.FieldByName(fields[i])
			}
			if !found {
				return fmt.Errorf("The field %s does not exist in the type %s", field, query.dataType)
			}
			current = structField.Type
		}
	}
	qCopy := *query
	qCopy.sort = nil
	qCopy.limit = 0
	qCopy.skip = 0
	var records []*record
	err := s.runQuery(source, dataType, &qCopy, nil, 0,
		func(r *record) error {
			records = append(records, r)
			return nil
		})
	if err != nil {
		return err
	}
	sort.Slice(records, func(i, j int) bool {
		for _, field := range query.sort {
			value, err := fieldValue(records[i].value.Elem(), field)
			if err != nil {
				panic(err.Error()) 
			}
			other, err := fieldValue(records[j].value.Elem(), field)
			if err != nil {
				panic(err.Error()) 
			}
			if query.reverse {
				value, other = other, value
			}
			cmp, cerr := compare(value, other)
			if cerr != nil {
				valS := fmt.Sprintf("%s", value)
				otherS := fmt.Sprintf("%s", other)
				if valS < otherS {
					return true
				} else if valS == otherS {
					continue
				}
				return false
			}
			if cmp == -1 {
				return true
			} else if cmp == 0 {
				continue
			}
			return false
		}
		return false
	})
	limit := query.limit
	skip := query.skip
	if skip > len(records) {
		records = records[0:0]
	} else {
		records = records[skip:]
	}
	if limit > 0 && limit <= len(records) {
		records = records[:limit]
	}
	for i := range records {
		err = action(records[i])
		if err != nil {
			return err
		}
	}
	return nil
}
func ( s * Store ) runQuerySort ( source BucketSource , dataType interface { } , query * Query , action func ( r * record ) error ) error { for _ , field := range query . sort { fields := strings . Split ( field , " " ) current := query . dataType for i := range fields { var structField reflect . StructField found := false if current . Kind ( ) == reflect . Ptr { structField , found = current . Elem ( ) . FieldByName ( fields [ i ] ) } else { structField , found = current . FieldByName ( fields [ i ] ) } if ! found { return fmt . Errorf ( " " , field , query . dataType ) } current = structField . Type } } qCopy := * query qCopy . sort = nil qCopy . limit = 0 qCopy . skip = 0 var records [ ] * record err := s . runQuery ( source , dataType , & qCopy , nil , 0 , func ( r * record ) error { records = append ( records , r ) return nil } ) if err != nil { return err } sort . Slice ( records , func ( i , j int ) bool { for _ , field := range query . sort { value , err := fieldValue ( records [ i ] . value . Elem ( ) , field ) if err != nil { panic ( err . Error ( ) ) } other , err := fieldValue ( records [ j ] . value . Elem ( ) , field ) if err != nil { panic ( err . Error ( ) ) } if query . reverse { value , other = other , value } cmp , cerr := compare ( value , other ) if cerr != nil { valS := fmt . Sprintf ( " " , value ) otherS := fmt . Sprintf ( " " , other ) if valS < otherS { return true } else if valS == otherS { continue } return false } if cmp == - 1 { return true } else if cmp == 0 { continue } return false } return false } ) limit := query . limit skip := query . skip if skip > len ( records ) { records = records [ 0 : 0 ] } else { records = records [ skip : ] } if limit > 0 && limit <= len ( records ) { records = records [ : limit ] } for i := range records { err = action ( records [ i ] ) if err != nil { return err } } return nil }
runQuerySort runs the query without sort, skip, or limit, then applies them to the entire result set
runQuerySort runs the query without sort skip or limit then applies them to the entire result set
// Validate sort fields // Run query without sort, skip or limit // apply sort, skip and limit to entire dataset // shouldn't happen due to field check above // shouldn't happen due to field check above // if for some reason there is an error on compare, fallback to a lexicographic compare // apply skip and limit