Абстракция базы данных / адаптеры для ruby - PullRequest
3 голосов
/ 31 мая 2010

Какие абстракции / адаптеры базы данных вы используете в Ruby? В основном меня интересуют ориентированные на данные функции, а не функции с сопоставлением объектов (например, активная запись или преобразователь данных).

Я сейчас пользуюсь сиквелом. Есть ли другие варианты?

Меня больше всего интересует:

  • простой, чистый и однозначный API
  • выбор данных (очевидно), фильтрация и агрегирование
  • выбор необработанных значений без сопоставление полей: SELECT col1, col2, col3 => [val1, val2, val3] не хеш {: col1 => val1 ...}
  • быть в состоянии передать список столбцов / значений для выбора: выберите (array_of_columns) (не: dataset.select (: col1,: col2,: col3), который требует, чтобы столбцы были известны)
  • API учитывает схемы таблиц some_schema.some_table согласованным (и рабочим) способом; также отражение для этого (получить схему из таблицы)
  • отражение в базе данных: получить список столбцов таблицы, их типы хранения в базе данных и, возможно, абстрагированные типы адаптера
  • создание таблицы, удаление
  • иметь возможность работать с другими таблицами (вставка, обновление) в цикле, перечисляющем выборку из другой таблицы, без необходимости извлечения всех записей из перечисляемой таблицы

Цель состоит в том, чтобы манипулировать данными со структурой unknown во время написания кода, что противоположно отображению объекта, где структура или большая часть структуры обычно хорошо известны. Мне не нужны накладные расходы на сопоставление объектов.

Какие есть варианты, включая серверные для библиотек отображения объектов?

1 Ответ

5 голосов
/ 01 июня 2010

Я ведущий разработчик Sequel, поэтому этот ответ явно предвзят, но я не знаю ни одной библиотеки баз данных ruby, которая делает все, что вы хотите.

Похоже, что некоторые из ваших желаний воспринимаются как ограничения в сиквеле, некоторые из которых можно устранить:

  • выбор необработанных значений без сопоставления полей: SELECT col1, col2, col3 => [val1, val2, val3] не хэш {: col1 => val1 ...}

Попробуйте:

DB[:table].filter([:col1, :col2, :col3].zip([1, 2, 3]))
# SELECT * FROM table WHERE ((col1 = 1) AND (col2 = 2) AND (col3 = 3))

Тривиально добавить новый метод набора данных, обеспечивающий более приятный API для вышеперечисленного:

DB[:table].bfilter([:col1, :col2, :col3], [1, 2, 3])
  • быть в состоянии передать список столбцов / значений для выбора: выберите (array_of_columns) (не: dataset.select (: col1,: col2,: col3), который требует, чтобы столбцы были известны)

Попробуйте:

array_of_columns = [:col1, :col2, :col3]
DB[:table].select(*array_of_columns)
# SELECT col1, col2, col3 FROM table
  • API учитывает схемы таблиц some_schema.some_table согласованным (и работающим) способом; также отражение для этого (получить схему из таблицы)

Сиквел имеет дело со схемами таблиц:

DB[:schema__table]
DB[:table.qualify(:schema)]
# SELECT * FROM schema.table

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

  • отражение в базе данных: получить список столбцов таблицы, их типы хранения в базе данных и, возможно, абстрагированные типы адаптера

Столбцы как массив символов:

DB[:table].columns
# => [:col1, :col2, :col3]

Информация о схеме:

DB.schema(:table)
# [[:col1=>{:type=>:integer, :db_type=>'int(11)', :default=>nil, ...}], ...]

: type - символ типа ruby,: db_type - строка типа базы данных.

  • иметь возможность работать с другими таблицами (вставка, обновление) в цикле, перечисляющем выборку из другой таблицы, без необходимости извлечения всех записей из перечисляемой таблицы

Полагаю, вы просите что-то вроде этого:

DB[:table].each do |row|
  DB[:other_table].insert(:blah=>row[:blah])
end

Что не работает корректно на некоторых адаптерах в Sequel из-за того, что пул соединений использует то же соединение с базой данных для вставки в: other_table, пока оно еще используется для: select on table. Вы можете обойти это, используя поддержку шардинга:

DB = Sequel.connect(..., :servers=>{:read_only=>{}})
DB[:table].each do |row|
  DB[:other_table].insert(:blah=>row[:blah])
end

В этом случае DB будет использовать: read_only shard для таблицы select on: и шард: default для вставки в: other_table. Вы также можете указать шарды явно:

DB[:table].server(:read_only).each do |row|
  DB[:other_table].server(:default).insert(:blah=>row[:blah])
end

Точки, о которых я не говорил, полагаю, вы знаете, что Сиквел уже справляется. И вполне возможно, что Sequel не удовлетворяет всем вашим потребностям, хотя в этом случае я сомневаюсь, что любая другая библиотека баз данных ruby ​​подойдет.

...