[Из песочницы] Экспорт плана нумерации Федерального Агентства Связи в реляционную БД

?v=1

Федеральное Агентство Связи регулярно обновляет размещённый в открытом доступе план нумерации. Если вы используете этот план для определения региона или провайдера абонента в своём диалплане, то скорее всего заинтересованы в актуальности этой информации. На первый взгляд нет ничего сложного в том, чтобы написать приложение, которое загрузит, обработает и отправит данные в БД, однако приступив к реализации, вы неизбежно наткнётесь на подводные камни, о которых я сейчас расскажу.
План набора состоит из четырёх табличных файлов в формате csv:

rossvyaz.ru/data/ABC-3xx.csv
rossvyaz.ru/data/ABC-4xx.csv
rossvyaz.ru/data/ABC-8xx.csv
rossvyaz.ru/data/DEF-9xx.csv

URL’ы иногда меняются.

Структура всех таблиц одинакова:

АВС/ DEF;От;До;Емкость;Оператор;Регион


В поле Регион у некоторых провайдеров есть лишние точки с запятой:

Московская область; Москва|Московская область; Москва


Чтобы избежать ошибки во время чтения таблицы вашим приложением, нужно отключить проверку на ожидаемое количество полей или заменить ошибочную запись на корректную.

Мы собираемся записать данные в таблицу со следующей структурой:

first BIGINT PRIMARY KEY NOT NULL  // начало диапазона
last BIGINT UNIQUE NOT NULL        // конец диапазона
provider TEXT                      // провайдер
source_region TEXT                 // текстовое значение поля Регион из плана набора Россвязи
region INT NOT NULL                // числовой код региона


Большинство регионов в таблицах можно однозначно определить по вхождению подстроки. К примеру, все записи для Саратовской области содержат подстроку Сарат.

Для тех регионов, которые нельзя однозначно определить, нужна дополнительная логика, о ней ниже.

Пример 1:

  • Ямало-Ненецкий АО
  • Ненецкий АО


Ямало-Ненецкий автономный округ входит в состав Тюменской области, а Ненецкий автономный округ — в состав Архангельской. Проблема определения числового кода региона заключается в том, что подстрока Ненецкий АО полностью входит в Ямало-Ненецкий АО. Это значит, что содержащим подстроку Ненецкий АО записям будут соответствовать два региона.

Чтобы решить эту проблему, нужно добавить проверку на отсутствие подстроки (исключающую подстроку). Другими словами Ямало-Ненецкий АО будем определять по вхождению Ямало, а Ненецкий АО по вхождению Ненец и отсутствию Ямало.

Пример 2:

  • г.о. Красногорск
  • г. Лянтор
  • п. Парца


Пример неопознанных регионов. Таких записей в таблицах Россвязи много. Поисковик помогает выяснить, что г.о. Красногорск — Московкая область, г. Лянтор — Ханты-Мансийский автономный округ, а п. Парца — республика Мордовия. Решение простое, искомая подстрока преобразуется в массив строк, а проверять вхождение будем в цикле. Исключающую подстроку тоже преобразуем в массив.

Пример 3:

  • Сибирский федеральный округ, Дальневосточный федеральный округ
  • Красноярский край, Республика Хакасия, г. Москва, г. Санкт-Петербург
  • Российская Федерация


В этом примере нет возможности однозначно определить регион. Вы можете выбрать самый населённый из перечисленных, или присвоить особый код таким записям. На самом деле, все записи, которым соответствуют несколько регионов — это номера 8–80[0–9], федеральные номера, за звонки на которые не взимается плата. Я присвоил таким записям коды в диапазоне от 200 до 210. Не думаю, что они мне когда-нибудь пригодятся.

Код приложения можно посмотреть тут.
Исполняемые файлы для платформ linux, macos и windows находятся в каталоге bin (работу приложения на платформе windows я не тестировал).

Конфигурационный файл config.yml должен находиться в том же каталоге, откуда запускается исполняемый файл. Если есть желание, можете реализовать в приложении поддержку флагов, чтобы указывать путь к конфигу в аргументах коммандной строки, pull-request’ы приветствуются.

Конфигурационный файл
data_source:
  - https://rossvyaz.ru/data/ABC-3xx.csv
  - https://rossvyaz.ru/data/ABC-4xx.csv
  - https://rossvyaz.ru/data/ABC-8xx.csv
  - https://rossvyaz.ru/data/DEF-9xx.csv
#  - ../service/testdata/ABC-3xx.csv
#  - ../service/testdata/ABC-4xx.csv
#  - ../service/testdata/ABC-8xx.csv
#  - ../service/testdata/DEF-9xx.csv
exceptions: exceptions.yml
regions: regions.yml
db:
  host: localhost
  name: asterisk
  table: codes
  user: asterisk
  password: asterisk


Поле data_source содержит пути до табличных файлов Россвязи. Если путь начинается с http, приложение загрузит таблицу с помощью встроенного веб-клиента, в противном случае попытается найти таблицу в файловой системе.

Обратите внимание на закомментированные строки. Это пути до табличных файлов Россвязи, сохранённых в репозитории. Если у вас не самое быстрое интернет-соединение, каждый запуск приложения будет загружать эти файлы заново. Для более быстрой работы приложения раскомментируйте эти строки и закомментируйте гиперссылки. Возможно приложение потребуется запускать чаще, чем вы думаете, позднее на примере объясню почему.

Поля exceptions и regions содержат пути до файлов с исправлениями и описанием регионов. О них чуть позднее.

В разделе db описаны параметры подключения к СУБД MySQL. Для использования другой СУБД нужно заменить драйвер в коде и шаблон строки подключения в конструкторе структуры Service

db, err := dbr.Open("mysql",
		fmt.Sprintf("%s:%s@tcp(%s)/%s", c.DB.User, c.DB.Password, c.DB.Host, c.DB.Name),
		nil)


Впрочем, нет ничего сложного в том, чтобы добавить поле с типом СУБД в конфиг и добавить поддержку этих типов в приложение, pull-request’ы вновь приветствуются.

Файл exceptions.yml содержит список исправлений. Все совпадения подстрок в exceptions.yml до двоеточия, найденные в табличных файлов Россвязи, будут заменены на подстроки, следующие после двоеточия.

Файл regions.yml содержит список числовых кодов регионов с массивами вхождений и исключающих подстрок, используемых для определения конкретного региона. Если для какой-либо записи не будет найдено соответствие ни одному региону или соответствий будет два и более, то эта запись попадёт в БД, но поле region будет содержать значение 0 (регион не определён).

Пример описания региона
78:
  name: Санкт-Петербург
  contain:
    - Ленинградская
    - Санкт
    - г.п. Никольское
  not_contain:
    - Красноярский


Перед запуском приложения, создайте базу данных с именем, указанным в db.name и убедитесь, что у пользователя, указанного в db.user, есть права на чтение и запись.

Итак, мы всё настроили, самое время запустить приложение.

Обратите внимание, что во время запуска таблица, указанная в поле db.table конфигурационного файла будет очищена, будьте осторожны.

./def2sql


Если ошибок и предупреждений нет, вы увидите похожий вывод
correct records amount: 372324
inserted 372324 records


В противном случае вы увидите отчёт с ошибками и предупреждениями
correct records amount: 372324
inserted 372324 records
{
    "unknown_regions": [
        {
            "First": 3424333950,
            "Last": 3424333999,
            "Range": 50,
            "Provider": "ООО \"КОКОБРИ\"",
            "SourceRegion": "г.о. Красновишерск",
            "Region": 0
        },
        {
            "First": 3424820000,
            "Last": 3424820049,
            "Range": 50,
            "Provider": "ООО \"КОКОБРИ\"",
            "SourceRegion": "г.о. Губаха",
            "Region": 0
        },
        {
            "First": 3425425000,
            "Last": 3425425049,
            "Range": 50,
            "Provider": "ООО \"КОКОБРИ\"",
            "SourceRegion": "г.о. Верещагино",
            "Region": 0
        },
        {
            "First": 3425620000,
            "Last": 3425620049,
            "Range": 50,
            "Provider": "ООО \"КОКОБРИ\"",
            "SourceRegion": "г.о. Чусовой",
            "Region": 0
        },
        {
            "First": 3426050000,
            "Last": 3426050050,
            "Range": 51,
            "Provider": "ООО \"КОКОБРИ\"",
            "SourceRegion": "г.о. Кудымкар",
            "Region": 0
        },
        {
            "First": 3427399950,
            "Last": 3427399999,
            "Range": 50,
            "Provider": "ООО \"КОКОБРИ\"",
            "SourceRegion": "г.о. Краснокамск",
            "Region": 0
        },
        {
            "First": 4217523500,
            "Last": 4217523999,
            "Range": 500,
            "Provider": "ПАО \"Компания \"Сухой\"",
            "SourceRegion": "АО Ленинский",
            "Region": 0
        },
        {
            "First": 4217526000,
            "Last": 4217526999,
            "Range": 1000,
            "Provider": "ПАО \"Компания \"Сухой\"",
            "SourceRegion": "АО Ленинский",
            "Region": 0
        },
        {
            "First": 8003550000,
            "Last": 8003559999,
            "Range": 10000,
            "Provider": "ООО \"ТК Телезон\" (ИНН 2460087999)",
            "SourceRegion": "Красноярский край * Республика Хакасия * г. Москва * г. Санкт-Петербург",
            "Region": 0
        },
        {
            "First": 8003810000,
            "Last": 8003819999,
            "Range": 10000,
            "Provider": "ПАО \"Ростелеком\"",
            "SourceRegion": "Сибирский федеральный округ * Дальневосточный федеральный округ",
            "Region": 0
        },
        {
            "First": 8013810000,
            "Last": 8013819999,
            "Range": 10000,
            "Provider": "ПАО \"Ростелеком\"",
            "SourceRegion": "Сибирский федеральный округ * Дальневосточный федеральный округ",
            "Region": 0
        },
        {
            "First": 8023810000,
            "Last": 8023819999,
            "Range": 10000,
            "Provider": "ПАО \"Ростелеком\"",
            "SourceRegion": "Сибирский федеральный округ * Дальневосточный федеральный округ",
            "Region": 0
        },
        {
            "First": 8031010000,
            "Last": 8031019999,
            "Range": 10000,
            "Provider": "ПАО \"Ростелеком\"",
            "SourceRegion": "Уральский федеральный округ * Приволжский федеральный округ",
            "Region": 0
        },
        {
            "First": 8033550000,
            "Last": 8033559999,
            "Range": 10000,
            "Provider": "ООО \"ТК Телезон\" (ИНН 2460087999)",
            "SourceRegion": "Красноярский край * Республика Хакасия * г. Москва * г. Санкт-Петербург",
            "Region": 0
        },
        {
            "First": 8033810000,
            "Last": 8033819999,
            "Range": 10000,
            "Provider": "ПАО \"Ростелеком\"",
            "SourceRegion": "Сибирский федеральный округ * Дальневосточный федеральный округ",
            "Region": 0
        },
        {
            "First": 8041010000,
            "Last": 8041019999,
            "Range": 10000,
            "Provider": "ПАО \"Ростелеком\"",
            "SourceRegion": "Уральский федеральный округ * Приволжский федеральный округ",
            "Region": 0
        },
        {
            "First": 8043810000,
            "Last": 8043819999,
            "Range": 10000,
            "Provider": "ПАО \"Ростелеком\"",
            "SourceRegion": "Сибирский федеральный округ * Дальневосточный федеральный округ",
            "Region": 0
        },
        {
            "First": 8051010000,
            "Last": 8051019999,
            "Range": 10000,
            "Provider": "ПАО \"Ростелеком\"",
            "SourceRegion": "Уральский федеральный округ * Приволжский федеральный округ",
            "Region": 0
        },
        {
            "First": 8053810000,
            "Last": 8053819999,
            "Range": 10000,
            "Provider": "ПАО \"Ростелеком\"",
            "SourceRegion": "Сибирский федеральный округ * Дальневосточный федеральный округ",
            "Region": 0
        },
        {
            "First": 8063810000,
            "Last": 8063819999,
            "Range": 10000,
            "Provider": "ПАО \"Ростелеком\"",
            "SourceRegion": "Сибирский федеральный округ * Дальневосточный федеральный округ",
            "Region": 0
        },
        {
            "First": 8073810000,
            "Last": 8073819999,
            "Range": 10000,
            "Provider": "ПАО \"Ростелеком\"",
            "SourceRegion": "Сибирский федеральный округ * Дальневосточный федеральный округ",
            "Region": 0
        },
        {
            "First": 8083810000,
            "Last": 8083819999,
            "Range": 10000,
            "Provider": "ПАО \"Ростелеком\"",
            "SourceRegion": "Сибирский федеральный округ * Дальневосточный федеральный округ",
            "Region": 0
        },
        {
            "First": 8091010000,
            "Last": 8091019999,
            "Range": 10000,
            "Provider": "ПАО \"Ростелеком\"",
            "SourceRegion": "Уральский федеральный округ * Приволжский федеральный округ",
            "Region": 0
        },
        {
            "First": 8093550000,
            "Last": 8093559999,
            "Range": 10000,
            "Provider": "ООО \"ТК Телезон\" (ИНН 2460087999)",
            "SourceRegion": "Красноярский край * Республика Хакасия * г. Москва * г. Санкт-Петербург",
            "Region": 0
        },
        {
            "First": 8093810000,
            "Last": 8093819999,
            "Range": 10000,
            "Provider": "ПАО \"Ростелеком\"",
            "SourceRegion": "Сибирский федеральный округ * Дальневосточный федеральный округ",
            "Region": 0
        },
        {
            "First": 9512780000,
            "Last": 9512789999,
            "Range": 10000,
            "Provider": "ООО \"Т2 Мобайл\"",
            "SourceRegion": "Абзелиловский район * Белорецкий район|Абзелиловский район * Белорецкий район",
            "Region": 0
        },
        {
            "First": 9963000000,
            "Last": 9963029999,
            "Range": 30000,
            "Provider": "ООО \"Т2 Мобайл\"",
            "SourceRegion": "Абзелиловский район * Белорецкий район|Абзелиловский район * Белорецкий район",
            "Region": 0
        }
    ],
    "warnings": [
        "couldn't find region for record (3424333950-3424333999; ООО \"КОКОБРИ\", г.о. Красновишерск)",
        "couldn't find region for record (3424820000-3424820049; ООО \"КОКОБРИ\", г.о. Губаха)",
        "couldn't find region for record (3425425000-3425425049; ООО \"КОКОБРИ\", г.о. Верещагино)",
        "couldn't find region for record (3425620000-3425620049; ООО \"КОКОБРИ\", г.о. Чусовой)",
        "couldn't find region for record (3426050000-3426050050; ООО \"КОКОБРИ\", г.о. Кудымкар)",
        "couldn't find region for record (3427399950-3427399999; ООО \"КОКОБРИ\", г.о. Краснокамск)",
        "couldn't find region for record (4217523500-4217523999; ПАО \"Компания \"Сухой\", АО Ленинский)",
        "couldn't find region for record (4217526000-4217526999; ПАО \"Компания \"Сухой\", АО Ленинский)",
        "couldn't find region for record (8003550000-8003559999; ООО \"ТК Телезон\" (ИНН 2460087999), Красноярский край * Республика Хакасия * г. Москва * г. Санкт-Петербург)",
initial commit
        "couldn't find region for record (8003810000-8003819999; ПАО \"Ростелеком\", Сибирский федеральный округ * Дальневосточный федеральный округ)",
        "couldn't find region for record (8013810000-8013819999; ПАО \"Ростелеком\", Сибирский федеральный округ * Дальневосточный федеральный округ)",
        "couldn't find region for record (8023810000-8023819999; ПАО \"Ростелеком\", Сибирский федеральный округ * Дальневосточный федеральный округ)",
        "couldn't find region for record (8031010000-8031019999; ПАО \"Ростелеком\", Уральский федеральный округ * Приволжский федеральный округ)",
        "couldn't find region for record (8033550000-8033559999; ООО \"ТК Телезон\" (ИНН 2460087999), Красноярский край * Республика Хакасия * г. Москва * г. Санкт-Петербург)",
        "couldn't find region for record (8033810000-8033819999; ПАО \"Ростелеком\", Сибирский федеральный округ * Дальневосточный федеральный округ)",
        "couldn't find region for record (8041010000-8041019999; ПАО \"Ростелеком\", Уральский федеральный округ * Приволжский федеральный округ)",
        "couldn't find region for record (8043810000-8043819999; ПАО \"Ростелеком\", Сибирский федеральный округ * Дальневосточный федеральный округ)",
        "couldn't find region for record (8051010000-8051019999; ПАО \"Ростелеком\", Уральский федеральный округ * Приволжский федеральный округ)",
        "couldn't find region for record (8053810000-8053819999; ПАО \"Ростелеком\", Сибирский федеральный округ * Дальневосточный федеральный округ)",
        "couldn't find region for record (8063810000-8063819999; ПАО \"Ростелеком\", Сибирский федеральный округ * Дальневосточный федеральный округ)",
        "couldn't find region for record (8073810000-8073819999; ПАО \"Ростелеком\", Сибирский федеральный округ * Дальневосточный федеральный округ)",
        "couldn't find region for record (8083810000-8083819999; ПАО \"Ростелеком\", Сибирский федеральный округ * Дальневосточный федеральный округ)",
        "couldn't find region for record (8091010000-8091019999; ПАО \"Ростелеком\", Уральский федеральный округ * Приволжский федеральный округ)",
        "couldn't find region for record (8093550000-8093559999; ООО \"ТК Телезон\" (ИНН 2460087999), Красноярский край * Республика Хакасия * г. Москва * г. Санкт-Петербург)",
        "couldn't find region for record (8093810000-8093819999; ПАО \"Ростелеком\", Сибирский федеральный округ * Дальневосточный федеральный округ)",
        "couldn't find region for record (9512780000-9512789999; ООО \"Т2 Мобайл\", Абзелиловский район * Белорецкий район|Абзелиловский район * Белорецкий район)",
        "couldn't find region for record (9963000000-9963029999; ООО \"Т2 Мобайл\", Абзелиловский район * Белорецкий район|Абзелиловский район * Белорецкий район)"
    ]
}


Отчёт содержит несколько разделов.

unknown_regions — список записей, которым не соответствует регионы, или их количество больше одного;
wrong_records — список некорректных записей в таблице Россвязи;
warnings — список предупреждений, возникших во время работы приложения;

Отчёт под последним спойлером я получил во время запуска приложения приблизительно через месяц после последних правок regions.yml.

Неактуальная версия regions.yml
1:
  name: Республика Адыгея (Адыгея)
  contain:
    - Адыгея
2:
  name: Республика Башкортостан
  contain:
    - Башкортостан
    - Абзелиловский и Белорецкий
3:
  name: Республика Бурятия
  contain:
    - Бурятия
4:
  name: Республика Алтай
  contain:
    - Республика Алтай
5:
  name: Республика Дагестан
  contain:
    - Дагестан
6:
  name: Республика Ингушетия
  contain:
    - Ингушетия
7:
  name: Кабардино-Балкарская Республика
  contain:
    - Кабардино-Балкарская
8:
  name: Республика Калмыкия
  contain:
    - Калмыкия
9:
  name: Карачаево-Черкесская Республика
  contain:
    - Карачаево
10:
  name: Республика Карелия
  contain:
    - Карелия
    - г.п. Сортавала
11:
  name: Республика Коми
  contain:
    - Коми
12:
  name: Республика Марий Эл
  contain:
    - Марий
13:
  name: Республика Мордовия
  contain:
    - Мордовия
    - п. Парца
14:
  name: Республика Саха (Якутия)
  contain:
    - Якутия
    - Нерюнгри
15:
  name: Республика Северная Осетия - Алания
  contain:
    - Осетия
16:
  name: Республика Татарстан (Татарстан)
  contain:
    - Татарстан
    - Казань
    - Челны
17:
  name: Республика Тыва
  contain:
    - Тыва
18:
  name: Удмуртская Республика
  contain:
    - Удмурт
    - пгт. Ува
19:
  name: Республика Хакасия
  contain:
    - Хакасия
  not_contain:
    - Красноярский
20:
  name: Чеченская Республика
  contain:
    - Чеченская Республика
    - Чечня
    - Республика Чеченская
21:
  name: Чувашская Республика - Чувашия
  contain:
    - Чувашская Республика
    - Чувашия
22:
  name: Алтайский край
  contain:
    - Алтайский край
23:
  name: Краснодарский край
  contain:
    - Краснодарский
24:
  name: Красноярский край
  contain:
    - Красноярский край
  not_contain:
    - Москва
25:
  name: Приморский край
  contain:
    - Приморский край
26:
  name: Ставропольский край
  contain:
    - Ставропольский край
27:
  name: Хабаровский край
  contain:
    - Хабаровский
28:
  name: Амурская область
  contain:
    - Амурская
29:
  name: Архангельская область
  contain:
    - Архангельская
    - Ненецкий
  not_contain:
    - Ямало
    - Красноярск
30:
  name: Астраханская область
  contain:
    - Астраханская
31:
  name: Белгородская область
  contain:
    - Белгородская
32:
  name: Брянская область
  contain:
    - Брянская
33:
  name: Владимирская область
  contain:
    - Владимирская
34:
  name: Волгоградская область
  contain:
    - Волгоградская
35:
  name: Вологодская область
  contain:
    - Вологодская
36:
  name: Воронежская область
  contain:
    - Воронежская
    - г.о. Борисоглебский
37:
  name: Ивановская область
  contain:
    - Ивановская
    - г.о. Иваново
    - г.о. Кинешма
38:
  name: Иркутская область
  contain:
    - Иркутская
39:
  name: Калининградская область
  contain:
    - Калининградская
40:
  name: Калужская область
  contain:
    - Калужская
41:
  name: Камчатский край
  contain:
    - Камчатский
42:
  name: Кемеровская область
  contain:
    - Кемеровская
43:
  name: Кировская область
  contain:
    - Кировская
44:
  name: Костромская область
  contain:
    - Костромская
45:
  name: Курганская область
  contain:
    - Курганская
46:
  name: Курская область
  contain:
    - Курская
#47:
#  name: Ленинградская область
#  contain:
#    - Ленинградская
48:
  name: Липецкая область
  contain:
    - Липецкая
49:
  name: Магаданская область
  contain:
    - Магаданская
#50:
#  name: Московская область
#  contain:
#    - Московская
51:
  name: Мурманская область
  contain:
    - Мурманская
52:
  name: Нижегородская область
  contain:
    - Нижегородская
53:
  name: Новгородская область
  contain:
    - Новгородская
54:
  name: Новосибирская область
  contain:
    - Новосибирская
    - г. Инская
55:
  name: Омская область
  contain:
    - Омская
    - АО. Ленинский
56:
  name: Оренбургская область
  contain:
    - Оренбургская
57:
  name: Орловская область
  contain:
    - Орловская
58:
  name: Пензенская область
  contain:
    - Пензенская
59:
  name: Пермский край
  contain:
    - Пермский
    - г.о. Соликамский
    - Лысьвенский р-н
    - р-н Чайковский
60:
  name: Псковская область
  contain:
    - Псковская
61:
  name: Ростовская область
  contain:
    - Ростовская
62:
  name: Рязанская область
  contain:
    - Рязанская
63:
  name: Самарская область
  contain:
    - Самарская
64:
  name: Саратовская область
  contain:
    - Саратовская
65:
  name: Сахалинская область
  contain:
    - Сахалинская
66:
  name: Свердловская область
  contain:
    - Свердловская
67:
  name: Смоленская область
  contain:
    - Смоленская
68:
  name: Тамбовская область
  contain:
    - Тамбовская
69:
  name: Тверская область
  contain:
    - Тверская
70:
  name: Томская область
  contain:
    - Томская
71:
  name: Тульская область
  contain:
    - Тульская
72:
  name: Тюменская область
  contain:
    - Тюменская
73:
  name: Ульяновская область
  contain:
    - Ульяновская
74:
  name: Челябинская область
  contain:
    - Челябинская
    - г.о. Златоустовский
    - г.о. Магнитогорский
75:
  name: Забайкальский край
  contain:
    - Забайкальский
76:
  name: Ярославская область
  contain:
    - Ярославская
77:
  name: г. Москва
  contain:
    - Московская
    - Москва
    - Люберцы
    - Мытищи
    - г.о. Красногорск
    - г.о. Солнечногорск
    - с.п. Пышлицкое
    - г.о. Озёры
    - с.п. Луневское
    - Рузский Санаторий Русь УПАТС
    - г.о. Клин
    - г.о. Щелково
    - г.о. Егорьевск
    - ЗАТО п. Восход
    - п. Федюково
  not_contain:
    - Красноярский
78:
  name: Санкт-Петербург
  contain:
    - Ленинградская
    - Санкт
    - г.п. Никольское
  not_contain:
    - Красноярский
79:
  name: Еврейская автономная область
  contain:
    - Еврейская
#83:
#  name: Ненецкий автономный округ
#  contain:
#    - Ненецкий
86:
  name: Ханты-Мансийский автономный округ - Югра
  contain:
    - Ханты
    - Сургут
    - Нефтеюганск
    - Лянтор
    - Когалым
    - г. Радужный
  not_contain:
    - Владимирская
87:
  name: Чукотский автономный округ
  contain:
    - Чукотский
89:
  name: Ямало-Ненецкий автономный округ
  contain:
    - Ямало-Ненецкий
91:
  name: Республика Крым
  contain:
    - Республика Крым
    - Симферополь
    - Севастополь
#92:
#  name: Севастополь
#  contain:
#    - Севастополь
99:
  name: Иные территории, включая город и космодром Байконур
  contain:
    - Байконур

200:
  name: Российская Федерация
  contain:
    - Российская

201:
  name: Дальневосточный федеральный округ
  contain:
    - Дальневосточный федеральный округ
  not_contain:
    - Сибирский федеральный округ
202:
  name: Сибирский федеральный округ
  contain:
    - Сибирский федеральный округ
  not_contain:
    - Дальневосточный федеральный округ
203:
  name: Центральный федеральный округ
  contain:
    - Центральный федеральный округ
204:
  name: Уральский федеральный округ
  contain:
    - Уральский федеральный округ
  not_contain:
    - Приволжский федеральный округ
205:
  name: Приволжский федеральный округ
  contain:
    - Приволжский федеральный округ
  not_contain:
    - Уральский федеральный округ
206:
  name: Северо-Западный федеральный округ
  contain:
    - Северо-Западный федеральный округ
207:
  name: Сибирский федеральный округ, Дальневосточный федеральный округ
  contain:
    - Сибирский федеральный округ, Дальневосточный федеральный округ
208:
  name: Уральский федеральный округ, Приволжский федеральный округ
  contain:
    - Уральский федеральный округ, Приволжский федеральный округ
209:
  name: Красноярский край, Республика Хакасия, г. Москва, г. Санкт-Петербург
  contain:
    - Красноярский край, Республика Хакасия, г. Москва, г. Санкт-Петербург


Чтобы избавиться от предупреждений и получить коды регионов для всех записей, нужно отредактировать regions.yml.

diff версий regions.yml
10d9
<     - Абзелиловский район
245d243
<     - АО Ленинский
265,270d262
<     - г.о. Красновишерск
<     - г.о. Губаха
<     - г.о. Верещагино
<     - г.о. Чусовой
<     - г.о. Кудымкар
<     - г.о. Краснокамск
452d443
<     - Сибирский федеральный округ * Дальневосточный федеральный округ
457d447
<     - Уральский федеральный округ * Приволжский федеральный округ
461,462c451
<     - Красноярский край, Республика Хакасия, г. Москва, г. Санкт-Петербург
<     - Красноярский край * Республика Хакасия * г. Москва * г. Санкт-Петербург
\ No newline at end of file
---
>     - Красноярский край, Республика Хакасия, г. Москва, г. Санкт-Петербург
\ No newline at end of file


Вуаля
correct records amount: 372324
inserted 372324 records


В качестве вишенки на торте предлагаю макрос диалплана Asterisk для определения региона по номеру абонента:

[macro-get-region]
        exten => s,1,MYSQL(Connect conn localhost user password dbname)
        exten => s,n,MYSQL(Query result ${conn} SELECT region FROM codes WHERE ${ARG1} BETWEEN first AND last LIMIT 1)
        exten => s,n,MYSQL(Fetch region ${result} region_num)
        exten => s,n,MYSQL(Clear ${result})
        exten => s,n,MYSQL(Disconnect ${conn})


Для этих же целей можно использовать Lua скрипт:

local driver = require("luasql.mysql")
local env = assert (driver.mysql())
local con = assert (env:connect("dbname", "user", "password"))
local cur = assert (con:execute(string.format("select region from codes where %s between first and last limit 1", arg[1])))

row = cur:fetch ({}, "a")
if row ~= nil then
    print(row.region)
else
    print(0)
end

cur:close()
con:close()
env:close(


Впрочем, подойдёт любой инструмент, поддерживающий SELECT запросы к MySQL.

Приятного вам администрирования.

© Habrahabr.ru