|
- /*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
- package sql
-
- import (
- "context"
- "database/sql/driver"
-
- "github.com/seata/seata-go/pkg/datasource/sql/exec"
- "github.com/seata/seata-go/pkg/datasource/sql/types"
- )
-
- type Stmt struct {
- conn *Conn
- // res
- res *DBResource
- // txCtx
- txCtx *types.TransactionContext
- // query
- query string
- // stmt
- stmt driver.Stmt
- }
-
- // Close closes the statement.
- //
- // As of Go 1.1, a Stmt will not be closed if it's in use
- // by any queries.
- //
- // Drivers must ensure all network calls made by Close
- // do not block indefinitely (e.g. apply a timeout).
- func (s *Stmt) Close() error {
- s.txCtx = nil
- return s.stmt.Close()
- }
-
- // NumInput returns the number of placeholder parameters.
- //
- // If NumInput returns >= 0, the sql package will sanity check
- // argument counts from callers and return errors to the caller
- // before the statement's Exec or Query methods are called.
- //
- // NumInput may also return -1, if the driver doesn't know
- // its number of placeholders. In that case, the sql package
- // will not sanity check Exec or Query argument counts.
- func (s *Stmt) NumInput() int {
- return s.stmt.NumInput()
- }
-
- // Query executes a query that may return rows, such as a
- // SELECT.
- //
- // Deprecated: Drivers should implement StmtQueryContext instead (or additionally).
- func (s *Stmt) Query(args []driver.Value) (driver.Rows, error) {
- executor, err := exec.BuildExecutor(s.res.dbType, s.txCtx.TransType, s.query)
- if err != nil {
- return nil, err
- }
-
- execCtx := &exec.ExecContext{
- TxCtx: s.txCtx,
- Query: s.query,
- Values: args,
- }
-
- ret, err := executor.ExecWithValue(context.Background(), execCtx,
- func(ctx context.Context, query string, args []driver.Value) (types.ExecResult, error) {
- ret, err := s.stmt.Query(args)
- if err != nil {
- return nil, err
- }
-
- return types.NewResult(types.WithRows(ret)), nil
- })
- if err != nil {
- return nil, err
- }
-
- return ret.GetRows(), nil
- }
-
- // StmtQueryContext enhances the Stmt interface by providing Query with context.
- // QueryContext executes a query that may return rows, such as a
- // SELECT.
- //
- // QueryContext must honor the context timeout and return when it is canceled.
- func (s *Stmt) QueryContext(ctx context.Context, args []driver.NamedValue) (driver.Rows, error) {
- stmt, ok := s.stmt.(driver.StmtQueryContext)
- if !ok {
- return nil, driver.ErrSkip
- }
-
- executor, err := exec.BuildExecutor(s.res.dbType, s.txCtx.TransType, s.query)
- if err != nil {
- return nil, err
- }
-
- execCtx := &exec.ExecContext{
- TxCtx: s.txCtx,
- Query: s.query,
- NamedValues: args,
- }
-
- ret, err := executor.ExecWithNamedValue(context.Background(), execCtx,
- func(ctx context.Context, query string, args []driver.NamedValue) (types.ExecResult, error) {
- ret, err := stmt.QueryContext(ctx, args)
- if err != nil {
- return nil, err
- }
-
- return types.NewResult(types.WithRows(ret)), nil
- })
- if err != nil {
- return nil, err
- }
-
- return ret.GetRows(), nil
- }
-
- // Exec executes a query that doesn't return rows, such
- // as an INSERT or UPDATE.
- //
- // Deprecated: Drivers should implement StmtExecContext instead (or additionally).
- func (s *Stmt) Exec(args []driver.Value) (driver.Result, error) {
- // in transaction, need run Executor
- executor, err := exec.BuildExecutor(s.res.dbType, s.txCtx.TransType, s.query)
- if err != nil {
- return nil, err
- }
-
- execCtx := &exec.ExecContext{
- TxCtx: s.txCtx,
- Query: s.query,
- Values: args,
- }
-
- ret, err := executor.ExecWithValue(context.Background(), execCtx,
- func(ctx context.Context, query string, args []driver.Value) (types.ExecResult, error) {
- ret, err := s.stmt.Exec(args)
- if err != nil {
- return nil, err
- }
-
- return types.NewResult(types.WithResult(ret)), nil
- })
-
- return ret.GetResult(), err
- }
-
- // ExecContext executes a query that doesn't return rows, such
- // as an INSERT or UPDATE.
- //
- // ExecContext must honor the context timeout and return when it is canceled.
- func (s *Stmt) ExecContext(ctx context.Context, args []driver.NamedValue) (driver.Result, error) {
- stmt, ok := s.stmt.(driver.StmtExecContext)
- if !ok {
- return nil, driver.ErrSkip
- }
-
- // in transaction, need run Executor
- executor, err := exec.BuildExecutor(s.res.dbType, s.txCtx.TransType, s.query)
- if err != nil {
- return nil, err
- }
-
- execCtx := &exec.ExecContext{
- TxCtx: s.txCtx,
- Query: s.query,
- NamedValues: args,
- }
-
- ret, err := executor.ExecWithNamedValue(ctx, execCtx,
- func(ctx context.Context, query string, args []driver.NamedValue) (types.ExecResult, error) {
- ret, err := stmt.ExecContext(ctx, args)
- if err != nil {
- return nil, err
- }
-
- return types.NewResult(types.WithResult(ret)), nil
- })
-
- return ret.GetResult(), err
- }
|