Slick: запрашивать несколько таблиц/баз данных с получением имен столбцов

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

Я использую этот подход, когда результат запроса выглядит так:

Map(columnName1 -> columnVal1, columnName2 -> columnVal2, ...)

Пример кода:

implicit val getListStringResult = GetResult[List[Any]] (
    r => (1 to r.numColumns).map(_ => r.nextObject).toList
)

def getSomething(): Map[String, Any] = DB.withSession {
    val columns = MTable.getTables(None, None, None, None).list.filter(_.name.name == "myTable").head.getColumns.list.map(_.column) 
    val result = sql"""SELECT * FROM myTable LIMIT 1""".as[List[Any]].firstOption.map(columns zip _ toMap).get
}

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

def getSomething(): Map[String, Any] = DB.withSession {

    //The line below is no longer valid because of multiple tables/databases
    val columns = MTable.getTables(None, None, None, None).list.filter(_.name.name == "table1").head.getColumns.list.map(_.column) 
    val result = sql"""
        SELECT      * 
        FROM        db1.table1
        LEFT JOIN   db2.table2 ON db2.table2.col1 = db1.table1.col1
        LIMIT       1
    """.as[List[Any]].firstOption.map(columns zip _ toMap).get

}

Тот же подход больше нельзя использовать для получения имен столбцов. Эта проблема не возникает при использовании чего-то вроде PHP PDO или Java JDBCTemplate — они извлекают имена столбцов без каких-либо дополнительных усилий.

Мой вопрос: как мне добиться этого с помощью Slick?


person Caballero    schedule 28.11.2013    source источник


Ответы (2)


Другой вариант, который создает карту с ненулевыми столбцами (ключи в нижнем регистре):

private implicit val getMap = GetResult[Map[String, Any]](r => {
    val metadata = r.rs.getMetaData
    (1 to r.numColumns).flatMap(i => {
        val columnName = metadata.getColumnName(i).toLowerCase
        val columnValue = r.nextObjectOption
        columnValue.map(columnName -> _)
    }).toMap
})
person caiiiycuk    schedule 21.08.2014

person    schedule
comment
Спасибо. Я думаю, что это должно быть scala.slick.session.PositionedResult вместо scala.slick.jdbc.PositionedResult? Другая проблема - если используется as(ResultMap).fistOption, он застревает в бесконечном цикле. Если используется as(ResultMap).list, все в порядке. Есть ли способ исправить это? - person Caballero; 29.11.2013
comment
Пожалуйста, свяжитесь с нами, если это все еще так в Slick 2.0. - person cvogt; 06.12.2013
comment
Я заметил, что в запросе SELECT c AS column1 FROM t имя столбца в результате по-прежнему остается c, что является большой проблемой, особенно для динамически вычисляемых столбцов. Есть ли решение для этого? - person Caballero; 12.02.2014
comment
Я не понимаю. Это связано? Если да, пожалуйста, объясните. В противном случае, пожалуйста, откройте отдельный вопрос. - person cvogt; 12.02.2014
comment
@cvogt, как это работает, когда запрос не возвращает никаких результатов. У меня есть аналогичное требование, чтобы получить только столбцы из запроса. Работает для запросов, возвращающих результаты, но не для запросов, не дающих результатов. - person mjlowky; 15.03.2021