github.com/hellobchain/third_party@v0.0.0-20230331131523-deb0478a2e52/go-sql-driver/mysql/statement.go (about)

     1  // Go MySQL Driver - A MySQL-Driver for Go's database/sql package
     2  //
     3  // Copyright 2012 The Go-MySQL-Driver Authors. All rights reserved.
     4  //
     5  // This Source Code Form is subject to the terms of the Mozilla Public
     6  // License, v. 2.0. If a copy of the MPL was not distributed with this file,
     7  // You can obtain one at http://mozilla.org/MPL/2.0/.
     8  
     9  package mysql
    10  
    11  import (
    12  	"database/sql/driver"
    13  	"fmt"
    14  	"io"
    15  	"reflect"
    16  )
    17  
    18  type mysqlStmt struct {
    19  	mc         *mysqlConn
    20  	id         uint32
    21  	paramCount int
    22  }
    23  
    24  func (stmt *mysqlStmt) Close() error {
    25  	if stmt.mc == nil || stmt.mc.closed.IsSet() {
    26  		// driver.Stmt.Close can be called more than once, thus this function
    27  		// has to be idempotent.
    28  		// See also Issue #450 and golang/go#16019.
    29  		//errLog.Print(ErrInvalidConn)
    30  		return driver.ErrBadConn
    31  	}
    32  
    33  	err := stmt.mc.writeCommandPacketUint32(comStmtClose, stmt.id)
    34  	stmt.mc = nil
    35  	return err
    36  }
    37  
    38  func (stmt *mysqlStmt) NumInput() int {
    39  	return stmt.paramCount
    40  }
    41  
    42  func (stmt *mysqlStmt) ColumnConverter(idx int) driver.ValueConverter {
    43  	return converter{}
    44  }
    45  
    46  func (stmt *mysqlStmt) Exec(args []driver.Value) (driver.Result, error) {
    47  	if stmt.mc.closed.IsSet() {
    48  		errLog.Print(ErrInvalidConn)
    49  		return nil, driver.ErrBadConn
    50  	}
    51  	// Send command
    52  	err := stmt.writeExecutePacket(args)
    53  	if err != nil {
    54  		return nil, stmt.mc.markBadConn(err)
    55  	}
    56  
    57  	mc := stmt.mc
    58  
    59  	mc.affectedRows = 0
    60  	mc.insertId = 0
    61  
    62  	// Read Result
    63  	resLen, err := mc.readResultSetHeaderPacket()
    64  	if err != nil {
    65  		return nil, err
    66  	}
    67  
    68  	if resLen > 0 {
    69  		// Columns
    70  		if err = mc.readUntilEOF(); err != nil {
    71  			return nil, err
    72  		}
    73  
    74  		// Rows
    75  		if err := mc.readUntilEOF(); err != nil {
    76  			return nil, err
    77  		}
    78  	}
    79  
    80  	if err := mc.discardResults(); err != nil {
    81  		return nil, err
    82  	}
    83  
    84  	return &mysqlResult{
    85  		affectedRows: int64(mc.affectedRows),
    86  		insertId:     int64(mc.insertId),
    87  	}, nil
    88  }
    89  
    90  func (stmt *mysqlStmt) Query(args []driver.Value) (driver.Rows, error) {
    91  	return stmt.query(args)
    92  }
    93  
    94  func (stmt *mysqlStmt) query(args []driver.Value) (*binaryRows, error) {
    95  	if stmt.mc.closed.IsSet() {
    96  		errLog.Print(ErrInvalidConn)
    97  		return nil, driver.ErrBadConn
    98  	}
    99  	// Send command
   100  	err := stmt.writeExecutePacket(args)
   101  	if err != nil {
   102  		return nil, stmt.mc.markBadConn(err)
   103  	}
   104  
   105  	mc := stmt.mc
   106  
   107  	// Read Result
   108  	resLen, err := mc.readResultSetHeaderPacket()
   109  	if err != nil {
   110  		return nil, err
   111  	}
   112  
   113  	rows := new(binaryRows)
   114  
   115  	if resLen > 0 {
   116  		rows.mc = mc
   117  		rows.rs.columns, err = mc.readColumns(resLen)
   118  	} else {
   119  		rows.rs.done = true
   120  
   121  		switch err := rows.NextResultSet(); err {
   122  		case nil, io.EOF:
   123  			return rows, nil
   124  		default:
   125  			return nil, err
   126  		}
   127  	}
   128  
   129  	return rows, err
   130  }
   131  
   132  type converter struct{}
   133  
   134  // ConvertValue mirrors the reference/default converter in database/sql/driver
   135  // with _one_ exception.  We support uint64 with their high bit and the default
   136  // implementation does not.  This function should be kept in sync with
   137  // database/sql/driver defaultConverter.ConvertValue() except for that
   138  // deliberate difference.
   139  func (c converter) ConvertValue(v interface{}) (driver.Value, error) {
   140  	if driver.IsValue(v) {
   141  		return v, nil
   142  	}
   143  
   144  	if vr, ok := v.(driver.Valuer); ok {
   145  		sv, err := callValuerValue(vr)
   146  		if err != nil {
   147  			return nil, err
   148  		}
   149  		if !driver.IsValue(sv) {
   150  			return nil, fmt.Errorf("non-Value type %T returned from Value", sv)
   151  		}
   152  		return sv, nil
   153  	}
   154  
   155  	rv := reflect.ValueOf(v)
   156  	switch rv.Kind() {
   157  	case reflect.Ptr:
   158  		// indirect pointers
   159  		if rv.IsNil() {
   160  			return nil, nil
   161  		} else {
   162  			return c.ConvertValue(rv.Elem().Interface())
   163  		}
   164  	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
   165  		return rv.Int(), nil
   166  	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
   167  		return rv.Uint(), nil
   168  	case reflect.Float32, reflect.Float64:
   169  		return rv.Float(), nil
   170  	case reflect.Bool:
   171  		return rv.Bool(), nil
   172  	case reflect.Slice:
   173  		ek := rv.Type().Elem().Kind()
   174  		if ek == reflect.Uint8 {
   175  			return rv.Bytes(), nil
   176  		}
   177  		return nil, fmt.Errorf("unsupported type %T, a slice of %s", v, ek)
   178  	case reflect.String:
   179  		return rv.String(), nil
   180  	}
   181  	return nil, fmt.Errorf("unsupported type %T, a %s", v, rv.Kind())
   182  }
   183  
   184  var valuerReflectType = reflect.TypeOf((*driver.Valuer)(nil)).Elem()
   185  
   186  // callValuerValue returns vr.Value(), with one exception:
   187  // If vr.Value is an auto-generated method on a pointer type and the
   188  // pointer is nil, it would panic at runtime in the panicwrap
   189  // method. Treat it like nil instead.
   190  //
   191  // This is so people can implement driver.Value on value types and
   192  // still use nil pointers to those types to mean nil/NULL, just like
   193  // string/*string.
   194  //
   195  // This is an exact copy of the same-named unexported function from the
   196  // database/sql package.
   197  func callValuerValue(vr driver.Valuer) (v driver.Value, err error) {
   198  	if rv := reflect.ValueOf(vr); rv.Kind() == reflect.Ptr &&
   199  		rv.IsNil() &&
   200  		rv.Type().Elem().Implements(valuerReflectType) {
   201  		return nil, nil
   202  	}
   203  	return vr.Value()
   204  }