1# dialects/postgresql/ranges.py
2# Copyright (C) 2013-2024 the SQLAlchemy authors and contributors
3# <see AUTHORS file>
4#
5# This module is part of SQLAlchemy and is released under
6# the MIT License: https://www.opensource.org/licenses/mit-license.php
7
8from ... import types as sqltypes
9
10
11__all__ = ("INT4RANGE", "INT8RANGE", "NUMRANGE")
12
13
14class RangeOperators(object):
15 """
16 This mixin provides functionality for the Range Operators
17 listed in the Range Operators table of the `PostgreSQL documentation`__
18 for Range Functions and Operators. It is used by all the range types
19 provided in the ``postgres`` dialect and can likely be used for
20 any range types you create yourself.
21
22 __ https://www.postgresql.org/docs/current/static/functions-range.html
23
24 No extra support is provided for the Range Functions listed in the Range
25 Functions table of the PostgreSQL documentation. For these, the normal
26 :func:`~sqlalchemy.sql.expression.func` object should be used.
27
28 """
29
30 class comparator_factory(sqltypes.Concatenable.Comparator):
31 """Define comparison operations for range types."""
32
33 def __ne__(self, other):
34 "Boolean expression. Returns true if two ranges are not equal"
35 if other is None:
36 return super(RangeOperators.comparator_factory, self).__ne__(
37 other
38 )
39 else:
40 return self.expr.op("<>", is_comparison=True)(other)
41
42 def contains(self, other, **kw):
43 """Boolean expression. Returns true if the right hand operand,
44 which can be an element or a range, is contained within the
45 column.
46
47 kwargs may be ignored by this operator but are required for API
48 conformance.
49 """
50 return self.expr.op("@>", is_comparison=True)(other)
51
52 def contained_by(self, other):
53 """Boolean expression. Returns true if the column is contained
54 within the right hand operand.
55 """
56 return self.expr.op("<@", is_comparison=True)(other)
57
58 def overlaps(self, other):
59 """Boolean expression. Returns true if the column overlaps
60 (has points in common with) the right hand operand.
61 """
62 return self.expr.op("&&", is_comparison=True)(other)
63
64 def strictly_left_of(self, other):
65 """Boolean expression. Returns true if the column is strictly
66 left of the right hand operand.
67 """
68 return self.expr.op("<<", is_comparison=True)(other)
69
70 __lshift__ = strictly_left_of
71
72 def strictly_right_of(self, other):
73 """Boolean expression. Returns true if the column is strictly
74 right of the right hand operand.
75 """
76 return self.expr.op(">>", is_comparison=True)(other)
77
78 __rshift__ = strictly_right_of
79
80 def not_extend_right_of(self, other):
81 """Boolean expression. Returns true if the range in the column
82 does not extend right of the range in the operand.
83 """
84 return self.expr.op("&<", is_comparison=True)(other)
85
86 def not_extend_left_of(self, other):
87 """Boolean expression. Returns true if the range in the column
88 does not extend left of the range in the operand.
89 """
90 return self.expr.op("&>", is_comparison=True)(other)
91
92 def adjacent_to(self, other):
93 """Boolean expression. Returns true if the range in the column
94 is adjacent to the range in the operand.
95 """
96 return self.expr.op("-|-", is_comparison=True)(other)
97
98 def __add__(self, other):
99 """Range expression. Returns the union of the two ranges.
100 Will raise an exception if the resulting range is not
101 contiguous.
102 """
103 return self.expr.op("+")(other)
104
105
106class INT4RANGE(RangeOperators, sqltypes.TypeEngine):
107 """Represent the PostgreSQL INT4RANGE type."""
108
109 __visit_name__ = "INT4RANGE"
110
111
112class INT8RANGE(RangeOperators, sqltypes.TypeEngine):
113 """Represent the PostgreSQL INT8RANGE type."""
114
115 __visit_name__ = "INT8RANGE"
116
117
118class NUMRANGE(RangeOperators, sqltypes.TypeEngine):
119 """Represent the PostgreSQL NUMRANGE type."""
120
121 __visit_name__ = "NUMRANGE"
122
123
124class DATERANGE(RangeOperators, sqltypes.TypeEngine):
125 """Represent the PostgreSQL DATERANGE type."""
126
127 __visit_name__ = "DATERANGE"
128
129
130class TSRANGE(RangeOperators, sqltypes.TypeEngine):
131 """Represent the PostgreSQL TSRANGE type."""
132
133 __visit_name__ = "TSRANGE"
134
135
136class TSTZRANGE(RangeOperators, sqltypes.TypeEngine):
137 """Represent the PostgreSQL TSTZRANGE type."""
138
139 __visit_name__ = "TSTZRANGE"