package exec import ( "database/sql" "errors" "reflect" "git.gdulai.com/gdulai/simpleorm" "git.gdulai.com/gdulai/simpleorm/schema" log "gitlab.com/gdulai/simpleloglvl" ) // Count represents a count query. type Count[T any] struct { target schema.Table whereStmt string args []any result int64 } // CreateCount returns a new instance of Count. // // orm is the simpleorm.ORM instance which connects, caches and manages the relations. func CreateCount[T any](orm *simpleorm.ORM, whereStmt string, args ...any) (Count[T], error) { table, ok := orm.Cache().Get(reflect.TypeFor[T]().Name()) if !ok { return Count[T]{}, errors.New("Failed to get table from schema cache") } return Count[T]{target: *table, whereStmt: whereStmt, args: args}, nil } // Result returns the result of the count query. func (c *Count[T]) Result() int64 { return c.result } // Execute executes the parsed count query against a connection and returns an error if there was any during the execution. // // conn is the simpleorm.DBConnection which handles the database connection. func (c *Count[T]) Execute(conn *simpleorm.DBConnection) error { return c.execute(conn, nil) } // execute executes the parsed count query against a connection and transaction and returns an error if there was any during the execution. // // conn is the simpleorm.DBConnection which handles the database connection. // tx is the sql.Tx transaction which the count query will be run in. func (c *Count[T]) execute(conn *simpleorm.DBConnection, tx *sql.Tx) error { // Reinit the results, new execution c.result = -1 dml := c.target.GetCountDML() if c.whereStmt != "" { dml += " WHERE " + c.whereStmt } log.LogDebug("Preparing sql: %s, with args: %s", dml, c.args) var stmt *sql.Stmt var err error if tx != nil { stmt, err = tx.Prepare(dml) } else { stmt, err = conn.Prepare(dml) } if err != nil { return err } defer stmt.Close() log.LogDebug("Executing statement: %s", stmt) if len(c.args) == 0 { err = stmt.QueryRow().Scan(&c.result) } else { // Flattent args to make sure it can be parsed correctly var flatArgs []any for _, a := range c.args { if s, ok := a.([]any); ok { flatArgs = append(flatArgs, s...) } else { flatArgs = append(flatArgs, a) } } err = stmt.QueryRow(flatArgs...).Scan(&c.result) } if err != nil { return err } return nil }