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 }