@roll-agent/octopus-agent 0.1.1 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json
CHANGED
package/pyproject.toml
CHANGED
|
@@ -970,18 +970,55 @@ def _concept_time_range_field_issue(
|
|
|
970
970
|
return None
|
|
971
971
|
|
|
972
972
|
|
|
973
|
+
_TIME_RANGE_DATE_LITERAL = r"'20\d{2}-\d{1,2}-\d{1,2}(?:\s+\d{1,2}:\d{2}:\d{2})?'"
|
|
974
|
+
|
|
975
|
+
|
|
973
976
|
def _sql_has_time_filter_for_range(sql: str, time_range: TimeRange) -> bool:
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
977
|
+
if _scope_has_time_filter_for_range(sql, time_range):
|
|
978
|
+
return True
|
|
979
|
+
for subquery in _sql_derived_subqueries(sql).values():
|
|
980
|
+
if _sql_has_time_filter_for_range(subquery, time_range):
|
|
981
|
+
return True
|
|
982
|
+
return False
|
|
983
|
+
|
|
984
|
+
|
|
985
|
+
def _mask_derived_subqueries(sql: str) -> str:
|
|
986
|
+
spans = _sql_derived_subquery_spans(sql)
|
|
987
|
+
if not spans:
|
|
988
|
+
return sql
|
|
989
|
+
chars = list(sql)
|
|
990
|
+
for start, end in spans:
|
|
991
|
+
for index in range(start, min(end, len(chars))):
|
|
992
|
+
chars[index] = " "
|
|
993
|
+
return "".join(chars)
|
|
994
|
+
|
|
995
|
+
|
|
996
|
+
def _scope_has_time_filter_for_range(sql: str, time_range: TimeRange) -> bool:
|
|
997
|
+
"""Return True if the designated time field is compared to a date literal in this
|
|
998
|
+
query scope.
|
|
999
|
+
|
|
1000
|
+
Nested derived subqueries are masked out here and evaluated separately by
|
|
1001
|
+
``_sql_has_time_filter_for_range`` so alias resolution stays scoped. The check
|
|
1002
|
+
scans the whole scope (not just the top-level WHERE) so the field can satisfy the
|
|
1003
|
+
requirement whether it is used in WHERE or inside a conditional aggregate such as
|
|
1004
|
+
``SUM(CASE WHEN sign_up_time >= ... THEN 1 ELSE 0 END)``, which some schema concepts
|
|
1005
|
+
mandate for period metrics.
|
|
1006
|
+
"""
|
|
1007
|
+
scope_text = _mask_derived_subqueries(sql)
|
|
1008
|
+
op = r"(?:>=|<=|>|<|=)"
|
|
1009
|
+
date = _TIME_RANGE_DATE_LITERAL
|
|
1010
|
+
field_patterns: list[str] = [_time_range_sql_field_pattern(scope_text, time_range)]
|
|
1011
|
+
base_tables = set(_sql_top_level_table_aliases(scope_text).values())
|
|
1012
|
+
if not time_range.table_name or base_tables == {time_range.table_name.lower()}:
|
|
1013
|
+
# Single base table in scope: an unqualified column reference is unambiguous.
|
|
1014
|
+
field_patterns.append(rf"(?<![.\w]){re.escape(time_range.field.lower())}\b")
|
|
1015
|
+
for field_pattern in field_patterns:
|
|
1016
|
+
checks = (
|
|
1017
|
+
rf"{field_pattern}\s*{op}\s*{date}",
|
|
1018
|
+
rf"{date}\s*{op}\s*{field_pattern}",
|
|
1019
|
+
rf"{field_pattern}\s+between\s+{date}\s+and\s+{date}",
|
|
1020
|
+
)
|
|
1021
|
+
if any(re.search(pattern, scope_text, flags=re.IGNORECASE) for pattern in checks):
|
|
985
1022
|
return True
|
|
986
1023
|
return False
|
|
987
1024
|
|