Разобрался, рассказываю.
Как удалось выяснить, данные из присоединенной таблицы нельзя передавать на клиента в формате application/vnd.ogc.gml, а можно только в text/html (в text/plain тоже нельзя), что это за форматы подробно рассмотрено 
тут. То есть map-файл обязательно должен содержать следующую инструкцию:
Код: Выделить всё
MAP   
   ...
   WEB
      ...
      METADATA     
         ...
         wms_feature_info_mime_type "text/html"
         ...
      END
      ...   
   END
   ...
END
В документации приведён пример подключения CSV к shp - он не работоспособный. Во-первых, в нём пропущена строка 
CONNECTIONTYPE csv, а во-вторых ссылка на поле csv-файла указывается не по имени, а по индексу, например, 
TO '1'.
Существует 2 принципиально различных режима JOIN: ONE-TO-ONE (по умолчанию) и ONE-TO-MANY. Первый используется когда ключевому полю в исходном файле соответствует одна запись в присоединённом, второй - когда ключевому полю в исходном файле соответствует несколько записей в присоединённом. Каждый из этих режимов предполагает различную конфигурацию map-файа.
ONE-TO-ONE
Пример JOIN-секции:
Код: Выделить всё
JOIN
    CONNECTIONTYPE csv
    NAME "lookup"
    TABLE 'landmap2.csv'
    FROM 'Code'
    TO '1'
    TYPE ONE-TO-ONE
END
Пример csv-файла:
Код: Выделить всё
ID,NameNN
1,1. Выпуклые водоразделы
2,2. Плоские и слабовыпуклые водоразделы
3,3. Плоские водоразделы
В JOIN-секции мы описываем поиск значения поля 
Code исходного shape-файла в первой колоне CSV-файла (CSV-драйвер не понимает имён полей, адресация выполняется по номеру).
Допустим, мы хотим получить информацию о некоторой точке карты, содержащую информацию как из исходного файла, так и из присоединённого. Для этого нам необходимо описать html-шаблон ответа сервера со вставкой необходимых полей. Пример такого шаблона:
Код: Выделить всё
<!-- MapServer Template -->
[lookup_2],[Cоde]
lookup_2 - это второе поле присоединённого csv-файла, описанного в JOIN-секции lookup (NAME "lookup"), то есть имя этого поля составляется из имени JOIN-секции, нижнего подчеркивания и номера поля присоединенного csv-файла.
Code - имя одного из полей исходного shape-файла.
Имя шаблона указывается внутри объекта LAYER:
Код: Выделить всё
MAP
   ...
       LAYER
          ...
          TEMPLATE layertemplate.html
          ...
       END
   ...   
END
Пример JOIN-секции:
Код: Выделить всё
JOIN
    CONNECTIONTYPE csv
    TEMPLATE jointemplate.html
    NAME "lookup"
    TABLE 'landmap2.csv'
    FROM 'Code'
    TO '1'
    TYPE ONE-TO-MANY
END
Всё то же самое, только возникает необходимости обязательного указания TEMPLATE еще и внутри самой секции JOIN. TEMPLATE внутри LAYER видоизменяется на:
То есть этой конструкцией как-бы говорится, что данный шаблон не надо использовать, а нужно использовать тот, что находится внутри секции JOIN с именем NAME "lookup".
Пример содержимого TEMPLATE в JOIN (в нашем примере - jointemplate.html):
Код: Выделить всё
<!-- MapServer Template -->
[lookup_2],[Code]
То есть фактически шаблон, указываемый при ONE-TO-ONE на уровне LAYER теперь переехал в JOIN.
Вот и всё. Если кто захочет воспользоваться данным подходом - предупреждаю, как экранировать запятые внутри csv пока не ясно, в документации ничего подобного я не нашёл, можно конечно исходники глянуть, но это уже вопрос к тем, кто разбирается в C.
Без 
этого поста было бы сложно разобраться.
Spatial is now, more than ever, just another column- The Geometry Column.