Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/sqlalchemy/sql/schema.py: 40%

Shortcuts on this page

r m x   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

1656 statements  

1# sql/schema.py 

2# Copyright (C) 2005-2024 the SQLAlchemy authors and contributors 

3# <see AUTHORS file> 

4# 

5# This module is part of SQLAlchemy and is released under 

6# the MIT License: https://www.opensource.org/licenses/mit-license.php 

7 

8"""The schema module provides the building blocks for database metadata. 

9 

10Each element within this module describes a database entity which can be 

11created and dropped, or is otherwise part of such an entity. Examples include 

12tables, columns, sequences, and indexes. 

13 

14All entities are subclasses of :class:`~sqlalchemy.schema.SchemaItem`, and as 

15defined in this module they are intended to be agnostic of any vendor-specific 

16constructs. 

17 

18A collection of entities are grouped into a unit called 

19:class:`~sqlalchemy.schema.MetaData`. MetaData serves as a logical grouping of 

20schema elements, and can also be associated with an actual database connection 

21such that operations involving the contained elements can contact the database 

22as needed. 

23 

24Two of the elements here also build upon their "syntactic" counterparts, which 

25are defined in :class:`~sqlalchemy.sql.expression.`, specifically 

26:class:`~sqlalchemy.schema.Table` and :class:`~sqlalchemy.schema.Column`. 

27Since these objects are part of the SQL expression language, they are usable 

28as components in SQL expressions. 

29 

30""" 

31from __future__ import annotations 

32 

33from abc import ABC 

34import collections 

35from enum import Enum 

36import operator 

37import typing 

38from typing import Any 

39from typing import Callable 

40from typing import cast 

41from typing import Collection 

42from typing import Dict 

43from typing import Final 

44from typing import Iterable 

45from typing import Iterator 

46from typing import List 

47from typing import Mapping 

48from typing import NoReturn 

49from typing import Optional 

50from typing import overload 

51from typing import Protocol 

52from typing import Sequence as _typing_Sequence 

53from typing import Set 

54from typing import Tuple 

55from typing import TYPE_CHECKING 

56from typing import TypedDict 

57from typing import TypeVar 

58from typing import Union 

59 

60from . import coercions 

61from . import ddl 

62from . import roles 

63from . import type_api 

64from . import visitors 

65from .base import _DefaultDescriptionTuple 

66from .base import _NoArg 

67from .base import _NoneName 

68from .base import _SentinelColumnCharacterization 

69from .base import _SentinelDefaultCharacterization 

70from .base import DedupeColumnCollection 

71from .base import DialectKWArgs 

72from .base import Executable 

73from .base import SchemaEventTarget as SchemaEventTarget 

74from .coercions import _document_text_coercion 

75from .elements import ClauseElement 

76from .elements import ColumnClause 

77from .elements import ColumnElement 

78from .elements import quoted_name 

79from .elements import TextClause 

80from .selectable import TableClause 

81from .type_api import to_instance 

82from .visitors import ExternallyTraversible 

83from .. import event 

84from .. import exc 

85from .. import inspection 

86from .. import util 

87from ..util import HasMemoized 

88from ..util.typing import Literal 

89from ..util.typing import Self 

90from ..util.typing import TypeGuard 

91 

92if typing.TYPE_CHECKING: 

93 from ._typing import _AutoIncrementType 

94 from ._typing import _DDLColumnArgument 

95 from ._typing import _DDLColumnReferenceArgument 

96 from ._typing import _InfoType 

97 from ._typing import _TextCoercedExpressionArgument 

98 from ._typing import _TypeEngineArgument 

99 from .base import ReadOnlyColumnCollection 

100 from .compiler import DDLCompiler 

101 from .elements import BindParameter 

102 from .functions import Function 

103 from .type_api import TypeEngine 

104 from .visitors import anon_map 

105 from ..engine import Connection 

106 from ..engine import Engine 

107 from ..engine.interfaces import _CoreMultiExecuteParams 

108 from ..engine.interfaces import CoreExecuteOptionsParameter 

109 from ..engine.interfaces import ExecutionContext 

110 from ..engine.mock import MockConnection 

111 from ..engine.reflection import _ReflectionInfo 

112 from ..sql.selectable import FromClause 

113 

114_T = TypeVar("_T", bound="Any") 

115_SI = TypeVar("_SI", bound="SchemaItem") 

116_TAB = TypeVar("_TAB", bound="Table") 

117 

118 

119_CreateDropBind = Union["Engine", "Connection", "MockConnection"] 

120 

121_ConstraintNameArgument = Optional[Union[str, _NoneName]] 

122 

123_ServerDefaultArgument = Union[ 

124 "FetchedValue", str, TextClause, ColumnElement[Any] 

125] 

126 

127_ServerOnUpdateArgument = _ServerDefaultArgument 

128 

129 

130class SchemaConst(Enum): 

131 RETAIN_SCHEMA = 1 

132 """Symbol indicating that a :class:`_schema.Table`, :class:`.Sequence` 

133 or in some cases a :class:`_schema.ForeignKey` object, in situations 

134 where the object is being copied for a :meth:`.Table.to_metadata` 

135 operation, should retain the schema name that it already has. 

136 

137 """ 

138 

139 BLANK_SCHEMA = 2 

140 """Symbol indicating that a :class:`_schema.Table` or :class:`.Sequence` 

141 should have 'None' for its schema, even if the parent 

142 :class:`_schema.MetaData` has specified a schema. 

143 

144 .. seealso:: 

145 

146 :paramref:`_schema.MetaData.schema` 

147 

148 :paramref:`_schema.Table.schema` 

149 

150 :paramref:`.Sequence.schema` 

151 

152 """ 

153 

154 NULL_UNSPECIFIED = 3 

155 """Symbol indicating the "nullable" keyword was not passed to a Column. 

156 

157 This is used to distinguish between the use case of passing 

158 ``nullable=None`` to a :class:`.Column`, which has special meaning 

159 on some backends such as SQL Server. 

160 

161 """ 

162 

163 

164RETAIN_SCHEMA: Final[Literal[SchemaConst.RETAIN_SCHEMA]] = ( 

165 SchemaConst.RETAIN_SCHEMA 

166) 

167BLANK_SCHEMA: Final[Literal[SchemaConst.BLANK_SCHEMA]] = ( 

168 SchemaConst.BLANK_SCHEMA 

169) 

170NULL_UNSPECIFIED: Final[Literal[SchemaConst.NULL_UNSPECIFIED]] = ( 

171 SchemaConst.NULL_UNSPECIFIED 

172) 

173 

174 

175def _get_table_key(name: str, schema: Optional[str]) -> str: 

176 if schema is None: 

177 return name 

178 else: 

179 return schema + "." + name 

180 

181 

182# this should really be in sql/util.py but we'd have to 

183# break an import cycle 

184def _copy_expression( 

185 expression: ColumnElement[Any], 

186 source_table: Optional[Table], 

187 target_table: Optional[Table], 

188) -> ColumnElement[Any]: 

189 if source_table is None or target_table is None: 

190 return expression 

191 

192 fixed_source_table = source_table 

193 fixed_target_table = target_table 

194 

195 def replace( 

196 element: ExternallyTraversible, **kw: Any 

197 ) -> Optional[ExternallyTraversible]: 

198 if ( 

199 isinstance(element, Column) 

200 and element.table is fixed_source_table 

201 and element.key in fixed_source_table.c 

202 ): 

203 return fixed_target_table.c[element.key] 

204 else: 

205 return None 

206 

207 return cast( 

208 ColumnElement[Any], 

209 visitors.replacement_traverse(expression, {}, replace), 

210 ) 

211 

212 

213@inspection._self_inspects 

214class SchemaItem(SchemaEventTarget, visitors.Visitable): 

215 """Base class for items that define a database schema.""" 

216 

217 __visit_name__ = "schema_item" 

218 

219 create_drop_stringify_dialect = "default" 

220 

221 def _init_items(self, *args: SchemaItem, **kw: Any) -> None: 

222 """Initialize the list of child items for this SchemaItem.""" 

223 for item in args: 

224 if item is not None: 

225 try: 

226 spwd = item._set_parent_with_dispatch 

227 except AttributeError as err: 

228 raise exc.ArgumentError( 

229 "'SchemaItem' object, such as a 'Column' or a " 

230 f"'Constraint' expected, got {item!r}" 

231 ) from err 

232 else: 

233 spwd(self, **kw) 

234 

235 def __repr__(self) -> str: 

236 return util.generic_repr(self, omit_kwarg=["info"]) 

237 

238 @util.memoized_property 

239 def info(self) -> _InfoType: 

240 """Info dictionary associated with the object, allowing user-defined 

241 data to be associated with this :class:`.SchemaItem`. 

242 

243 The dictionary is automatically generated when first accessed. 

244 It can also be specified in the constructor of some objects, 

245 such as :class:`_schema.Table` and :class:`_schema.Column`. 

246 

247 """ 

248 return {} 

249 

250 def _schema_item_copy(self, schema_item: _SI) -> _SI: 

251 if "info" in self.__dict__: 

252 schema_item.info = self.info.copy() 

253 schema_item.dispatch._update(self.dispatch) 

254 return schema_item 

255 

256 _use_schema_map = True 

257 

258 

259class HasConditionalDDL: 

260 """define a class that includes the :meth:`.HasConditionalDDL.ddl_if` 

261 method, allowing for conditional rendering of DDL. 

262 

263 Currently applies to constraints and indexes. 

264 

265 .. versionadded:: 2.0 

266 

267 

268 """ 

269 

270 _ddl_if: Optional[ddl.DDLIf] = None 

271 

272 def ddl_if( 

273 self, 

274 dialect: Optional[str] = None, 

275 callable_: Optional[ddl.DDLIfCallable] = None, 

276 state: Optional[Any] = None, 

277 ) -> Self: 

278 r"""apply a conditional DDL rule to this schema item. 

279 

280 These rules work in a similar manner to the 

281 :meth:`.ExecutableDDLElement.execute_if` callable, with the added 

282 feature that the criteria may be checked within the DDL compilation 

283 phase for a construct such as :class:`.CreateTable`. 

284 :meth:`.HasConditionalDDL.ddl_if` currently applies towards the 

285 :class:`.Index` construct as well as all :class:`.Constraint` 

286 constructs. 

287 

288 :param dialect: string name of a dialect, or a tuple of string names 

289 to indicate multiple dialect types. 

290 

291 :param callable\_: a callable that is constructed using the same form 

292 as that described in 

293 :paramref:`.ExecutableDDLElement.execute_if.callable_`. 

294 

295 :param state: any arbitrary object that will be passed to the 

296 callable, if present. 

297 

298 .. versionadded:: 2.0 

299 

300 .. seealso:: 

301 

302 :ref:`schema_ddl_ddl_if` - background and usage examples 

303 

304 

305 """ 

306 self._ddl_if = ddl.DDLIf(dialect, callable_, state) 

307 return self 

308 

309 

310class HasSchemaAttr(SchemaItem): 

311 """schema item that includes a top-level schema name""" 

312 

313 schema: Optional[str] 

314 

315 

316class Table( 

317 DialectKWArgs, HasSchemaAttr, TableClause, inspection.Inspectable["Table"] 

318): 

319 r"""Represent a table in a database. 

320 

321 e.g.:: 

322 

323 mytable = Table( 

324 "mytable", metadata, 

325 Column('mytable_id', Integer, primary_key=True), 

326 Column('value', String(50)) 

327 ) 

328 

329 The :class:`_schema.Table` 

330 object constructs a unique instance of itself based 

331 on its name and optional schema name within the given 

332 :class:`_schema.MetaData` object. Calling the :class:`_schema.Table` 

333 constructor with the same name and same :class:`_schema.MetaData` argument 

334 a second time will return the *same* :class:`_schema.Table` 

335 object - in this way 

336 the :class:`_schema.Table` constructor acts as a registry function. 

337 

338 .. seealso:: 

339 

340 :ref:`metadata_describing` - Introduction to database metadata 

341 

342 """ 

343 

344 __visit_name__ = "table" 

345 

346 if TYPE_CHECKING: 

347 

348 @util.ro_non_memoized_property 

349 def primary_key(self) -> PrimaryKeyConstraint: ... 

350 

351 @util.ro_non_memoized_property 

352 def foreign_keys(self) -> Set[ForeignKey]: ... 

353 

354 _columns: DedupeColumnCollection[Column[Any]] 

355 

356 _sentinel_column: Optional[Column[Any]] 

357 

358 constraints: Set[Constraint] 

359 """A collection of all :class:`_schema.Constraint` objects associated with 

360 this :class:`_schema.Table`. 

361 

362 Includes :class:`_schema.PrimaryKeyConstraint`, 

363 :class:`_schema.ForeignKeyConstraint`, :class:`_schema.UniqueConstraint`, 

364 :class:`_schema.CheckConstraint`. A separate collection 

365 :attr:`_schema.Table.foreign_key_constraints` refers to the collection 

366 of all :class:`_schema.ForeignKeyConstraint` objects, and the 

367 :attr:`_schema.Table.primary_key` attribute refers to the single 

368 :class:`_schema.PrimaryKeyConstraint` associated with the 

369 :class:`_schema.Table`. 

370 

371 .. seealso:: 

372 

373 :attr:`_schema.Table.constraints` 

374 

375 :attr:`_schema.Table.primary_key` 

376 

377 :attr:`_schema.Table.foreign_key_constraints` 

378 

379 :attr:`_schema.Table.indexes` 

380 

381 :class:`_reflection.Inspector` 

382 

383 

384 """ 

385 

386 indexes: Set[Index] 

387 """A collection of all :class:`_schema.Index` objects associated with this 

388 :class:`_schema.Table`. 

389 

390 .. seealso:: 

391 

392 :meth:`_reflection.Inspector.get_indexes` 

393 

394 """ 

395 

396 if TYPE_CHECKING: 

397 

398 @util.ro_non_memoized_property 

399 def columns(self) -> ReadOnlyColumnCollection[str, Column[Any]]: ... 

400 

401 @util.ro_non_memoized_property 

402 def exported_columns( 

403 self, 

404 ) -> ReadOnlyColumnCollection[str, Column[Any]]: ... 

405 

406 @util.ro_non_memoized_property 

407 def c(self) -> ReadOnlyColumnCollection[str, Column[Any]]: ... 

408 

409 def _gen_cache_key( 

410 self, anon_map: anon_map, bindparams: List[BindParameter[Any]] 

411 ) -> Tuple[Any, ...]: 

412 if self._annotations: 

413 return (self,) + self._annotations_cache_key 

414 else: 

415 return (self,) 

416 

417 if not typing.TYPE_CHECKING: 

418 # typing tools seem to be inconsistent in how they handle 

419 # __new__, so suggest this pattern for classes that use 

420 # __new__. apply typing to the __init__ method normally 

421 @util.deprecated_params( 

422 mustexist=( 

423 "1.4", 

424 "Deprecated alias of :paramref:`_schema.Table.must_exist`", 

425 ), 

426 ) 

427 def __new__(cls, *args: Any, **kw: Any) -> Any: 

428 return cls._new(*args, **kw) 

429 

430 @classmethod 

431 def _new(cls, *args: Any, **kw: Any) -> Any: 

432 if not args and not kw: 

433 # python3k pickle seems to call this 

434 return object.__new__(cls) 

435 

436 try: 

437 name, metadata, args = args[0], args[1], args[2:] 

438 except IndexError: 

439 raise TypeError( 

440 "Table() takes at least two positional-only " 

441 "arguments 'name' and 'metadata'" 

442 ) 

443 

444 schema = kw.get("schema", None) 

445 if schema is None: 

446 schema = metadata.schema 

447 elif schema is BLANK_SCHEMA: 

448 schema = None 

449 keep_existing = kw.get("keep_existing", False) 

450 extend_existing = kw.get("extend_existing", False) 

451 

452 if keep_existing and extend_existing: 

453 msg = "keep_existing and extend_existing are mutually exclusive." 

454 raise exc.ArgumentError(msg) 

455 

456 must_exist = kw.pop("must_exist", kw.pop("mustexist", False)) 

457 key = _get_table_key(name, schema) 

458 if key in metadata.tables: 

459 if not keep_existing and not extend_existing and bool(args): 

460 raise exc.InvalidRequestError( 

461 f"Table '{key}' is already defined for this MetaData " 

462 "instance. Specify 'extend_existing=True' " 

463 "to redefine " 

464 "options and columns on an " 

465 "existing Table object." 

466 ) 

467 table = metadata.tables[key] 

468 if extend_existing: 

469 table._init_existing(*args, **kw) 

470 return table 

471 else: 

472 if must_exist: 

473 raise exc.InvalidRequestError(f"Table '{key}' not defined") 

474 table = object.__new__(cls) 

475 table.dispatch.before_parent_attach(table, metadata) 

476 metadata._add_table(name, schema, table) 

477 try: 

478 table.__init__(name, metadata, *args, _no_init=False, **kw) 

479 table.dispatch.after_parent_attach(table, metadata) 

480 return table 

481 except Exception: 

482 with util.safe_reraise(): 

483 metadata._remove_table(name, schema) 

484 

485 def __init__( 

486 self, 

487 name: str, 

488 metadata: MetaData, 

489 *args: SchemaItem, 

490 schema: Optional[Union[str, Literal[SchemaConst.BLANK_SCHEMA]]] = None, 

491 quote: Optional[bool] = None, 

492 quote_schema: Optional[bool] = None, 

493 autoload_with: Optional[Union[Engine, Connection]] = None, 

494 autoload_replace: bool = True, 

495 keep_existing: bool = False, 

496 extend_existing: bool = False, 

497 resolve_fks: bool = True, 

498 include_columns: Optional[Collection[str]] = None, 

499 implicit_returning: bool = True, 

500 comment: Optional[str] = None, 

501 info: Optional[Dict[Any, Any]] = None, 

502 listeners: Optional[ 

503 _typing_Sequence[Tuple[str, Callable[..., Any]]] 

504 ] = None, 

505 prefixes: Optional[_typing_Sequence[str]] = None, 

506 # used internally in the metadata.reflect() process 

507 _extend_on: Optional[Set[Table]] = None, 

508 # used by __new__ to bypass __init__ 

509 _no_init: bool = True, 

510 # dialect-specific keyword args 

511 **kw: Any, 

512 ) -> None: 

513 r"""Constructor for :class:`_schema.Table`. 

514 

515 

516 :param name: The name of this table as represented in the database. 

517 

518 The table name, along with the value of the ``schema`` parameter, 

519 forms a key which uniquely identifies this :class:`_schema.Table` 

520 within 

521 the owning :class:`_schema.MetaData` collection. 

522 Additional calls to :class:`_schema.Table` with the same name, 

523 metadata, 

524 and schema name will return the same :class:`_schema.Table` object. 

525 

526 Names which contain no upper case characters 

527 will be treated as case insensitive names, and will not be quoted 

528 unless they are a reserved word or contain special characters. 

529 A name with any number of upper case characters is considered 

530 to be case sensitive, and will be sent as quoted. 

531 

532 To enable unconditional quoting for the table name, specify the flag 

533 ``quote=True`` to the constructor, or use the :class:`.quoted_name` 

534 construct to specify the name. 

535 

536 :param metadata: a :class:`_schema.MetaData` 

537 object which will contain this 

538 table. The metadata is used as a point of association of this table 

539 with other tables which are referenced via foreign key. It also 

540 may be used to associate this table with a particular 

541 :class:`.Connection` or :class:`.Engine`. 

542 

543 :param \*args: Additional positional arguments are used primarily 

544 to add the list of :class:`_schema.Column` 

545 objects contained within this 

546 table. Similar to the style of a CREATE TABLE statement, other 

547 :class:`.SchemaItem` constructs may be added here, including 

548 :class:`.PrimaryKeyConstraint`, and 

549 :class:`_schema.ForeignKeyConstraint`. 

550 

551 :param autoload_replace: Defaults to ``True``; when using 

552 :paramref:`_schema.Table.autoload_with` 

553 in conjunction with :paramref:`_schema.Table.extend_existing`, 

554 indicates 

555 that :class:`_schema.Column` objects present in the already-existing 

556 :class:`_schema.Table` 

557 object should be replaced with columns of the same 

558 name retrieved from the autoload process. When ``False``, columns 

559 already present under existing names will be omitted from the 

560 reflection process. 

561 

562 Note that this setting does not impact :class:`_schema.Column` objects 

563 specified programmatically within the call to :class:`_schema.Table` 

564 that 

565 also is autoloading; those :class:`_schema.Column` objects will always 

566 replace existing columns of the same name when 

567 :paramref:`_schema.Table.extend_existing` is ``True``. 

568 

569 .. seealso:: 

570 

571 :paramref:`_schema.Table.autoload_with` 

572 

573 :paramref:`_schema.Table.extend_existing` 

574 

575 :param autoload_with: An :class:`_engine.Engine` or 

576 :class:`_engine.Connection` object, 

577 or a :class:`_reflection.Inspector` object as returned by 

578 :func:`_sa.inspect` 

579 against one, with which this :class:`_schema.Table` 

580 object will be reflected. 

581 When set to a non-None value, the autoload process will take place 

582 for this table against the given engine or connection. 

583 

584 .. seealso:: 

585 

586 :ref:`metadata_reflection_toplevel` 

587 

588 :meth:`_events.DDLEvents.column_reflect` 

589 

590 :ref:`metadata_reflection_dbagnostic_types` 

591 

592 :param extend_existing: When ``True``, indicates that if this 

593 :class:`_schema.Table` is already present in the given 

594 :class:`_schema.MetaData`, 

595 apply further arguments within the constructor to the existing 

596 :class:`_schema.Table`. 

597 

598 If :paramref:`_schema.Table.extend_existing` or 

599 :paramref:`_schema.Table.keep_existing` are not set, 

600 and the given name 

601 of the new :class:`_schema.Table` refers to a :class:`_schema.Table` 

602 that is 

603 already present in the target :class:`_schema.MetaData` collection, 

604 and 

605 this :class:`_schema.Table` 

606 specifies additional columns or other constructs 

607 or flags that modify the table's state, an 

608 error is raised. The purpose of these two mutually-exclusive flags 

609 is to specify what action should be taken when a 

610 :class:`_schema.Table` 

611 is specified that matches an existing :class:`_schema.Table`, 

612 yet specifies 

613 additional constructs. 

614 

615 :paramref:`_schema.Table.extend_existing` 

616 will also work in conjunction 

617 with :paramref:`_schema.Table.autoload_with` to run a new reflection 

618 operation against the database, even if a :class:`_schema.Table` 

619 of the same name is already present in the target 

620 :class:`_schema.MetaData`; newly reflected :class:`_schema.Column` 

621 objects 

622 and other options will be added into the state of the 

623 :class:`_schema.Table`, potentially overwriting existing columns 

624 and options of the same name. 

625 

626 As is always the case with :paramref:`_schema.Table.autoload_with`, 

627 :class:`_schema.Column` objects can be specified in the same 

628 :class:`_schema.Table` 

629 constructor, which will take precedence. Below, the existing 

630 table ``mytable`` will be augmented with :class:`_schema.Column` 

631 objects 

632 both reflected from the database, as well as the given 

633 :class:`_schema.Column` 

634 named "y":: 

635 

636 Table("mytable", metadata, 

637 Column('y', Integer), 

638 extend_existing=True, 

639 autoload_with=engine 

640 ) 

641 

642 .. seealso:: 

643 

644 :paramref:`_schema.Table.autoload_with` 

645 

646 :paramref:`_schema.Table.autoload_replace` 

647 

648 :paramref:`_schema.Table.keep_existing` 

649 

650 

651 :param implicit_returning: True by default - indicates that 

652 RETURNING can be used, typically by the ORM, in order to fetch 

653 server-generated values such as primary key values and 

654 server side defaults, on those backends which support RETURNING. 

655 

656 In modern SQLAlchemy there is generally no reason to alter this 

657 setting, except for some backend specific cases 

658 (see :ref:`mssql_triggers` in the SQL Server dialect documentation 

659 for one such example). 

660 

661 :param include_columns: A list of strings indicating a subset of 

662 columns to be loaded via the ``autoload`` operation; table columns who 

663 aren't present in this list will not be represented on the resulting 

664 ``Table`` object. Defaults to ``None`` which indicates all columns 

665 should be reflected. 

666 

667 :param resolve_fks: Whether or not to reflect :class:`_schema.Table` 

668 objects 

669 related to this one via :class:`_schema.ForeignKey` objects, when 

670 :paramref:`_schema.Table.autoload_with` is 

671 specified. Defaults to True. Set to False to disable reflection of 

672 related tables as :class:`_schema.ForeignKey` 

673 objects are encountered; may be 

674 used either to save on SQL calls or to avoid issues with related tables 

675 that can't be accessed. Note that if a related table is already present 

676 in the :class:`_schema.MetaData` collection, or becomes present later, 

677 a 

678 :class:`_schema.ForeignKey` object associated with this 

679 :class:`_schema.Table` will 

680 resolve to that table normally. 

681 

682 .. versionadded:: 1.3 

683 

684 .. seealso:: 

685 

686 :paramref:`.MetaData.reflect.resolve_fks` 

687 

688 

689 :param info: Optional data dictionary which will be populated into the 

690 :attr:`.SchemaItem.info` attribute of this object. 

691 

692 :param keep_existing: When ``True``, indicates that if this Table 

693 is already present in the given :class:`_schema.MetaData`, ignore 

694 further arguments within the constructor to the existing 

695 :class:`_schema.Table`, and return the :class:`_schema.Table` 

696 object as 

697 originally created. This is to allow a function that wishes 

698 to define a new :class:`_schema.Table` on first call, but on 

699 subsequent calls will return the same :class:`_schema.Table`, 

700 without any of the declarations (particularly constraints) 

701 being applied a second time. 

702 

703 If :paramref:`_schema.Table.extend_existing` or 

704 :paramref:`_schema.Table.keep_existing` are not set, 

705 and the given name 

706 of the new :class:`_schema.Table` refers to a :class:`_schema.Table` 

707 that is 

708 already present in the target :class:`_schema.MetaData` collection, 

709 and 

710 this :class:`_schema.Table` 

711 specifies additional columns or other constructs 

712 or flags that modify the table's state, an 

713 error is raised. The purpose of these two mutually-exclusive flags 

714 is to specify what action should be taken when a 

715 :class:`_schema.Table` 

716 is specified that matches an existing :class:`_schema.Table`, 

717 yet specifies 

718 additional constructs. 

719 

720 .. seealso:: 

721 

722 :paramref:`_schema.Table.extend_existing` 

723 

724 :param listeners: A list of tuples of the form ``(<eventname>, <fn>)`` 

725 which will be passed to :func:`.event.listen` upon construction. 

726 This alternate hook to :func:`.event.listen` allows the establishment 

727 of a listener function specific to this :class:`_schema.Table` before 

728 the "autoload" process begins. Historically this has been intended 

729 for use with the :meth:`.DDLEvents.column_reflect` event, however 

730 note that this event hook may now be associated with the 

731 :class:`_schema.MetaData` object directly:: 

732 

733 def listen_for_reflect(table, column_info): 

734 "handle the column reflection event" 

735 # ... 

736 

737 t = Table( 

738 'sometable', 

739 autoload_with=engine, 

740 listeners=[ 

741 ('column_reflect', listen_for_reflect) 

742 ]) 

743 

744 .. seealso:: 

745 

746 :meth:`_events.DDLEvents.column_reflect` 

747 

748 :param must_exist: When ``True``, indicates that this Table must already 

749 be present in the given :class:`_schema.MetaData` collection, else 

750 an exception is raised. 

751 

752 :param prefixes: 

753 A list of strings to insert after CREATE in the CREATE TABLE 

754 statement. They will be separated by spaces. 

755 

756 :param quote: Force quoting of this table's name on or off, corresponding 

757 to ``True`` or ``False``. When left at its default of ``None``, 

758 the column identifier will be quoted according to whether the name is 

759 case sensitive (identifiers with at least one upper case character are 

760 treated as case sensitive), or if it's a reserved word. This flag 

761 is only needed to force quoting of a reserved word which is not known 

762 by the SQLAlchemy dialect. 

763 

764 .. note:: setting this flag to ``False`` will not provide 

765 case-insensitive behavior for table reflection; table reflection 

766 will always search for a mixed-case name in a case sensitive 

767 fashion. Case insensitive names are specified in SQLAlchemy only 

768 by stating the name with all lower case characters. 

769 

770 :param quote_schema: same as 'quote' but applies to the schema identifier. 

771 

772 :param schema: The schema name for this table, which is required if 

773 the table resides in a schema other than the default selected schema 

774 for the engine's database connection. Defaults to ``None``. 

775 

776 If the owning :class:`_schema.MetaData` of this :class:`_schema.Table` 

777 specifies its 

778 own :paramref:`_schema.MetaData.schema` parameter, 

779 then that schema name will 

780 be applied to this :class:`_schema.Table` 

781 if the schema parameter here is set 

782 to ``None``. To set a blank schema name on a :class:`_schema.Table` 

783 that 

784 would otherwise use the schema set on the owning 

785 :class:`_schema.MetaData`, 

786 specify the special symbol :attr:`.BLANK_SCHEMA`. 

787 

788 The quoting rules for the schema name are the same as those for the 

789 ``name`` parameter, in that quoting is applied for reserved words or 

790 case-sensitive names; to enable unconditional quoting for the schema 

791 name, specify the flag ``quote_schema=True`` to the constructor, or use 

792 the :class:`.quoted_name` construct to specify the name. 

793 

794 :param comment: Optional string that will render an SQL comment on table 

795 creation. 

796 

797 .. versionadded:: 1.2 Added the :paramref:`_schema.Table.comment` 

798 parameter 

799 to :class:`_schema.Table`. 

800 

801 :param \**kw: Additional keyword arguments not mentioned above are 

802 dialect specific, and passed in the form ``<dialectname>_<argname>``. 

803 See the documentation regarding an individual dialect at 

804 :ref:`dialect_toplevel` for detail on documented arguments. 

805 

806 """ # noqa: E501 

807 if _no_init: 

808 # don't run __init__ from __new__ by default; 

809 # __new__ has a specific place that __init__ is called 

810 return 

811 

812 super().__init__(quoted_name(name, quote)) 

813 self.metadata = metadata 

814 

815 if schema is None: 

816 self.schema = metadata.schema 

817 elif schema is BLANK_SCHEMA: 

818 self.schema = None 

819 else: 

820 quote_schema = quote_schema 

821 assert isinstance(schema, str) 

822 self.schema = quoted_name(schema, quote_schema) 

823 

824 self._sentinel_column = None 

825 

826 self.indexes = set() 

827 self.constraints = set() 

828 PrimaryKeyConstraint( 

829 _implicit_generated=True 

830 )._set_parent_with_dispatch(self) 

831 self.foreign_keys = set() # type: ignore 

832 self._extra_dependencies: Set[Table] = set() 

833 if self.schema is not None: 

834 self.fullname = "%s.%s" % (self.schema, self.name) 

835 else: 

836 self.fullname = self.name 

837 

838 self.implicit_returning = implicit_returning 

839 _reflect_info = kw.pop("_reflect_info", None) 

840 

841 self.comment = comment 

842 

843 if info is not None: 

844 self.info = info 

845 

846 if listeners is not None: 

847 for evt, fn in listeners: 

848 event.listen(self, evt, fn) 

849 

850 self._prefixes = prefixes if prefixes else [] 

851 

852 self._extra_kwargs(**kw) 

853 

854 # load column definitions from the database if 'autoload' is defined 

855 # we do it after the table is in the singleton dictionary to support 

856 # circular foreign keys 

857 if autoload_with is not None: 

858 self._autoload( 

859 metadata, 

860 autoload_with, 

861 include_columns, 

862 _extend_on=_extend_on, 

863 _reflect_info=_reflect_info, 

864 resolve_fks=resolve_fks, 

865 ) 

866 

867 # initialize all the column, etc. objects. done after reflection to 

868 # allow user-overrides 

869 

870 self._init_items( 

871 *args, 

872 allow_replacements=extend_existing 

873 or keep_existing 

874 or autoload_with, 

875 all_names={}, 

876 ) 

877 

878 def _autoload( 

879 self, 

880 metadata: MetaData, 

881 autoload_with: Union[Engine, Connection], 

882 include_columns: Optional[Collection[str]], 

883 exclude_columns: Collection[str] = (), 

884 resolve_fks: bool = True, 

885 _extend_on: Optional[Set[Table]] = None, 

886 _reflect_info: _ReflectionInfo | None = None, 

887 ) -> None: 

888 insp = inspection.inspect(autoload_with) 

889 with insp._inspection_context() as conn_insp: 

890 conn_insp.reflect_table( 

891 self, 

892 include_columns, 

893 exclude_columns, 

894 resolve_fks, 

895 _extend_on=_extend_on, 

896 _reflect_info=_reflect_info, 

897 ) 

898 

899 @property 

900 def _sorted_constraints(self) -> List[Constraint]: 

901 """Return the set of constraints as a list, sorted by creation 

902 order. 

903 

904 """ 

905 

906 return sorted(self.constraints, key=lambda c: c._creation_order) 

907 

908 @property 

909 def foreign_key_constraints(self) -> Set[ForeignKeyConstraint]: 

910 """:class:`_schema.ForeignKeyConstraint` objects referred to by this 

911 :class:`_schema.Table`. 

912 

913 This list is produced from the collection of 

914 :class:`_schema.ForeignKey` 

915 objects currently associated. 

916 

917 

918 .. seealso:: 

919 

920 :attr:`_schema.Table.constraints` 

921 

922 :attr:`_schema.Table.foreign_keys` 

923 

924 :attr:`_schema.Table.indexes` 

925 

926 """ 

927 return { 

928 fkc.constraint 

929 for fkc in self.foreign_keys 

930 if fkc.constraint is not None 

931 } 

932 

933 def _init_existing(self, *args: Any, **kwargs: Any) -> None: 

934 autoload_with = kwargs.pop("autoload_with", None) 

935 autoload = kwargs.pop("autoload", autoload_with is not None) 

936 autoload_replace = kwargs.pop("autoload_replace", True) 

937 schema = kwargs.pop("schema", None) 

938 _extend_on = kwargs.pop("_extend_on", None) 

939 _reflect_info = kwargs.pop("_reflect_info", None) 

940 

941 # these arguments are only used with _init() 

942 extend_existing = kwargs.pop("extend_existing", False) 

943 keep_existing = kwargs.pop("keep_existing", False) 

944 

945 assert extend_existing 

946 assert not keep_existing 

947 

948 if schema and schema != self.schema: 

949 raise exc.ArgumentError( 

950 f"Can't change schema of existing table " 

951 f"from '{self.schema}' to '{schema}'", 

952 ) 

953 

954 include_columns = kwargs.pop("include_columns", None) 

955 if include_columns is not None: 

956 for c in self.c: 

957 if c.name not in include_columns: 

958 self._columns.remove(c) 

959 

960 resolve_fks = kwargs.pop("resolve_fks", True) 

961 

962 for key in ("quote", "quote_schema"): 

963 if key in kwargs: 

964 raise exc.ArgumentError( 

965 "Can't redefine 'quote' or 'quote_schema' arguments" 

966 ) 

967 

968 # update `self` with these kwargs, if provided 

969 self.comment = kwargs.pop("comment", self.comment) 

970 self.implicit_returning = kwargs.pop( 

971 "implicit_returning", self.implicit_returning 

972 ) 

973 self.info = kwargs.pop("info", self.info) 

974 

975 exclude_columns: _typing_Sequence[str] 

976 

977 if autoload: 

978 if not autoload_replace: 

979 # don't replace columns already present. 

980 # we'd like to do this for constraints also however we don't 

981 # have simple de-duping for unnamed constraints. 

982 exclude_columns = [c.name for c in self.c] 

983 else: 

984 exclude_columns = () 

985 self._autoload( 

986 self.metadata, 

987 autoload_with, 

988 include_columns, 

989 exclude_columns, 

990 resolve_fks, 

991 _extend_on=_extend_on, 

992 _reflect_info=_reflect_info, 

993 ) 

994 

995 all_names = {c.name: c for c in self.c} 

996 self._extra_kwargs(**kwargs) 

997 self._init_items(*args, allow_replacements=True, all_names=all_names) 

998 

999 def _extra_kwargs(self, **kwargs: Any) -> None: 

1000 self._validate_dialect_kwargs(kwargs) 

1001 

1002 def _init_collections(self) -> None: 

1003 pass 

1004 

1005 def _reset_exported(self) -> None: 

1006 pass 

1007 

1008 @util.ro_non_memoized_property 

1009 def _autoincrement_column(self) -> Optional[Column[int]]: 

1010 return self.primary_key._autoincrement_column 

1011 

1012 @util.ro_memoized_property 

1013 def _sentinel_column_characteristics( 

1014 self, 

1015 ) -> _SentinelColumnCharacterization: 

1016 """determine a candidate column (or columns, in case of a client 

1017 generated composite primary key) which can be used as an 

1018 "insert sentinel" for an INSERT statement. 

1019 

1020 The returned structure, :class:`_SentinelColumnCharacterization`, 

1021 includes all the details needed by :class:`.Dialect` and 

1022 :class:`.SQLCompiler` to determine if these column(s) can be used 

1023 as an INSERT..RETURNING sentinel for a particular database 

1024 dialect. 

1025 

1026 .. versionadded:: 2.0.10 

1027 

1028 """ 

1029 

1030 sentinel_is_explicit = False 

1031 sentinel_is_autoinc = False 

1032 the_sentinel: Optional[_typing_Sequence[Column[Any]]] = None 

1033 

1034 # see if a column was explicitly marked "insert_sentinel=True". 

1035 explicit_sentinel_col = self._sentinel_column 

1036 

1037 if explicit_sentinel_col is not None: 

1038 the_sentinel = (explicit_sentinel_col,) 

1039 sentinel_is_explicit = True 

1040 

1041 autoinc_col = self._autoincrement_column 

1042 if sentinel_is_explicit and explicit_sentinel_col is autoinc_col: 

1043 assert autoinc_col is not None 

1044 sentinel_is_autoinc = True 

1045 elif explicit_sentinel_col is None and autoinc_col is not None: 

1046 the_sentinel = (autoinc_col,) 

1047 sentinel_is_autoinc = True 

1048 

1049 default_characterization = _SentinelDefaultCharacterization.UNKNOWN 

1050 

1051 if the_sentinel: 

1052 the_sentinel_zero = the_sentinel[0] 

1053 if the_sentinel_zero.identity: 

1054 if the_sentinel_zero.identity._increment_is_negative: 

1055 if sentinel_is_explicit: 

1056 raise exc.InvalidRequestError( 

1057 "Can't use IDENTITY default with negative " 

1058 "increment as an explicit sentinel column" 

1059 ) 

1060 else: 

1061 if sentinel_is_autoinc: 

1062 autoinc_col = None 

1063 sentinel_is_autoinc = False 

1064 the_sentinel = None 

1065 else: 

1066 default_characterization = ( 

1067 _SentinelDefaultCharacterization.IDENTITY 

1068 ) 

1069 elif ( 

1070 the_sentinel_zero.default is None 

1071 and the_sentinel_zero.server_default is None 

1072 ): 

1073 if the_sentinel_zero.nullable: 

1074 raise exc.InvalidRequestError( 

1075 f"Column {the_sentinel_zero} has been marked as a " 

1076 "sentinel " 

1077 "column with no default generation function; it " 

1078 "at least needs to be marked nullable=False assuming " 

1079 "user-populated sentinel values will be used." 

1080 ) 

1081 default_characterization = ( 

1082 _SentinelDefaultCharacterization.NONE 

1083 ) 

1084 elif the_sentinel_zero.default is not None: 

1085 if the_sentinel_zero.default.is_sentinel: 

1086 default_characterization = ( 

1087 _SentinelDefaultCharacterization.SENTINEL_DEFAULT 

1088 ) 

1089 elif default_is_sequence(the_sentinel_zero.default): 

1090 if the_sentinel_zero.default._increment_is_negative: 

1091 if sentinel_is_explicit: 

1092 raise exc.InvalidRequestError( 

1093 "Can't use SEQUENCE default with negative " 

1094 "increment as an explicit sentinel column" 

1095 ) 

1096 else: 

1097 if sentinel_is_autoinc: 

1098 autoinc_col = None 

1099 sentinel_is_autoinc = False 

1100 the_sentinel = None 

1101 

1102 default_characterization = ( 

1103 _SentinelDefaultCharacterization.SEQUENCE 

1104 ) 

1105 elif the_sentinel_zero.default.is_callable: 

1106 default_characterization = ( 

1107 _SentinelDefaultCharacterization.CLIENTSIDE 

1108 ) 

1109 elif the_sentinel_zero.server_default is not None: 

1110 if sentinel_is_explicit: 

1111 raise exc.InvalidRequestError( 

1112 f"Column {the_sentinel[0]} can't be a sentinel column " 

1113 "because it uses an explicit server side default " 

1114 "that's not the Identity() default." 

1115 ) 

1116 

1117 default_characterization = ( 

1118 _SentinelDefaultCharacterization.SERVERSIDE 

1119 ) 

1120 

1121 if the_sentinel is None and self.primary_key: 

1122 assert autoinc_col is None 

1123 

1124 # determine for non-autoincrement pk if all elements are 

1125 # client side 

1126 for _pkc in self.primary_key: 

1127 if _pkc.server_default is not None or ( 

1128 _pkc.default and not _pkc.default.is_callable 

1129 ): 

1130 break 

1131 else: 

1132 the_sentinel = tuple(self.primary_key) 

1133 default_characterization = ( 

1134 _SentinelDefaultCharacterization.CLIENTSIDE 

1135 ) 

1136 

1137 return _SentinelColumnCharacterization( 

1138 the_sentinel, 

1139 sentinel_is_explicit, 

1140 sentinel_is_autoinc, 

1141 default_characterization, 

1142 ) 

1143 

1144 @property 

1145 def autoincrement_column(self) -> Optional[Column[int]]: 

1146 """Returns the :class:`.Column` object which currently represents 

1147 the "auto increment" column, if any, else returns None. 

1148 

1149 This is based on the rules for :class:`.Column` as defined by the 

1150 :paramref:`.Column.autoincrement` parameter, which generally means the 

1151 column within a single integer column primary key constraint that is 

1152 not constrained by a foreign key. If the table does not have such 

1153 a primary key constraint, then there's no "autoincrement" column. 

1154 A :class:`.Table` may have only one column defined as the 

1155 "autoincrement" column. 

1156 

1157 .. versionadded:: 2.0.4 

1158 

1159 .. seealso:: 

1160 

1161 :paramref:`.Column.autoincrement` 

1162 

1163 """ 

1164 return self._autoincrement_column 

1165 

1166 @property 

1167 def key(self) -> str: 

1168 """Return the 'key' for this :class:`_schema.Table`. 

1169 

1170 This value is used as the dictionary key within the 

1171 :attr:`_schema.MetaData.tables` collection. It is typically the same 

1172 as that of :attr:`_schema.Table.name` for a table with no 

1173 :attr:`_schema.Table.schema` 

1174 set; otherwise it is typically of the form 

1175 ``schemaname.tablename``. 

1176 

1177 """ 

1178 return _get_table_key(self.name, self.schema) 

1179 

1180 def __repr__(self) -> str: 

1181 return "Table(%s)" % ", ".join( 

1182 [repr(self.name)] 

1183 + [repr(self.metadata)] 

1184 + [repr(x) for x in self.columns] 

1185 + ["%s=%s" % (k, repr(getattr(self, k))) for k in ["schema"]] 

1186 ) 

1187 

1188 def __str__(self) -> str: 

1189 return _get_table_key(self.description, self.schema) 

1190 

1191 def add_is_dependent_on(self, table: Table) -> None: 

1192 """Add a 'dependency' for this Table. 

1193 

1194 This is another Table object which must be created 

1195 first before this one can, or dropped after this one. 

1196 

1197 Usually, dependencies between tables are determined via 

1198 ForeignKey objects. However, for other situations that 

1199 create dependencies outside of foreign keys (rules, inheriting), 

1200 this method can manually establish such a link. 

1201 

1202 """ 

1203 self._extra_dependencies.add(table) 

1204 

1205 def append_column( 

1206 self, column: ColumnClause[Any], replace_existing: bool = False 

1207 ) -> None: 

1208 """Append a :class:`_schema.Column` to this :class:`_schema.Table`. 

1209 

1210 The "key" of the newly added :class:`_schema.Column`, i.e. the 

1211 value of its ``.key`` attribute, will then be available 

1212 in the ``.c`` collection of this :class:`_schema.Table`, and the 

1213 column definition will be included in any CREATE TABLE, SELECT, 

1214 UPDATE, etc. statements generated from this :class:`_schema.Table` 

1215 construct. 

1216 

1217 Note that this does **not** change the definition of the table 

1218 as it exists within any underlying database, assuming that 

1219 table has already been created in the database. Relational 

1220 databases support the addition of columns to existing tables 

1221 using the SQL ALTER command, which would need to be 

1222 emitted for an already-existing table that doesn't contain 

1223 the newly added column. 

1224 

1225 :param replace_existing: When ``True``, allows replacing existing 

1226 columns. When ``False``, the default, an warning will be raised 

1227 if a column with the same ``.key`` already exists. A future 

1228 version of sqlalchemy will instead rise a warning. 

1229 

1230 .. versionadded:: 1.4.0 

1231 """ 

1232 

1233 try: 

1234 column._set_parent_with_dispatch( 

1235 self, 

1236 allow_replacements=replace_existing, 

1237 all_names={c.name: c for c in self.c}, 

1238 ) 

1239 except exc.DuplicateColumnError as de: 

1240 raise exc.DuplicateColumnError( 

1241 f"{de.args[0]} Specify replace_existing=True to " 

1242 "Table.append_column() to replace an " 

1243 "existing column." 

1244 ) from de 

1245 

1246 def append_constraint(self, constraint: Union[Index, Constraint]) -> None: 

1247 """Append a :class:`_schema.Constraint` to this 

1248 :class:`_schema.Table`. 

1249 

1250 This has the effect of the constraint being included in any 

1251 future CREATE TABLE statement, assuming specific DDL creation 

1252 events have not been associated with the given 

1253 :class:`_schema.Constraint` object. 

1254 

1255 Note that this does **not** produce the constraint within the 

1256 relational database automatically, for a table that already exists 

1257 in the database. To add a constraint to an 

1258 existing relational database table, the SQL ALTER command must 

1259 be used. SQLAlchemy also provides the 

1260 :class:`.AddConstraint` construct which can produce this SQL when 

1261 invoked as an executable clause. 

1262 

1263 """ 

1264 

1265 constraint._set_parent_with_dispatch(self) 

1266 

1267 def _set_parent(self, parent: SchemaEventTarget, **kw: Any) -> None: 

1268 metadata = parent 

1269 assert isinstance(metadata, MetaData) 

1270 metadata._add_table(self.name, self.schema, self) 

1271 self.metadata = metadata 

1272 

1273 def create(self, bind: _CreateDropBind, checkfirst: bool = False) -> None: 

1274 """Issue a ``CREATE`` statement for this 

1275 :class:`_schema.Table`, using the given 

1276 :class:`.Connection` or :class:`.Engine` 

1277 for connectivity. 

1278 

1279 .. seealso:: 

1280 

1281 :meth:`_schema.MetaData.create_all`. 

1282 

1283 """ 

1284 

1285 bind._run_ddl_visitor(ddl.SchemaGenerator, self, checkfirst=checkfirst) 

1286 

1287 def drop(self, bind: _CreateDropBind, checkfirst: bool = False) -> None: 

1288 """Issue a ``DROP`` statement for this 

1289 :class:`_schema.Table`, using the given 

1290 :class:`.Connection` or :class:`.Engine` for connectivity. 

1291 

1292 .. seealso:: 

1293 

1294 :meth:`_schema.MetaData.drop_all`. 

1295 

1296 """ 

1297 bind._run_ddl_visitor(ddl.SchemaDropper, self, checkfirst=checkfirst) 

1298 

1299 @util.deprecated( 

1300 "1.4", 

1301 ":meth:`_schema.Table.tometadata` is renamed to " 

1302 ":meth:`_schema.Table.to_metadata`", 

1303 ) 

1304 def tometadata( 

1305 self, 

1306 metadata: MetaData, 

1307 schema: Union[str, Literal[SchemaConst.RETAIN_SCHEMA]] = RETAIN_SCHEMA, 

1308 referred_schema_fn: Optional[ 

1309 Callable[ 

1310 [Table, Optional[str], ForeignKeyConstraint, Optional[str]], 

1311 Optional[str], 

1312 ] 

1313 ] = None, 

1314 name: Optional[str] = None, 

1315 ) -> Table: 

1316 """Return a copy of this :class:`_schema.Table` 

1317 associated with a different 

1318 :class:`_schema.MetaData`. 

1319 

1320 See :meth:`_schema.Table.to_metadata` for a full description. 

1321 

1322 """ 

1323 return self.to_metadata( 

1324 metadata, 

1325 schema=schema, 

1326 referred_schema_fn=referred_schema_fn, 

1327 name=name, 

1328 ) 

1329 

1330 def to_metadata( 

1331 self, 

1332 metadata: MetaData, 

1333 schema: Union[str, Literal[SchemaConst.RETAIN_SCHEMA]] = RETAIN_SCHEMA, 

1334 referred_schema_fn: Optional[ 

1335 Callable[ 

1336 [Table, Optional[str], ForeignKeyConstraint, Optional[str]], 

1337 Optional[str], 

1338 ] 

1339 ] = None, 

1340 name: Optional[str] = None, 

1341 ) -> Table: 

1342 """Return a copy of this :class:`_schema.Table` associated with a 

1343 different :class:`_schema.MetaData`. 

1344 

1345 E.g.:: 

1346 

1347 m1 = MetaData() 

1348 

1349 user = Table('user', m1, Column('id', Integer, primary_key=True)) 

1350 

1351 m2 = MetaData() 

1352 user_copy = user.to_metadata(m2) 

1353 

1354 .. versionchanged:: 1.4 The :meth:`_schema.Table.to_metadata` function 

1355 was renamed from :meth:`_schema.Table.tometadata`. 

1356 

1357 

1358 :param metadata: Target :class:`_schema.MetaData` object, 

1359 into which the 

1360 new :class:`_schema.Table` object will be created. 

1361 

1362 :param schema: optional string name indicating the target schema. 

1363 Defaults to the special symbol :attr:`.RETAIN_SCHEMA` which indicates 

1364 that no change to the schema name should be made in the new 

1365 :class:`_schema.Table`. If set to a string name, the new 

1366 :class:`_schema.Table` 

1367 will have this new name as the ``.schema``. If set to ``None``, the 

1368 schema will be set to that of the schema set on the target 

1369 :class:`_schema.MetaData`, which is typically ``None`` as well, 

1370 unless 

1371 set explicitly:: 

1372 

1373 m2 = MetaData(schema='newschema') 

1374 

1375 # user_copy_one will have "newschema" as the schema name 

1376 user_copy_one = user.to_metadata(m2, schema=None) 

1377 

1378 m3 = MetaData() # schema defaults to None 

1379 

1380 # user_copy_two will have None as the schema name 

1381 user_copy_two = user.to_metadata(m3, schema=None) 

1382 

1383 :param referred_schema_fn: optional callable which can be supplied 

1384 in order to provide for the schema name that should be assigned 

1385 to the referenced table of a :class:`_schema.ForeignKeyConstraint`. 

1386 The callable accepts this parent :class:`_schema.Table`, the 

1387 target schema that we are changing to, the 

1388 :class:`_schema.ForeignKeyConstraint` object, and the existing 

1389 "target schema" of that constraint. The function should return the 

1390 string schema name that should be applied. To reset the schema 

1391 to "none", return the symbol :data:`.BLANK_SCHEMA`. To effect no 

1392 change, return ``None`` or :data:`.RETAIN_SCHEMA`. 

1393 

1394 .. versionchanged:: 1.4.33 The ``referred_schema_fn`` function 

1395 may return the :data:`.BLANK_SCHEMA` or :data:`.RETAIN_SCHEMA` 

1396 symbols. 

1397 

1398 E.g.:: 

1399 

1400 def referred_schema_fn(table, to_schema, 

1401 constraint, referred_schema): 

1402 if referred_schema == 'base_tables': 

1403 return referred_schema 

1404 else: 

1405 return to_schema 

1406 

1407 new_table = table.to_metadata(m2, schema="alt_schema", 

1408 referred_schema_fn=referred_schema_fn) 

1409 

1410 :param name: optional string name indicating the target table name. 

1411 If not specified or None, the table name is retained. This allows 

1412 a :class:`_schema.Table` to be copied to the same 

1413 :class:`_schema.MetaData` target 

1414 with a new name. 

1415 

1416 """ 

1417 if name is None: 

1418 name = self.name 

1419 

1420 actual_schema: Optional[str] 

1421 

1422 if schema is RETAIN_SCHEMA: 

1423 actual_schema = self.schema 

1424 elif schema is None: 

1425 actual_schema = metadata.schema 

1426 else: 

1427 actual_schema = schema 

1428 key = _get_table_key(name, actual_schema) 

1429 if key in metadata.tables: 

1430 util.warn( 

1431 f"Table '{self.description}' already exists within the given " 

1432 "MetaData - not copying." 

1433 ) 

1434 return metadata.tables[key] 

1435 

1436 args = [] 

1437 for col in self.columns: 

1438 args.append(col._copy(schema=actual_schema, _to_metadata=metadata)) 

1439 table = Table( 

1440 name, 

1441 metadata, 

1442 schema=actual_schema, 

1443 comment=self.comment, 

1444 *args, 

1445 **self.kwargs, 

1446 ) 

1447 for const in self.constraints: 

1448 if isinstance(const, ForeignKeyConstraint): 

1449 referred_schema = const._referred_schema 

1450 if referred_schema_fn: 

1451 fk_constraint_schema = referred_schema_fn( 

1452 self, actual_schema, const, referred_schema 

1453 ) 

1454 else: 

1455 fk_constraint_schema = ( 

1456 actual_schema 

1457 if referred_schema == self.schema 

1458 else None 

1459 ) 

1460 table.append_constraint( 

1461 const._copy( 

1462 schema=fk_constraint_schema, target_table=table 

1463 ) 

1464 ) 

1465 elif not const._type_bound: 

1466 # skip unique constraints that would be generated 

1467 # by the 'unique' flag on Column 

1468 if const._column_flag: 

1469 continue 

1470 

1471 table.append_constraint( 

1472 const._copy(schema=actual_schema, target_table=table) 

1473 ) 

1474 for index in self.indexes: 

1475 # skip indexes that would be generated 

1476 # by the 'index' flag on Column 

1477 if index._column_flag: 

1478 continue 

1479 Index( 

1480 index.name, 

1481 unique=index.unique, 

1482 *[ 

1483 _copy_expression(expr, self, table) 

1484 for expr in index._table_bound_expressions 

1485 ], 

1486 _table=table, 

1487 **index.kwargs, 

1488 ) 

1489 return self._schema_item_copy(table) 

1490 

1491 

1492class Column(DialectKWArgs, SchemaItem, ColumnClause[_T]): 

1493 """Represents a column in a database table.""" 

1494 

1495 __visit_name__ = "column" 

1496 

1497 inherit_cache = True 

1498 key: str 

1499 

1500 server_default: Optional[FetchedValue] 

1501 

1502 def __init__( 

1503 self, 

1504 __name_pos: Optional[ 

1505 Union[str, _TypeEngineArgument[_T], SchemaEventTarget] 

1506 ] = None, 

1507 __type_pos: Optional[ 

1508 Union[_TypeEngineArgument[_T], SchemaEventTarget] 

1509 ] = None, 

1510 /, 

1511 *args: SchemaEventTarget, 

1512 name: Optional[str] = None, 

1513 type_: Optional[_TypeEngineArgument[_T]] = None, 

1514 autoincrement: _AutoIncrementType = "auto", 

1515 default: Optional[Any] = _NoArg.NO_ARG, 

1516 insert_default: Optional[Any] = _NoArg.NO_ARG, 

1517 doc: Optional[str] = None, 

1518 key: Optional[str] = None, 

1519 index: Optional[bool] = None, 

1520 unique: Optional[bool] = None, 

1521 info: Optional[_InfoType] = None, 

1522 nullable: Optional[ 

1523 Union[bool, Literal[SchemaConst.NULL_UNSPECIFIED]] 

1524 ] = SchemaConst.NULL_UNSPECIFIED, 

1525 onupdate: Optional[Any] = None, 

1526 primary_key: bool = False, 

1527 server_default: Optional[_ServerDefaultArgument] = None, 

1528 server_onupdate: Optional[_ServerOnUpdateArgument] = None, 

1529 quote: Optional[bool] = None, 

1530 system: bool = False, 

1531 comment: Optional[str] = None, 

1532 insert_sentinel: bool = False, 

1533 _omit_from_statements: bool = False, 

1534 _proxies: Optional[Any] = None, 

1535 **dialect_kwargs: Any, 

1536 ): 

1537 r""" 

1538 Construct a new ``Column`` object. 

1539 

1540 :param name: The name of this column as represented in the database. 

1541 This argument may be the first positional argument, or specified 

1542 via keyword. 

1543 

1544 Names which contain no upper case characters 

1545 will be treated as case insensitive names, and will not be quoted 

1546 unless they are a reserved word. Names with any number of upper 

1547 case characters will be quoted and sent exactly. Note that this 

1548 behavior applies even for databases which standardize upper 

1549 case names as case insensitive such as Oracle. 

1550 

1551 The name field may be omitted at construction time and applied 

1552 later, at any time before the Column is associated with a 

1553 :class:`_schema.Table`. This is to support convenient 

1554 usage within the :mod:`~sqlalchemy.ext.declarative` extension. 

1555 

1556 :param type\_: The column's type, indicated using an instance which 

1557 subclasses :class:`~sqlalchemy.types.TypeEngine`. If no arguments 

1558 are required for the type, the class of the type can be sent 

1559 as well, e.g.:: 

1560 

1561 # use a type with arguments 

1562 Column('data', String(50)) 

1563 

1564 # use no arguments 

1565 Column('level', Integer) 

1566 

1567 The ``type`` argument may be the second positional argument 

1568 or specified by keyword. 

1569 

1570 If the ``type`` is ``None`` or is omitted, it will first default to 

1571 the special type :class:`.NullType`. If and when this 

1572 :class:`_schema.Column` is made to refer to another column using 

1573 :class:`_schema.ForeignKey` and/or 

1574 :class:`_schema.ForeignKeyConstraint`, the type 

1575 of the remote-referenced column will be copied to this column as 

1576 well, at the moment that the foreign key is resolved against that 

1577 remote :class:`_schema.Column` object. 

1578 

1579 :param \*args: Additional positional arguments include various 

1580 :class:`.SchemaItem` derived constructs which will be applied 

1581 as options to the column. These include instances of 

1582 :class:`.Constraint`, :class:`_schema.ForeignKey`, 

1583 :class:`.ColumnDefault`, :class:`.Sequence`, :class:`.Computed` 

1584 :class:`.Identity`. In some cases an 

1585 equivalent keyword argument is available such as ``server_default``, 

1586 ``default`` and ``unique``. 

1587 

1588 :param autoincrement: Set up "auto increment" semantics for an 

1589 **integer primary key column with no foreign key dependencies** 

1590 (see later in this docstring for a more specific definition). 

1591 This may influence the :term:`DDL` that will be emitted for 

1592 this column during a table create, as well as how the column 

1593 will be considered when INSERT statements are compiled and 

1594 executed. 

1595 

1596 The default value is the string ``"auto"``, 

1597 which indicates that a single-column (i.e. non-composite) primary key 

1598 that is of an INTEGER type with no other client-side or server-side 

1599 default constructs indicated should receive auto increment semantics 

1600 automatically. Other values include ``True`` (force this column to 

1601 have auto-increment semantics for a :term:`composite primary key` as 

1602 well), ``False`` (this column should never have auto-increment 

1603 semantics), and the string ``"ignore_fk"`` (special-case for foreign 

1604 key columns, see below). 

1605 

1606 The term "auto increment semantics" refers both to the kind of DDL 

1607 that will be emitted for the column within a CREATE TABLE statement, 

1608 when methods such as :meth:`.MetaData.create_all` and 

1609 :meth:`.Table.create` are invoked, as well as how the column will be 

1610 considered when an INSERT statement is compiled and emitted to the 

1611 database: 

1612 

1613 * **DDL rendering** (i.e. :meth:`.MetaData.create_all`, 

1614 :meth:`.Table.create`): When used on a :class:`.Column` that has 

1615 no other 

1616 default-generating construct associated with it (such as a 

1617 :class:`.Sequence` or :class:`.Identity` construct), the parameter 

1618 will imply that database-specific keywords such as PostgreSQL 

1619 ``SERIAL``, MySQL ``AUTO_INCREMENT``, or ``IDENTITY`` on SQL Server 

1620 should also be rendered. Not every database backend has an 

1621 "implied" default generator available; for example the Oracle 

1622 backend always needs an explicit construct such as 

1623 :class:`.Identity` to be included with a :class:`.Column` in order 

1624 for the DDL rendered to include auto-generating constructs to also 

1625 be produced in the database. 

1626 

1627 * **INSERT semantics** (i.e. when a :func:`_sql.insert` construct is 

1628 compiled into a SQL string and is then executed on a database using 

1629 :meth:`_engine.Connection.execute` or equivalent): A single-row 

1630 INSERT statement will be known to produce a new integer primary key 

1631 value automatically for this column, which will be accessible 

1632 after the statement is invoked via the 

1633 :attr:`.CursorResult.inserted_primary_key` attribute upon the 

1634 :class:`_result.Result` object. This also applies towards use of the 

1635 ORM when ORM-mapped objects are persisted to the database, 

1636 indicating that a new integer primary key will be available to 

1637 become part of the :term:`identity key` for that object. This 

1638 behavior takes place regardless of what DDL constructs are 

1639 associated with the :class:`_schema.Column` and is independent 

1640 of the "DDL Rendering" behavior discussed in the previous note 

1641 above. 

1642 

1643 The parameter may be set to ``True`` to indicate that a column which 

1644 is part of a composite (i.e. multi-column) primary key should 

1645 have autoincrement semantics, though note that only one column 

1646 within a primary key may have this setting. It can also 

1647 be set to ``True`` to indicate autoincrement semantics on a 

1648 column that has a client-side or server-side default configured, 

1649 however note that not all dialects can accommodate all styles 

1650 of default as an "autoincrement". It can also be 

1651 set to ``False`` on a single-column primary key that has a 

1652 datatype of INTEGER in order to disable auto increment semantics 

1653 for that column. 

1654 

1655 The setting *only* has an effect for columns which are: 

1656 

1657 * Integer derived (i.e. INT, SMALLINT, BIGINT). 

1658 

1659 * Part of the primary key 

1660 

1661 * Not referring to another column via :class:`_schema.ForeignKey`, 

1662 unless 

1663 the value is specified as ``'ignore_fk'``:: 

1664 

1665 # turn on autoincrement for this column despite 

1666 # the ForeignKey() 

1667 Column('id', ForeignKey('other.id'), 

1668 primary_key=True, autoincrement='ignore_fk') 

1669 

1670 It is typically not desirable to have "autoincrement" enabled on a 

1671 column that refers to another via foreign key, as such a column is 

1672 required to refer to a value that originates from elsewhere. 

1673 

1674 The setting has these effects on columns that meet the 

1675 above criteria: 

1676 

1677 * DDL issued for the column, if the column does not already include 

1678 a default generating construct supported by the backend such as 

1679 :class:`.Identity`, will include database-specific 

1680 keywords intended to signify this column as an 

1681 "autoincrement" column for specific backends. Behavior for 

1682 primary SQLAlchemy dialects includes: 

1683 

1684 * AUTO INCREMENT on MySQL and MariaDB 

1685 * SERIAL on PostgreSQL 

1686 * IDENTITY on MS-SQL - this occurs even without the 

1687 :class:`.Identity` construct as the 

1688 :paramref:`.Column.autoincrement` parameter pre-dates this 

1689 construct. 

1690 * SQLite - SQLite integer primary key columns are implicitly 

1691 "auto incrementing" and no additional keywords are rendered; 

1692 to render the special SQLite keyword ``AUTOINCREMENT`` 

1693 is not included as this is unnecessary and not recommended 

1694 by the database vendor. See the section 

1695 :ref:`sqlite_autoincrement` for more background. 

1696 * Oracle - The Oracle dialect has no default "autoincrement" 

1697 feature available at this time, instead the :class:`.Identity` 

1698 construct is recommended to achieve this (the :class:`.Sequence` 

1699 construct may also be used). 

1700 * Third-party dialects - consult those dialects' documentation 

1701 for details on their specific behaviors. 

1702 

1703 * When a single-row :func:`_sql.insert` construct is compiled and 

1704 executed, which does not set the :meth:`_sql.Insert.inline` 

1705 modifier, newly generated primary key values for this column 

1706 will be automatically retrieved upon statement execution 

1707 using a method specific to the database driver in use: 

1708 

1709 * MySQL, SQLite - calling upon ``cursor.lastrowid()`` 

1710 (see 

1711 `https://www.python.org/dev/peps/pep-0249/#lastrowid 

1712 <https://www.python.org/dev/peps/pep-0249/#lastrowid>`_) 

1713 * PostgreSQL, SQL Server, Oracle - use RETURNING or an equivalent 

1714 construct when rendering an INSERT statement, and then retrieving 

1715 the newly generated primary key values after execution 

1716 * PostgreSQL, Oracle for :class:`_schema.Table` objects that 

1717 set :paramref:`_schema.Table.implicit_returning` to False - 

1718 for a :class:`.Sequence` only, the :class:`.Sequence` is invoked 

1719 explicitly before the INSERT statement takes place so that the 

1720 newly generated primary key value is available to the client 

1721 * SQL Server for :class:`_schema.Table` objects that 

1722 set :paramref:`_schema.Table.implicit_returning` to False - 

1723 the ``SELECT scope_identity()`` construct is used after the 

1724 INSERT statement is invoked to retrieve the newly generated 

1725 primary key value. 

1726 * Third-party dialects - consult those dialects' documentation 

1727 for details on their specific behaviors. 

1728 

1729 * For multiple-row :func:`_sql.insert` constructs invoked with 

1730 a list of parameters (i.e. "executemany" semantics), primary-key 

1731 retrieving behaviors are generally disabled, however there may 

1732 be special APIs that may be used to retrieve lists of new 

1733 primary key values for an "executemany", such as the psycopg2 

1734 "fast insertmany" feature. Such features are very new and 

1735 may not yet be well covered in documentation. 

1736 

1737 :param default: A scalar, Python callable, or 

1738 :class:`_expression.ColumnElement` expression representing the 

1739 *default value* for this column, which will be invoked upon insert 

1740 if this column is otherwise not specified in the VALUES clause of 

1741 the insert. This is a shortcut to using :class:`.ColumnDefault` as 

1742 a positional argument; see that class for full detail on the 

1743 structure of the argument. 

1744 

1745 Contrast this argument to 

1746 :paramref:`_schema.Column.server_default` 

1747 which creates a default generator on the database side. 

1748 

1749 .. seealso:: 

1750 

1751 :ref:`metadata_defaults_toplevel` 

1752 

1753 :param insert_default: An alias of :paramref:`.Column.default` 

1754 for compatibility with :func:`_orm.mapped_column`. 

1755 

1756 .. versionadded: 2.0.31 

1757 

1758 :param doc: optional String that can be used by the ORM or similar 

1759 to document attributes on the Python side. This attribute does 

1760 **not** render SQL comments; use the 

1761 :paramref:`_schema.Column.comment` 

1762 parameter for this purpose. 

1763 

1764 :param key: An optional string identifier which will identify this 

1765 ``Column`` object on the :class:`_schema.Table`. 

1766 When a key is provided, 

1767 this is the only identifier referencing the ``Column`` within the 

1768 application, including ORM attribute mapping; the ``name`` field 

1769 is used only when rendering SQL. 

1770 

1771 :param index: When ``True``, indicates that a :class:`_schema.Index` 

1772 construct will be automatically generated for this 

1773 :class:`_schema.Column`, which will result in a "CREATE INDEX" 

1774 statement being emitted for the :class:`_schema.Table` when the DDL 

1775 create operation is invoked. 

1776 

1777 Using this flag is equivalent to making use of the 

1778 :class:`_schema.Index` construct explicitly at the level of the 

1779 :class:`_schema.Table` construct itself:: 

1780 

1781 Table( 

1782 "some_table", 

1783 metadata, 

1784 Column("x", Integer), 

1785 Index("ix_some_table_x", "x") 

1786 ) 

1787 

1788 To add the :paramref:`_schema.Index.unique` flag to the 

1789 :class:`_schema.Index`, set both the 

1790 :paramref:`_schema.Column.unique` and 

1791 :paramref:`_schema.Column.index` flags to True simultaneously, 

1792 which will have the effect of rendering the "CREATE UNIQUE INDEX" 

1793 DDL instruction instead of "CREATE INDEX". 

1794 

1795 The name of the index is generated using the 

1796 :ref:`default naming convention <constraint_default_naming_convention>` 

1797 which for the :class:`_schema.Index` construct is of the form 

1798 ``ix_<tablename>_<columnname>``. 

1799 

1800 As this flag is intended only as a convenience for the common case 

1801 of adding a single-column, default configured index to a table 

1802 definition, explicit use of the :class:`_schema.Index` construct 

1803 should be preferred for most use cases, including composite indexes 

1804 that encompass more than one column, indexes with SQL expressions 

1805 or ordering, backend-specific index configuration options, and 

1806 indexes that use a specific name. 

1807 

1808 .. note:: the :attr:`_schema.Column.index` attribute on 

1809 :class:`_schema.Column` 

1810 **does not indicate** if this column is indexed or not, only 

1811 if this flag was explicitly set here. To view indexes on 

1812 a column, view the :attr:`_schema.Table.indexes` collection 

1813 or use :meth:`_reflection.Inspector.get_indexes`. 

1814 

1815 .. seealso:: 

1816 

1817 :ref:`schema_indexes` 

1818 

1819 :ref:`constraint_naming_conventions` 

1820 

1821 :paramref:`_schema.Column.unique` 

1822 

1823 :param info: Optional data dictionary which will be populated into the 

1824 :attr:`.SchemaItem.info` attribute of this object. 

1825 

1826 :param nullable: When set to ``False``, will cause the "NOT NULL" 

1827 phrase to be added when generating DDL for the column. When 

1828 ``True``, will normally generate nothing (in SQL this defaults to 

1829 "NULL"), except in some very specific backend-specific edge cases 

1830 where "NULL" may render explicitly. 

1831 Defaults to ``True`` unless :paramref:`_schema.Column.primary_key` 

1832 is also ``True`` or the column specifies a :class:`_sql.Identity`, 

1833 in which case it defaults to ``False``. 

1834 This parameter is only used when issuing CREATE TABLE statements. 

1835 

1836 .. note:: 

1837 

1838 When the column specifies a :class:`_sql.Identity` this 

1839 parameter is in general ignored by the DDL compiler. The 

1840 PostgreSQL database allows nullable identity column by 

1841 setting this parameter to ``True`` explicitly. 

1842 

1843 :param onupdate: A scalar, Python callable, or 

1844 :class:`~sqlalchemy.sql.expression.ClauseElement` representing a 

1845 default value to be applied to the column within UPDATE 

1846 statements, which will be invoked upon update if this column is not 

1847 present in the SET clause of the update. This is a shortcut to 

1848 using :class:`.ColumnDefault` as a positional argument with 

1849 ``for_update=True``. 

1850 

1851 .. seealso:: 

1852 

1853 :ref:`metadata_defaults` - complete discussion of onupdate 

1854 

1855 :param primary_key: If ``True``, marks this column as a primary key 

1856 column. Multiple columns can have this flag set to specify 

1857 composite primary keys. As an alternative, the primary key of a 

1858 :class:`_schema.Table` can be specified via an explicit 

1859 :class:`.PrimaryKeyConstraint` object. 

1860 

1861 :param server_default: A :class:`.FetchedValue` instance, str, Unicode 

1862 or :func:`~sqlalchemy.sql.expression.text` construct representing 

1863 the DDL DEFAULT value for the column. 

1864 

1865 String types will be emitted as-is, surrounded by single quotes:: 

1866 

1867 Column('x', Text, server_default="val") 

1868 

1869 x TEXT DEFAULT 'val' 

1870 

1871 A :func:`~sqlalchemy.sql.expression.text` expression will be 

1872 rendered as-is, without quotes:: 

1873 

1874 Column('y', DateTime, server_default=text('NOW()')) 

1875 

1876 y DATETIME DEFAULT NOW() 

1877 

1878 Strings and text() will be converted into a 

1879 :class:`.DefaultClause` object upon initialization. 

1880 

1881 This parameter can also accept complex combinations of contextually 

1882 valid SQLAlchemy expressions or constructs:: 

1883 

1884 from sqlalchemy import create_engine 

1885 from sqlalchemy import Table, Column, MetaData, ARRAY, Text 

1886 from sqlalchemy.dialects.postgresql import array 

1887 

1888 engine = create_engine( 

1889 'postgresql+psycopg2://scott:tiger@localhost/mydatabase' 

1890 ) 

1891 metadata_obj = MetaData() 

1892 tbl = Table( 

1893 "foo", 

1894 metadata_obj, 

1895 Column("bar", 

1896 ARRAY(Text), 

1897 server_default=array(["biz", "bang", "bash"]) 

1898 ) 

1899 ) 

1900 metadata_obj.create_all(engine) 

1901 

1902 The above results in a table created with the following SQL:: 

1903 

1904 CREATE TABLE foo ( 

1905 bar TEXT[] DEFAULT ARRAY['biz', 'bang', 'bash'] 

1906 ) 

1907 

1908 Use :class:`.FetchedValue` to indicate that an already-existing 

1909 column will generate a default value on the database side which 

1910 will be available to SQLAlchemy for post-fetch after inserts. This 

1911 construct does not specify any DDL and the implementation is left 

1912 to the database, such as via a trigger. 

1913 

1914 .. seealso:: 

1915 

1916 :ref:`server_defaults` - complete discussion of server side 

1917 defaults 

1918 

1919 :param server_onupdate: A :class:`.FetchedValue` instance 

1920 representing a database-side default generation function, 

1921 such as a trigger. This 

1922 indicates to SQLAlchemy that a newly generated value will be 

1923 available after updates. This construct does not actually 

1924 implement any kind of generation function within the database, 

1925 which instead must be specified separately. 

1926 

1927 

1928 .. warning:: This directive **does not** currently produce MySQL's 

1929 "ON UPDATE CURRENT_TIMESTAMP()" clause. See 

1930 :ref:`mysql_timestamp_onupdate` for background on how to 

1931 produce this clause. 

1932 

1933 .. seealso:: 

1934 

1935 :ref:`triggered_columns` 

1936 

1937 :param quote: Force quoting of this column's name on or off, 

1938 corresponding to ``True`` or ``False``. When left at its default 

1939 of ``None``, the column identifier will be quoted according to 

1940 whether the name is case sensitive (identifiers with at least one 

1941 upper case character are treated as case sensitive), or if it's a 

1942 reserved word. This flag is only needed to force quoting of a 

1943 reserved word which is not known by the SQLAlchemy dialect. 

1944 

1945 :param unique: When ``True``, and the :paramref:`_schema.Column.index` 

1946 parameter is left at its default value of ``False``, 

1947 indicates that a :class:`_schema.UniqueConstraint` 

1948 construct will be automatically generated for this 

1949 :class:`_schema.Column`, 

1950 which will result in a "UNIQUE CONSTRAINT" clause referring 

1951 to this column being included 

1952 in the ``CREATE TABLE`` statement emitted, when the DDL create 

1953 operation for the :class:`_schema.Table` object is invoked. 

1954 

1955 When this flag is ``True`` while the 

1956 :paramref:`_schema.Column.index` parameter is simultaneously 

1957 set to ``True``, the effect instead is that a 

1958 :class:`_schema.Index` construct which includes the 

1959 :paramref:`_schema.Index.unique` parameter set to ``True`` 

1960 is generated. See the documentation for 

1961 :paramref:`_schema.Column.index` for additional detail. 

1962 

1963 Using this flag is equivalent to making use of the 

1964 :class:`_schema.UniqueConstraint` construct explicitly at the 

1965 level of the :class:`_schema.Table` construct itself:: 

1966 

1967 Table( 

1968 "some_table", 

1969 metadata, 

1970 Column("x", Integer), 

1971 UniqueConstraint("x") 

1972 ) 

1973 

1974 The :paramref:`_schema.UniqueConstraint.name` parameter 

1975 of the unique constraint object is left at its default value 

1976 of ``None``; in the absence of a :ref:`naming convention <constraint_naming_conventions>` 

1977 for the enclosing :class:`_schema.MetaData`, the UNIQUE CONSTRAINT 

1978 construct will be emitted as unnamed, which typically invokes 

1979 a database-specific naming convention to take place. 

1980 

1981 As this flag is intended only as a convenience for the common case 

1982 of adding a single-column, default configured unique constraint to a table 

1983 definition, explicit use of the :class:`_schema.UniqueConstraint` construct 

1984 should be preferred for most use cases, including composite constraints 

1985 that encompass more than one column, backend-specific index configuration options, and 

1986 constraints that use a specific name. 

1987 

1988 .. note:: the :attr:`_schema.Column.unique` attribute on 

1989 :class:`_schema.Column` 

1990 **does not indicate** if this column has a unique constraint or 

1991 not, only if this flag was explicitly set here. To view 

1992 indexes and unique constraints that may involve this column, 

1993 view the 

1994 :attr:`_schema.Table.indexes` and/or 

1995 :attr:`_schema.Table.constraints` collections or use 

1996 :meth:`_reflection.Inspector.get_indexes` and/or 

1997 :meth:`_reflection.Inspector.get_unique_constraints` 

1998 

1999 .. seealso:: 

2000 

2001 :ref:`schema_unique_constraint` 

2002 

2003 :ref:`constraint_naming_conventions` 

2004 

2005 :paramref:`_schema.Column.index` 

2006 

2007 :param system: When ``True``, indicates this is a "system" column, 

2008 that is a column which is automatically made available by the 

2009 database, and should not be included in the columns list for a 

2010 ``CREATE TABLE`` statement. 

2011 

2012 For more elaborate scenarios where columns should be 

2013 conditionally rendered differently on different backends, 

2014 consider custom compilation rules for :class:`.CreateColumn`. 

2015 

2016 :param comment: Optional string that will render an SQL comment on 

2017 table creation. 

2018 

2019 .. versionadded:: 1.2 Added the 

2020 :paramref:`_schema.Column.comment` 

2021 parameter to :class:`_schema.Column`. 

2022 

2023 :param insert_sentinel: Marks this :class:`_schema.Column` as an 

2024 :term:`insert sentinel` used for optimizing the performance of the 

2025 :term:`insertmanyvalues` feature for tables that don't 

2026 otherwise have qualifying primary key configurations. 

2027 

2028 .. versionadded:: 2.0.10 

2029 

2030 .. seealso:: 

2031 

2032 :func:`_schema.insert_sentinel` - all in one helper for declaring 

2033 sentinel columns 

2034 

2035 :ref:`engine_insertmanyvalues` 

2036 

2037 :ref:`engine_insertmanyvalues_sentinel_columns` 

2038 

2039 

2040 """ # noqa: E501, RST201, RST202 

2041 

2042 l_args = [__name_pos, __type_pos] + list(args) 

2043 del args 

2044 

2045 if l_args: 

2046 if isinstance(l_args[0], str): 

2047 if name is not None: 

2048 raise exc.ArgumentError( 

2049 "May not pass name positionally and as a keyword." 

2050 ) 

2051 name = l_args.pop(0) # type: ignore 

2052 elif l_args[0] is None: 

2053 l_args.pop(0) 

2054 if l_args: 

2055 coltype = l_args[0] 

2056 

2057 if hasattr(coltype, "_sqla_type"): 

2058 if type_ is not None: 

2059 raise exc.ArgumentError( 

2060 "May not pass type_ positionally and as a keyword." 

2061 ) 

2062 type_ = l_args.pop(0) # type: ignore 

2063 elif l_args[0] is None: 

2064 l_args.pop(0) 

2065 

2066 if name is not None: 

2067 name = quoted_name(name, quote) 

2068 elif quote is not None: 

2069 raise exc.ArgumentError( 

2070 "Explicit 'name' is required when sending 'quote' argument" 

2071 ) 

2072 

2073 # name = None is expected to be an interim state 

2074 # note this use case is legacy now that ORM declarative has a 

2075 # dedicated "column" construct local to the ORM 

2076 super().__init__(name, type_) # type: ignore 

2077 

2078 self.key = key if key is not None else name # type: ignore 

2079 self.primary_key = primary_key 

2080 self._insert_sentinel = insert_sentinel 

2081 self._omit_from_statements = _omit_from_statements 

2082 self._user_defined_nullable = udn = nullable 

2083 if udn is not NULL_UNSPECIFIED: 

2084 self.nullable = udn 

2085 else: 

2086 self.nullable = not primary_key 

2087 

2088 # these default to None because .index and .unique is *not* 

2089 # an informational flag about Column - there can still be an 

2090 # Index or UniqueConstraint referring to this Column. 

2091 self.index = index 

2092 self.unique = unique 

2093 

2094 self.system = system 

2095 self.doc = doc 

2096 self.autoincrement: _AutoIncrementType = autoincrement 

2097 self.constraints = set() 

2098 self.foreign_keys = set() 

2099 self.comment = comment 

2100 self.computed = None 

2101 self.identity = None 

2102 

2103 # check if this Column is proxying another column 

2104 

2105 if _proxies is not None: 

2106 self._proxies = _proxies 

2107 else: 

2108 # otherwise, add DDL-related events 

2109 self._set_type(self.type) 

2110 

2111 if insert_default is not _NoArg.NO_ARG: 

2112 resolved_default = insert_default 

2113 elif default is not _NoArg.NO_ARG: 

2114 resolved_default = default 

2115 else: 

2116 resolved_default = None 

2117 

2118 if resolved_default is not None: 

2119 if not isinstance(resolved_default, (ColumnDefault, Sequence)): 

2120 resolved_default = ColumnDefault(resolved_default) 

2121 

2122 self.default = resolved_default 

2123 l_args.append(resolved_default) 

2124 else: 

2125 self.default = None 

2126 

2127 if onupdate is not None: 

2128 if not isinstance(onupdate, (ColumnDefault, Sequence)): 

2129 onupdate = ColumnDefault(onupdate, for_update=True) 

2130 

2131 self.onupdate = onupdate 

2132 l_args.append(onupdate) 

2133 else: 

2134 self.onupdate = None 

2135 

2136 if server_default is not None: 

2137 if isinstance(server_default, FetchedValue): 

2138 server_default = server_default._as_for_update(False) 

2139 l_args.append(server_default) 

2140 else: 

2141 server_default = DefaultClause(server_default) 

2142 l_args.append(server_default) 

2143 self.server_default = server_default 

2144 

2145 if server_onupdate is not None: 

2146 if isinstance(server_onupdate, FetchedValue): 

2147 server_onupdate = server_onupdate._as_for_update(True) 

2148 l_args.append(server_onupdate) 

2149 else: 

2150 server_onupdate = DefaultClause( 

2151 server_onupdate, for_update=True 

2152 ) 

2153 l_args.append(server_onupdate) 

2154 self.server_onupdate = server_onupdate 

2155 

2156 self._init_items(*cast(_typing_Sequence[SchemaItem], l_args)) 

2157 

2158 util.set_creation_order(self) 

2159 

2160 if info is not None: 

2161 self.info = info 

2162 

2163 self._extra_kwargs(**dialect_kwargs) 

2164 

2165 table: Table 

2166 

2167 constraints: Set[Constraint] 

2168 

2169 foreign_keys: Set[ForeignKey] 

2170 """A collection of all :class:`_schema.ForeignKey` marker objects 

2171 associated with this :class:`_schema.Column`. 

2172 

2173 Each object is a member of a :class:`_schema.Table`-wide 

2174 :class:`_schema.ForeignKeyConstraint`. 

2175 

2176 .. seealso:: 

2177 

2178 :attr:`_schema.Table.foreign_keys` 

2179 

2180 """ 

2181 

2182 index: Optional[bool] 

2183 """The value of the :paramref:`_schema.Column.index` parameter. 

2184 

2185 Does not indicate if this :class:`_schema.Column` is actually indexed 

2186 or not; use :attr:`_schema.Table.indexes`. 

2187 

2188 .. seealso:: 

2189 

2190 :attr:`_schema.Table.indexes` 

2191 """ 

2192 

2193 unique: Optional[bool] 

2194 """The value of the :paramref:`_schema.Column.unique` parameter. 

2195 

2196 Does not indicate if this :class:`_schema.Column` is actually subject to 

2197 a unique constraint or not; use :attr:`_schema.Table.indexes` and 

2198 :attr:`_schema.Table.constraints`. 

2199 

2200 .. seealso:: 

2201 

2202 :attr:`_schema.Table.indexes` 

2203 

2204 :attr:`_schema.Table.constraints`. 

2205 

2206 """ 

2207 

2208 computed: Optional[Computed] 

2209 

2210 identity: Optional[Identity] 

2211 

2212 def _set_type(self, type_: TypeEngine[Any]) -> None: 

2213 assert self.type._isnull or type_ is self.type 

2214 

2215 self.type = type_ 

2216 if isinstance(self.type, SchemaEventTarget): 

2217 self.type._set_parent_with_dispatch(self) 

2218 for impl in self.type._variant_mapping.values(): 

2219 if isinstance(impl, SchemaEventTarget): 

2220 impl._set_parent_with_dispatch(self) 

2221 

2222 @HasMemoized.memoized_attribute 

2223 def _default_description_tuple(self) -> _DefaultDescriptionTuple: 

2224 """used by default.py -> _process_execute_defaults()""" 

2225 

2226 return _DefaultDescriptionTuple._from_column_default(self.default) 

2227 

2228 @HasMemoized.memoized_attribute 

2229 def _onupdate_description_tuple(self) -> _DefaultDescriptionTuple: 

2230 """used by default.py -> _process_execute_defaults()""" 

2231 return _DefaultDescriptionTuple._from_column_default(self.onupdate) 

2232 

2233 @util.memoized_property 

2234 def _gen_static_annotations_cache_key(self) -> bool: # type: ignore 

2235 """special attribute used by cache key gen, if true, we will 

2236 use a static cache key for the annotations dictionary, else we 

2237 will generate a new cache key for annotations each time. 

2238 

2239 Added for #8790 

2240 

2241 """ 

2242 return self.table is not None and self.table._is_table 

2243 

2244 def _extra_kwargs(self, **kwargs: Any) -> None: 

2245 self._validate_dialect_kwargs(kwargs) 

2246 

2247 def __str__(self) -> str: 

2248 if self.name is None: 

2249 return "(no name)" 

2250 elif self.table is not None: 

2251 if self.table.named_with_column: 

2252 return self.table.description + "." + self.description 

2253 else: 

2254 return self.description 

2255 else: 

2256 return self.description 

2257 

2258 def references(self, column: Column[Any]) -> bool: 

2259 """Return True if this Column references the given column via foreign 

2260 key.""" 

2261 

2262 for fk in self.foreign_keys: 

2263 if fk.column.proxy_set.intersection(column.proxy_set): 

2264 return True 

2265 else: 

2266 return False 

2267 

2268 def append_foreign_key(self, fk: ForeignKey) -> None: 

2269 fk._set_parent_with_dispatch(self) 

2270 

2271 def __repr__(self) -> str: 

2272 kwarg = [] 

2273 if self.key != self.name: 

2274 kwarg.append("key") 

2275 if self.primary_key: 

2276 kwarg.append("primary_key") 

2277 if not self.nullable: 

2278 kwarg.append("nullable") 

2279 if self.onupdate: 

2280 kwarg.append("onupdate") 

2281 if self.default: 

2282 kwarg.append("default") 

2283 if self.server_default: 

2284 kwarg.append("server_default") 

2285 if self.comment: 

2286 kwarg.append("comment") 

2287 return "Column(%s)" % ", ".join( 

2288 [repr(self.name)] 

2289 + [repr(self.type)] 

2290 + [repr(x) for x in self.foreign_keys if x is not None] 

2291 + [repr(x) for x in self.constraints] 

2292 + [ 

2293 ( 

2294 self.table is not None 

2295 and "table=<%s>" % self.table.description 

2296 or "table=None" 

2297 ) 

2298 ] 

2299 + ["%s=%s" % (k, repr(getattr(self, k))) for k in kwarg] 

2300 ) 

2301 

2302 def _set_parent( # type: ignore[override] 

2303 self, 

2304 parent: SchemaEventTarget, 

2305 *, 

2306 all_names: Dict[str, Column[Any]], 

2307 allow_replacements: bool, 

2308 **kw: Any, 

2309 ) -> None: 

2310 table = parent 

2311 assert isinstance(table, Table) 

2312 if not self.name: 

2313 raise exc.ArgumentError( 

2314 "Column must be constructed with a non-blank name or " 

2315 "assign a non-blank .name before adding to a Table." 

2316 ) 

2317 

2318 self._reset_memoizations() 

2319 

2320 if self.key is None: 

2321 self.key = self.name 

2322 

2323 existing = getattr(self, "table", None) 

2324 if existing is not None and existing is not table: 

2325 raise exc.ArgumentError( 

2326 f"Column object '{self.key}' already " 

2327 f"assigned to Table '{existing.description}'" 

2328 ) 

2329 

2330 extra_remove = None 

2331 existing_col = None 

2332 conflicts_on = "" 

2333 

2334 if self.key in table._columns: 

2335 existing_col = table._columns[self.key] 

2336 if self.key == self.name: 

2337 conflicts_on = "name" 

2338 else: 

2339 conflicts_on = "key" 

2340 elif self.name in all_names: 

2341 existing_col = all_names[self.name] 

2342 extra_remove = {existing_col} 

2343 conflicts_on = "name" 

2344 

2345 if existing_col is not None: 

2346 if existing_col is not self: 

2347 if not allow_replacements: 

2348 raise exc.DuplicateColumnError( 

2349 f"A column with {conflicts_on} " 

2350 f"""'{ 

2351 self.key if conflicts_on == 'key' else self.name 

2352 }' """ 

2353 f"is already present in table '{table.name}'." 

2354 ) 

2355 for fk in existing_col.foreign_keys: 

2356 table.foreign_keys.remove(fk) 

2357 if fk.constraint in table.constraints: 

2358 # this might have been removed 

2359 # already, if it's a composite constraint 

2360 # and more than one col being replaced 

2361 table.constraints.remove(fk.constraint) 

2362 

2363 if extra_remove and existing_col is not None and self.key == self.name: 

2364 util.warn( 

2365 f'Column with user-specified key "{existing_col.key}" is ' 

2366 "being replaced with " 

2367 f'plain named column "{self.name}", ' 

2368 f'key "{existing_col.key}" is being removed. If this is a ' 

2369 "reflection operation, specify autoload_replace=False to " 

2370 "prevent this replacement." 

2371 ) 

2372 table._columns.replace(self, extra_remove=extra_remove) 

2373 all_names[self.name] = self 

2374 self.table = table 

2375 

2376 if self._insert_sentinel: 

2377 if self.table._sentinel_column is not None: 

2378 raise exc.ArgumentError( 

2379 "a Table may have only one explicit sentinel column" 

2380 ) 

2381 self.table._sentinel_column = self 

2382 

2383 if self.primary_key: 

2384 table.primary_key._replace(self) 

2385 elif self.key in table.primary_key: 

2386 raise exc.ArgumentError( 

2387 f"Trying to redefine primary-key column '{self.key}' as a " 

2388 f"non-primary-key column on table '{table.fullname}'" 

2389 ) 

2390 

2391 if self.index: 

2392 if isinstance(self.index, str): 

2393 raise exc.ArgumentError( 

2394 "The 'index' keyword argument on Column is boolean only. " 

2395 "To create indexes with a specific name, create an " 

2396 "explicit Index object external to the Table." 

2397 ) 

2398 table.append_constraint( 

2399 Index( 

2400 None, self.key, unique=bool(self.unique), _column_flag=True 

2401 ) 

2402 ) 

2403 

2404 elif self.unique: 

2405 if isinstance(self.unique, str): 

2406 raise exc.ArgumentError( 

2407 "The 'unique' keyword argument on Column is boolean " 

2408 "only. To create unique constraints or indexes with a " 

2409 "specific name, append an explicit UniqueConstraint to " 

2410 "the Table's list of elements, or create an explicit " 

2411 "Index object external to the Table." 

2412 ) 

2413 table.append_constraint( 

2414 UniqueConstraint(self.key, _column_flag=True) 

2415 ) 

2416 

2417 self._setup_on_memoized_fks(lambda fk: fk._set_remote_table(table)) 

2418 

2419 if self.identity and ( 

2420 isinstance(self.default, Sequence) 

2421 or isinstance(self.onupdate, Sequence) 

2422 ): 

2423 raise exc.ArgumentError( 

2424 "An column cannot specify both Identity and Sequence." 

2425 ) 

2426 

2427 def _setup_on_memoized_fks(self, fn: Callable[..., Any]) -> None: 

2428 fk_keys = [ 

2429 ((self.table.key, self.key), False), 

2430 ((self.table.key, self.name), True), 

2431 ] 

2432 for fk_key, link_to_name in fk_keys: 

2433 if fk_key in self.table.metadata._fk_memos: 

2434 for fk in self.table.metadata._fk_memos[fk_key]: 

2435 if fk.link_to_name is link_to_name: 

2436 fn(fk) 

2437 

2438 def _on_table_attach(self, fn: Callable[..., Any]) -> None: 

2439 if self.table is not None: 

2440 fn(self, self.table) 

2441 else: 

2442 event.listen(self, "after_parent_attach", fn) 

2443 

2444 @util.deprecated( 

2445 "1.4", 

2446 "The :meth:`_schema.Column.copy` method is deprecated " 

2447 "and will be removed in a future release.", 

2448 ) 

2449 def copy(self, **kw: Any) -> Column[Any]: 

2450 return self._copy(**kw) 

2451 

2452 def _copy(self, **kw: Any) -> Column[Any]: 

2453 """Create a copy of this ``Column``, uninitialized. 

2454 

2455 This is used in :meth:`_schema.Table.to_metadata` and by the ORM. 

2456 

2457 """ 

2458 

2459 # Constraint objects plus non-constraint-bound ForeignKey objects 

2460 args: List[SchemaItem] = [ 

2461 c._copy(**kw) for c in self.constraints if not c._type_bound 

2462 ] + [c._copy(**kw) for c in self.foreign_keys if not c.constraint] 

2463 

2464 # ticket #5276 

2465 column_kwargs = {} 

2466 for dialect_name in self.dialect_options: 

2467 dialect_options = self.dialect_options[dialect_name]._non_defaults 

2468 for ( 

2469 dialect_option_key, 

2470 dialect_option_value, 

2471 ) in dialect_options.items(): 

2472 column_kwargs[dialect_name + "_" + dialect_option_key] = ( 

2473 dialect_option_value 

2474 ) 

2475 

2476 server_default = self.server_default 

2477 server_onupdate = self.server_onupdate 

2478 if isinstance(server_default, (Computed, Identity)): 

2479 # TODO: likely should be copied in all cases 

2480 # TODO: if a Sequence, we would need to transfer the Sequence 

2481 # .metadata as well 

2482 args.append(server_default._copy(**kw)) 

2483 server_default = server_onupdate = None 

2484 

2485 type_ = self.type 

2486 if isinstance(type_, SchemaEventTarget): 

2487 type_ = type_.copy(**kw) 

2488 

2489 # TODO: DefaultGenerator is not copied here! it's just used again 

2490 # with _set_parent() pointing to the old column. see the new 

2491 # use of _copy() in the new _merge() method 

2492 

2493 c = self._constructor( 

2494 name=self.name, 

2495 type_=type_, 

2496 key=self.key, 

2497 primary_key=self.primary_key, 

2498 unique=self.unique, 

2499 system=self.system, 

2500 # quote=self.quote, # disabled 2013-08-27 (commit 031ef080) 

2501 index=self.index, 

2502 autoincrement=self.autoincrement, 

2503 default=self.default, 

2504 server_default=server_default, 

2505 onupdate=self.onupdate, 

2506 server_onupdate=server_onupdate, 

2507 doc=self.doc, 

2508 comment=self.comment, 

2509 _omit_from_statements=self._omit_from_statements, 

2510 insert_sentinel=self._insert_sentinel, 

2511 *args, 

2512 **column_kwargs, 

2513 ) 

2514 

2515 # copy the state of "nullable" exactly, to accommodate for 

2516 # ORM flipping the .nullable flag directly 

2517 c.nullable = self.nullable 

2518 c._user_defined_nullable = self._user_defined_nullable 

2519 

2520 return self._schema_item_copy(c) 

2521 

2522 def _merge(self, other: Column[Any]) -> None: 

2523 """merge the elements of another column into this one. 

2524 

2525 this is used by ORM pep-593 merge and will likely need a lot 

2526 of fixes. 

2527 

2528 

2529 """ 

2530 

2531 if self.primary_key: 

2532 other.primary_key = True 

2533 

2534 if self.autoincrement != "auto" and other.autoincrement == "auto": 

2535 other.autoincrement = self.autoincrement 

2536 

2537 if self.system: 

2538 other.system = self.system 

2539 

2540 if self.info: 

2541 other.info.update(self.info) 

2542 

2543 type_ = self.type 

2544 if not type_._isnull and other.type._isnull: 

2545 if isinstance(type_, SchemaEventTarget): 

2546 type_ = type_.copy() 

2547 

2548 other.type = type_ 

2549 

2550 if isinstance(type_, SchemaEventTarget): 

2551 type_._set_parent_with_dispatch(other) 

2552 

2553 for impl in type_._variant_mapping.values(): 

2554 if isinstance(impl, SchemaEventTarget): 

2555 impl._set_parent_with_dispatch(other) 

2556 

2557 if ( 

2558 self._user_defined_nullable is not NULL_UNSPECIFIED 

2559 and other._user_defined_nullable is NULL_UNSPECIFIED 

2560 ): 

2561 other.nullable = self.nullable 

2562 other._user_defined_nullable = self._user_defined_nullable 

2563 

2564 if self.default is not None and other.default is None: 

2565 new_default = self.default._copy() 

2566 new_default._set_parent(other) 

2567 

2568 if self.server_default and other.server_default is None: 

2569 new_server_default = self.server_default 

2570 if isinstance(new_server_default, FetchedValue): 

2571 new_server_default = new_server_default._copy() 

2572 new_server_default._set_parent(other) 

2573 else: 

2574 other.server_default = new_server_default 

2575 

2576 if self.server_onupdate and other.server_onupdate is None: 

2577 new_server_onupdate = self.server_onupdate 

2578 new_server_onupdate = new_server_onupdate._copy() 

2579 new_server_onupdate._set_parent(other) 

2580 

2581 if self.onupdate and other.onupdate is None: 

2582 new_onupdate = self.onupdate._copy() 

2583 new_onupdate._set_parent(other) 

2584 

2585 if self.index in (True, False) and other.index is None: 

2586 other.index = self.index 

2587 

2588 if self.unique in (True, False) and other.unique is None: 

2589 other.unique = self.unique 

2590 

2591 if self.doc and other.doc is None: 

2592 other.doc = self.doc 

2593 

2594 if self.comment and other.comment is None: 

2595 other.comment = self.comment 

2596 

2597 for const in self.constraints: 

2598 if not const._type_bound: 

2599 new_const = const._copy() 

2600 new_const._set_parent(other) 

2601 

2602 for fk in self.foreign_keys: 

2603 if not fk.constraint: 

2604 new_fk = fk._copy() 

2605 new_fk._set_parent(other) 

2606 

2607 def _make_proxy( 

2608 self, 

2609 selectable: FromClause, 

2610 name: Optional[str] = None, 

2611 key: Optional[str] = None, 

2612 name_is_truncatable: bool = False, 

2613 compound_select_cols: Optional[ 

2614 _typing_Sequence[ColumnElement[Any]] 

2615 ] = None, 

2616 **kw: Any, 

2617 ) -> Tuple[str, ColumnClause[_T]]: 

2618 """Create a *proxy* for this column. 

2619 

2620 This is a copy of this ``Column`` referenced by a different parent 

2621 (such as an alias or select statement). The column should 

2622 be used only in select scenarios, as its full DDL/default 

2623 information is not transferred. 

2624 

2625 """ 

2626 

2627 fk = [ 

2628 ForeignKey( 

2629 col if col is not None else f._colspec, 

2630 _unresolvable=col is None, 

2631 _constraint=f.constraint, 

2632 ) 

2633 for f, col in [ 

2634 (fk, fk._resolve_column(raiseerr=False)) 

2635 for fk in self.foreign_keys 

2636 ] 

2637 ] 

2638 

2639 if name is None and self.name is None: 

2640 raise exc.InvalidRequestError( 

2641 "Cannot initialize a sub-selectable" 

2642 " with this Column object until its 'name' has " 

2643 "been assigned." 

2644 ) 

2645 try: 

2646 c = self._constructor( 

2647 ( 

2648 coercions.expect( 

2649 roles.TruncatedLabelRole, name if name else self.name 

2650 ) 

2651 if name_is_truncatable 

2652 else (name or self.name) 

2653 ), 

2654 self.type, 

2655 # this may actually be ._proxy_key when the key is incoming 

2656 key=key if key else name if name else self.key, 

2657 primary_key=self.primary_key, 

2658 nullable=self.nullable, 

2659 _proxies=( 

2660 list(compound_select_cols) 

2661 if compound_select_cols 

2662 else [self] 

2663 ), 

2664 *fk, 

2665 ) 

2666 except TypeError as err: 

2667 raise TypeError( 

2668 "Could not create a copy of this %r object. " 

2669 "Ensure the class includes a _constructor() " 

2670 "attribute or method which accepts the " 

2671 "standard Column constructor arguments, or " 

2672 "references the Column class itself." % self.__class__ 

2673 ) from err 

2674 

2675 c.table = selectable 

2676 c._propagate_attrs = selectable._propagate_attrs 

2677 if selectable._is_clone_of is not None: 

2678 c._is_clone_of = selectable._is_clone_of.columns.get(c.key) 

2679 if self.primary_key: 

2680 selectable.primary_key.add(c) # type: ignore 

2681 if fk: 

2682 selectable.foreign_keys.update(fk) # type: ignore 

2683 return c.key, c 

2684 

2685 

2686def insert_sentinel( 

2687 name: Optional[str] = None, 

2688 type_: Optional[_TypeEngineArgument[_T]] = None, 

2689 *, 

2690 default: Optional[Any] = None, 

2691 omit_from_statements: bool = True, 

2692) -> Column[Any]: 

2693 """Provides a surrogate :class:`_schema.Column` that will act as a 

2694 dedicated insert :term:`sentinel` column, allowing efficient bulk 

2695 inserts with deterministic RETURNING sorting for tables that 

2696 don't otherwise have qualifying primary key configurations. 

2697 

2698 Adding this column to a :class:`.Table` object requires that a 

2699 corresponding database table actually has this column present, so if adding 

2700 it to an existing model, existing database tables would need to be migrated 

2701 (e.g. using ALTER TABLE or similar) to include this column. 

2702 

2703 For background on how this object is used, see the section 

2704 :ref:`engine_insertmanyvalues_sentinel_columns` as part of the 

2705 section :ref:`engine_insertmanyvalues`. 

2706 

2707 The :class:`_schema.Column` returned will be a nullable integer column by 

2708 default and make use of a sentinel-specific default generator used only in 

2709 "insertmanyvalues" operations. 

2710 

2711 .. seealso:: 

2712 

2713 :func:`_orm.orm_insert_sentinel` 

2714 

2715 :paramref:`_schema.Column.insert_sentinel` 

2716 

2717 :ref:`engine_insertmanyvalues` 

2718 

2719 :ref:`engine_insertmanyvalues_sentinel_columns` 

2720 

2721 

2722 .. versionadded:: 2.0.10 

2723 

2724 """ 

2725 return Column( 

2726 name=name, 

2727 type_=type_api.INTEGERTYPE if type_ is None else type_, 

2728 default=( 

2729 default if default is not None else _InsertSentinelColumnDefault() 

2730 ), 

2731 _omit_from_statements=omit_from_statements, 

2732 insert_sentinel=True, 

2733 ) 

2734 

2735 

2736class ForeignKey(DialectKWArgs, SchemaItem): 

2737 """Defines a dependency between two columns. 

2738 

2739 ``ForeignKey`` is specified as an argument to a :class:`_schema.Column` 

2740 object, 

2741 e.g.:: 

2742 

2743 t = Table("remote_table", metadata, 

2744 Column("remote_id", ForeignKey("main_table.id")) 

2745 ) 

2746 

2747 Note that ``ForeignKey`` is only a marker object that defines 

2748 a dependency between two columns. The actual constraint 

2749 is in all cases represented by the :class:`_schema.ForeignKeyConstraint` 

2750 object. This object will be generated automatically when 

2751 a ``ForeignKey`` is associated with a :class:`_schema.Column` which 

2752 in turn is associated with a :class:`_schema.Table`. Conversely, 

2753 when :class:`_schema.ForeignKeyConstraint` is applied to a 

2754 :class:`_schema.Table`, 

2755 ``ForeignKey`` markers are automatically generated to be 

2756 present on each associated :class:`_schema.Column`, which are also 

2757 associated with the constraint object. 

2758 

2759 Note that you cannot define a "composite" foreign key constraint, 

2760 that is a constraint between a grouping of multiple parent/child 

2761 columns, using ``ForeignKey`` objects. To define this grouping, 

2762 the :class:`_schema.ForeignKeyConstraint` object must be used, and applied 

2763 to the :class:`_schema.Table`. The associated ``ForeignKey`` objects 

2764 are created automatically. 

2765 

2766 The ``ForeignKey`` objects associated with an individual 

2767 :class:`_schema.Column` 

2768 object are available in the `foreign_keys` collection 

2769 of that column. 

2770 

2771 Further examples of foreign key configuration are in 

2772 :ref:`metadata_foreignkeys`. 

2773 

2774 """ 

2775 

2776 __visit_name__ = "foreign_key" 

2777 

2778 parent: Column[Any] 

2779 

2780 _table_column: Optional[Column[Any]] 

2781 

2782 _colspec: Union[str, Column[Any]] 

2783 

2784 def __init__( 

2785 self, 

2786 column: _DDLColumnReferenceArgument, 

2787 _constraint: Optional[ForeignKeyConstraint] = None, 

2788 use_alter: bool = False, 

2789 name: _ConstraintNameArgument = None, 

2790 onupdate: Optional[str] = None, 

2791 ondelete: Optional[str] = None, 

2792 deferrable: Optional[bool] = None, 

2793 initially: Optional[str] = None, 

2794 link_to_name: bool = False, 

2795 match: Optional[str] = None, 

2796 info: Optional[_InfoType] = None, 

2797 comment: Optional[str] = None, 

2798 _unresolvable: bool = False, 

2799 **dialect_kw: Any, 

2800 ): 

2801 r""" 

2802 Construct a column-level FOREIGN KEY. 

2803 

2804 The :class:`_schema.ForeignKey` object when constructed generates a 

2805 :class:`_schema.ForeignKeyConstraint` 

2806 which is associated with the parent 

2807 :class:`_schema.Table` object's collection of constraints. 

2808 

2809 :param column: A single target column for the key relationship. A 

2810 :class:`_schema.Column` object or a column name as a string: 

2811 ``tablename.columnkey`` or ``schema.tablename.columnkey``. 

2812 ``columnkey`` is the ``key`` which has been assigned to the column 

2813 (defaults to the column name itself), unless ``link_to_name`` is 

2814 ``True`` in which case the rendered name of the column is used. 

2815 

2816 :param name: Optional string. An in-database name for the key if 

2817 `constraint` is not provided. 

2818 

2819 :param onupdate: Optional string. If set, emit ON UPDATE <value> when 

2820 issuing DDL for this constraint. Typical values include CASCADE, 

2821 DELETE and RESTRICT. 

2822 

2823 :param ondelete: Optional string. If set, emit ON DELETE <value> when 

2824 issuing DDL for this constraint. Typical values include CASCADE, 

2825 DELETE and RESTRICT. 

2826 

2827 :param deferrable: Optional bool. If set, emit DEFERRABLE or NOT 

2828 DEFERRABLE when issuing DDL for this constraint. 

2829 

2830 :param initially: Optional string. If set, emit INITIALLY <value> when 

2831 issuing DDL for this constraint. 

2832 

2833 :param link_to_name: if True, the string name given in ``column`` is 

2834 the rendered name of the referenced column, not its locally 

2835 assigned ``key``. 

2836 

2837 :param use_alter: passed to the underlying 

2838 :class:`_schema.ForeignKeyConstraint` 

2839 to indicate the constraint should 

2840 be generated/dropped externally from the CREATE TABLE/ DROP TABLE 

2841 statement. See :paramref:`_schema.ForeignKeyConstraint.use_alter` 

2842 for further description. 

2843 

2844 .. seealso:: 

2845 

2846 :paramref:`_schema.ForeignKeyConstraint.use_alter` 

2847 

2848 :ref:`use_alter` 

2849 

2850 :param match: Optional string. If set, emit MATCH <value> when issuing 

2851 DDL for this constraint. Typical values include SIMPLE, PARTIAL 

2852 and FULL. 

2853 

2854 :param info: Optional data dictionary which will be populated into the 

2855 :attr:`.SchemaItem.info` attribute of this object. 

2856 

2857 :param comment: Optional string that will render an SQL comment on 

2858 foreign key constraint creation. 

2859 

2860 .. versionadded:: 2.0 

2861 

2862 :param \**dialect_kw: Additional keyword arguments are dialect 

2863 specific, and passed in the form ``<dialectname>_<argname>``. The 

2864 arguments are ultimately handled by a corresponding 

2865 :class:`_schema.ForeignKeyConstraint`. 

2866 See the documentation regarding 

2867 an individual dialect at :ref:`dialect_toplevel` for detail on 

2868 documented arguments. 

2869 

2870 """ 

2871 

2872 self._unresolvable = _unresolvable 

2873 

2874 self._colspec, self._table_column = self._parse_colspec_argument( 

2875 column 

2876 ) 

2877 

2878 # the linked ForeignKeyConstraint. 

2879 # ForeignKey will create this when parent Column 

2880 # is attached to a Table, *or* ForeignKeyConstraint 

2881 # object passes itself in when creating ForeignKey 

2882 # markers. 

2883 self.constraint = _constraint 

2884 

2885 # .parent is not Optional under normal use 

2886 self.parent = None # type: ignore 

2887 

2888 self.use_alter = use_alter 

2889 self.name = name 

2890 self.onupdate = onupdate 

2891 self.ondelete = ondelete 

2892 self.deferrable = deferrable 

2893 self.initially = initially 

2894 self.link_to_name = link_to_name 

2895 self.match = match 

2896 self.comment = comment 

2897 if info: 

2898 self.info = info 

2899 self._unvalidated_dialect_kw = dialect_kw 

2900 

2901 def _resolve_colspec_argument( 

2902 self, 

2903 ) -> Tuple[ 

2904 Union[str, Column[Any]], 

2905 Optional[Column[Any]], 

2906 ]: 

2907 argument = self._colspec 

2908 

2909 return self._parse_colspec_argument(argument) 

2910 

2911 def _parse_colspec_argument( 

2912 self, 

2913 argument: _DDLColumnArgument, 

2914 ) -> Tuple[ 

2915 Union[str, Column[Any]], 

2916 Optional[Column[Any]], 

2917 ]: 

2918 _colspec = coercions.expect(roles.DDLReferredColumnRole, argument) 

2919 

2920 if isinstance(_colspec, str): 

2921 _table_column = None 

2922 else: 

2923 assert isinstance(_colspec, ColumnClause) 

2924 _table_column = _colspec 

2925 

2926 if not isinstance(_table_column.table, (type(None), TableClause)): 

2927 raise exc.ArgumentError( 

2928 "ForeignKey received Column not bound " 

2929 "to a Table, got: %r" % _table_column.table 

2930 ) 

2931 

2932 return _colspec, _table_column 

2933 

2934 def __repr__(self) -> str: 

2935 return "ForeignKey(%r)" % self._get_colspec() 

2936 

2937 @util.deprecated( 

2938 "1.4", 

2939 "The :meth:`_schema.ForeignKey.copy` method is deprecated " 

2940 "and will be removed in a future release.", 

2941 ) 

2942 def copy(self, *, schema: Optional[str] = None, **kw: Any) -> ForeignKey: 

2943 return self._copy(schema=schema, **kw) 

2944 

2945 def _copy(self, *, schema: Optional[str] = None, **kw: Any) -> ForeignKey: 

2946 """Produce a copy of this :class:`_schema.ForeignKey` object. 

2947 

2948 The new :class:`_schema.ForeignKey` will not be bound 

2949 to any :class:`_schema.Column`. 

2950 

2951 This method is usually used by the internal 

2952 copy procedures of :class:`_schema.Column`, :class:`_schema.Table`, 

2953 and :class:`_schema.MetaData`. 

2954 

2955 :param schema: The returned :class:`_schema.ForeignKey` will 

2956 reference the original table and column name, qualified 

2957 by the given string schema name. 

2958 

2959 """ 

2960 fk = ForeignKey( 

2961 self._get_colspec(schema=schema), 

2962 use_alter=self.use_alter, 

2963 name=self.name, 

2964 onupdate=self.onupdate, 

2965 ondelete=self.ondelete, 

2966 deferrable=self.deferrable, 

2967 initially=self.initially, 

2968 link_to_name=self.link_to_name, 

2969 match=self.match, 

2970 comment=self.comment, 

2971 **self._unvalidated_dialect_kw, 

2972 ) 

2973 return self._schema_item_copy(fk) 

2974 

2975 def _get_colspec( 

2976 self, 

2977 schema: Optional[ 

2978 Union[ 

2979 str, 

2980 Literal[SchemaConst.RETAIN_SCHEMA, SchemaConst.BLANK_SCHEMA], 

2981 ] 

2982 ] = None, 

2983 table_name: Optional[str] = None, 

2984 _is_copy: bool = False, 

2985 ) -> str: 

2986 """Return a string based 'column specification' for this 

2987 :class:`_schema.ForeignKey`. 

2988 

2989 This is usually the equivalent of the string-based "tablename.colname" 

2990 argument first passed to the object's constructor. 

2991 

2992 """ 

2993 

2994 _colspec, effective_table_column = self._resolve_colspec_argument() 

2995 

2996 if schema not in (None, RETAIN_SCHEMA): 

2997 _schema, tname, colname = self._column_tokens 

2998 if table_name is not None: 

2999 tname = table_name 

3000 if schema is BLANK_SCHEMA: 

3001 return "%s.%s" % (tname, colname) 

3002 else: 

3003 return "%s.%s.%s" % (schema, tname, colname) 

3004 elif table_name: 

3005 schema, tname, colname = self._column_tokens 

3006 if schema: 

3007 return "%s.%s.%s" % (schema, table_name, colname) 

3008 else: 

3009 return "%s.%s" % (table_name, colname) 

3010 elif effective_table_column is not None: 

3011 if effective_table_column.table is None: 

3012 if _is_copy: 

3013 raise exc.InvalidRequestError( 

3014 f"Can't copy ForeignKey object which refers to " 

3015 f"non-table bound Column {effective_table_column!r}" 

3016 ) 

3017 else: 

3018 return effective_table_column.key 

3019 return "%s.%s" % ( 

3020 effective_table_column.table.fullname, 

3021 effective_table_column.key, 

3022 ) 

3023 else: 

3024 assert isinstance(_colspec, str) 

3025 return _colspec 

3026 

3027 @property 

3028 def _referred_schema(self) -> Optional[str]: 

3029 return self._column_tokens[0] 

3030 

3031 def _table_key_within_construction(self) -> Any: 

3032 """get the table key but only safely""" 

3033 

3034 if self._table_column is not None: 

3035 if self._table_column.table is None: 

3036 return None 

3037 else: 

3038 return self._table_column.table.key 

3039 else: 

3040 schema, tname, colname = self._column_tokens 

3041 return _get_table_key(tname, schema) 

3042 

3043 target_fullname = property(_get_colspec) 

3044 

3045 def references(self, table: Table) -> bool: 

3046 """Return True if the given :class:`_schema.Table` 

3047 is referenced by this 

3048 :class:`_schema.ForeignKey`.""" 

3049 

3050 return table.corresponding_column(self.column) is not None 

3051 

3052 def get_referent(self, table: FromClause) -> Optional[Column[Any]]: 

3053 """Return the :class:`_schema.Column` in the given 

3054 :class:`_schema.Table` (or any :class:`.FromClause`) 

3055 referenced by this :class:`_schema.ForeignKey`. 

3056 

3057 Returns None if this :class:`_schema.ForeignKey` 

3058 does not reference the given 

3059 :class:`_schema.Table`. 

3060 

3061 """ 

3062 # our column is a Column, and any subquery etc. proxying us 

3063 # would be doing so via another Column, so that's what would 

3064 # be returned here 

3065 return table.columns.corresponding_column(self.column) # type: ignore 

3066 

3067 @util.memoized_property 

3068 def _column_tokens(self) -> Tuple[Optional[str], str, Optional[str]]: 

3069 """parse a string-based _colspec into its component parts.""" 

3070 

3071 m = self._get_colspec().split(".") 

3072 if len(m) == 1: 

3073 tname = m.pop() 

3074 colname = None 

3075 else: 

3076 colname = m.pop() 

3077 tname = m.pop() 

3078 

3079 # A FK between column 'bar' and table 'foo' can be 

3080 # specified as 'foo', 'foo.bar', 'dbo.foo.bar', 

3081 # 'otherdb.dbo.foo.bar'. Once we have the column name and 

3082 # the table name, treat everything else as the schema 

3083 # name. Some databases (e.g. Sybase) support 

3084 # inter-database foreign keys. See tickets#1341 and -- 

3085 # indirectly related -- Ticket #594. This assumes that '.' 

3086 # will never appear *within* any component of the FK. 

3087 

3088 if len(m) > 0: 

3089 schema = ".".join(m) 

3090 else: 

3091 schema = None 

3092 return schema, tname, colname 

3093 

3094 def _resolve_col_tokens(self) -> Tuple[Table, str, Optional[str]]: 

3095 if self.parent is None: 

3096 raise exc.InvalidRequestError( 

3097 "this ForeignKey object does not yet have a " 

3098 "parent Column associated with it." 

3099 ) 

3100 

3101 elif self.parent.table is None: 

3102 raise exc.InvalidRequestError( 

3103 "this ForeignKey's parent column is not yet associated " 

3104 "with a Table." 

3105 ) 

3106 

3107 parenttable = self.parent.table 

3108 

3109 if self._unresolvable: 

3110 schema, tname, colname = self._column_tokens 

3111 tablekey = _get_table_key(tname, schema) 

3112 return parenttable, tablekey, colname 

3113 

3114 # assertion 

3115 # basically Column._make_proxy() sends the actual 

3116 # target Column to the ForeignKey object, so the 

3117 # string resolution here is never called. 

3118 for c in self.parent.base_columns: 

3119 if isinstance(c, Column): 

3120 assert c.table is parenttable 

3121 break 

3122 else: 

3123 assert False 

3124 ###################### 

3125 

3126 schema, tname, colname = self._column_tokens 

3127 

3128 if schema is None and parenttable.metadata.schema is not None: 

3129 schema = parenttable.metadata.schema 

3130 

3131 tablekey = _get_table_key(tname, schema) 

3132 return parenttable, tablekey, colname 

3133 

3134 def _link_to_col_by_colstring( 

3135 self, parenttable: Table, table: Table, colname: Optional[str] 

3136 ) -> Column[Any]: 

3137 _column = None 

3138 if colname is None: 

3139 # colname is None in the case that ForeignKey argument 

3140 # was specified as table name only, in which case we 

3141 # match the column name to the same column on the 

3142 # parent. 

3143 # this use case wasn't working in later 1.x series 

3144 # as it had no test coverage; fixed in 2.0 

3145 parent = self.parent 

3146 assert parent is not None 

3147 key = parent.key 

3148 _column = table.c.get(key, None) 

3149 elif self.link_to_name: 

3150 key = colname 

3151 for c in table.c: 

3152 if c.name == colname: 

3153 _column = c 

3154 else: 

3155 key = colname 

3156 _column = table.c.get(colname, None) 

3157 

3158 if _column is None: 

3159 raise exc.NoReferencedColumnError( 

3160 "Could not initialize target column " 

3161 f"for ForeignKey '{self._get_colspec()}' " 

3162 f"on table '{parenttable.name}': " 

3163 f"table '{table.name}' has no column named '{key}'", 

3164 table.name, 

3165 key, 

3166 ) 

3167 

3168 return _column 

3169 

3170 def _set_target_column(self, column: Column[Any]) -> None: 

3171 assert self.parent is not None 

3172 

3173 # propagate TypeEngine to parent if it didn't have one 

3174 if self.parent.type._isnull: 

3175 self.parent.type = column.type 

3176 

3177 # super-edgy case, if other FKs point to our column, 

3178 # they'd get the type propagated out also. 

3179 

3180 def set_type(fk: ForeignKey) -> None: 

3181 if fk.parent.type._isnull: 

3182 fk.parent.type = column.type 

3183 

3184 self.parent._setup_on_memoized_fks(set_type) 

3185 

3186 self.column = column # type: ignore 

3187 

3188 @util.ro_memoized_property 

3189 def column(self) -> Column[Any]: 

3190 """Return the target :class:`_schema.Column` referenced by this 

3191 :class:`_schema.ForeignKey`. 

3192 

3193 If no target column has been established, an exception 

3194 is raised. 

3195 

3196 """ 

3197 return self._resolve_column() 

3198 

3199 @overload 

3200 def _resolve_column( 

3201 self, *, raiseerr: Literal[True] = ... 

3202 ) -> Column[Any]: ... 

3203 

3204 @overload 

3205 def _resolve_column( 

3206 self, *, raiseerr: bool = ... 

3207 ) -> Optional[Column[Any]]: ... 

3208 

3209 def _resolve_column( 

3210 self, *, raiseerr: bool = True 

3211 ) -> Optional[Column[Any]]: 

3212 _column: Column[Any] 

3213 

3214 _colspec, effective_table_column = self._resolve_colspec_argument() 

3215 

3216 if isinstance(_colspec, str): 

3217 parenttable, tablekey, colname = self._resolve_col_tokens() 

3218 

3219 if self._unresolvable or tablekey not in parenttable.metadata: 

3220 if not raiseerr: 

3221 return None 

3222 raise exc.NoReferencedTableError( 

3223 f"Foreign key associated with column " 

3224 f"'{self.parent}' could not find " 

3225 f"table '{tablekey}' with which to generate a " 

3226 f"foreign key to target column '{colname}'", 

3227 tablekey, 

3228 ) 

3229 elif parenttable.key not in parenttable.metadata: 

3230 if not raiseerr: 

3231 return None 

3232 raise exc.InvalidRequestError( 

3233 f"Table {parenttable} is no longer associated with its " 

3234 "parent MetaData" 

3235 ) 

3236 else: 

3237 table = parenttable.metadata.tables[tablekey] 

3238 return self._link_to_col_by_colstring( 

3239 parenttable, table, colname 

3240 ) 

3241 

3242 elif hasattr(_colspec, "__clause_element__"): 

3243 _column = _colspec.__clause_element__() 

3244 return _column 

3245 else: 

3246 assert isinstance(_colspec, Column) 

3247 _column = _colspec 

3248 return _column 

3249 

3250 def _set_parent(self, parent: SchemaEventTarget, **kw: Any) -> None: 

3251 assert isinstance(parent, Column) 

3252 

3253 if self.parent is not None and self.parent is not parent: 

3254 raise exc.InvalidRequestError( 

3255 "This ForeignKey already has a parent !" 

3256 ) 

3257 self.parent = parent 

3258 self.parent.foreign_keys.add(self) 

3259 self.parent._on_table_attach(self._set_table) 

3260 

3261 def _set_remote_table(self, table: Table) -> None: 

3262 parenttable, _, colname = self._resolve_col_tokens() 

3263 _column = self._link_to_col_by_colstring(parenttable, table, colname) 

3264 self._set_target_column(_column) 

3265 assert self.constraint is not None 

3266 self.constraint._validate_dest_table(table) 

3267 

3268 def _remove_from_metadata(self, metadata: MetaData) -> None: 

3269 parenttable, table_key, colname = self._resolve_col_tokens() 

3270 fk_key = (table_key, colname) 

3271 

3272 if self in metadata._fk_memos[fk_key]: 

3273 # TODO: no test coverage for self not in memos 

3274 metadata._fk_memos[fk_key].remove(self) 

3275 

3276 def _set_table(self, column: Column[Any], table: Table) -> None: 

3277 # standalone ForeignKey - create ForeignKeyConstraint 

3278 # on the hosting Table when attached to the Table. 

3279 assert isinstance(table, Table) 

3280 if self.constraint is None: 

3281 self.constraint = ForeignKeyConstraint( 

3282 [], 

3283 [], 

3284 use_alter=self.use_alter, 

3285 name=self.name, 

3286 onupdate=self.onupdate, 

3287 ondelete=self.ondelete, 

3288 deferrable=self.deferrable, 

3289 initially=self.initially, 

3290 match=self.match, 

3291 comment=self.comment, 

3292 **self._unvalidated_dialect_kw, 

3293 ) 

3294 self.constraint._append_element(column, self) 

3295 self.constraint._set_parent_with_dispatch(table) 

3296 table.foreign_keys.add(self) 

3297 # set up remote ".column" attribute, or a note to pick it 

3298 # up when the other Table/Column shows up 

3299 

3300 _colspec, _ = self._resolve_colspec_argument() 

3301 if isinstance(_colspec, str): 

3302 parenttable, table_key, colname = self._resolve_col_tokens() 

3303 fk_key = (table_key, colname) 

3304 if table_key in parenttable.metadata.tables: 

3305 table = parenttable.metadata.tables[table_key] 

3306 try: 

3307 _column = self._link_to_col_by_colstring( 

3308 parenttable, table, colname 

3309 ) 

3310 except exc.NoReferencedColumnError: 

3311 # this is OK, we'll try later 

3312 pass 

3313 else: 

3314 self._set_target_column(_column) 

3315 

3316 parenttable.metadata._fk_memos[fk_key].append(self) 

3317 elif hasattr(_colspec, "__clause_element__"): 

3318 _column = _colspec.__clause_element__() 

3319 self._set_target_column(_column) 

3320 else: 

3321 self._set_target_column(_colspec) 

3322 

3323 

3324if TYPE_CHECKING: 

3325 

3326 def default_is_sequence( 

3327 obj: Optional[DefaultGenerator], 

3328 ) -> TypeGuard[Sequence]: ... 

3329 

3330 def default_is_clause_element( 

3331 obj: Optional[DefaultGenerator], 

3332 ) -> TypeGuard[ColumnElementColumnDefault]: ... 

3333 

3334 def default_is_scalar( 

3335 obj: Optional[DefaultGenerator], 

3336 ) -> TypeGuard[ScalarElementColumnDefault]: ... 

3337 

3338else: 

3339 default_is_sequence = operator.attrgetter("is_sequence") 

3340 

3341 default_is_clause_element = operator.attrgetter("is_clause_element") 

3342 

3343 default_is_scalar = operator.attrgetter("is_scalar") 

3344 

3345 

3346class DefaultGenerator(Executable, SchemaItem): 

3347 """Base class for column *default* values. 

3348 

3349 This object is only present on column.default or column.onupdate. 

3350 It's not valid as a server default. 

3351 

3352 """ 

3353 

3354 __visit_name__ = "default_generator" 

3355 

3356 _is_default_generator = True 

3357 is_sequence = False 

3358 is_identity = False 

3359 is_server_default = False 

3360 is_clause_element = False 

3361 is_callable = False 

3362 is_scalar = False 

3363 has_arg = False 

3364 is_sentinel = False 

3365 column: Optional[Column[Any]] 

3366 

3367 def __init__(self, for_update: bool = False) -> None: 

3368 self.for_update = for_update 

3369 

3370 def _set_parent(self, parent: SchemaEventTarget, **kw: Any) -> None: 

3371 if TYPE_CHECKING: 

3372 assert isinstance(parent, Column) 

3373 self.column = parent 

3374 if self.for_update: 

3375 self.column.onupdate = self 

3376 else: 

3377 self.column.default = self 

3378 

3379 def _copy(self) -> DefaultGenerator: 

3380 raise NotImplementedError() 

3381 

3382 def _execute_on_connection( 

3383 self, 

3384 connection: Connection, 

3385 distilled_params: _CoreMultiExecuteParams, 

3386 execution_options: CoreExecuteOptionsParameter, 

3387 ) -> Any: 

3388 util.warn_deprecated( 

3389 "Using the .execute() method to invoke a " 

3390 "DefaultGenerator object is deprecated; please use " 

3391 "the .scalar() method.", 

3392 "2.0", 

3393 ) 

3394 return self._execute_on_scalar( 

3395 connection, distilled_params, execution_options 

3396 ) 

3397 

3398 def _execute_on_scalar( 

3399 self, 

3400 connection: Connection, 

3401 distilled_params: _CoreMultiExecuteParams, 

3402 execution_options: CoreExecuteOptionsParameter, 

3403 ) -> Any: 

3404 return connection._execute_default( 

3405 self, distilled_params, execution_options 

3406 ) 

3407 

3408 

3409class ColumnDefault(DefaultGenerator, ABC): 

3410 """A plain default value on a column. 

3411 

3412 This could correspond to a constant, a callable function, 

3413 or a SQL clause. 

3414 

3415 :class:`.ColumnDefault` is generated automatically 

3416 whenever the ``default``, ``onupdate`` arguments of 

3417 :class:`_schema.Column` are used. A :class:`.ColumnDefault` 

3418 can be passed positionally as well. 

3419 

3420 For example, the following:: 

3421 

3422 Column('foo', Integer, default=50) 

3423 

3424 Is equivalent to:: 

3425 

3426 Column('foo', Integer, ColumnDefault(50)) 

3427 

3428 

3429 """ 

3430 

3431 arg: Any 

3432 

3433 @overload 

3434 def __new__( 

3435 cls, arg: Callable[..., Any], for_update: bool = ... 

3436 ) -> CallableColumnDefault: ... 

3437 

3438 @overload 

3439 def __new__( 

3440 cls, arg: ColumnElement[Any], for_update: bool = ... 

3441 ) -> ColumnElementColumnDefault: ... 

3442 

3443 # if I return ScalarElementColumnDefault here, which is what's actually 

3444 # returned, mypy complains that 

3445 # overloads overlap w/ incompatible return types. 

3446 @overload 

3447 def __new__(cls, arg: object, for_update: bool = ...) -> ColumnDefault: ... 

3448 

3449 def __new__( 

3450 cls, arg: Any = None, for_update: bool = False 

3451 ) -> ColumnDefault: 

3452 """Construct a new :class:`.ColumnDefault`. 

3453 

3454 

3455 :param arg: argument representing the default value. 

3456 May be one of the following: 

3457 

3458 * a plain non-callable Python value, such as a 

3459 string, integer, boolean, or other simple type. 

3460 The default value will be used as is each time. 

3461 * a SQL expression, that is one which derives from 

3462 :class:`_expression.ColumnElement`. The SQL expression will 

3463 be rendered into the INSERT or UPDATE statement, 

3464 or in the case of a primary key column when 

3465 RETURNING is not used may be 

3466 pre-executed before an INSERT within a SELECT. 

3467 * A Python callable. The function will be invoked for each 

3468 new row subject to an INSERT or UPDATE. 

3469 The callable must accept exactly 

3470 zero or one positional arguments. The one-argument form 

3471 will receive an instance of the :class:`.ExecutionContext`, 

3472 which provides contextual information as to the current 

3473 :class:`_engine.Connection` in use as well as the current 

3474 statement and parameters. 

3475 

3476 """ 

3477 

3478 if isinstance(arg, FetchedValue): 

3479 raise exc.ArgumentError( 

3480 "ColumnDefault may not be a server-side default type." 

3481 ) 

3482 elif callable(arg): 

3483 cls = CallableColumnDefault 

3484 elif isinstance(arg, ClauseElement): 

3485 cls = ColumnElementColumnDefault 

3486 elif arg is not None: 

3487 cls = ScalarElementColumnDefault 

3488 

3489 return object.__new__(cls) 

3490 

3491 def __repr__(self) -> str: 

3492 return f"{self.__class__.__name__}({self.arg!r})" 

3493 

3494 

3495class ScalarElementColumnDefault(ColumnDefault): 

3496 """default generator for a fixed scalar Python value 

3497 

3498 .. versionadded: 2.0 

3499 

3500 """ 

3501 

3502 is_scalar = True 

3503 has_arg = True 

3504 

3505 def __init__(self, arg: Any, for_update: bool = False) -> None: 

3506 self.for_update = for_update 

3507 self.arg = arg 

3508 

3509 def _copy(self) -> ScalarElementColumnDefault: 

3510 return ScalarElementColumnDefault( 

3511 arg=self.arg, for_update=self.for_update 

3512 ) 

3513 

3514 

3515class _InsertSentinelColumnDefault(ColumnDefault): 

3516 """Default generator that's specific to the use of a "sentinel" column 

3517 when using the insertmanyvalues feature. 

3518 

3519 This default is used as part of the :func:`_schema.insert_sentinel` 

3520 construct. 

3521 

3522 """ 

3523 

3524 is_sentinel = True 

3525 for_update = False 

3526 arg = None 

3527 

3528 def __new__(cls) -> _InsertSentinelColumnDefault: 

3529 return object.__new__(cls) 

3530 

3531 def __init__(self) -> None: 

3532 pass 

3533 

3534 def _set_parent(self, parent: SchemaEventTarget, **kw: Any) -> None: 

3535 col = cast("Column[Any]", parent) 

3536 if not col._insert_sentinel: 

3537 raise exc.ArgumentError( 

3538 "The _InsertSentinelColumnDefault may only be applied to a " 

3539 "Column marked as insert_sentinel=True" 

3540 ) 

3541 elif not col.nullable: 

3542 raise exc.ArgumentError( 

3543 "The _InsertSentinelColumnDefault may only be applied to a " 

3544 "Column that is nullable" 

3545 ) 

3546 

3547 super()._set_parent(parent, **kw) 

3548 

3549 def _copy(self) -> _InsertSentinelColumnDefault: 

3550 return _InsertSentinelColumnDefault() 

3551 

3552 

3553_SQLExprDefault = Union["ColumnElement[Any]", "TextClause"] 

3554 

3555 

3556class ColumnElementColumnDefault(ColumnDefault): 

3557 """default generator for a SQL expression 

3558 

3559 .. versionadded:: 2.0 

3560 

3561 """ 

3562 

3563 is_clause_element = True 

3564 has_arg = True 

3565 arg: _SQLExprDefault 

3566 

3567 def __init__( 

3568 self, 

3569 arg: _SQLExprDefault, 

3570 for_update: bool = False, 

3571 ) -> None: 

3572 self.for_update = for_update 

3573 self.arg = arg 

3574 

3575 def _copy(self) -> ColumnElementColumnDefault: 

3576 return ColumnElementColumnDefault( 

3577 arg=self.arg, for_update=self.for_update 

3578 ) 

3579 

3580 @util.memoized_property 

3581 @util.preload_module("sqlalchemy.sql.sqltypes") 

3582 def _arg_is_typed(self) -> bool: 

3583 sqltypes = util.preloaded.sql_sqltypes 

3584 

3585 return not isinstance(self.arg.type, sqltypes.NullType) 

3586 

3587 

3588class _CallableColumnDefaultProtocol(Protocol): 

3589 def __call__(self, context: ExecutionContext) -> Any: ... 

3590 

3591 

3592class CallableColumnDefault(ColumnDefault): 

3593 """default generator for a callable Python function 

3594 

3595 .. versionadded:: 2.0 

3596 

3597 """ 

3598 

3599 is_callable = True 

3600 arg: _CallableColumnDefaultProtocol 

3601 has_arg = True 

3602 

3603 def __init__( 

3604 self, 

3605 arg: Union[_CallableColumnDefaultProtocol, Callable[[], Any]], 

3606 for_update: bool = False, 

3607 ) -> None: 

3608 self.for_update = for_update 

3609 self.arg = self._maybe_wrap_callable(arg) 

3610 

3611 def _copy(self) -> CallableColumnDefault: 

3612 return CallableColumnDefault(arg=self.arg, for_update=self.for_update) 

3613 

3614 def _maybe_wrap_callable( 

3615 self, fn: Union[_CallableColumnDefaultProtocol, Callable[[], Any]] 

3616 ) -> _CallableColumnDefaultProtocol: 

3617 """Wrap callables that don't accept a context. 

3618 

3619 This is to allow easy compatibility with default callables 

3620 that aren't specific to accepting of a context. 

3621 

3622 """ 

3623 

3624 try: 

3625 argspec = util.get_callable_argspec(fn, no_self=True) 

3626 except TypeError: 

3627 return util.wrap_callable(lambda ctx: fn(), fn) # type: ignore 

3628 

3629 defaulted = argspec[3] is not None and len(argspec[3]) or 0 

3630 positionals = len(argspec[0]) - defaulted 

3631 

3632 if positionals == 0: 

3633 return util.wrap_callable(lambda ctx: fn(), fn) # type: ignore 

3634 

3635 elif positionals == 1: 

3636 return fn # type: ignore 

3637 else: 

3638 raise exc.ArgumentError( 

3639 "ColumnDefault Python function takes zero or one " 

3640 "positional arguments" 

3641 ) 

3642 

3643 

3644class IdentityOptions(DialectKWArgs): 

3645 """Defines options for a named database sequence or an identity column. 

3646 

3647 .. versionadded:: 1.3.18 

3648 

3649 .. seealso:: 

3650 

3651 :class:`.Sequence` 

3652 

3653 """ 

3654 

3655 def __init__( 

3656 self, 

3657 start: Optional[int] = None, 

3658 increment: Optional[int] = None, 

3659 minvalue: Optional[int] = None, 

3660 maxvalue: Optional[int] = None, 

3661 nominvalue: Optional[bool] = None, 

3662 nomaxvalue: Optional[bool] = None, 

3663 cycle: Optional[bool] = None, 

3664 cache: Optional[int] = None, 

3665 order: Optional[bool] = None, 

3666 **dialect_kw: Any, 

3667 ) -> None: 

3668 """Construct a :class:`.IdentityOptions` object. 

3669 

3670 See the :class:`.Sequence` documentation for a complete description 

3671 of the parameters. 

3672 

3673 :param start: the starting index of the sequence. 

3674 :param increment: the increment value of the sequence. 

3675 :param minvalue: the minimum value of the sequence. 

3676 :param maxvalue: the maximum value of the sequence. 

3677 :param nominvalue: no minimum value of the sequence. 

3678 :param nomaxvalue: no maximum value of the sequence. 

3679 :param cycle: allows the sequence to wrap around when the maxvalue 

3680 or minvalue has been reached. 

3681 :param cache: optional integer value; number of future values in the 

3682 sequence which are calculated in advance. 

3683 :param order: optional boolean value; if ``True``, renders the 

3684 ORDER keyword. 

3685 

3686 .. deprecated:: 2.1 Use ``oracle_order`` instead. 

3687 

3688 """ 

3689 self.start = start 

3690 self.increment = increment 

3691 self.minvalue = minvalue 

3692 self.maxvalue = maxvalue 

3693 self.nominvalue = nominvalue 

3694 self.nomaxvalue = nomaxvalue 

3695 self.cycle = cycle 

3696 self.cache = cache 

3697 if order is not None: 

3698 if "oracle_order" in dialect_kw: 

3699 raise exc.ArgumentError( 

3700 "Cannot specify both 'order' and 'oracle_order'. " 

3701 "Plese use only 'oracle_order'." 

3702 ) 

3703 dialect_kw["oracle_order"] = order 

3704 self._validate_dialect_kwargs(dialect_kw) 

3705 

3706 @property 

3707 def _increment_is_negative(self) -> bool: 

3708 return self.increment is not None and self.increment < 0 

3709 

3710 @property 

3711 def order(self) -> Optional[bool]: 

3712 """Alias of the ``dialect_kwargs`` ``'oracle_order'``. 

3713 

3714 .. deprecated:: 2.1 The 'order' attribute is deprecated. 

3715 """ 

3716 value: Optional[bool] = self.dialect_kwargs.get("oracle_order") 

3717 return value 

3718 

3719 def _as_dict(self) -> Dict[str, Any]: 

3720 return { 

3721 k: v 

3722 for k, v in { 

3723 "start": self.start, 

3724 "increment": self.increment, 

3725 "minvalue": self.minvalue, 

3726 "maxvalue": self.maxvalue, 

3727 "nominvalue": self.nominvalue, 

3728 "nomaxvalue": self.nomaxvalue, 

3729 "cycle": self.cycle, 

3730 "cache": self.cache, 

3731 }.items() 

3732 if v != None 

3733 } 

3734 

3735 

3736class Sequence(HasSchemaAttr, IdentityOptions, DefaultGenerator): 

3737 """Represents a named database sequence. 

3738 

3739 The :class:`.Sequence` object represents the name and configurational 

3740 parameters of a database sequence. It also represents 

3741 a construct that can be "executed" by a SQLAlchemy :class:`_engine.Engine` 

3742 or :class:`_engine.Connection`, 

3743 rendering the appropriate "next value" function 

3744 for the target database and returning a result. 

3745 

3746 The :class:`.Sequence` is typically associated with a primary key column:: 

3747 

3748 some_table = Table( 

3749 'some_table', metadata, 

3750 Column('id', Integer, Sequence('some_table_seq', start=1), 

3751 primary_key=True) 

3752 ) 

3753 

3754 When CREATE TABLE is emitted for the above :class:`_schema.Table`, if the 

3755 target platform supports sequences, a CREATE SEQUENCE statement will 

3756 be emitted as well. For platforms that don't support sequences, 

3757 the :class:`.Sequence` construct is ignored. 

3758 

3759 .. seealso:: 

3760 

3761 :ref:`defaults_sequences` 

3762 

3763 :class:`.CreateSequence` 

3764 

3765 :class:`.DropSequence` 

3766 

3767 """ 

3768 

3769 __visit_name__ = "sequence" 

3770 

3771 is_sequence = True 

3772 

3773 column: Optional[Column[Any]] 

3774 data_type: Optional[TypeEngine[int]] 

3775 

3776 @util.deprecated_params( 

3777 order=( 

3778 "2.1", 

3779 "This parameter is supported only by Oracle, " 

3780 "use ``oracle_order`` instead.", 

3781 ) 

3782 ) 

3783 def __init__( 

3784 self, 

3785 name: str, 

3786 start: Optional[int] = None, 

3787 increment: Optional[int] = None, 

3788 minvalue: Optional[int] = None, 

3789 maxvalue: Optional[int] = None, 

3790 nominvalue: Optional[bool] = None, 

3791 nomaxvalue: Optional[bool] = None, 

3792 cycle: Optional[bool] = None, 

3793 schema: Optional[Union[str, Literal[SchemaConst.BLANK_SCHEMA]]] = None, 

3794 cache: Optional[int] = None, 

3795 order: Optional[bool] = None, 

3796 data_type: Optional[_TypeEngineArgument[int]] = None, 

3797 optional: bool = False, 

3798 quote: Optional[bool] = None, 

3799 metadata: Optional[MetaData] = None, 

3800 quote_schema: Optional[bool] = None, 

3801 for_update: bool = False, 

3802 **dialect_kw: Any, 

3803 ) -> None: 

3804 """Construct a :class:`.Sequence` object. 

3805 

3806 :param name: the name of the sequence. 

3807 

3808 :param start: the starting index of the sequence. This value is 

3809 used when the CREATE SEQUENCE command is emitted to the database 

3810 as the value of the "START WITH" clause. If ``None``, the 

3811 clause is omitted, which on most platforms indicates a starting 

3812 value of 1. 

3813 

3814 .. versionchanged:: 2.0 The :paramref:`.Sequence.start` parameter 

3815 is required in order to have DDL emit "START WITH". This is a 

3816 reversal of a change made in version 1.4 which would implicitly 

3817 render "START WITH 1" if the :paramref:`.Sequence.start` were 

3818 not included. See :ref:`change_7211` for more detail. 

3819 

3820 :param increment: the increment value of the sequence. This 

3821 value is used when the CREATE SEQUENCE command is emitted to 

3822 the database as the value of the "INCREMENT BY" clause. If ``None``, 

3823 the clause is omitted, which on most platforms indicates an 

3824 increment of 1. 

3825 :param minvalue: the minimum value of the sequence. This 

3826 value is used when the CREATE SEQUENCE command is emitted to 

3827 the database as the value of the "MINVALUE" clause. If ``None``, 

3828 the clause is omitted, which on most platforms indicates a 

3829 minvalue of 1 and -2^63-1 for ascending and descending sequences, 

3830 respectively. 

3831 

3832 :param maxvalue: the maximum value of the sequence. This 

3833 value is used when the CREATE SEQUENCE command is emitted to 

3834 the database as the value of the "MAXVALUE" clause. If ``None``, 

3835 the clause is omitted, which on most platforms indicates a 

3836 maxvalue of 2^63-1 and -1 for ascending and descending sequences, 

3837 respectively. 

3838 

3839 :param nominvalue: no minimum value of the sequence. This 

3840 value is used when the CREATE SEQUENCE command is emitted to 

3841 the database as the value of the "NO MINVALUE" clause. If ``None``, 

3842 the clause is omitted, which on most platforms indicates a 

3843 minvalue of 1 and -2^63-1 for ascending and descending sequences, 

3844 respectively. 

3845 

3846 :param nomaxvalue: no maximum value of the sequence. This 

3847 value is used when the CREATE SEQUENCE command is emitted to 

3848 the database as the value of the "NO MAXVALUE" clause. If ``None``, 

3849 the clause is omitted, which on most platforms indicates a 

3850 maxvalue of 2^63-1 and -1 for ascending and descending sequences, 

3851 respectively. 

3852 

3853 :param cycle: allows the sequence to wrap around when the maxvalue 

3854 or minvalue has been reached by an ascending or descending sequence 

3855 respectively. This value is used when the CREATE SEQUENCE command 

3856 is emitted to the database as the "CYCLE" clause. If the limit is 

3857 reached, the next number generated will be the minvalue or maxvalue, 

3858 respectively. If cycle=False (the default) any calls to nextval 

3859 after the sequence has reached its maximum value will return an 

3860 error. 

3861 

3862 :param schema: optional schema name for the sequence, if located 

3863 in a schema other than the default. The rules for selecting the 

3864 schema name when a :class:`_schema.MetaData` 

3865 is also present are the same 

3866 as that of :paramref:`_schema.Table.schema`. 

3867 

3868 :param cache: optional integer value; number of future values in the 

3869 sequence which are calculated in advance. Renders the CACHE keyword 

3870 understood by Oracle and PostgreSQL. 

3871 

3872 :param order: optional boolean value; if ``True``, renders the 

3873 ORDER keyword, understood by Oracle, indicating the sequence is 

3874 definitively ordered. May be necessary to provide deterministic 

3875 ordering using Oracle RAC. 

3876 

3877 :param data_type: The type to be returned by the sequence, for 

3878 dialects that allow us to choose between INTEGER, BIGINT, etc. 

3879 (e.g., mssql). 

3880 

3881 .. versionadded:: 1.4.0 

3882 

3883 :param optional: boolean value, when ``True``, indicates that this 

3884 :class:`.Sequence` object only needs to be explicitly generated 

3885 on backends that don't provide another way to generate primary 

3886 key identifiers. Currently, it essentially means, "don't create 

3887 this sequence on the PostgreSQL backend, where the SERIAL keyword 

3888 creates a sequence for us automatically". 

3889 :param quote: boolean value, when ``True`` or ``False``, explicitly 

3890 forces quoting of the :paramref:`_schema.Sequence.name` on or off. 

3891 When left at its default of ``None``, normal quoting rules based 

3892 on casing and reserved words take place. 

3893 :param quote_schema: Set the quoting preferences for the ``schema`` 

3894 name. 

3895 

3896 :param metadata: optional :class:`_schema.MetaData` object which this 

3897 :class:`.Sequence` will be associated with. A :class:`.Sequence` 

3898 that is associated with a :class:`_schema.MetaData` 

3899 gains the following 

3900 capabilities: 

3901 

3902 * The :class:`.Sequence` will inherit the 

3903 :paramref:`_schema.MetaData.schema` 

3904 parameter specified to the target :class:`_schema.MetaData`, which 

3905 affects the production of CREATE / DROP DDL, if any. 

3906 

3907 * The :meth:`.Sequence.create` and :meth:`.Sequence.drop` methods 

3908 automatically use the engine bound to the :class:`_schema.MetaData` 

3909 object, if any. 

3910 

3911 * The :meth:`_schema.MetaData.create_all` and 

3912 :meth:`_schema.MetaData.drop_all` 

3913 methods will emit CREATE / DROP for this :class:`.Sequence`, 

3914 even if the :class:`.Sequence` is not associated with any 

3915 :class:`_schema.Table` / :class:`_schema.Column` 

3916 that's a member of this 

3917 :class:`_schema.MetaData`. 

3918 

3919 The above behaviors can only occur if the :class:`.Sequence` is 

3920 explicitly associated with the :class:`_schema.MetaData` 

3921 via this parameter. 

3922 

3923 .. seealso:: 

3924 

3925 :ref:`sequence_metadata` - full discussion of the 

3926 :paramref:`.Sequence.metadata` parameter. 

3927 

3928 :param for_update: Indicates this :class:`.Sequence`, when associated 

3929 with a :class:`_schema.Column`, 

3930 should be invoked for UPDATE statements 

3931 on that column's table, rather than for INSERT statements, when 

3932 no value is otherwise present for that column in the statement. 

3933 

3934 """ 

3935 DefaultGenerator.__init__(self, for_update=for_update) 

3936 IdentityOptions.__init__( 

3937 self, 

3938 start=start, 

3939 increment=increment, 

3940 minvalue=minvalue, 

3941 maxvalue=maxvalue, 

3942 nominvalue=nominvalue, 

3943 nomaxvalue=nomaxvalue, 

3944 cycle=cycle, 

3945 cache=cache, 

3946 order=order, 

3947 **dialect_kw, 

3948 ) 

3949 self.column = None 

3950 self.name = quoted_name(name, quote) 

3951 self.optional = optional 

3952 if schema is BLANK_SCHEMA: 

3953 self.schema = schema = None 

3954 elif metadata is not None and schema is None and metadata.schema: 

3955 self.schema = schema = metadata.schema 

3956 else: 

3957 self.schema = quoted_name.construct(schema, quote_schema) 

3958 self.metadata = metadata 

3959 self._key = _get_table_key(name, schema) 

3960 if metadata: 

3961 self._set_metadata(metadata) 

3962 if data_type is not None: 

3963 self.data_type = to_instance(data_type) 

3964 else: 

3965 self.data_type = None 

3966 

3967 @util.preload_module("sqlalchemy.sql.functions") 

3968 def next_value(self) -> Function[int]: 

3969 """Return a :class:`.next_value` function element 

3970 which will render the appropriate increment function 

3971 for this :class:`.Sequence` within any SQL expression. 

3972 

3973 """ 

3974 return util.preloaded.sql_functions.func.next_value(self) 

3975 

3976 def _set_parent(self, parent: SchemaEventTarget, **kw: Any) -> None: 

3977 column = parent 

3978 assert isinstance(column, Column) 

3979 super()._set_parent(column) 

3980 column._on_table_attach(self._set_table) 

3981 

3982 def _copy(self) -> Sequence: 

3983 return Sequence( 

3984 name=self.name, 

3985 schema=self.schema, 

3986 data_type=self.data_type, 

3987 optional=self.optional, 

3988 metadata=self.metadata, 

3989 for_update=self.for_update, 

3990 **self._as_dict(), 

3991 **self.dialect_kwargs, 

3992 ) 

3993 

3994 def _set_table(self, column: Column[Any], table: Table) -> None: 

3995 self._set_metadata(table.metadata) 

3996 

3997 def _set_metadata(self, metadata: MetaData) -> None: 

3998 self.metadata = metadata 

3999 self.metadata._sequences[self._key] = self 

4000 

4001 def create(self, bind: _CreateDropBind, checkfirst: bool = True) -> None: 

4002 """Creates this sequence in the database.""" 

4003 

4004 bind._run_ddl_visitor(ddl.SchemaGenerator, self, checkfirst=checkfirst) 

4005 

4006 def drop(self, bind: _CreateDropBind, checkfirst: bool = True) -> None: 

4007 """Drops this sequence from the database.""" 

4008 

4009 bind._run_ddl_visitor(ddl.SchemaDropper, self, checkfirst=checkfirst) 

4010 

4011 def _not_a_column_expr(self) -> NoReturn: 

4012 raise exc.InvalidRequestError( 

4013 f"This {self.__class__.__name__} cannot be used directly " 

4014 "as a column expression. Use func.next_value(sequence) " 

4015 "to produce a 'next value' function that's usable " 

4016 "as a column element." 

4017 ) 

4018 

4019 

4020@inspection._self_inspects 

4021class FetchedValue(SchemaEventTarget): 

4022 """A marker for a transparent database-side default. 

4023 

4024 Use :class:`.FetchedValue` when the database is configured 

4025 to provide some automatic default for a column. 

4026 

4027 E.g.:: 

4028 

4029 Column('foo', Integer, FetchedValue()) 

4030 

4031 Would indicate that some trigger or default generator 

4032 will create a new value for the ``foo`` column during an 

4033 INSERT. 

4034 

4035 .. seealso:: 

4036 

4037 :ref:`triggered_columns` 

4038 

4039 """ 

4040 

4041 is_server_default = True 

4042 reflected = False 

4043 has_argument = False 

4044 is_clause_element = False 

4045 is_identity = False 

4046 

4047 column: Optional[Column[Any]] 

4048 

4049 def __init__(self, for_update: bool = False) -> None: 

4050 self.for_update = for_update 

4051 

4052 def _as_for_update(self, for_update: bool) -> FetchedValue: 

4053 if for_update == self.for_update: 

4054 return self 

4055 else: 

4056 return self._clone(for_update) 

4057 

4058 def _copy(self) -> FetchedValue: 

4059 return FetchedValue(self.for_update) 

4060 

4061 def _clone(self, for_update: bool) -> Self: 

4062 n = self.__class__.__new__(self.__class__) 

4063 n.__dict__.update(self.__dict__) 

4064 n.__dict__.pop("column", None) 

4065 n.for_update = for_update 

4066 return n 

4067 

4068 def _set_parent(self, parent: SchemaEventTarget, **kw: Any) -> None: 

4069 column = parent 

4070 assert isinstance(column, Column) 

4071 self.column = column 

4072 if self.for_update: 

4073 self.column.server_onupdate = self 

4074 else: 

4075 self.column.server_default = self 

4076 

4077 def __repr__(self) -> str: 

4078 return util.generic_repr(self) 

4079 

4080 

4081class DefaultClause(FetchedValue): 

4082 """A DDL-specified DEFAULT column value. 

4083 

4084 :class:`.DefaultClause` is a :class:`.FetchedValue` 

4085 that also generates a "DEFAULT" clause when 

4086 "CREATE TABLE" is emitted. 

4087 

4088 :class:`.DefaultClause` is generated automatically 

4089 whenever the ``server_default``, ``server_onupdate`` arguments of 

4090 :class:`_schema.Column` are used. A :class:`.DefaultClause` 

4091 can be passed positionally as well. 

4092 

4093 For example, the following:: 

4094 

4095 Column('foo', Integer, server_default="50") 

4096 

4097 Is equivalent to:: 

4098 

4099 Column('foo', Integer, DefaultClause("50")) 

4100 

4101 """ 

4102 

4103 has_argument = True 

4104 

4105 def __init__( 

4106 self, 

4107 arg: Union[str, ClauseElement, TextClause], 

4108 for_update: bool = False, 

4109 _reflected: bool = False, 

4110 ) -> None: 

4111 util.assert_arg_type(arg, (str, ClauseElement, TextClause), "arg") 

4112 super().__init__(for_update) 

4113 self.arg = arg 

4114 self.reflected = _reflected 

4115 

4116 def _copy(self) -> DefaultClause: 

4117 return DefaultClause( 

4118 arg=self.arg, for_update=self.for_update, _reflected=self.reflected 

4119 ) 

4120 

4121 def __repr__(self) -> str: 

4122 return "DefaultClause(%r, for_update=%r)" % (self.arg, self.for_update) 

4123 

4124 

4125class Constraint(DialectKWArgs, HasConditionalDDL, SchemaItem): 

4126 """A table-level SQL constraint. 

4127 

4128 :class:`_schema.Constraint` serves as the base class for the series of 

4129 constraint objects that can be associated with :class:`_schema.Table` 

4130 objects, including :class:`_schema.PrimaryKeyConstraint`, 

4131 :class:`_schema.ForeignKeyConstraint` 

4132 :class:`_schema.UniqueConstraint`, and 

4133 :class:`_schema.CheckConstraint`. 

4134 

4135 """ 

4136 

4137 __visit_name__ = "constraint" 

4138 

4139 _creation_order: int 

4140 _column_flag: bool 

4141 

4142 def __init__( 

4143 self, 

4144 name: _ConstraintNameArgument = None, 

4145 deferrable: Optional[bool] = None, 

4146 initially: Optional[str] = None, 

4147 info: Optional[_InfoType] = None, 

4148 comment: Optional[str] = None, 

4149 _create_rule: Optional[Any] = None, 

4150 _type_bound: bool = False, 

4151 **dialect_kw: Any, 

4152 ) -> None: 

4153 r"""Create a SQL constraint. 

4154 

4155 :param name: 

4156 Optional, the in-database name of this ``Constraint``. 

4157 

4158 :param deferrable: 

4159 Optional bool. If set, emit DEFERRABLE or NOT DEFERRABLE when 

4160 issuing DDL for this constraint. 

4161 

4162 :param initially: 

4163 Optional string. If set, emit INITIALLY <value> when issuing DDL 

4164 for this constraint. 

4165 

4166 :param info: Optional data dictionary which will be populated into the 

4167 :attr:`.SchemaItem.info` attribute of this object. 

4168 

4169 :param comment: Optional string that will render an SQL comment on 

4170 foreign key constraint creation. 

4171 

4172 .. versionadded:: 2.0 

4173 

4174 :param \**dialect_kw: Additional keyword arguments are dialect 

4175 specific, and passed in the form ``<dialectname>_<argname>``. See 

4176 the documentation regarding an individual dialect at 

4177 :ref:`dialect_toplevel` for detail on documented arguments. 

4178 

4179 :param _create_rule: 

4180 used internally by some datatypes that also create constraints. 

4181 

4182 :param _type_bound: 

4183 used internally to indicate that this constraint is associated with 

4184 a specific datatype. 

4185 

4186 """ 

4187 

4188 self.name = name 

4189 self.deferrable = deferrable 

4190 self.initially = initially 

4191 if info: 

4192 self.info = info 

4193 self._create_rule = _create_rule 

4194 self._type_bound = _type_bound 

4195 util.set_creation_order(self) 

4196 self._validate_dialect_kwargs(dialect_kw) 

4197 self.comment = comment 

4198 

4199 def _should_create_for_compiler( 

4200 self, compiler: DDLCompiler, **kw: Any 

4201 ) -> bool: 

4202 if self._create_rule is not None and not self._create_rule(compiler): 

4203 return False 

4204 elif self._ddl_if is not None: 

4205 return self._ddl_if._should_execute( 

4206 ddl.CreateConstraint(self), self, None, compiler=compiler, **kw 

4207 ) 

4208 else: 

4209 return True 

4210 

4211 @property 

4212 def table(self) -> Table: 

4213 try: 

4214 if isinstance(self.parent, Table): 

4215 return self.parent 

4216 except AttributeError: 

4217 pass 

4218 raise exc.InvalidRequestError( 

4219 "This constraint is not bound to a table. Did you " 

4220 "mean to call table.append_constraint(constraint) ?" 

4221 ) 

4222 

4223 def _set_parent(self, parent: SchemaEventTarget, **kw: Any) -> None: 

4224 assert isinstance(parent, (Table, Column)) 

4225 self.parent = parent 

4226 parent.constraints.add(self) 

4227 

4228 @util.deprecated( 

4229 "1.4", 

4230 "The :meth:`_schema.Constraint.copy` method is deprecated " 

4231 "and will be removed in a future release.", 

4232 ) 

4233 def copy(self, **kw: Any) -> Self: 

4234 return self._copy(**kw) 

4235 

4236 def _copy(self, **kw: Any) -> Self: 

4237 raise NotImplementedError() 

4238 

4239 

4240class ColumnCollectionMixin: 

4241 """A :class:`_expression.ColumnCollection` of :class:`_schema.Column` 

4242 objects. 

4243 

4244 This collection represents the columns which are referred to by 

4245 this object. 

4246 

4247 """ 

4248 

4249 _columns: DedupeColumnCollection[Column[Any]] 

4250 

4251 _allow_multiple_tables = False 

4252 

4253 _pending_colargs: List[Optional[Union[str, Column[Any]]]] 

4254 

4255 if TYPE_CHECKING: 

4256 

4257 def _set_parent_with_dispatch( 

4258 self, parent: SchemaEventTarget, **kw: Any 

4259 ) -> None: ... 

4260 

4261 def __init__( 

4262 self, 

4263 *columns: _DDLColumnArgument, 

4264 _autoattach: bool = True, 

4265 _column_flag: bool = False, 

4266 _gather_expressions: Optional[ 

4267 List[Union[str, ColumnElement[Any]]] 

4268 ] = None, 

4269 ) -> None: 

4270 self._column_flag = _column_flag 

4271 self._columns = DedupeColumnCollection() 

4272 

4273 processed_expressions: Optional[ 

4274 List[Union[ColumnElement[Any], str]] 

4275 ] = _gather_expressions 

4276 

4277 if processed_expressions is not None: 

4278 self._pending_colargs = [] 

4279 for ( 

4280 expr, 

4281 _, 

4282 _, 

4283 add_element, 

4284 ) in coercions.expect_col_expression_collection( 

4285 roles.DDLConstraintColumnRole, columns 

4286 ): 

4287 self._pending_colargs.append(add_element) 

4288 processed_expressions.append(expr) 

4289 else: 

4290 self._pending_colargs = [ 

4291 coercions.expect(roles.DDLConstraintColumnRole, column) 

4292 for column in columns 

4293 ] 

4294 

4295 if _autoattach and self._pending_colargs: 

4296 self._check_attach() 

4297 

4298 def _check_attach(self, evt: bool = False) -> None: 

4299 col_objs = [c for c in self._pending_colargs if isinstance(c, Column)] 

4300 

4301 cols_w_table = [c for c in col_objs if isinstance(c.table, Table)] 

4302 

4303 cols_wo_table = set(col_objs).difference(cols_w_table) 

4304 if cols_wo_table: 

4305 # feature #3341 - place event listeners for Column objects 

4306 # such that when all those cols are attached, we autoattach. 

4307 assert not evt, "Should not reach here on event call" 

4308 

4309 # issue #3411 - don't do the per-column auto-attach if some of the 

4310 # columns are specified as strings. 

4311 has_string_cols = { 

4312 c for c in self._pending_colargs if c is not None 

4313 }.difference(col_objs) 

4314 if not has_string_cols: 

4315 

4316 def _col_attached(column: Column[Any], table: Table) -> None: 

4317 # this isinstance() corresponds with the 

4318 # isinstance() above; only want to count Table-bound 

4319 # columns 

4320 if isinstance(table, Table): 

4321 cols_wo_table.discard(column) 

4322 if not cols_wo_table: 

4323 self._check_attach(evt=True) 

4324 

4325 self._cols_wo_table = cols_wo_table 

4326 for col in cols_wo_table: 

4327 col._on_table_attach(_col_attached) 

4328 return 

4329 

4330 columns = cols_w_table 

4331 

4332 tables = {c.table for c in columns} 

4333 if len(tables) == 1: 

4334 self._set_parent_with_dispatch(tables.pop()) 

4335 elif len(tables) > 1 and not self._allow_multiple_tables: 

4336 table = columns[0].table 

4337 others = [c for c in columns[1:] if c.table is not table] 

4338 if others: 

4339 # black could not format this inline 

4340 other_str = ", ".join("'%s'" % c for c in others) 

4341 raise exc.ArgumentError( 

4342 f"Column(s) {other_str} " 

4343 f"are not part of table '{table.description}'." 

4344 ) 

4345 

4346 @util.ro_memoized_property 

4347 def columns(self) -> ReadOnlyColumnCollection[str, Column[Any]]: 

4348 return self._columns.as_readonly() 

4349 

4350 @util.ro_memoized_property 

4351 def c(self) -> ReadOnlyColumnCollection[str, Column[Any]]: 

4352 return self._columns.as_readonly() 

4353 

4354 def _col_expressions( 

4355 self, parent: Union[Table, Column[Any]] 

4356 ) -> List[Optional[Column[Any]]]: 

4357 if isinstance(parent, Column): 

4358 result: List[Optional[Column[Any]]] = [ 

4359 c for c in self._pending_colargs if isinstance(c, Column) 

4360 ] 

4361 assert len(result) == len(self._pending_colargs) 

4362 return result 

4363 else: 

4364 try: 

4365 return [ 

4366 parent.c[col] if isinstance(col, str) else col 

4367 for col in self._pending_colargs 

4368 ] 

4369 except KeyError as ke: 

4370 raise exc.ConstraintColumnNotFoundError( 

4371 f"Can't create {self.__class__.__name__} " 

4372 f"on table '{parent.description}': no column " 

4373 f"named '{ke.args[0]}' is present." 

4374 ) from ke 

4375 

4376 def _set_parent(self, parent: SchemaEventTarget, **kw: Any) -> None: 

4377 assert isinstance(parent, (Table, Column)) 

4378 

4379 for col in self._col_expressions(parent): 

4380 if col is not None: 

4381 self._columns.add(col) 

4382 

4383 

4384class ColumnCollectionConstraint(ColumnCollectionMixin, Constraint): 

4385 """A constraint that proxies a ColumnCollection.""" 

4386 

4387 def __init__( 

4388 self, 

4389 *columns: _DDLColumnArgument, 

4390 name: _ConstraintNameArgument = None, 

4391 deferrable: Optional[bool] = None, 

4392 initially: Optional[str] = None, 

4393 info: Optional[_InfoType] = None, 

4394 _autoattach: bool = True, 

4395 _column_flag: bool = False, 

4396 _gather_expressions: Optional[List[_DDLColumnArgument]] = None, 

4397 **dialect_kw: Any, 

4398 ) -> None: 

4399 r""" 

4400 :param \*columns: 

4401 A sequence of column names or Column objects. 

4402 

4403 :param name: 

4404 Optional, the in-database name of this constraint. 

4405 

4406 :param deferrable: 

4407 Optional bool. If set, emit DEFERRABLE or NOT DEFERRABLE when 

4408 issuing DDL for this constraint. 

4409 

4410 :param initially: 

4411 Optional string. If set, emit INITIALLY <value> when issuing DDL 

4412 for this constraint. 

4413 

4414 :param \**dialect_kw: other keyword arguments including 

4415 dialect-specific arguments are propagated to the :class:`.Constraint` 

4416 superclass. 

4417 

4418 """ 

4419 Constraint.__init__( 

4420 self, 

4421 name=name, 

4422 deferrable=deferrable, 

4423 initially=initially, 

4424 info=info, 

4425 **dialect_kw, 

4426 ) 

4427 ColumnCollectionMixin.__init__( 

4428 self, *columns, _autoattach=_autoattach, _column_flag=_column_flag 

4429 ) 

4430 

4431 columns: ReadOnlyColumnCollection[str, Column[Any]] 

4432 """A :class:`_expression.ColumnCollection` representing the set of columns 

4433 for this constraint. 

4434 

4435 """ 

4436 

4437 def _set_parent(self, parent: SchemaEventTarget, **kw: Any) -> None: 

4438 assert isinstance(parent, (Column, Table)) 

4439 Constraint._set_parent(self, parent) 

4440 ColumnCollectionMixin._set_parent(self, parent) 

4441 

4442 def __contains__(self, x: Any) -> bool: 

4443 return x in self._columns 

4444 

4445 @util.deprecated( 

4446 "1.4", 

4447 "The :meth:`_schema.ColumnCollectionConstraint.copy` method " 

4448 "is deprecated and will be removed in a future release.", 

4449 ) 

4450 def copy( 

4451 self, 

4452 *, 

4453 target_table: Optional[Table] = None, 

4454 **kw: Any, 

4455 ) -> ColumnCollectionConstraint: 

4456 return self._copy(target_table=target_table, **kw) 

4457 

4458 def _copy( 

4459 self, 

4460 *, 

4461 target_table: Optional[Table] = None, 

4462 **kw: Any, 

4463 ) -> ColumnCollectionConstraint: 

4464 # ticket #5276 

4465 constraint_kwargs = {} 

4466 for dialect_name in self.dialect_options: 

4467 dialect_options = self.dialect_options[dialect_name]._non_defaults 

4468 for ( 

4469 dialect_option_key, 

4470 dialect_option_value, 

4471 ) in dialect_options.items(): 

4472 constraint_kwargs[dialect_name + "_" + dialect_option_key] = ( 

4473 dialect_option_value 

4474 ) 

4475 

4476 assert isinstance(self.parent, Table) 

4477 c = self.__class__( 

4478 name=self.name, 

4479 deferrable=self.deferrable, 

4480 initially=self.initially, 

4481 *[ 

4482 _copy_expression(expr, self.parent, target_table) 

4483 for expr in self._columns 

4484 ], 

4485 comment=self.comment, 

4486 **constraint_kwargs, 

4487 ) 

4488 return self._schema_item_copy(c) 

4489 

4490 def contains_column(self, col: Column[Any]) -> bool: 

4491 """Return True if this constraint contains the given column. 

4492 

4493 Note that this object also contains an attribute ``.columns`` 

4494 which is a :class:`_expression.ColumnCollection` of 

4495 :class:`_schema.Column` objects. 

4496 

4497 """ 

4498 

4499 return self._columns.contains_column(col) 

4500 

4501 def __iter__(self) -> Iterator[Column[Any]]: 

4502 return iter(self._columns) 

4503 

4504 def __len__(self) -> int: 

4505 return len(self._columns) 

4506 

4507 

4508class CheckConstraint(ColumnCollectionConstraint): 

4509 """A table- or column-level CHECK constraint. 

4510 

4511 Can be included in the definition of a Table or Column. 

4512 """ 

4513 

4514 _allow_multiple_tables = True 

4515 

4516 __visit_name__ = "table_or_column_check_constraint" 

4517 

4518 @_document_text_coercion( 

4519 "sqltext", 

4520 ":class:`.CheckConstraint`", 

4521 ":paramref:`.CheckConstraint.sqltext`", 

4522 ) 

4523 def __init__( 

4524 self, 

4525 sqltext: _TextCoercedExpressionArgument[Any], 

4526 name: _ConstraintNameArgument = None, 

4527 deferrable: Optional[bool] = None, 

4528 initially: Optional[str] = None, 

4529 table: Optional[Table] = None, 

4530 info: Optional[_InfoType] = None, 

4531 _create_rule: Optional[Any] = None, 

4532 _autoattach: bool = True, 

4533 _type_bound: bool = False, 

4534 **dialect_kw: Any, 

4535 ) -> None: 

4536 r"""Construct a CHECK constraint. 

4537 

4538 :param sqltext: 

4539 A string containing the constraint definition, which will be used 

4540 verbatim, or a SQL expression construct. If given as a string, 

4541 the object is converted to a :func:`_expression.text` object. 

4542 If the textual 

4543 string includes a colon character, escape this using a backslash:: 

4544 

4545 CheckConstraint(r"foo ~ E'a(?\:b|c)d") 

4546 

4547 :param name: 

4548 Optional, the in-database name of the constraint. 

4549 

4550 :param deferrable: 

4551 Optional bool. If set, emit DEFERRABLE or NOT DEFERRABLE when 

4552 issuing DDL for this constraint. 

4553 

4554 :param initially: 

4555 Optional string. If set, emit INITIALLY <value> when issuing DDL 

4556 for this constraint. 

4557 

4558 :param info: Optional data dictionary which will be populated into the 

4559 :attr:`.SchemaItem.info` attribute of this object. 

4560 

4561 """ 

4562 

4563 self.sqltext = coercions.expect(roles.DDLExpressionRole, sqltext) 

4564 columns: List[Column[Any]] = [] 

4565 visitors.traverse(self.sqltext, {}, {"column": columns.append}) 

4566 

4567 super().__init__( 

4568 name=name, 

4569 deferrable=deferrable, 

4570 initially=initially, 

4571 _create_rule=_create_rule, 

4572 info=info, 

4573 _type_bound=_type_bound, 

4574 _autoattach=_autoattach, 

4575 *columns, 

4576 **dialect_kw, 

4577 ) 

4578 if table is not None: 

4579 self._set_parent_with_dispatch(table) 

4580 

4581 @property 

4582 def is_column_level(self) -> bool: 

4583 return not isinstance(self.parent, Table) 

4584 

4585 @util.deprecated( 

4586 "1.4", 

4587 "The :meth:`_schema.CheckConstraint.copy` method is deprecated " 

4588 "and will be removed in a future release.", 

4589 ) 

4590 def copy( 

4591 self, *, target_table: Optional[Table] = None, **kw: Any 

4592 ) -> CheckConstraint: 

4593 return self._copy(target_table=target_table, **kw) 

4594 

4595 def _copy( 

4596 self, *, target_table: Optional[Table] = None, **kw: Any 

4597 ) -> CheckConstraint: 

4598 if target_table is not None: 

4599 # note that target_table is None for the copy process of 

4600 # a column-bound CheckConstraint, so this path is not reached 

4601 # in that case. 

4602 sqltext = _copy_expression(self.sqltext, self.table, target_table) 

4603 else: 

4604 sqltext = self.sqltext 

4605 c = CheckConstraint( 

4606 sqltext, 

4607 name=self.name, 

4608 initially=self.initially, 

4609 deferrable=self.deferrable, 

4610 _create_rule=self._create_rule, 

4611 table=target_table, 

4612 comment=self.comment, 

4613 _autoattach=False, 

4614 _type_bound=self._type_bound, 

4615 ) 

4616 return self._schema_item_copy(c) 

4617 

4618 

4619class ForeignKeyConstraint(ColumnCollectionConstraint): 

4620 """A table-level FOREIGN KEY constraint. 

4621 

4622 Defines a single column or composite FOREIGN KEY ... REFERENCES 

4623 constraint. For a no-frills, single column foreign key, adding a 

4624 :class:`_schema.ForeignKey` to the definition of a :class:`_schema.Column` 

4625 is a 

4626 shorthand equivalent for an unnamed, single column 

4627 :class:`_schema.ForeignKeyConstraint`. 

4628 

4629 Examples of foreign key configuration are in :ref:`metadata_foreignkeys`. 

4630 

4631 """ 

4632 

4633 __visit_name__ = "foreign_key_constraint" 

4634 

4635 def __init__( 

4636 self, 

4637 columns: _typing_Sequence[_DDLColumnArgument], 

4638 refcolumns: _typing_Sequence[_DDLColumnReferenceArgument], 

4639 name: _ConstraintNameArgument = None, 

4640 onupdate: Optional[str] = None, 

4641 ondelete: Optional[str] = None, 

4642 deferrable: Optional[bool] = None, 

4643 initially: Optional[str] = None, 

4644 use_alter: bool = False, 

4645 link_to_name: bool = False, 

4646 match: Optional[str] = None, 

4647 table: Optional[Table] = None, 

4648 info: Optional[_InfoType] = None, 

4649 comment: Optional[str] = None, 

4650 **dialect_kw: Any, 

4651 ) -> None: 

4652 r"""Construct a composite-capable FOREIGN KEY. 

4653 

4654 :param columns: A sequence of local column names. The named columns 

4655 must be defined and present in the parent Table. The names should 

4656 match the ``key`` given to each column (defaults to the name) unless 

4657 ``link_to_name`` is True. 

4658 

4659 :param refcolumns: A sequence of foreign column names or Column 

4660 objects. The columns must all be located within the same Table. 

4661 

4662 :param name: Optional, the in-database name of the key. 

4663 

4664 :param onupdate: Optional string. If set, emit ON UPDATE <value> when 

4665 issuing DDL for this constraint. Typical values include CASCADE, 

4666 DELETE and RESTRICT. 

4667 

4668 :param ondelete: Optional string. If set, emit ON DELETE <value> when 

4669 issuing DDL for this constraint. Typical values include CASCADE, 

4670 DELETE and RESTRICT. 

4671 

4672 :param deferrable: Optional bool. If set, emit DEFERRABLE or NOT 

4673 DEFERRABLE when issuing DDL for this constraint. 

4674 

4675 :param initially: Optional string. If set, emit INITIALLY <value> when 

4676 issuing DDL for this constraint. 

4677 

4678 :param link_to_name: if True, the string name given in ``column`` is 

4679 the rendered name of the referenced column, not its locally assigned 

4680 ``key``. 

4681 

4682 :param use_alter: If True, do not emit the DDL for this constraint as 

4683 part of the CREATE TABLE definition. Instead, generate it via an 

4684 ALTER TABLE statement issued after the full collection of tables 

4685 have been created, and drop it via an ALTER TABLE statement before 

4686 the full collection of tables are dropped. 

4687 

4688 The use of :paramref:`_schema.ForeignKeyConstraint.use_alter` is 

4689 particularly geared towards the case where two or more tables 

4690 are established within a mutually-dependent foreign key constraint 

4691 relationship; however, the :meth:`_schema.MetaData.create_all` and 

4692 :meth:`_schema.MetaData.drop_all` 

4693 methods will perform this resolution 

4694 automatically, so the flag is normally not needed. 

4695 

4696 .. seealso:: 

4697 

4698 :ref:`use_alter` 

4699 

4700 :param match: Optional string. If set, emit MATCH <value> when issuing 

4701 DDL for this constraint. Typical values include SIMPLE, PARTIAL 

4702 and FULL. 

4703 

4704 :param info: Optional data dictionary which will be populated into the 

4705 :attr:`.SchemaItem.info` attribute of this object. 

4706 

4707 :param comment: Optional string that will render an SQL comment on 

4708 foreign key constraint creation. 

4709 

4710 .. versionadded:: 2.0 

4711 

4712 :param \**dialect_kw: Additional keyword arguments are dialect 

4713 specific, and passed in the form ``<dialectname>_<argname>``. See 

4714 the documentation regarding an individual dialect at 

4715 :ref:`dialect_toplevel` for detail on documented arguments. 

4716 

4717 """ 

4718 

4719 Constraint.__init__( 

4720 self, 

4721 name=name, 

4722 deferrable=deferrable, 

4723 initially=initially, 

4724 info=info, 

4725 comment=comment, 

4726 **dialect_kw, 

4727 ) 

4728 self.onupdate = onupdate 

4729 self.ondelete = ondelete 

4730 self.link_to_name = link_to_name 

4731 self.use_alter = use_alter 

4732 self.match = match 

4733 

4734 if len(set(columns)) != len(refcolumns): 

4735 if len(set(columns)) != len(columns): 

4736 # e.g. FOREIGN KEY (a, a) REFERENCES r (b, c) 

4737 raise exc.ArgumentError( 

4738 "ForeignKeyConstraint with duplicate source column " 

4739 "references are not supported." 

4740 ) 

4741 else: 

4742 # e.g. FOREIGN KEY (a) REFERENCES r (b, c) 

4743 # paraphrasing 

4744 # https://www.postgresql.org/docs/current/static/ddl-constraints.html 

4745 raise exc.ArgumentError( 

4746 "ForeignKeyConstraint number " 

4747 "of constrained columns must match the number of " 

4748 "referenced columns." 

4749 ) 

4750 

4751 # standalone ForeignKeyConstraint - create 

4752 # associated ForeignKey objects which will be applied to hosted 

4753 # Column objects (in col.foreign_keys), either now or when attached 

4754 # to the Table for string-specified names 

4755 self.elements = [ 

4756 ForeignKey( 

4757 refcol, 

4758 _constraint=self, 

4759 name=self.name, 

4760 onupdate=self.onupdate, 

4761 ondelete=self.ondelete, 

4762 use_alter=self.use_alter, 

4763 link_to_name=self.link_to_name, 

4764 match=self.match, 

4765 deferrable=self.deferrable, 

4766 initially=self.initially, 

4767 **self.dialect_kwargs, 

4768 ) 

4769 for refcol in refcolumns 

4770 ] 

4771 

4772 ColumnCollectionMixin.__init__(self, *columns) 

4773 if table is not None: 

4774 if hasattr(self, "parent"): 

4775 assert table is self.parent 

4776 self._set_parent_with_dispatch(table) 

4777 

4778 def _append_element(self, column: Column[Any], fk: ForeignKey) -> None: 

4779 self._columns.add(column) 

4780 self.elements.append(fk) 

4781 

4782 columns: ReadOnlyColumnCollection[str, Column[Any]] 

4783 """A :class:`_expression.ColumnCollection` representing the set of columns 

4784 for this constraint. 

4785 

4786 """ 

4787 

4788 elements: List[ForeignKey] 

4789 """A sequence of :class:`_schema.ForeignKey` objects. 

4790 

4791 Each :class:`_schema.ForeignKey` 

4792 represents a single referring column/referred 

4793 column pair. 

4794 

4795 This collection is intended to be read-only. 

4796 

4797 """ 

4798 

4799 @property 

4800 def _elements(self) -> util.OrderedDict[str, ForeignKey]: 

4801 # legacy - provide a dictionary view of (column_key, fk) 

4802 return util.OrderedDict(zip(self.column_keys, self.elements)) 

4803 

4804 @property 

4805 def _referred_schema(self) -> Optional[str]: 

4806 for elem in self.elements: 

4807 return elem._referred_schema 

4808 else: 

4809 return None 

4810 

4811 @property 

4812 def referred_table(self) -> Table: 

4813 """The :class:`_schema.Table` object to which this 

4814 :class:`_schema.ForeignKeyConstraint` references. 

4815 

4816 This is a dynamically calculated attribute which may not be available 

4817 if the constraint and/or parent table is not yet associated with 

4818 a metadata collection that contains the referred table. 

4819 

4820 """ 

4821 return self.elements[0].column.table 

4822 

4823 def _validate_dest_table(self, table: Table) -> None: 

4824 table_keys = { 

4825 elem._table_key_within_construction() for elem in self.elements 

4826 } 

4827 if None not in table_keys and len(table_keys) > 1: 

4828 elem0, elem1 = sorted(table_keys)[0:2] 

4829 raise exc.ArgumentError( 

4830 f"ForeignKeyConstraint on " 

4831 f"{table.fullname}({self._col_description}) refers to " 

4832 f"multiple remote tables: {elem0} and {elem1}" 

4833 ) 

4834 

4835 @property 

4836 def column_keys(self) -> _typing_Sequence[str]: 

4837 """Return a list of string keys representing the local 

4838 columns in this :class:`_schema.ForeignKeyConstraint`. 

4839 

4840 This list is either the original string arguments sent 

4841 to the constructor of the :class:`_schema.ForeignKeyConstraint`, 

4842 or if the constraint has been initialized with :class:`_schema.Column` 

4843 objects, is the string ``.key`` of each element. 

4844 

4845 """ 

4846 if hasattr(self, "parent"): 

4847 return self._columns.keys() 

4848 else: 

4849 return [ 

4850 col.key if isinstance(col, ColumnElement) else str(col) 

4851 for col in self._pending_colargs 

4852 ] 

4853 

4854 @property 

4855 def _col_description(self) -> str: 

4856 return ", ".join(self.column_keys) 

4857 

4858 def _set_parent(self, parent: SchemaEventTarget, **kw: Any) -> None: 

4859 table = parent 

4860 assert isinstance(table, Table) 

4861 Constraint._set_parent(self, table) 

4862 

4863 ColumnCollectionConstraint._set_parent(self, table) 

4864 

4865 for col, fk in zip(self._columns, self.elements): 

4866 if not hasattr(fk, "parent") or fk.parent is not col: 

4867 fk._set_parent_with_dispatch(col) 

4868 

4869 self._validate_dest_table(table) 

4870 

4871 @util.deprecated( 

4872 "1.4", 

4873 "The :meth:`_schema.ForeignKeyConstraint.copy` method is deprecated " 

4874 "and will be removed in a future release.", 

4875 ) 

4876 def copy( 

4877 self, 

4878 *, 

4879 schema: Optional[str] = None, 

4880 target_table: Optional[Table] = None, 

4881 **kw: Any, 

4882 ) -> ForeignKeyConstraint: 

4883 return self._copy(schema=schema, target_table=target_table, **kw) 

4884 

4885 def _copy( 

4886 self, 

4887 *, 

4888 schema: Optional[str] = None, 

4889 target_table: Optional[Table] = None, 

4890 **kw: Any, 

4891 ) -> ForeignKeyConstraint: 

4892 fkc = ForeignKeyConstraint( 

4893 [x.parent.key for x in self.elements], 

4894 [ 

4895 x._get_colspec( 

4896 schema=schema, 

4897 table_name=( 

4898 target_table.name 

4899 if target_table is not None 

4900 and x._table_key_within_construction() 

4901 == x.parent.table.key 

4902 else None 

4903 ), 

4904 _is_copy=True, 

4905 ) 

4906 for x in self.elements 

4907 ], 

4908 name=self.name, 

4909 onupdate=self.onupdate, 

4910 ondelete=self.ondelete, 

4911 use_alter=self.use_alter, 

4912 deferrable=self.deferrable, 

4913 initially=self.initially, 

4914 link_to_name=self.link_to_name, 

4915 match=self.match, 

4916 comment=self.comment, 

4917 ) 

4918 for self_fk, other_fk in zip(self.elements, fkc.elements): 

4919 self_fk._schema_item_copy(other_fk) 

4920 return self._schema_item_copy(fkc) 

4921 

4922 

4923class PrimaryKeyConstraint(ColumnCollectionConstraint): 

4924 """A table-level PRIMARY KEY constraint. 

4925 

4926 The :class:`.PrimaryKeyConstraint` object is present automatically 

4927 on any :class:`_schema.Table` object; it is assigned a set of 

4928 :class:`_schema.Column` objects corresponding to those marked with 

4929 the :paramref:`_schema.Column.primary_key` flag:: 

4930 

4931 >>> my_table = Table('mytable', metadata, 

4932 ... Column('id', Integer, primary_key=True), 

4933 ... Column('version_id', Integer, primary_key=True), 

4934 ... Column('data', String(50)) 

4935 ... ) 

4936 >>> my_table.primary_key 

4937 PrimaryKeyConstraint( 

4938 Column('id', Integer(), table=<mytable>, 

4939 primary_key=True, nullable=False), 

4940 Column('version_id', Integer(), table=<mytable>, 

4941 primary_key=True, nullable=False) 

4942 ) 

4943 

4944 The primary key of a :class:`_schema.Table` can also be specified by using 

4945 a :class:`.PrimaryKeyConstraint` object explicitly; in this mode of usage, 

4946 the "name" of the constraint can also be specified, as well as other 

4947 options which may be recognized by dialects:: 

4948 

4949 my_table = Table('mytable', metadata, 

4950 Column('id', Integer), 

4951 Column('version_id', Integer), 

4952 Column('data', String(50)), 

4953 PrimaryKeyConstraint('id', 'version_id', 

4954 name='mytable_pk') 

4955 ) 

4956 

4957 The two styles of column-specification should generally not be mixed. 

4958 An warning is emitted if the columns present in the 

4959 :class:`.PrimaryKeyConstraint` 

4960 don't match the columns that were marked as ``primary_key=True``, if both 

4961 are present; in this case, the columns are taken strictly from the 

4962 :class:`.PrimaryKeyConstraint` declaration, and those columns otherwise 

4963 marked as ``primary_key=True`` are ignored. This behavior is intended to 

4964 be backwards compatible with previous behavior. 

4965 

4966 For the use case where specific options are to be specified on the 

4967 :class:`.PrimaryKeyConstraint`, but the usual style of using 

4968 ``primary_key=True`` flags is still desirable, an empty 

4969 :class:`.PrimaryKeyConstraint` may be specified, which will take on the 

4970 primary key column collection from the :class:`_schema.Table` based on the 

4971 flags:: 

4972 

4973 my_table = Table('mytable', metadata, 

4974 Column('id', Integer, primary_key=True), 

4975 Column('version_id', Integer, primary_key=True), 

4976 Column('data', String(50)), 

4977 PrimaryKeyConstraint(name='mytable_pk', 

4978 mssql_clustered=True) 

4979 ) 

4980 

4981 """ 

4982 

4983 __visit_name__ = "primary_key_constraint" 

4984 

4985 def __init__( 

4986 self, 

4987 *columns: _DDLColumnArgument, 

4988 name: Optional[str] = None, 

4989 deferrable: Optional[bool] = None, 

4990 initially: Optional[str] = None, 

4991 info: Optional[_InfoType] = None, 

4992 _implicit_generated: bool = False, 

4993 **dialect_kw: Any, 

4994 ) -> None: 

4995 self._implicit_generated = _implicit_generated 

4996 super().__init__( 

4997 *columns, 

4998 name=name, 

4999 deferrable=deferrable, 

5000 initially=initially, 

5001 info=info, 

5002 **dialect_kw, 

5003 ) 

5004 

5005 def _set_parent(self, parent: SchemaEventTarget, **kw: Any) -> None: 

5006 table = parent 

5007 assert isinstance(table, Table) 

5008 super()._set_parent(table) 

5009 

5010 if table.primary_key is not self: 

5011 table.constraints.discard(table.primary_key) 

5012 table.primary_key = self # type: ignore 

5013 table.constraints.add(self) 

5014 

5015 table_pks = [c for c in table.c if c.primary_key] 

5016 if ( 

5017 self._columns 

5018 and table_pks 

5019 and set(table_pks) != set(self._columns) 

5020 ): 

5021 # black could not format these inline 

5022 table_pk_str = ", ".join("'%s'" % c.name for c in table_pks) 

5023 col_str = ", ".join("'%s'" % c.name for c in self._columns) 

5024 

5025 util.warn( 

5026 f"Table '{table.name}' specifies columns " 

5027 f"{table_pk_str} as " 

5028 f"primary_key=True, " 

5029 f"not matching locally specified columns {col_str}; " 

5030 f"setting the " 

5031 f"current primary key columns to " 

5032 f"{col_str}. " 

5033 f"This warning " 

5034 f"may become an exception in a future release" 

5035 ) 

5036 table_pks[:] = [] 

5037 

5038 for c in self._columns: 

5039 c.primary_key = True 

5040 if c._user_defined_nullable is NULL_UNSPECIFIED: 

5041 c.nullable = False 

5042 if table_pks: 

5043 self._columns.extend(table_pks) 

5044 

5045 def _reload(self, columns: Iterable[Column[Any]]) -> None: 

5046 """repopulate this :class:`.PrimaryKeyConstraint` given 

5047 a set of columns. 

5048 

5049 Existing columns in the table that are marked as primary_key=True 

5050 are maintained. 

5051 

5052 Also fires a new event. 

5053 

5054 This is basically like putting a whole new 

5055 :class:`.PrimaryKeyConstraint` object on the parent 

5056 :class:`_schema.Table` object without actually replacing the object. 

5057 

5058 The ordering of the given list of columns is also maintained; these 

5059 columns will be appended to the list of columns after any which 

5060 are already present. 

5061 

5062 """ 

5063 # set the primary key flag on new columns. 

5064 # note any existing PK cols on the table also have their 

5065 # flag still set. 

5066 for col in columns: 

5067 col.primary_key = True 

5068 

5069 self._columns.extend(columns) 

5070 

5071 PrimaryKeyConstraint._autoincrement_column._reset(self) # type: ignore 

5072 self._set_parent_with_dispatch(self.table) 

5073 

5074 def _replace(self, col: Column[Any]) -> None: 

5075 PrimaryKeyConstraint._autoincrement_column._reset(self) # type: ignore 

5076 self._columns.replace(col) 

5077 

5078 self.dispatch._sa_event_column_added_to_pk_constraint(self, col) 

5079 

5080 @property 

5081 def columns_autoinc_first(self) -> List[Column[Any]]: 

5082 autoinc = self._autoincrement_column 

5083 

5084 if autoinc is not None: 

5085 return [autoinc] + [c for c in self._columns if c is not autoinc] 

5086 else: 

5087 return list(self._columns) 

5088 

5089 @util.ro_memoized_property 

5090 def _autoincrement_column(self) -> Optional[Column[int]]: 

5091 def _validate_autoinc(col: Column[Any], autoinc_true: bool) -> bool: 

5092 if col.type._type_affinity is None or not issubclass( 

5093 col.type._type_affinity, 

5094 ( 

5095 type_api.INTEGERTYPE._type_affinity, 

5096 type_api.NUMERICTYPE._type_affinity, 

5097 ), 

5098 ): 

5099 if autoinc_true: 

5100 raise exc.ArgumentError( 

5101 f"Column type {col.type} on column '{col}' is not " 

5102 f"compatible with autoincrement=True" 

5103 ) 

5104 else: 

5105 return False 

5106 elif ( 

5107 not isinstance(col.default, (type(None), Sequence)) 

5108 and not autoinc_true 

5109 ): 

5110 return False 

5111 elif ( 

5112 col.server_default is not None 

5113 and not isinstance(col.server_default, Identity) 

5114 and not autoinc_true 

5115 ): 

5116 return False 

5117 elif col.foreign_keys and col.autoincrement not in ( 

5118 True, 

5119 "ignore_fk", 

5120 ): 

5121 return False 

5122 return True 

5123 

5124 if len(self._columns) == 1: 

5125 col = list(self._columns)[0] 

5126 

5127 if col.autoincrement is True: 

5128 _validate_autoinc(col, True) 

5129 return col 

5130 elif col.autoincrement in ( 

5131 "auto", 

5132 "ignore_fk", 

5133 ) and _validate_autoinc(col, False): 

5134 return col 

5135 else: 

5136 return None 

5137 

5138 else: 

5139 autoinc = None 

5140 for col in self._columns: 

5141 if col.autoincrement is True: 

5142 _validate_autoinc(col, True) 

5143 if autoinc is not None: 

5144 raise exc.ArgumentError( 

5145 f"Only one Column may be marked " 

5146 f"autoincrement=True, found both " 

5147 f"{col.name} and {autoinc.name}." 

5148 ) 

5149 else: 

5150 autoinc = col 

5151 

5152 return autoinc 

5153 

5154 

5155class UniqueConstraint(ColumnCollectionConstraint): 

5156 """A table-level UNIQUE constraint. 

5157 

5158 Defines a single column or composite UNIQUE constraint. For a no-frills, 

5159 single column constraint, adding ``unique=True`` to the ``Column`` 

5160 definition is a shorthand equivalent for an unnamed, single column 

5161 UniqueConstraint. 

5162 """ 

5163 

5164 __visit_name__ = "unique_constraint" 

5165 

5166 

5167class Index( 

5168 DialectKWArgs, ColumnCollectionMixin, HasConditionalDDL, SchemaItem 

5169): 

5170 """A table-level INDEX. 

5171 

5172 Defines a composite (one or more column) INDEX. 

5173 

5174 E.g.:: 

5175 

5176 sometable = Table("sometable", metadata, 

5177 Column("name", String(50)), 

5178 Column("address", String(100)) 

5179 ) 

5180 

5181 Index("some_index", sometable.c.name) 

5182 

5183 For a no-frills, single column index, adding 

5184 :class:`_schema.Column` also supports ``index=True``:: 

5185 

5186 sometable = Table("sometable", metadata, 

5187 Column("name", String(50), index=True) 

5188 ) 

5189 

5190 For a composite index, multiple columns can be specified:: 

5191 

5192 Index("some_index", sometable.c.name, sometable.c.address) 

5193 

5194 Functional indexes are supported as well, typically by using the 

5195 :data:`.func` construct in conjunction with table-bound 

5196 :class:`_schema.Column` objects:: 

5197 

5198 Index("some_index", func.lower(sometable.c.name)) 

5199 

5200 An :class:`.Index` can also be manually associated with a 

5201 :class:`_schema.Table`, 

5202 either through inline declaration or using 

5203 :meth:`_schema.Table.append_constraint`. When this approach is used, 

5204 the names 

5205 of the indexed columns can be specified as strings:: 

5206 

5207 Table("sometable", metadata, 

5208 Column("name", String(50)), 

5209 Column("address", String(100)), 

5210 Index("some_index", "name", "address") 

5211 ) 

5212 

5213 To support functional or expression-based indexes in this form, the 

5214 :func:`_expression.text` construct may be used:: 

5215 

5216 from sqlalchemy import text 

5217 

5218 Table("sometable", metadata, 

5219 Column("name", String(50)), 

5220 Column("address", String(100)), 

5221 Index("some_index", text("lower(name)")) 

5222 ) 

5223 

5224 .. seealso:: 

5225 

5226 :ref:`schema_indexes` - General information on :class:`.Index`. 

5227 

5228 :ref:`postgresql_indexes` - PostgreSQL-specific options available for 

5229 the :class:`.Index` construct. 

5230 

5231 :ref:`mysql_indexes` - MySQL-specific options available for the 

5232 :class:`.Index` construct. 

5233 

5234 :ref:`mssql_indexes` - MSSQL-specific options available for the 

5235 :class:`.Index` construct. 

5236 

5237 """ 

5238 

5239 __visit_name__ = "index" 

5240 

5241 table: Optional[Table] 

5242 expressions: _typing_Sequence[Union[str, ColumnElement[Any]]] 

5243 _table_bound_expressions: _typing_Sequence[ColumnElement[Any]] 

5244 

5245 def __init__( 

5246 self, 

5247 name: Optional[str], 

5248 *expressions: _DDLColumnArgument, 

5249 unique: bool = False, 

5250 quote: Optional[bool] = None, 

5251 info: Optional[_InfoType] = None, 

5252 _table: Optional[Table] = None, 

5253 _column_flag: bool = False, 

5254 **dialect_kw: Any, 

5255 ) -> None: 

5256 r"""Construct an index object. 

5257 

5258 :param name: 

5259 The name of the index 

5260 

5261 :param \*expressions: 

5262 Column expressions to include in the index. The expressions 

5263 are normally instances of :class:`_schema.Column`, but may also 

5264 be arbitrary SQL expressions which ultimately refer to a 

5265 :class:`_schema.Column`. 

5266 

5267 :param unique=False: 

5268 Keyword only argument; if True, create a unique index. 

5269 

5270 :param quote=None: 

5271 Keyword only argument; whether to apply quoting to the name of 

5272 the index. Works in the same manner as that of 

5273 :paramref:`_schema.Column.quote`. 

5274 

5275 :param info=None: Optional data dictionary which will be populated 

5276 into the :attr:`.SchemaItem.info` attribute of this object. 

5277 

5278 :param \**dialect_kw: Additional keyword arguments not mentioned above 

5279 are dialect specific, and passed in the form 

5280 ``<dialectname>_<argname>``. See the documentation regarding an 

5281 individual dialect at :ref:`dialect_toplevel` for detail on 

5282 documented arguments. 

5283 

5284 """ 

5285 self.table = table = None 

5286 

5287 self.name = quoted_name.construct(name, quote) 

5288 self.unique = unique 

5289 if info is not None: 

5290 self.info = info 

5291 

5292 # TODO: consider "table" argument being public, but for 

5293 # the purpose of the fix here, it starts as private. 

5294 if _table is not None: 

5295 table = _table 

5296 

5297 self._validate_dialect_kwargs(dialect_kw) 

5298 

5299 self.expressions = [] 

5300 # will call _set_parent() if table-bound column 

5301 # objects are present 

5302 ColumnCollectionMixin.__init__( 

5303 self, 

5304 *expressions, 

5305 _column_flag=_column_flag, 

5306 _gather_expressions=self.expressions, 

5307 ) 

5308 if table is not None: 

5309 self._set_parent(table) 

5310 

5311 def _set_parent(self, parent: SchemaEventTarget, **kw: Any) -> None: 

5312 table = parent 

5313 assert isinstance(table, Table) 

5314 ColumnCollectionMixin._set_parent(self, table) 

5315 

5316 if self.table is not None and table is not self.table: 

5317 raise exc.ArgumentError( 

5318 f"Index '{self.name}' is against table " 

5319 f"'{self.table.description}', and " 

5320 f"cannot be associated with table '{table.description}'." 

5321 ) 

5322 self.table = table 

5323 table.indexes.add(self) 

5324 

5325 expressions = self.expressions 

5326 col_expressions = self._col_expressions(table) 

5327 assert len(expressions) == len(col_expressions) 

5328 

5329 exprs = [] 

5330 for expr, colexpr in zip(expressions, col_expressions): 

5331 if isinstance(expr, ClauseElement): 

5332 exprs.append(expr) 

5333 elif colexpr is not None: 

5334 exprs.append(colexpr) 

5335 else: 

5336 assert False 

5337 self.expressions = self._table_bound_expressions = exprs 

5338 

5339 def create(self, bind: _CreateDropBind, checkfirst: bool = False) -> None: 

5340 """Issue a ``CREATE`` statement for this 

5341 :class:`.Index`, using the given 

5342 :class:`.Connection` or :class:`.Engine`` for connectivity. 

5343 

5344 .. seealso:: 

5345 

5346 :meth:`_schema.MetaData.create_all`. 

5347 

5348 """ 

5349 bind._run_ddl_visitor(ddl.SchemaGenerator, self, checkfirst=checkfirst) 

5350 

5351 def drop(self, bind: _CreateDropBind, checkfirst: bool = False) -> None: 

5352 """Issue a ``DROP`` statement for this 

5353 :class:`.Index`, using the given 

5354 :class:`.Connection` or :class:`.Engine` for connectivity. 

5355 

5356 .. seealso:: 

5357 

5358 :meth:`_schema.MetaData.drop_all`. 

5359 

5360 """ 

5361 bind._run_ddl_visitor(ddl.SchemaDropper, self, checkfirst=checkfirst) 

5362 

5363 def __repr__(self) -> str: 

5364 exprs: _typing_Sequence[Any] # noqa: F842 

5365 

5366 return "Index(%s)" % ( 

5367 ", ".join( 

5368 [repr(self.name)] 

5369 + [repr(e) for e in self.expressions] 

5370 + (self.unique and ["unique=True"] or []) 

5371 ) 

5372 ) 

5373 

5374 

5375_NamingSchemaCallable = Callable[[Constraint, Table], str] 

5376_NamingSchemaDirective = Union[str, _NamingSchemaCallable] 

5377 

5378 

5379class _NamingSchemaTD(TypedDict, total=False): 

5380 fk: _NamingSchemaDirective 

5381 pk: _NamingSchemaDirective 

5382 ix: _NamingSchemaDirective 

5383 ck: _NamingSchemaDirective 

5384 uq: _NamingSchemaDirective 

5385 

5386 

5387_NamingSchemaParameter = Union[ 

5388 # it seems like the TypedDict here is useful for pylance typeahead, 

5389 # and not much else 

5390 _NamingSchemaTD, 

5391 # there is no form that allows Union[Type[Any], str] to work in all 

5392 # cases, including breaking out Mapping[] entries for each combination 

5393 # even, therefore keys must be `Any` (see #10264) 

5394 Mapping[Any, _NamingSchemaDirective], 

5395] 

5396 

5397 

5398DEFAULT_NAMING_CONVENTION: _NamingSchemaParameter = util.immutabledict( 

5399 {"ix": "ix_%(column_0_label)s"} 

5400) 

5401 

5402 

5403class MetaData(HasSchemaAttr): 

5404 """A collection of :class:`_schema.Table` 

5405 objects and their associated schema 

5406 constructs. 

5407 

5408 Holds a collection of :class:`_schema.Table` objects as well as 

5409 an optional binding to an :class:`_engine.Engine` or 

5410 :class:`_engine.Connection`. If bound, the :class:`_schema.Table` objects 

5411 in the collection and their columns may participate in implicit SQL 

5412 execution. 

5413 

5414 The :class:`_schema.Table` objects themselves are stored in the 

5415 :attr:`_schema.MetaData.tables` dictionary. 

5416 

5417 :class:`_schema.MetaData` is a thread-safe object for read operations. 

5418 Construction of new tables within a single :class:`_schema.MetaData` 

5419 object, 

5420 either explicitly or via reflection, may not be completely thread-safe. 

5421 

5422 .. seealso:: 

5423 

5424 :ref:`metadata_describing` - Introduction to database metadata 

5425 

5426 """ 

5427 

5428 __visit_name__ = "metadata" 

5429 

5430 def __init__( 

5431 self, 

5432 schema: Optional[str] = None, 

5433 quote_schema: Optional[bool] = None, 

5434 naming_convention: Optional[_NamingSchemaParameter] = None, 

5435 info: Optional[_InfoType] = None, 

5436 ) -> None: 

5437 """Create a new MetaData object. 

5438 

5439 :param schema: 

5440 The default schema to use for the :class:`_schema.Table`, 

5441 :class:`.Sequence`, and potentially other objects associated with 

5442 this :class:`_schema.MetaData`. Defaults to ``None``. 

5443 

5444 .. seealso:: 

5445 

5446 :ref:`schema_metadata_schema_name` - details on how the 

5447 :paramref:`_schema.MetaData.schema` parameter is used. 

5448 

5449 :paramref:`_schema.Table.schema` 

5450 

5451 :paramref:`.Sequence.schema` 

5452 

5453 :param quote_schema: 

5454 Sets the ``quote_schema`` flag for those :class:`_schema.Table`, 

5455 :class:`.Sequence`, and other objects which make usage of the 

5456 local ``schema`` name. 

5457 

5458 :param info: Optional data dictionary which will be populated into the 

5459 :attr:`.SchemaItem.info` attribute of this object. 

5460 

5461 :param naming_convention: a dictionary referring to values which 

5462 will establish default naming conventions for :class:`.Constraint` 

5463 and :class:`.Index` objects, for those objects which are not given 

5464 a name explicitly. 

5465 

5466 The keys of this dictionary may be: 

5467 

5468 * a constraint or Index class, e.g. the :class:`.UniqueConstraint`, 

5469 :class:`_schema.ForeignKeyConstraint` class, the :class:`.Index` 

5470 class 

5471 

5472 * a string mnemonic for one of the known constraint classes; 

5473 ``"fk"``, ``"pk"``, ``"ix"``, ``"ck"``, ``"uq"`` for foreign key, 

5474 primary key, index, check, and unique constraint, respectively. 

5475 

5476 * the string name of a user-defined "token" that can be used 

5477 to define new naming tokens. 

5478 

5479 The values associated with each "constraint class" or "constraint 

5480 mnemonic" key are string naming templates, such as 

5481 ``"uq_%(table_name)s_%(column_0_name)s"``, 

5482 which describe how the name should be composed. The values 

5483 associated with user-defined "token" keys should be callables of the 

5484 form ``fn(constraint, table)``, which accepts the constraint/index 

5485 object and :class:`_schema.Table` as arguments, returning a string 

5486 result. 

5487 

5488 The built-in names are as follows, some of which may only be 

5489 available for certain types of constraint: 

5490 

5491 * ``%(table_name)s`` - the name of the :class:`_schema.Table` 

5492 object 

5493 associated with the constraint. 

5494 

5495 * ``%(referred_table_name)s`` - the name of the 

5496 :class:`_schema.Table` 

5497 object associated with the referencing target of a 

5498 :class:`_schema.ForeignKeyConstraint`. 

5499 

5500 * ``%(column_0_name)s`` - the name of the :class:`_schema.Column` 

5501 at 

5502 index position "0" within the constraint. 

5503 

5504 * ``%(column_0N_name)s`` - the name of all :class:`_schema.Column` 

5505 objects in order within the constraint, joined without a 

5506 separator. 

5507 

5508 * ``%(column_0_N_name)s`` - the name of all 

5509 :class:`_schema.Column` 

5510 objects in order within the constraint, joined with an 

5511 underscore as a separator. 

5512 

5513 * ``%(column_0_label)s``, ``%(column_0N_label)s``, 

5514 ``%(column_0_N_label)s`` - the label of either the zeroth 

5515 :class:`_schema.Column` or all :class:`.Columns`, separated with 

5516 or without an underscore 

5517 

5518 * ``%(column_0_key)s``, ``%(column_0N_key)s``, 

5519 ``%(column_0_N_key)s`` - the key of either the zeroth 

5520 :class:`_schema.Column` or all :class:`.Columns`, separated with 

5521 or without an underscore 

5522 

5523 * ``%(referred_column_0_name)s``, ``%(referred_column_0N_name)s`` 

5524 ``%(referred_column_0_N_name)s``, ``%(referred_column_0_key)s``, 

5525 ``%(referred_column_0N_key)s``, ... column tokens which 

5526 render the names/keys/labels of columns that are referenced 

5527 by a :class:`_schema.ForeignKeyConstraint`. 

5528 

5529 * ``%(constraint_name)s`` - a special key that refers to the 

5530 existing name given to the constraint. When this key is 

5531 present, the :class:`.Constraint` object's existing name will be 

5532 replaced with one that is composed from template string that 

5533 uses this token. When this token is present, it is required that 

5534 the :class:`.Constraint` is given an explicit name ahead of time. 

5535 

5536 * user-defined: any additional token may be implemented by passing 

5537 it along with a ``fn(constraint, table)`` callable to the 

5538 naming_convention dictionary. 

5539 

5540 .. versionadded:: 1.3.0 - added new ``%(column_0N_name)s``, 

5541 ``%(column_0_N_name)s``, and related tokens that produce 

5542 concatenations of names, keys, or labels for all columns referred 

5543 to by a given constraint. 

5544 

5545 .. seealso:: 

5546 

5547 :ref:`constraint_naming_conventions` - for detailed usage 

5548 examples. 

5549 

5550 """ 

5551 if schema is not None and not isinstance(schema, str): 

5552 raise exc.ArgumentError( 

5553 "expected schema argument to be a string, " 

5554 f"got {type(schema)}." 

5555 ) 

5556 self.tables = util.FacadeDict() 

5557 self.schema = quoted_name.construct(schema, quote_schema) 

5558 self.naming_convention = ( 

5559 naming_convention 

5560 if naming_convention 

5561 else DEFAULT_NAMING_CONVENTION 

5562 ) 

5563 if info: 

5564 self.info = info 

5565 self._schemas: Set[str] = set() 

5566 self._sequences: Dict[str, Sequence] = {} 

5567 self._fk_memos: Dict[Tuple[str, Optional[str]], List[ForeignKey]] = ( 

5568 collections.defaultdict(list) 

5569 ) 

5570 

5571 tables: util.FacadeDict[str, Table] 

5572 """A dictionary of :class:`_schema.Table` 

5573 objects keyed to their name or "table key". 

5574 

5575 The exact key is that determined by the :attr:`_schema.Table.key` 

5576 attribute; 

5577 for a table with no :attr:`_schema.Table.schema` attribute, 

5578 this is the same 

5579 as :attr:`_schema.Table.name`. For a table with a schema, 

5580 it is typically of the 

5581 form ``schemaname.tablename``. 

5582 

5583 .. seealso:: 

5584 

5585 :attr:`_schema.MetaData.sorted_tables` 

5586 

5587 """ 

5588 

5589 def __repr__(self) -> str: 

5590 return "MetaData()" 

5591 

5592 def __contains__(self, table_or_key: Union[str, Table]) -> bool: 

5593 if not isinstance(table_or_key, str): 

5594 table_or_key = table_or_key.key 

5595 return table_or_key in self.tables 

5596 

5597 def _add_table( 

5598 self, name: str, schema: Optional[str], table: Table 

5599 ) -> None: 

5600 key = _get_table_key(name, schema) 

5601 self.tables._insert_item(key, table) 

5602 if schema: 

5603 self._schemas.add(schema) 

5604 

5605 def _remove_table(self, name: str, schema: Optional[str]) -> None: 

5606 key = _get_table_key(name, schema) 

5607 removed = dict.pop(self.tables, key, None) 

5608 if removed is not None: 

5609 for fk in removed.foreign_keys: 

5610 fk._remove_from_metadata(self) 

5611 if self._schemas: 

5612 self._schemas = { 

5613 t.schema for t in self.tables.values() if t.schema is not None 

5614 } 

5615 

5616 def __getstate__(self) -> Dict[str, Any]: 

5617 return { 

5618 "tables": self.tables, 

5619 "schema": self.schema, 

5620 "schemas": self._schemas, 

5621 "sequences": self._sequences, 

5622 "fk_memos": self._fk_memos, 

5623 "naming_convention": self.naming_convention, 

5624 } 

5625 

5626 def __setstate__(self, state: Dict[str, Any]) -> None: 

5627 self.tables = state["tables"] 

5628 self.schema = state["schema"] 

5629 self.naming_convention = state["naming_convention"] 

5630 self._sequences = state["sequences"] 

5631 self._schemas = state["schemas"] 

5632 self._fk_memos = state["fk_memos"] 

5633 

5634 def clear(self) -> None: 

5635 """Clear all Table objects from this MetaData.""" 

5636 

5637 dict.clear(self.tables) # type: ignore 

5638 self._schemas.clear() 

5639 self._fk_memos.clear() 

5640 

5641 def remove(self, table: Table) -> None: 

5642 """Remove the given Table object from this MetaData.""" 

5643 

5644 self._remove_table(table.name, table.schema) 

5645 

5646 @property 

5647 def sorted_tables(self) -> List[Table]: 

5648 """Returns a list of :class:`_schema.Table` objects sorted in order of 

5649 foreign key dependency. 

5650 

5651 The sorting will place :class:`_schema.Table` 

5652 objects that have dependencies 

5653 first, before the dependencies themselves, representing the 

5654 order in which they can be created. To get the order in which 

5655 the tables would be dropped, use the ``reversed()`` Python built-in. 

5656 

5657 .. warning:: 

5658 

5659 The :attr:`.MetaData.sorted_tables` attribute cannot by itself 

5660 accommodate automatic resolution of dependency cycles between 

5661 tables, which are usually caused by mutually dependent foreign key 

5662 constraints. When these cycles are detected, the foreign keys 

5663 of these tables are omitted from consideration in the sort. 

5664 A warning is emitted when this condition occurs, which will be an 

5665 exception raise in a future release. Tables which are not part 

5666 of the cycle will still be returned in dependency order. 

5667 

5668 To resolve these cycles, the 

5669 :paramref:`_schema.ForeignKeyConstraint.use_alter` parameter may be 

5670 applied to those constraints which create a cycle. Alternatively, 

5671 the :func:`_schema.sort_tables_and_constraints` function will 

5672 automatically return foreign key constraints in a separate 

5673 collection when cycles are detected so that they may be applied 

5674 to a schema separately. 

5675 

5676 .. versionchanged:: 1.3.17 - a warning is emitted when 

5677 :attr:`.MetaData.sorted_tables` cannot perform a proper sort 

5678 due to cyclical dependencies. This will be an exception in a 

5679 future release. Additionally, the sort will continue to return 

5680 other tables not involved in the cycle in dependency order which 

5681 was not the case previously. 

5682 

5683 .. seealso:: 

5684 

5685 :func:`_schema.sort_tables` 

5686 

5687 :func:`_schema.sort_tables_and_constraints` 

5688 

5689 :attr:`_schema.MetaData.tables` 

5690 

5691 :meth:`_reflection.Inspector.get_table_names` 

5692 

5693 :meth:`_reflection.Inspector.get_sorted_table_and_fkc_names` 

5694 

5695 

5696 """ 

5697 return ddl.sort_tables( 

5698 sorted(self.tables.values(), key=lambda t: t.key) # type: ignore 

5699 ) 

5700 

5701 # overload needed to work around mypy this mypy 

5702 # https://github.com/python/mypy/issues/17093 

5703 @overload 

5704 def reflect( 

5705 self, 

5706 bind: Engine, 

5707 schema: Optional[str] = ..., 

5708 views: bool = ..., 

5709 only: Union[ 

5710 _typing_Sequence[str], Callable[[str, MetaData], bool], None 

5711 ] = ..., 

5712 extend_existing: bool = ..., 

5713 autoload_replace: bool = ..., 

5714 resolve_fks: bool = ..., 

5715 **dialect_kwargs: Any, 

5716 ) -> None: ... 

5717 

5718 @overload 

5719 def reflect( 

5720 self, 

5721 bind: Connection, 

5722 schema: Optional[str] = ..., 

5723 views: bool = ..., 

5724 only: Union[ 

5725 _typing_Sequence[str], Callable[[str, MetaData], bool], None 

5726 ] = ..., 

5727 extend_existing: bool = ..., 

5728 autoload_replace: bool = ..., 

5729 resolve_fks: bool = ..., 

5730 **dialect_kwargs: Any, 

5731 ) -> None: ... 

5732 

5733 @util.preload_module("sqlalchemy.engine.reflection") 

5734 def reflect( 

5735 self, 

5736 bind: Union[Engine, Connection], 

5737 schema: Optional[str] = None, 

5738 views: bool = False, 

5739 only: Union[ 

5740 _typing_Sequence[str], Callable[[str, MetaData], bool], None 

5741 ] = None, 

5742 extend_existing: bool = False, 

5743 autoload_replace: bool = True, 

5744 resolve_fks: bool = True, 

5745 **dialect_kwargs: Any, 

5746 ) -> None: 

5747 r"""Load all available table definitions from the database. 

5748 

5749 Automatically creates ``Table`` entries in this ``MetaData`` for any 

5750 table available in the database but not yet present in the 

5751 ``MetaData``. May be called multiple times to pick up tables recently 

5752 added to the database, however no special action is taken if a table 

5753 in this ``MetaData`` no longer exists in the database. 

5754 

5755 :param bind: 

5756 A :class:`.Connection` or :class:`.Engine` used to access the 

5757 database. 

5758 

5759 :param schema: 

5760 Optional, query and reflect tables from an alternate schema. 

5761 If None, the schema associated with this :class:`_schema.MetaData` 

5762 is used, if any. 

5763 

5764 :param views: 

5765 If True, also reflect views (materialized and plain). 

5766 

5767 :param only: 

5768 Optional. Load only a sub-set of available named tables. May be 

5769 specified as a sequence of names or a callable. 

5770 

5771 If a sequence of names is provided, only those tables will be 

5772 reflected. An error is raised if a table is requested but not 

5773 available. Named tables already present in this ``MetaData`` are 

5774 ignored. 

5775 

5776 If a callable is provided, it will be used as a boolean predicate to 

5777 filter the list of potential table names. The callable is called 

5778 with a table name and this ``MetaData`` instance as positional 

5779 arguments and should return a true value for any table to reflect. 

5780 

5781 :param extend_existing: Passed along to each :class:`_schema.Table` as 

5782 :paramref:`_schema.Table.extend_existing`. 

5783 

5784 :param autoload_replace: Passed along to each :class:`_schema.Table` 

5785 as 

5786 :paramref:`_schema.Table.autoload_replace`. 

5787 

5788 :param resolve_fks: if True, reflect :class:`_schema.Table` 

5789 objects linked 

5790 to :class:`_schema.ForeignKey` objects located in each 

5791 :class:`_schema.Table`. 

5792 For :meth:`_schema.MetaData.reflect`, 

5793 this has the effect of reflecting 

5794 related tables that might otherwise not be in the list of tables 

5795 being reflected, for example if the referenced table is in a 

5796 different schema or is omitted via the 

5797 :paramref:`.MetaData.reflect.only` parameter. When False, 

5798 :class:`_schema.ForeignKey` objects are not followed to the 

5799 :class:`_schema.Table` 

5800 in which they link, however if the related table is also part of the 

5801 list of tables that would be reflected in any case, the 

5802 :class:`_schema.ForeignKey` object will still resolve to its related 

5803 :class:`_schema.Table` after the :meth:`_schema.MetaData.reflect` 

5804 operation is 

5805 complete. Defaults to True. 

5806 

5807 .. versionadded:: 1.3.0 

5808 

5809 .. seealso:: 

5810 

5811 :paramref:`_schema.Table.resolve_fks` 

5812 

5813 :param \**dialect_kwargs: Additional keyword arguments not mentioned 

5814 above are dialect specific, and passed in the form 

5815 ``<dialectname>_<argname>``. See the documentation regarding an 

5816 individual dialect at :ref:`dialect_toplevel` for detail on 

5817 documented arguments. 

5818 

5819 .. seealso:: 

5820 

5821 :ref:`metadata_reflection_toplevel` 

5822 

5823 :meth:`_events.DDLEvents.column_reflect` - Event used to customize 

5824 the reflected columns. Usually used to generalize the types using 

5825 :meth:`_types.TypeEngine.as_generic` 

5826 

5827 :ref:`metadata_reflection_dbagnostic_types` - describes how to 

5828 reflect tables using general types. 

5829 

5830 """ 

5831 

5832 with inspection.inspect(bind)._inspection_context() as insp: 

5833 reflect_opts: Any = { 

5834 "autoload_with": insp, 

5835 "extend_existing": extend_existing, 

5836 "autoload_replace": autoload_replace, 

5837 "resolve_fks": resolve_fks, 

5838 "_extend_on": set(), 

5839 } 

5840 

5841 reflect_opts.update(dialect_kwargs) 

5842 

5843 if schema is None: 

5844 schema = self.schema 

5845 

5846 if schema is not None: 

5847 reflect_opts["schema"] = schema 

5848 

5849 kind = util.preloaded.engine_reflection.ObjectKind.TABLE 

5850 available: util.OrderedSet[str] = util.OrderedSet( 

5851 insp.get_table_names(schema) 

5852 ) 

5853 if views: 

5854 kind = util.preloaded.engine_reflection.ObjectKind.ANY 

5855 available.update(insp.get_view_names(schema)) 

5856 try: 

5857 available.update(insp.get_materialized_view_names(schema)) 

5858 except NotImplementedError: 

5859 pass 

5860 

5861 if schema is not None: 

5862 available_w_schema: util.OrderedSet[str] = util.OrderedSet( 

5863 [f"{schema}.{name}" for name in available] 

5864 ) 

5865 else: 

5866 available_w_schema = available 

5867 

5868 current = set(self.tables) 

5869 

5870 if only is None: 

5871 load = [ 

5872 name 

5873 for name, schname in zip(available, available_w_schema) 

5874 if extend_existing or schname not in current 

5875 ] 

5876 elif callable(only): 

5877 load = [ 

5878 name 

5879 for name, schname in zip(available, available_w_schema) 

5880 if (extend_existing or schname not in current) 

5881 and only(name, self) 

5882 ] 

5883 else: 

5884 missing = [name for name in only if name not in available] 

5885 if missing: 

5886 s = schema and (" schema '%s'" % schema) or "" 

5887 missing_str = ", ".join(missing) 

5888 raise exc.InvalidRequestError( 

5889 f"Could not reflect: requested table(s) not available " 

5890 f"in {bind.engine!r}{s}: ({missing_str})" 

5891 ) 

5892 load = [ 

5893 name 

5894 for name in only 

5895 if extend_existing or name not in current 

5896 ] 

5897 # pass the available tables so the inspector can 

5898 # choose to ignore the filter_names 

5899 _reflect_info = insp._get_reflection_info( 

5900 schema=schema, 

5901 filter_names=load, 

5902 available=available, 

5903 kind=kind, 

5904 scope=util.preloaded.engine_reflection.ObjectScope.ANY, 

5905 **dialect_kwargs, 

5906 ) 

5907 reflect_opts["_reflect_info"] = _reflect_info 

5908 

5909 for name in load: 

5910 try: 

5911 Table(name, self, **reflect_opts) 

5912 except exc.UnreflectableTableError as uerr: 

5913 util.warn(f"Skipping table {name}: {uerr}") 

5914 

5915 def create_all( 

5916 self, 

5917 bind: _CreateDropBind, 

5918 tables: Optional[_typing_Sequence[Table]] = None, 

5919 checkfirst: bool = True, 

5920 ) -> None: 

5921 """Create all tables stored in this metadata. 

5922 

5923 Conditional by default, will not attempt to recreate tables already 

5924 present in the target database. 

5925 

5926 :param bind: 

5927 A :class:`.Connection` or :class:`.Engine` used to access the 

5928 database. 

5929 

5930 :param tables: 

5931 Optional list of ``Table`` objects, which is a subset of the total 

5932 tables in the ``MetaData`` (others are ignored). 

5933 

5934 :param checkfirst: 

5935 Defaults to True, don't issue CREATEs for tables already present 

5936 in the target database. 

5937 

5938 """ 

5939 bind._run_ddl_visitor( 

5940 ddl.SchemaGenerator, self, checkfirst=checkfirst, tables=tables 

5941 ) 

5942 

5943 def drop_all( 

5944 self, 

5945 bind: _CreateDropBind, 

5946 tables: Optional[_typing_Sequence[Table]] = None, 

5947 checkfirst: bool = True, 

5948 ) -> None: 

5949 """Drop all tables stored in this metadata. 

5950 

5951 Conditional by default, will not attempt to drop tables not present in 

5952 the target database. 

5953 

5954 :param bind: 

5955 A :class:`.Connection` or :class:`.Engine` used to access the 

5956 database. 

5957 

5958 :param tables: 

5959 Optional list of ``Table`` objects, which is a subset of the 

5960 total tables in the ``MetaData`` (others are ignored). 

5961 

5962 :param checkfirst: 

5963 Defaults to True, only issue DROPs for tables confirmed to be 

5964 present in the target database. 

5965 

5966 """ 

5967 bind._run_ddl_visitor( 

5968 ddl.SchemaDropper, self, checkfirst=checkfirst, tables=tables 

5969 ) 

5970 

5971 

5972class Computed(FetchedValue, SchemaItem): 

5973 """Defines a generated column, i.e. "GENERATED ALWAYS AS" syntax. 

5974 

5975 The :class:`.Computed` construct is an inline construct added to the 

5976 argument list of a :class:`_schema.Column` object:: 

5977 

5978 from sqlalchemy import Computed 

5979 

5980 Table('square', metadata_obj, 

5981 Column('side', Float, nullable=False), 

5982 Column('area', Float, Computed('side * side')) 

5983 ) 

5984 

5985 See the linked documentation below for complete details. 

5986 

5987 .. versionadded:: 1.3.11 

5988 

5989 .. seealso:: 

5990 

5991 :ref:`computed_ddl` 

5992 

5993 """ 

5994 

5995 __visit_name__ = "computed_column" 

5996 

5997 column: Optional[Column[Any]] 

5998 

5999 @_document_text_coercion( 

6000 "sqltext", ":class:`.Computed`", ":paramref:`.Computed.sqltext`" 

6001 ) 

6002 def __init__( 

6003 self, sqltext: _DDLColumnArgument, persisted: Optional[bool] = None 

6004 ) -> None: 

6005 """Construct a GENERATED ALWAYS AS DDL construct to accompany a 

6006 :class:`_schema.Column`. 

6007 

6008 :param sqltext: 

6009 A string containing the column generation expression, which will be 

6010 used verbatim, or a SQL expression construct, such as a 

6011 :func:`_expression.text` 

6012 object. If given as a string, the object is converted to a 

6013 :func:`_expression.text` object. 

6014 

6015 :param persisted: 

6016 Optional, controls how this column should be persisted by the 

6017 database. Possible values are: 

6018 

6019 * ``None``, the default, it will use the default persistence 

6020 defined by the database. 

6021 * ``True``, will render ``GENERATED ALWAYS AS ... STORED``, or the 

6022 equivalent for the target database if supported. 

6023 * ``False``, will render ``GENERATED ALWAYS AS ... VIRTUAL``, or 

6024 the equivalent for the target database if supported. 

6025 

6026 Specifying ``True`` or ``False`` may raise an error when the DDL 

6027 is emitted to the target database if the database does not support 

6028 that persistence option. Leaving this parameter at its default 

6029 of ``None`` is guaranteed to succeed for all databases that support 

6030 ``GENERATED ALWAYS AS``. 

6031 

6032 """ 

6033 self.sqltext = coercions.expect(roles.DDLExpressionRole, sqltext) 

6034 self.persisted = persisted 

6035 self.column = None 

6036 

6037 def _set_parent(self, parent: SchemaEventTarget, **kw: Any) -> None: 

6038 assert isinstance(parent, Column) 

6039 

6040 if not isinstance( 

6041 parent.server_default, (type(None), Computed) 

6042 ) or not isinstance(parent.server_onupdate, (type(None), Computed)): 

6043 raise exc.ArgumentError( 

6044 "A generated column cannot specify a server_default or a " 

6045 "server_onupdate argument" 

6046 ) 

6047 self.column = parent 

6048 parent.computed = self 

6049 self.column.server_onupdate = self 

6050 self.column.server_default = self 

6051 

6052 def _as_for_update(self, for_update: bool) -> FetchedValue: 

6053 return self 

6054 

6055 @util.deprecated( 

6056 "1.4", 

6057 "The :meth:`_schema.Computed.copy` method is deprecated " 

6058 "and will be removed in a future release.", 

6059 ) 

6060 def copy( 

6061 self, *, target_table: Optional[Table] = None, **kw: Any 

6062 ) -> Computed: 

6063 return self._copy(target_table=target_table, **kw) 

6064 

6065 def _copy( 

6066 self, *, target_table: Optional[Table] = None, **kw: Any 

6067 ) -> Computed: 

6068 sqltext = _copy_expression( 

6069 self.sqltext, 

6070 self.column.table if self.column is not None else None, 

6071 target_table, 

6072 ) 

6073 g = Computed(sqltext, persisted=self.persisted) 

6074 

6075 return self._schema_item_copy(g) 

6076 

6077 

6078class Identity(IdentityOptions, FetchedValue, SchemaItem): 

6079 """Defines an identity column, i.e. "GENERATED { ALWAYS | BY DEFAULT } 

6080 AS IDENTITY" syntax. 

6081 

6082 The :class:`.Identity` construct is an inline construct added to the 

6083 argument list of a :class:`_schema.Column` object:: 

6084 

6085 from sqlalchemy import Identity 

6086 

6087 Table('foo', metadata_obj, 

6088 Column('id', Integer, Identity()) 

6089 Column('description', Text), 

6090 ) 

6091 

6092 See the linked documentation below for complete details. 

6093 

6094 .. versionadded:: 1.4 

6095 

6096 .. seealso:: 

6097 

6098 :ref:`identity_ddl` 

6099 

6100 """ 

6101 

6102 __visit_name__ = "identity_column" 

6103 

6104 is_identity = True 

6105 

6106 @util.deprecated_params( 

6107 order=( 

6108 "2.1", 

6109 "This parameter is supported only by Oracle, " 

6110 "use ``oracle_order`` instead.", 

6111 ), 

6112 on_null=( 

6113 "2.1", 

6114 "This parameter is supported only by Oracle, " 

6115 "use ``oracle_on_null`` instead.", 

6116 ), 

6117 ) 

6118 def __init__( 

6119 self, 

6120 always: Optional[bool] = False, 

6121 on_null: Optional[bool] = None, 

6122 start: Optional[int] = None, 

6123 increment: Optional[int] = None, 

6124 minvalue: Optional[int] = None, 

6125 maxvalue: Optional[int] = None, 

6126 nominvalue: Optional[bool] = None, 

6127 nomaxvalue: Optional[bool] = None, 

6128 cycle: Optional[bool] = None, 

6129 cache: Optional[int] = None, 

6130 order: Optional[bool] = None, 

6131 **dialect_kw: Any, 

6132 ) -> None: 

6133 """Construct a GENERATED { ALWAYS | BY DEFAULT } AS IDENTITY DDL 

6134 construct to accompany a :class:`_schema.Column`. 

6135 

6136 See the :class:`.Sequence` documentation for a complete description 

6137 of most parameters. 

6138 

6139 .. note:: 

6140 MSSQL supports this construct as the preferred alternative to 

6141 generate an IDENTITY on a column, but it uses non standard 

6142 syntax that only support :paramref:`_schema.Identity.start` 

6143 and :paramref:`_schema.Identity.increment`. 

6144 All other parameters are ignored. 

6145 

6146 :param always: 

6147 A boolean, that indicates the type of identity column. 

6148 If ``False`` is specified, the default, then the user-specified 

6149 value takes precedence. 

6150 If ``True`` is specified, a user-specified value is not accepted ( 

6151 on some backends, like PostgreSQL, OVERRIDING SYSTEM VALUE, or 

6152 similar, may be specified in an INSERT to override the sequence 

6153 value). 

6154 Some backends also have a default value for this parameter, 

6155 ``None`` can be used to omit rendering this part in the DDL. It 

6156 will be treated as ``False`` if a backend does not have a default 

6157 value. 

6158 

6159 :param on_null: 

6160 Set to ``True`` to specify ON NULL in conjunction with a 

6161 ``always=False`` identity column. This option is only supported on 

6162 some backends, like Oracle. 

6163 

6164 :param start: the starting index of the sequence. 

6165 :param increment: the increment value of the sequence. 

6166 :param minvalue: the minimum value of the sequence. 

6167 :param maxvalue: the maximum value of the sequence. 

6168 :param nominvalue: no minimum value of the sequence. 

6169 :param nomaxvalue: no maximum value of the sequence. 

6170 :param cycle: allows the sequence to wrap around when the maxvalue 

6171 or minvalue has been reached. 

6172 :param cache: optional integer value; number of future values in the 

6173 sequence which are calculated in advance. 

6174 :param order: optional boolean value; if true, renders the 

6175 ORDER keyword. 

6176 

6177 """ 

6178 self.dialect_options 

6179 if on_null is not None: 

6180 if "oracle_on_null" in dialect_kw: 

6181 raise exc.ArgumentError( 

6182 "Cannot specify both 'on_null' and 'oracle_on_null'. " 

6183 "Plese use only 'oracle_on_null'." 

6184 ) 

6185 dialect_kw["oracle_on_null"] = on_null 

6186 

6187 IdentityOptions.__init__( 

6188 self, 

6189 start=start, 

6190 increment=increment, 

6191 minvalue=minvalue, 

6192 maxvalue=maxvalue, 

6193 nominvalue=nominvalue, 

6194 nomaxvalue=nomaxvalue, 

6195 cycle=cycle, 

6196 cache=cache, 

6197 order=order, 

6198 **dialect_kw, 

6199 ) 

6200 self.always = always 

6201 self.column = None 

6202 

6203 @property 

6204 def on_null(self) -> Optional[bool]: 

6205 """Alias of the ``dialect_kwargs`` ``'oracle_on_null'``. 

6206 

6207 .. deprecated:: 2.1 The 'on_null' attribute is deprecated. 

6208 """ 

6209 value: Optional[bool] = self.dialect_kwargs.get("oracle_on_null") 

6210 return value 

6211 

6212 def _set_parent(self, parent: SchemaEventTarget, **kw: Any) -> None: 

6213 assert isinstance(parent, Column) 

6214 if not isinstance( 

6215 parent.server_default, (type(None), Identity) 

6216 ) or not isinstance(parent.server_onupdate, type(None)): 

6217 raise exc.ArgumentError( 

6218 "A column with an Identity object cannot specify a " 

6219 "server_default or a server_onupdate argument" 

6220 ) 

6221 if parent.autoincrement is False: 

6222 raise exc.ArgumentError( 

6223 "A column with an Identity object cannot specify " 

6224 "autoincrement=False" 

6225 ) 

6226 self.column = parent 

6227 

6228 parent.identity = self 

6229 if parent._user_defined_nullable is NULL_UNSPECIFIED: 

6230 parent.nullable = False 

6231 

6232 parent.server_default = self 

6233 

6234 def _as_for_update(self, for_update: bool) -> FetchedValue: 

6235 return self 

6236 

6237 @util.deprecated( 

6238 "1.4", 

6239 "The :meth:`_schema.Identity.copy` method is deprecated " 

6240 "and will be removed in a future release.", 

6241 ) 

6242 def copy(self, **kw: Any) -> Identity: 

6243 return self._copy(**kw) 

6244 

6245 def _copy(self, **kw: Any) -> Identity: 

6246 i = Identity(**self._as_dict(), **self.dialect_kwargs) 

6247 

6248 return self._schema_item_copy(i) 

6249 

6250 def _as_dict(self) -> Dict[str, Any]: 

6251 return { 

6252 # always=None means something different than always=False 

6253 "always": self.always, 

6254 **super()._as_dict(), 

6255 }