Лексическая структура

Запрос на языке YQL представляет собой валидный UTF-8 текст, который состоит из команд (statement) разделенных символом точка с запятой (;).
Последняя точка с запятой при этом может отсутствовать.
Каждая команда, в свою очередь, состоит из последовательности токенов допустимых для данной команды.
Токеном может быть ключевое слово, идентификатор, литерал и другие.
Токены разделяются пробельными символами (пробел, табуляция, перевод строки) либо комментариями. Комментарий не является частью команды и синтаксически эквивалентен пробельному символу.

Режимы совместимости синтаксиса

Поддерживаются два режима совместимости синтаксиса:

  • Расширенный C++ (по-умолчанию)
  • ANSI SQL

Режим ANSI SQL включается с помощью специального комментария --!ansi-lexer, который должен стоять в начале запроса.

Особенности интерпретации лексических элементов в разных режимах совместимости описаны ниже.

Комментарии

Поддерживаются следующие виды комментариев:

  • Однострочные: начинается с последовательности символов -- (два минуса подряд) и продолжается до конца строки
  • Многострочные: начинается с последовательности символов /* и заканчивается на последовательности символов */
SELECT 1; -- A single-line comment
/*
   Some multi-line comment
*/

В режиме совместимости синтаксиса C++ (по-умолчанию) многострочный комментарий заканчивается на ближайшей последовательности символов */.
В режиме совместимости синтаксиса ANSI SQL учитывается вложенность многострочных комментариев:

--!ansi_lexer
SELECT * FROM T; /* комментарий /* вложенный комментарий, без ansi_lexer будет ошибка  */ */

Ключевые слова и идентификаторы

Ключевые слова – это токены, имеющее фиксированное значение в языке YQL. Примеры ключевых слов – SELECT, INSERT, FROM, ACTION и т.д. Ключевые слова регистронезависимы, то есть SELECT и SeLEcT эквивалентны.
Список ключевых слов не фиксирован – по мере развития языка он будет расширяться. Ключевое слово не может содержать цифры и начинаться или заканчиваться символом подчеркивания.

Идентификаторы – это токены, которые идентифицируют имена таблиц, колонок и других объектов в YQL. Идентификаторы в YQL всегда регистрозависимы.
Идентификатор может быть записан в теле программы без специального оформления, если он:

  • Не является ключевым словом
  • Начинается с латинской буквы или подчеркивания
  • Последующими символами могут быть латинская буква, подчеркивание или цифра
SELECT my_column FROM my_table; -- my_column and my_table are identifiers

Для записи в теле запроса произвольного идентификатора он заключается в обратные кавычки (бэктики):

SELECT `column with space` from T;
SELECT * FROM `my_dir/my_table`

Идентификатор в обратных кавычках никогда не интерпретируется как ключевое слово:

SELECT `select` FROM T; -- select - имя колонки в таблице T

При использовании обратных кавычек применим стандартный C-эскейпинг:

SELECT 1 as `column with\n newline, \x0a newline and \` backtick `;

В режиме совместимости синтаксиса ANSI SQL произвольные идентификаторы также могут быть выделены заключением их в двойные кавычки. Для включения двойной кавычки в идентификатор в кавычках она должна быть удвоена:

--!ansi_lexer
SELECT 1 as "column with "" double quoute"; -- имя колонки будет: column with " double quoute

SQL хинты

SQL хинты – это специальные настройки, которые позволяют пользователю влиять на план выполнения запроса
(например, включать/выключать определенные оптимизации, форсировать стратегию JOIN-а и т.п.).
В отличие от PRAGMA, SQL хинты обладают локальным действием – они привязаны к определенной точке YQL запроса (обычно следуют после ключевого слова)
и влияют только на соответствующий statement или даже его часть.
SQL хинты представляют собой набор настроек "имя-список значений" и задаются внутри комментариев специального вида –
первым символом комментария с SQL хинтами должен быть +:

--+ Name1(Value1 Value2 Value3) Name2(Value4) ...

Имя SQL хинта должно состоять из алфавтно-цифровых ASCII символов и начинаться с буквы. Регистр букв в имени хинта игнорируется.
После имени хинта в скобках задается произвольное количество значений, разделенных пробелами. В качестве значения может выступать произвольный набор символов.
Если в наборе символов значения имеется пробел или скобка, то необходимо использовать одинарные кавычки:

--+ foo('value with space and paren)')
--+ foo('value1' value2)
-- эквивалетно
--+ foo(value1 value2)

Одинарную кавычку внутри значения необходимо эскейпить путем дублирования:

--+ foo('value with single quote '' inside')

Неизвестные имена SQL хинтов (либо синтаксически некорректные хинты) никогда не вызывают ошибок – они просто игнорируется:

--+ foo(value1) bar(value2  baz(value3)
-- из-за пропущенной закрывающей скобки в bar эквивалетно
--+ foo(value1)

Такое поведение связано с нежеланием ломать написанные ранее валидные YQL запросы с комментариями, которые похожи на хинты.
При этом синтаксически корректные SQL хинты в неожиданном для YQL месте вызывают предупреждение:

-- в данный момент хинты после SELECT не поддерживаются
SELECT /*+ foo(123) */ 1; -- предупреждение 'Hint foo will not be used'

Хочется заметить, что SQL хинты – это именно подсказки оптимизатору, поэтому:

  • хинты никогда не влияют на результат запроса
  • по мере развития оптимизаторов в YQL вполне возможна ситуация, в которой хинт становится неактуальным и начнет игнорироваться (например, полностью поменялся алгоритм, который настраивался данным хинтом, либо оптимизатор настолько улучшился, что гарантированно выбирает оптимальное решение, поэтому какие-то ручные настройки будут скорее вредить)

Строковые литералы

Строковый литерал (константа) записывается как последовательность символов, заключенных в одинарные кавычки. Внутри строкового литерала можно использовать правила эскейпинга в стиле C:

SELECT 'string with\n newline, \x0a newline and \' backtick ';

В режиме совместимости синтаксиса С++ (по-умолчанию) разрешается использовать вместо одинарных кавычек двойные:

SELECT "string with\n newline, \x0a newline and \" backtick ";

В режиме совместимости синтаксиса ASNI SQL двойные кавычки используются для идентификаторов, а единственный вид эскепинга который действует для строковых литералов – это дублирование символа одиночной кавычки:

--!ansi_lexer
SELECT 'string with '' quote'; -- результат: string with ' quote

На основании строковых литералов могут быть получены литералы простых типов.

Многострочные строковые литералы

Многострочный строковой литерал записывается в виде произвольного набора символов между двойными собачками @@:

$text = @@some
multiline
text@@;
SELECT LENGTH($text);

Если необходимо вставить в текст двойную собачку, ее необходимо удвоить:

$text = @@some
multiline with double at: @@@@
text@@;
SELECT $text;

Типизированные строковые литералы

  • Для строкового литерала, включая многострочный, по умолчанию используется тип String (см. также PRAGMA UnicodeLiterals).
  • С помощью следующих суффиксов можно явно управлять типом литерала:
    • sString;
    • uUtf8;
    • yYson;
    • jJson.

Пример:

SELECT "foo"u, '[1;2]'y, @@{"a":null}@@j;

Числовые литералы

  • Целочисленные литералы по умолчанию имеют тип Int32, если попадают в его диапазон, и в противном случае автоматически расширяются до Int64.
  • С помощью следующих суффиксов можно явно управлять типом литерала:
    • lInt64;
    • sInt16;
    • tInt8.
  • Добавление суффикса u превращает тип в соответствующий беззнаковый:
    • ulUint64;
    • uUint32;
    • usUint16;
    • utUint8.
  • Также для целочисленных литералов доступна запись в шестнадцатеричной, восьмеричной и двоичной форме с помощью префиксов 0x, 0o и 0b, соответственно. Их можно произвольным образом комбинировать с описанными выше суффиксами.
  • Литералы с плавающей точкой по умолчанию имеют тип Double, но с помощью суффикса f его можно сузить до Float.
SELECT
  123l AS `Int64`,
  0b01u AS `Uint32`,
  0xfful AS `Uint64`,
  0o7ut AS `Uint8`,
  456s AS `Int16`,
  1.2345f AS `Float`;
Предыдущая
Следующая