Разбор YAML для создания динамических запросов в оболочке

Разбор YAML для создания динамических запросов в оболочке

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

config:
  - system1:
      database_name: database1
      port: '1234'
      table:
        - name: table1
          values: 'table_id, value1, 30, randomValue'
        - name: table2
          values: 'table_id, value1, randomValue, randomValue, value2'
        - name: table2
          values: 'table_id, value2, randomValue, randomValue'
  - system2:
      database_name: database2
      port: '12345'
      table:
        - name: table4
          values: 'table_id, value3, 30, randomValue'
        - name: table5
          values: 'table_id, randomValue, randomValue, value4'
        - name: table6
          values: 'table_id, value3, value4'

Скрипт, который я сейчас пытаюсь написать, представляет собой не более чем SELECTутверждения, но он будет развиваться позже:

# This will later be used to create insert/update queries based on the values so 
# will be needing a handle for that too.
psql -h localhost -p $PORT -d $DATABASE << EOF
select * from $TABLE LIMIT 10;
EOF

Если это возможно, не выглядя при этом навязчивым, я бы хотел получить предложения о том, как я могу использовать yqбиблиотеку, учитывая, что она поддерживает ряд операций, которые мне нужно будет выполнить с этим скриптом после завершения части SQL.

Прошу прощения, если вопрос слишком глупый, это мой первый опыт написания сценариев оболочки.

Я использую дистрибутив Ubuntu 18.4, если это актуально.

решение1

С использованиемАндрей Кислюкyq(оболочка с поддержкой YAML вокруг процессора JSON jq) вместо Майка Фараха yq, вы можете создать операторы оболочки, необходимые для выполнения запросов, следующим образом:

yq -r '
    .config[] |
    map(
        @sh "psql -h localhost -p \(.port) -d \(.database_name) <<END_SQL",
        (.table | map("SELECT \(.values) FROM \(.name) LIMIT 10;"))[],
        "END_SQL"
    )[]' file

или, если вам не нравится использовать map:

yq -r '
    .config[][] |
    @sh "psql -h localhost -p \(.port) -d \(.database_name) <<END_SQL",
    (.table[] | "SELECT \(.values) FROM \(.name) LIMIT 10;"), 
    "END_SQL"' file

Это итерирует по configмассиву, создавая одну psqlкоманду для каждого элемента. psqlКоманда получает свои -pи -dаргументы опции из записей portи database_nameзначений (заключенных в кавычки для оболочки с использованием @shоператора вывода).

Фактические операторы SQL передаются команде через перенаправление here-document, разделенное произвольно выбранной строкой END_SQL. Операторы используют valuesзначение «как есть» для полей, которые необходимо извлечь, и nameзначение в качестве имени таблицы, из которой следует извлечь поля. Для этих значений не выполняется никаких специальных кавычек.

Учитывая данные из вопроса, приведенная выше команда генерирует следующий код оболочки:

psql -h localhost -p '1234' -d 'database1' <<END_SQL
SELECT table_id, value1, 30, randomValue FROM table1 LIMIT 10;
SELECT table_id, value1, randomValue, randomValue, value2 FROM table2 LIMIT 10;
SELECT table_id, value2, randomValue, randomValue FROM table2 LIMIT 10;
END_SQL
psql -h localhost -p '12345' -d 'database2' <<END_SQL
SELECT table_id, value3, 30, randomValue FROM table4 LIMIT 10;
SELECT table_id, randomValue, randomValue, value4 FROM table5 LIMIT 10;
SELECT table_id, value3, value4 FROM table6 LIMIT 10;
END_SQL

Затем вы можете выполнить этот код, либо передав его по конвейеру sh -s, либо выполнив его с помощью eval.

Связанный контент