Собственный синтаксис Tengri

В Tengri реализованы собственные синтаксические конструкции и ключевые слова для удобной работы на нескольких языках (SQL и Python) в единой среде.

Ключевое слово cell_output

Ключевое слово cell_output используется в ячейках типа Python для обращения к результату предыдущей ячейки типа SQL. С помощью этого ключевого слова удобно переходить с SQL на Python при работе с данными внутри одного ноутбука.

Данные в cell_output записываются в виде Pandas DataFrame.

Ключевое слово cell_output интерпретируется для каждой ячейки, а не для всего ноутбука. Это значит, что значения, записанные в cell_output, могут быть разными в разных ячейках типа Python внутри одного ноутбука в зависимости от предыдущих ячеек типа SQL. Поэтому рекомендуется записывать содержимое переменной cell_output в новую переменную, если предполагается работать с этими данными в нескольких ячейках Python (как это показано в примере ниже).

Пример

Выполним ячейку типа SQL с запросом SELECT на вывод чисел от 1 до 5. Для этого используем функции unnest и generate_series:

SELECT unnest(generate_series(1,5)) as numbers;
+---------+
| numbers |
+---------+
| 1       |
+---------+
| 2       |
+---------+
| 3       |
+---------+
| 4       |
+---------+
| 5       |
+---------+

В следующей ячейке типа Python того же ноутбука обратимся к выведенной в предыдущей ячейке таблице через ключевое слово cell_output:

# Выведем значение переменной cell_output
print(cell_output)
print()

# Выведем тип переменной cell_output
print(type(cell_output))
print()

# Запишем значение переменной cell_output в новую переменную
df = cell_output

# Отфильтруем значения в DataFrame по условию на колонку, используя новую переменную
print(df.loc[df['numbers'] > 2])
numbers
0        1
1        2
2        3
3        4
4        5

<class 'pandas.core.frame.DataFrame'>

   numbers
2        3
3        4
4        5

Мы видим, что содержимое переменной cell_output в этой ячейке представляет собой DataFrame с данными, взятыми из результата предыдущей ячейки. С этим DataFrame можно работать с помощью любых стандартных средств Python.


Реальные примеры использования ключевого слова cell_output можно увидеть в сценариях:

Кросс-языковые переменные

В Tengri реализован специальный синтаксис для единообразного задания переменных в SQL и в Python. Эти переменные задаются на уровне ноутбука, и их можно использовать в любых ячейках независимо от языка.

Значения переменных задаются через графический интерфейс во вкладке Variables (Переменные). Имена переменных появляются в списке в этой вкладке в тот момент, когда конструкция с ними записывается в ячейку с кодом. Чтобы создать переменную, достаточно просто записать ее в коде — никаких специальных действий для инициализации не требуется.

Переменные можно использовать в коде в двух вариантах: в виде строковых значений и в виде "сырых" значений.

Строковые значения

Синтаксис для SQL и Python:

{@ variable_name @}

"Сырые" значения

Синтаксис SQL и Python:

{@ raw variable_name @}

Указание дефолтного значения

При необходимости можно указать дефолтное значение, которое примет переменная, если оставить поле для значения данной переменной во вкладке Variables (Переменные) пустым.

Синтаксис SQL и Python:

{@ variable_name | default_value @}
{@ raw variable_name | default_value @}

Примеры

Запишем через графический интерфейс в переменную my_var значение my_value.

Выполним код в ячейке типа Python, используя строковые значения:

print({@ my_var @})
my_value

Выполним код в ячейке типа SQL, используя строковые значения:

SELECT {@ my_var @} AS my_column
+-----------+
| my_column |
+-----------+
| my_value  |
+-----------+

Выполним код в ячейке типа Python, используя "сырые" значения:

print({@ raw my_var @}) # Error expected
NameError: name 'my_value' is not defined
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In[12], line 1
----> 1 print(my_value)
NameError: name 'my_value' is not defined

Ожидаемо получаем ошибку NameError, так как переменная с именем my_value не была задана.


Зададим эту переменную и выведем ее значение:

{@ raw my_var @} = 2025

print({@ raw my_var @})
2025

Выполним код в ячейке типа SQL, используя "сырые" значения:

SELECT {@ raw my_var @} AS my_column -- Error expected
ERROR: BinderException: Binder Error: Referenced column "my_value" not found in FROM clause!

Ожидаемо получаем ошибку BinderException, так как в запросе есть колонка my_value, но ее нет в таблице, откуда делается SELECT.


Выполним код в ячейке типа SQL, используя "сырые" значения, но так, чтобы "сырое" значение переменной задавало имя колонки:

SELECT 2025 AS {@ raw my_var @}
+----------+
| my_value |
+----------+
| 2025     |
+----------+

Оставим поле для значения переменной пустым и выполним код в ячейке типа SQL:

SELECT {@ my_var | my_default_value @} AS my_column
+------------------+
| my_column        |
+------------------+
| my_default_value |
+------------------+

Использование кросс-языковых переменных возможно в том числе в случае интерполяции строк в Python:

print(f'my_var: {{@ my_var @}}')

print('my_var: {}'.format({@ my_var @}))
my_var: my_value
my_var: my_value