count.go raw

   1  //go:build !(js && wasm)
   2  
   3  package database
   4  
   5  import (
   6  	"context"
   7  
   8  	"next.orly.dev/pkg/nostr/encoders/filter"
   9  )
  10  
  11  // CountEvents mirrors the initial selection logic of QueryEvents but stops
  12  // once we have identified candidate event serials (id/pk/ts). It returns the
  13  // count of those serials. The `approx` flag is always false as requested.
  14  func (d *D) CountEvents(c context.Context, f *filter.F) (
  15  	count int, approx bool, err error,
  16  ) {
  17  	approx = false
  18  	if f == nil {
  19  		return 0, false, nil
  20  	}
  21  
  22  	// If explicit Ids are provided, count how many of them resolve to serials.
  23  	if f.Ids != nil && f.Ids.Len() > 0 {
  24  		var serials map[string]interface{}
  25  		// Use type inference without importing extra packages by discarding the
  26  		// concrete value type via a two-step assignment.
  27  		if tmp, idErr := d.GetSerialsByIds(f.Ids); idErr != nil {
  28  			return 0, false, idErr
  29  		} else {
  30  			// Reassign to a map with empty interface values to avoid referencing
  31  			// the concrete Uint40 type here.
  32  			serials = make(map[string]interface{}, len(tmp))
  33  			for k := range tmp {
  34  				serials[k] = struct{}{}
  35  			}
  36  		}
  37  		return len(serials), false, nil
  38  	}
  39  
  40  	// Otherwise, query for candidate Id/Pubkey/Timestamp triplets and count them.
  41  	if idPkTs, qErr := d.QueryForIds(c, f); qErr != nil {
  42  		return 0, false, qErr
  43  	} else {
  44  		return len(idPkTs), false, nil
  45  	}
  46  }
  47