Skip to content

Commit ba39474

Browse files
simplified set implementation
1 parent 772f248 commit ba39474

2 files changed

Lines changed: 49 additions & 68 deletions

File tree

elasticsearch/esql/esql.py

Lines changed: 43 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -27,32 +27,16 @@
2727
ExpressionType = Any
2828

2929

30-
class _ESQL(ABC):
30+
class ESQL(ABC):
3131
"""The static methods of the ``ESQL`` class provide access to the ES|QL source
3232
commands, used to create ES|QL queries.
3333
3434
These methods return an instance of class ``ESQLBase``, which provides access to
3535
the ES|QL processing commands.
3636
"""
3737

38-
def __init__(self, parent: Optional["_ESQL"] = None):
39-
self._directives: List[_ESQL] = []
40-
41-
def _render_internal(self) -> str:
42-
return ""
43-
4438
@staticmethod
45-
def _format_id(id: FieldType, allow_patterns: bool = False) -> str:
46-
s = str(id) # in case it is an InstrumentedField
47-
if allow_patterns and "*" in s:
48-
return s # patterns cannot be escaped
49-
if re.fullmatch(r"[a-zA-Z_@][a-zA-Z0-9_\.]*", s):
50-
return s
51-
# this identifier needs to be escaped
52-
s = s.replace("`", "``")
53-
return f"`{s}`"
54-
55-
def from_(self, *indices: IndexType) -> "From":
39+
def from_(*indices: IndexType) -> "From":
5640
"""The ``FROM`` source command returns a table with data from a data stream, index, or alias.
5741
5842
:param indices: A list of indices, data streams or aliases. Supports wildcards and date math.
@@ -65,11 +49,10 @@ def from_(self, *indices: IndexType) -> "From":
6549
query4 = ESQL.from_("cluster_one:employees-00001", "cluster_two:other-employees-*")
6650
query5 = ESQL.from_("employees").metadata("_id")
6751
"""
68-
new_root = From(*indices)
69-
new_root._directives = self._directives.copy()
70-
return new_root
52+
return From(*indices)
7153

72-
def row(self, **params: ExpressionType) -> "Row":
54+
@staticmethod
55+
def row(**params: ExpressionType) -> "Row":
7356
"""The ``ROW`` source command produces a row with one or more columns with values that you specify.
7457
This can be useful for testing.
7558
@@ -81,11 +64,10 @@ def row(self, **params: ExpressionType) -> "Row":
8164
query2 = ESQL.row(a=[1, 2])
8265
query3 = ESQL.row(a=functions.round(1.23, 0))
8366
"""
84-
new_root = Row(**params)
85-
new_root._directives = self._directives.copy()
86-
return new_root
67+
return Row(**params)
8768

88-
def show(self, item: str) -> "Show":
69+
@staticmethod
70+
def show(item: str) -> "Show":
8971
"""The ``SHOW`` source command returns information about the deployment and its capabilities.
9072
9173
:param item: Can only be ``INFO``.
@@ -94,11 +76,10 @@ def show(self, item: str) -> "Show":
9476
9577
query = ESQL.show("INFO")
9678
"""
97-
new_root = Show(item)
98-
new_root._directives = self._directives.copy()
99-
return new_root
79+
return Show(item)
10080

101-
def ts(self, *indices: IndexType) -> "TS":
81+
@staticmethod
82+
def ts(*indices: IndexType) -> "TS":
10283
"""The ``TS`` source command is similar to ``FROM``, but for time series indices.
10384
10485
:param indices: A list of indices, data streams or aliases. Supports wildcards and date math.
@@ -111,11 +92,10 @@ def ts(self, *indices: IndexType) -> "TS":
11192
.stats("SUM(AVG_OVER_TIME(memory_usage)").by("host", "TBUCKET(1 hour)")
11293
)
11394
"""
114-
new_root = TS(*indices)
115-
new_root._directives = self._directives.copy()
116-
return new_root
95+
return TS(*indices)
11796

118-
def branch(self) -> "Branch":
97+
@staticmethod
98+
def branch() -> "Branch":
11999
"""This method can only be used inside a ``FORK`` command to create each branch.
120100
121101
Examples::
@@ -127,28 +107,6 @@ def branch(self) -> "Branch":
127107
"""
128108
return Branch()
129109

130-
def set(self, **params: ExpressionType) -> "_ESQL":
131-
"""The ``SET`` directive can be used to specify query settings that
132-
modify the behavior of an ES|QL query.
133-
134-
Examples::
135-
136-
query1 = (
137-
ESQL.set(approximation=True)
138-
.from_("many_numbers")
139-
.stats(sum="SUM(sv)")
140-
)
141-
query2 = (
142-
ESQL.set(approximation={"rows": 10000})
143-
.from_("many_numbers")
144-
.stats(median="MEDIAN(sv)")
145-
)
146-
"""
147-
new_root = _ESQL()
148-
new_root._directives = self._directives.copy()
149-
new_root._directives.append(Set(**params))
150-
return new_root
151-
152110

153111
class ESQLBase(ABC):
154112
"""The methods of the ``ESQLBase`` class provide access to the ES|QL processing
@@ -157,7 +115,7 @@ class ESQLBase(ABC):
157115

158116
def __init__(self, parent: Optional["ESQLBase"] = None):
159117
self._parent = parent
160-
self._directives: List[_ESQL] = []
118+
self._directives: List["ESQLBase"] = []
161119

162120
def __repr__(self) -> str:
163121
return self.render()
@@ -205,6 +163,32 @@ def _is_forked(self) -> bool:
205163
return self._parent._is_forked()
206164
return False
207165

166+
def _add_directive(self, directive: "ESQLBase") -> None:
167+
if self._parent:
168+
self._parent._add_directive(directive)
169+
else:
170+
self._directives.append(directive)
171+
172+
def set(self, **params: ExpressionType) -> "ESQLBase":
173+
"""The ``SET`` directive can be used to specify query settings that
174+
modify the behavior of an ES|QL query.
175+
176+
Examples::
177+
178+
query1 = (
179+
ESQL.from_("many_numbers")
180+
.stats(sum="SUM(sv)")
181+
.set(approximation=True)
182+
)
183+
query2 = (
184+
ESQL.from_("many_numbers")
185+
.stats(median="MEDIAN(sv)")
186+
.set(approximation={"rows": 10000})
187+
)
188+
"""
189+
self._add_directive(Set(**params))
190+
return self
191+
208192
def change_point(self, value: FieldType) -> "ChangePoint":
209193
"""``CHANGE_POINT`` detects spikes, dips, and change points in a metric.
210194
@@ -1033,7 +1017,7 @@ def _render_internal(self) -> str:
10331017
return ""
10341018

10351019

1036-
class Set(_ESQL):
1020+
class Set(ESQLBase):
10371021
"""Implementation of the ``SET`` query directive.
10381022
10391023
This class inherits from :class:`ESQL <elasticsearch.esql.esql.ESQL>`,
@@ -1044,7 +1028,7 @@ class Set(_ESQL):
10441028
def __init__(self, **params: ExpressionType):
10451029
super().__init__()
10461030
self._params = {
1047-
_ESQL._format_id(k): (
1031+
self._format_id(k): (
10481032
json.dumps(v)
10491033
if not isinstance(v, InstrumentedExpression)
10501034
else ESQLBase._format_expr(v)
@@ -1822,6 +1806,3 @@ def or_(*expressions: InstrumentedExpression) -> "InstrumentedExpression":
18221806
def not_(expression: InstrumentedExpression) -> "InstrumentedExpression":
18231807
"""Negate an expression."""
18241808
return InstrumentedExpression(f"NOT ({expression})")
1825-
1826-
1827-
ESQL = _ESQL()

test_elasticsearch/test_esql.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ def test_ts():
7272

7373

7474
def test_set():
75-
query = ESQL.set(approximation=True).from_("many_numbers").stats(sum="SUM(sv)")
75+
query = ESQL.from_("many_numbers").stats(sum="SUM(sv)").set(approximation=True)
7676
assert (
7777
query.render()
7878
== """SET approximation = true;
@@ -81,9 +81,9 @@ def test_set():
8181
)
8282

8383
query = (
84-
ESQL.set(approximation={"rows": 10000})
85-
.from_("many_numbers")
84+
ESQL.from_("many_numbers")
8685
.stats(median="MEDIAN(sv)")
86+
.set(approximation={"rows": 10000})
8787
)
8888
assert (
8989
query.render()
@@ -92,11 +92,11 @@ def test_set():
9292
| STATS median = MEDIAN(sv)"""
9393
)
9494

95-
query = ESQL.set(approximation=True).row(a=1)
95+
query = ESQL.row(a=1).set(approximation=True)
9696
assert query.render() == "SET approximation = true;\nROW a = 1"
97-
query = ESQL.set(approximation=True).show("INFO")
97+
query = ESQL.show("INFO").set(approximation=True)
9898
assert query.render() == "SET approximation = true;\nSHOW INFO"
99-
query = ESQL.set(approximation=True).ts("many_numbers")
99+
query = ESQL.ts("many_numbers").set(approximation=True)
100100
assert query.render() == "SET approximation = true;\nTS many_numbers"
101101

102102

0 commit comments

Comments
 (0)