Класс C++ DBI - лучший/самый удобный для разработчиков стиль

В нашем текущем проекте нам нужен высокоуровневый DBI для разных баз данных. Он должен обеспечивать следующие функции:

  • в кеше памяти — DBI должен иметь возможность кэшировать все операции чтения и обновлять кеш при записи вызовов (приложение, в котором мы кодируем, является многопоточным и постоянно нуждается в быстром доступе к текущим данным). ). Кэш памяти будет основан на boost::multi_index
  • автоматическое построение sql. Мы не хотим анализировать оператор sql для поиска в кеше памяти.

Поскольку нам нужно предоставить функции для: определения макета таблицы, выбора, вставки, обновления, объединения и т. д., интерфейс станет очень сложным.

Нам нужен хороший способ вызова функции интерфейса.

Вокруг много стилей, но мы не смогли найти ни одного полезного для нашего использования.

Вот несколько примеров:

СОКИ

sql << "select name, salary from persons where id = " << id, into(name), into(salary);

Нам не нужны некоторые операторы SQL, поэтому нам придется определить what и from по-другому.

pqxx

Conn.prepare("select_salary",
    "select name, salary from persons where id = $1")
    ((string)"integer",prepare::treat_direct);

Интенсивное использование перегруженного operator() просто уродливо, но это может сработать и для нас.

Есть предложения по разработке интерфейса?


person Thomas Berger    schedule 01.07.2011    source источник


Ответы (2)


Как насчет использования объектно-реляционного сопоставления? Вот некоторые идеи фрагментов кода, которые пришли мне в голову - я делал это только на Python, никогда на C++ и только для довольно простых баз данных. В Википедии есть список фреймворков, которые должны избегать слишком большого количества колес. связанные НИОКР.

class people: public dbi_table
{
    // id column handled by dbi_table.
    name: string_column;
    salary: money_column;
};

class cost_center: public dbi_table
{
    name: string_column;
    office: foreign_key<offices>;
};

class people_cost_center_link: public link_table
{
    // Many-many relationships.
};

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

person Optimal Cynic    schedule 05.07.2011
comment
Спасибо за ваши идеи, но мы уже оценили это. ODB использует собственный компилятор/препроцессор, большинство фреймворков ORM используют типы данных, зависящие от базы данных, и многое другое. Мне нравится стиль кодирования для использования с ODB, но сейчас я понятия не имею, как это реализовать без необходимости использования собственного компилятора/препроцессора. Поскольку нам также необходимо запрашивать внутренний кеш, мы должны иметь возможность сопоставлять типы данных sql с соответствующими внутренними типами. Может быть ты. - person Thomas Berger; 05.07.2011
comment
Итак, если мы исключаем использование существующей структуры, кажется, что самая большая проблема заключается в синтаксисе запроса, верно? Вставки, обновления и поиск по идентификатору могут обрабатываться вашей таблицей, столбцом и т. Д. Объектами. Что, если бы вы реализовали метод search_by‹field_name› для каждой таблицы, которая в основном выполнялась, если не в кеше, тогда sql select * from table, где field_name — бла? - person Optimal Cynic; 05.07.2011
comment
search_by<field_name> звучит великолепно. сегодня вечером посмотрю на это поглубже - person Thomas Berger; 05.07.2011
comment
@Thomas, фреймворки ORM на других языках также используют метакомпилятор, кстати, компилятор ODB будет собирать исходный код C++, который вы затем создадите с помощью своего g++ или любого другого компилятора, который вы используете. Я не вижу, какую проблему вы видите в этом. мне это кажется замечательным - person lurscher; 06.07.2011
comment
@lurscher: прочитайте мой вопрос. Нам нужно реализовать кеш (чтение/запись) и приложение имеет поддержку плагинов. Поэтому сторонние плагины не должны мешать созданию собственного кеша. - person Thomas Berger; 06.07.2011

Я бы сделал это так (и это было бы хорошо с точки зрения С++, не знаю, правильно ли это работает с базой данных):

struct Handle { int id; }
class DBI 
{
public:
   virtual Handle select(int column_id)=0;
   virtual Handle select(int column1, int column2)=0;
   virtual Handle id(int id)=0;
   virtual Handle join(Handle i1, Handle i2)=0;
   virtual void execute_query(Handle i)=0;
};

Обычно эти функции реализуются так:

Handle select(int column_id) {
   return new_handle(new SelectNode(column_id));
}

где функция new_handle просто вставит SelectNode в std::vector или std::map и создаст для него дескриптор.

person tp1    schedule 05.07.2011