vitess.io/vitess@v0.16.2/go/vt/vtgate/semantics/errors.go (about)

     1  /*
     2  Copyright 2022 The Vitess Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package semantics
    18  
    19  import (
    20  	"fmt"
    21  
    22  	vtrpcpb "vitess.io/vitess/go/vt/proto/vtrpc"
    23  	"vitess.io/vitess/go/vt/sqlparser"
    24  	"vitess.io/vitess/go/vt/vterrors"
    25  )
    26  
    27  type (
    28  	ErrorCode int
    29  
    30  	Error struct {
    31  		Code ErrorCode
    32  		args []any
    33  	}
    34  	ErrType int
    35  
    36  	info struct {
    37  		format string
    38  		state  vterrors.State
    39  		code   vtrpcpb.Code
    40  		id     string
    41  		typ    ErrType
    42  	}
    43  )
    44  
    45  const (
    46  	Other ErrType = iota
    47  	Unsupported
    48  	Bug
    49  )
    50  
    51  const (
    52  	UnionColumnsDoNotMatch ErrorCode = iota
    53  	UnsupportedMultiTablesInUpdate
    54  	UnsupportedNaturalJoin
    55  	TableNotUpdatable
    56  	UnionWithSQLCalcFoundRows
    57  	SQLCalcFoundRowsUsage
    58  	CantUseOptionHere
    59  	MissingInVSchema
    60  	NotSequenceTable
    61  	NextWithMultipleTables
    62  	LockOnlyWithDual
    63  	QualifiedOrderInUnion
    64  	JSONTables
    65  	Buggy
    66  	ColumnNotFound
    67  	AmbiguousColumn
    68  )
    69  
    70  func NewError(code ErrorCode, args ...any) *Error {
    71  	return &Error{
    72  		Code: code,
    73  		args: args,
    74  	}
    75  }
    76  
    77  var errors = map[ErrorCode]info{
    78  	UnionColumnsDoNotMatch: {
    79  		format: "The used SELECT statements have a different number of columns",
    80  		state:  vterrors.WrongNumberOfColumnsInSelect,
    81  		code:   vtrpcpb.Code_FAILED_PRECONDITION,
    82  	},
    83  	UnsupportedMultiTablesInUpdate: {
    84  		format: "multiple tables in update",
    85  		typ:    Unsupported,
    86  	},
    87  	TableNotUpdatable: {
    88  		format: "The target table %s of the UPDATE is not updatable",
    89  		state:  vterrors.NonUpdateableTable,
    90  		code:   vtrpcpb.Code_INVALID_ARGUMENT,
    91  	},
    92  	UnsupportedNaturalJoin: {
    93  		format: "%s",
    94  		typ:    Unsupported,
    95  	},
    96  	UnionWithSQLCalcFoundRows: {
    97  		format: "SQL_CALC_FOUND_ROWS not supported with union",
    98  		typ:    Unsupported,
    99  	},
   100  	SQLCalcFoundRowsUsage: {
   101  		format: "Incorrect usage/placement of 'SQL_CALC_FOUND_ROWS'",
   102  		code:   vtrpcpb.Code_INVALID_ARGUMENT,
   103  	},
   104  	CantUseOptionHere: {
   105  		format: "Incorrect usage/placement of '%s'",
   106  		state:  vterrors.CantUseOptionHere,
   107  		code:   vtrpcpb.Code_INVALID_ARGUMENT,
   108  	},
   109  	MissingInVSchema: {
   110  		format: "Table information is not provided in vschema",
   111  		code:   vtrpcpb.Code_INVALID_ARGUMENT,
   112  	},
   113  	NotSequenceTable: {
   114  		format: "NEXT used on a non-sequence table",
   115  		code:   vtrpcpb.Code_INVALID_ARGUMENT,
   116  	},
   117  	NextWithMultipleTables: {
   118  		format: "Next statement should not contain multiple tables",
   119  		typ:    Bug,
   120  	},
   121  	LockOnlyWithDual: {
   122  		format: "%v allowed only with dual",
   123  		code:   vtrpcpb.Code_UNIMPLEMENTED,
   124  	},
   125  	QualifiedOrderInUnion: {
   126  		format: "Table %s from one of the SELECTs cannot be used in global ORDER clause",
   127  	},
   128  	JSONTables: {
   129  		format: "json_table expressions",
   130  		typ:    Unsupported,
   131  	},
   132  	Buggy: {
   133  		format: "%s",
   134  		typ:    Bug,
   135  	},
   136  	ColumnNotFound: {
   137  		format: "symbol %s not found",
   138  		state:  vterrors.BadFieldError,
   139  		code:   vtrpcpb.Code_INVALID_ARGUMENT,
   140  	},
   141  	AmbiguousColumn: {
   142  		format: "Column '%s' in field list is ambiguous",
   143  		state:  vterrors.BadFieldError,
   144  		code:   vtrpcpb.Code_INVALID_ARGUMENT,
   145  	},
   146  }
   147  
   148  func (n *Error) Error() string {
   149  	f, ok := errors[n.Code]
   150  	if !ok {
   151  		return "unknown error"
   152  	}
   153  
   154  	format := f.format
   155  
   156  	if f.id != "" {
   157  		format = fmt.Sprintf("%s: %s", f.id, format)
   158  	}
   159  
   160  	switch f.typ {
   161  	case Unsupported:
   162  		format = "VT12001: unsupported: " + format
   163  	case Bug:
   164  		format = "VT13001: [BUG] " + format
   165  	}
   166  
   167  	var args []any
   168  	for _, arg := range n.args {
   169  		ast, isAST := arg.(sqlparser.SQLNode)
   170  		if isAST {
   171  			args = append(args, sqlparser.String(ast))
   172  		} else {
   173  			args = append(args, arg)
   174  		}
   175  	}
   176  
   177  	return fmt.Sprintf(format, args...)
   178  }
   179  
   180  func (n *Error) ErrorState() vterrors.State {
   181  	f, ok := errors[n.Code]
   182  	if !ok {
   183  		return vterrors.Undefined
   184  	}
   185  
   186  	return f.state
   187  }
   188  
   189  func (n *Error) ErrorCode() vtrpcpb.Code {
   190  	f, ok := errors[n.Code]
   191  	if !ok {
   192  		return vtrpcpb.Code_UNKNOWN
   193  	}
   194  
   195  	switch f.typ {
   196  	case Unsupported:
   197  		return vtrpcpb.Code_UNIMPLEMENTED
   198  	case Bug:
   199  		return vtrpcpb.Code_INTERNAL
   200  	default:
   201  		return f.code
   202  	}
   203  }