github.com/dolthub/go-mysql-server@v0.18.0/driver/stmt.go (about)

     1  // Copyright 2020-2021 Dolthub, Inc.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package driver
    16  
    17  import (
    18  	"context"
    19  	"database/sql/driver"
    20  
    21  	querypb "github.com/dolthub/vitess/go/vt/proto/query"
    22  )
    23  
    24  // Stmt is a prepared statement.
    25  type Stmt struct {
    26  	conn     *Conn
    27  	queryStr string
    28  }
    29  
    30  // Close does nothing.
    31  func (s *Stmt) Close() error {
    32  	return nil
    33  }
    34  
    35  // NumInput returns the number of placeholder parameters.
    36  //
    37  // If NumInput returns >= 0, the sql package will sanity check
    38  // argument counts from callers and return errors to the caller
    39  // before the statement's Exec or Query methods are called.
    40  //
    41  // NumInput may also return -1, if the driver doesn't know
    42  // its number of placeholders. In that case, the sql package
    43  // will not sanity check Exec or Query argument counts.
    44  func (s *Stmt) NumInput() int {
    45  	return -1
    46  }
    47  
    48  // Exec executes a query that doesn't return rows, such
    49  // as an INSERT or UPDATE.
    50  func (s *Stmt) Exec(args []driver.Value) (driver.Result, error) {
    51  	bindings, err := valuesToBindings(args)
    52  	if err != nil {
    53  		return nil, err
    54  	}
    55  	return s.exec(context.Background(), bindings)
    56  }
    57  
    58  // Query executes a query that may return rows, such as a
    59  // SELECT.
    60  func (s *Stmt) Query(args []driver.Value) (driver.Rows, error) {
    61  	bindings, err := valuesToBindings(args)
    62  	if err != nil {
    63  		return nil, err
    64  	}
    65  	return s.query(context.Background(), bindings)
    66  }
    67  
    68  // ExecContext executes a query that doesn't return rows, such
    69  // as an INSERT or UPDATE.
    70  func (s *Stmt) ExecContext(ctx context.Context, args []driver.NamedValue) (driver.Result, error) {
    71  	bindings, err := namedValuesToBindings(args)
    72  	if err != nil {
    73  		return nil, err
    74  	}
    75  	return s.exec(ctx, bindings)
    76  }
    77  
    78  // QueryContext executes a query that may return rows, such as a
    79  // SELECT.
    80  func (s *Stmt) QueryContext(ctx context.Context, args []driver.NamedValue) (driver.Rows, error) {
    81  	bindings, err := namedValuesToBindings(args)
    82  	if err != nil {
    83  		return nil, err
    84  	}
    85  	return s.query(ctx, bindings)
    86  }
    87  
    88  func (s *Stmt) exec(ctx context.Context, bindings map[string]*querypb.BindVariable) (driver.Result, error) {
    89  	qctx, err := s.conn.newContextWithQuery(ctx, s.queryStr)
    90  	if err != nil {
    91  		return nil, err
    92  	}
    93  
    94  	_, rows, err := s.conn.dbConn.engine.QueryWithBindings(qctx, s.queryStr, nil, bindings)
    95  	if err != nil {
    96  		return nil, err
    97  	}
    98  
    99  	okr, found, err := getOKResult(qctx, rows)
   100  	if err != nil {
   101  		return nil, err
   102  	} else if !found {
   103  		return &ResultNotFound{}, nil
   104  	}
   105  
   106  	return &Result{okr}, nil
   107  }
   108  
   109  func (s *Stmt) query(ctx context.Context, bindings map[string]*querypb.BindVariable) (driver.Rows, error) {
   110  	qctx, err := s.conn.newContextWithQuery(ctx, s.queryStr)
   111  	if err != nil {
   112  		return nil, err
   113  	}
   114  
   115  	cols, rows, err := s.conn.dbConn.engine.QueryWithBindings(qctx, s.queryStr, nil, bindings)
   116  	if err != nil {
   117  		return nil, err
   118  	}
   119  
   120  	return &Rows{s.conn.options, qctx, cols, rows}, nil
   121  }