# Выполнение запросов выборки

Для всех SQL-драйверов построение простой таблицы, как правило, происходит следующим образом.

* Устанавливается соединение с базой данных.
* Выполняются запросы `sql_query_pre_all` для выполнения необходимой начальной настройки, например, установки кодировки на соединение в MySQL. Эти запросы выполняются до всего процесса индексирования, а также после переподключения для индексирования атрибутов MVA и связанных полей.
* Выполняется предварительный запрос `sql_query_pre` для выполнения необходимой начальной настройки, например, создания временных таблиц или ведения счетчиков. Эти запросы выполняются один раз за весь процесс индексирования.
* Выполняется предварительный запрос `sql_query_pre` для выполнения необходимой начальной настройки, например, создания временных
  таблиц или ведения счетчиков. Эти запросы выполняются один раз за весь процесс индексирования.
* Выполняется основной запрос `sql_query`, результаты которого обрабатываются.
* Выполняется пост-запрос `sql_query_post` для выполнения необходимой очистки.
* Соединение с базой данных закрывается.
* Индексатор выполняет фазу сортировки (точнее говоря, специфическую для типа таблицы постобработку).
* Соединение с базой данных устанавливается снова.
* Выполняется запрос постобработки `sql_query_post_index` для выполнения необходимой окончательной очистки.
* Соединение с базой данных снова закрывается.

Пример источника, выбирающего данные из MYSQL:

```ini
source mysource {
  type             = mysql
  path             = /path/to/realtime
  sql_host         = localhost
  sql_user         = myuser
  sql_pass         = mypass
  sql_db           = mydb
  sql_query_pre    = SET CHARACTER_SET_RESULTS=utf8
  sql_query_pre    = SET NAMES utf8
  sql_query        =  SELECT id, title, description, category_id  FROM mytable
  sql_query_post   = DROP TABLE view_table
  sql_query_post_index = REPLACE INTO counters ( id, val ) \
    VALUES ( 'max_indexed_id', $maxid )
  sql_attr_uint    = category_id
  sql_field_string = title
 }

table mytable {
  type   = plain
  source = mysource
  path   = /path/to/mytable
  ...
 }
```

## sql_query

Это запрос, используемый для извлечения документов из SQL-сервера. Может быть объявлен только один sql_query, и его наличие обязательно. См. также [Обработка полученных данных](../../../Data_creation_and_modification/Adding_data_from_external_storages/Fetching_from_databases/Processing_fetched_data.md#Processing-fetched-data)

## sql_query_pre

Предварительный запрос выборки или pre-query. Это настройка с множественным значением, необязательная, по умолчанию – пустой список запросов. Предварительные запросы выполняются перед sql_query в том порядке, в каком они указаны в конфигурационном файле. Результаты предварительных запросов игнорируются.

Предварительные запросы полезны во многих случаях. Они могут использоваться для установки кодировки, отметки записей, которые будут индексированы, обновления внутренних счетчиков, установки различных параметров и переменных SQL-сервера, связанных с соединением, и так далее.

Вероятно, наиболее частое использование предварительного запроса – указание кодировки, которую сервер будет использовать для возвращаемых строк. Обратите внимание, что Manticore принимает только текст в кодировке UTF-8. Два специфических для MySQL примера установки кодировки:

```ini
sql_query_pre = SET CHARACTER_SET_RESULTS=utf8
sql_query_pre = SET NAMES utf8
```

Также, специфично для источников MySQL, полезно отключить кэш запросов (только для соединения индексатора) в предварительном запросе, поскольку индексационные запросы все равно часто не будут выполняться повторно, и нет смысла кэшировать их результаты.
Это может быть сделано так:

```ini
sql_query_pre = SET SESSION query_cache_type=OFF
```

## sql_query_post

Пост-запрос выборки. Эта настройка необязательна, значение по умолчанию – пустое.

Этот запрос выполняется сразу после успешного завершения sql_query. Если при выполнении пост-запроса возникают ошибки, они регистрируются как предупреждения, но индексирование не прерывается. Его результирующий набор игнорируется. Обратите внимание, что в момент выполнения этого запроса индексирование еще не завершено, и оно все еще может завершиться ошибкой. Поэтому из этого запроса не следует выполнять постоянные обновления. Например, обновления вспомогательной таблицы, которые перманентно изменяют последний успешно индексированный ID, не должны выполняться из `sql_query_post`; вместо этого они должны выполняться из запроса `sql_query_post_index`.

## sql_query_post_index

Запрос постобработки. Эта настройка необязательна, значение по умолчанию – пустое.

Этот запрос выполняется, когда индексирование полностью и успешно завершено. Если этот запрос вызывает ошибки, они регистрируются как предупреждения, но индексирование не прерывается. Его результирующий набор игнорируется. В тексте запроса можно использовать макрос `$maxid`; он будет расширен до максимального ID документа, который был фактически извлечен из базы данных во время индексирования. Если документы не индексировались, `$maxid` будет расширен до 0.

Пример:
```ini
sql_query_post_index = REPLACE INTO counters ( id, val ) \
    VALUES ( 'max_indexed_id', $maxid )
```

Разница между `sql_query_post` и `sql_query_post_index` в том, что `sql_query_post` выполняется сразу после получения Manticore всех документов, однако индексирование все еще может завершиться неудачей по другой причине. Напротив, к моменту выполнения `sql_query_post_index` гарантируется, что таблица была успешно создана. Соединение с базой данных разрывается и устанавливается заново, поскольку фаза сортировки может быть очень долгой и в противном случае просто прервется по тайм-ауту.

<!-- proofread -->

