github.com/dolthub/go-mysql-server@v0.18.0/sql/tables.go (about)

     1  // Copyright 2022 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  )
    20  
    21  // Table is a SQL table.
    22  type Table interface {
    23  	Nameable
    24  	fmt.Stringer
    25  	// Schema returns the table's schema.
    26  	Schema() Schema
    27  	// Collation returns the table's collation.
    28  	Collation() CollationID
    29  	// Partitions returns the table's partitions in an iterator.
    30  	Partitions(*Context) (PartitionIter, error)
    31  	// PartitionRows returns the rows in the given partition, which was returned by Partitions.
    32  	PartitionRows(*Context, Partition) (RowIter, error)
    33  }
    34  
    35  // TableFunction is a node that is generated by a function and can be used as a table factor in many SQL queries.
    36  type TableFunction interface {
    37  	Node
    38  	Expressioner
    39  	Databaser
    40  	Nameable
    41  
    42  	// NewInstance calls the table function with the arguments provided, producing a Node
    43  	NewInstance(ctx *Context, db Database, args []Expression) (Node, error)
    44  }
    45  
    46  // CatalogTableFunction is a table function that can be used as a table factor in many SQL queries.
    47  type CatalogTableFunction interface {
    48  	TableFunction
    49  
    50  	// WithCatalog returns a new instance of the table function with the given catalog
    51  	WithCatalog(c Catalog) (TableFunction, error)
    52  }
    53  
    54  // TemporaryTable allows tables to declare that they are temporary (created by CREATE TEMPORARY TABLE).
    55  // Only used for validation of certain DDL operations -- in almost all respects TemporaryTables are indistinguishable
    56  // from persisted tables to the engine.
    57  type TemporaryTable interface {
    58  	// IsTemporary should return true if the table is temporary to the session
    59  	IsTemporary() bool
    60  }
    61  
    62  // TableWrapper is a node that wraps the real table. This is needed because wrappers cannot implement some methods the
    63  // table may implement. This interface is used in analysis and planning and is not expected to be implemented by
    64  // integrators.
    65  type TableWrapper interface {
    66  	// Underlying returns the underlying table.
    67  	Underlying() Table
    68  }
    69  
    70  // MutableTableWrapper is a TableWrapper that can change its underlying table.
    71  type MutableTableWrapper interface {
    72  	TableWrapper
    73  	WithUnderlying(Table) Table
    74  }
    75  
    76  // FilteredTable is a table that can filter its result rows from RowIter using filter expressions that would otherwise
    77  // be applied by a separate Filter node.
    78  type FilteredTable interface {
    79  	Table
    80  	// Filters returns the filter expressions that have been applied to this table.
    81  	Filters() []Expression
    82  	// HandledFilters returns the subset of the filter expressions given that this table can apply.
    83  	HandledFilters(filters []Expression) []Expression
    84  	// WithFilters returns a table with the given filter expressions applied.
    85  	WithFilters(ctx *Context, filters []Expression) Table
    86  }
    87  
    88  // CommentedTable is a table that has a comment on it.
    89  type CommentedTable interface {
    90  	Table
    91  	// Comment returns the table's optional comment.
    92  	Comment() string
    93  }
    94  
    95  // ProjectedTable is a table that can return only a subset of its columns from RowIter. This provides a very large
    96  // efficiency gain during table scans. Tables that implement this interface must return only the projected columns
    97  // in future calls to Schema.
    98  type ProjectedTable interface {
    99  	Table
   100  	// WithProjections returns a version of this table with only the subset of columns named. Calls to Schema must
   101  	// only include these columns. A zero-length slice of column names is valid and indicates that rows from this table
   102  	// should be spooled, but no columns should be returned. A nil slice will never be provided.
   103  	WithProjections(colNames []string) Table
   104  	// Projections returns the names of the column projections applied to this table, or nil if no projection is applied
   105  	// and all columns of the schema will be returned.
   106  	Projections() []string
   107  }
   108  
   109  // IndexAddressable is a table that can be scanned through a primary index
   110  type IndexAddressable interface {
   111  	// IndexedAccess returns a table that can perform scans constrained to
   112  	// an IndexLookup on the index given, or nil if the index cannot support
   113  	// the lookup expression.
   114  	IndexedAccess(lookup IndexLookup) IndexedTable
   115  	// GetIndexes returns an array of this table's Indexes
   116  	GetIndexes(ctx *Context) ([]Index, error)
   117  	// PreciseMatch returns whether an indexed access can substitute for filters
   118  	PreciseMatch() bool
   119  }
   120  
   121  // IndexRequired tables cannot be executed without index lookups on certain
   122  // columns. Join planning uses this interface to maintain plan correctness
   123  // for these nodes
   124  type IndexRequired interface {
   125  	IndexAddressable
   126  	// RequiredPredicates returns a list of columns that need IndexedTableAccess
   127  	RequiredPredicates() []string
   128  }
   129  
   130  // IndexAddressableTable is a table that can be accessed through an index
   131  type IndexAddressableTable interface {
   132  	Table
   133  	IndexAddressable
   134  }
   135  
   136  // IndexedTable is a table with an index chosen for range scans
   137  type IndexedTable interface {
   138  	Table
   139  	// LookupPartitions returns partitions scanned by the given IndexLookup
   140  	LookupPartitions(*Context, IndexLookup) (PartitionIter, error)
   141  }
   142  
   143  // IndexAlterableTable represents a table that supports index modification operations.
   144  type IndexAlterableTable interface {
   145  	Table
   146  	// CreateIndex creates an index for this table, using the provided parameters.
   147  	// Returns an error if the index name already exists, or an index with the same columns already exists.
   148  	CreateIndex(ctx *Context, indexDef IndexDef) error
   149  	// DropIndex removes an index from this table, if it exists.
   150  	// Returns an error if the removal failed or the index does not exist.
   151  	DropIndex(ctx *Context, indexName string) error
   152  	// RenameIndex renames an existing index to another name that is not already taken by another index on this table.
   153  	RenameIndex(ctx *Context, fromIndexName string, toIndexName string) error
   154  }
   155  
   156  // IndexBuildingTable is an optional extension to IndexAlterableTable that supports the engine's assistance in building
   157  // a newly created index, or rebuilding an existing one. This interface is non-optional for tables that wish to create
   158  // indexes on virtual columns, as the engine must provide a value for these columns.
   159  type IndexBuildingTable interface {
   160  	IndexAlterableTable
   161  	// ShouldBuildIndex returns whether the given index should be build via BuildIndex. Some indexes require building,
   162  	// in which case this method is not called.
   163  	ShouldBuildIndex(ctx *Context, indexDef IndexDef) (bool, error)
   164  	// BuildIndex returns a RowInserter for that will be passed all existing rows of the table. The returned RowInserter
   165  	// should use the rows provided to populate the newly created index given by the definition. When |Close| is called
   166  	// on the RowInserter, the index should be fully populated and available for further use in the session.
   167  	BuildIndex(ctx *Context, indexDef IndexDef) (RowInserter, error)
   168  }
   169  
   170  // ForeignKeyTable is a table that declares foreign key constraints, and can be referenced by other tables' foreign
   171  // key constraints.
   172  type ForeignKeyTable interface {
   173  	IndexAddressableTable
   174  	// CreateIndexForForeignKey creates an index for this table, using the provided parameters. Indexes created through
   175  	// this function are specifically ones generated for use with a foreign key. Returns an error if the index name
   176  	// already exists, or an index on the same columns already exists.
   177  	CreateIndexForForeignKey(ctx *Context, indexDef IndexDef) error
   178  	// GetDeclaredForeignKeys returns the foreign key constraints that are declared by this table.
   179  	GetDeclaredForeignKeys(ctx *Context) ([]ForeignKeyConstraint, error)
   180  	// GetReferencedForeignKeys returns the foreign key constraints that are referenced by this table.
   181  	GetReferencedForeignKeys(ctx *Context) ([]ForeignKeyConstraint, error)
   182  	// AddForeignKey adds the given foreign key constraint to the table. Returns an error if the foreign key name
   183  	// already exists on any other table within the database.
   184  	AddForeignKey(ctx *Context, fk ForeignKeyConstraint) error
   185  	// DropForeignKey removes a foreign key from the table.
   186  	DropForeignKey(ctx *Context, fkName string) error
   187  	// UpdateForeignKey updates the given foreign key constraint. May range from updated table names to setting the
   188  	// IsResolved boolean.
   189  	UpdateForeignKey(ctx *Context, fkName string, fk ForeignKeyConstraint) error
   190  	// GetForeignKeyEditor returns a ForeignKeyEditor for this table.
   191  	GetForeignKeyEditor(ctx *Context) ForeignKeyEditor
   192  }
   193  
   194  // ForeignKeyEditor is a TableEditor that is addressable via IndexLookup.
   195  type ForeignKeyEditor interface {
   196  	TableEditor
   197  	IndexAddressable
   198  }
   199  
   200  // ReferenceChecker is usually an IndexAddressableTable that does key
   201  // lookups for existence checks. Indicating that the engine is performing
   202  // a reference check lets the integrator avoid expensive deserialization
   203  // steps.
   204  type ReferenceChecker interface {
   205  	SetReferenceCheck() error
   206  }
   207  
   208  // CheckTable is a table that declares check constraints.
   209  type CheckTable interface {
   210  	Table
   211  	// GetChecks returns the check constraints on this table.
   212  	GetChecks(ctx *Context) ([]CheckDefinition, error)
   213  }
   214  
   215  // CheckAlterableTable represents a table that supports check constraints.
   216  type CheckAlterableTable interface {
   217  	Table
   218  	// CreateCheck creates an check constraint for this table, using the provided parameters.
   219  	// Returns an error if the constraint name already exists.
   220  	CreateCheck(ctx *Context, check *CheckDefinition) error
   221  	// DropCheck removes a check constraint from the database.
   222  	DropCheck(ctx *Context, chName string) error
   223  }
   224  
   225  // CollationAlterableTable represents a table that supports the alteration of its collation.
   226  type CollationAlterableTable interface {
   227  	Table
   228  	// ModifyStoredCollation modifies the default collation that is set on the table, along with converting all columns
   229  	// to the given collation (ALTER TABLE ... CONVERT TO CHARACTER SET).
   230  	ModifyStoredCollation(ctx *Context, collation CollationID) error
   231  	// ModifyDefaultCollation modifies the default collation that is set on the table (ALTER TABLE ... COLLATE).
   232  	ModifyDefaultCollation(ctx *Context, collation CollationID) error
   233  }
   234  
   235  // PrimaryKeyTable is a table with a primary key.
   236  type PrimaryKeyTable interface {
   237  	// PrimaryKeySchema returns this table's PrimaryKeySchema
   238  	PrimaryKeySchema() PrimaryKeySchema
   239  }
   240  
   241  // PrimaryKeyAlterableTable represents a table that supports primary key changes.
   242  type PrimaryKeyAlterableTable interface {
   243  	Table
   244  	// CreatePrimaryKey creates a primary key for this table, using the provided parameters.
   245  	// Returns an error if the new primary key set is not compatible with the current table data.
   246  	CreatePrimaryKey(ctx *Context, columns []IndexColumn) error
   247  	// DropPrimaryKey drops a primary key on a table. Returns an error if that table does not have a key.
   248  	DropPrimaryKey(ctx *Context) error
   249  }
   250  
   251  // EditOpenerCloser is the base interface for table editors, and deals with statement boundaries.
   252  type EditOpenerCloser interface {
   253  	// StatementBegin is called before the first operation of a statement. Integrators should mark the state of the data
   254  	// in some way that it may be returned to in the case of an error.
   255  	StatementBegin(ctx *Context)
   256  	// DiscardChanges is called if a statement encounters an error, and all current changes since the statement beginning
   257  	// should be discarded.
   258  	DiscardChanges(ctx *Context, errorEncountered error) error
   259  	// StatementComplete is called after the last operation of the statement, indicating that it has successfully completed.
   260  	// The mark set in StatementBegin may be removed, and a new one should be created on the next StatementBegin.
   261  	StatementComplete(ctx *Context) error
   262  }
   263  
   264  // InsertableTable is a table that can process insertion of new rows.
   265  type InsertableTable interface {
   266  	Table
   267  	// Inserter returns an Inserter for this table. The Inserter will get one call to Insert() for each row to be
   268  	// inserted, and will end with a call to Close() to finalize the insert operation.
   269  	Inserter(*Context) RowInserter
   270  }
   271  
   272  // RowInserter is an insert cursor that can insert one or more values to a table.
   273  type RowInserter interface {
   274  	EditOpenerCloser
   275  	// Insert inserts the row given, returning an error if it cannot. Insert will be called once for each row to process
   276  	// for the insert operation, which may involve many rows. After all rows in an operation have been processed, Close
   277  	// is called.
   278  	Insert(*Context, Row) error
   279  	// Close finalizes the insert operation, persisting its result.
   280  	Closer
   281  }
   282  
   283  // DeletableTable is a table that can delete rows.
   284  type DeletableTable interface {
   285  	Table
   286  	// Deleter returns a RowDeleter for this table. The RowDeleter will get one call to Delete for each row to be deleted,
   287  	// and will end with a call to Close() to finalize the delete operation.
   288  	Deleter(*Context) RowDeleter
   289  }
   290  
   291  // RowDeleter is a delete cursor that can delete one or more rows from a table.
   292  type RowDeleter interface {
   293  	EditOpenerCloser
   294  	// Delete deletes the given row. Returns ErrDeleteRowNotFound if the row was not found. Delete will be called once for
   295  	// each row to process for the delete operation, which may involve many rows. After all rows have been processed,
   296  	// Close is called.
   297  	Delete(*Context, Row) error
   298  	// Closer finalizes the delete operation, persisting the result.
   299  	Closer
   300  }
   301  
   302  // TruncateableTable is a table that can process the deletion of all rows either via a TRUNCATE TABLE statement or a
   303  // DELETE statement without a WHERE clause. This is usually much faster that deleting rows one at a time.
   304  type TruncateableTable interface {
   305  	Table
   306  	// Truncate removes all rows from the table. If the table also implements DeletableTable and it is determined that
   307  	// truncate would be equivalent to a DELETE which spans the entire table, then this function will be called instead.
   308  	// Returns the number of rows that were removed.
   309  	Truncate(*Context) (int, error)
   310  }
   311  
   312  // AutoIncrementTable is a table that supports AUTO_INCREMENT. Getter and Setter methods access the table's
   313  // AUTO_INCREMENT sequence. These methods should only be used for tables with and AUTO_INCREMENT column in their schema.
   314  type AutoIncrementTable interface {
   315  	Table
   316  	// PeekNextAutoIncrementValue returns the next AUTO_INCREMENT value without incrementing the current
   317  	// auto_increment counter.
   318  	PeekNextAutoIncrementValue(ctx *Context) (uint64, error)
   319  	// GetNextAutoIncrementValue gets the next AUTO_INCREMENT value. In the case that a table with an autoincrement
   320  	// column is passed in a row with the autoinc column failed, the next auto increment value must
   321  	// update its internal state accordingly and use the insert val at runtime.
   322  	// Implementations are responsible for updating their state to provide the correct values.
   323  	GetNextAutoIncrementValue(ctx *Context, insertVal interface{}) (uint64, error)
   324  	// AutoIncrementSetter returns an AutoIncrementSetter.
   325  	AutoIncrementSetter(*Context) AutoIncrementSetter
   326  }
   327  
   328  // AutoIncrementSetter provides support for altering a table's
   329  // AUTO_INCREMENT sequence, eg 'ALTER TABLE t AUTO_INCREMENT = 10;'
   330  type AutoIncrementSetter interface {
   331  	// SetAutoIncrementValue sets a new AUTO_INCREMENT value.
   332  	SetAutoIncrementValue(*Context, uint64) error
   333  	// Closer finalizes the set operation, persisting the result.
   334  	Closer
   335  }
   336  
   337  // ReplaceableTable allows rows to be replaced through a Delete (if applicable) then Insert.
   338  type ReplaceableTable interface {
   339  	Table
   340  	// Replacer returns a RowReplacer for this table. The RowReplacer will have Insert and optionally Delete called once
   341  	// for each row, followed by a call to Close() when all rows have been processed.
   342  	Replacer(ctx *Context) RowReplacer
   343  }
   344  
   345  // RowReplacer is a combination of RowDeleter and RowInserter.
   346  type RowReplacer interface {
   347  	EditOpenerCloser
   348  	RowInserter
   349  	RowDeleter
   350  }
   351  
   352  // UpdatableTable is a table that can process updates of existing rows via update statements.
   353  type UpdatableTable interface {
   354  	Table
   355  	// Updater returns a RowUpdater for this table. The RowUpdater will have Update called once for each row to be
   356  	// updated, followed by a call to Close() when all rows have been processed.
   357  	Updater(ctx *Context) RowUpdater
   358  }
   359  
   360  // RowUpdater is an update cursor that can update one or more rows in a table.
   361  type RowUpdater interface {
   362  	EditOpenerCloser
   363  	// Update the given row. Provides both the old and new rows.
   364  	Update(ctx *Context, old Row, new Row) error
   365  	// Closer finalizes the update operation, persisting the result.
   366  	Closer
   367  }
   368  
   369  // TableEditor is the combination of interfaces that allow any table edit operation:
   370  // i.e. INSERT, UPDATE, DELETE, REPLACE
   371  type TableEditor interface {
   372  	RowReplacer
   373  	RowUpdater
   374  }
   375  
   376  // RewritableTable is an extension to Table that makes it simpler for integrators to adapt to schema changes that must
   377  // rewrite every row of the table. In this case, rows are streamed from the existing table in the old schema,
   378  // transformed / updated appropriately, and written with the new format.
   379  type RewritableTable interface {
   380  	Table
   381  	AlterableTable
   382  
   383  	// ShouldRewriteTable returns whether this table should be rewritten because of a schema change. The old and new
   384  	// versions of the schema and modified column are provided. For some operations, one or both of |oldColumn| or
   385  	// |newColumn| may be nil.
   386  	// The engine may decide to rewrite tables regardless in some cases, such as when a new non-nullable column is added.
   387  	ShouldRewriteTable(ctx *Context, oldSchema, newSchema PrimaryKeySchema, oldColumn, newColumn *Column) bool
   388  
   389  	// RewriteInserter returns a RowInserter for the new schema. Rows from the current table, with the old schema, will
   390  	// be streamed from the table and passed to this RowInserter. Implementor tables must still return rows in the
   391  	// current schema until the rewrite operation completes. |Close| will be called on RowInserter when all rows have
   392  	// been inserted.
   393  	RewriteInserter(ctx *Context, oldSchema, newSchema PrimaryKeySchema, oldColumn, newColumn *Column, idxCols []IndexColumn) (RowInserter, error)
   394  }
   395  
   396  // AlterableTable should be implemented by tables that can receive
   397  // ALTER TABLE statements to modify their schemas.
   398  type AlterableTable interface {
   399  	Table
   400  	UpdatableTable
   401  
   402  	// AddColumn adds a column to this table as given. If non-nil, order
   403  	// specifies where in the schema to add the column.
   404  	AddColumn(ctx *Context, column *Column, order *ColumnOrder) error
   405  	// DropColumn drops the column with the name given.
   406  	DropColumn(ctx *Context, columnName string) error
   407  	// ModifyColumn modifies the column with the name given, replacing
   408  	// with the new column definition provided (which may include a name
   409  	// change). If non-nil, order specifies where in the schema to move
   410  	// the column.
   411  	ModifyColumn(ctx *Context, columnName string, column *Column, order *ColumnOrder) error
   412  }
   413  
   414  // SchemaValidator is a database that performs schema compatibility checks
   415  // for CREATE and ALTER TABLE statements.
   416  type SchemaValidator interface {
   417  	Database
   418  	// ValidateSchema lets storage integrators validate whether they can
   419  	// serialize a given schema.
   420  	ValidateSchema(Schema) error
   421  }
   422  
   423  // UnresolvedTable is a Table that is either unresolved or deferred for until an asOf resolution.
   424  // Used by the analyzer during planning, and is not expected to be implemented by integrators.
   425  type UnresolvedTable interface {
   426  	Nameable
   427  	// Database returns the database, which may be unresolved
   428  	Database() Database
   429  	// WithAsOf returns a copy of this versioned table with its AsOf
   430  	// field set to the given value. Analogous to WithChildren.
   431  	WithAsOf(asOf Expression) (Node, error)
   432  	// AsOf returns this table's asof expression.
   433  	AsOf() Expression
   434  }
   435  
   436  // TableNode is an interface for nodes that are also tables. A node that implements this interface exposes all the
   437  // information needed for filters on the table to be optimized into indexes. This is possible when the return value
   438  // of `UnderlyingTable` is a table that implements `sql.IndexAddressable`
   439  // For an example of how to use this interface to optimize a system table or table function, see memory.IntSequenceTable
   440  type TableNode interface {
   441  	Table
   442  	Node
   443  	CollationCoercible
   444  	Databaser
   445  	// UnderlyingTable returns the table that this node is wrapping, recursively unwrapping any further layers of
   446  	// wrapping to get to the base sql.Table.
   447  	UnderlyingTable() Table
   448  }
   449  
   450  // MutableTableNode is a TableNode that can update its underlying table. Different methods are provided to accommodate
   451  // different use cases that require working with base-level tables v. wrappers on top of them. Some uses of these
   452  // methods might require that return values that implement all the same subinterfaces as the wrapped table, e.g.
   453  // IndexedTable, ProjectableTable, etc. Callers of these methods should verify that the MutableTableNode's
   454  // new table respects this contract.
   455  type MutableTableNode interface {
   456  	TableNode
   457  	// WithTable returns a new TableNode with the table given. If the MutableTableNode has a MutableTableWrapper, it must
   458  	// re-wrap the table given with this wrapper.
   459  	WithTable(Table) (MutableTableNode, error)
   460  	// ReplaceTable replaces the table with the table given, with no re-wrapping semantics.
   461  	ReplaceTable(table Table) (MutableTableNode, error)
   462  	// WrappedTable returns the Table this node wraps, without unwinding any additional layers of wrapped tables.
   463  	WrappedTable() Table
   464  }
   465  
   466  // IndexSearchable lets a node use custom logic to create
   467  // *plan.IndexedTableAccess
   468  type IndexSearchable interface {
   469  	// SkipIndexCosting defers to an integrator for provide a suitable
   470  	// index lookup.
   471  	SkipIndexCosting() bool
   472  	// LookupForExpressions returns an sql.IndexLookup for an expression
   473  	// set.
   474  	LookupForExpressions(*Context, []Expression) (IndexLookup, error)
   475  }
   476  
   477  // IndexSearchableTable is a Table supports custom index generation.
   478  type IndexSearchableTable interface {
   479  	IndexAddressableTable
   480  	IndexSearchable
   481  }