Здравствуйте, PM, Вы писали:
PM>Обертка на C++ для sqlite. Создана в духе библиотеки SOCI от Maciej Sobczak.
Судя по примеру очень круто. Особенно впечатлила возможность вот таких запросов:
statement s(db);
// fetch records from some_table
s << "select id, name, salary from some_table", into(id, "id"),
into(name, "name"), into(salary, "salary");
count = 0;
while ( s.exec() )
{
//...
}
Только не могу понять как это работает. Где и как вы разбираете конструкции into и use?
Здравствуйте, MarW, Вы писали:
PM>>Обертка на C++ для sqlite. Создана в духе библиотеки SOCI от Maciej Sobczak. MW>Судя по примеру очень круто. Особенно впечатлила возможность вот таких запросов:
MW>
MW> statement s(db);
MW> // fetch records from some_table
MW> s << "select id, name, salary from some_table", into(id, "id"),
MW> into(name, "name"), into(salary, "salary");
MW> count = 0;
MW> while ( s.exec() )
MW> {
MW> //...
MW> }
MW>
MW>Только не могу понять как это работает. Где и как вы разбираете конструкции into и use?
statement::operator << возвращает временный объект типа prepare_info. В prepare_info имеется парочка operator , (into_holder_ptr) и operator , (into_holder_ptr), которые добавлют создаваемые функциями into и use объекты into_holder_base и use_holder_base во внутренние списки statement.
Так как временный объект, созданный statement::operator << живет лишь до конца выражения, то в его деструкторе можно делать обработку данных. Реально происходит только сохранение запроса (statement::set_query()), а привязка into- и uses-ссылок происходит при первом вызове statement::exec
Если у SQL оператора есть результат (у select, например), то производится обновление into-ссылок.
Примерно так и работает. Запутанно как-то объяснил Поставте точки останова на statement::prepare и statement::exec и попробуйте погонять тесты под отладчиком.
Здравствуйте, PM, Вы писали:
PM>Обертка на C++ для sqlite. Создана в духе библиотеки SOCI от Maciej Sobczak. PM>Брать здесь PM>Интенсивно не тестировалась, наверняка баги присутствуют
Угу, присутсвуют. А именно: если вот конструктор session(std::string const& file_name) вызвать с плохим именем базы, то кинется исключение и деструктор не будет вызван. А следовательно и не будет вызвана функция sqlite3_close, а это надо делать, даже если sqlite3_open вернула ошибку.
Здравствуйте, Рома Мик, Вы писали:
> PM>Интенсивно не тестировалась, наверняка баги присутствуют > Угу, присутсвуют. А именно: если вот конструктор session(std::string > const& file_name) вызвать с плохим именем базы, то кинется исключение и > деструктор не будет вызван. А следовательно и не будет вызвана функция > sqlite3_close, а это надо делать, даже если sqlite3_open вернула ошибку.
Хм. Достаточно странное поведение со стороны SQLite
К сожалению, до понедельника наврядли удастся поэкспериментировать
(выходные уже запланированы ) так что пока сказать ничего определенного
не смогу. В любом случае спасибо за информацию, приму к сведению.
Здравствуйте, PM, Вы писали:
PM>Хм. Достаточно странное поведение со стороны SQLite
Я так понял, что это сделано, чтобы errcode и errmsg работали. В любом случае это четко написано в документации.
Здравствуйте, PM, Вы писали:
PM>Обертка на C++ для sqlite. Создана в духе библиотеки SOCI от Maciej Sobczak. PM>Интенсивно не тестировалась, наверняка баги присутствуют PM>Брать здесь
Произошли небольшие изменения: классы теперь лежат в пространстве имен sqlitepp, избавился от лишних выделений динамической памяти и boost::shared_ptr, соответственно. Исправлен баг, замеченный Миклашевским Романом.
Здравствуйте, Mamut, Вы писали:
> PM>Новая версия лежит там же <http://gzip.rsdn.ru/File/7790/sqlitepp.zip>. > Какие условия использования? Public Domain, GPL, LGPL, CPL или > что-нибудь еще?
Use, modification and distribution is subject to the Boost Software
License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
Здравствуйте, PM, Вы писали:
PM>Обертка на C++ для sqlite. Создана в духе библиотеки SOCI от Maciej Sobczak. PM>Интенсивно не тестировалась, наверняка баги присутствуют PM>Брать здесь
Еще могу заметить, что sqlite3_errmsg возвращает куда более информативный текст, чем тот, что отдает еxception. В идеале неплохо бы помнить и то и другое, а еще и и запрос, который вызвал ошибку, т.к. иначе возможности отладки не очень хорошие.
Здравствуйте, Рома Мик, Вы писали:
> Еще могу заметить, что sqlite3_errmsg возвращает куда более > информативный текст, чем тот, что отдает еxception. В идеале неплохо бы > помнить и то и другое, а еще и и запрос, который вызвал ошибку, т.к. > иначе возможности отладки не очень хорошие.
Да это так, вообще обработка ошибко пока недостаточно продумана
--
foobar2000 v0.8.3: 03. Prodigy — Voodoo People [Exclusive Edition:
Everybody In The Place/Selected Mixes] (пауза)
Здравствуйте, PM, Вы писали:
PM>Здравствуйте, Рома Мик, Вы писали:
>> Еще могу заметить, что sqlite3_errmsg возвращает куда более >> информативный текст, чем тот, что отдает еxception. В идеале неплохо бы >> помнить и то и другое, а еще и и запрос, который вызвал ошибку, т.к. >> иначе возможности отладки не очень хорошие. PM>Да это так, вообще обработка ошибко пока недостаточно продумана
Я просто добавил в session функцию, возвращающую результат sqlite3_errmsg,
да определил пару доп. членов в exception для хранения ошибки/запроса.
Ну, и конструктор(ы) там чуток изменил для их инициализации, и ф-цию what()...
Дальнейшее совсем просто, благо throw там не так много...
PS: PM, очень правильная получилась библиотека, спасибо!!
Здравствуйте, Ant K, Вы писали: > PM>Да это так, вообще обработка ошибко пока недостаточно продумана > > Я просто добавил в session функцию, возвращающую результат sqlite3_errmsg, > да определил пару доп. членов в exception для хранения ошибки/запроса. > Ну, и конструктор(ы) там чуток изменил для их инициализации, и ф-цию > what()... > Дальнейшее совсем просто, благо throw там не так много...
Отлично, я давно собирался этл сделать Может быть стоит выложить сюда diffы исправлений? > PS: PM, очень правильная получилась библиотека, спасибо!!
Пожалуйста, только помните, что тестировалась она очень мало
--
foobar2000 v0.8.3: 10. Paul Oakenfold — Motion (feat. Grant Lee Phil.. [Bunkka]
Здравствуйте, PM, Вы писали:
PM>Отлично, я давно собирался этл сделать Может быть стоит выложить сюда diffы исправлений?
Запросто. Сегодня-завтра выложу...
Здравствуйте, PM, Вы писали:
PM>Отлично, я давно собирался этл сделать Может быть стоит выложить сюда diffы исправлений? diffы здесь PM>Пожалуйста, только помните, что тестировалась она очень мало
Да, нашлась ошибочка в transaction::exec_sql (см.).
Re: SQLite C++ wrapper (альтернативы)
От:
Аноним
Дата:
09.03.05 09:11
Оценка:
Кто нибудь сравнивал враппер сабжевый с CppSQLite — C++ Wrapper for SQLite? Интересуют преимущества и недостатки одного перед другим.
И сразу другой вопрос: сабж нормально компилируется в VS2003, но при сборке в VS2002 на фрагменте кода из файла tut.h
error C2065: 'Test' : undeclared identifier
error C2065: 'Group' : undeclared identifier
error C2687: cannot define a nested UDT of a template class out of line
Здравствуйте, <Аноним>, Вы писали:
А>Кто нибудь сравнивал враппер сабжевый с CppSQLite — C++ Wrapper for SQLite? Интересуют преимущества и недостатки одного перед другим.
Недостатки того класса: слишком тонкий враппер, надо самому вызывать finalize, геморно получать результаты и т.д.
Недостотаки этого класса: мало оттестирован, довольно сложный для неподготовленного взгляда код.
А>И сразу другой вопрос: сабж нормально компилируется в VS2003, но при сборке в VS2002
Ну там компилятор еще почти что шестерошный, так что вряд ли можно что-то сделать, все же до настоящего C++ он не дотягивает.
Здравствуйте, аноним, Вы писали:
> Кто нибудь сравнивал враппер сабжевый с CppSQLite — C++ Wrapper for > SQLite <http://codeproject.com/database/CppSQLite.asp>? Интересуют > преимущества и недостатки одного перед другим.
Думаю, я буду необъективен
Просто разные подходы, вот примерный код для сравнения:
CppSQLite
// open database
CppSQLiteDB db;
db.open("test.db");
// create and fill table
db.execDML("create table emp(no integer primary key, name char(20))");
for (int i = 0; i < 5; i++)
{
char buf[128];
sprintf(buf, "insert into emp(name) values('Empname%06d');", i+1);
db.execDML(buf);
}
// fetch data
CppSQLiteQuery q = db.execQuery("select * from emp");
for ( ; !q.eof(); q.nextRow() )
{
cout << q.fieldValue(0) << "|" << q.fieldValue(1) << "|" << endl;
}
SQLite++
// open database
session se("test.db");
// create and fill table
se << "create table emp(no integer primary key, name char(20))";
for (int i = 0; i < 5; i++)
{
se << "insert into emp(name) values('" << "Empname" << i+1 << "')";
}
// fetch data
statement st(se);
int no;
string name;
st << "select * from emp", into(no), into(name);
while ( st )
{
cout << no << "|" << name;
}
> И сразу другой вопрос: сабж нормально компилируется в VS2003, но при > сборке в VS2002 на фрагменте кода из файла tut.h
[ошибка поскипана] > Кто может помочь разобраться и пофиксить?
TUT использует шаблонные техники с которыми VS2002 категорически не дружит.
Выход — не компилировать тестовый проект или сменить компилятор
Я собирал SQLite++ только с gcc 3.2.3 и VS2003, так что более древними компиляторами (типа Visual C++ 6 или gcc 2.x.x)
может и не скомпилироваться.
--
foobar2000 v0.8.3: 07. Jerry Beeks — Flash $ [Nightmares on Wax DJ-KICKS:]
Re[3]: SQLite C++ wrapper (альтернативы)
От:
Аноним
Дата:
09.03.05 14:32
Оценка:
Здравствуйте, PM, Вы писали:
PM>Думаю, я буду необъективен PM>Просто разные подходы, вот примерный код для сравнения:
Да, спасибо за наглядный сравнительный пример .
Пожалуй, сабжевый враппер стОит потестировать по-конкретнее (чем и займемся )
Здравствуйте, Аноним, Вы писали:
А>Здравствуйте, PM, Вы писали:
PM>>Думаю, я буду необъективен PM>>Просто разные подходы, вот примерный код для сравнения: А>Да, спасибо за наглядный сравнительный пример . А>Пожалуй, сабжевый враппер стОит потестировать по-конкретнее (чем и займемся )
Смотрю тоже на этот врапер, хочу спросить как успехи в тестировании, и работает ли еще автор над врапером?
PM>Смотрю тоже на этот врапер, хочу спросить как успехи в тестировании, и работает ли еще автор над врапером?
Я переписывался с автором пару месяцев тому назад. Он собирался модифицироват враппер, выкинуть оттуда буст и внести еще кой-какие изменения. К сожалению, ему пришлось уйти в оффлайн на неопределенное время С тех пор — ни слуху ни духу.
А враппер в ом виде, что есть я даже использую в одной программе. Нареканий не возникало.
Вводная часть:
sqlite только начинаю изучать,
Boost'a у меня нет(скачать тоже нет возможности) + нужна поддержка уникода.
В меру своих сил я изменил код сабжа, но вот такие примеры не работают.
Просьба прогнать их на оригинальном враппере (а то не пойму толи я где-то накосячил, толи лыжи не едут)
пример 1:
int _tmain(int argc, _TCHAR* argv[])
{
session db;
try
{
db.open(L"d:\\test.db");
statement st(db);
int id;
double salary;
CString name;
st << L"create table some_table(id integer, name varcharn(100) not null, salary real(8))";
st.exec();
st << L"insert into some_table(id, name, salary) values(1, 'anna', 345.2)";
st.exec();
//st << L"select id, name, salary from some_table where id > " << 0, into(id), into(name), into(salary);
//st.exec();
//std::wcout << id << L' ' << (LPCTSTR)name << L' ' << salary << std::endl;
// в этом примере таблица не дропиться, если предыдущие три строки раскомментарины - причем никаких исключений не возникает
// если они закомментарины (как сейчас), то все работает как-надо
st << L"drop table some_table";
st.exec();
}
catch (exception r)
{ std::wcout << L"Error: " << r.code << std::endl;
}
db.close();
return 0;
}
пример 2:
int _tmain(int argc, _TCHAR* argv[])
{
session db;
try
{
db.open(L"test.db");
statement st(db);
int id;
double salary;
CString name;
st << L"create table some_table(id integer, name varcharn(100) not null, salary real(8))";
st.exec();
st << L"insert into some_table(id, name, salary) values(1, 'anna', 345.2)";
st.exec();
st << L"insert into some_table(id, name, salary) values(2, 'peter', 999.2)";
st.exec();
st << L"select id, name, salary from some_table where id > " << 0, into(id), into(name), into(salary);
st.exec();
std::wcout << id << L' ' << (LPCTSTR)name << L' ' << salary << std::endl;
// исключений в примере никаких нет, но второй select выдает все по нулям, таблица не дропиться
st << L"select id, name, salary from some_table where id > " << 1, into(id), into(name), into(salary);
st.exec();
std::wcout << id << L' ' << (LPCTSTR)name << L' ' << salary << std::endl;
st << L"drop table some_table";
st.exec();
}
catch (exception r)
{ std::wcout << L"Error: " << r.code << std::endl;
}
db.close();
return 0;
}
Наконец-то выложил поправленную версию. Есть небольшая несовместимость в интерфейсах с предыдущей, до документации и build-скриптов руки пока не дошли Поставляется с исходниками SQLite 3.2.7 (последняя версия). Собиралось Visual C++ 7.1 (более старые версии не поддерживаются). Когда-то давно собирал g++ 3.2.3, но makefile не осталось.
Если кому-то будет интересно, буду продолжать развитие по мере сил и свободного времени. У меня сейчас нет проектов с использованием SQLite, так что любые отзывы приветсвуются
version 0.3.1
Minor bug fixes, some interface changes.
version 0.3
Dependences to third-party libraries are removed. Except SQLite of course
version 0.2
Implementation is refactored, dynamic memory allocations are minimized.
version 0.1
This is first release. Basic concepts are implemented.
Re[2]: SQLite C++ wrapper
От:
Аноним
Дата:
06.10.05 08:13
Оценка:
Здравствуйте, PM, Вы писали:
PM>Здравствуйте, PM, Вы писали:
PM>Наконец-то выложил поправленную версию.
Спасибо что поддерживаешь продукт
PM>Если кому-то будет интересно, буду продолжать развитие по мере сил и свободного времени. У меня сейчас нет проектов с использованием SQLite, так что любые отзывы приветсвуются
Интересно, думаю не только мне
Как насчет поддержки уникода?
Здравствуйте, Аноним, Вы писали:
PM>>Если кому-то будет интересно, буду продолжать развитие по мере сил и свободного времени. У меня сейчас нет проектов с использованием SQLite, так что любые отзывы приветсвуются А>Интересно, думаю не только мне А>Как насчет поддержки уникода?
В одном из промежуточных вариантов я пытался это сделать, но подход мне не понравился. Сейчас вот думаю как это сделать.
p.s. Я оказался неоригинальным, и название SQLite++ уже используется. Так что, похоже, надо думать о смене названия
Здравствуйте, PM, Вы писали:
PM>Если кому-то будет интересно, буду продолжать развитие по мере сил и свободного времени. У меня сейчас нет проектов с использованием SQLite, так что любые отзывы приветсвуются
Отзыв.
Потребовалась удобная и не громоздкая СУБД, посоветовали Вашу.
Скачал версию 0.3.2. Компилирую под VisualC++ 7. Возникают ошибки
...\sqlitepp0.3.2\sqlitepp3\test\tut\tut.h(520): error C2065: 'Group' : undeclared identifier
...\sqlitepp0.3.2\sqlitepp3\test\tut\tut.h(520): error C2065: 'Test' : undeclared identifier
в строках кода:
Здравствуйте, Didro, Вы писали:
D>Отзыв. D>Потребовалась удобная и не громоздкая СУБД, посоветовали Вашу. D>Скачал версию 0.3.2. Компилирую под VisualC++ 7. Возникают ошибки D>...\sqlitepp0.3.2\sqlitepp3\test\tut\tut.h(520): error C2065: 'Group' : undeclared identifier D>...\sqlitepp0.3.2\sqlitepp3\test\tut\tut.h(520): error C2065: 'Test' : undeclared identifier D>в строках кода:
Это тесты, а не сама библиотека, для тестов нужен соотвествующий фреймворк, но тесты никому, кроме разработчика не нужны, разве что в качестве примеров кода использовать.
... << RSDN@Home 1.2.0 alpha rev. 619>>
Re[2]: SQLite C++ wrapper
От:
Аноним
Дата:
30.07.07 02:18
Оценка:
Здравствуйте, PM, Вы писали:
PM>Здравствуйте, PM, Вы писали:
PM>Если кому-то будет интересно, буду продолжать развитие по мере сил и свободного времени. У меня сейчас нет проектов с использованием SQLite, так что любые отзывы приветсвуются
[/q]
А как обновлять записи ? Попробовал в примере (выделенные строки ниже) — какая-то хрень получилась.
Отладчик показывает, что вместо Kat, там МММ.
Чуствую, что что-то не правильно сделал, но что ?
template<>template<>
void object::test<1>()
{
record recs[2] = { record(1, "Наталия", 123.45), record(2, "Анастасия", 678.90) };
// insert recordsfor (size_t i = 0; i < dimof(recs); ++i)
{
st << "insert into some_table values( :id, :name, :salary, NULL)",
use(recs[i].id), use(recs[i].name), use(recs[i].salary);
ensure("row inserted", !st.exec() );
}
// count inserted recordint count;
se << "select count(*) from some_table", into(count);
ensure_equals("row count", count, dimof(recs) );
se << "update some_table set name = :name where id = 1", use("Kat");
st.exec();// check inserted records
record r;
st << "select id, name, salary from some_table",
into(r.id, "id"), into(r.name, "name"), into(r.salary, "salary");
for (count = 0; st.exec(); ++count)
{
ensure_equals(recs[count], r);
}
ensure_equals(count, dimof(recs));
}
Здравствуйте, Аноним, Вы писали:
А>А как обновлять записи ? Попробовал в примере (выделенные строки ниже) — какая-то хрень получилась. А>Отладчик показывает, что вместо Kat, там МММ. А>Чуствую, что что-то не правильно сделал, но что ?
А>
А>template<>template<>
А>void object::test<1>()
А>{
А> record recs[2] = { record(1, "Наталия", 123.45), record(2, "Анастасия", 678.90) };
А> // insert records
А> for (size_t i = 0; i < dimof(recs); ++i)
А> {
А> st << "insert into some_table values( :id, :name, :salary, NULL)",
А> use(recs[i].id), use(recs[i].name), use(recs[i].salary);
А> ensure("row inserted", !st.exec() );
А> }
А> // count inserted record
А> int count;
А> se << "select count(*) from some_table", into(count);
А> ensure_equals("row count", count, dimof(recs) );
// здесь выполняется UPDATE в БД, представленной экземпляром se класса session
А> se << "update some_table set name = :name where id = 1", use("Kat");
// а следом за ним выполняется подготовленный statement st
// вида "insert into some_table values( :id, :name, :salary, NULL)", use(recs[i].id), use(recs[i].name), use(recs[i].salary);
// но т.к. из цикла уже вышли, то индекс i указывает на мусор за пределами массива recs
А> st.exec();
А> // check inserted records
А> record r;
А> st << "select id, name, salary from some_table",
А> into(r.id, "id"), into(r.name, "name"), into(r.salary, "salary");
А> for (count = 0; st.exec(); ++count)
А> {
А> ensure_equals(recs[count], r);
А> }
А> ensure_equals(count, dimof(recs));
А>}
А>
Это соображения, почему вместо Kat получается MMM.
Обновлять записи так же, как и добавлять — либо выполнять SQL операторы непосредственно в базе, либо подготовить statement и привязывать к нему данные. Типа такого..
1. Непосредственное выполненение. Используется в основном когда нужно по-быстрому какую-то запись
session se("test.db");
se << "UPDATE some_table SET name = :name WHERE id = :id", use("Kat"), use(1);
2. Выполненение statement'а. Подготавливается SQL запрос, а реальные данные подставляются по мере необходимости:
session se("test.db");
statement st(se);
string name;
int id;
// подготавливаем оператор
st << "UPDATE some_table SET name = :name WHERE id = :id", use(name), use(id);
for (id = 1; id < 100; ++i)
{
std::cin >> name;
st.exec(); // здесь выполняется UPDATE
}
Здравствуйте, PM, Вы писали:
PM>Обертка на C++ для sqlite. Создана в духе библиотеки SOCI от Maciej Sobczak. PM>Интенсивно не тестировалась, наверняка баги присутствуют PM>Брать здесь
Давненько сюда не писал. Вообще-то иногда обертка даже обновляется. Выложил библиотечку в Subversion на berlios.de
Re: SQLite C++ wrapper
От:
Аноним
Дата:
01.06.09 09:09
Оценка:
Здравствуйте PM, юзаю ваш враппер, а как на счет BLOB?
Здравствуйте, Аноним, Вы писали:
А>Здравствуйте PM, юзаю ваш враппер, а как на счет BLOB?
Все нормально
В string.hpp есть такое:
struct blob
{
void const* data;
size_t size;
};
В statement.hpp есть:
class statement
{
...
// Column value as BLOB.void column_value(int column, blob& value) const;
// Use BLOB value in query.void use_value(int pos, blob const& value);
};
Есть конвертер из std::vector<T> в blob, который можно использовать так:
statement st(db);
std::vector<float> reals(200);
st << "create table test(vals blob)";
st << "insert into test(:vals)", use(reals);