Собрать заголовки отчёта и отличить описание поля от NULL

Фактические данные получены через расширение interbase от отдельной локальной базы Firebird. Собственная учебная таблица удалена после наблюдений.

Наблюдаемый результат программы
НаблюдениеРезультат
Столбцов в результате3
Строк данных2
Заголовки по aliasITEM_ID, PRODUCT_NAME, COMMENT_TEXT
Имя исходного второго столбцаTITLE
Его alias в отчётеPRODUCT_NAME
Тип второго столбцаVARCHAR
length второго столбца, байт160
Первый комментарий действительно NULLда
Второй комментарий — пустая строкада
Строки и дополнительные наблюдения
{
    "field_metadata": [
        {
            "name": "ID",
            "alias": "ITEM_ID",
            "relation": "FB153_METADATA_3993D6C963",
            "length": "4",
            "type": "INTEGER"
        },
        {
            "name": "TITLE",
            "alias": "PRODUCT_NAME",
            "relation": "FB153_METADATA_3993D6C963",
            "length": "160",
            "type": "VARCHAR"
        },
        {
            "name": "NOTE",
            "alias": "COMMENT_TEXT",
            "relation": "FB153_METADATA_3993D6C963",
            "length": "80",
            "type": "VARCHAR"
        }
    ],
    "data_rows": [
        {
            "ITEM_ID": 1,
            "PRODUCT_NAME": "Кабель №7",
            "COMMENT_TEXT": null
        },
        {
            "ITEM_ID": 2,
            "PRODUCT_NAME": "Адаптер",
            "COMMENT_TEXT": ""
        }
    ],
    "headers": [
        "ITEM_ID",
        "PRODUCT_NAME",
        "COMMENT_TEXT"
    ],
    "source_character_limit": 40,
    "reported_length_measures_bytes": true,
    "metadata_does_not_supply_nullable_flag": true
}

Самостоятельный запуск создаёт result.json с данными и metrics.json с проверками рядом с example.php.