diff --git a/pykusto/_src/expressions.py b/pykusto/_src/expressions.py index 4a4c05d..ac8de74 100644 --- a/pykusto/_src/expressions.py +++ b/pykusto/_src/expressions.py @@ -523,6 +523,13 @@ class _StringExpression(BaseExpression): f'{self.as_subexpression()} {"!has_cs" if case_sensitive else "!has"} {_to_kql(exp, True)}' )) + def has_any(self, other: ArrayType) -> '_BooleanExpression': + """ + https://docs.microsoft.com/en-us/azure/data-explorer/kusto/query/has-anyoperator + """ + assert isinstance(other, (List, Tuple)), "Compared array must be a list of tabular, scalar, or literal expressions" + return _BooleanExpression(KQL(f'{self.kql} has_any ({", ".join(map(_to_kql, other))})')) + @_plain_expression(_KustoType.DATETIME) class _DatetimeExpression(BaseExpression): diff --git a/pykusto/_src/functions.py b/pykusto/_src/functions.py index fe0c1a3..cc25227 100644 --- a/pykusto/_src/functions.py +++ b/pykusto/_src/functions.py @@ -645,11 +645,11 @@ class Functions: return _NumberExpression(KQL(f'pow({_to_kql(expr1)}, {_to_kql(expr2)})')) # def radians(self): return - # - # - # def rand(self): return - # - # + + @staticmethod + def rand(n: NumberType = None): + return _NumberExpression(KQL("rand()") if n is None else f'rand({_to_kql(n)})') + # def range(self): return # # @@ -1208,7 +1208,7 @@ class Functions: return _NumberAggregationExpression(KQL(f'dcount({_to_kql(expr)})' if accuracy is None else f'dcount({_to_kql(expr)}, {_to_kql(accuracy)})')) @staticmethod - def dcount_if(expr: ExpressionType, predicate: BooleanType, accuracy: NumberType = 0) -> _NumberAggregationExpression: + def dcount_if(expr: ExpressionType, predicate: BooleanType, accuracy: NumberType = 1) -> _NumberAggregationExpression: """ https://docs.microsoft.com/en-us/azure/data-explorer/kusto/query/dcountif-aggfunction """ diff --git a/test/test_expressions.py b/test/test_expressions.py index df4ebdd..e05b2db 100644 --- a/test/test_expressions.py +++ b/test/test_expressions.py @@ -450,6 +450,16 @@ class TestExpressions(TestBase): Query().where(t.stringField.has("test", case_sensitive=True)).render() ) + def test_has_any(self): + self.assertEqual( + ' | where stringField has_any ("field", "string")', + Query().where(t.stringField.has_any(["field", "string"])).render() + ) + self.assertRaises( + AssertionError("Compared array must be a list of tabular, scalar, or literal expressions"), + lambda: t.stringField.has_any(t.stringField2) + ) + def test_column_generator(self): field1 = col.foo field2 = col['foo.bar'] diff --git a/test/test_functions.py b/test/test_functions.py index 5704b35..698ec9f 100644 --- a/test/test_functions.py +++ b/test/test_functions.py @@ -621,6 +621,17 @@ class TestFunction(TestBase): ' | where (trim("--", stringField)) == "text"', Query().where(f.trim("--", t.stringField) == "text").render() ) + + def test_rand(self): + self.assertEqual( + " | extend rnd = rand()", + Query().extend(rnd=f.rand()).render() + ) + self.assertEqual( + " | extend rnd = rand(5)", + Query().extend(rnd=f.rand(5)).render() + ) + # ------------------------------------------------------ # Aggregation Functions # ------------------------------------------------------ @@ -772,7 +783,7 @@ class TestFunction(TestBase): def test_dcountif(self): self.assertEqual( - " | summarize dcountif(stringField, boolField, 0)", + " | summarize dcountif(stringField, boolField, 1)", Query().summarize(f.dcount_if(t.stringField, t.boolField)).render() )