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

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

1708 statements  

1# sql/schema.py 

2# Copyright (C) 2005-2025 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 Literal 

48from typing import Mapping 

49from typing import NoReturn 

50from typing import Optional 

51from typing import overload 

52from typing import Protocol 

53from typing import Sequence as _typing_Sequence 

54from typing import Set 

55from typing import Tuple 

56from typing import Type 

57from typing import TYPE_CHECKING 

58from typing import TypedDict 

59from typing import TypeGuard 

60from typing import TypeVar 

61from typing import Union 

62 

63from . import coercions 

64from . import ddl 

65from . import roles 

66from . import type_api 

67from . import visitors 

68from .base import _DefaultDescriptionTuple 

69from .base import _NoArg 

70from .base import _NoneName 

71from .base import _SentinelColumnCharacterization 

72from .base import _SentinelDefaultCharacterization 

73from .base import DedupeColumnCollection 

74from .base import DialectKWArgs 

75from .base import Executable 

76from .base import SchemaEventTarget as SchemaEventTarget 

77from .base import SchemaVisitable as SchemaVisitable 

78from .coercions import _document_text_coercion 

79from .ddl import CheckFirst 

80from .elements import ClauseElement 

81from .elements import ColumnClause 

82from .elements import ColumnElement 

83from .elements import quoted_name 

84from .elements import TextClause 

85from .selectable import TableClause 

86from .type_api import to_instance 

87from .visitors import ExternallyTraversible 

88from .. import event 

89from .. import exc 

90from .. import inspection 

91from .. import util 

92from ..util import HasMemoized 

93from ..util.typing import Self 

94 

95if typing.TYPE_CHECKING: 

96 from ._typing import _AutoIncrementType 

97 from ._typing import _CreateDropBind 

98 from ._typing import _DDLColumnArgument 

99 from ._typing import _DDLColumnReferenceArgument 

100 from ._typing import _InfoType 

101 from ._typing import _TextCoercedExpressionArgument 

102 from ._typing import _TypeEngineArgument 

103 from .base import ColumnSet 

104 from .base import ReadOnlyColumnCollection 

105 from .compiler import DDLCompiler 

106 from .elements import BindParameter 

107 from .elements import KeyedColumnElement 

108 from .functions import Function 

109 from .sqltypes import SchemaType 

110 from .type_api import TypeEngine 

111 from .visitors import anon_map 

112 from ..engine import Connection 

113 from ..engine import Engine 

114 from ..engine.interfaces import _CoreMultiExecuteParams 

115 from ..engine.interfaces import CoreExecuteOptionsParameter 

116 from ..engine.interfaces import ExecutionContext 

117 from ..engine.reflection import _ReflectionInfo 

118 from ..sql.selectable import FromClause 

119 

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

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

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

123 

124 

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

126 

127_ServerDefaultArgument = Union[ 

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

129] 

130 

131_ServerOnUpdateArgument = _ServerDefaultArgument 

132 

133 

134class SchemaConst(Enum): 

135 RETAIN_SCHEMA = 1 

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

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

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

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

140 

141 """ 

142 

143 BLANK_SCHEMA = 2 

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

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

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

147 

148 .. seealso:: 

149 

150 :paramref:`_schema.MetaData.schema` 

151 

152 :paramref:`_schema.Table.schema` 

153 

154 :paramref:`.Sequence.schema` 

155 

156 """ 

157 

158 NULL_UNSPECIFIED = 3 

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

160 

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

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

163 on some backends such as SQL Server. 

164 

165 """ 

166 

167 

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

169 SchemaConst.RETAIN_SCHEMA 

170) 

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

172 SchemaConst.BLANK_SCHEMA 

173) 

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

175 SchemaConst.NULL_UNSPECIFIED 

176) 

177 

178 

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

180 if schema is None: 

181 return name 

182 else: 

183 return schema + "." + name 

184 

185 

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

187# break an import cycle 

188def _copy_expression( 

189 expression: ColumnElement[Any], 

190 source_table: Optional[Table], 

191 target_table: Optional[Table], 

192) -> ColumnElement[Any]: 

193 if source_table is None or target_table is None: 

194 return expression 

195 

196 fixed_source_table = source_table 

197 fixed_target_table = target_table 

198 

199 def replace( 

200 element: ExternallyTraversible, **kw: Any 

201 ) -> Optional[ExternallyTraversible]: 

202 if ( 

203 isinstance(element, Column) 

204 and element.table is fixed_source_table 

205 and element.key in fixed_source_table.c 

206 ): 

207 return fixed_target_table.c[element.key] 

208 else: 

209 return None 

210 

211 return cast( 

212 ColumnElement[Any], 

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

214 ) 

215 

216 

217@inspection._self_inspects 

218class SchemaItem(SchemaVisitable): 

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

220 

221 __visit_name__ = "schema_item" 

222 

223 create_drop_stringify_dialect = "default" 

224 

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

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

227 for item in args: 

228 if item is not None: 

229 try: 

230 spwd = item._set_parent_with_dispatch 

231 except AttributeError as err: 

232 raise exc.ArgumentError( 

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

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

235 ) from err 

236 else: 

237 spwd(self, **kw) 

238 

239 def __repr__(self) -> str: 

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

241 

242 @util.memoized_property 

243 def info(self) -> _InfoType: 

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

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

246 

247 The dictionary is automatically generated when first accessed. 

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

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

250 

251 """ 

252 return {} 

253 

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

255 if "info" in self.__dict__: 

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

257 schema_item.dispatch._update(self.dispatch) 

258 return schema_item 

259 

260 _use_schema_map = True 

261 

262 

263class HasConditionalDDL: 

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

265 method, allowing for conditional rendering of DDL. 

266 

267 Currently applies to constraints and indexes. 

268 

269 .. versionadded:: 2.0 

270 

271 

272 """ 

273 

274 _ddl_if: Optional[ddl.DDLIf] = None 

275 

276 def ddl_if( 

277 self, 

278 dialect: Optional[str] = None, 

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

280 state: Optional[Any] = None, 

281 ) -> Self: 

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

283 

284 These rules work in a similar manner to the 

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

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

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

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

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

290 constructs. 

291 

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

293 to indicate multiple dialect types. 

294 

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

296 as that described in 

297 :paramref:`.ExecutableDDLElement.execute_if.callable_`. 

298 

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

300 callable, if present. 

301 

302 .. versionadded:: 2.0 

303 

304 .. seealso:: 

305 

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

307 

308 

309 """ 

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

311 return self 

312 

313 

314class HasSchemaAttr(SchemaItem): 

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

316 

317 schema: Optional[str] 

318 

319 

320class Table( 

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

322): 

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

324 

325 e.g.:: 

326 

327 mytable = Table( 

328 "mytable", 

329 metadata, 

330 Column("mytable_id", Integer, primary_key=True), 

331 Column("value", String(50)), 

332 ) 

333 

334 The :class:`_schema.Table` 

335 object constructs a unique instance of itself based 

336 on its name and optional schema name within the given 

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

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

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

340 object - in this way 

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

342 

343 .. seealso:: 

344 

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

346 

347 """ 

348 

349 __visit_name__ = "table" 

350 

351 if TYPE_CHECKING: 

352 

353 @util.ro_non_memoized_property 

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

355 

356 @util.ro_non_memoized_property 

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

358 

359 _columns: DedupeColumnCollection[Column[Any]] # type: ignore[assignment] 

360 

361 _sentinel_column: Optional[Column[Any]] 

362 

363 constraints: Set[Constraint] 

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

365 this :class:`_schema.Table`. 

366 

367 Includes :class:`_schema.PrimaryKeyConstraint`, 

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

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

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

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

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

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

374 :class:`_schema.Table`. 

375 

376 .. seealso:: 

377 

378 :attr:`_schema.Table.constraints` 

379 

380 :attr:`_schema.Table.primary_key` 

381 

382 :attr:`_schema.Table.foreign_key_constraints` 

383 

384 :attr:`_schema.Table.indexes` 

385 

386 :class:`_reflection.Inspector` 

387 

388 

389 """ 

390 

391 indexes: Set[Index] 

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

393 :class:`_schema.Table`. 

394 

395 .. seealso:: 

396 

397 :meth:`_reflection.Inspector.get_indexes` 

398 

399 """ 

400 

401 if TYPE_CHECKING: 

402 

403 @util.ro_non_memoized_property 

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

405 

406 @util.ro_non_memoized_property 

407 def exported_columns( 

408 self, 

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

410 

411 @util.ro_non_memoized_property 

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

413 

414 def _gen_cache_key( 

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

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

417 if self._annotations: 

418 return (self,) + self._annotations_cache_key 

419 else: 

420 return (self,) 

421 

422 if not typing.TYPE_CHECKING: 

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

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

425 # __new__. apply typing to the __init__ method normally 

426 @util.deprecated_params( 

427 mustexist=( 

428 "1.4", 

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

430 ), 

431 ) 

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

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

434 

435 @classmethod 

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

437 if not args and not kw: 

438 # python3k pickle seems to call this 

439 return object.__new__(cls) 

440 

441 try: 

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

443 except IndexError: 

444 raise TypeError( 

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

446 "arguments 'name' and 'metadata'" 

447 ) 

448 

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

450 if schema is None: 

451 schema = metadata.schema 

452 elif schema is BLANK_SCHEMA: 

453 schema = None 

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

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

456 

457 if keep_existing and extend_existing: 

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

459 raise exc.ArgumentError(msg) 

460 

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

462 key = _get_table_key(name, schema) 

463 if key in metadata.tables: 

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

465 raise exc.InvalidRequestError( 

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

467 "instance. Specify 'extend_existing=True' " 

468 "to redefine " 

469 "options and columns on an " 

470 "existing Table object." 

471 ) 

472 table = metadata.tables[key] 

473 if extend_existing: 

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

475 return table 

476 else: 

477 if must_exist: 

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

479 table = object.__new__(cls) 

480 table.dispatch.before_parent_attach(table, metadata) 

481 metadata._add_table(name, schema, table) 

482 try: 

483 table.__init__(name, metadata, *args, _no_init=False, **kw) # type: ignore[misc] # noqa: E501 

484 table.dispatch.after_parent_attach(table, metadata) 

485 return table 

486 except Exception: 

487 with util.safe_reraise(): 

488 metadata._remove_table(name, schema) 

489 

490 def __init__( 

491 self, 

492 name: str, 

493 metadata: MetaData, 

494 *args: SchemaItem, 

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

496 quote: Optional[bool] = None, 

497 quote_schema: Optional[bool] = None, 

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

499 autoload_replace: bool = True, 

500 keep_existing: bool = False, 

501 extend_existing: bool = False, 

502 resolve_fks: bool = True, 

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

504 implicit_returning: bool = True, 

505 comment: Optional[str] = None, 

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

507 listeners: Optional[ 

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

509 ] = None, 

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

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

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

513 # used by __new__ to bypass __init__ 

514 _no_init: bool = True, 

515 # dialect-specific keyword args 

516 **kw: Any, 

517 ) -> None: 

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

519 

520 

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

522 

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

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

525 within 

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

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

528 metadata, 

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

530 

531 Names which contain no upper case characters 

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

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

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

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

536 

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

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

539 construct to specify the name. 

540 

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

542 object which will contain this 

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

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

545 may be used to associate this table with a particular 

546 :class:`.Connection` or :class:`.Engine`. 

547 

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

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

550 objects contained within this 

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

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

553 :class:`.PrimaryKeyConstraint`, and 

554 :class:`_schema.ForeignKeyConstraint`. 

555 

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

557 :paramref:`_schema.Table.autoload_with` 

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

559 indicates 

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

561 :class:`_schema.Table` 

562 object should be replaced with columns of the same 

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

564 already present under existing names will be omitted from the 

565 reflection process. 

566 

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

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

569 that 

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

571 replace existing columns of the same name when 

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

573 

574 .. seealso:: 

575 

576 :paramref:`_schema.Table.autoload_with` 

577 

578 :paramref:`_schema.Table.extend_existing` 

579 

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

581 :class:`_engine.Connection` object, 

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

583 :func:`_sa.inspect` 

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

585 object will be reflected. 

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

587 for this table against the given engine or connection. 

588 

589 .. seealso:: 

590 

591 :ref:`metadata_reflection_toplevel` 

592 

593 :meth:`_events.DDLEvents.column_reflect` 

594 

595 :ref:`metadata_reflection_dbagnostic_types` 

596 

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

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

599 :class:`_schema.MetaData`, 

600 apply further arguments within the constructor to the existing 

601 :class:`_schema.Table`. 

602 

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

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

605 and the given name 

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

607 that is 

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

609 and 

610 this :class:`_schema.Table` 

611 specifies additional columns or other constructs 

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

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

614 is to specify what action should be taken when a 

615 :class:`_schema.Table` 

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

617 yet specifies 

618 additional constructs. 

619 

620 :paramref:`_schema.Table.extend_existing` 

621 will also work in conjunction 

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

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

624 of the same name is already present in the target 

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

626 objects 

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

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

629 and options of the same name. 

630 

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

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

633 :class:`_schema.Table` 

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

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

636 objects 

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

638 :class:`_schema.Column` 

639 named "y":: 

640 

641 Table( 

642 "mytable", 

643 metadata, 

644 Column("y", Integer), 

645 extend_existing=True, 

646 autoload_with=engine, 

647 ) 

648 

649 .. seealso:: 

650 

651 :paramref:`_schema.Table.autoload_with` 

652 

653 :paramref:`_schema.Table.autoload_replace` 

654 

655 :paramref:`_schema.Table.keep_existing` 

656 

657 

658 :param implicit_returning: True by default - indicates that 

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

660 server-generated values such as primary key values and 

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

662 

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

664 setting, except for some backend specific cases 

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

666 for one such example). 

667 

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

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

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

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

672 should be reflected. 

673 

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

675 objects 

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

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

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

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

680 objects are encountered; may be 

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

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

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

684 a 

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

686 :class:`_schema.Table` will 

687 resolve to that table normally. 

688 

689 .. seealso:: 

690 

691 :paramref:`.MetaData.reflect.resolve_fks` 

692 

693 

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

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

696 

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

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

699 further arguments within the constructor to the existing 

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

701 object as 

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

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

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

705 without any of the declarations (particularly constraints) 

706 being applied a second time. 

707 

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

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

710 and the given name 

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

712 that is 

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

714 and 

715 this :class:`_schema.Table` 

716 specifies additional columns or other constructs 

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

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

719 is to specify what action should be taken when a 

720 :class:`_schema.Table` 

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

722 yet specifies 

723 additional constructs. 

724 

725 .. seealso:: 

726 

727 :paramref:`_schema.Table.extend_existing` 

728 

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

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

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

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

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

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

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

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

737 

738 def listen_for_reflect(table, column_info): 

739 "handle the column reflection event" 

740 # ... 

741 

742 

743 t = Table( 

744 "sometable", 

745 autoload_with=engine, 

746 listeners=[("column_reflect", listen_for_reflect)], 

747 ) 

748 

749 .. seealso:: 

750 

751 :meth:`_events.DDLEvents.column_reflect` 

752 

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

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

755 an exception is raised. 

756 

757 :param prefixes: 

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

759 statement. They will be separated by spaces. 

760 

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

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

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

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

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

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

767 by the SQLAlchemy dialect. 

768 

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

770 case-insensitive behavior for table reflection; table reflection 

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

772 fashion. Case insensitive names are specified in SQLAlchemy only 

773 by stating the name with all lower case characters. 

774 

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

776 

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

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

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

780 

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

782 specifies its 

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

784 then that schema name will 

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

786 if the schema parameter here is set 

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

788 that 

789 would otherwise use the schema set on the owning 

790 :class:`_schema.MetaData`, 

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

792 

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

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

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

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

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

798 

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

800 creation. 

801 

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

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

804 See the documentation regarding an individual dialect at 

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

806 

807 """ # noqa: E501 

808 if _no_init: 

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

810 # __new__ has a specific place that __init__ is called 

811 return 

812 

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

814 self.metadata = metadata 

815 

816 if schema is None: 

817 self.schema = metadata.schema 

818 elif schema is BLANK_SCHEMA: 

819 self.schema = None 

820 else: 

821 quote_schema = quote_schema 

822 assert isinstance(schema, str) 

823 self.schema = quoted_name(schema, quote_schema) 

824 

825 self._sentinel_column = None 

826 

827 self.indexes = set() 

828 self.constraints = set() 

829 PrimaryKeyConstraint( 

830 _implicit_generated=True 

831 )._set_parent_with_dispatch(self) 

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

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

834 if self.schema is not None: 

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

836 else: 

837 self.fullname = self.name 

838 

839 self.implicit_returning = implicit_returning 

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

841 

842 self.comment = comment 

843 

844 if info is not None: 

845 self.info = info 

846 

847 if listeners is not None: 

848 for evt, fn in listeners: 

849 event.listen(self, evt, fn) 

850 

851 self._prefixes = prefixes if prefixes else [] 

852 

853 self._extra_kwargs(**kw) 

854 

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

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

857 # circular foreign keys 

858 if autoload_with is not None: 

859 self._autoload( 

860 metadata, 

861 autoload_with, 

862 include_columns, 

863 _extend_on=_extend_on, 

864 _reflect_info=_reflect_info, 

865 resolve_fks=resolve_fks, 

866 ) 

867 

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

869 # allow user-overrides 

870 

871 self._init_items( 

872 *args, 

873 allow_replacements=extend_existing 

874 or keep_existing 

875 or autoload_with, 

876 all_names={}, 

877 ) 

878 

879 def _autoload( 

880 self, 

881 metadata: MetaData, 

882 autoload_with: Union[Engine, Connection], 

883 include_columns: Optional[Collection[str]], 

884 exclude_columns: Collection[str] = (), 

885 resolve_fks: bool = True, 

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

887 _reflect_info: _ReflectionInfo | None = None, 

888 ) -> None: 

889 insp = inspection.inspect(autoload_with) 

890 with insp._inspection_context() as conn_insp: 

891 conn_insp.reflect_table( 

892 self, 

893 include_columns, 

894 exclude_columns, 

895 resolve_fks, 

896 _extend_on=_extend_on, 

897 _reflect_info=_reflect_info, 

898 ) 

899 

900 @property 

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

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

903 order. 

904 

905 """ 

906 

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

908 

909 @property 

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

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

912 :class:`_schema.Table`. 

913 

914 This list is produced from the collection of 

915 :class:`_schema.ForeignKey` 

916 objects currently associated. 

917 

918 

919 .. seealso:: 

920 

921 :attr:`_schema.Table.constraints` 

922 

923 :attr:`_schema.Table.foreign_keys` 

924 

925 :attr:`_schema.Table.indexes` 

926 

927 """ 

928 return { 

929 fkc.constraint 

930 for fkc in self.foreign_keys 

931 if fkc.constraint is not None 

932 } 

933 

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

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

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

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

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

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

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

941 

942 # these arguments are only used with _init() 

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

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

945 

946 assert extend_existing 

947 assert not keep_existing 

948 

949 if schema and schema != self.schema: 

950 raise exc.ArgumentError( 

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

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

953 ) 

954 

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

956 if include_columns is not None: 

957 for c in self.c: 

958 if c.name not in include_columns: 

959 self._columns.remove(c) 

960 

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

962 

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

964 if key in kwargs: 

965 raise exc.ArgumentError( 

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

967 ) 

968 

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

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

971 self.implicit_returning = kwargs.pop( 

972 "implicit_returning", self.implicit_returning 

973 ) 

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

975 

976 exclude_columns: _typing_Sequence[str] 

977 

978 if autoload: 

979 if not autoload_replace: 

980 # don't replace columns already present. 

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

982 # have simple de-duping for unnamed constraints. 

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

984 else: 

985 exclude_columns = () 

986 self._autoload( 

987 self.metadata, 

988 autoload_with, 

989 include_columns, 

990 exclude_columns, 

991 resolve_fks, 

992 _extend_on=_extend_on, 

993 _reflect_info=_reflect_info, 

994 ) 

995 

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

997 self._extra_kwargs(**kwargs) 

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

999 

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

1001 self._validate_dialect_kwargs(kwargs) 

1002 

1003 def _init_collections(self) -> None: 

1004 pass 

1005 

1006 def _reset_exported(self) -> None: 

1007 pass 

1008 

1009 @util.ro_non_memoized_property 

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

1011 return self.primary_key._autoincrement_column 

1012 

1013 @util.ro_memoized_property 

1014 def _sentinel_column_characteristics( 

1015 self, 

1016 ) -> _SentinelColumnCharacterization: 

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

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

1019 "insert sentinel" for an INSERT statement. 

1020 

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

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

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

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

1025 dialect. 

1026 

1027 .. versionadded:: 2.0.10 

1028 

1029 """ 

1030 

1031 sentinel_is_explicit = False 

1032 sentinel_is_autoinc = False 

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

1034 

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

1036 explicit_sentinel_col = self._sentinel_column 

1037 

1038 if explicit_sentinel_col is not None: 

1039 the_sentinel = (explicit_sentinel_col,) 

1040 sentinel_is_explicit = True 

1041 

1042 autoinc_col = self._autoincrement_column 

1043 if sentinel_is_explicit and explicit_sentinel_col is autoinc_col: 

1044 assert autoinc_col is not None 

1045 sentinel_is_autoinc = True 

1046 elif explicit_sentinel_col is None and autoinc_col is not None: 

1047 the_sentinel = (autoinc_col,) 

1048 sentinel_is_autoinc = True 

1049 

1050 default_characterization = _SentinelDefaultCharacterization.UNKNOWN 

1051 

1052 if the_sentinel: 

1053 the_sentinel_zero = the_sentinel[0] 

1054 if the_sentinel_zero.identity: 

1055 if the_sentinel_zero.identity._increment_is_negative: 

1056 if sentinel_is_explicit: 

1057 raise exc.InvalidRequestError( 

1058 "Can't use IDENTITY default with negative " 

1059 "increment as an explicit sentinel column" 

1060 ) 

1061 else: 

1062 if sentinel_is_autoinc: 

1063 autoinc_col = None 

1064 sentinel_is_autoinc = False 

1065 the_sentinel = None 

1066 else: 

1067 default_characterization = ( 

1068 _SentinelDefaultCharacterization.IDENTITY 

1069 ) 

1070 elif ( 

1071 the_sentinel_zero.default is None 

1072 and the_sentinel_zero.server_default is None 

1073 ): 

1074 if the_sentinel_zero.nullable: 

1075 raise exc.InvalidRequestError( 

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

1077 "sentinel " 

1078 "column with no default generation function; it " 

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

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

1081 ) 

1082 default_characterization = ( 

1083 _SentinelDefaultCharacterization.NONE 

1084 ) 

1085 elif the_sentinel_zero.default is not None: 

1086 if the_sentinel_zero.default.is_sentinel: 

1087 default_characterization = ( 

1088 _SentinelDefaultCharacterization.SENTINEL_DEFAULT 

1089 ) 

1090 elif default_is_sequence(the_sentinel_zero.default): 

1091 if the_sentinel_zero.default._increment_is_negative: 

1092 if sentinel_is_explicit: 

1093 raise exc.InvalidRequestError( 

1094 "Can't use SEQUENCE default with negative " 

1095 "increment as an explicit sentinel column" 

1096 ) 

1097 else: 

1098 if sentinel_is_autoinc: 

1099 autoinc_col = None 

1100 sentinel_is_autoinc = False 

1101 the_sentinel = None 

1102 

1103 default_characterization = ( 

1104 _SentinelDefaultCharacterization.SEQUENCE 

1105 ) 

1106 elif the_sentinel_zero.default.is_callable: 

1107 default_characterization = ( 

1108 _SentinelDefaultCharacterization.CLIENTSIDE 

1109 ) 

1110 elif the_sentinel_zero.server_default is not None: 

1111 if sentinel_is_explicit: 

1112 raise exc.InvalidRequestError( 

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

1114 "because it uses an explicit server side default " 

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

1116 ) 

1117 

1118 default_characterization = ( 

1119 _SentinelDefaultCharacterization.SERVERSIDE 

1120 ) 

1121 

1122 if the_sentinel is None and self.primary_key: 

1123 assert autoinc_col is None 

1124 

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

1126 # client side 

1127 for _pkc in self.primary_key: 

1128 if _pkc.server_default is not None or ( 

1129 _pkc.default and not _pkc.default.is_callable 

1130 ): 

1131 break 

1132 else: 

1133 the_sentinel = tuple(self.primary_key) 

1134 default_characterization = ( 

1135 _SentinelDefaultCharacterization.CLIENTSIDE 

1136 ) 

1137 

1138 return _SentinelColumnCharacterization( 

1139 the_sentinel, 

1140 sentinel_is_explicit, 

1141 sentinel_is_autoinc, 

1142 default_characterization, 

1143 ) 

1144 

1145 @property 

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

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

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

1149 

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

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

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

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

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

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

1156 "autoincrement" column. 

1157 

1158 .. versionadded:: 2.0.4 

1159 

1160 .. seealso:: 

1161 

1162 :paramref:`.Column.autoincrement` 

1163 

1164 """ 

1165 return self._autoincrement_column 

1166 

1167 @property 

1168 def key(self) -> str: 

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

1170 

1171 This value is used as the dictionary key within the 

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

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

1174 :attr:`_schema.Table.schema` 

1175 set; otherwise it is typically of the form 

1176 ``schemaname.tablename``. 

1177 

1178 """ 

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

1180 

1181 def __repr__(self) -> str: 

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

1183 [repr(self.name)] 

1184 + [repr(self.metadata)] 

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

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

1187 ) 

1188 

1189 def __str__(self) -> str: 

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

1191 

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

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

1194 

1195 This is another Table object which must be created 

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

1197 

1198 Usually, dependencies between tables are determined via 

1199 ForeignKey objects. However, for other situations that 

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

1201 this method can manually establish such a link. 

1202 

1203 """ 

1204 self._extra_dependencies.add(table) 

1205 

1206 def _insert_col_impl( 

1207 self, 

1208 column: ColumnClause[Any], 

1209 *, 

1210 index: Optional[int] = None, 

1211 replace_existing: bool = False, 

1212 ) -> None: 

1213 try: 

1214 column._set_parent_with_dispatch( 

1215 self, 

1216 allow_replacements=replace_existing, 

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

1218 index=index, 

1219 ) 

1220 except exc.DuplicateColumnError as de: 

1221 raise exc.DuplicateColumnError( 

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

1223 "Table.append_column() or Table.insert_column() to replace an " 

1224 "existing column." 

1225 ) from de 

1226 

1227 def insert_column( 

1228 self, 

1229 column: ColumnClause[Any], 

1230 index: int, 

1231 *, 

1232 replace_existing: bool = False, 

1233 ) -> None: 

1234 """Insert a :class:`_schema.Column` to this :class:`_schema.Table` at 

1235 a specific position. 

1236 

1237 Behavior is identical to :meth:`.Table.append_column` except that 

1238 the index position can be controlled using the 

1239 :paramref:`.Table.insert_column.index` 

1240 parameter. 

1241 

1242 :param replace_existing: 

1243 see :paramref:`.Table.append_column.replace_existing` 

1244 :param index: integer index to insert the new column. 

1245 

1246 .. versionadded:: 2.1 

1247 

1248 """ 

1249 self._insert_col_impl( 

1250 column, index=index, replace_existing=replace_existing 

1251 ) 

1252 

1253 def append_column( 

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

1255 ) -> None: 

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

1257 

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

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

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

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

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

1263 construct. 

1264 

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

1266 as it exists within any underlying database, assuming that 

1267 table has already been created in the database. Relational 

1268 databases support the addition of columns to existing tables 

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

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

1271 the newly added column. 

1272 

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

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

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

1276 version of sqlalchemy will instead rise a warning. 

1277 

1278 .. versionadded:: 1.4.0 

1279 

1280 .. seealso:: 

1281 

1282 :meth:`.Table.insert_column` 

1283 

1284 """ 

1285 self._insert_col_impl(column, replace_existing=replace_existing) 

1286 

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

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

1289 :class:`_schema.Table`. 

1290 

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

1292 future CREATE TABLE statement, assuming specific DDL creation 

1293 events have not been associated with the given 

1294 :class:`_schema.Constraint` object. 

1295 

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

1297 relational database automatically, for a table that already exists 

1298 in the database. To add a constraint to an 

1299 existing relational database table, the SQL ALTER command must 

1300 be used. SQLAlchemy also provides the 

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

1302 invoked as an executable clause. 

1303 

1304 """ 

1305 

1306 constraint._set_parent_with_dispatch(self) 

1307 

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

1309 metadata = parent 

1310 assert isinstance(metadata, MetaData) 

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

1312 self.metadata = metadata 

1313 

1314 def create( 

1315 self, 

1316 bind: _CreateDropBind, 

1317 checkfirst: Union[bool, CheckFirst] = CheckFirst.TYPES, 

1318 ) -> None: 

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

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

1321 :class:`.Connection` or :class:`.Engine` 

1322 for connectivity. 

1323 

1324 .. seealso:: 

1325 

1326 :meth:`_schema.MetaData.create_all`. 

1327 

1328 """ 

1329 

1330 # the default is to only check for schema objects 

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

1332 

1333 def drop( 

1334 self, 

1335 bind: _CreateDropBind, 

1336 checkfirst: Union[bool, CheckFirst] = CheckFirst.NONE, 

1337 ) -> None: 

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

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

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

1341 

1342 .. seealso:: 

1343 

1344 :meth:`_schema.MetaData.drop_all`. 

1345 

1346 """ 

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

1348 

1349 @util.deprecated( 

1350 "1.4", 

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

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

1353 ) 

1354 def tometadata( 

1355 self, 

1356 metadata: MetaData, 

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

1358 referred_schema_fn: Optional[ 

1359 Callable[ 

1360 [Table, Optional[str], ForeignKeyConstraint, Optional[str]], 

1361 Optional[str], 

1362 ] 

1363 ] = None, 

1364 name: Optional[str] = None, 

1365 ) -> Table: 

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

1367 associated with a different 

1368 :class:`_schema.MetaData`. 

1369 

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

1371 

1372 """ 

1373 return self.to_metadata( 

1374 metadata, 

1375 schema=schema, 

1376 referred_schema_fn=referred_schema_fn, 

1377 name=name, 

1378 ) 

1379 

1380 def to_metadata( 

1381 self, 

1382 metadata: MetaData, 

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

1384 referred_schema_fn: Optional[ 

1385 Callable[ 

1386 [Table, Optional[str], ForeignKeyConstraint, Optional[str]], 

1387 Optional[str], 

1388 ] 

1389 ] = None, 

1390 name: Optional[str] = None, 

1391 ) -> Table: 

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

1393 different :class:`_schema.MetaData`. 

1394 

1395 E.g.:: 

1396 

1397 m1 = MetaData() 

1398 

1399 user = Table("user", m1, Column("id", Integer, primary_key=True)) 

1400 

1401 m2 = MetaData() 

1402 user_copy = user.to_metadata(m2) 

1403 

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

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

1406 

1407 

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

1409 into which the 

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

1411 

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

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

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

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

1416 :class:`_schema.Table` 

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

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

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

1420 unless 

1421 set explicitly:: 

1422 

1423 m2 = MetaData(schema="newschema") 

1424 

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

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

1427 

1428 m3 = MetaData() # schema defaults to None 

1429 

1430 # user_copy_two will have None as the schema name 

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

1432 

1433 :param referred_schema_fn: optional callable which can be supplied 

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

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

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

1437 target schema that we are changing to, the 

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

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

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

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

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

1443 

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

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

1446 symbols. 

1447 

1448 E.g.:: 

1449 

1450 def referred_schema_fn(table, to_schema, constraint, referred_schema): 

1451 if referred_schema == "base_tables": 

1452 return referred_schema 

1453 else: 

1454 return to_schema 

1455 

1456 

1457 new_table = table.to_metadata( 

1458 m2, schema="alt_schema", referred_schema_fn=referred_schema_fn 

1459 ) 

1460 

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

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

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

1464 :class:`_schema.MetaData` target 

1465 with a new name. 

1466 

1467 """ # noqa: E501 

1468 if name is None: 

1469 name = self.name 

1470 

1471 actual_schema: Optional[str] 

1472 

1473 if schema is RETAIN_SCHEMA: 

1474 actual_schema = self.schema 

1475 elif schema is None: 

1476 actual_schema = metadata.schema 

1477 else: 

1478 actual_schema = schema 

1479 key = _get_table_key(name, actual_schema) 

1480 if key in metadata.tables: 

1481 util.warn( 

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

1483 "MetaData - not copying." 

1484 ) 

1485 return metadata.tables[key] 

1486 

1487 args = [] 

1488 for col in self.columns: 

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

1490 table = Table( 

1491 name, 

1492 metadata, 

1493 schema=actual_schema, 

1494 comment=self.comment, 

1495 *args, 

1496 **self.kwargs, 

1497 ) 

1498 for const in self.constraints: 

1499 if isinstance(const, ForeignKeyConstraint): 

1500 referred_schema = const._referred_schema 

1501 if referred_schema_fn: 

1502 fk_constraint_schema = referred_schema_fn( 

1503 self, actual_schema, const, referred_schema 

1504 ) 

1505 else: 

1506 fk_constraint_schema = ( 

1507 actual_schema 

1508 if referred_schema == self.schema 

1509 else None 

1510 ) 

1511 table.append_constraint( 

1512 const._copy( 

1513 schema=fk_constraint_schema, target_table=table 

1514 ) 

1515 ) 

1516 elif not const._type_bound: 

1517 # skip unique constraints that would be generated 

1518 # by the 'unique' flag on Column 

1519 if const._column_flag: 

1520 continue 

1521 

1522 table.append_constraint( 

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

1524 ) 

1525 for index in self.indexes: 

1526 # skip indexes that would be generated 

1527 # by the 'index' flag on Column 

1528 if index._column_flag: 

1529 continue 

1530 Index( 

1531 index.name, 

1532 unique=index.unique, 

1533 *[ 

1534 _copy_expression(expr, self, table) 

1535 for expr in index._table_bound_expressions 

1536 ], 

1537 _table=table, 

1538 **index.kwargs, 

1539 ) 

1540 return self._schema_item_copy(table) 

1541 

1542 

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

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

1545 

1546 __visit_name__ = "column" 

1547 

1548 inherit_cache = True 

1549 key: str 

1550 

1551 server_default: Optional[FetchedValue] 

1552 

1553 def __init__( 

1554 self, 

1555 __name_pos: Optional[ 

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

1557 ] = None, 

1558 __type_pos: Optional[ 

1559 Union[_TypeEngineArgument[_T], SchemaEventTarget] 

1560 ] = None, 

1561 /, 

1562 *args: SchemaEventTarget, 

1563 name: Optional[str] = None, 

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

1565 autoincrement: _AutoIncrementType = "auto", 

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

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

1568 doc: Optional[str] = None, 

1569 key: Optional[str] = None, 

1570 index: Optional[bool] = None, 

1571 unique: Optional[bool] = None, 

1572 info: Optional[_InfoType] = None, 

1573 nullable: Optional[ 

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

1575 ] = SchemaConst.NULL_UNSPECIFIED, 

1576 onupdate: Optional[Any] = None, 

1577 primary_key: bool = False, 

1578 server_default: Optional[_ServerDefaultArgument] = None, 

1579 server_onupdate: Optional[_ServerOnUpdateArgument] = None, 

1580 quote: Optional[bool] = None, 

1581 system: bool = False, 

1582 comment: Optional[str] = None, 

1583 insert_sentinel: bool = False, 

1584 _omit_from_statements: bool = False, 

1585 _proxies: Optional[Any] = None, 

1586 **dialect_kwargs: Any, 

1587 ): 

1588 r""" 

1589 Construct a new ``Column`` object. 

1590 

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

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

1593 via keyword. 

1594 

1595 Names which contain no upper case characters 

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

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

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

1599 behavior applies even for databases which standardize upper 

1600 case names as case insensitive such as Oracle Database. 

1601 

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

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

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

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

1606 

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

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

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

1610 as well, e.g.:: 

1611 

1612 # use a type with arguments 

1613 Column("data", String(50)) 

1614 

1615 # use no arguments 

1616 Column("level", Integer) 

1617 

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

1619 or specified by keyword. 

1620 

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

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

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

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

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

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

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

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

1629 

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

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

1632 as options to the column. These include instances of 

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

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

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

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

1637 ``default`` and ``unique``. 

1638 

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

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

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

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

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

1644 will be considered when INSERT statements are compiled and 

1645 executed. 

1646 

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

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

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

1650 default constructs indicated should receive auto increment semantics 

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

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

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

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

1655 key columns, see below). 

1656 

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

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

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

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

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

1662 database: 

1663 

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

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

1666 no other 

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

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

1669 will imply that database-specific keywords such as PostgreSQL 

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

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

1672 "implied" default generator available; for example the Oracle Database 

1673 backends alway needs an explicit construct such as 

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

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

1676 be produced in the database. 

1677 

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

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

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

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

1682 value automatically for this column, which will be accessible 

1683 after the statement is invoked via the 

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

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

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

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

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

1689 behavior takes place regardless of what DDL constructs are 

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

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

1692 above. 

1693 

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

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

1696 have autoincrement semantics, though note that only one column 

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

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

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

1700 however note that not all dialects can accommodate all styles 

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

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

1703 datatype of INTEGER in order to disable auto increment semantics 

1704 for that column. 

1705 

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

1707 

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

1709 

1710 * Part of the primary key 

1711 

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

1713 unless 

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

1715 

1716 # turn on autoincrement for this column despite 

1717 # the ForeignKey() 

1718 Column( 

1719 "id", 

1720 ForeignKey("other.id"), 

1721 primary_key=True, 

1722 autoincrement="ignore_fk", 

1723 ) 

1724 

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

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

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

1728 

1729 The setting has these effects on columns that meet the 

1730 above criteria: 

1731 

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

1733 a default generating construct supported by the backend such as 

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

1735 keywords intended to signify this column as an 

1736 "autoincrement" column for specific backends. Behavior for 

1737 primary SQLAlchemy dialects includes: 

1738 

1739 * AUTO INCREMENT on MySQL and MariaDB 

1740 * SERIAL on PostgreSQL 

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

1742 :class:`.Identity` construct as the 

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

1744 construct. 

1745 * SQLite - SQLite integer primary key columns are implicitly 

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

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

1748 is not included as this is unnecessary and not recommended 

1749 by the database vendor. See the section 

1750 :ref:`sqlite_autoincrement` for more background. 

1751 * Oracle Database - The Oracle Database dialects have no default "autoincrement" 

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

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

1754 construct may also be used). 

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

1756 for details on their specific behaviors. 

1757 

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

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

1760 modifier, newly generated primary key values for this column 

1761 will be automatically retrieved upon statement execution 

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

1763 

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

1765 (see 

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

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

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

1769 construct when rendering an INSERT statement, and then retrieving 

1770 the newly generated primary key values after execution 

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

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

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

1774 explicitly before the INSERT statement takes place so that the 

1775 newly generated primary key value is available to the client 

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

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

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

1779 INSERT statement is invoked to retrieve the newly generated 

1780 primary key value. 

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

1782 for details on their specific behaviors. 

1783 

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

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

1786 retrieving behaviors are generally disabled, however there may 

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

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

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

1790 may not yet be well covered in documentation. 

1791 

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

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

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

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

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

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

1798 structure of the argument. 

1799 

1800 Contrast this argument to 

1801 :paramref:`_schema.Column.server_default` 

1802 which creates a default generator on the database side. 

1803 

1804 .. seealso:: 

1805 

1806 :ref:`metadata_defaults_toplevel` 

1807 

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

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

1810 

1811 .. versionadded:: 2.0.31 

1812 

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

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

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

1816 :paramref:`_schema.Column.comment` 

1817 parameter for this purpose. 

1818 

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

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

1821 When a key is provided, 

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

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

1824 is used only when rendering SQL. 

1825 

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

1827 construct will be automatically generated for this 

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

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

1830 create operation is invoked. 

1831 

1832 Using this flag is equivalent to making use of the 

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

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

1835 

1836 Table( 

1837 "some_table", 

1838 metadata, 

1839 Column("x", Integer), 

1840 Index("ix_some_table_x", "x"), 

1841 ) 

1842 

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

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

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

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

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

1848 DDL instruction instead of "CREATE INDEX". 

1849 

1850 The name of the index is generated using the 

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

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

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

1854 

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

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

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

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

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

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

1861 indexes that use a specific name. 

1862 

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

1864 :class:`_schema.Column` 

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

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

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

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

1869 

1870 .. seealso:: 

1871 

1872 :ref:`schema_indexes` 

1873 

1874 :ref:`constraint_naming_conventions` 

1875 

1876 :paramref:`_schema.Column.unique` 

1877 

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

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

1880 

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

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

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

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

1885 where "NULL" may render explicitly. 

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

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

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

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

1890 

1891 .. note:: 

1892 

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

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

1895 PostgreSQL database allows nullable identity column by 

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

1897 

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

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

1900 default value to be applied to the column within UPDATE 

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

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

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

1904 ``for_update=True``. 

1905 

1906 .. seealso:: 

1907 

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

1909 

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

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

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

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

1914 :class:`.PrimaryKeyConstraint` object. 

1915 

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

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

1918 the DDL DEFAULT value for the column. 

1919 

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

1921 

1922 Column("x", Text, server_default="val") 

1923 

1924 will render: 

1925 

1926 .. sourcecode:: sql 

1927 

1928 x TEXT DEFAULT 'val' 

1929 

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

1931 rendered as-is, without quotes:: 

1932 

1933 Column("y", DateTime, server_default=text("NOW()")) 

1934 

1935 will render: 

1936 

1937 .. sourcecode:: sql 

1938 

1939 y DATETIME DEFAULT NOW() 

1940 

1941 Strings and text() will be converted into a 

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

1943 

1944 This parameter can also accept complex combinations of contextually 

1945 valid SQLAlchemy expressions or constructs:: 

1946 

1947 from sqlalchemy import create_engine 

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

1949 from sqlalchemy.dialects.postgresql import array 

1950 

1951 engine = create_engine( 

1952 "postgresql+psycopg2://scott:tiger@localhost/mydatabase" 

1953 ) 

1954 metadata_obj = MetaData() 

1955 tbl = Table( 

1956 "foo", 

1957 metadata_obj, 

1958 Column( 

1959 "bar", ARRAY(Text), server_default=array(["biz", "bang", "bash"]) 

1960 ), 

1961 ) 

1962 metadata_obj.create_all(engine) 

1963 

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

1965 

1966 .. sourcecode:: sql 

1967 

1968 CREATE TABLE foo ( 

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

1970 ) 

1971 

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

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

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

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

1976 to the database, such as via a trigger. 

1977 

1978 .. seealso:: 

1979 

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

1981 defaults 

1982 

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

1984 representing a database-side default generation function, 

1985 such as a trigger. This 

1986 indicates to SQLAlchemy that a newly generated value will be 

1987 available after updates. This construct does not actually 

1988 implement any kind of generation function within the database, 

1989 which instead must be specified separately. 

1990 

1991 

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

1993 "ON UPDATE CURRENT_TIMESTAMP()" clause. See 

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

1995 produce this clause. 

1996 

1997 .. seealso:: 

1998 

1999 :ref:`triggered_columns` 

2000 

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

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

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

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

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

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

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

2008 

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

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

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

2012 construct will be automatically generated for this 

2013 :class:`_schema.Column`, 

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

2015 to this column being included 

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

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

2018 

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

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

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

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

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

2024 is generated. See the documentation for 

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

2026 

2027 Using this flag is equivalent to making use of the 

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

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

2030 

2031 Table("some_table", metadata, Column("x", Integer), UniqueConstraint("x")) 

2032 

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

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

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

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

2037 construct will be emitted as unnamed, which typically invokes 

2038 a database-specific naming convention to take place. 

2039 

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

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

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

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

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

2045 constraints that use a specific name. 

2046 

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

2048 :class:`_schema.Column` 

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

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

2051 indexes and unique constraints that may involve this column, 

2052 view the 

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

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

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

2056 :meth:`_reflection.Inspector.get_unique_constraints` 

2057 

2058 .. seealso:: 

2059 

2060 :ref:`schema_unique_constraint` 

2061 

2062 :ref:`constraint_naming_conventions` 

2063 

2064 :paramref:`_schema.Column.index` 

2065 

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

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

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

2069 ``CREATE TABLE`` statement. 

2070 

2071 For more elaborate scenarios where columns should be 

2072 conditionally rendered differently on different backends, 

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

2074 

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

2076 table creation. 

2077 

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

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

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

2081 otherwise have qualifying primary key configurations. 

2082 

2083 .. versionadded:: 2.0.10 

2084 

2085 .. seealso:: 

2086 

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

2088 sentinel columns 

2089 

2090 :ref:`engine_insertmanyvalues` 

2091 

2092 :ref:`engine_insertmanyvalues_sentinel_columns` 

2093 

2094 

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

2096 

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

2098 del args 

2099 

2100 if l_args: 

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

2102 if name is not None: 

2103 raise exc.ArgumentError( 

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

2105 ) 

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

2107 elif l_args[0] is None: 

2108 l_args.pop(0) 

2109 if l_args: 

2110 coltype = l_args[0] 

2111 

2112 if hasattr(coltype, "_sqla_type"): 

2113 if type_ is not None: 

2114 raise exc.ArgumentError( 

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

2116 ) 

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

2118 elif l_args[0] is None: 

2119 l_args.pop(0) 

2120 

2121 if name is not None: 

2122 name = quoted_name(name, quote) 

2123 elif quote is not None: 

2124 raise exc.ArgumentError( 

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

2126 ) 

2127 

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

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

2130 # dedicated "column" construct local to the ORM 

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

2132 

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

2134 self.primary_key = primary_key 

2135 self._insert_sentinel = insert_sentinel 

2136 self._omit_from_statements = _omit_from_statements 

2137 self._user_defined_nullable = udn = nullable 

2138 if udn is not NULL_UNSPECIFIED: 

2139 self.nullable = udn 

2140 else: 

2141 self.nullable = not primary_key 

2142 

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

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

2145 # Index or UniqueConstraint referring to this Column. 

2146 self.index = index 

2147 self.unique = unique 

2148 

2149 self.system = system 

2150 self.doc = doc 

2151 self.autoincrement: _AutoIncrementType = autoincrement 

2152 self.constraints = set() 

2153 self.foreign_keys = set() 

2154 self.comment = comment 

2155 self.computed = None 

2156 self.identity = None 

2157 

2158 # check if this Column is proxying another column 

2159 

2160 if _proxies is not None: 

2161 self._proxies = _proxies 

2162 else: 

2163 # otherwise, add DDL-related events 

2164 self._set_type(self.type) 

2165 

2166 if insert_default is not _NoArg.NO_ARG: 

2167 if default is not _NoArg.NO_ARG: 

2168 raise exc.ArgumentError( 

2169 "The 'default' and 'insert_default' parameters " 

2170 "of Column are mutually exclusive" 

2171 ) 

2172 resolved_default = insert_default 

2173 elif default is not _NoArg.NO_ARG: 

2174 resolved_default = default 

2175 else: 

2176 resolved_default = None 

2177 

2178 if resolved_default is not None: 

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

2180 resolved_default = ColumnDefault(resolved_default) 

2181 

2182 self.default = resolved_default 

2183 l_args.append(resolved_default) 

2184 else: 

2185 self.default = None 

2186 

2187 if onupdate is not None: 

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

2189 onupdate = ColumnDefault(onupdate, for_update=True) 

2190 

2191 self.onupdate = onupdate 

2192 l_args.append(onupdate) 

2193 else: 

2194 self.onupdate = None 

2195 

2196 if server_default is not None: 

2197 if isinstance(server_default, FetchedValue): 

2198 server_default = server_default._as_for_update(False) 

2199 l_args.append(server_default) 

2200 else: 

2201 server_default = DefaultClause(server_default) 

2202 l_args.append(server_default) 

2203 self.server_default = server_default 

2204 

2205 if server_onupdate is not None: 

2206 if isinstance(server_onupdate, FetchedValue): 

2207 server_onupdate = server_onupdate._as_for_update(True) 

2208 l_args.append(server_onupdate) 

2209 else: 

2210 server_onupdate = DefaultClause( 

2211 server_onupdate, for_update=True 

2212 ) 

2213 l_args.append(server_onupdate) 

2214 self.server_onupdate = server_onupdate 

2215 

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

2217 

2218 util.set_creation_order(self) 

2219 

2220 if info is not None: 

2221 self.info = info 

2222 

2223 self._extra_kwargs(**dialect_kwargs) 

2224 

2225 table: Table 

2226 

2227 constraints: Set[Constraint] 

2228 

2229 foreign_keys: Set[ForeignKey] 

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

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

2232 

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

2234 :class:`_schema.ForeignKeyConstraint`. 

2235 

2236 .. seealso:: 

2237 

2238 :attr:`_schema.Table.foreign_keys` 

2239 

2240 """ 

2241 

2242 index: Optional[bool] 

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

2244 

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

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

2247 

2248 .. seealso:: 

2249 

2250 :attr:`_schema.Table.indexes` 

2251 """ 

2252 

2253 unique: Optional[bool] 

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

2255 

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

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

2258 :attr:`_schema.Table.constraints`. 

2259 

2260 .. seealso:: 

2261 

2262 :attr:`_schema.Table.indexes` 

2263 

2264 :attr:`_schema.Table.constraints`. 

2265 

2266 """ 

2267 

2268 computed: Optional[Computed] 

2269 

2270 identity: Optional[Identity] 

2271 

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

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

2274 

2275 self.type = type_ 

2276 if isinstance(self.type, SchemaEventTarget): 

2277 self.type._set_parent_with_dispatch(self) 

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

2279 if isinstance(impl, SchemaEventTarget): 

2280 impl._set_parent_with_dispatch(self) 

2281 

2282 @HasMemoized.memoized_attribute 

2283 def _default_description_tuple(self) -> _DefaultDescriptionTuple: 

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

2285 

2286 return _DefaultDescriptionTuple._from_column_default(self.default) 

2287 

2288 @HasMemoized.memoized_attribute 

2289 def _onupdate_description_tuple(self) -> _DefaultDescriptionTuple: 

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

2291 return _DefaultDescriptionTuple._from_column_default(self.onupdate) 

2292 

2293 @util.memoized_property 

2294 def _gen_static_annotations_cache_key(self) -> bool: 

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

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

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

2298 

2299 Added for #8790 

2300 

2301 """ 

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

2303 

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

2305 self._validate_dialect_kwargs(kwargs) 

2306 

2307 def __str__(self) -> str: 

2308 if self.name is None: 

2309 return "(no name)" 

2310 elif self.table is not None: 

2311 if self.table.named_with_column: 

2312 return self.table.description + "." + self.description 

2313 else: 

2314 return self.description 

2315 else: 

2316 return self.description 

2317 

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

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

2320 key.""" 

2321 

2322 for fk in self.foreign_keys: 

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

2324 return True 

2325 else: 

2326 return False 

2327 

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

2329 fk._set_parent_with_dispatch(self) 

2330 

2331 def __repr__(self) -> str: 

2332 kwarg = [] 

2333 if self.key != self.name: 

2334 kwarg.append("key") 

2335 if self.primary_key: 

2336 kwarg.append("primary_key") 

2337 if not self.nullable: 

2338 kwarg.append("nullable") 

2339 if self.onupdate: 

2340 kwarg.append("onupdate") 

2341 if self.default: 

2342 kwarg.append("default") 

2343 if self.server_default: 

2344 kwarg.append("server_default") 

2345 if self.comment: 

2346 kwarg.append("comment") 

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

2348 [repr(self.name)] 

2349 + [repr(self.type)] 

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

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

2352 + [ 

2353 ( 

2354 self.table is not None 

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

2356 or "table=None" 

2357 ) 

2358 ] 

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

2360 ) 

2361 

2362 def _set_parent( # type: ignore[override] 

2363 self, 

2364 parent: SchemaEventTarget, 

2365 *, 

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

2367 allow_replacements: bool, 

2368 index: Optional[int] = None, 

2369 **kw: Any, 

2370 ) -> None: 

2371 table = parent 

2372 assert isinstance(table, Table) 

2373 if not self.name: 

2374 raise exc.ArgumentError( 

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

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

2377 ) 

2378 

2379 self._reset_memoizations() 

2380 

2381 if self.key is None: 

2382 self.key = self.name 

2383 

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

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

2386 raise exc.ArgumentError( 

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

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

2389 ) 

2390 

2391 extra_remove = None 

2392 existing_col = None 

2393 conflicts_on = "" 

2394 

2395 if self.key in table._columns: 

2396 existing_col = table._columns[self.key] 

2397 if self.key == self.name: 

2398 conflicts_on = "name" 

2399 else: 

2400 conflicts_on = "key" 

2401 elif self.name in all_names: 

2402 existing_col = all_names[self.name] 

2403 extra_remove = {existing_col} 

2404 conflicts_on = "name" 

2405 

2406 if existing_col is not None: 

2407 if existing_col is not self: 

2408 if not allow_replacements: 

2409 raise exc.DuplicateColumnError( 

2410 f"A column with {conflicts_on} " 

2411 f"""'{ 

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

2413 }' """ 

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

2415 ) 

2416 for fk in existing_col.foreign_keys: 

2417 table.foreign_keys.remove(fk) 

2418 if fk.constraint in table.constraints: 

2419 # this might have been removed 

2420 # already, if it's a composite constraint 

2421 # and more than one col being replaced 

2422 table.constraints.remove(fk.constraint) 

2423 

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

2425 util.warn( 

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

2427 "being replaced with " 

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

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

2430 "reflection operation, specify autoload_replace=False to " 

2431 "prevent this replacement." 

2432 ) 

2433 table._columns.replace(self, extra_remove=extra_remove, index=index) 

2434 all_names[self.name] = self 

2435 self.table = table 

2436 

2437 if self._insert_sentinel: 

2438 if self.table._sentinel_column is not None: 

2439 raise exc.ArgumentError( 

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

2441 ) 

2442 self.table._sentinel_column = self 

2443 

2444 if self.primary_key: 

2445 table.primary_key._replace(self) 

2446 elif self.key in table.primary_key: 

2447 raise exc.ArgumentError( 

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

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

2450 ) 

2451 

2452 if self.index: 

2453 if isinstance(self.index, str): 

2454 raise exc.ArgumentError( 

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

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

2457 "explicit Index object external to the Table." 

2458 ) 

2459 table.append_constraint( 

2460 Index( 

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

2462 ) 

2463 ) 

2464 

2465 elif self.unique: 

2466 if isinstance(self.unique, str): 

2467 raise exc.ArgumentError( 

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

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

2470 "specific name, append an explicit UniqueConstraint to " 

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

2472 "Index object external to the Table." 

2473 ) 

2474 table.append_constraint( 

2475 UniqueConstraint(self.key, _column_flag=True) 

2476 ) 

2477 

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

2479 

2480 if self.identity and ( 

2481 isinstance(self.default, Sequence) 

2482 or isinstance(self.onupdate, Sequence) 

2483 ): 

2484 raise exc.ArgumentError( 

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

2486 ) 

2487 

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

2489 fk_keys = [ 

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

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

2492 ] 

2493 for fk_key, link_to_name in fk_keys: 

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

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

2496 if fk.link_to_name is link_to_name: 

2497 fn(fk) 

2498 

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

2500 if self.table is not None: 

2501 fn(self, self.table) 

2502 else: 

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

2504 

2505 @util.deprecated( 

2506 "1.4", 

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

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

2509 ) 

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

2511 return self._copy(**kw) 

2512 

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

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

2515 

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

2517 

2518 """ 

2519 

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

2521 args: List[SchemaItem] = [ 

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

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

2524 

2525 # ticket #5276 

2526 column_kwargs = {} 

2527 for dialect_name in self.dialect_options: 

2528 dialect_options = self.dialect_options[dialect_name]._non_defaults 

2529 for ( 

2530 dialect_option_key, 

2531 dialect_option_value, 

2532 ) in dialect_options.items(): 

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

2534 dialect_option_value 

2535 ) 

2536 

2537 server_default = self.server_default 

2538 server_onupdate = self.server_onupdate 

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

2540 # TODO: likely should be copied in all cases 

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

2542 # .metadata as well 

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

2544 server_default = server_onupdate = None 

2545 

2546 type_ = self.type 

2547 if isinstance(type_, SchemaEventTarget): 

2548 type_ = type_.copy(**kw) 

2549 

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

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

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

2553 

2554 c = self._constructor( 

2555 name=self.name, 

2556 type_=type_, 

2557 key=self.key, 

2558 primary_key=self.primary_key, 

2559 unique=self.unique, 

2560 system=self.system, 

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

2562 index=self.index, 

2563 autoincrement=self.autoincrement, 

2564 default=self.default, 

2565 server_default=server_default, 

2566 onupdate=self.onupdate, 

2567 server_onupdate=server_onupdate, 

2568 doc=self.doc, 

2569 comment=self.comment, 

2570 _omit_from_statements=self._omit_from_statements, 

2571 insert_sentinel=self._insert_sentinel, 

2572 *args, 

2573 **column_kwargs, 

2574 ) 

2575 

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

2577 # ORM flipping the .nullable flag directly 

2578 c.nullable = self.nullable 

2579 c._user_defined_nullable = self._user_defined_nullable 

2580 

2581 return self._schema_item_copy(c) 

2582 

2583 def _merge( 

2584 self, other: Column[Any], *, omit_defaults: bool = False 

2585 ) -> None: 

2586 """merge the elements of this column onto "other" 

2587 

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

2589 of fixes. 

2590 

2591 

2592 """ 

2593 

2594 if self.primary_key: 

2595 other.primary_key = True 

2596 

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

2598 other.autoincrement = self.autoincrement 

2599 

2600 if self.system: 

2601 other.system = self.system 

2602 

2603 if self.info: 

2604 other.info.update(self.info) 

2605 

2606 type_ = self.type 

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

2608 if isinstance(type_, SchemaEventTarget): 

2609 type_ = type_.copy() 

2610 

2611 other.type = type_ 

2612 

2613 if isinstance(type_, SchemaEventTarget): 

2614 type_._set_parent_with_dispatch(other) 

2615 

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

2617 if isinstance(impl, SchemaEventTarget): 

2618 impl._set_parent_with_dispatch(other) 

2619 

2620 if ( 

2621 self._user_defined_nullable is not NULL_UNSPECIFIED 

2622 and other._user_defined_nullable is NULL_UNSPECIFIED 

2623 ): 

2624 other.nullable = self.nullable 

2625 other._user_defined_nullable = self._user_defined_nullable 

2626 

2627 if ( 

2628 not omit_defaults 

2629 and self.default is not None 

2630 and other.default is None 

2631 ): 

2632 new_default = self.default._copy() 

2633 new_default._set_parent(other) 

2634 

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

2636 new_server_default = self.server_default 

2637 if isinstance(new_server_default, FetchedValue): 

2638 new_server_default = new_server_default._copy() 

2639 new_server_default._set_parent(other) 

2640 else: 

2641 other.server_default = new_server_default 

2642 

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

2644 new_server_onupdate = self.server_onupdate 

2645 new_server_onupdate = new_server_onupdate._copy() 

2646 new_server_onupdate._set_parent(other) 

2647 

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

2649 new_onupdate = self.onupdate._copy() 

2650 new_onupdate._set_parent(other) 

2651 

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

2653 other.index = self.index 

2654 

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

2656 other.unique = self.unique 

2657 

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

2659 other.doc = self.doc 

2660 

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

2662 other.comment = self.comment 

2663 

2664 for const in self.constraints: 

2665 if not const._type_bound: 

2666 new_const = const._copy() 

2667 new_const._set_parent(other) 

2668 

2669 for fk in self.foreign_keys: 

2670 if not fk.constraint: 

2671 new_fk = fk._copy() 

2672 new_fk._set_parent(other) 

2673 

2674 def _make_proxy( 

2675 self, 

2676 selectable: FromClause, 

2677 primary_key: ColumnSet, 

2678 foreign_keys: Set[KeyedColumnElement[Any]], 

2679 name: Optional[str] = None, 

2680 key: Optional[str] = None, 

2681 name_is_truncatable: bool = False, 

2682 compound_select_cols: Optional[ 

2683 _typing_Sequence[ColumnElement[Any]] 

2684 ] = None, 

2685 **kw: Any, 

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

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

2688 

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

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

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

2692 information is not transferred. 

2693 

2694 """ 

2695 

2696 fk = [ 

2697 ForeignKey( 

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

2699 _unresolvable=col is None, 

2700 _constraint=f.constraint, 

2701 ) 

2702 for f, col in [ 

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

2704 for fk in self.foreign_keys 

2705 ] 

2706 ] 

2707 

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

2709 raise exc.InvalidRequestError( 

2710 "Cannot initialize a sub-selectable" 

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

2712 "been assigned." 

2713 ) 

2714 try: 

2715 c = self._constructor( 

2716 ( 

2717 coercions.expect( 

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

2719 ) 

2720 if name_is_truncatable 

2721 else (name or self.name) 

2722 ), 

2723 self.type, 

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

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

2726 primary_key=self.primary_key, 

2727 nullable=self.nullable, 

2728 _proxies=( 

2729 list(compound_select_cols) 

2730 if compound_select_cols 

2731 else [self] 

2732 ), 

2733 *fk, 

2734 ) 

2735 except TypeError as err: 

2736 raise TypeError( 

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

2738 "Ensure the class includes a _constructor() " 

2739 "attribute or method which accepts the " 

2740 "standard Column constructor arguments, or " 

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

2742 ) from err 

2743 

2744 c.table = selectable 

2745 c._propagate_attrs = selectable._propagate_attrs 

2746 if selectable._is_clone_of is not None: 

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

2748 

2749 if self.primary_key: 

2750 primary_key.add(c) 

2751 

2752 if fk: 

2753 foreign_keys.update(fk) # type: ignore 

2754 

2755 return c.key, c 

2756 

2757 

2758def insert_sentinel( 

2759 name: Optional[str] = None, 

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

2761 *, 

2762 default: Optional[Any] = None, 

2763 omit_from_statements: bool = True, 

2764) -> Column[Any]: 

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

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

2767 inserts with deterministic RETURNING sorting for tables that 

2768 don't otherwise have qualifying primary key configurations. 

2769 

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

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

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

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

2774 

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

2776 :ref:`engine_insertmanyvalues_sentinel_columns` as part of the 

2777 section :ref:`engine_insertmanyvalues`. 

2778 

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

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

2781 "insertmanyvalues" operations. 

2782 

2783 .. seealso:: 

2784 

2785 :func:`_orm.orm_insert_sentinel` 

2786 

2787 :paramref:`_schema.Column.insert_sentinel` 

2788 

2789 :ref:`engine_insertmanyvalues` 

2790 

2791 :ref:`engine_insertmanyvalues_sentinel_columns` 

2792 

2793 

2794 .. versionadded:: 2.0.10 

2795 

2796 """ 

2797 return Column( 

2798 name=name, 

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

2800 default=( 

2801 default if default is not None else _InsertSentinelColumnDefault() 

2802 ), 

2803 _omit_from_statements=omit_from_statements, 

2804 insert_sentinel=True, 

2805 ) 

2806 

2807 

2808class ForeignKey(DialectKWArgs, SchemaItem): 

2809 """Defines a dependency between two columns. 

2810 

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

2812 object, 

2813 e.g.:: 

2814 

2815 t = Table( 

2816 "remote_table", 

2817 metadata, 

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

2819 ) 

2820 

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

2822 a dependency between two columns. The actual constraint 

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

2824 object. This object will be generated automatically when 

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

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

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

2828 :class:`_schema.Table`, 

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

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

2831 associated with the constraint object. 

2832 

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

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

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

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

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

2838 are created automatically. 

2839 

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

2841 :class:`_schema.Column` 

2842 object are available in the `foreign_keys` collection 

2843 of that column. 

2844 

2845 Further examples of foreign key configuration are in 

2846 :ref:`metadata_foreignkeys`. 

2847 

2848 """ 

2849 

2850 __visit_name__ = "foreign_key" 

2851 

2852 parent: Column[Any] 

2853 

2854 _table_column: Optional[Column[Any]] 

2855 

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

2857 

2858 def __init__( 

2859 self, 

2860 column: _DDLColumnReferenceArgument, 

2861 _constraint: Optional[ForeignKeyConstraint] = None, 

2862 use_alter: bool = False, 

2863 name: _ConstraintNameArgument = None, 

2864 onupdate: Optional[str] = None, 

2865 ondelete: Optional[str] = None, 

2866 deferrable: Optional[bool] = None, 

2867 initially: Optional[str] = None, 

2868 link_to_name: bool = False, 

2869 match: Optional[str] = None, 

2870 info: Optional[_InfoType] = None, 

2871 comment: Optional[str] = None, 

2872 _unresolvable: bool = False, 

2873 **dialect_kw: Any, 

2874 ): 

2875 r""" 

2876 Construct a column-level FOREIGN KEY. 

2877 

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

2879 :class:`_schema.ForeignKeyConstraint` 

2880 which is associated with the parent 

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

2882 

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

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

2885 ``tablename.columnkey`` or ``schema.tablename.columnkey``. 

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

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

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

2889 

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

2891 `constraint` is not provided. 

2892 

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

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

2895 DELETE and RESTRICT. 

2896 

2897 .. seealso:: 

2898 

2899 :ref:`on_update_on_delete` 

2900 

2901 :param ondelete: Optional string. If set, emit ON DELETE <value> when 

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

2903 SET NULL and RESTRICT. Some dialects may allow for additional 

2904 syntaxes. 

2905 

2906 .. seealso:: 

2907 

2908 :ref:`on_update_on_delete` 

2909 

2910 :param deferrable: Optional bool. If set, emit DEFERRABLE or NOT 

2911 DEFERRABLE when issuing DDL for this constraint. 

2912 

2913 :param initially: Optional string. If set, emit INITIALLY <value> when 

2914 issuing DDL for this constraint. 

2915 

2916 :param link_to_name: if True, the string name given in ``column`` is 

2917 the rendered name of the referenced column, not its locally 

2918 assigned ``key``. 

2919 

2920 :param use_alter: passed to the underlying 

2921 :class:`_schema.ForeignKeyConstraint` 

2922 to indicate the constraint should 

2923 be generated/dropped externally from the CREATE TABLE/ DROP TABLE 

2924 statement. See :paramref:`_schema.ForeignKeyConstraint.use_alter` 

2925 for further description. 

2926 

2927 .. seealso:: 

2928 

2929 :paramref:`_schema.ForeignKeyConstraint.use_alter` 

2930 

2931 :ref:`use_alter` 

2932 

2933 :param match: Optional string. If set, emit MATCH <value> when issuing 

2934 DDL for this constraint. Typical values include SIMPLE, PARTIAL 

2935 and FULL. 

2936 

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

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

2939 

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

2941 foreign key constraint creation. 

2942 

2943 .. versionadded:: 2.0 

2944 

2945 :param \**dialect_kw: Additional keyword arguments are dialect 

2946 specific, and passed in the form ``<dialectname>_<argname>``. The 

2947 arguments are ultimately handled by a corresponding 

2948 :class:`_schema.ForeignKeyConstraint`. 

2949 See the documentation regarding 

2950 an individual dialect at :ref:`dialect_toplevel` for detail on 

2951 documented arguments. 

2952 

2953 """ 

2954 

2955 self._unresolvable = _unresolvable 

2956 

2957 self._colspec, self._table_column = self._parse_colspec_argument( 

2958 column 

2959 ) 

2960 

2961 # the linked ForeignKeyConstraint. 

2962 # ForeignKey will create this when parent Column 

2963 # is attached to a Table, *or* ForeignKeyConstraint 

2964 # object passes itself in when creating ForeignKey 

2965 # markers. 

2966 self.constraint = _constraint 

2967 

2968 # .parent is not Optional under normal use 

2969 self.parent = None # type: ignore 

2970 

2971 self.use_alter = use_alter 

2972 self.name = name 

2973 self.onupdate = onupdate 

2974 self.ondelete = ondelete 

2975 self.deferrable = deferrable 

2976 self.initially = initially 

2977 self.link_to_name = link_to_name 

2978 self.match = match 

2979 self.comment = comment 

2980 if info: 

2981 self.info = info 

2982 self._unvalidated_dialect_kw = dialect_kw 

2983 

2984 def _resolve_colspec_argument( 

2985 self, 

2986 ) -> Tuple[ 

2987 Union[str, Column[Any]], 

2988 Optional[Column[Any]], 

2989 ]: 

2990 argument = self._colspec 

2991 

2992 return self._parse_colspec_argument(argument) 

2993 

2994 def _parse_colspec_argument( 

2995 self, 

2996 argument: _DDLColumnArgument, 

2997 ) -> Tuple[ 

2998 Union[str, Column[Any]], 

2999 Optional[Column[Any]], 

3000 ]: 

3001 _colspec = coercions.expect(roles.DDLReferredColumnRole, argument) 

3002 

3003 if isinstance(_colspec, str): 

3004 _table_column = None 

3005 else: 

3006 assert isinstance(_colspec, ColumnClause) 

3007 _table_column = _colspec 

3008 

3009 if not isinstance(_table_column.table, (type(None), TableClause)): 

3010 raise exc.ArgumentError( 

3011 "ForeignKey received Column not bound " 

3012 "to a Table, got: %r" % _table_column.table 

3013 ) 

3014 

3015 return _colspec, _table_column 

3016 

3017 def __repr__(self) -> str: 

3018 return "ForeignKey(%r)" % self._get_colspec() 

3019 

3020 @util.deprecated( 

3021 "1.4", 

3022 "The :meth:`_schema.ForeignKey.copy` method is deprecated " 

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

3024 ) 

3025 def copy(self, *, schema: Optional[str] = None, **kw: Any) -> ForeignKey: 

3026 return self._copy(schema=schema, **kw) 

3027 

3028 def _copy(self, *, schema: Optional[str] = None, **kw: Any) -> ForeignKey: 

3029 """Produce a copy of this :class:`_schema.ForeignKey` object. 

3030 

3031 The new :class:`_schema.ForeignKey` will not be bound 

3032 to any :class:`_schema.Column`. 

3033 

3034 This method is usually used by the internal 

3035 copy procedures of :class:`_schema.Column`, :class:`_schema.Table`, 

3036 and :class:`_schema.MetaData`. 

3037 

3038 :param schema: The returned :class:`_schema.ForeignKey` will 

3039 reference the original table and column name, qualified 

3040 by the given string schema name. 

3041 

3042 """ 

3043 fk = ForeignKey( 

3044 self._get_colspec(schema=schema), 

3045 use_alter=self.use_alter, 

3046 name=self.name, 

3047 onupdate=self.onupdate, 

3048 ondelete=self.ondelete, 

3049 deferrable=self.deferrable, 

3050 initially=self.initially, 

3051 link_to_name=self.link_to_name, 

3052 match=self.match, 

3053 comment=self.comment, 

3054 **self._unvalidated_dialect_kw, 

3055 ) 

3056 return self._schema_item_copy(fk) 

3057 

3058 def _get_colspec( 

3059 self, 

3060 schema: Optional[ 

3061 Union[ 

3062 str, 

3063 Literal[SchemaConst.RETAIN_SCHEMA, SchemaConst.BLANK_SCHEMA], 

3064 ] 

3065 ] = None, 

3066 table_name: Optional[str] = None, 

3067 _is_copy: bool = False, 

3068 ) -> str: 

3069 """Return a string based 'column specification' for this 

3070 :class:`_schema.ForeignKey`. 

3071 

3072 This is usually the equivalent of the string-based "tablename.colname" 

3073 argument first passed to the object's constructor. 

3074 

3075 """ 

3076 

3077 _colspec, effective_table_column = self._resolve_colspec_argument() 

3078 

3079 if schema not in (None, RETAIN_SCHEMA): 

3080 _schema, tname, colname = self._column_tokens 

3081 if table_name is not None: 

3082 tname = table_name 

3083 if schema is BLANK_SCHEMA: 

3084 return "%s.%s" % (tname, colname) 

3085 else: 

3086 return "%s.%s.%s" % (schema, tname, colname) 

3087 elif table_name: 

3088 schema, tname, colname = self._column_tokens 

3089 if schema: 

3090 return "%s.%s.%s" % (schema, table_name, colname) 

3091 else: 

3092 return "%s.%s" % (table_name, colname) 

3093 elif effective_table_column is not None: 

3094 if effective_table_column.table is None: 

3095 if _is_copy: 

3096 raise exc.InvalidRequestError( 

3097 f"Can't copy ForeignKey object which refers to " 

3098 f"non-table bound Column {effective_table_column!r}" 

3099 ) 

3100 else: 

3101 return effective_table_column.key 

3102 return "%s.%s" % ( 

3103 effective_table_column.table.fullname, 

3104 effective_table_column.key, 

3105 ) 

3106 else: 

3107 assert isinstance(_colspec, str) 

3108 return _colspec 

3109 

3110 @property 

3111 def _referred_schema(self) -> Optional[str]: 

3112 return self._column_tokens[0] 

3113 

3114 def _table_key_within_construction(self) -> Any: 

3115 """get the table key but only safely""" 

3116 

3117 if self._table_column is not None: 

3118 if self._table_column.table is None: 

3119 return None 

3120 else: 

3121 return self._table_column.table.key 

3122 else: 

3123 schema, tname, colname = self._column_tokens 

3124 return _get_table_key(tname, schema) 

3125 

3126 target_fullname = property(_get_colspec) 

3127 

3128 def references(self, table: Table) -> bool: 

3129 """Return True if the given :class:`_schema.Table` 

3130 is referenced by this 

3131 :class:`_schema.ForeignKey`.""" 

3132 

3133 return table.corresponding_column(self.column) is not None 

3134 

3135 def get_referent(self, table: FromClause) -> Optional[Column[Any]]: 

3136 """Return the :class:`_schema.Column` in the given 

3137 :class:`_schema.Table` (or any :class:`.FromClause`) 

3138 referenced by this :class:`_schema.ForeignKey`. 

3139 

3140 Returns None if this :class:`_schema.ForeignKey` 

3141 does not reference the given 

3142 :class:`_schema.Table`. 

3143 

3144 """ 

3145 # our column is a Column, and any subquery etc. proxying us 

3146 # would be doing so via another Column, so that's what would 

3147 # be returned here 

3148 return table.columns.corresponding_column(self.column) # type: ignore 

3149 

3150 @util.memoized_property 

3151 def _column_tokens(self) -> Tuple[Optional[str], str, Optional[str]]: 

3152 """parse a string-based _colspec into its component parts.""" 

3153 

3154 m = self._get_colspec().split(".") 

3155 if len(m) == 1: 

3156 tname = m.pop() 

3157 colname = None 

3158 else: 

3159 colname = m.pop() 

3160 tname = m.pop() 

3161 

3162 # A FK between column 'bar' and table 'foo' can be 

3163 # specified as 'foo', 'foo.bar', 'dbo.foo.bar', 

3164 # 'otherdb.dbo.foo.bar'. Once we have the column name and 

3165 # the table name, treat everything else as the schema 

3166 # name. Some databases (e.g. Sybase) support 

3167 # inter-database foreign keys. See tickets#1341 and -- 

3168 # indirectly related -- Ticket #594. This assumes that '.' 

3169 # will never appear *within* any component of the FK. 

3170 

3171 if len(m) > 0: 

3172 schema = ".".join(m) 

3173 else: 

3174 schema = None 

3175 return schema, tname, colname 

3176 

3177 def _resolve_col_tokens(self) -> Tuple[Table, str, Optional[str]]: 

3178 if self.parent is None: 

3179 raise exc.InvalidRequestError( 

3180 "this ForeignKey object does not yet have a " 

3181 "parent Column associated with it." 

3182 ) 

3183 

3184 elif self.parent.table is None: 

3185 raise exc.InvalidRequestError( 

3186 "this ForeignKey's parent column is not yet associated " 

3187 "with a Table." 

3188 ) 

3189 

3190 parenttable = self.parent.table 

3191 

3192 if self._unresolvable: 

3193 schema, tname, colname = self._column_tokens 

3194 tablekey = _get_table_key(tname, schema) 

3195 return parenttable, tablekey, colname 

3196 

3197 # assertion 

3198 # basically Column._make_proxy() sends the actual 

3199 # target Column to the ForeignKey object, so the 

3200 # string resolution here is never called. 

3201 for c in self.parent.base_columns: 

3202 if isinstance(c, Column): 

3203 assert c.table is parenttable 

3204 break 

3205 else: 

3206 assert False 

3207 ###################### 

3208 

3209 schema, tname, colname = self._column_tokens 

3210 

3211 if schema is None and parenttable.metadata.schema is not None: 

3212 schema = parenttable.metadata.schema 

3213 

3214 tablekey = _get_table_key(tname, schema) 

3215 return parenttable, tablekey, colname 

3216 

3217 def _link_to_col_by_colstring( 

3218 self, parenttable: Table, table: Table, colname: Optional[str] 

3219 ) -> Column[Any]: 

3220 _column = None 

3221 if colname is None: 

3222 # colname is None in the case that ForeignKey argument 

3223 # was specified as table name only, in which case we 

3224 # match the column name to the same column on the 

3225 # parent. 

3226 # this use case wasn't working in later 1.x series 

3227 # as it had no test coverage; fixed in 2.0 

3228 parent = self.parent 

3229 assert parent is not None 

3230 key = parent.key 

3231 _column = table.c.get(key, None) 

3232 elif self.link_to_name: 

3233 key = colname 

3234 for c in table.c: 

3235 if c.name == colname: 

3236 _column = c 

3237 else: 

3238 key = colname 

3239 _column = table.c.get(colname, None) 

3240 

3241 if _column is None: 

3242 raise exc.NoReferencedColumnError( 

3243 "Could not initialize target column " 

3244 f"for ForeignKey '{self._get_colspec()}' " 

3245 f"on table '{parenttable.name}': " 

3246 f"table '{table.name}' has no column named '{key}'", 

3247 table.name, 

3248 key, 

3249 ) 

3250 

3251 return _column 

3252 

3253 def _set_target_column(self, column: Column[Any]) -> None: 

3254 assert self.parent is not None 

3255 

3256 # propagate TypeEngine to parent if it didn't have one 

3257 if self.parent.type._isnull: 

3258 self.parent.type = column.type 

3259 

3260 # super-edgy case, if other FKs point to our column, 

3261 # they'd get the type propagated out also. 

3262 

3263 def set_type(fk: ForeignKey) -> None: 

3264 if fk.parent.type._isnull: 

3265 fk.parent.type = column.type 

3266 

3267 self.parent._setup_on_memoized_fks(set_type) 

3268 

3269 self.column = column # type: ignore 

3270 

3271 @util.ro_memoized_property 

3272 def column(self) -> Column[Any]: 

3273 """Return the target :class:`_schema.Column` referenced by this 

3274 :class:`_schema.ForeignKey`. 

3275 

3276 If no target column has been established, an exception 

3277 is raised. 

3278 

3279 """ 

3280 return self._resolve_column() 

3281 

3282 @overload 

3283 def _resolve_column( 

3284 self, *, raiseerr: Literal[True] = ... 

3285 ) -> Column[Any]: ... 

3286 

3287 @overload 

3288 def _resolve_column( 

3289 self, *, raiseerr: bool = ... 

3290 ) -> Optional[Column[Any]]: ... 

3291 

3292 def _resolve_column( 

3293 self, *, raiseerr: bool = True 

3294 ) -> Optional[Column[Any]]: 

3295 _column: Column[Any] 

3296 

3297 _colspec, effective_table_column = self._resolve_colspec_argument() 

3298 

3299 if isinstance(_colspec, str): 

3300 parenttable, tablekey, colname = self._resolve_col_tokens() 

3301 

3302 if self._unresolvable or tablekey not in parenttable.metadata: 

3303 if not raiseerr: 

3304 return None 

3305 raise exc.NoReferencedTableError( 

3306 f"Foreign key associated with column " 

3307 f"'{self.parent}' could not find " 

3308 f"table '{tablekey}' with which to generate a " 

3309 f"foreign key to target column '{colname}'", 

3310 tablekey, 

3311 ) 

3312 elif parenttable.key not in parenttable.metadata: 

3313 if not raiseerr: 

3314 return None 

3315 raise exc.InvalidRequestError( 

3316 f"Table {parenttable} is no longer associated with its " 

3317 "parent MetaData" 

3318 ) 

3319 else: 

3320 table = parenttable.metadata.tables[tablekey] 

3321 return self._link_to_col_by_colstring( 

3322 parenttable, table, colname 

3323 ) 

3324 

3325 elif hasattr(_colspec, "__clause_element__"): 

3326 _column = _colspec.__clause_element__() 

3327 return _column 

3328 else: 

3329 assert isinstance(_colspec, Column) 

3330 _column = _colspec 

3331 return _column 

3332 

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

3334 assert isinstance(parent, Column) 

3335 

3336 if self.parent is not None and self.parent is not parent: 

3337 raise exc.InvalidRequestError( 

3338 "This ForeignKey already has a parent !" 

3339 ) 

3340 self.parent = parent 

3341 self.parent.foreign_keys.add(self) 

3342 self.parent._on_table_attach(self._set_table) 

3343 

3344 def _set_remote_table(self, table: Table) -> None: 

3345 parenttable, _, colname = self._resolve_col_tokens() 

3346 _column = self._link_to_col_by_colstring(parenttable, table, colname) 

3347 self._set_target_column(_column) 

3348 assert self.constraint is not None 

3349 self.constraint._validate_dest_table(table) 

3350 

3351 def _remove_from_metadata(self, metadata: MetaData) -> None: 

3352 parenttable, table_key, colname = self._resolve_col_tokens() 

3353 fk_key = (table_key, colname) 

3354 

3355 if self in metadata._fk_memos[fk_key]: 

3356 # TODO: no test coverage for self not in memos 

3357 metadata._fk_memos[fk_key].remove(self) 

3358 

3359 def _set_table(self, column: Column[Any], table: Table) -> None: 

3360 # standalone ForeignKey - create ForeignKeyConstraint 

3361 # on the hosting Table when attached to the Table. 

3362 assert isinstance(table, Table) 

3363 if self.constraint is None: 

3364 self.constraint = ForeignKeyConstraint( 

3365 [], 

3366 [], 

3367 use_alter=self.use_alter, 

3368 name=self.name, 

3369 onupdate=self.onupdate, 

3370 ondelete=self.ondelete, 

3371 deferrable=self.deferrable, 

3372 initially=self.initially, 

3373 match=self.match, 

3374 comment=self.comment, 

3375 **self._unvalidated_dialect_kw, 

3376 ) 

3377 self.constraint._append_element(column, self) 

3378 self.constraint._set_parent_with_dispatch(table) 

3379 table.foreign_keys.add(self) 

3380 # set up remote ".column" attribute, or a note to pick it 

3381 # up when the other Table/Column shows up 

3382 

3383 _colspec, _ = self._resolve_colspec_argument() 

3384 if isinstance(_colspec, str): 

3385 parenttable, table_key, colname = self._resolve_col_tokens() 

3386 fk_key = (table_key, colname) 

3387 if table_key in parenttable.metadata.tables: 

3388 table = parenttable.metadata.tables[table_key] 

3389 try: 

3390 _column = self._link_to_col_by_colstring( 

3391 parenttable, table, colname 

3392 ) 

3393 except exc.NoReferencedColumnError: 

3394 # this is OK, we'll try later 

3395 pass 

3396 else: 

3397 self._set_target_column(_column) 

3398 

3399 parenttable.metadata._fk_memos[fk_key].append(self) 

3400 elif hasattr(_colspec, "__clause_element__"): 

3401 _column = _colspec.__clause_element__() 

3402 self._set_target_column(_column) 

3403 else: 

3404 self._set_target_column(_colspec) 

3405 

3406 

3407if TYPE_CHECKING: 

3408 

3409 def default_is_sequence( 

3410 obj: Optional[DefaultGenerator], 

3411 ) -> TypeGuard[Sequence]: ... 

3412 

3413 def default_is_clause_element( 

3414 obj: Optional[DefaultGenerator], 

3415 ) -> TypeGuard[ColumnElementColumnDefault]: ... 

3416 

3417 def default_is_scalar( 

3418 obj: Optional[DefaultGenerator], 

3419 ) -> TypeGuard[ScalarElementColumnDefault]: ... 

3420 

3421else: 

3422 default_is_sequence = operator.attrgetter("is_sequence") 

3423 

3424 default_is_clause_element = operator.attrgetter("is_clause_element") 

3425 

3426 default_is_scalar = operator.attrgetter("is_scalar") 

3427 

3428 

3429class DefaultGenerator(Executable, SchemaItem): 

3430 """Base class for column *default* values. 

3431 

3432 This object is only present on column.default or column.onupdate. 

3433 It's not valid as a server default. 

3434 

3435 """ 

3436 

3437 __visit_name__ = "default_generator" 

3438 

3439 _is_default_generator = True 

3440 is_sequence = False 

3441 is_identity = False 

3442 is_server_default = False 

3443 is_clause_element = False 

3444 is_callable = False 

3445 is_scalar = False 

3446 has_arg = False 

3447 is_sentinel = False 

3448 column: Optional[Column[Any]] 

3449 

3450 def __init__(self, for_update: bool = False) -> None: 

3451 self.for_update = for_update 

3452 

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

3454 if TYPE_CHECKING: 

3455 assert isinstance(parent, Column) 

3456 self.column = parent 

3457 if self.for_update: 

3458 self.column.onupdate = self 

3459 else: 

3460 self.column.default = self 

3461 

3462 def _copy(self) -> DefaultGenerator: 

3463 raise NotImplementedError() 

3464 

3465 def _execute_on_connection( 

3466 self, 

3467 connection: Connection, 

3468 distilled_params: _CoreMultiExecuteParams, 

3469 execution_options: CoreExecuteOptionsParameter, 

3470 ) -> Any: 

3471 util.warn_deprecated( 

3472 "Using the .execute() method to invoke a " 

3473 "DefaultGenerator object is deprecated; please use " 

3474 "the .scalar() method.", 

3475 "2.0", 

3476 ) 

3477 return self._execute_on_scalar( 

3478 connection, distilled_params, execution_options 

3479 ) 

3480 

3481 def _execute_on_scalar( 

3482 self, 

3483 connection: Connection, 

3484 distilled_params: _CoreMultiExecuteParams, 

3485 execution_options: CoreExecuteOptionsParameter, 

3486 ) -> Any: 

3487 return connection._execute_default( 

3488 self, distilled_params, execution_options 

3489 ) 

3490 

3491 

3492class ColumnDefault(DefaultGenerator, ABC): 

3493 """A plain default value on a column. 

3494 

3495 This could correspond to a constant, a callable function, 

3496 or a SQL clause. 

3497 

3498 :class:`.ColumnDefault` is generated automatically 

3499 whenever the ``default``, ``onupdate`` arguments of 

3500 :class:`_schema.Column` are used. A :class:`.ColumnDefault` 

3501 can be passed positionally as well. 

3502 

3503 For example, the following:: 

3504 

3505 Column("foo", Integer, default=50) 

3506 

3507 Is equivalent to:: 

3508 

3509 Column("foo", Integer, ColumnDefault(50)) 

3510 

3511 """ 

3512 

3513 arg: Any 

3514 

3515 @overload 

3516 def __new__( 

3517 cls, arg: Callable[..., Any], for_update: bool = ... 

3518 ) -> CallableColumnDefault: ... 

3519 

3520 @overload 

3521 def __new__( 

3522 cls, arg: ColumnElement[Any], for_update: bool = ... 

3523 ) -> ColumnElementColumnDefault: ... 

3524 

3525 # if I return ScalarElementColumnDefault here, which is what's actually 

3526 # returned, mypy complains that 

3527 # overloads overlap w/ incompatible return types. 

3528 @overload 

3529 def __new__(cls, arg: object, for_update: bool = ...) -> ColumnDefault: ... 

3530 

3531 def __new__( 

3532 cls, arg: Any = None, for_update: bool = False 

3533 ) -> ColumnDefault: 

3534 """Construct a new :class:`.ColumnDefault`. 

3535 

3536 

3537 :param arg: argument representing the default value. 

3538 May be one of the following: 

3539 

3540 * a plain non-callable Python value, such as a 

3541 string, integer, boolean, or other simple type. 

3542 The default value will be used as is each time. 

3543 * a SQL expression, that is one which derives from 

3544 :class:`_expression.ColumnElement`. The SQL expression will 

3545 be rendered into the INSERT or UPDATE statement, 

3546 or in the case of a primary key column when 

3547 RETURNING is not used may be 

3548 pre-executed before an INSERT within a SELECT. 

3549 * A Python callable. The function will be invoked for each 

3550 new row subject to an INSERT or UPDATE. 

3551 The callable must accept exactly 

3552 zero or one positional arguments. The one-argument form 

3553 will receive an instance of the :class:`.ExecutionContext`, 

3554 which provides contextual information as to the current 

3555 :class:`_engine.Connection` in use as well as the current 

3556 statement and parameters. 

3557 

3558 """ 

3559 

3560 if isinstance(arg, FetchedValue): 

3561 raise exc.ArgumentError( 

3562 "ColumnDefault may not be a server-side default type." 

3563 ) 

3564 elif callable(arg): 

3565 cls = CallableColumnDefault 

3566 elif isinstance(arg, ClauseElement): 

3567 cls = ColumnElementColumnDefault 

3568 elif arg is not None: 

3569 cls = ScalarElementColumnDefault 

3570 

3571 return object.__new__(cls) 

3572 

3573 def __repr__(self) -> str: 

3574 return f"{self.__class__.__name__}({self.arg!r})" 

3575 

3576 

3577class ScalarElementColumnDefault(ColumnDefault): 

3578 """default generator for a fixed scalar Python value 

3579 

3580 .. versionadded:: 2.0 

3581 

3582 """ 

3583 

3584 is_scalar = True 

3585 has_arg = True 

3586 

3587 def __init__(self, arg: Any, for_update: bool = False) -> None: 

3588 self.for_update = for_update 

3589 self.arg = arg 

3590 

3591 def _copy(self) -> ScalarElementColumnDefault: 

3592 return ScalarElementColumnDefault( 

3593 arg=self.arg, for_update=self.for_update 

3594 ) 

3595 

3596 

3597class _InsertSentinelColumnDefault(ColumnDefault): 

3598 """Default generator that's specific to the use of a "sentinel" column 

3599 when using the insertmanyvalues feature. 

3600 

3601 This default is used as part of the :func:`_schema.insert_sentinel` 

3602 construct. 

3603 

3604 """ 

3605 

3606 is_sentinel = True 

3607 for_update = False 

3608 arg = None 

3609 

3610 def __new__(cls) -> _InsertSentinelColumnDefault: 

3611 return object.__new__(cls) 

3612 

3613 def __init__(self) -> None: 

3614 pass 

3615 

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

3617 col = cast("Column[Any]", parent) 

3618 if not col._insert_sentinel: 

3619 raise exc.ArgumentError( 

3620 "The _InsertSentinelColumnDefault may only be applied to a " 

3621 "Column marked as insert_sentinel=True" 

3622 ) 

3623 elif not col.nullable: 

3624 raise exc.ArgumentError( 

3625 "The _InsertSentinelColumnDefault may only be applied to a " 

3626 "Column that is nullable" 

3627 ) 

3628 

3629 super()._set_parent(parent, **kw) 

3630 

3631 def _copy(self) -> _InsertSentinelColumnDefault: 

3632 return _InsertSentinelColumnDefault() 

3633 

3634 

3635_SQLExprDefault = Union["ColumnElement[Any]", "TextClause"] 

3636 

3637 

3638class ColumnElementColumnDefault(ColumnDefault): 

3639 """default generator for a SQL expression 

3640 

3641 .. versionadded:: 2.0 

3642 

3643 """ 

3644 

3645 is_clause_element = True 

3646 has_arg = True 

3647 arg: _SQLExprDefault 

3648 

3649 def __init__( 

3650 self, 

3651 arg: _SQLExprDefault, 

3652 for_update: bool = False, 

3653 ) -> None: 

3654 self.for_update = for_update 

3655 self.arg = arg 

3656 

3657 def _copy(self) -> ColumnElementColumnDefault: 

3658 return ColumnElementColumnDefault( 

3659 arg=self.arg, for_update=self.for_update 

3660 ) 

3661 

3662 @util.memoized_property 

3663 @util.preload_module("sqlalchemy.sql.sqltypes") 

3664 def _arg_is_typed(self) -> bool: 

3665 sqltypes = util.preloaded.sql_sqltypes 

3666 

3667 return not isinstance(self.arg.type, sqltypes.NullType) 

3668 

3669 

3670class _CallableColumnDefaultProtocol(Protocol): 

3671 def __call__(self, context: ExecutionContext) -> Any: ... 

3672 

3673 

3674class CallableColumnDefault(ColumnDefault): 

3675 """default generator for a callable Python function 

3676 

3677 .. versionadded:: 2.0 

3678 

3679 """ 

3680 

3681 is_callable = True 

3682 arg: _CallableColumnDefaultProtocol 

3683 has_arg = True 

3684 

3685 def __init__( 

3686 self, 

3687 arg: Union[_CallableColumnDefaultProtocol, Callable[[], Any]], 

3688 for_update: bool = False, 

3689 ) -> None: 

3690 self.for_update = for_update 

3691 self.arg = self._maybe_wrap_callable(arg) 

3692 

3693 def _copy(self) -> CallableColumnDefault: 

3694 return CallableColumnDefault(arg=self.arg, for_update=self.for_update) 

3695 

3696 def _maybe_wrap_callable( 

3697 self, fn: Union[_CallableColumnDefaultProtocol, Callable[[], Any]] 

3698 ) -> _CallableColumnDefaultProtocol: 

3699 """Wrap callables that don't accept a context. 

3700 

3701 This is to allow easy compatibility with default callables 

3702 that aren't specific to accepting of a context. 

3703 

3704 """ 

3705 

3706 try: 

3707 argspec = util.get_callable_argspec(fn, no_self=True) 

3708 except TypeError: 

3709 return util.wrap_callable(lambda ctx: fn(), fn) # type: ignore 

3710 

3711 defaulted = argspec[3] is not None and len(argspec[3]) or 0 

3712 positionals = len(argspec[0]) - defaulted 

3713 

3714 if positionals == 0: 

3715 return util.wrap_callable(lambda ctx: fn(), fn) # type: ignore 

3716 

3717 elif positionals == 1: 

3718 return fn # type: ignore 

3719 else: 

3720 raise exc.ArgumentError( 

3721 "ColumnDefault Python function takes zero or one " 

3722 "positional arguments" 

3723 ) 

3724 

3725 

3726class IdentityOptions(DialectKWArgs): 

3727 """Defines options for a named database sequence or an identity column. 

3728 

3729 .. seealso:: 

3730 

3731 :class:`.Sequence` 

3732 

3733 """ 

3734 

3735 def __init__( 

3736 self, 

3737 start: Optional[int] = None, 

3738 increment: Optional[int] = None, 

3739 minvalue: Optional[int] = None, 

3740 maxvalue: Optional[int] = None, 

3741 nominvalue: Optional[bool] = None, 

3742 nomaxvalue: Optional[bool] = None, 

3743 cycle: Optional[bool] = None, 

3744 cache: Optional[int] = None, 

3745 order: Optional[bool] = None, 

3746 **dialect_kw: Any, 

3747 ) -> None: 

3748 """Construct a :class:`.IdentityOptions` object. 

3749 

3750 See the :class:`.Sequence` documentation for a complete description 

3751 of the parameters. 

3752 

3753 :param start: the starting index of the sequence. 

3754 :param increment: the increment value of the sequence. 

3755 :param minvalue: the minimum value of the sequence. 

3756 :param maxvalue: the maximum value of the sequence. 

3757 :param nominvalue: no minimum value of the sequence. 

3758 :param nomaxvalue: no maximum value of the sequence. 

3759 :param cycle: allows the sequence to wrap around when the maxvalue 

3760 or minvalue has been reached. 

3761 :param cache: optional integer value; number of future values in the 

3762 sequence which are calculated in advance. 

3763 :param order: optional boolean value; if ``True``, renders the 

3764 ORDER keyword. 

3765 

3766 .. deprecated:: 2.1 Use ``oracle_order`` instead. 

3767 

3768 """ 

3769 self.start = start 

3770 self.increment = increment 

3771 self.minvalue = minvalue 

3772 self.maxvalue = maxvalue 

3773 self.nominvalue = nominvalue 

3774 self.nomaxvalue = nomaxvalue 

3775 self.cycle = cycle 

3776 self.cache = cache 

3777 if order is not None: 

3778 if "oracle_order" in dialect_kw: 

3779 raise exc.ArgumentError( 

3780 "Cannot specify both 'order' and 'oracle_order'. " 

3781 "Plese use only 'oracle_order'." 

3782 ) 

3783 dialect_kw["oracle_order"] = order 

3784 self._validate_dialect_kwargs(dialect_kw) 

3785 

3786 @property 

3787 def _increment_is_negative(self) -> bool: 

3788 return self.increment is not None and self.increment < 0 

3789 

3790 @property 

3791 def order(self) -> Optional[bool]: 

3792 """Alias of the ``dialect_kwargs`` ``'oracle_order'``. 

3793 

3794 .. deprecated:: 2.1 The 'order' attribute is deprecated. 

3795 """ 

3796 value: Optional[bool] = self.dialect_kwargs.get("oracle_order") 

3797 return value 

3798 

3799 def _as_dict(self) -> Dict[str, Any]: 

3800 return { 

3801 k: v 

3802 for k, v in { 

3803 "start": self.start, 

3804 "increment": self.increment, 

3805 "minvalue": self.minvalue, 

3806 "maxvalue": self.maxvalue, 

3807 "nominvalue": self.nominvalue, 

3808 "nomaxvalue": self.nomaxvalue, 

3809 "cycle": self.cycle, 

3810 "cache": self.cache, 

3811 }.items() 

3812 if v != None 

3813 } 

3814 

3815 

3816class Sequence(HasSchemaAttr, IdentityOptions, DefaultGenerator): 

3817 """Represents a named database sequence. 

3818 

3819 The :class:`.Sequence` object represents the name and configurational 

3820 parameters of a database sequence. It also represents 

3821 a construct that can be "executed" by a SQLAlchemy :class:`_engine.Engine` 

3822 or :class:`_engine.Connection`, 

3823 rendering the appropriate "next value" function 

3824 for the target database and returning a result. 

3825 

3826 The :class:`.Sequence` is typically associated with a primary key column:: 

3827 

3828 some_table = Table( 

3829 "some_table", 

3830 metadata, 

3831 Column( 

3832 "id", 

3833 Integer, 

3834 Sequence("some_table_seq", start=1), 

3835 primary_key=True, 

3836 ), 

3837 ) 

3838 

3839 When CREATE TABLE is emitted for the above :class:`_schema.Table`, if the 

3840 target platform supports sequences, a CREATE SEQUENCE statement will 

3841 be emitted as well. For platforms that don't support sequences, 

3842 the :class:`.Sequence` construct is ignored. 

3843 

3844 .. seealso:: 

3845 

3846 :ref:`defaults_sequences` 

3847 

3848 :class:`.CreateSequence` 

3849 

3850 :class:`.DropSequence` 

3851 

3852 """ 

3853 

3854 __visit_name__ = "sequence" 

3855 

3856 is_sequence = True 

3857 

3858 column: Optional[Column[Any]] 

3859 data_type: Optional[TypeEngine[int]] 

3860 

3861 metadata: Optional[MetaData] 

3862 

3863 @util.deprecated_params( 

3864 order=( 

3865 "2.1", 

3866 "This parameter is supported only by Oracle Database, " 

3867 "use ``oracle_order`` instead.", 

3868 ) 

3869 ) 

3870 def __init__( 

3871 self, 

3872 name: str, 

3873 start: Optional[int] = None, 

3874 increment: Optional[int] = None, 

3875 minvalue: Optional[int] = None, 

3876 maxvalue: Optional[int] = None, 

3877 nominvalue: Optional[bool] = None, 

3878 nomaxvalue: Optional[bool] = None, 

3879 cycle: Optional[bool] = None, 

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

3881 cache: Optional[int] = None, 

3882 order: Optional[bool] = None, 

3883 data_type: Optional[_TypeEngineArgument[int]] = None, 

3884 optional: bool = False, 

3885 quote: Optional[bool] = None, 

3886 metadata: Optional[MetaData] = None, 

3887 quote_schema: Optional[bool] = None, 

3888 for_update: bool = False, 

3889 **dialect_kw: Any, 

3890 ) -> None: 

3891 """Construct a :class:`.Sequence` object. 

3892 

3893 :param name: the name of the sequence. 

3894 

3895 :param start: the starting index of the sequence. This value is 

3896 used when the CREATE SEQUENCE command is emitted to the database 

3897 as the value of the "START WITH" clause. If ``None``, the 

3898 clause is omitted, which on most platforms indicates a starting 

3899 value of 1. 

3900 

3901 .. versionchanged:: 2.0 The :paramref:`.Sequence.start` parameter 

3902 is required in order to have DDL emit "START WITH". This is a 

3903 reversal of a change made in version 1.4 which would implicitly 

3904 render "START WITH 1" if the :paramref:`.Sequence.start` were 

3905 not included. See :ref:`change_7211` for more detail. 

3906 

3907 :param increment: the increment value of the sequence. This 

3908 value is used when the CREATE SEQUENCE command is emitted to 

3909 the database as the value of the "INCREMENT BY" clause. If ``None``, 

3910 the clause is omitted, which on most platforms indicates an 

3911 increment of 1. 

3912 :param minvalue: the minimum value of the sequence. This 

3913 value is used when the CREATE SEQUENCE command is emitted to 

3914 the database as the value of the "MINVALUE" clause. If ``None``, 

3915 the clause is omitted, which on most platforms indicates a 

3916 minvalue of 1 and -2^63-1 for ascending and descending sequences, 

3917 respectively. 

3918 

3919 :param maxvalue: the maximum value of the sequence. This 

3920 value is used when the CREATE SEQUENCE command is emitted to 

3921 the database as the value of the "MAXVALUE" clause. If ``None``, 

3922 the clause is omitted, which on most platforms indicates a 

3923 maxvalue of 2^63-1 and -1 for ascending and descending sequences, 

3924 respectively. 

3925 

3926 :param nominvalue: no minimum value of the sequence. This 

3927 value is used when the CREATE SEQUENCE command is emitted to 

3928 the database as the value of the "NO MINVALUE" clause. If ``None``, 

3929 the clause is omitted, which on most platforms indicates a 

3930 minvalue of 1 and -2^63-1 for ascending and descending sequences, 

3931 respectively. 

3932 

3933 :param nomaxvalue: no maximum value of the sequence. This 

3934 value is used when the CREATE SEQUENCE command is emitted to 

3935 the database as the value of the "NO MAXVALUE" clause. If ``None``, 

3936 the clause is omitted, which on most platforms indicates a 

3937 maxvalue of 2^63-1 and -1 for ascending and descending sequences, 

3938 respectively. 

3939 

3940 :param cycle: allows the sequence to wrap around when the maxvalue 

3941 or minvalue has been reached by an ascending or descending sequence 

3942 respectively. This value is used when the CREATE SEQUENCE command 

3943 is emitted to the database as the "CYCLE" clause. If the limit is 

3944 reached, the next number generated will be the minvalue or maxvalue, 

3945 respectively. If cycle=False (the default) any calls to nextval 

3946 after the sequence has reached its maximum value will return an 

3947 error. 

3948 

3949 :param schema: optional schema name for the sequence, if located 

3950 in a schema other than the default. The rules for selecting the 

3951 schema name when a :class:`_schema.MetaData` 

3952 is also present are the same 

3953 as that of :paramref:`_schema.Table.schema`. 

3954 

3955 :param cache: optional integer value; number of future values in the 

3956 sequence which are calculated in advance. Renders the CACHE keyword 

3957 understood by Oracle Database and PostgreSQL. 

3958 

3959 :param order: optional boolean value; if ``True``, renders the 

3960 ORDER keyword, understood by Oracle Database, indicating the sequence 

3961 is definitively ordered. May be necessary to provide deterministic 

3962 ordering using Oracle RAC. 

3963 

3964 :param data_type: The type to be returned by the sequence, for 

3965 dialects that allow us to choose between INTEGER, BIGINT, etc. 

3966 (e.g., mssql). 

3967 

3968 .. versionadded:: 1.4.0 

3969 

3970 :param optional: boolean value, when ``True``, indicates that this 

3971 :class:`.Sequence` object only needs to be explicitly generated 

3972 on backends that don't provide another way to generate primary 

3973 key identifiers. Currently, it essentially means, "don't create 

3974 this sequence on the PostgreSQL backend, where the SERIAL keyword 

3975 creates a sequence for us automatically". 

3976 :param quote: boolean value, when ``True`` or ``False``, explicitly 

3977 forces quoting of the :paramref:`_schema.Sequence.name` on or off. 

3978 When left at its default of ``None``, normal quoting rules based 

3979 on casing and reserved words take place. 

3980 :param quote_schema: Set the quoting preferences for the ``schema`` 

3981 name. 

3982 

3983 :param metadata: optional :class:`_schema.MetaData` object which this 

3984 :class:`.Sequence` will be associated with. A :class:`.Sequence` 

3985 that is associated with a :class:`_schema.MetaData` 

3986 gains the following 

3987 capabilities: 

3988 

3989 * The :class:`.Sequence` will inherit the 

3990 :paramref:`_schema.MetaData.schema` 

3991 parameter specified to the target :class:`_schema.MetaData`, which 

3992 affects the production of CREATE / DROP DDL, if any. 

3993 

3994 * The :meth:`.Sequence.create` and :meth:`.Sequence.drop` methods 

3995 automatically use the engine bound to the :class:`_schema.MetaData` 

3996 object, if any. 

3997 

3998 * The :meth:`_schema.MetaData.create_all` and 

3999 :meth:`_schema.MetaData.drop_all` 

4000 methods will emit CREATE / DROP for this :class:`.Sequence`, 

4001 even if the :class:`.Sequence` is not associated with any 

4002 :class:`_schema.Table` / :class:`_schema.Column` 

4003 that's a member of this 

4004 :class:`_schema.MetaData`. 

4005 

4006 The above behaviors can only occur if the :class:`.Sequence` is 

4007 explicitly associated with the :class:`_schema.MetaData` 

4008 via this parameter. 

4009 

4010 .. seealso:: 

4011 

4012 :ref:`sequence_metadata` - full discussion of the 

4013 :paramref:`.Sequence.metadata` parameter. 

4014 

4015 :param for_update: Indicates this :class:`.Sequence`, when associated 

4016 with a :class:`_schema.Column`, 

4017 should be invoked for UPDATE statements 

4018 on that column's table, rather than for INSERT statements, when 

4019 no value is otherwise present for that column in the statement. 

4020 

4021 """ 

4022 DefaultGenerator.__init__(self, for_update=for_update) 

4023 IdentityOptions.__init__( 

4024 self, 

4025 start=start, 

4026 increment=increment, 

4027 minvalue=minvalue, 

4028 maxvalue=maxvalue, 

4029 nominvalue=nominvalue, 

4030 nomaxvalue=nomaxvalue, 

4031 cycle=cycle, 

4032 cache=cache, 

4033 order=order, 

4034 **dialect_kw, 

4035 ) 

4036 self.column = None 

4037 self.name = quoted_name(name, quote) 

4038 self.optional = optional 

4039 if schema is BLANK_SCHEMA: 

4040 self.schema = schema = None 

4041 elif metadata is not None and schema is None and metadata.schema: 

4042 self.schema = schema = metadata.schema 

4043 else: 

4044 self.schema = quoted_name.construct(schema, quote_schema) 

4045 self._key = _get_table_key(name, schema) 

4046 if data_type is not None: 

4047 self.data_type = to_instance(data_type) 

4048 else: 

4049 self.data_type = None 

4050 

4051 if metadata: 

4052 self._set_metadata(metadata) 

4053 else: 

4054 self.metadata = None 

4055 

4056 @util.preload_module("sqlalchemy.sql.functions") 

4057 def next_value(self) -> Function[int]: 

4058 """Return a :class:`.next_value` function element 

4059 which will render the appropriate increment function 

4060 for this :class:`.Sequence` within any SQL expression. 

4061 

4062 """ 

4063 return util.preloaded.sql_functions.func.next_value(self) 

4064 

4065 def _copy(self) -> Sequence: 

4066 return Sequence( 

4067 name=self.name, 

4068 schema=self.schema, 

4069 data_type=self.data_type, 

4070 optional=self.optional, 

4071 metadata=self.metadata, 

4072 for_update=self.for_update, 

4073 **self._as_dict(), 

4074 **self.dialect_kwargs, 

4075 ) 

4076 

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

4078 assert isinstance(parent, Column) 

4079 super()._set_parent(parent, **kw) 

4080 parent._on_table_attach(self._set_table) 

4081 

4082 def _set_table(self, column: Column[Any], table: Table) -> None: 

4083 self._set_metadata(table.metadata) 

4084 

4085 def _set_metadata(self, metadata: MetaData) -> None: 

4086 self.metadata = metadata 

4087 self.metadata._register_object(self) 

4088 metadata._sequences[self._key] = self 

4089 

4090 def create( 

4091 self, 

4092 bind: _CreateDropBind, 

4093 checkfirst: Union[bool, CheckFirst] = CheckFirst.SEQUENCES, 

4094 ) -> None: 

4095 """Creates this sequence in the database.""" 

4096 

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

4098 

4099 def drop( 

4100 self, 

4101 bind: _CreateDropBind, 

4102 checkfirst: Union[bool, CheckFirst] = CheckFirst.SEQUENCES, 

4103 ) -> None: 

4104 """Drops this sequence from the database.""" 

4105 

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

4107 

4108 def _not_a_column_expr(self) -> NoReturn: 

4109 raise exc.InvalidRequestError( 

4110 f"This {self.__class__.__name__} cannot be used directly " 

4111 "as a column expression. Use func.next_value(sequence) " 

4112 "to produce a 'next value' function that's usable " 

4113 "as a column element." 

4114 ) 

4115 

4116 

4117@inspection._self_inspects 

4118class FetchedValue(SchemaEventTarget): 

4119 """A marker for a transparent database-side default. 

4120 

4121 Use :class:`.FetchedValue` when the database is configured 

4122 to provide some automatic default for a column. 

4123 

4124 E.g.:: 

4125 

4126 Column("foo", Integer, FetchedValue()) 

4127 

4128 Would indicate that some trigger or default generator 

4129 will create a new value for the ``foo`` column during an 

4130 INSERT. 

4131 

4132 .. seealso:: 

4133 

4134 :ref:`triggered_columns` 

4135 

4136 """ 

4137 

4138 is_server_default = True 

4139 reflected = False 

4140 has_argument = False 

4141 is_clause_element = False 

4142 is_identity = False 

4143 

4144 column: Optional[Column[Any]] 

4145 

4146 def __init__(self, for_update: bool = False) -> None: 

4147 self.for_update = for_update 

4148 

4149 def _as_for_update(self, for_update: bool) -> FetchedValue: 

4150 if for_update == self.for_update: 

4151 return self 

4152 else: 

4153 return self._clone(for_update) 

4154 

4155 def _copy(self) -> FetchedValue: 

4156 return FetchedValue(self.for_update) 

4157 

4158 def _clone(self, for_update: bool) -> Self: 

4159 n = self.__class__.__new__(self.__class__) 

4160 n.__dict__.update(self.__dict__) 

4161 n.__dict__.pop("column", None) 

4162 n.for_update = for_update 

4163 return n 

4164 

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

4166 column = parent 

4167 assert isinstance(column, Column) 

4168 self.column = column 

4169 if self.for_update: 

4170 self.column.server_onupdate = self 

4171 else: 

4172 self.column.server_default = self 

4173 

4174 def __repr__(self) -> str: 

4175 return util.generic_repr(self) 

4176 

4177 

4178class DefaultClause(FetchedValue): 

4179 """A DDL-specified DEFAULT column value. 

4180 

4181 :class:`.DefaultClause` is a :class:`.FetchedValue` 

4182 that also generates a "DEFAULT" clause when 

4183 "CREATE TABLE" is emitted. 

4184 

4185 :class:`.DefaultClause` is generated automatically 

4186 whenever the ``server_default``, ``server_onupdate`` arguments of 

4187 :class:`_schema.Column` are used. A :class:`.DefaultClause` 

4188 can be passed positionally as well. 

4189 

4190 For example, the following:: 

4191 

4192 Column("foo", Integer, server_default="50") 

4193 

4194 Is equivalent to:: 

4195 

4196 Column("foo", Integer, DefaultClause("50")) 

4197 

4198 """ 

4199 

4200 has_argument = True 

4201 

4202 def __init__( 

4203 self, 

4204 arg: Union[str, ClauseElement, TextClause], 

4205 for_update: bool = False, 

4206 _reflected: bool = False, 

4207 ) -> None: 

4208 util.assert_arg_type(arg, (str, ClauseElement, TextClause), "arg") 

4209 super().__init__(for_update) 

4210 self.arg = arg 

4211 self.reflected = _reflected 

4212 

4213 def _copy(self) -> DefaultClause: 

4214 return DefaultClause( 

4215 arg=self.arg, for_update=self.for_update, _reflected=self.reflected 

4216 ) 

4217 

4218 def __repr__(self) -> str: 

4219 return "DefaultClause(%r, for_update=%r)" % (self.arg, self.for_update) 

4220 

4221 

4222class Constraint(DialectKWArgs, HasConditionalDDL, SchemaItem): 

4223 """A table-level SQL constraint. 

4224 

4225 :class:`_schema.Constraint` serves as the base class for the series of 

4226 constraint objects that can be associated with :class:`_schema.Table` 

4227 objects, including :class:`_schema.PrimaryKeyConstraint`, 

4228 :class:`_schema.ForeignKeyConstraint` 

4229 :class:`_schema.UniqueConstraint`, and 

4230 :class:`_schema.CheckConstraint`. 

4231 

4232 """ 

4233 

4234 __visit_name__ = "constraint" 

4235 

4236 _creation_order: int 

4237 _column_flag: bool 

4238 

4239 def __init__( 

4240 self, 

4241 name: _ConstraintNameArgument = None, 

4242 deferrable: Optional[bool] = None, 

4243 initially: Optional[str] = None, 

4244 info: Optional[_InfoType] = None, 

4245 comment: Optional[str] = None, 

4246 _create_rule: Optional[Any] = None, 

4247 _type_bound: bool = False, 

4248 **dialect_kw: Any, 

4249 ) -> None: 

4250 r"""Create a SQL constraint. 

4251 

4252 :param name: 

4253 Optional, the in-database name of this ``Constraint``. 

4254 

4255 :param deferrable: 

4256 Optional bool. If set, emit DEFERRABLE or NOT DEFERRABLE when 

4257 issuing DDL for this constraint. 

4258 

4259 :param initially: 

4260 Optional string. If set, emit INITIALLY <value> when issuing DDL 

4261 for this constraint. 

4262 

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

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

4265 

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

4267 foreign key constraint creation. 

4268 

4269 .. versionadded:: 2.0 

4270 

4271 :param \**dialect_kw: Additional keyword arguments are dialect 

4272 specific, and passed in the form ``<dialectname>_<argname>``. See 

4273 the documentation regarding an individual dialect at 

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

4275 

4276 :param _create_rule: 

4277 used internally by some datatypes that also create constraints. 

4278 

4279 :param _type_bound: 

4280 used internally to indicate that this constraint is associated with 

4281 a specific datatype. 

4282 

4283 """ 

4284 

4285 self.name = name 

4286 self.deferrable = deferrable 

4287 self.initially = initially 

4288 if info: 

4289 self.info = info 

4290 self._create_rule = _create_rule 

4291 self._type_bound = _type_bound 

4292 util.set_creation_order(self) 

4293 self._validate_dialect_kwargs(dialect_kw) 

4294 self.comment = comment 

4295 

4296 def _should_create_for_compiler( 

4297 self, compiler: DDLCompiler, **kw: Any 

4298 ) -> bool: 

4299 if self._create_rule is not None and not self._create_rule(compiler): 

4300 return False 

4301 elif self._ddl_if is not None: 

4302 return self._ddl_if._should_execute( 

4303 ddl.CreateConstraint(self), self, None, compiler=compiler, **kw 

4304 ) 

4305 else: 

4306 return True 

4307 

4308 @property 

4309 def table(self) -> Table: 

4310 try: 

4311 if isinstance(self.parent, Table): 

4312 return self.parent 

4313 except AttributeError: 

4314 pass 

4315 raise exc.InvalidRequestError( 

4316 "This constraint is not bound to a table. Did you " 

4317 "mean to call table.append_constraint(constraint) ?" 

4318 ) 

4319 

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

4321 assert isinstance(parent, (Table, Column)) 

4322 self.parent = parent 

4323 parent.constraints.add(self) 

4324 

4325 @util.deprecated( 

4326 "1.4", 

4327 "The :meth:`_schema.Constraint.copy` method is deprecated " 

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

4329 ) 

4330 def copy(self, **kw: Any) -> Self: 

4331 return self._copy(**kw) 

4332 

4333 def _copy(self, **kw: Any) -> Self: 

4334 raise NotImplementedError() 

4335 

4336 

4337class ColumnCollectionMixin: 

4338 """A :class:`_expression.ColumnCollection` of :class:`_schema.Column` 

4339 objects. 

4340 

4341 This collection represents the columns which are referred to by 

4342 this object. 

4343 

4344 """ 

4345 

4346 _columns: DedupeColumnCollection[Column[Any]] 

4347 

4348 _allow_multiple_tables = False 

4349 

4350 _pending_colargs: List[Optional[Union[str, Column[Any]]]] 

4351 

4352 if TYPE_CHECKING: 

4353 

4354 def _set_parent_with_dispatch( 

4355 self, parent: SchemaEventTarget, **kw: Any 

4356 ) -> None: ... 

4357 

4358 def __init__( 

4359 self, 

4360 *columns: _DDLColumnArgument, 

4361 _autoattach: bool = True, 

4362 _column_flag: bool = False, 

4363 _gather_expressions: Optional[ 

4364 List[Union[str, ColumnElement[Any]]] 

4365 ] = None, 

4366 ) -> None: 

4367 self._column_flag = _column_flag 

4368 self._columns = DedupeColumnCollection() 

4369 

4370 processed_expressions: Optional[ 

4371 List[Union[ColumnElement[Any], str]] 

4372 ] = _gather_expressions 

4373 

4374 if processed_expressions is not None: 

4375 

4376 # this is expected to be an empty list 

4377 assert not processed_expressions 

4378 

4379 self._pending_colargs = [] 

4380 for ( 

4381 expr, 

4382 _, 

4383 _, 

4384 add_element, 

4385 ) in coercions.expect_col_expression_collection( 

4386 roles.DDLConstraintColumnRole, columns 

4387 ): 

4388 self._pending_colargs.append(add_element) 

4389 processed_expressions.append(expr) 

4390 else: 

4391 self._pending_colargs = [ 

4392 coercions.expect(roles.DDLConstraintColumnRole, column) 

4393 for column in columns 

4394 ] 

4395 

4396 if _autoattach and self._pending_colargs: 

4397 self._check_attach() 

4398 

4399 def _check_attach(self, evt: bool = False) -> None: 

4400 col_objs = [c for c in self._pending_colargs if isinstance(c, Column)] 

4401 

4402 cols_w_table = [c for c in col_objs if isinstance(c.table, Table)] 

4403 

4404 cols_wo_table = set(col_objs).difference(cols_w_table) 

4405 if cols_wo_table: 

4406 # feature #3341 - place event listeners for Column objects 

4407 # such that when all those cols are attached, we autoattach. 

4408 assert not evt, "Should not reach here on event call" 

4409 

4410 # issue #3411 - don't do the per-column auto-attach if some of the 

4411 # columns are specified as strings. 

4412 has_string_cols = { 

4413 c for c in self._pending_colargs if c is not None 

4414 }.difference(col_objs) 

4415 if not has_string_cols: 

4416 

4417 def _col_attached(column: Column[Any], table: Table) -> None: 

4418 # this isinstance() corresponds with the 

4419 # isinstance() above; only want to count Table-bound 

4420 # columns 

4421 if isinstance(table, Table): 

4422 cols_wo_table.discard(column) 

4423 if not cols_wo_table: 

4424 self._check_attach(evt=True) 

4425 

4426 self._cols_wo_table = cols_wo_table 

4427 for col in cols_wo_table: 

4428 col._on_table_attach(_col_attached) 

4429 return 

4430 

4431 columns = cols_w_table 

4432 

4433 tables = {c.table for c in columns} 

4434 if len(tables) == 1: 

4435 self._set_parent_with_dispatch(tables.pop()) 

4436 elif len(tables) > 1 and not self._allow_multiple_tables: 

4437 table = columns[0].table 

4438 others = [c for c in columns[1:] if c.table is not table] 

4439 if others: 

4440 # black could not format this inline 

4441 other_str = ", ".join("'%s'" % c for c in others) 

4442 raise exc.ArgumentError( 

4443 f"Column(s) {other_str} " 

4444 f"are not part of table '{table.description}'." 

4445 ) 

4446 

4447 @util.ro_memoized_property 

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

4449 return self._columns.as_readonly() 

4450 

4451 @util.ro_memoized_property 

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

4453 return self._columns.as_readonly() 

4454 

4455 def _col_expressions( 

4456 self, parent: Union[Table, Column[Any]] 

4457 ) -> List[Optional[Column[Any]]]: 

4458 if isinstance(parent, Column): 

4459 result: List[Optional[Column[Any]]] = [ 

4460 c for c in self._pending_colargs if isinstance(c, Column) 

4461 ] 

4462 assert len(result) == len(self._pending_colargs) 

4463 return result 

4464 else: 

4465 try: 

4466 return [ 

4467 parent.c[col] if isinstance(col, str) else col 

4468 for col in self._pending_colargs 

4469 ] 

4470 except KeyError as ke: 

4471 raise exc.ConstraintColumnNotFoundError( 

4472 f"Can't create {self.__class__.__name__} " 

4473 f"on table '{parent.description}': no column " 

4474 f"named '{ke.args[0]}' is present." 

4475 ) from ke 

4476 

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

4478 assert isinstance(parent, (Table, Column)) 

4479 

4480 for col in self._col_expressions(parent): 

4481 if col is not None: 

4482 self._columns.add(col) 

4483 

4484 

4485class ColumnCollectionConstraint(ColumnCollectionMixin, Constraint): 

4486 """A constraint that proxies a ColumnCollection.""" 

4487 

4488 def __init__( 

4489 self, 

4490 *columns: _DDLColumnArgument, 

4491 name: _ConstraintNameArgument = None, 

4492 deferrable: Optional[bool] = None, 

4493 initially: Optional[str] = None, 

4494 info: Optional[_InfoType] = None, 

4495 _autoattach: bool = True, 

4496 _column_flag: bool = False, 

4497 _gather_expressions: Optional[List[_DDLColumnArgument]] = None, 

4498 **dialect_kw: Any, 

4499 ) -> None: 

4500 r""" 

4501 :param \*columns: 

4502 A sequence of column names or Column objects. 

4503 

4504 :param name: 

4505 Optional, the in-database name of this constraint. 

4506 

4507 :param deferrable: 

4508 Optional bool. If set, emit DEFERRABLE or NOT DEFERRABLE when 

4509 issuing DDL for this constraint. 

4510 

4511 :param initially: 

4512 Optional string. If set, emit INITIALLY <value> when issuing DDL 

4513 for this constraint. 

4514 

4515 :param \**dialect_kw: other keyword arguments including 

4516 dialect-specific arguments are propagated to the :class:`.Constraint` 

4517 superclass. 

4518 

4519 """ 

4520 Constraint.__init__( 

4521 self, 

4522 name=name, 

4523 deferrable=deferrable, 

4524 initially=initially, 

4525 info=info, 

4526 **dialect_kw, 

4527 ) 

4528 ColumnCollectionMixin.__init__( 

4529 self, *columns, _autoattach=_autoattach, _column_flag=_column_flag 

4530 ) 

4531 

4532 columns: ReadOnlyColumnCollection[str, Column[Any]] 

4533 """A :class:`_expression.ColumnCollection` representing the set of columns 

4534 for this constraint. 

4535 

4536 """ 

4537 

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

4539 assert isinstance(parent, (Column, Table)) 

4540 Constraint._set_parent(self, parent) 

4541 ColumnCollectionMixin._set_parent(self, parent) 

4542 

4543 def __contains__(self, x: Any) -> bool: 

4544 return x in self._columns 

4545 

4546 @util.deprecated( 

4547 "1.4", 

4548 "The :meth:`_schema.ColumnCollectionConstraint.copy` method " 

4549 "is deprecated and will be removed in a future release.", 

4550 ) 

4551 def copy( 

4552 self, 

4553 *, 

4554 target_table: Optional[Table] = None, 

4555 **kw: Any, 

4556 ) -> ColumnCollectionConstraint: 

4557 return self._copy(target_table=target_table, **kw) 

4558 

4559 def _copy( 

4560 self, 

4561 *, 

4562 target_table: Optional[Table] = None, 

4563 **kw: Any, 

4564 ) -> ColumnCollectionConstraint: 

4565 # ticket #5276 

4566 constraint_kwargs = {} 

4567 for dialect_name in self.dialect_options: 

4568 dialect_options = self.dialect_options[dialect_name]._non_defaults 

4569 for ( 

4570 dialect_option_key, 

4571 dialect_option_value, 

4572 ) in dialect_options.items(): 

4573 constraint_kwargs[dialect_name + "_" + dialect_option_key] = ( 

4574 dialect_option_value 

4575 ) 

4576 

4577 assert isinstance(self.parent, Table) 

4578 c = self.__class__( 

4579 name=self.name, 

4580 deferrable=self.deferrable, 

4581 initially=self.initially, 

4582 *[ 

4583 _copy_expression(expr, self.parent, target_table) 

4584 for expr in self._columns 

4585 ], 

4586 comment=self.comment, 

4587 **constraint_kwargs, 

4588 ) 

4589 return self._schema_item_copy(c) 

4590 

4591 def contains_column(self, col: Column[Any]) -> bool: 

4592 """Return True if this constraint contains the given column. 

4593 

4594 Note that this object also contains an attribute ``.columns`` 

4595 which is a :class:`_expression.ColumnCollection` of 

4596 :class:`_schema.Column` objects. 

4597 

4598 """ 

4599 

4600 return self._columns.contains_column(col) 

4601 

4602 def __iter__(self) -> Iterator[Column[Any]]: 

4603 return iter(self._columns) 

4604 

4605 def __len__(self) -> int: 

4606 return len(self._columns) 

4607 

4608 

4609class CheckConstraint(ColumnCollectionConstraint): 

4610 """A table- or column-level CHECK constraint. 

4611 

4612 Can be included in the definition of a Table or Column. 

4613 """ 

4614 

4615 _allow_multiple_tables = True 

4616 

4617 __visit_name__ = "table_or_column_check_constraint" 

4618 

4619 @_document_text_coercion( 

4620 "sqltext", 

4621 ":class:`.CheckConstraint`", 

4622 ":paramref:`.CheckConstraint.sqltext`", 

4623 ) 

4624 def __init__( 

4625 self, 

4626 sqltext: _TextCoercedExpressionArgument[Any], 

4627 name: _ConstraintNameArgument = None, 

4628 deferrable: Optional[bool] = None, 

4629 initially: Optional[str] = None, 

4630 table: Optional[Table] = None, 

4631 info: Optional[_InfoType] = None, 

4632 _create_rule: Optional[Any] = None, 

4633 _autoattach: bool = True, 

4634 _type_bound: bool = False, 

4635 **dialect_kw: Any, 

4636 ) -> None: 

4637 r"""Construct a CHECK constraint. 

4638 

4639 :param sqltext: 

4640 A string containing the constraint definition, which will be used 

4641 verbatim, or a SQL expression construct. If given as a string, 

4642 the object is converted to a :func:`_expression.text` object. 

4643 If the textual 

4644 string includes a colon character, escape this using a backslash:: 

4645 

4646 CheckConstraint(r"foo ~ E'a(?\:b|c)d") 

4647 

4648 :param name: 

4649 Optional, the in-database name of the constraint. 

4650 

4651 :param deferrable: 

4652 Optional bool. If set, emit DEFERRABLE or NOT DEFERRABLE when 

4653 issuing DDL for this constraint. 

4654 

4655 :param initially: 

4656 Optional string. If set, emit INITIALLY <value> when issuing DDL 

4657 for this constraint. 

4658 

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

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

4661 

4662 """ 

4663 

4664 self.sqltext = coercions.expect(roles.DDLExpressionRole, sqltext) 

4665 columns: List[Column[Any]] = [] 

4666 visitors.traverse(self.sqltext, {}, {"column": columns.append}) 

4667 

4668 super().__init__( 

4669 name=name, 

4670 deferrable=deferrable, 

4671 initially=initially, 

4672 _create_rule=_create_rule, 

4673 info=info, 

4674 _type_bound=_type_bound, 

4675 _autoattach=_autoattach, 

4676 *columns, 

4677 **dialect_kw, 

4678 ) 

4679 if table is not None: 

4680 self._set_parent_with_dispatch(table) 

4681 

4682 @property 

4683 def is_column_level(self) -> bool: 

4684 return not isinstance(self.parent, Table) 

4685 

4686 @util.deprecated( 

4687 "1.4", 

4688 "The :meth:`_schema.CheckConstraint.copy` method is deprecated " 

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

4690 ) 

4691 def copy( 

4692 self, *, target_table: Optional[Table] = None, **kw: Any 

4693 ) -> CheckConstraint: 

4694 return self._copy(target_table=target_table, **kw) 

4695 

4696 def _copy( 

4697 self, *, target_table: Optional[Table] = None, **kw: Any 

4698 ) -> CheckConstraint: 

4699 if target_table is not None: 

4700 # note that target_table is None for the copy process of 

4701 # a column-bound CheckConstraint, so this path is not reached 

4702 # in that case. 

4703 sqltext = _copy_expression(self.sqltext, self.table, target_table) 

4704 else: 

4705 sqltext = self.sqltext 

4706 c = CheckConstraint( 

4707 sqltext, 

4708 name=self.name, 

4709 initially=self.initially, 

4710 deferrable=self.deferrable, 

4711 _create_rule=self._create_rule, 

4712 table=target_table, 

4713 comment=self.comment, 

4714 _autoattach=False, 

4715 _type_bound=self._type_bound, 

4716 ) 

4717 return self._schema_item_copy(c) 

4718 

4719 

4720class ForeignKeyConstraint(ColumnCollectionConstraint): 

4721 """A table-level FOREIGN KEY constraint. 

4722 

4723 Defines a single column or composite FOREIGN KEY ... REFERENCES 

4724 constraint. For a no-frills, single column foreign key, adding a 

4725 :class:`_schema.ForeignKey` to the definition of a :class:`_schema.Column` 

4726 is a 

4727 shorthand equivalent for an unnamed, single column 

4728 :class:`_schema.ForeignKeyConstraint`. 

4729 

4730 Examples of foreign key configuration are in :ref:`metadata_foreignkeys`. 

4731 

4732 """ 

4733 

4734 __visit_name__ = "foreign_key_constraint" 

4735 

4736 def __init__( 

4737 self, 

4738 columns: _typing_Sequence[_DDLColumnArgument], 

4739 refcolumns: _typing_Sequence[_DDLColumnReferenceArgument], 

4740 name: _ConstraintNameArgument = None, 

4741 onupdate: Optional[str] = None, 

4742 ondelete: Optional[str] = None, 

4743 deferrable: Optional[bool] = None, 

4744 initially: Optional[str] = None, 

4745 use_alter: bool = False, 

4746 link_to_name: bool = False, 

4747 match: Optional[str] = None, 

4748 table: Optional[Table] = None, 

4749 info: Optional[_InfoType] = None, 

4750 comment: Optional[str] = None, 

4751 **dialect_kw: Any, 

4752 ) -> None: 

4753 r"""Construct a composite-capable FOREIGN KEY. 

4754 

4755 :param columns: A sequence of local column names. The named columns 

4756 must be defined and present in the parent Table. The names should 

4757 match the ``key`` given to each column (defaults to the name) unless 

4758 ``link_to_name`` is True. 

4759 

4760 :param refcolumns: A sequence of foreign column names or Column 

4761 objects. The columns must all be located within the same Table. 

4762 

4763 :param name: Optional, the in-database name of the key. 

4764 

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

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

4767 DELETE and RESTRICT. 

4768 

4769 .. seealso:: 

4770 

4771 :ref:`on_update_on_delete` 

4772 

4773 :param ondelete: Optional string. If set, emit ON DELETE <value> when 

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

4775 SET NULL and RESTRICT. Some dialects may allow for additional 

4776 syntaxes. 

4777 

4778 .. seealso:: 

4779 

4780 :ref:`on_update_on_delete` 

4781 

4782 :param deferrable: Optional bool. If set, emit DEFERRABLE or NOT 

4783 DEFERRABLE when issuing DDL for this constraint. 

4784 

4785 :param initially: Optional string. If set, emit INITIALLY <value> when 

4786 issuing DDL for this constraint. 

4787 

4788 :param link_to_name: if True, the string name given in ``column`` is 

4789 the rendered name of the referenced column, not its locally assigned 

4790 ``key``. 

4791 

4792 :param use_alter: If True, do not emit the DDL for this constraint as 

4793 part of the CREATE TABLE definition. Instead, generate it via an 

4794 ALTER TABLE statement issued after the full collection of tables 

4795 have been created, and drop it via an ALTER TABLE statement before 

4796 the full collection of tables are dropped. 

4797 

4798 The use of :paramref:`_schema.ForeignKeyConstraint.use_alter` is 

4799 particularly geared towards the case where two or more tables 

4800 are established within a mutually-dependent foreign key constraint 

4801 relationship; however, the :meth:`_schema.MetaData.create_all` and 

4802 :meth:`_schema.MetaData.drop_all` 

4803 methods will perform this resolution 

4804 automatically, so the flag is normally not needed. 

4805 

4806 .. seealso:: 

4807 

4808 :ref:`use_alter` 

4809 

4810 :param match: Optional string. If set, emit MATCH <value> when issuing 

4811 DDL for this constraint. Typical values include SIMPLE, PARTIAL 

4812 and FULL. 

4813 

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

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

4816 

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

4818 foreign key constraint creation. 

4819 

4820 .. versionadded:: 2.0 

4821 

4822 :param \**dialect_kw: Additional keyword arguments are dialect 

4823 specific, and passed in the form ``<dialectname>_<argname>``. See 

4824 the documentation regarding an individual dialect at 

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

4826 

4827 """ 

4828 

4829 Constraint.__init__( 

4830 self, 

4831 name=name, 

4832 deferrable=deferrable, 

4833 initially=initially, 

4834 info=info, 

4835 comment=comment, 

4836 **dialect_kw, 

4837 ) 

4838 self.onupdate = onupdate 

4839 self.ondelete = ondelete 

4840 self.link_to_name = link_to_name 

4841 self.use_alter = use_alter 

4842 self.match = match 

4843 

4844 if len(set(columns)) != len(refcolumns): 

4845 if len(set(columns)) != len(columns): 

4846 # e.g. FOREIGN KEY (a, a) REFERENCES r (b, c) 

4847 raise exc.ArgumentError( 

4848 "ForeignKeyConstraint with duplicate source column " 

4849 "references are not supported." 

4850 ) 

4851 else: 

4852 # e.g. FOREIGN KEY (a) REFERENCES r (b, c) 

4853 # paraphrasing 

4854 # https://www.postgresql.org/docs/current/static/ddl-constraints.html 

4855 raise exc.ArgumentError( 

4856 "ForeignKeyConstraint number " 

4857 "of constrained columns must match the number of " 

4858 "referenced columns." 

4859 ) 

4860 

4861 # standalone ForeignKeyConstraint - create 

4862 # associated ForeignKey objects which will be applied to hosted 

4863 # Column objects (in col.foreign_keys), either now or when attached 

4864 # to the Table for string-specified names 

4865 self.elements = [ 

4866 ForeignKey( 

4867 refcol, 

4868 _constraint=self, 

4869 name=self.name, 

4870 onupdate=self.onupdate, 

4871 ondelete=self.ondelete, 

4872 use_alter=self.use_alter, 

4873 link_to_name=self.link_to_name, 

4874 match=self.match, 

4875 deferrable=self.deferrable, 

4876 initially=self.initially, 

4877 **self.dialect_kwargs, 

4878 ) 

4879 for refcol in refcolumns 

4880 ] 

4881 

4882 ColumnCollectionMixin.__init__(self, *columns) 

4883 if table is not None: 

4884 if hasattr(self, "parent"): 

4885 assert table is self.parent 

4886 self._set_parent_with_dispatch(table) 

4887 

4888 def _append_element(self, column: Column[Any], fk: ForeignKey) -> None: 

4889 self._columns.add(column) 

4890 self.elements.append(fk) 

4891 

4892 columns: ReadOnlyColumnCollection[str, Column[Any]] 

4893 """A :class:`_expression.ColumnCollection` representing the set of columns 

4894 for this constraint. 

4895 

4896 """ 

4897 

4898 elements: List[ForeignKey] 

4899 """A sequence of :class:`_schema.ForeignKey` objects. 

4900 

4901 Each :class:`_schema.ForeignKey` 

4902 represents a single referring column/referred 

4903 column pair. 

4904 

4905 This collection is intended to be read-only. 

4906 

4907 """ 

4908 

4909 @property 

4910 def _elements(self) -> util.OrderedDict[str, ForeignKey]: 

4911 # legacy - provide a dictionary view of (column_key, fk) 

4912 return util.OrderedDict(zip(self.column_keys, self.elements)) 

4913 

4914 @property 

4915 def _referred_schema(self) -> Optional[str]: 

4916 for elem in self.elements: 

4917 return elem._referred_schema 

4918 else: 

4919 return None 

4920 

4921 @property 

4922 def referred_table(self) -> Table: 

4923 """The :class:`_schema.Table` object to which this 

4924 :class:`_schema.ForeignKeyConstraint` references. 

4925 

4926 This is a dynamically calculated attribute which may not be available 

4927 if the constraint and/or parent table is not yet associated with 

4928 a metadata collection that contains the referred table. 

4929 

4930 """ 

4931 return self.elements[0].column.table 

4932 

4933 def _validate_dest_table(self, table: Table) -> None: 

4934 table_keys = { 

4935 elem._table_key_within_construction() for elem in self.elements 

4936 } 

4937 if None not in table_keys and len(table_keys) > 1: 

4938 elem0, elem1 = sorted(table_keys)[0:2] 

4939 raise exc.ArgumentError( 

4940 f"ForeignKeyConstraint on " 

4941 f"{table.fullname}({self._col_description}) refers to " 

4942 f"multiple remote tables: {elem0} and {elem1}" 

4943 ) 

4944 

4945 @property 

4946 def column_keys(self) -> _typing_Sequence[str]: 

4947 """Return a list of string keys representing the local 

4948 columns in this :class:`_schema.ForeignKeyConstraint`. 

4949 

4950 This list is either the original string arguments sent 

4951 to the constructor of the :class:`_schema.ForeignKeyConstraint`, 

4952 or if the constraint has been initialized with :class:`_schema.Column` 

4953 objects, is the string ``.key`` of each element. 

4954 

4955 """ 

4956 if hasattr(self, "parent"): 

4957 return self._columns.keys() 

4958 else: 

4959 return [ 

4960 col.key if isinstance(col, ColumnElement) else str(col) 

4961 for col in self._pending_colargs 

4962 ] 

4963 

4964 @property 

4965 def _col_description(self) -> str: 

4966 return ", ".join(self.column_keys) 

4967 

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

4969 table = parent 

4970 assert isinstance(table, Table) 

4971 Constraint._set_parent(self, table) 

4972 

4973 ColumnCollectionConstraint._set_parent(self, table) 

4974 

4975 for col, fk in zip(self._columns, self.elements): 

4976 if not hasattr(fk, "parent") or fk.parent is not col: 

4977 fk._set_parent_with_dispatch(col) 

4978 

4979 self._validate_dest_table(table) 

4980 

4981 @util.deprecated( 

4982 "1.4", 

4983 "The :meth:`_schema.ForeignKeyConstraint.copy` method is deprecated " 

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

4985 ) 

4986 def copy( 

4987 self, 

4988 *, 

4989 schema: Optional[str] = None, 

4990 target_table: Optional[Table] = None, 

4991 **kw: Any, 

4992 ) -> ForeignKeyConstraint: 

4993 return self._copy(schema=schema, target_table=target_table, **kw) 

4994 

4995 def _copy( 

4996 self, 

4997 *, 

4998 schema: Optional[str] = None, 

4999 target_table: Optional[Table] = None, 

5000 **kw: Any, 

5001 ) -> ForeignKeyConstraint: 

5002 fkc = ForeignKeyConstraint( 

5003 [x.parent.key for x in self.elements], 

5004 [ 

5005 x._get_colspec( 

5006 schema=schema, 

5007 table_name=( 

5008 target_table.name 

5009 if target_table is not None 

5010 and x._table_key_within_construction() 

5011 == x.parent.table.key 

5012 else None 

5013 ), 

5014 _is_copy=True, 

5015 ) 

5016 for x in self.elements 

5017 ], 

5018 name=self.name, 

5019 onupdate=self.onupdate, 

5020 ondelete=self.ondelete, 

5021 use_alter=self.use_alter, 

5022 deferrable=self.deferrable, 

5023 initially=self.initially, 

5024 link_to_name=self.link_to_name, 

5025 match=self.match, 

5026 comment=self.comment, 

5027 ) 

5028 for self_fk, other_fk in zip(self.elements, fkc.elements): 

5029 self_fk._schema_item_copy(other_fk) 

5030 return self._schema_item_copy(fkc) 

5031 

5032 

5033class PrimaryKeyConstraint(ColumnCollectionConstraint): 

5034 """A table-level PRIMARY KEY constraint. 

5035 

5036 The :class:`.PrimaryKeyConstraint` object is present automatically 

5037 on any :class:`_schema.Table` object; it is assigned a set of 

5038 :class:`_schema.Column` objects corresponding to those marked with 

5039 the :paramref:`_schema.Column.primary_key` flag:: 

5040 

5041 >>> my_table = Table( 

5042 ... "mytable", 

5043 ... metadata, 

5044 ... Column("id", Integer, primary_key=True), 

5045 ... Column("version_id", Integer, primary_key=True), 

5046 ... Column("data", String(50)), 

5047 ... ) 

5048 >>> my_table.primary_key 

5049 PrimaryKeyConstraint( 

5050 Column('id', Integer(), table=<mytable>, 

5051 primary_key=True, nullable=False), 

5052 Column('version_id', Integer(), table=<mytable>, 

5053 primary_key=True, nullable=False) 

5054 ) 

5055 

5056 The primary key of a :class:`_schema.Table` can also be specified by using 

5057 a :class:`.PrimaryKeyConstraint` object explicitly; in this mode of usage, 

5058 the "name" of the constraint can also be specified, as well as other 

5059 options which may be recognized by dialects:: 

5060 

5061 my_table = Table( 

5062 "mytable", 

5063 metadata, 

5064 Column("id", Integer), 

5065 Column("version_id", Integer), 

5066 Column("data", String(50)), 

5067 PrimaryKeyConstraint("id", "version_id", name="mytable_pk"), 

5068 ) 

5069 

5070 The two styles of column-specification should generally not be mixed. 

5071 An warning is emitted if the columns present in the 

5072 :class:`.PrimaryKeyConstraint` 

5073 don't match the columns that were marked as ``primary_key=True``, if both 

5074 are present; in this case, the columns are taken strictly from the 

5075 :class:`.PrimaryKeyConstraint` declaration, and those columns otherwise 

5076 marked as ``primary_key=True`` are ignored. This behavior is intended to 

5077 be backwards compatible with previous behavior. 

5078 

5079 For the use case where specific options are to be specified on the 

5080 :class:`.PrimaryKeyConstraint`, but the usual style of using 

5081 ``primary_key=True`` flags is still desirable, an empty 

5082 :class:`.PrimaryKeyConstraint` may be specified, which will take on the 

5083 primary key column collection from the :class:`_schema.Table` based on the 

5084 flags:: 

5085 

5086 my_table = Table( 

5087 "mytable", 

5088 metadata, 

5089 Column("id", Integer, primary_key=True), 

5090 Column("version_id", Integer, primary_key=True), 

5091 Column("data", String(50)), 

5092 PrimaryKeyConstraint(name="mytable_pk", mssql_clustered=True), 

5093 ) 

5094 

5095 """ 

5096 

5097 __visit_name__ = "primary_key_constraint" 

5098 

5099 def __init__( 

5100 self, 

5101 *columns: _DDLColumnArgument, 

5102 name: Optional[str] = None, 

5103 deferrable: Optional[bool] = None, 

5104 initially: Optional[str] = None, 

5105 info: Optional[_InfoType] = None, 

5106 _implicit_generated: bool = False, 

5107 **dialect_kw: Any, 

5108 ) -> None: 

5109 self._implicit_generated = _implicit_generated 

5110 super().__init__( 

5111 *columns, 

5112 name=name, 

5113 deferrable=deferrable, 

5114 initially=initially, 

5115 info=info, 

5116 **dialect_kw, 

5117 ) 

5118 

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

5120 table = parent 

5121 assert isinstance(table, Table) 

5122 super()._set_parent(table) 

5123 

5124 if table.primary_key is not self: 

5125 table.constraints.discard(table.primary_key) 

5126 table.primary_key = self # type: ignore 

5127 table.constraints.add(self) 

5128 

5129 table_pks = [c for c in table.c if c.primary_key] 

5130 if ( 

5131 self._columns 

5132 and table_pks 

5133 and set(table_pks) != set(self._columns) 

5134 ): 

5135 # black could not format these inline 

5136 table_pk_str = ", ".join("'%s'" % c.name for c in table_pks) 

5137 col_str = ", ".join("'%s'" % c.name for c in self._columns) 

5138 

5139 util.warn( 

5140 f"Table '{table.name}' specifies columns " 

5141 f"{table_pk_str} as " 

5142 f"primary_key=True, " 

5143 f"not matching locally specified columns {col_str}; " 

5144 f"setting the " 

5145 f"current primary key columns to " 

5146 f"{col_str}. " 

5147 f"This warning " 

5148 f"may become an exception in a future release" 

5149 ) 

5150 table_pks[:] = [] 

5151 

5152 for c in self._columns: 

5153 c.primary_key = True 

5154 if c._user_defined_nullable is NULL_UNSPECIFIED: 

5155 c.nullable = False 

5156 if table_pks: 

5157 self._columns.extend(table_pks) 

5158 

5159 def _reload(self, columns: Iterable[Column[Any]]) -> None: 

5160 """repopulate this :class:`.PrimaryKeyConstraint` given 

5161 a set of columns. 

5162 

5163 Existing columns in the table that are marked as primary_key=True 

5164 are maintained. 

5165 

5166 Also fires a new event. 

5167 

5168 This is basically like putting a whole new 

5169 :class:`.PrimaryKeyConstraint` object on the parent 

5170 :class:`_schema.Table` object without actually replacing the object. 

5171 

5172 The ordering of the given list of columns is also maintained; these 

5173 columns will be appended to the list of columns after any which 

5174 are already present. 

5175 

5176 """ 

5177 # set the primary key flag on new columns. 

5178 # note any existing PK cols on the table also have their 

5179 # flag still set. 

5180 for col in columns: 

5181 col.primary_key = True 

5182 

5183 self._columns.extend(columns) 

5184 

5185 PrimaryKeyConstraint._autoincrement_column._reset(self) # type: ignore 

5186 self._set_parent_with_dispatch(self.table) 

5187 

5188 def _replace(self, col: Column[Any]) -> None: 

5189 PrimaryKeyConstraint._autoincrement_column._reset(self) # type: ignore 

5190 self._columns.replace(col) 

5191 

5192 self.dispatch._sa_event_column_added_to_pk_constraint(self, col) 

5193 

5194 @property 

5195 def columns_autoinc_first(self) -> List[Column[Any]]: 

5196 autoinc = self._autoincrement_column 

5197 

5198 if autoinc is not None: 

5199 return [autoinc] + [c for c in self._columns if c is not autoinc] 

5200 else: 

5201 return list(self._columns) 

5202 

5203 @util.ro_memoized_property 

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

5205 def _validate_autoinc(col: Column[Any], autoinc_true: bool) -> bool: 

5206 if col.type._type_affinity is not None and issubclass( 

5207 col.type._type_affinity, type_api.NUMERICTYPE._type_affinity 

5208 ): 

5209 scale = col.type.scale # type: ignore[attr-defined] 

5210 if scale != 0 and autoinc_true: 

5211 raise exc.ArgumentError( 

5212 f"Column type {col.type} with non-zero scale " 

5213 f"{scale} on column '{col}' is not " 

5214 f"compatible with autoincrement=True" 

5215 ) 

5216 elif not autoinc_true: 

5217 return False 

5218 elif col.type._type_affinity is None or not issubclass( 

5219 col.type._type_affinity, type_api.INTEGERTYPE._type_affinity 

5220 ): 

5221 if autoinc_true: 

5222 raise exc.ArgumentError( 

5223 f"Column type {col.type} on column '{col}' is not " 

5224 f"compatible with autoincrement=True" 

5225 ) 

5226 else: 

5227 return False 

5228 elif ( 

5229 col.default is not None 

5230 and not isinstance(col.default, Sequence) 

5231 and not autoinc_true 

5232 ): 

5233 return False 

5234 elif ( 

5235 col.server_default is not None 

5236 and not isinstance(col.server_default, Identity) 

5237 and not autoinc_true 

5238 ): 

5239 return False 

5240 elif col.foreign_keys and col.autoincrement not in ( 

5241 True, 

5242 "ignore_fk", 

5243 ): 

5244 return False 

5245 return True 

5246 

5247 if len(self._columns) == 1: 

5248 col = list(self._columns)[0] 

5249 

5250 if col.autoincrement is True: 

5251 _validate_autoinc(col, True) 

5252 return col 

5253 elif col.autoincrement in ( 

5254 "auto", 

5255 "ignore_fk", 

5256 ) and _validate_autoinc(col, False): 

5257 return col 

5258 else: 

5259 return None 

5260 

5261 else: 

5262 autoinc = None 

5263 for col in self._columns: 

5264 if col.autoincrement is True: 

5265 _validate_autoinc(col, True) 

5266 if autoinc is not None: 

5267 raise exc.ArgumentError( 

5268 f"Only one Column may be marked " 

5269 f"autoincrement=True, found both " 

5270 f"{col.name} and {autoinc.name}." 

5271 ) 

5272 else: 

5273 autoinc = col 

5274 

5275 return autoinc 

5276 

5277 

5278class UniqueConstraint(ColumnCollectionConstraint): 

5279 """A table-level UNIQUE constraint. 

5280 

5281 Defines a single column or composite UNIQUE constraint. For a no-frills, 

5282 single column constraint, adding ``unique=True`` to the ``Column`` 

5283 definition is a shorthand equivalent for an unnamed, single column 

5284 UniqueConstraint. 

5285 """ 

5286 

5287 __visit_name__ = "unique_constraint" 

5288 

5289 

5290class Index( 

5291 DialectKWArgs, ColumnCollectionMixin, HasConditionalDDL, SchemaItem 

5292): 

5293 """A table-level INDEX. 

5294 

5295 Defines a composite (one or more column) INDEX. 

5296 

5297 E.g.:: 

5298 

5299 sometable = Table( 

5300 "sometable", 

5301 metadata, 

5302 Column("name", String(50)), 

5303 Column("address", String(100)), 

5304 ) 

5305 

5306 Index("some_index", sometable.c.name) 

5307 

5308 For a no-frills, single column index, adding 

5309 :class:`_schema.Column` also supports ``index=True``:: 

5310 

5311 sometable = Table( 

5312 "sometable", metadata, Column("name", String(50), index=True) 

5313 ) 

5314 

5315 For a composite index, multiple columns can be specified:: 

5316 

5317 Index("some_index", sometable.c.name, sometable.c.address) 

5318 

5319 Functional indexes are supported as well, typically by using the 

5320 :data:`.func` construct in conjunction with table-bound 

5321 :class:`_schema.Column` objects:: 

5322 

5323 Index("some_index", func.lower(sometable.c.name)) 

5324 

5325 An :class:`.Index` can also be manually associated with a 

5326 :class:`_schema.Table`, 

5327 either through inline declaration or using 

5328 :meth:`_schema.Table.append_constraint`. When this approach is used, 

5329 the names 

5330 of the indexed columns can be specified as strings:: 

5331 

5332 Table( 

5333 "sometable", 

5334 metadata, 

5335 Column("name", String(50)), 

5336 Column("address", String(100)), 

5337 Index("some_index", "name", "address"), 

5338 ) 

5339 

5340 To support functional or expression-based indexes in this form, the 

5341 :func:`_expression.text` construct may be used:: 

5342 

5343 from sqlalchemy import text 

5344 

5345 Table( 

5346 "sometable", 

5347 metadata, 

5348 Column("name", String(50)), 

5349 Column("address", String(100)), 

5350 Index("some_index", text("lower(name)")), 

5351 ) 

5352 

5353 .. seealso:: 

5354 

5355 :ref:`schema_indexes` - General information on :class:`.Index`. 

5356 

5357 :ref:`postgresql_indexes` - PostgreSQL-specific options available for 

5358 the :class:`.Index` construct. 

5359 

5360 :ref:`mysql_indexes` - MySQL-specific options available for the 

5361 :class:`.Index` construct. 

5362 

5363 :ref:`mssql_indexes` - MSSQL-specific options available for the 

5364 :class:`.Index` construct. 

5365 

5366 """ 

5367 

5368 __visit_name__ = "index" 

5369 

5370 table: Optional[Table] 

5371 expressions: _typing_Sequence[Union[str, ColumnElement[Any]]] 

5372 _table_bound_expressions: _typing_Sequence[ColumnElement[Any]] 

5373 

5374 def __init__( 

5375 self, 

5376 name: Optional[str], 

5377 *expressions: _DDLColumnArgument, 

5378 unique: bool = False, 

5379 quote: Optional[bool] = None, 

5380 info: Optional[_InfoType] = None, 

5381 _table: Optional[Table] = None, 

5382 _column_flag: bool = False, 

5383 **dialect_kw: Any, 

5384 ) -> None: 

5385 r"""Construct an index object. 

5386 

5387 :param name: 

5388 The name of the index 

5389 

5390 :param \*expressions: 

5391 Column expressions to include in the index. The expressions 

5392 are normally instances of :class:`_schema.Column`, but may also 

5393 be arbitrary SQL expressions which ultimately refer to a 

5394 :class:`_schema.Column`. 

5395 

5396 :param unique=False: 

5397 Keyword only argument; if True, create a unique index. 

5398 

5399 :param quote=None: 

5400 Keyword only argument; whether to apply quoting to the name of 

5401 the index. Works in the same manner as that of 

5402 :paramref:`_schema.Column.quote`. 

5403 

5404 :param info=None: Optional data dictionary which will be populated 

5405 into the :attr:`.SchemaItem.info` attribute of this object. 

5406 

5407 :param \**dialect_kw: Additional keyword arguments not mentioned above 

5408 are dialect specific, and passed in the form 

5409 ``<dialectname>_<argname>``. See the documentation regarding an 

5410 individual dialect at :ref:`dialect_toplevel` for detail on 

5411 documented arguments. 

5412 

5413 """ 

5414 self.table = table = None 

5415 

5416 self.name = quoted_name.construct(name, quote) 

5417 self.unique = unique 

5418 if info is not None: 

5419 self.info = info 

5420 

5421 # TODO: consider "table" argument being public, but for 

5422 # the purpose of the fix here, it starts as private. 

5423 if _table is not None: 

5424 table = _table 

5425 

5426 self._validate_dialect_kwargs(dialect_kw) 

5427 

5428 self.expressions = [] 

5429 # will call _set_parent() if table-bound column 

5430 # objects are present 

5431 ColumnCollectionMixin.__init__( 

5432 self, 

5433 *expressions, 

5434 _column_flag=_column_flag, 

5435 _gather_expressions=self.expressions, 

5436 ) 

5437 if table is not None: 

5438 self._set_parent(table) 

5439 

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

5441 table = parent 

5442 assert isinstance(table, Table) 

5443 ColumnCollectionMixin._set_parent(self, table) 

5444 

5445 if self.table is not None and table is not self.table: 

5446 raise exc.ArgumentError( 

5447 f"Index '{self.name}' is against table " 

5448 f"'{self.table.description}', and " 

5449 f"cannot be associated with table '{table.description}'." 

5450 ) 

5451 self.table = table 

5452 table.indexes.add(self) 

5453 

5454 expressions = self.expressions 

5455 col_expressions = self._col_expressions(table) 

5456 assert len(expressions) == len(col_expressions) 

5457 

5458 exprs = [] 

5459 for expr, colexpr in zip(expressions, col_expressions): 

5460 if isinstance(expr, ClauseElement): 

5461 exprs.append(expr) 

5462 elif colexpr is not None: 

5463 exprs.append(colexpr) 

5464 else: 

5465 assert False 

5466 self.expressions = self._table_bound_expressions = exprs 

5467 

5468 def create( 

5469 self, 

5470 bind: _CreateDropBind, 

5471 checkfirst: Union[bool, CheckFirst] = CheckFirst.NONE, 

5472 ) -> None: 

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

5474 :class:`.Index`, using the given 

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

5476 

5477 .. seealso:: 

5478 

5479 :meth:`_schema.MetaData.create_all`. 

5480 

5481 """ 

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

5483 

5484 def drop( 

5485 self, 

5486 bind: _CreateDropBind, 

5487 checkfirst: Union[bool, CheckFirst] = CheckFirst.NONE, 

5488 ) -> None: 

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

5490 :class:`.Index`, using the given 

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

5492 

5493 .. seealso:: 

5494 

5495 :meth:`_schema.MetaData.drop_all`. 

5496 

5497 """ 

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

5499 

5500 def __repr__(self) -> str: 

5501 exprs: _typing_Sequence[Any] # noqa: F842 

5502 

5503 return "Index(%s)" % ( 

5504 ", ".join( 

5505 [repr(self.name)] 

5506 + [repr(e) for e in self.expressions] 

5507 + (self.unique and ["unique=True"] or []) 

5508 ) 

5509 ) 

5510 

5511 

5512_NamingSchemaCallable = Callable[[Constraint, Table], str] 

5513_NamingSchemaDirective = Union[str, _NamingSchemaCallable] 

5514 

5515 

5516class _NamingSchemaTD(TypedDict, total=False): 

5517 fk: _NamingSchemaDirective 

5518 pk: _NamingSchemaDirective 

5519 ix: _NamingSchemaDirective 

5520 ck: _NamingSchemaDirective 

5521 uq: _NamingSchemaDirective 

5522 

5523 

5524_NamingSchemaParameter = Union[ 

5525 # it seems like the TypedDict here is useful for pylance typeahead, 

5526 # and not much else 

5527 _NamingSchemaTD, 

5528 # there is no form that allows Union[Type[Any], str] to work in all 

5529 # cases, including breaking out Mapping[] entries for each combination 

5530 # even, therefore keys must be `Any` (see #10264) 

5531 Mapping[Any, _NamingSchemaDirective], 

5532] 

5533 

5534 

5535DEFAULT_NAMING_CONVENTION: _NamingSchemaParameter = util.immutabledict( 

5536 {"ix": "ix_%(column_0_label)s"} 

5537) 

5538 

5539 

5540class MetaData(HasSchemaAttr): 

5541 """A collection of :class:`_schema.Table` 

5542 objects and their associated schema 

5543 constructs. 

5544 

5545 Holds a collection of :class:`_schema.Table` objects as well as 

5546 an optional binding to an :class:`_engine.Engine` or 

5547 :class:`_engine.Connection`. If bound, the :class:`_schema.Table` objects 

5548 in the collection and their columns may participate in implicit SQL 

5549 execution. 

5550 

5551 The :class:`_schema.Table` objects themselves are stored in the 

5552 :attr:`_schema.MetaData.tables` dictionary. 

5553 

5554 :class:`_schema.MetaData` is a thread-safe object for read operations. 

5555 Construction of new tables within a single :class:`_schema.MetaData` 

5556 object, 

5557 either explicitly or via reflection, may not be completely thread-safe. 

5558 

5559 .. seealso:: 

5560 

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

5562 

5563 """ 

5564 

5565 __visit_name__ = "metadata" 

5566 

5567 def __init__( 

5568 self, 

5569 schema: Optional[str] = None, 

5570 quote_schema: Optional[bool] = None, 

5571 naming_convention: Optional[_NamingSchemaParameter] = None, 

5572 info: Optional[_InfoType] = None, 

5573 ) -> None: 

5574 """Create a new MetaData object. 

5575 

5576 :param schema: 

5577 The default schema to use for the :class:`_schema.Table`, 

5578 :class:`.Sequence`, and potentially other objects associated with 

5579 this :class:`_schema.MetaData`. Defaults to ``None``. 

5580 

5581 .. seealso:: 

5582 

5583 :ref:`schema_metadata_schema_name` - details on how the 

5584 :paramref:`_schema.MetaData.schema` parameter is used. 

5585 

5586 :paramref:`_schema.Table.schema` 

5587 

5588 :paramref:`.Sequence.schema` 

5589 

5590 :param quote_schema: 

5591 Sets the ``quote_schema`` flag for those :class:`_schema.Table`, 

5592 :class:`.Sequence`, and other objects which make usage of the 

5593 local ``schema`` name. 

5594 

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

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

5597 

5598 :param naming_convention: a dictionary referring to values which 

5599 will establish default naming conventions for :class:`.Constraint` 

5600 and :class:`.Index` objects, for those objects which are not given 

5601 a name explicitly. 

5602 

5603 The keys of this dictionary may be: 

5604 

5605 * a constraint or Index class, e.g. the :class:`.UniqueConstraint`, 

5606 :class:`_schema.ForeignKeyConstraint` class, the :class:`.Index` 

5607 class 

5608 

5609 * a string mnemonic for one of the known constraint classes; 

5610 ``"fk"``, ``"pk"``, ``"ix"``, ``"ck"``, ``"uq"`` for foreign key, 

5611 primary key, index, check, and unique constraint, respectively. 

5612 

5613 * the string name of a user-defined "token" that can be used 

5614 to define new naming tokens. 

5615 

5616 The values associated with each "constraint class" or "constraint 

5617 mnemonic" key are string naming templates, such as 

5618 ``"uq_%(table_name)s_%(column_0_name)s"``, 

5619 which describe how the name should be composed. The values 

5620 associated with user-defined "token" keys should be callables of the 

5621 form ``fn(constraint, table)``, which accepts the constraint/index 

5622 object and :class:`_schema.Table` as arguments, returning a string 

5623 result. 

5624 

5625 The built-in names are as follows, some of which may only be 

5626 available for certain types of constraint: 

5627 

5628 * ``%(table_name)s`` - the name of the :class:`_schema.Table` 

5629 object 

5630 associated with the constraint. 

5631 

5632 * ``%(referred_table_name)s`` - the name of the 

5633 :class:`_schema.Table` 

5634 object associated with the referencing target of a 

5635 :class:`_schema.ForeignKeyConstraint`. 

5636 

5637 * ``%(column_0_name)s`` - the name of the :class:`_schema.Column` 

5638 at 

5639 index position "0" within the constraint. 

5640 

5641 * ``%(column_0N_name)s`` - the name of all :class:`_schema.Column` 

5642 objects in order within the constraint, joined without a 

5643 separator. 

5644 

5645 * ``%(column_0_N_name)s`` - the name of all 

5646 :class:`_schema.Column` 

5647 objects in order within the constraint, joined with an 

5648 underscore as a separator. 

5649 

5650 * ``%(column_0_label)s``, ``%(column_0N_label)s``, 

5651 ``%(column_0_N_label)s`` - the label of either the zeroth 

5652 :class:`_schema.Column` or all :class:`.Columns`, separated with 

5653 or without an underscore 

5654 

5655 * ``%(column_0_key)s``, ``%(column_0N_key)s``, 

5656 ``%(column_0_N_key)s`` - the key of either the zeroth 

5657 :class:`_schema.Column` or all :class:`.Columns`, separated with 

5658 or without an underscore 

5659 

5660 * ``%(referred_column_0_name)s``, ``%(referred_column_0N_name)s`` 

5661 ``%(referred_column_0_N_name)s``, ``%(referred_column_0_key)s``, 

5662 ``%(referred_column_0N_key)s``, ... column tokens which 

5663 render the names/keys/labels of columns that are referenced 

5664 by a :class:`_schema.ForeignKeyConstraint`. 

5665 

5666 * ``%(constraint_name)s`` - a special key that refers to the 

5667 existing name given to the constraint. When this key is 

5668 present, the :class:`.Constraint` object's existing name will be 

5669 replaced with one that is composed from template string that 

5670 uses this token. When this token is present, it is required that 

5671 the :class:`.Constraint` is given an explicit name ahead of time. 

5672 

5673 * user-defined: any additional token may be implemented by passing 

5674 it along with a ``fn(constraint, table)`` callable to the 

5675 naming_convention dictionary. 

5676 

5677 .. seealso:: 

5678 

5679 :ref:`constraint_naming_conventions` - for detailed usage 

5680 examples. 

5681 

5682 """ 

5683 if schema is not None and not isinstance(schema, str): 

5684 raise exc.ArgumentError( 

5685 "expected schema argument to be a string, " 

5686 f"got {type(schema)}." 

5687 ) 

5688 self.tables = util.FacadeDict() 

5689 self.schema = quoted_name.construct(schema, quote_schema) 

5690 self.naming_convention = ( 

5691 naming_convention 

5692 if naming_convention 

5693 else DEFAULT_NAMING_CONVENTION 

5694 ) 

5695 if info: 

5696 self.info = info 

5697 self._schemas: Set[str] = set() 

5698 self._sequences: Dict[str, Sequence] = {} 

5699 self._fk_memos: Dict[Tuple[str, Optional[str]], List[ForeignKey]] = ( 

5700 collections.defaultdict(list) 

5701 ) 

5702 self._objects: Set[Union[HasSchemaAttr, SchemaType]] = set() 

5703 

5704 tables: util.FacadeDict[str, Table] 

5705 """A dictionary of :class:`_schema.Table` 

5706 objects keyed to their name or "table key". 

5707 

5708 The exact key is that determined by the :attr:`_schema.Table.key` 

5709 attribute; 

5710 for a table with no :attr:`_schema.Table.schema` attribute, 

5711 this is the same 

5712 as :attr:`_schema.Table.name`. For a table with a schema, 

5713 it is typically of the 

5714 form ``schemaname.tablename``. 

5715 

5716 .. seealso:: 

5717 

5718 :attr:`_schema.MetaData.sorted_tables` 

5719 

5720 """ 

5721 

5722 def __repr__(self) -> str: 

5723 return "MetaData()" 

5724 

5725 def __contains__(self, table_or_key: Union[str, Table]) -> bool: 

5726 if not isinstance(table_or_key, str): 

5727 table_or_key = table_or_key.key 

5728 return table_or_key in self.tables 

5729 

5730 def _add_table( 

5731 self, name: str, schema: Optional[str], table: Table 

5732 ) -> None: 

5733 key = _get_table_key(name, schema) 

5734 self.tables._insert_item(key, table) 

5735 if schema: 

5736 self._schemas.add(schema) 

5737 

5738 def _remove_table(self, name: str, schema: Optional[str]) -> None: 

5739 key = _get_table_key(name, schema) 

5740 removed = dict.pop(self.tables, key, None) 

5741 if removed is not None: 

5742 for fk in removed.foreign_keys: 

5743 fk._remove_from_metadata(self) 

5744 if self._schemas: 

5745 self._schemas = { 

5746 t.schema for t in self.tables.values() if t.schema is not None 

5747 } 

5748 

5749 def __getstate__(self) -> Dict[str, Any]: 

5750 return { 

5751 "tables": self.tables, 

5752 "schema": self.schema, 

5753 "schemas": self._schemas, 

5754 "sequences": self._sequences, 

5755 "fk_memos": self._fk_memos, 

5756 "naming_convention": self.naming_convention, 

5757 "objects": self._objects, 

5758 } 

5759 

5760 def __setstate__(self, state: Dict[str, Any]) -> None: 

5761 self.tables = state["tables"] 

5762 self.schema = state["schema"] 

5763 self.naming_convention = state["naming_convention"] 

5764 self._sequences = state["sequences"] 

5765 self._schemas = state["schemas"] 

5766 self._fk_memos = state["fk_memos"] 

5767 self._objects = state.get("objects", set()) 

5768 

5769 def clear(self) -> None: 

5770 """Clear all objects from this MetaData.""" 

5771 

5772 dict.clear(self.tables) 

5773 self._schemas.clear() 

5774 self._fk_memos.clear() 

5775 self._sequences.clear() 

5776 self._objects.clear() 

5777 

5778 def remove(self, table: Table) -> None: 

5779 """Remove the given Table object from this MetaData.""" 

5780 

5781 self._remove_table(table.name, table.schema) 

5782 

5783 @property 

5784 def sorted_tables(self) -> List[Table]: 

5785 """Returns a list of :class:`_schema.Table` objects sorted in order of 

5786 foreign key dependency. 

5787 

5788 The sorting will place :class:`_schema.Table` 

5789 objects that have dependencies 

5790 first, before the dependencies themselves, representing the 

5791 order in which they can be created. To get the order in which 

5792 the tables would be dropped, use the ``reversed()`` Python built-in. 

5793 

5794 .. warning:: 

5795 

5796 The :attr:`.MetaData.sorted_tables` attribute cannot by itself 

5797 accommodate automatic resolution of dependency cycles between 

5798 tables, which are usually caused by mutually dependent foreign key 

5799 constraints. When these cycles are detected, the foreign keys 

5800 of these tables are omitted from consideration in the sort. 

5801 A warning is emitted when this condition occurs, which will be an 

5802 exception raise in a future release. Tables which are not part 

5803 of the cycle will still be returned in dependency order. 

5804 

5805 To resolve these cycles, the 

5806 :paramref:`_schema.ForeignKeyConstraint.use_alter` parameter may be 

5807 applied to those constraints which create a cycle. Alternatively, 

5808 the :func:`_schema.sort_tables_and_constraints` function will 

5809 automatically return foreign key constraints in a separate 

5810 collection when cycles are detected so that they may be applied 

5811 to a schema separately. 

5812 

5813 .. seealso:: 

5814 

5815 :func:`_schema.sort_tables` 

5816 

5817 :func:`_schema.sort_tables_and_constraints` 

5818 

5819 :attr:`_schema.MetaData.tables` 

5820 

5821 :meth:`_reflection.Inspector.get_table_names` 

5822 

5823 :meth:`_reflection.Inspector.get_sorted_table_and_fkc_names` 

5824 

5825 

5826 """ 

5827 return ddl.sort_tables( 

5828 sorted(self.tables.values(), key=lambda t: t.key) # type: ignore 

5829 ) 

5830 

5831 # overload needed to work around mypy this mypy 

5832 # https://github.com/python/mypy/issues/17093 

5833 @overload 

5834 def reflect( 

5835 self, 

5836 bind: Engine, 

5837 schema: Optional[str] = ..., 

5838 views: bool = ..., 

5839 only: Union[ 

5840 _typing_Sequence[str], Callable[[str, MetaData], bool], None 

5841 ] = ..., 

5842 extend_existing: bool = ..., 

5843 autoload_replace: bool = ..., 

5844 resolve_fks: bool = ..., 

5845 **dialect_kwargs: Any, 

5846 ) -> None: ... 

5847 

5848 @overload 

5849 def reflect( 

5850 self, 

5851 bind: Connection, 

5852 schema: Optional[str] = ..., 

5853 views: bool = ..., 

5854 only: Union[ 

5855 _typing_Sequence[str], Callable[[str, MetaData], bool], None 

5856 ] = ..., 

5857 extend_existing: bool = ..., 

5858 autoload_replace: bool = ..., 

5859 resolve_fks: bool = ..., 

5860 **dialect_kwargs: Any, 

5861 ) -> None: ... 

5862 

5863 @util.preload_module("sqlalchemy.engine.reflection") 

5864 def reflect( 

5865 self, 

5866 bind: Union[Engine, Connection], 

5867 schema: Optional[str] = None, 

5868 views: bool = False, 

5869 only: Union[ 

5870 _typing_Sequence[str], Callable[[str, MetaData], bool], None 

5871 ] = None, 

5872 extend_existing: bool = False, 

5873 autoload_replace: bool = True, 

5874 resolve_fks: bool = True, 

5875 **dialect_kwargs: Any, 

5876 ) -> None: 

5877 r"""Load all available table definitions from the database. 

5878 

5879 Automatically creates ``Table`` entries in this ``MetaData`` for any 

5880 table available in the database but not yet present in the 

5881 ``MetaData``. May be called multiple times to pick up tables recently 

5882 added to the database, however no special action is taken if a table 

5883 in this ``MetaData`` no longer exists in the database. 

5884 

5885 :param bind: 

5886 A :class:`.Connection` or :class:`.Engine` used to access the 

5887 database. 

5888 

5889 :param schema: 

5890 Optional, query and reflect tables from an alternate schema. 

5891 If None, the schema associated with this :class:`_schema.MetaData` 

5892 is used, if any. 

5893 

5894 :param views: 

5895 If True, also reflect views (materialized and plain). 

5896 

5897 :param only: 

5898 Optional. Load only a sub-set of available named tables. May be 

5899 specified as a sequence of names or a callable. 

5900 

5901 If a sequence of names is provided, only those tables will be 

5902 reflected. An error is raised if a table is requested but not 

5903 available. Named tables already present in this ``MetaData`` are 

5904 ignored. 

5905 

5906 If a callable is provided, it will be used as a boolean predicate to 

5907 filter the list of potential table names. The callable is called 

5908 with a table name and this ``MetaData`` instance as positional 

5909 arguments and should return a true value for any table to reflect. 

5910 

5911 :param extend_existing: Passed along to each :class:`_schema.Table` as 

5912 :paramref:`_schema.Table.extend_existing`. 

5913 

5914 :param autoload_replace: Passed along to each :class:`_schema.Table` 

5915 as 

5916 :paramref:`_schema.Table.autoload_replace`. 

5917 

5918 :param resolve_fks: if True, reflect :class:`_schema.Table` 

5919 objects linked 

5920 to :class:`_schema.ForeignKey` objects located in each 

5921 :class:`_schema.Table`. 

5922 For :meth:`_schema.MetaData.reflect`, 

5923 this has the effect of reflecting 

5924 related tables that might otherwise not be in the list of tables 

5925 being reflected, for example if the referenced table is in a 

5926 different schema or is omitted via the 

5927 :paramref:`.MetaData.reflect.only` parameter. When False, 

5928 :class:`_schema.ForeignKey` objects are not followed to the 

5929 :class:`_schema.Table` 

5930 in which they link, however if the related table is also part of the 

5931 list of tables that would be reflected in any case, the 

5932 :class:`_schema.ForeignKey` object will still resolve to its related 

5933 :class:`_schema.Table` after the :meth:`_schema.MetaData.reflect` 

5934 operation is 

5935 complete. Defaults to True. 

5936 

5937 .. seealso:: 

5938 

5939 :paramref:`_schema.Table.resolve_fks` 

5940 

5941 :param \**dialect_kwargs: Additional keyword arguments not mentioned 

5942 above are dialect specific, and passed in the form 

5943 ``<dialectname>_<argname>``. See the documentation regarding an 

5944 individual dialect at :ref:`dialect_toplevel` for detail on 

5945 documented arguments. 

5946 

5947 .. seealso:: 

5948 

5949 :ref:`metadata_reflection_toplevel` 

5950 

5951 :meth:`_events.DDLEvents.column_reflect` - Event used to customize 

5952 the reflected columns. Usually used to generalize the types using 

5953 :meth:`_types.TypeEngine.as_generic` 

5954 

5955 :ref:`metadata_reflection_dbagnostic_types` - describes how to 

5956 reflect tables using general types. 

5957 

5958 """ 

5959 

5960 with inspection.inspect(bind)._inspection_context() as insp: 

5961 reflect_opts: Any = { 

5962 "autoload_with": insp, 

5963 "extend_existing": extend_existing, 

5964 "autoload_replace": autoload_replace, 

5965 "resolve_fks": resolve_fks, 

5966 "_extend_on": set(), 

5967 } 

5968 

5969 reflect_opts.update(dialect_kwargs) 

5970 

5971 if schema is None: 

5972 schema = self.schema 

5973 

5974 if schema is not None: 

5975 reflect_opts["schema"] = schema 

5976 

5977 kind = util.preloaded.engine_reflection.ObjectKind.TABLE 

5978 available: util.OrderedSet[str] = util.OrderedSet( 

5979 insp.get_table_names(schema, **dialect_kwargs) 

5980 ) 

5981 if views: 

5982 kind = util.preloaded.engine_reflection.ObjectKind.ANY 

5983 available.update(insp.get_view_names(schema, **dialect_kwargs)) 

5984 try: 

5985 available.update( 

5986 insp.get_materialized_view_names( 

5987 schema, **dialect_kwargs 

5988 ) 

5989 ) 

5990 except NotImplementedError: 

5991 pass 

5992 

5993 if schema is not None: 

5994 available_w_schema: util.OrderedSet[str] = util.OrderedSet( 

5995 [f"{schema}.{name}" for name in available] 

5996 ) 

5997 else: 

5998 available_w_schema = available 

5999 

6000 current = set(self.tables) 

6001 

6002 if only is None: 

6003 load = [ 

6004 name 

6005 for name, schname in zip(available, available_w_schema) 

6006 if extend_existing or schname not in current 

6007 ] 

6008 elif callable(only): 

6009 load = [ 

6010 name 

6011 for name, schname in zip(available, available_w_schema) 

6012 if (extend_existing or schname not in current) 

6013 and only(name, self) 

6014 ] 

6015 else: 

6016 missing = [name for name in only if name not in available] 

6017 if missing: 

6018 s = schema and (" schema '%s'" % schema) or "" 

6019 missing_str = ", ".join(missing) 

6020 raise exc.InvalidRequestError( 

6021 f"Could not reflect: requested table(s) not available " 

6022 f"in {bind.engine!r}{s}: ({missing_str})" 

6023 ) 

6024 load = [ 

6025 name 

6026 for name in only 

6027 if extend_existing or name not in current 

6028 ] 

6029 # pass the available tables so the inspector can 

6030 # choose to ignore the filter_names 

6031 _reflect_info = insp._get_reflection_info( 

6032 schema=schema, 

6033 filter_names=load, 

6034 available=available, 

6035 kind=kind, 

6036 scope=util.preloaded.engine_reflection.ObjectScope.ANY, 

6037 **dialect_kwargs, 

6038 ) 

6039 reflect_opts["_reflect_info"] = _reflect_info 

6040 

6041 for name in load: 

6042 try: 

6043 Table(name, self, **reflect_opts) 

6044 except exc.UnreflectableTableError as uerr: 

6045 util.warn(f"Skipping table {name}: {uerr}") 

6046 

6047 def create_all( 

6048 self, 

6049 bind: _CreateDropBind, 

6050 tables: Optional[_typing_Sequence[Table]] = None, 

6051 checkfirst: Union[bool, CheckFirst] = CheckFirst.ALL, 

6052 ) -> None: 

6053 """Create all tables stored in this metadata. 

6054 

6055 Conditional by default, will not attempt to recreate tables already 

6056 present in the target database. 

6057 

6058 :param bind: 

6059 A :class:`.Connection` or :class:`.Engine` used to access the 

6060 database. 

6061 

6062 :param tables: 

6063 Optional list of ``Table`` objects, which is a subset of the total 

6064 tables in the ``MetaData`` (others are ignored). 

6065 

6066 :param checkfirst: A boolean value or instance of :class:`.CheckFirst`. 

6067 Indicates which objects should be checked for within a separate pass 

6068 before creating schema objects. 

6069 

6070 """ 

6071 bind._run_ddl_visitor( 

6072 ddl.SchemaGenerator, self, checkfirst=checkfirst, tables=tables 

6073 ) 

6074 

6075 def drop_all( 

6076 self, 

6077 bind: _CreateDropBind, 

6078 tables: Optional[_typing_Sequence[Table]] = None, 

6079 checkfirst: Union[bool, CheckFirst] = CheckFirst.ALL, 

6080 ) -> None: 

6081 """Drop all tables stored in this metadata. 

6082 

6083 Conditional by default, will not attempt to drop tables not present in 

6084 the target database. 

6085 

6086 :param bind: 

6087 A :class:`.Connection` or :class:`.Engine` used to access the 

6088 database. 

6089 

6090 :param tables: 

6091 Optional list of ``Table`` objects, which is a subset of the 

6092 total tables in the ``MetaData`` (others are ignored). 

6093 

6094 :param checkfirst: A boolean value or instance of :class:`.CheckFirst`. 

6095 Indicates which objects should be checked for within a separate pass 

6096 before dropping schema objects. 

6097 

6098 """ 

6099 bind._run_ddl_visitor( 

6100 ddl.SchemaDropper, self, checkfirst=checkfirst, tables=tables 

6101 ) 

6102 

6103 @property 

6104 def schemas(self) -> _typing_Sequence[str]: 

6105 """A sequence of schema names that are present in this MetaData.""" 

6106 schemas = self._schemas 

6107 if self.schema: 

6108 schemas = schemas | {self.schema} 

6109 return tuple(schemas) 

6110 

6111 def get_schema_objects( 

6112 self, 

6113 kind: Type[_T], 

6114 *, 

6115 schema: Union[str, None, Literal[_NoArg.NO_ARG]] = _NoArg.NO_ARG, 

6116 ) -> _typing_Sequence[_T]: 

6117 """Return a sequence of schema objects of the given kind. 

6118 

6119 This method can be used to return :class:`_sqltypes.Enum`, 

6120 :class:`.Sequence`, etc. objects registered in this 

6121 :class:`_schema.MetaData`. 

6122 

6123 :param kind: a type that indicates what object to return, such as 

6124 :class:`Enum` or :class:`Sequence`. 

6125 :param schema: Optional, a schema name to filter the objects by. If 

6126 not provided the default schema of the metadata is used. 

6127 

6128 """ 

6129 

6130 if schema is _NoArg.NO_ARG: 

6131 schema = self.schema 

6132 return tuple( 

6133 obj 

6134 for obj in self._objects 

6135 if isinstance(obj, kind) and obj.schema == schema 

6136 ) 

6137 

6138 def get_schema_object_by_name( 

6139 self, 

6140 kind: Type[_T], 

6141 name: str, 

6142 *, 

6143 schema: Union[str, None, Literal[_NoArg.NO_ARG]] = _NoArg.NO_ARG, 

6144 ) -> Optional[_T]: 

6145 """Return a schema objects of the given kind and name if found. 

6146 

6147 This method can be used to return :class:`_sqltypes.Enum`, 

6148 :class:`.Sequence`, etc. objects registered in this 

6149 :class:`_schema.MetaData`. 

6150 

6151 :param kind: a type that indicates what object to return, such as 

6152 :class:`Enum` or :class:`Sequence`. 

6153 :param name: the name of the object to return. 

6154 :param schema: Optional, a schema name to filter the objects by. If 

6155 not provided the default schema of the metadata is used. 

6156 

6157 """ 

6158 

6159 for obj in self.get_schema_objects(kind, schema=schema): 

6160 if getattr(obj, "name", None) == name: 

6161 return obj 

6162 return None 

6163 

6164 def _register_object(self, obj: Union[HasSchemaAttr, SchemaType]) -> None: 

6165 self._objects.add(obj) 

6166 

6167 

6168class Computed(FetchedValue, SchemaItem): 

6169 """Defines a generated column, i.e. "GENERATED ALWAYS AS" syntax. 

6170 

6171 The :class:`.Computed` construct is an inline construct added to the 

6172 argument list of a :class:`_schema.Column` object:: 

6173 

6174 from sqlalchemy import Computed 

6175 

6176 Table( 

6177 "square", 

6178 metadata_obj, 

6179 Column("side", Float, nullable=False), 

6180 Column("area", Float, Computed("side * side")), 

6181 ) 

6182 

6183 See the linked documentation below for complete details. 

6184 

6185 .. seealso:: 

6186 

6187 :ref:`computed_ddl` 

6188 

6189 """ 

6190 

6191 __visit_name__ = "computed_column" 

6192 

6193 column: Optional[Column[Any]] 

6194 

6195 @_document_text_coercion( 

6196 "sqltext", ":class:`.Computed`", ":paramref:`.Computed.sqltext`" 

6197 ) 

6198 def __init__( 

6199 self, sqltext: _DDLColumnArgument, persisted: Optional[bool] = None 

6200 ) -> None: 

6201 """Construct a GENERATED ALWAYS AS DDL construct to accompany a 

6202 :class:`_schema.Column`. 

6203 

6204 :param sqltext: 

6205 A string containing the column generation expression, which will be 

6206 used verbatim, or a SQL expression construct, such as a 

6207 :func:`_expression.text` 

6208 object. If given as a string, the object is converted to a 

6209 :func:`_expression.text` object. 

6210 

6211 :param persisted: 

6212 Optional, controls how this column should be persisted by the 

6213 database. Possible values are: 

6214 

6215 * ``None``, the default, it will use the default persistence 

6216 defined by the database. 

6217 * ``True``, will render ``GENERATED ALWAYS AS ... STORED``, or the 

6218 equivalent for the target database if supported. 

6219 * ``False``, will render ``GENERATED ALWAYS AS ... VIRTUAL``, or 

6220 the equivalent for the target database if supported. 

6221 

6222 Specifying ``True`` or ``False`` may raise an error when the DDL 

6223 is emitted to the target database if the database does not support 

6224 that persistence option. Leaving this parameter at its default 

6225 of ``None`` is guaranteed to succeed for all databases that support 

6226 ``GENERATED ALWAYS AS``. 

6227 

6228 """ 

6229 self.sqltext = coercions.expect(roles.DDLExpressionRole, sqltext) 

6230 self.persisted = persisted 

6231 self.column = None 

6232 

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

6234 assert isinstance(parent, Column) 

6235 

6236 if not isinstance( 

6237 parent.server_default, (type(None), Computed) 

6238 ) or not isinstance(parent.server_onupdate, (type(None), Computed)): 

6239 raise exc.ArgumentError( 

6240 "A generated column cannot specify a server_default or a " 

6241 "server_onupdate argument" 

6242 ) 

6243 self.column = parent 

6244 parent.computed = self 

6245 self.column.server_onupdate = self 

6246 self.column.server_default = self 

6247 

6248 def _as_for_update(self, for_update: bool) -> FetchedValue: 

6249 return self 

6250 

6251 @util.deprecated( 

6252 "1.4", 

6253 "The :meth:`_schema.Computed.copy` method is deprecated " 

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

6255 ) 

6256 def copy( 

6257 self, *, target_table: Optional[Table] = None, **kw: Any 

6258 ) -> Computed: 

6259 return self._copy(target_table=target_table, **kw) 

6260 

6261 def _copy( 

6262 self, *, target_table: Optional[Table] = None, **kw: Any 

6263 ) -> Computed: 

6264 sqltext = _copy_expression( 

6265 self.sqltext, 

6266 self.column.table if self.column is not None else None, 

6267 target_table, 

6268 ) 

6269 g = Computed(sqltext, persisted=self.persisted) 

6270 

6271 return self._schema_item_copy(g) 

6272 

6273 

6274class Identity(IdentityOptions, FetchedValue, SchemaItem): 

6275 """Defines an identity column, i.e. "GENERATED { ALWAYS | BY DEFAULT } 

6276 AS IDENTITY" syntax. 

6277 

6278 The :class:`.Identity` construct is an inline construct added to the 

6279 argument list of a :class:`_schema.Column` object:: 

6280 

6281 from sqlalchemy import Identity 

6282 

6283 Table( 

6284 "foo", 

6285 metadata_obj, 

6286 Column("id", Integer, Identity()), 

6287 Column("description", Text), 

6288 ) 

6289 

6290 See the linked documentation below for complete details. 

6291 

6292 .. versionadded:: 1.4 

6293 

6294 .. seealso:: 

6295 

6296 :ref:`identity_ddl` 

6297 

6298 """ 

6299 

6300 __visit_name__ = "identity_column" 

6301 

6302 is_identity = True 

6303 

6304 @util.deprecated_params( 

6305 order=( 

6306 "2.1", 

6307 "This parameter is supported only by Oracle Database, " 

6308 "use ``oracle_order`` instead.", 

6309 ), 

6310 on_null=( 

6311 "2.1", 

6312 "This parameter is supported only by Oracle Database, " 

6313 "use ``oracle_on_null`` instead.", 

6314 ), 

6315 ) 

6316 def __init__( 

6317 self, 

6318 always: Optional[bool] = False, 

6319 on_null: Optional[bool] = None, 

6320 start: Optional[int] = None, 

6321 increment: Optional[int] = None, 

6322 minvalue: Optional[int] = None, 

6323 maxvalue: Optional[int] = None, 

6324 nominvalue: Optional[bool] = None, 

6325 nomaxvalue: Optional[bool] = None, 

6326 cycle: Optional[bool] = None, 

6327 cache: Optional[int] = None, 

6328 order: Optional[bool] = None, 

6329 **dialect_kw: Any, 

6330 ) -> None: 

6331 """Construct a GENERATED { ALWAYS | BY DEFAULT } AS IDENTITY DDL 

6332 construct to accompany a :class:`_schema.Column`. 

6333 

6334 See the :class:`.Sequence` documentation for a complete description 

6335 of most parameters. 

6336 

6337 .. note:: 

6338 MSSQL supports this construct as the preferred alternative to 

6339 generate an IDENTITY on a column, but it uses non standard 

6340 syntax that only support :paramref:`_schema.Identity.start` 

6341 and :paramref:`_schema.Identity.increment`. 

6342 All other parameters are ignored. 

6343 

6344 :param always: 

6345 A boolean, that indicates the type of identity column. 

6346 If ``False`` is specified, the default, then the user-specified 

6347 value takes precedence. 

6348 If ``True`` is specified, a user-specified value is not accepted ( 

6349 on some backends, like PostgreSQL, OVERRIDING SYSTEM VALUE, or 

6350 similar, may be specified in an INSERT to override the sequence 

6351 value). 

6352 Some backends also have a default value for this parameter, 

6353 ``None`` can be used to omit rendering this part in the DDL. It 

6354 will be treated as ``False`` if a backend does not have a default 

6355 value. 

6356 

6357 :param on_null: 

6358 Set to ``True`` to specify ON NULL in conjunction with a 

6359 ``always=False`` identity column. This option is only supported on 

6360 some backends, like Oracle Database. 

6361 

6362 :param start: the starting index of the sequence. 

6363 :param increment: the increment value of the sequence. 

6364 :param minvalue: the minimum value of the sequence. 

6365 :param maxvalue: the maximum value of the sequence. 

6366 :param nominvalue: no minimum value of the sequence. 

6367 :param nomaxvalue: no maximum value of the sequence. 

6368 :param cycle: allows the sequence to wrap around when the maxvalue 

6369 or minvalue has been reached. 

6370 :param cache: optional integer value; number of future values in the 

6371 sequence which are calculated in advance. 

6372 :param order: optional boolean value; if true, renders the 

6373 ORDER keyword. 

6374 

6375 """ 

6376 self.dialect_options 

6377 if on_null is not None: 

6378 if "oracle_on_null" in dialect_kw: 

6379 raise exc.ArgumentError( 

6380 "Cannot specify both 'on_null' and 'oracle_on_null'. " 

6381 "Plese use only 'oracle_on_null'." 

6382 ) 

6383 dialect_kw["oracle_on_null"] = on_null 

6384 

6385 IdentityOptions.__init__( 

6386 self, 

6387 start=start, 

6388 increment=increment, 

6389 minvalue=minvalue, 

6390 maxvalue=maxvalue, 

6391 nominvalue=nominvalue, 

6392 nomaxvalue=nomaxvalue, 

6393 cycle=cycle, 

6394 cache=cache, 

6395 order=order, 

6396 **dialect_kw, 

6397 ) 

6398 self.always = always 

6399 self.column = None 

6400 

6401 @property 

6402 def on_null(self) -> Optional[bool]: 

6403 """Alias of the ``dialect_kwargs`` ``'oracle_on_null'``. 

6404 

6405 .. deprecated:: 2.1 The 'on_null' attribute is deprecated. 

6406 """ 

6407 value: Optional[bool] = self.dialect_kwargs.get("oracle_on_null") 

6408 return value 

6409 

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

6411 assert isinstance(parent, Column) 

6412 if not isinstance( 

6413 parent.server_default, (type(None), Identity) 

6414 ) or not isinstance(parent.server_onupdate, type(None)): 

6415 raise exc.ArgumentError( 

6416 "A column with an Identity object cannot specify a " 

6417 "server_default or a server_onupdate argument" 

6418 ) 

6419 if parent.autoincrement is False: 

6420 raise exc.ArgumentError( 

6421 "A column with an Identity object cannot specify " 

6422 "autoincrement=False" 

6423 ) 

6424 self.column = parent 

6425 

6426 parent.identity = self 

6427 if parent._user_defined_nullable is NULL_UNSPECIFIED: 

6428 parent.nullable = False 

6429 

6430 parent.server_default = self 

6431 

6432 def _as_for_update(self, for_update: bool) -> FetchedValue: 

6433 return self 

6434 

6435 @util.deprecated( 

6436 "1.4", 

6437 "The :meth:`_schema.Identity.copy` method is deprecated " 

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

6439 ) 

6440 def copy(self, **kw: Any) -> Identity: 

6441 return self._copy(**kw) 

6442 

6443 def _copy(self, **kw: Any) -> Identity: 

6444 i = Identity(**self._as_dict(), **self.dialect_kwargs) 

6445 

6446 return self._schema_item_copy(i) 

6447 

6448 def _as_dict(self) -> Dict[str, Any]: 

6449 return { 

6450 # always=None means something different than always=False 

6451 "always": self.always, 

6452 **super()._as_dict(), 

6453 }