Quote column name if it is a Kusto keyword + workaround (#72)

This commit is contained in:
Yonatan Most 2020-05-07 11:30:44 +03:00 коммит произвёл GitHub
Родитель 4232fc8aee
Коммит 896d617d1a
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
3 изменённых файлов: 169 добавлений и 2 удалений

Просмотреть файл

@ -2,6 +2,7 @@ from datetime import datetime, timedelta
from typing import Any, List, Tuple, Mapping, Optional
from typing import Union
from pykusto.keywords import KUSTO_KEYWORDS
from pykusto.kql_converters import KQL
from pykusto.type_utils import plain_expression, aggregation_expression, PythonTypes, kql_converter, KustoType, typed_column, TypeRegistrar, get_base_types
@ -786,8 +787,8 @@ class BaseColumn(BaseExpression):
assert cls is not BaseColumn, "BaseColumn is abstract"
return object.__new__(cls)
def __init__(self, name: str) -> None:
super().__init__(KQL(f"['{name}']" if '.' in name else name))
def __init__(self, name: str, quote: bool = False) -> None:
super().__init__(KQL(f"['{name}']" if quote or '.' in name or name in KUSTO_KEYWORDS else name))
self._name = name
def get_name(self) -> str:
@ -872,6 +873,13 @@ class ColumnGenerator:
def __getitem__(self, name: str) -> AnyTypeColumn:
return AnyTypeColumn(name)
# noinspection PyMethodMayBeStatic
def of(self, name: str) -> AnyTypeColumn:
"""
Workaround in case automatic column name quoting fails
"""
return AnyTypeColumn(name, quote=True)
# Recommended usage: from pykusto.expressions import column_generator as col
# TODO: Is there a way to enforce this to be a singleton?

149
pykusto/keywords.py Normal file
Просмотреть файл

@ -0,0 +1,149 @@
# noinspection SpellCheckingInspection
KUSTO_KEYWORDS = frozenset([
'abs',
'accumulate',
'acos',
'ago',
'and',
'anomalychart',
'anomalycolumns',
'areachart',
'array_concat',
'array_iif',
'array_index_of',
'array_length',
'array_rotate_left',
'array_rotate_right',
'array_shift_left',
'array_shift_right',
'array_slice',
'array_split',
'avg',
'avgif',
'axes',
'bag_keys',
'barchart',
'bin',
'bin',
'bin',
'bin_at',
'bin_auto',
'card',
'ceiling',
'columnchart',
'contains',
'cos',
'countif',
'dcount',
'dcount_hll',
'dcountif',
'dynamic',
'endofday',
'endofmonth',
'endofweek',
'endofyear',
'endswith',
'exp',
'floor',
'format_datetime',
'format_timespan',
'getmonth',
'gettype',
'getyear',
'hash',
'hourofday',
'iff',
'iif',
'in',
'isempty',
'isfinite',
'isinf',
'isnan',
'isnotempty',
'isnotnull',
'isnull',
'kind',
'ladderchart',
'legend',
'linechart',
'log',
'loggamma',
'make_bag',
'make_datetime',
'make_list',
'make_set',
'matches',
'max',
'maxif',
'min',
'minif',
'none',
'not',
'now',
'or',
'pack',
'pack_array',
'panels',
'parse_json',
'percentiles',
'piechart',
'pivotchart',
'pow',
'regex',
'round',
'scatterchart',
'series',
'set_difference',
'set_has_element',
'set_intersect',
'set_union',
'sign',
'split',
'sqrt',
'stacked',
'stacked100',
'stackedareachart',
'startofday',
'startofmonth',
'startofweek',
'startofyear',
'startswith',
'stdev',
'stdevif',
'stdevp',
'strcat_array',
'strcat_delim',
'strcmp',
'string_size',
'strlen',
'strrep',
'substring',
'sum',
'sumif',
'table',
'timechart',
'timepivot',
'title',
'tobool',
'todatetime',
'tohex',
'toint',
'tolong',
'tolower',
'tostring',
'toupper',
'unstacked',
'variance',
'varianceif',
'variancep',
'xaxis',
'xcolumn',
'xtitle',
'yaxis',
'ycolumns',
'ymax',
'ymin',
'ysplit',
'ysplit',
'ytitle',
])

Просмотреть файл

@ -349,3 +349,13 @@ class TestExpressions(TestBase):
self.assertIsInstance(field2, AnyTypeColumn)
self.assertEqual('foo', field1.get_name())
self.assertEqual('foo.bar', field2.get_name())
def test_column_name_quoting(self):
self.assertEqual(
' | where [\'title\'] has "test"',
Query().where(t.title.has("test")).render()
)
self.assertEqual(
' | where [\'stringField\'] has "test"',
Query().where(col.of('stringField').has("test")).render()
)