Represent a SQL tuple.
| 3504 | |
| 3505 | |
| 3506 | class Tuple(ClauseList, ColumnElement[TupleAny]): |
| 3507 | """Represent a SQL tuple.""" |
| 3508 | |
| 3509 | __visit_name__ = "tuple" |
| 3510 | |
| 3511 | _traverse_internals: _TraverseInternalsType = ( |
| 3512 | ClauseList._traverse_internals + [] |
| 3513 | ) |
| 3514 | |
| 3515 | type: TupleType |
| 3516 | |
| 3517 | @util.preload_module("sqlalchemy.sql.sqltypes") |
| 3518 | def __init__( |
| 3519 | self, |
| 3520 | *clauses: _ColumnExpressionArgument[Any], |
| 3521 | types: Optional[Sequence[_TypeEngineArgument[Any]]] = None, |
| 3522 | ): |
| 3523 | sqltypes = util.preloaded.sql_sqltypes |
| 3524 | |
| 3525 | if types is None: |
| 3526 | init_clauses: List[ColumnElement[Any]] = [ |
| 3527 | coercions.expect(roles.ExpressionElementRole, c) |
| 3528 | for c in clauses |
| 3529 | ] |
| 3530 | else: |
| 3531 | if len(types) != len(clauses): |
| 3532 | raise exc.ArgumentError( |
| 3533 | "Wrong number of elements for %d-tuple: %r " |
| 3534 | % (len(types), clauses) |
| 3535 | ) |
| 3536 | init_clauses = [ |
| 3537 | coercions.expect( |
| 3538 | roles.ExpressionElementRole, |
| 3539 | c, |
| 3540 | type_=typ if not typ._isnull else None, |
| 3541 | ) |
| 3542 | for typ, c in zip(types, clauses) |
| 3543 | ] |
| 3544 | |
| 3545 | self.type = sqltypes.TupleType(*[arg.type for arg in init_clauses]) |
| 3546 | super().__init__(*init_clauses) |
| 3547 | |
| 3548 | @property |
| 3549 | def _select_iterable(self) -> _SelectIterable: |
| 3550 | return (self,) |
| 3551 | |
| 3552 | def _bind_param(self, operator, obj, type_=None, expanding=False): |
| 3553 | if expanding: |
| 3554 | return BindParameter( |
| 3555 | None, |
| 3556 | value=obj, |
| 3557 | _compared_to_operator=operator, |
| 3558 | unique=True, |
| 3559 | expanding=True, |
| 3560 | type_=type_, |
| 3561 | _compared_to_type=self.type, |
| 3562 | ) |
| 3563 | else: |
no outgoing calls
no test coverage detected