...

Source file src/github.com/doug-martin/goqu/v9/exec/query_executor.go

Documentation: github.com/doug-martin/goqu/v9/exec

     1  package exec
     2  
     3  import (
     4  	"context"
     5  	gsql "database/sql"
     6  	"reflect"
     7  
     8  	"github.com/doug-martin/goqu/v9/internal/errors"
     9  	"github.com/doug-martin/goqu/v9/internal/util"
    10  )
    11  
    12  type (
    13  	QueryExecutor struct {
    14  		de    DbExecutor
    15  		err   error
    16  		query string
    17  		args  []interface{}
    18  	}
    19  )
    20  
    21  var (
    22  	errUnsupportedScanStructType  = errors.New("type must be a pointer to a struct when scanning into a struct")
    23  	errUnsupportedScanStructsType = errors.New("type must be a pointer to a slice when scanning into structs")
    24  	errUnsupportedScanValsType    = errors.New("type must be a pointer to a slice when scanning into vals")
    25  	errScanValPointer             = errors.New("type must be a pointer when scanning into val")
    26  	errScanValNonSlice            = errors.New("type cannot be a pointer to a slice when scanning into val")
    27  )
    28  
    29  func newQueryExecutor(de DbExecutor, err error, query string, args ...interface{}) QueryExecutor {
    30  	return QueryExecutor{de: de, err: err, query: query, args: args}
    31  }
    32  
    33  func (q QueryExecutor) ToSQL() (sql string, args []interface{}, err error) {
    34  	return q.query, q.args, q.err
    35  }
    36  
    37  func (q QueryExecutor) Exec() (gsql.Result, error) {
    38  	return q.ExecContext(context.Background())
    39  }
    40  
    41  func (q QueryExecutor) ExecContext(ctx context.Context) (gsql.Result, error) {
    42  	if q.err != nil {
    43  		return nil, q.err
    44  	}
    45  	return q.de.ExecContext(ctx, q.query, q.args...)
    46  }
    47  
    48  func (q QueryExecutor) Query() (*gsql.Rows, error) {
    49  	return q.QueryContext(context.Background())
    50  }
    51  
    52  func (q QueryExecutor) QueryContext(ctx context.Context) (*gsql.Rows, error) {
    53  	if q.err != nil {
    54  		return nil, q.err
    55  	}
    56  	return q.de.QueryContext(ctx, q.query, q.args...)
    57  }
    58  
    59  // This will execute the SQL and append results to the slice
    60  //    var myStructs []MyStruct
    61  //    if err := db.From("test").ScanStructs(&myStructs); err != nil{
    62  //        panic(err.Error()
    63  //    }
    64  //    //use your structs
    65  //
    66  //
    67  // i: A pointer to a slice of structs.
    68  func (q QueryExecutor) ScanStructs(i interface{}) error {
    69  	return q.ScanStructsContext(context.Background(), i)
    70  }
    71  
    72  // This will execute the SQL and append results to the slice
    73  //    var myStructs []MyStruct
    74  //    if err := db.From("test").ScanStructsContext(ctx, &myStructs); err != nil{
    75  //        panic(err.Error()
    76  //    }
    77  //    //use your structs
    78  //
    79  //
    80  // i: A pointer to a slice of structs.
    81  func (q QueryExecutor) ScanStructsContext(ctx context.Context, i interface{}) error {
    82  	scanner, err := q.ScannerContext(ctx)
    83  	if err != nil {
    84  		return err
    85  	}
    86  	defer func() { _ = scanner.Close() }()
    87  	return scanner.ScanStructs(i)
    88  }
    89  
    90  // This will execute the SQL and fill out the struct with the fields returned.
    91  // This method returns a boolean value that is false if no record was found
    92  //    var myStruct MyStruct
    93  //    found, err := db.From("test").Limit(1).ScanStruct(&myStruct)
    94  //    if err != nil{
    95  //        panic(err.Error()
    96  //    }
    97  //    if !found{
    98  //          fmt.Println("NOT FOUND")
    99  //    }
   100  //
   101  // i: A pointer to a struct
   102  func (q QueryExecutor) ScanStruct(i interface{}) (bool, error) {
   103  	return q.ScanStructContext(context.Background(), i)
   104  }
   105  
   106  // This will execute the SQL and fill out the struct with the fields returned.
   107  // This method returns a boolean value that is false if no record was found
   108  //    var myStruct MyStruct
   109  //    found, err := db.From("test").Limit(1).ScanStructContext(ctx, &myStruct)
   110  //    if err != nil{
   111  //        panic(err.Error()
   112  //    }
   113  //    if !found{
   114  //          fmt.Println("NOT FOUND")
   115  //    }
   116  //
   117  // i: A pointer to a struct
   118  func (q QueryExecutor) ScanStructContext(ctx context.Context, i interface{}) (bool, error) {
   119  	val := reflect.ValueOf(i)
   120  	if !util.IsPointer(val.Kind()) {
   121  		return false, errUnsupportedScanStructType
   122  	}
   123  	val = reflect.Indirect(val)
   124  	if !util.IsStruct(val.Kind()) {
   125  		return false, errUnsupportedScanStructType
   126  	}
   127  
   128  	scanner, err := q.ScannerContext(ctx)
   129  	if err != nil {
   130  		return false, err
   131  	}
   132  
   133  	defer func() { _ = scanner.Close() }()
   134  
   135  	if scanner.Next() {
   136  		err = scanner.ScanStruct(i)
   137  		if err != nil {
   138  			return false, err
   139  		}
   140  
   141  		return true, scanner.Err()
   142  	}
   143  
   144  	return false, scanner.Err()
   145  }
   146  
   147  // This will execute the SQL and append results to the slice.
   148  //    var ids []uint32
   149  //    if err := db.From("test").Select("id").ScanVals(&ids); err != nil{
   150  //        panic(err.Error()
   151  //    }
   152  //
   153  // i: Takes a pointer to a slice of primitive values.
   154  func (q QueryExecutor) ScanVals(i interface{}) error {
   155  	return q.ScanValsContext(context.Background(), i)
   156  }
   157  
   158  // This will execute the SQL and append results to the slice.
   159  //    var ids []uint32
   160  //    if err := db.From("test").Select("id").ScanValsContext(ctx, &ids); err != nil{
   161  //        panic(err.Error()
   162  //    }
   163  //
   164  // i: Takes a pointer to a slice of primitive values.
   165  func (q QueryExecutor) ScanValsContext(ctx context.Context, i interface{}) error {
   166  	scanner, err := q.ScannerContext(ctx)
   167  	if err != nil {
   168  		return err
   169  	}
   170  	defer func() { _ = scanner.Close() }()
   171  	return scanner.ScanVals(i)
   172  }
   173  
   174  // This will execute the SQL and set the value of the primitive. This method will return false if no record is found.
   175  //    var id uint32
   176  //    found, err := db.From("test").Select("id").Limit(1).ScanVal(&id)
   177  //    if err != nil{
   178  //        panic(err.Error()
   179  //    }
   180  //    if !found{
   181  //        fmt.Println("NOT FOUND")
   182  //    }
   183  //
   184  //   i: Takes a pointer to a primitive value.
   185  func (q QueryExecutor) ScanVal(i interface{}) (bool, error) {
   186  	return q.ScanValContext(context.Background(), i)
   187  }
   188  
   189  // This will execute the SQL and set the value of the primitive. This method will return false if no record is found.
   190  //    var id uint32
   191  //    found, err := db.From("test").Select("id").Limit(1).ScanValContext(ctx, &id)
   192  //    if err != nil{
   193  //        panic(err.Error()
   194  //    }
   195  //    if !found{
   196  //        fmt.Println("NOT FOUND")
   197  //    }
   198  //
   199  //   i: Takes a pointer to a primitive value.
   200  func (q QueryExecutor) ScanValContext(ctx context.Context, i interface{}) (bool, error) {
   201  	val := reflect.ValueOf(i)
   202  	if !util.IsPointer(val.Kind()) {
   203  		return false, errScanValPointer
   204  	}
   205  	val = reflect.Indirect(val)
   206  	if util.IsSlice(val.Kind()) {
   207  		switch i.(type) {
   208  		case *gsql.RawBytes: // do nothing
   209  		case *[]byte: // do nothing
   210  		case gsql.Scanner: // do nothing
   211  		default:
   212  			return false, errScanValNonSlice
   213  		}
   214  	}
   215  
   216  	scanner, err := q.ScannerContext(ctx)
   217  	if err != nil {
   218  		return false, err
   219  	}
   220  
   221  	defer func() { _ = scanner.Close() }()
   222  
   223  	if scanner.Next() {
   224  		err = scanner.ScanVal(i)
   225  		if err != nil {
   226  			return false, err
   227  		}
   228  
   229  		return true, scanner.Err()
   230  	}
   231  
   232  	return false, scanner.Err()
   233  }
   234  
   235  // Scanner will return a Scanner that can be used for manually scanning rows.
   236  func (q QueryExecutor) Scanner() (Scanner, error) {
   237  	return q.ScannerContext(context.Background())
   238  }
   239  
   240  // ScannerContext will return a Scanner that can be used for manually scanning rows.
   241  func (q QueryExecutor) ScannerContext(ctx context.Context) (Scanner, error) {
   242  	rows, err := q.QueryContext(ctx)
   243  	if err != nil {
   244  		return nil, err
   245  	}
   246  	return NewScanner(rows), nil
   247  }
   248  

View as plain text