github.com/dolthub/go-mysql-server@v0.18.0/sql/core.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 sql
    16  
    17  import (
    18  	"fmt"
    19  	"strconv"
    20  	"time"
    21  
    22  	"github.com/shopspring/decimal"
    23  )
    24  
    25  // Expression is a combination of one or more SQL expressions.
    26  type Expression interface {
    27  	Resolvable
    28  	fmt.Stringer
    29  	// Type returns the expression type.
    30  	Type() Type
    31  	// IsNullable returns whether the expression can be null.
    32  	IsNullable() bool
    33  	// Eval evaluates the given row and returns a result.
    34  	Eval(ctx *Context, row Row) (interface{}, error)
    35  	// Children returns the children expressions of this expression.
    36  	Children() []Expression
    37  	// WithChildren returns a copy of the expression with children replaced.
    38  	// It will return an error if the number of children is different than
    39  	// the current number of children. They must be given in the same order
    40  	// as they are returned by Children.
    41  	WithChildren(children ...Expression) (Expression, error)
    42  }
    43  
    44  // ExpressionWithNodes is an expression that contains nodes as children.
    45  type ExpressionWithNodes interface {
    46  	Expression
    47  	// NodeChildren returns all node children.
    48  	NodeChildren() []Node
    49  	// WithNodeChildren returns a copy of the expression with its node children replaced. It will return an error if the
    50  	// number of children is different than the current number of children. They must be given in the same order as they
    51  	// are returned by NodeChildren.
    52  	WithNodeChildren(children ...Node) (ExpressionWithNodes, error)
    53  }
    54  
    55  // NonDeterministicExpression allows a way for expressions to declare that they are non-deterministic, which will
    56  // signal the engine to not cache their results when this would otherwise appear to be safe.
    57  type NonDeterministicExpression interface {
    58  	Expression
    59  	// IsNonDeterministic returns whether this expression returns a non-deterministic result. An expression is
    60  	// non-deterministic if it can return different results on subsequent evaluations.
    61  	IsNonDeterministic() bool
    62  }
    63  
    64  // Node is a node in the execution plan tree.
    65  type Node interface {
    66  	Resolvable
    67  	fmt.Stringer
    68  	// Schema of the node.
    69  	Schema() Schema
    70  	// Children nodes.
    71  	Children() []Node
    72  	// WithChildren returns a copy of the node with children replaced.
    73  	// It will return an error if the number of children is different than
    74  	// the current number of children. They must be given in the same order
    75  	// as they are returned by Children.
    76  	WithChildren(children ...Node) (Node, error)
    77  	// CheckPrivileges passes the operations representative of this Node to the PrivilegedOperationChecker to determine
    78  	// whether a user (contained in the context, along with their active roles) has the necessary privileges to execute
    79  	// this node (and its children).
    80  	CheckPrivileges(ctx *Context, opChecker PrivilegedOperationChecker) bool
    81  
    82  	IsReadOnly() bool
    83  }
    84  
    85  // NodeExecBuilder converts a sql.Node tree into a RowIter.
    86  type NodeExecBuilder interface {
    87  	Build(ctx *Context, n Node, r Row) (RowIter, error)
    88  }
    89  
    90  // ExecSourceRel is a node that has no children and is directly
    91  // row generating.
    92  type ExecSourceRel interface {
    93  	Node
    94  	RowIter(ctx *Context, r Row) (RowIter, error)
    95  }
    96  
    97  // Nameable is something that has a name.
    98  type Nameable interface {
    99  	// Name returns the name.
   100  	Name() string
   101  }
   102  
   103  // RenameableNode is a Node that can be renamed.
   104  type RenameableNode interface {
   105  	Nameable
   106  	Node
   107  	// WithName returns a copy of the node with the name changed.
   108  	WithName(string) Node
   109  }
   110  
   111  // Tableable is something that has a table.
   112  type Tableable interface {
   113  	// Table returns the table name.
   114  	Table() string
   115  }
   116  
   117  // Resolvable is something that can be resolved or not.
   118  type Resolvable interface {
   119  	// Resolved returns whether the node is resolved.
   120  	Resolved() bool
   121  }
   122  
   123  // BinaryNode is a Node with two children
   124  type BinaryNode interface {
   125  	Left() Node
   126  	Right() Node
   127  }
   128  
   129  // UnaryNode is a Node with one child.
   130  type UnaryNode interface {
   131  	Child() Node
   132  }
   133  
   134  // CommentedNode allows comments to be set and retrieved on it. Used primarily for join hint comments.
   135  type CommentedNode interface {
   136  	Node
   137  	WithComment(string) Node
   138  	Comment() string
   139  }
   140  
   141  // OpaqueNode is a node that doesn't allow transformations to its children and
   142  // acts as a black box.
   143  type OpaqueNode interface {
   144  	Node
   145  	// Opaque reports whether the node is opaque or not.
   146  	Opaque() bool
   147  }
   148  
   149  // Projector is a node that projects expressions for parent nodes to consume (i.e. GroupBy, Window, Project).
   150  type Projector interface {
   151  	// ProjectedExprs returns the list of expressions projected by this node.
   152  	ProjectedExprs() []Expression
   153  }
   154  
   155  // Expressioner is a node that contains expressions.
   156  type Expressioner interface {
   157  	// Expressions returns the list of expressions contained by the node.
   158  	Expressions() []Expression
   159  	// WithExpressions returns a copy of the node with expressions replaced.
   160  	// It will return an error if the number of expressions is different than
   161  	// the current number of expressions. They must be given in the same order
   162  	// as they are returned by Expressions.
   163  	WithExpressions(...Expression) (Node, error)
   164  }
   165  
   166  // SchemaTarget is a node that has a target schema that can be set during analysis. This is necessary because some
   167  // schema objects (things that involve expressions, column references, etc.) can only be reified during analysis. The
   168  // target schema is the schema of a table under a DDL operation, not the schema of rows returned by this node.
   169  type SchemaTarget interface {
   170  	// WithTargetSchema returns a copy of this node with the target schema set
   171  	WithTargetSchema(Schema) (Node, error)
   172  	// TargetSchema returns the target schema for this node
   173  	TargetSchema() Schema
   174  }
   175  
   176  // PrimaryKeySchemaTarget is a node that has a primary key target schema that can be set
   177  type PrimaryKeySchemaTarget interface {
   178  	SchemaTarget
   179  	WithPrimaryKeySchema(schema PrimaryKeySchema) (Node, error)
   180  }
   181  
   182  // DynamicColumnsTable is a table with a schema that is variable depending
   183  // on the tables in the database (information_schema.columns).
   184  type DynamicColumnsTable interface {
   185  	// AllColumns returns all columns that need to be resolved
   186  	// for this particular table.
   187  	AllColumns(*Context) (Schema, error)
   188  	// WithDefaultsSchema returns a table with a fully resolved
   189  	// schema for every column in AllColumns.
   190  	WithDefaultsSchema(Schema) (Table, error)
   191  	// HasDynamicColumns indicates that a type implements the
   192  	// DynamicColumnsTable interface.
   193  	HasDynamicColumns() bool
   194  }
   195  
   196  // PartitionCounter can return the number of partitions.
   197  type PartitionCounter interface {
   198  	// PartitionCount returns the number of partitions.
   199  	PartitionCount(*Context) (int64, error)
   200  }
   201  
   202  // Closer is a node that can be closed.
   203  type Closer interface {
   204  	Close(*Context) error
   205  }
   206  
   207  // ExternalStoredProcedureProvider provides access to built-in stored procedures. These procedures are implemented
   208  // as functions, instead of as SQL statements. The returned stored procedures cannot be modified or deleted.
   209  type ExternalStoredProcedureProvider interface {
   210  	// ExternalStoredProcedure returns the external stored procedure details for the procedure with the specified name
   211  	// that is able to accept the specified number of parameters. If no matching external stored procedure is found,
   212  	// nil, nil is returned. If an unexpected error is encountered, it is returned as the error parameter.
   213  	ExternalStoredProcedure(ctx *Context, name string, numOfParams int) (*ExternalStoredProcedureDetails, error)
   214  	// ExternalStoredProcedures returns a slice of all external stored procedure details with the specified name. External
   215  	// stored procedures can overload the same name with different arguments, so this method enables a caller to see all
   216  	// available variants with the specified name. If no matching external stored procedures are found, an
   217  	// empty slice is returned, with a nil error. If an unexpected error is encountered, it is returned as the
   218  	// error parameter.
   219  	ExternalStoredProcedures(ctx *Context, name string) ([]ExternalStoredProcedureDetails, error)
   220  }
   221  
   222  type TransactionCharacteristic int
   223  
   224  const (
   225  	ReadWrite TransactionCharacteristic = iota
   226  	ReadOnly
   227  )
   228  
   229  // Transaction is an opaque type implemented by an integrator to record necessary information at the start of a
   230  // transaction. Active transactions will be recorded in the session.
   231  type Transaction interface {
   232  	fmt.Stringer
   233  	IsReadOnly() bool
   234  }
   235  
   236  // Lockable should be implemented by tables that can be locked and unlocked.
   237  type Lockable interface {
   238  	Nameable
   239  	// Lock locks the table either for reads or writes. Any session clients can
   240  	// read while the table is locked for read, but not write.
   241  	// When the table is locked for write, nobody can write except for the
   242  	// session client that requested the lock.
   243  	Lock(ctx *Context, write bool) error
   244  	// Unlock releases the lock for the current session client. It blocks until
   245  	// all reads or writes started during the lock are finished.
   246  	// Context may be nil if the unlock it's because the connection was closed.
   247  	// The id will always be provided, since in some cases context is not
   248  	// available.
   249  	Unlock(ctx *Context, id uint32) error
   250  }
   251  
   252  // ConvertToBool converts a value to a boolean. nil is considered false.
   253  func ConvertToBool(ctx *Context, v interface{}) (bool, error) {
   254  	switch b := v.(type) {
   255  	case []uint8:
   256  		return ConvertToBool(ctx, string(b))
   257  	case bool:
   258  		return b, nil
   259  	case int:
   260  		return b != 0, nil
   261  	case int64:
   262  		return b != 0, nil
   263  	case int32:
   264  		return b != 0, nil
   265  	case int16:
   266  		return b != 0, nil
   267  	case int8:
   268  		return b != 0, nil
   269  	case uint:
   270  		return b != 0, nil
   271  	case uint64:
   272  		return b != 0, nil
   273  	case uint32:
   274  		return b != 0, nil
   275  	case uint16:
   276  		return b != 0, nil
   277  	case uint8:
   278  		return b != 0, nil
   279  	case time.Duration:
   280  		return b != 0, nil
   281  	case time.Time:
   282  		return b.UnixNano() != 0, nil
   283  	case float32:
   284  		return b != 0, nil
   285  	case float64:
   286  		return b != 0, nil
   287  	case string:
   288  		bFloat, err := strconv.ParseFloat(b, 64)
   289  		if err != nil {
   290  			// In MySQL, if the string does not represent a float then it's false
   291  			ctx.Warn(1292, "Truncated incorrect DOUBLE value: '%s'", b)
   292  			return false, nil
   293  		}
   294  		return bFloat != 0, nil
   295  	case decimal.Decimal:
   296  		return !b.IsZero(), nil
   297  	case nil:
   298  		return false, fmt.Errorf("unable to cast nil to bool")
   299  	default:
   300  		return false, fmt.Errorf("unable to cast %#v of type %T to bool", v, v)
   301  	}
   302  }
   303  
   304  // EvaluateCondition evaluates a condition, which is an expression whose value
   305  // will be nil or coerced boolean.
   306  func EvaluateCondition(ctx *Context, cond Expression, row Row) (interface{}, error) {
   307  	v, err := cond.Eval(ctx, row)
   308  	if err != nil {
   309  		return false, err
   310  	}
   311  	if v == nil {
   312  		return nil, nil
   313  	}
   314  	res, err := ConvertToBool(ctx, v)
   315  	if err != nil {
   316  		return nil, err
   317  	}
   318  	return res, nil
   319  }
   320  
   321  // IsFalse coerces EvaluateCondition interface{} response to boolean
   322  func IsFalse(val interface{}) bool {
   323  	res, ok := val.(bool)
   324  	return ok && !res
   325  }
   326  
   327  // IsTrue coerces EvaluateCondition interface{} response to boolean
   328  func IsTrue(val interface{}) bool {
   329  	res, ok := val.(bool)
   330  	return ok && res
   331  }
   332  
   333  // DebugStringer is shared by implementors of Node and Expression, and is used for debugging the analyzer. It allows
   334  // a node or expression to be printed in greater detail than its default String() representation.
   335  type DebugStringer interface {
   336  	// DebugString prints a debug string of the node in question.
   337  	DebugString() string
   338  }
   339  
   340  // DebugString returns a debug string for the Node or Expression given.
   341  func DebugString(nodeOrExpression interface{}) string {
   342  	if ds, ok := nodeOrExpression.(DebugStringer); ok {
   343  		return ds.DebugString()
   344  	}
   345  	if s, ok := nodeOrExpression.(fmt.Stringer); ok {
   346  		return s.String()
   347  	}
   348  	panic(fmt.Sprintf("Expected sql.DebugString or fmt.Stringer for %T", nodeOrExpression))
   349  }
   350  
   351  // Expression2 is an experimental future interface alternative to Expression to provide faster access.
   352  type Expression2 interface {
   353  	Expression
   354  	// Eval2 evaluates the given row frame and returns a result.
   355  	Eval2(ctx *Context, row Row2) (Value, error)
   356  	// Type2 returns the expression type.
   357  	Type2() Type2
   358  }
   359  
   360  var SystemVariables SystemVariableRegistry
   361  
   362  // SystemVariableRegistry is a registry of system variables. Each session gets its own copy of all values via the
   363  // SessionMap() method.
   364  type SystemVariableRegistry interface {
   365  	// AddSystemVariables adds the given system variables to this registry
   366  	AddSystemVariables(sysVars []SystemVariable)
   367  	// AssignValues assigns the given values to the system variables in this registry
   368  	AssignValues(vals map[string]interface{}) error
   369  	// NewSessionMap returns a map of system variables values that can be used by a session
   370  	NewSessionMap() map[string]SystemVarValue
   371  	// GetGlobal returns the global value of the system variable with the given name
   372  	GetGlobal(name string) (SystemVariable, interface{}, bool)
   373  	// SetGlobal sets the global value of the system variable with the given name
   374  	SetGlobal(name string, val interface{}) error
   375  	// GetAllGlobalVariables returns a copy of all global variable values.
   376  	GetAllGlobalVariables() map[string]interface{}
   377  }
   378  
   379  // SystemVariable represents a system variable.
   380  type SystemVariable struct {
   381  	// Name is the name of the system variable.
   382  	Name string
   383  	// Scope defines the scope of the system variable, which is either Global, Session, or Both.
   384  	Scope SystemVariableScope
   385  	// Dynamic defines whether the variable may be written to during runtime. Variables with this set to `false` will
   386  	// return an error if a user attempts to set a value.
   387  	Dynamic bool
   388  	// SetVarHintApplies defines if the variable may be set for a single query using SET_VAR().
   389  	// https://dev.mysql.com/doc/refman/8.0/en/optimizer-hints.html#optimizer-hints-set-var
   390  	SetVarHintApplies bool
   391  	// Type defines the type of the system variable. This may be a special type not accessible to standard MySQL operations.
   392  	Type Type
   393  	// Default defines the default value of the system variable.
   394  	Default interface{}
   395  	// NotifyChanged is called by the engine if the value of this variable
   396  	// changes during runtime.  It is typically |nil|, but can be used for
   397  	// system variables which control the behavior of the running server.
   398  	// For example, replication threads might need to be started or stopped
   399  	// when replication is enabled or disabled. This provides a scalable
   400  	// alternative to polling.
   401  	//
   402  	// Calls to NotifyChanged are serialized for a given system variable in
   403  	// the global context and in a particular session. They should never
   404  	// block.  NotifyChanged is not called when a new system variable is
   405  	// registered.
   406  	NotifyChanged func(SystemVariableScope, SystemVarValue) error
   407  	// ValueFunction defines an optional function that is executed to provide
   408  	// the value of this system variable whenever it is requested. System variables
   409  	// that provide a ValueFunction should also set Dynamic to false, since they
   410  	// cannot be assigned a value and will return a read-only error if tried.
   411  	ValueFunction func() (interface{}, error)
   412  }
   413  
   414  // SystemVariableScope represents the scope of a system variable.
   415  type SystemVariableScope byte
   416  
   417  const (
   418  	// SystemVariableScope_Global is set when the system variable exists only in the global context.
   419  	SystemVariableScope_Global SystemVariableScope = iota
   420  	// SystemVariableScope_Session is set when the system variable exists only in the session context.
   421  	SystemVariableScope_Session
   422  	// SystemVariableScope_Both is set when the system variable exists in both the global and session contexts.
   423  	SystemVariableScope_Both
   424  	// SystemVariableScope_Persist is set when the system variable is global and persisted.
   425  	SystemVariableScope_Persist
   426  	// SystemVariableScope_PersistOnly is set when the system variable is persisted outside of server context.
   427  	SystemVariableScope_PersistOnly
   428  	// SystemVariableScope_ResetPersist is used to remove a persisted variable
   429  	SystemVariableScope_ResetPersist
   430  )
   431  
   432  // String returns the scope as an uppercase string.
   433  func (s SystemVariableScope) String() string {
   434  	switch s {
   435  	case SystemVariableScope_Global:
   436  		return "GLOBAL"
   437  	case SystemVariableScope_Session:
   438  		return "SESSION"
   439  	case SystemVariableScope_Persist:
   440  		return "GLOBAL, PERSIST"
   441  	case SystemVariableScope_PersistOnly:
   442  		return "PERSIST"
   443  	case SystemVariableScope_ResetPersist:
   444  		return "RESET PERSIST"
   445  	case SystemVariableScope_Both:
   446  		return "GLOBAL, SESSION"
   447  	default:
   448  		return "UNKNOWN_SYSTEM_SCOPE"
   449  	}
   450  }
   451  
   452  type SystemVarValue struct {
   453  	Var SystemVariable
   454  	Val interface{}
   455  }
   456  
   457  type NameableNode interface {
   458  	Nameable
   459  	Node
   460  }