mirror of
https://github.com/PostHog/posthog.git
synced 2024-12-01 12:21:02 +01:00
f36495bec6
* Don't colorize sql for output * Handle setting array props as values * Handle arrays exact/is_not property filters Also updates tests to use parameterization * Avoid autoclosing PropertyFilter popup As key changes, old one got removed from DOM * Improve filter UX Don't allow filter to become multi-line and keep inputs the same size. Previous flex={1} was doing flex: 1 1 auto which was messing things up * Fix typescript issue * Handle array lookups in postgres * Update types * Fix fixture to recreate tables * Make replace spaces logic consistent with what was there before * Handle list filtering better in postgres * Update frontend tests * Handle edge case: Switching between multi operator and single operators
86 lines
2.3 KiB
Python
86 lines
2.3 KiB
Python
import json
|
|
from typing import Optional, Union
|
|
|
|
import pytz
|
|
from dateutil.parser import isoparse
|
|
from django.utils import timezone
|
|
|
|
from posthog.models.property import Property
|
|
|
|
|
|
def get_operator(prop: Property, arg: str):
|
|
operator = prop.operator
|
|
|
|
if operator == "is_not":
|
|
return "(trim(BOTH '\"' FROM ep.value) = %({})s)".format(arg), prop.value
|
|
elif operator == "icontains" or operator == "not_icontains":
|
|
value = "%{}%".format(prop.value)
|
|
return "(trim(BOTH '\"' FROM ep.value) LIKE %({})s)".format(arg), value
|
|
elif operator == "regex" or operator == "not_regex":
|
|
return "match(trim(BOTH '\"' FROM ep.value), %({})s)".format(arg), prop.value
|
|
elif operator == "is_set":
|
|
return "", prop.value
|
|
elif operator == "is_not_set":
|
|
return "", prop.value
|
|
elif operator == "gt":
|
|
return (
|
|
"(toInt64(trim(BOTH '\"' FROM ep.value)) > %({})s)".format(arg),
|
|
prop.value,
|
|
)
|
|
elif operator == "lt":
|
|
return (
|
|
"(toInt64(trim(BOTH '\"' FROM ep.value)) < %({})s)".format(arg),
|
|
prop.value,
|
|
)
|
|
else:
|
|
if is_json(prop.value):
|
|
return (
|
|
"replaceRegexpAll(trim(BOTH '\"' FROM ep.value),' ', '') = replaceRegexpAll(toString(%({})s),' ', '')".format(
|
|
arg
|
|
),
|
|
prop.value,
|
|
)
|
|
else:
|
|
return (
|
|
"(trim(BOTH '\"' FROM ep.value) = toString(%({})s))".format(arg),
|
|
prop.value,
|
|
)
|
|
|
|
|
|
def is_json(val):
|
|
if isinstance(val, int):
|
|
return False
|
|
|
|
try:
|
|
int(val)
|
|
return False
|
|
except:
|
|
pass
|
|
try:
|
|
json.loads(val)
|
|
except (ValueError, TypeError):
|
|
return False
|
|
return True
|
|
|
|
|
|
def is_int(value: Optional[Union[str, int]]) -> bool:
|
|
try:
|
|
int(value) # type: ignore
|
|
except (ValueError, TypeError):
|
|
return False
|
|
else:
|
|
return True
|
|
|
|
|
|
def cast_timestamp_or_now(timestamp: Optional[Union[timezone.datetime, str]]) -> str:
|
|
if not timestamp:
|
|
timestamp = timezone.now()
|
|
|
|
# clickhouse specific formatting
|
|
if isinstance(timestamp, str):
|
|
timestamp = isoparse(timestamp)
|
|
else:
|
|
timestamp = timestamp.astimezone(pytz.utc)
|
|
|
|
return timestamp.strftime("%Y-%m-%d %H:%M:%S.%f")
|