Represent a SQL tuple.
| 3221 | |
| 3222 | |
| 3223 | class Tuple(ClauseList, ColumnElement[typing_Tuple[Any, ...]]): |
| 3224 | """Represent a SQL tuple.""" |
| 3225 | |
| 3226 | __visit_name__ = "tuple" |
| 3227 | |
| 3228 | _traverse_internals: _TraverseInternalsType = ( |
| 3229 | ClauseList._traverse_internals + [] |
| 3230 | ) |
| 3231 | |
| 3232 | type: TupleType |
| 3233 | |
| 3234 | @util.preload_module("sqlalchemy.sql.sqltypes") |
| 3235 | def __init__( |
| 3236 | self, |
| 3237 | *clauses: _ColumnExpressionArgument[Any], |
| 3238 | types: Optional[Sequence[_TypeEngineArgument[Any]]] = None, |
| 3239 | ): |
| 3240 | sqltypes = util.preloaded.sql_sqltypes |
| 3241 | |
| 3242 | if types is None: |
| 3243 | init_clauses: List[ColumnElement[Any]] = [ |
| 3244 | coercions.expect(roles.ExpressionElementRole, c) |
| 3245 | for c in clauses |
| 3246 | ] |
| 3247 | else: |
| 3248 | if len(types) != len(clauses): |
| 3249 | raise exc.ArgumentError( |
| 3250 | "Wrong number of elements for %d-tuple: %r " |
| 3251 | % (len(types), clauses) |
| 3252 | ) |
| 3253 | init_clauses = [ |
| 3254 | coercions.expect( |
| 3255 | roles.ExpressionElementRole, |
| 3256 | c, |
| 3257 | type_=typ if not typ._isnull else None, |
| 3258 | ) |
| 3259 | for typ, c in zip(types, clauses) |
| 3260 | ] |
| 3261 | |
| 3262 | self.type = sqltypes.TupleType(*[arg.type for arg in init_clauses]) |
| 3263 | super().__init__(*init_clauses) |
| 3264 | |
| 3265 | @property |
| 3266 | def _select_iterable(self) -> _SelectIterable: |
| 3267 | return (self,) |
| 3268 | |
| 3269 | def _bind_param(self, operator, obj, type_=None, expanding=False): |
| 3270 | if expanding: |
| 3271 | return BindParameter( |
| 3272 | None, |
| 3273 | value=obj, |
| 3274 | _compared_to_operator=operator, |
| 3275 | unique=True, |
| 3276 | expanding=True, |
| 3277 | type_=type_, |
| 3278 | _compared_to_type=self.type, |
| 3279 | ) |
| 3280 | else: |
no outgoing calls
no test coverage detected