Russian Qt Forum

Qt => Дополнительные компоненты => Тема начата: GraninAS от Декабрь 09, 2009, 12:03



Название: QST: QsT SQL Tools
Отправлено: GraninAS от Декабрь 09, 2009, 12:03
Добрый день, уважаемые коллеги!

Хочу поделиться своим инструментарием QsT Sql Tools, да не просто так, а с корыстными целями: мне нужна помощь по выявлению ошибок, особенно это касается SqlTreeModel - древовидной модели данных.

Вкратце о проекте.

QsT Sql Tools - это набор классов (который пока трудно назвать библиотекой), облегчающий в разы программирование приложений баз данных на Qt. Основная цель банальна: абстрагироваться от "лапши", которая появляется при внесении SQL-запросов в код. Делается это, разумеется, путем генерации SQL-запросов. Но куда менее были бы полезными мои классы, если бы они не позволяли работать с полями поименно, создавать запросы не просто в виде строки, а виде неких структур (даже можно сказать - классов), где потом можно поменять, к примеру, значение какого-нибудь фильтра... И, самое главное, облегчается настройка модели/представления.

Да не просто облегчается, а практически исчезает. В общем, я буду рад, если вам понравится.

Что хотелось бы взамен? Помощи. Плохо работает SqlTreeModel. Во-первых, модель только для чтения. Во-вторых, выдает странности в некоторых моментах. Моменты можно увидеть в прикрепленном здесь примере. С ним я уже обращался на один из форумов, но там молчат как рыбы. Надеюсь, что вы не оставите меня, так как хотелось бы довести библиотечку до нужной кондиции. Она того стоит.

Итак, во вложении вы найдете эту несчастную SqlTreeModel. Я понимаю, что вопросы, подобные моему, всплывают и здесь, и вообще везде. Сам рыл, причины искал, и понял, что чего-то не знаю. Вообще, хочется переписать SqlTreeModel, чтобы не использовать new или другое явное выделение памяти, - это дюже нехорошо. Но сначала надо понять, что я сделал не так...

Сам инструментарий находится здесь: https://sourceforge.net/projects/qstsqltools/
Там же есть пример базы данных, написанной с его помощью. Какое-то время он там полежит, потом я его уберу, - в нем классы еще даже без шапки и без лицензии, а это не есть гуд.

Итак, с волнением жду вашей реакции. Заранее спасибо, - хоть эти два слова и набили всем оскомину. :)


Название: Re: Qst SQL Tools
Отправлено: panAlexey от Декабрь 09, 2009, 12:40
Интересно. Поставлю закладку. :)


Название: Re: Qst SQL Tools
Отправлено: viktor.kz от Декабрь 09, 2009, 13:12
Error in 'Icons.qrc': Cannot find file 'Resources/Icons/arrow-circle-double-135.png'

Ресурсики бы ещё получить бы ...


Название: Re: Qst SQL Tools
Отправлено: GraninAS от Декабрь 10, 2009, 02:46
P.S. от 7 апреля 2010
Ссылка на ресурсы более не актуальна. Пример использования QST убран с сайта. Скоро выложу новый пример.
P.P.S от 12 апреля 2010
Выложил новый пример.

Ресурсики бы ещё получить бы ...

Да, действительно, я о них забыл... Добавил отдельным файлом, вот: http://sourceforge.net/projects/qstsqltools/files/TradeDB%20Resources.rar/download.
Весят много, 4мб. Это Fugue Icons (http://code.google.com/p/fugue-icons/). И хотя используются далеко не все, залил полную папку.

Скопируйте ее в папку проекта. Должно скомпилироваться... Правда, давно не проверял исходники примера. Они могут быть "грязными".


Название: Re: Qst SQL Tools
Отправлено: GraninAS от Декабрь 10, 2009, 03:45
Интересно. Поставлю закладку. :)

Могу рассказать подробнее... Хотите?

...Ммм, ну так вот. Самое интересное: генерация SQL. Вообще, для QST как-то сама собой разработалась концепция DFD - Declarative Field Descriptor. (Я понимаю, что звучит это масштабно, не в пример самой библиотечке, но у меня такая слабость - ставить высокие цели и называть их соответствующим образом.) По ней, простые запросы SQL мысленно разбиваются на "поля" и "значения" с разными свойствами, из которых потом можно собрать пакет. Пример скажет лучше.
Код:
SQL:
SELECT Name, Birthday, Birthplace, ID
FROM tPersons
WHERE
Age > 30
AND
Name LIKE 'Алекс%'

DFD:
SqlBatch batch;
batch.addSource("tPersons");

batch << SqlField("Name", fv_visible, fr_none, "Имя", 100)
<< SqlField("Birthday", fv_visible, fr_none, "Дата рождения", 80)
<< SqlField("Birthplace", fv_visible, fr_none, "Место рождения", 120)
<< SqlField("ID", fv_invisible, fr_id)

<< SqlField("Age", SqlValue(30, fo_greater), fp_where)
<< SqlField("Name", SqlValue("Алекс", fo_like, fb_right), fp_where);
Генератор принимает два параметра:
Код:
SqlGen gen;
QString query = gen.query(batch, sql_select);
Но вообще-то о его работе задумываться стоит только тогда, когда нужно понять/поменять алгоритм генерации. Сама генерация скрыта. Дело в том, что главной единицей для оперирования как DFD-описателями, так и моделями/представлениями становится класс, отнаследованный от AbstractModelHandler. Фактически, класс представляет собой функции, создающие DFD под конкретную задачу. Например, для работы с определенной таблицей БД. Конечно, никто не мешает в этом классе сделать дополнительные функции, например, что-то вроде addPerson(), updatePerson(), deletePerson() и т.д., которые бы сами создавали нужный DFD-описатель, а программист просто их вызывал с параметрами. Вот пример из другой БД, которую сейчас пишу:
Код:
#include "abstractmodelhandler.h"

using namespace Sql;

const QString GLOBAL_PARAMETERS_SOURCE = "ParamS";

const int GLOBAL_PARAMETERS = 3335;

const int GLOBAL_PARAMETER_CLOSE_PROC = 41;

class h_GlobalParametersHandler : public AbstractModelHandler
{
public:
    h_GlobalParametersHandler();

bool updateParameter(const SqlValue &oldId,
const SqlValue &name,
const SqlValue &stringValue,
const SqlValue &intValue,
const SqlValue &floatValue,
const SqlValue &description,
const SqlValue &dateBegin,
const SqlValue &dateEnd);

private:

virtual SqlQueryDescriptor _selector(const SqlQueryModelTypes &modelType = mt_plain,
const int &queryNumber = 0) const;
virtual SqlQueryDescriptor _inserter(const int &queryNumber = 0) const;
virtual SqlQueryDescriptor _updater(const int &queryNumber = 0) const;
virtual SqlQueryDescriptor _deleter(const int &queryNumber = 0) const;
virtual SqlQueryDescriptor _executor(const int &queryNumber = 0) const;
};
[code]
И определение класса:
[code]
bool h_GlobalParametersHandler::updateParameter(const SqlValue &oldId,
const SqlValue &name,
const SqlValue &stringValue,
const SqlValue &intValue,
const SqlValue &floatValue,
const SqlValue &description,
const SqlValue dateBegin,
const SqlValue dateEnd)
{
h_GlobalParametersHandler th;
th.setValue(ID_VALUE, oldId);
th.setValue("DateAfter", dateBegin);
bool res = th.Exec(GLOBAL_PARAMETER_CLOSE_PROC);
Q_ASSERT(res);

th.clearValues();
th.setValue("Name", name);
th.setValue("StringValue", stringValue);
th.setValue("IntValue", intValue);
th.setValue("FloatValue", floatValue);
th.setValue("Description", description);
th.setValue("DateBegin", dateBegin);
th.setValue("DateEnd", dateEnd);
res = th.Insert();

return res;
}

SqlQueryDescriptor h_GlobalParametersHandler::_selector(const SqlQueryModelTypes &modelType,
const int &queryNumber) const
{
SqlBatch batch;

batch.addSource("vGlobalParams");

if (queryNumber == GLOBAL_PARAMETERS)
{
batch << SqlField("ID", fv_invisible, fr_id)
<< SqlField("Name", fv_visible, fr_none, "Название", 100)
<< SqlField("StringValue", fv_visible, fr_none, "Строка", 120)
<< SqlField("IntValue", fv_visible, fr_none, "Целое", 50)
<< SqlField("FloatValue", fv_visible, fr_none, "Действит.", 70)
<< SqlField("Description", fv_visible, fr_none, "Описание", 120)
<< SqlField("vcDateBegin", fv_visible, fr_none, "Начало действия", 100)
<< SqlField("vcDateEnd", fv_visible, fr_none, "Конец действия", 100)
<< SqlField("vcIsUsed", fv_visible, fr_none, "Актив.?", 60)

<< SqlField("DateBegin", fv_invisible)
<< SqlField("DateEnd", fv_invisible)

<< SqlField("ID", value(ID_VALUE), fp_where)

<< SqlField("Name", value("Name"), fp_where)
<< SqlField("IsUsed", value("IsUsed"), fp_where)
<< SqlField("DateBegin", value("DateBegin"), fp_where)
<< SqlField("DateEnd", value("DateEnd"), fp_where);
}
else
if (queryNumber == LAST_ID)
{
batch << SqlField(MAX_ID, fv_visible, fr_none);
}
else
{
Q_ASSERT(false);
}

return SqlQueryDescriptor(batch, sql_select, queryNumber);
}

SqlQueryDescriptor h_GlobalParametersHandler::_inserter(const int &queryNumber) const
{
SqlBatch batch;

batch.addSource("tGlobalParams");

batch << SqlField("Name", value("Name"), fp_insert)
<< SqlField("StringValue", value("StringValue"), fp_insert)
<< SqlField("IntValue", value("IntValue"), fp_insert)
<< SqlField("FloatValue", value("FloatValue"), fp_insert)
<< SqlField("Description", value("Description"), fp_insert)
<< SqlField("DateBegin", value("DateBegin"), fp_insert)
<< SqlField("DateEnd", value("DateEnd"), fp_insert);

return SqlQueryDescriptor(batch, sql_insert, queryNumber);
}

SqlQueryDescriptor h_GlobalParametersHandler::_updater(const int &queryNumber) const
{
SqlBatch batch;

batch.addSource("tGlobalParams");

batch << SqlField("Name", value("Name"), fp_update)
<< SqlField("StringValue", value("StringValue"), fp_update)
<< SqlField("IntValue", value("IntValue"), fp_update)
<< SqlField("FloatValue", value("FloatValue"), fp_update)
<< SqlField("Description", value("Description"), fp_update)
<< SqlField("DateBegin", value("DateBegin"), fp_update)
<< SqlField("DateEnd", value("DateEnd"), fp_update)

<< SqlField("ID", value(ID_VALUE, SqlValue(nt_null)), fp_where);

return SqlQueryDescriptor(batch, sql_update, queryNumber);
}

SqlQueryDescriptor h_GlobalParametersHandler::_deleter(const int &queryNumber) const
{
SqlBatch batch;

batch.addSource("tGlobalParams");

batch << SqlField("ID", value(ID_VALUE, SqlValue(nt_null)), fp_where);

return SqlQueryDescriptor(batch, sql_delete, queryNumber);
}

SqlQueryDescriptor h_GlobalParametersHandler::_executor(const int &queryNumber) const
{
SqlBatch batch;

if (queryNumber == GLOBAL_PARAMETER_CLOSE_PROC)
{
batch.addSource("pCloseGlobalParameter");
batch << SqlValue(value(ID_VALUE, SqlValue(nt_null)))
<< SqlValue(value("DateAfter"));
}
else
{
Q_ASSERT(false);
}

return SqlQueryDescriptor(batch, sql_execute, queryNumber);
}
Закономерный вопрос: что эта вся мишура дает? Отвечу кодом. Сначала часть класса формы:
Код:
h_GlobalParametersHandler _handler
SqlQueryModel _model;
Затем некоторые функции класса формы:
Код:
void f_GlobalParametersForm::loadParameters()
{
// Загружаем источник данных. Берем select-запрос из h_GlobalParametersHandler::_selector() с номером GLOBAL_PARAMETERS.
_handler.reloadSource(GLOBAL_PARAMETERS_SOURCE, GLOBAL_PARAMETERS, &_model);
// Настраиваем tableView на источник данных. Названия колонок, их ширина, ориентация, - все берется из описателя DFD, сформированного функцией _selector с номером запроса GLOBAL_PARAMETERS и типом модели mt_plain (если бы использовался TreeView, тип модели был бы mt_tree).
_handler.setTableView(GLOBAL_PARAMETERS_SOURCE, ui->tv_Parameters);
}

SqlValue f_GlobalParametersForm::parameterID() const
{
// Ключевое значение текущей строки во view.
return _handler.keyValueOfView(GLOBAL_PARAMETERS_SOURCE);
}

// Удаление текущей строки во view из БД.
void f_GlobalParametersForm::deleteParameter()
{
d_ConfirmDialog dlg;
if (dlg.exec() == QDialog::Accepted)
{
_handler.DeleteCurrent(GLOBAL_PARAMETERS_SOURCE, ui->tv_Parameters);
loadParameters();
}
}

...И некоторые другие фишки.

Хотя, многого SQT не хватает. Например, создавать более сложные запросы или хотя бы те, где в секции WHERE есть OR. Я пока думаю над этим. Кое-какие мысли уже есть.[/code][/code]


Название: Re: QST: QsT SQL Tools
Отправлено: daimon от Декабрь 10, 2009, 09:43
Ваша Sql модель позволяет находу добавлять колонки и записывать их в базу и добавлять не в конец, а например в середину?


Название: Re: QST: QsT SQL Tools
Отправлено: lit-uriy от Декабрь 10, 2009, 10:10
daimon, в БД нельзя добавлять не в конец таблицы


Название: Re: QST: QsT SQL Tools
Отправлено: GraninAS от Декабрь 10, 2009, 10:15
Ваша Sql модель позволяет находу добавлять колонки и записывать их в базу и добавлять не в конец, а например в середину?
А что подразумевается под колонками в базе, и о какой модели вы спрашиваете: SqlTreeModel или SqlQueryModel?

В любом случае, древовидная Sql-модель - нет. Она вообще ущербная, надо сказать. Ничего, кроме чтения данных, не умеет, да и там могут быть ошибки (см. пример в аттаче к первому сообщению).

Если вы имеете в виду поля какой-то таблицы, то - нет, этого инструментарий не умеет. Это уже не простой SQL-запрос получается, а целый ALTER TABLE. В подавляющем большинстве случаев такие запросы в приложении баз данных не нужны. К простым же запросам я отношу следующие: SELECT, INSERT, UPDATE, DELETE, EXEC(UTE).

Если вы имеете в виду записи какой-то таблицы, то - нет, это не умеет SqlTreeModel, но умеет SqlQueryModel (поскольку она незначительно отличается от родителя - QSqlQueryModel). И еще это умеет хэндлер - класс, инкапсулирующий работу с SQL-запросами к конкретной таблицей базы данных (или к нескольким, как уж напишете), правда, чтобы он это умел, нужно прописать дескриптор функции _inserter().

Я ответил на ваш вопрос?


UPD

И да: без танцев с бубном в середину таблицы записи не добавишь.


Название: Re: QST: QsT SQL Tools
Отправлено: GraninAS от Декабрь 16, 2009, 02:50
Написал статью на Хабр о QST. В ней - более развернуто о многом.

http://graninas.habrahabr.ru/blog/78394/


Название: Re: QST: QsT SQL Tools
Отправлено: GraninAS от Апрель 07, 2010, 07:08
Уважаемые господа!

Я закончил QST 0.3. Теперь из категории pre-alpha она переместилась в категорию beta. Много ли сделано?

* Исправлены ошибки. Тонны ошибок. Но не все. До сих пор меня мучает та самая древовидная модель данных, - ну и шут с ней. Пользоваться можно. В версии 0.4 напишу новую, толковую модель, благо, теперь разобрался, что там к чему в системе Interview.
* Ошибки исправлялись за счет создания модульных тестов. Пока их 4 для следующих классов: SqlBatch, SqlValue, SqlGen и SqlField.
* Функции этих четырех классов теперь документированы модульными тестами. Их поведение полностью предсказуемо.
* Кое-что изменилось в интерфейсах классов. Версии pre-alpha и beta во многом не совместимы.
* Полностью написана документация. Не то чтобы очень подробная, но, мне кажется, ее вполне хватает, - вкупе с материалами, которые выкладываю в Интернете.
* Пример, выложенный для QST 0.3 pre-alpha (простая БД о торговле) является примером, как лучше не делать. С тех пор я обкатал новые техники и способы программирования при помощи QST, многое упростилось и стало понятным, менее многословным. Старый пример с SourceForge убрал, новый пример скоро будет.

Более развиваться ветка 0.3 не будет, за исключением незначительных правок и оставшихся модульных тестов. На замену устаревшему коду я пишу 0.4, в большинстве случаев не совместимую с предшественницей.

Возможности QST 0.4 в сравнении с QST 0.3
* Убрано понятие "источники данных" класса AbstractModelHandler. Оказалось, что они не нужны и сильно мешаются. Легче создать два разных экземпляра своего класса-хэндлера, чем создавать в одном классе-хэндлере несколько источников данных и потом в них путаться.
* Полный рефакторинг имен: пространств, классов, перечислений, типов и функций. За основу именования взят стиль именования Qt 4.5 и выше. Главное правило: чтобы все было логично и очевидно.
* Пересматриваются возможности DFD-языка. Планирую ввести древовидные описатели с тем, чтобы можно было создавать SQL-запросы с подзапросами.
* Расширяется сам язык DFD. Вводится поддержка некоторых других элементов SQL.
* Планируется сделать заменяемый движок компоновки SQL с тем, чтобы легко можно было написать поддержку иного диалекта нежели T-SQL. Это, разумеется, потребует многих изменений в структуре проекта.
* Упрощение. Сейчас, например, уже упрощены функции DFD-генерации (_selector(), _inserter() и т.д.). Они теперь возвращают QstBatch. Все остальное (тип и номер запроса) уже известно перед вызовом функций, зачем заставлять программиста это еще раз указывать?
* И некоторые другие интересные штуки. Например, кэширование и динамически изменяемые DFD-описатели.

Как всегда, исходники можно взять здесь:
* 0.3 beta: http://sourceforge.net/projects/qstsqltools/files/qst%200.3%20beta/QST%200.3%20beta.rar/download (http://sourceforge.net/projects/qstsqltools/files/qst%200.3%20beta/QST%200.3%20beta.rar/download)
* 0.3 pre-alpha: https://sourceforge.net/projects/qstsqltools/files/qst%200.3%20pre-alpha/QST%200.3%20pre-alpha.rar/download (https://sourceforge.net/projects/qstsqltools/files/qst%200.3%20pre-alpha/QST%200.3%20pre-alpha.rar/download)

Или слить 0.3 beta с SVN: https://qstsqltools.svn.sourceforge.net/svnroot/qstsqltools (https://qstsqltools.svn.sourceforge.net/svnroot/qstsqltools qstsqltools)

Скоро выложу какие-нибудь хорошие примеры и зачатки версии 0.4.


Название: Re: QST: QsT SQL Tools
Отправлено: GraninAS от Апрель 12, 2010, 02:47
Слегка обновил QST 0.3 beta, теперь она стала QST 0.3c beta. Что изменилось? Обновил заголовки копирайтов, а то они на прошлый год записаны. Из функционала добавил тип в файл sqlvalue.h:

typedef QMap<QString, SqlValue>      SqlValuesMap

И две функции в класс AbstractModelHandler, аналогичные value и setValue, но работают с картой значений:

AbstractModelHandler::setValuesMap(const SqlValuesMap &valMap)
SqlValuesMap AbstractModelHandler::valuesMap() const

Версию 0.3 beta оставляю тоже, 0.3c beta кладу рядом.

Дополнительно, создал специальную программу для демонстрации некоторых возможностей QST 0.3, а точнее, ту же TradeDB, переписанную с нуля с применением некоторых важных установок. В частности, очень ратую за то, чтобы вместо _inserter(), _updater() и _deleter() вызывались хранимые процедуры. Во-первых, всегда можно поменять алгоритм работы. Во-вторых, проще отследить. В-третьих, можно раздать права. В-четвертых, логика разделена, и это очень хорошо снижает ошибкоопасность.

Программа использует базу данных SQL Server 2000 (которая, кажется, цепляется и к более новым версиям сервера). Источник данных называется Trade, пользователь – user с таким же паролем. Подключение можно изменить в файле main.cpp программы-примера. Ресурсы (Fugue Icons) так же выкладываю рядом с программой. Скопировать внутреннюю папку Resources (в которой лежит непосредственно 4 объекта: Icons, all-shadowless.png, history.txt и readme.txt) в папку проекта. Выкладываю раздельно потому, что размер ресурсов довольно большой, почти 5 мб. Возможно, кому-то иконки не нужны.

Зачатки QST 0.4 на подходе.

Кстати, принимаются предложения по усовершенствованию. Или запросы каких-либо функций. В общем, любой feedback категорически приветствуется!

С уважением.

QST 0.3c beta (https://sourceforge.net/projects/qstsqltools/files/QST%200.3c%20beta/QST%200.3c%20beta.rar/download)

TradeDB 0.3 special src (https://sourceforge.net/projects/qstsqltools/files/TradeDB%200.3%20example/TradeDB%200.3%20special%20src.rar/download)

TradeDB 0.3 special Resources (https://sourceforge.net/projects/qstsqltools/files/TradeDB%200.3%20example/TradeDB%200.3%20special%20-%20Resources.rar/download)

TradeDB 0.3 special database (https://sourceforge.net/projects/qstsqltools/files/TradeDB%200.3%20example/TradeDB%200.3%20special%20-%20database.rar/download)

UPD

При попытке залить что-то из TradeDB мой файерфокс уходит в какой-то странный цикл. Что бы это могло быть? Подозреваю длинные имена файлов.

UPD2

Видимо, это SourceForge трясется в лихорадке. Перезалил пример. Скачивается все, кроме ресурсов. Подождем, пока зеркала договорятся о том, что есть "новая информация"...

UPD3

Кажется, все заработало.


Название: Re: QST: QsT SQL Tools
Отправлено: BaltikS от Апрель 12, 2010, 22:12
GraninAS, без обид, кроме тебя этим кто нить пользуется? У меня создалось впечатление что нет. Потому всё это как то не удобно... Многие конструкции SQL-языка не поддерживаются, да и проще по-моему QSqlQuery и его производные модели юзать... С вашей моделью, я так понимаю, быстрее всё равно работать не будет.  Если не прав-поправьте....может я чего то недопонял...
Цитировать
QsT Sql Tools - это набор классов (который пока трудно назвать библиотекой), облегчающий в разы программирование приложений баз данных на Qt
Насчёт в разы категорически не согласен. Потому как есть визуальные построители запросов, которые на выходе генерируют SQL запрос, вот это действительно ускоряет работу. А разрабатывать клиента БД, не зная основ БД по-моему как-то не особо получится, даже используя вашу библиотеку!


Название: Re: QST: QsT SQL Tools
Отправлено: GraninAS от Апрель 13, 2010, 02:58
Да нет, какие обиды, мне самому интересен ответ на ваш первый вопрос. Кто-то еще пользуется? Не знаю, может быть. Код скачивают, примеры скачивают, даже вчера предложили услуги по тестированию.

SQL поддерживается на самом-самом базовом уровне, верно. И поэтому уйти от знания SQL с помощью библиотеки невозможно: придется писать view'шки, хранимые процедуры. Но задача ORM-системы и не в том, чтобы заменить SQL. Вряд ли это возможно, я себе такое представить не могу. Главная задача ORM - избавиться от лапша-style-кода. Чтобы изменить одно-единственное поле в какой-нибудь таблице БД и не бегать по всем файлам проекта в поисках, где же это поле встречается. Чтобы можно было настраивать запрос перед его выполнением, и при том единообразно настраивать, чтобы смысл оставался прозрачным. Ну а раз все равно при таких требованиях запрос придется генерировать, так почему не поднять над ним абстракцию, которая бы, помимо прочего, позволяла обращаться к полям не по их индексу, а по имени?

Это извечный холивар - использовать ORM в ущерб производительности или писать "чистые" запросы в коде. Я только утверждаю, что ORM делает работу удобнее и безопаснее, хотя и несколько увеличивает локальные затраты времени на код. Судите сами: написать запрос или сгенерировать его в каком-нибудь визуальном компоненте - дело двух минут, а вот создать тот же класс-хэндлер в моей QST, - на это надо минут 7 при том, что и запрос написать придется тоже, если вы не можете его в уме составить. Однако, в конечном итоге вы напишете класс-хэндлер один раз и будете везде его использовать; "чистые" запросы придется писать постоянно.

А отладка и тестирование! Они облегчаются в разы. Смотрите: регрессия ошибок от того, что изменилась структура БД, при использовании QST минимальна и сосредоточена всего лишь в одном файле; тогда как "чистые" запросы могут быть разбросаны повсеместно. И даже если не разбросаны, в них будет нечто вроде:

\\1.cpp
QString query = QString("SELECT ID, Name, Surname WHERE Age > " + QString::number(ageParameter));

Но это очень простой запрос. А что если вам понадобится не один параметр в секцию WHERE, а десять? Или в одном месте программы - один параметр, а в другом - другой? Количество запросов возрастает:

\\2.cpp
QString query = QString("SELECT ID, Name, Surname WHERE Age > " + QString::number(ageParameter)) + " AND Name LIKE %" + nameParameter + "%");

\\3.cpp
QString query = QString("SELECT ID, Name, Surname WHERE Age <= 10 AND SurName LIKE %" + nameParameter + "%" AND Address LIKE %'" + addressParameter.arg("ул. Лесная").arg(25).arg(6) + "%'");

Сколько здесь допущено ошибок, как вы думаете? Не меньше шести, есть и синтаксические. Отладка такого кода становится кошмаром. Могу вас уверить, QST от этого всего избавляет сразу и навсегда. И, например, чтобы посмотреть, какой там запрос выполнился, достаточно взглянуть на окно Applicaton Output в Qt Creator'е: там все запросы выводятся, уже чистые SQL-запросы, которые можно скопировать и протестировать отдельно. Я тестирую, например, с помощью Query Analyser'а. Он мне сразу же говорит, что у меня нет поля Surname, - я смотрю, какое есть, - и изменяю его в одном месте. А сколько телодвижений сделаете вы, прежде чем выясните причину ошибки? В этом и есть разница между "чистыми" SQL-запросами и ORM-обертками, в этом и есть удобство. Раз убедившись в этом, уже вряд ли будешь думать иначе.


Название: Re: QST: QsT SQL Tools
Отправлено: BaltikS от Апрель 13, 2010, 09:00
Отладка такого кода становится кошмаром. Могу вас уверить, QST от этого всего избавляет сразу и навсегда. И, например, чтобы посмотреть, какой там запрос выполнился, достаточно взглянуть на окно Applicaton Output в Qt Creator'е: там все запросы выводятся, уже чистые SQL-запросы, которые можно скопировать и протестировать отдельно. Я тестирую, например, с помощью Query Analyser'а. Он мне сразу же говорит, что у меня нет поля Surname, - я смотрю, какое есть, - и изменяю его в одном месте. А сколько телодвижений сделаете вы, прежде чем выясните причину ошибки? В этом и есть разница между "чистыми" SQL-запросами и ORM-обертками, в этом и есть удобство. Раз убедившись в этом, уже вряд ли будешь думать иначе.
всё таки позволю с вами не согласится...
1) если однотипный запрос используется много раз, то используется view. И если меняется таблица, меняется и view и мне не нужно править код.
2) По поводу поиска ошибок в коде. Это далеко не кошмар, есть опять таки визуальные построители запросов, которые избавляют пользователя от отладки запросов. А если необходимо всё таки отлаживаться имеется мощный отладчик.  И не приходится сравнивать того что выводит отладчик с тем, что должно быть.
3)
Цитировать
позволяла обращаться к полям не по их индексу, а по имени
есть такой метод QSqlRecord::field ( const QString & name ) const, который позволяет обращаться по имени.
4) Мой вывод таков: чтобы использовать библиотеку, нужно
Цитировать
поэтому уйти от знания SQL с помощью библиотеки невозможно: придется писать view'шки, хранимые процедуры
, что займёт время. К тому же
Цитировать
использовать ORM в ущерб производительности
как то тоже не здорово. В итоге, для себя я уяснил, что зачем это использовать, если время займёт на разработку больше? Это как писать приложения Qt на QtScript, вроде бы просто, но ....

GraninAS, спасибо за подробное разъяснение :)


Название: Re: QST: QsT SQL Tools
Отправлено: Marat(Qt) от Апрель 14, 2010, 12:46
Итак GraninAS привел свое решение, BaltikS свое. На мой взгляд, оба правы, но не во всем.
Лапша, которую привел GraninAS - не лучший метод написания запросов стандартными средствами Qt, есть bindValue, который упрощает код (хотя я, в основном, использую QString::arg). Но и bindValue не так хорош как идея QST. Как проверить запрос в самом Qt, не используя ничего со стороны? QSqlQuery::lastError - не лучший вариант (опять же IMHO), ибо результат виден только во время выполнения программы. Но как говорит BaltikS - вполне можно использовать сторонние утилиты. Только я вот терпеть не могу необходимость использования чего-то стороннего(если это не плагин для QtCreator). Т.е. QST - хорошая идея.

С другой стороны, расхвален он с большим авансом. Сейчас он написан настолько, насколько он нужен топикстартеру. Настолько универсально и настолько удобно. Он знает что это, знает как оно работает, как им пользоваться и наслаждается отсутствием лапши. Но я не буду использовать QST потому что:
1) синтаксис SQL я знаю лучше чем суть QST
2) QST не шибко универсален
3) самое главное: стиль работы с QST далек от стиля работы в Qt. Где вы видели в Qt имена подобные этим: fv_visible, fr_none, fo_like, fb_right, fp_where? Да это коротко и для автора очень удобно. Но не для меня, я не вижу логики: где эти штуки объявлены? почему где-то префикс fr, а где-то fo? зачем символ '_' в именах?

До современного стиля написания кода Qt рос довольно долго. enum'ы типа Qt::Ascending и им подобные в большинстве своем появились только в Qt4 (могу жутко ошибаться, статью читал давно, если что поправьте). Думаю, если QST не заглохнет, то может дорасти до библиотеки, бесшовно сливающейся с Qt. Время есть, а я пока с лапшой помучаюсь.


Название: Re: QST: QsT SQL Tools
Отправлено: GraninAS от Апрель 15, 2010, 04:24
Благодарю за отзывы, господа коллеги.

Мне не хотелось  бы, чтобы тема утонула в холиваре ORM vs SQL, тем паче, что позиция BaltikS'а мне ясна, аргументы не изменились, и смысла повторяться нет. Marat(Qt) прав, что оба подхода имеют право на существование. Каждый решает для себя, что ему нужно. Так же Marat(Qt) прав, что QST сейчас в зачаточном состоянии. С другой стороны, какая библиотека могла бы развиться, минуя данный этап? Я не считаю, что расхвалил библиотеку авансом, - я показал то, что она умеет и сказал, чего не умеет, прекрасно осознавая, что версия 0.3 весьма кривая даже в системе именования. Несколькими сообщениями ранее я рассказал, что в 0.4 версии это все пересматривается, посему стиль работы с QST будет постепенно приближаться к стилю работы в Qt. В частности, первое, что я сделал для этого, - переименовал все enum'ы (и я уже об этом упоминал выше). Вот примеры:

>   Functor                   CompareFunctor
>   fo_equal                  FunctorEqual
>   fb_left                   BracesLeft
>   SqlQueryTypes             QueryType
>   sql_select                QuerySelect
>   SqlFieldVisibility        FieldVisibility
>   fv_visible                FieldVisible
>   SqlFieldPurpose           FieldPurpose
>   fp_select                 PurposeSelect
>   fp_all_valued             PurposeAllValued_Mask
>   SqlFieldRoles             FieldRole
>   fr_id                     RolePrimaryKey
>   fr_parent                 RoleParentKey

и т.д. Как видим, главный пункт уважаемого Marat(Qt)'а и меня волновал давно...

Я выложил версию QST 0.4.1 pre-alpha (https://sourceforge.net/projects/qstsqltools/files/QST%200.4%20pre-alpha/QST%200.4.1%20pre-alpha.rar/download).

Основные изменения.
- Рефакторинг имен.
- define'ы глобальных параметров (таких как SQL_VALUE_SET_DEFAULT_FUNCTORS) переименованы и перенесены в файл "qstglobal.h".
- QstAbstractModelHandler: устранено понятие источника данных. Теперь не нужно писать имя источника данных:
Код:
_productsHandler.reload(PRODUCTS, &_productsModel);
_productsHandler.setTableView(ui->tv_Products);
_productsHandler.keyValueOfView()
- Создан класс QstAbstractItemNameExtractor, предназначенный для извлечения имени объекта в конструкциях вида "count([ID])"; "field AS FieldName"; "max(field) as [count]", "tableName AS alias". Класс задает интерфейс для создания собственных классов, реализующих извлечение имени.
- Создан класс QstDefaultItemNameExtractor, так же создан модульный тест для него - ut_QstDefaultItemNameExtractor.
- Класс QstBatch теперь позволяет загрузить любой класс типа QstAbstractItemNameExtractor. Если в методах указать, что требуется извлечение имени, то будет задействован этот класс. По умолчанию загружается QstDefaultItemNameExtractor.

Почти полный список можно посмотреть в файле "qst\0.3 beta to 0.4 pre-alpha Changes.txt".

На данный момент разрабатываю иерархические DFD, чтобы можно было создавать сложные вложенные SQL-запросы, а так же JOIN'ы. В планах еще много чего, так что пока к "заглоханию" особых предпосылок нет.

С уважением.

P.S. Рад любым дельным предложениям.


Название: Re: QST: QsT SQL Tools
Отправлено: immerrr от Май 10, 2010, 15:26
с тех самых пор, как мне пришлось подержать в руках python django (фреймворк для написания веб-приложений и сайтов) и его ORM, я люто-бешено хочу заиметь такое "для души", т.е. в Qt. настолько хочу, что завидев автора, который, вроде, хочет что-то стоящее получить из своего творения, даже зарегался :)

причем, отдавая себе отчет в том, что в производительности я в лучшем случае не выиграю, то по крайней мере получить преимущество в
  • синтаксисе
  • упрощении поддержки кода
  • уменьшении жесткости связей с БД
  • использовании qt properties
  • ... ну и всякого другого по мелочи


workflow моего "идеального орм" выглядел бы так:
1. подключил заголовок;
2. на метаязыке описал объекты, которые предполагается хранить в бд и, возможно, связи между ними;
3. написал бы метазапросы, которые бы, в принципе, были понятны человеку знакомому с SQL, но незнакомому с C++; что-нибудь вида,
Код:
  List<MyObject> list = MyObject::select_all("as o1").join(OtherObject::query("as o2"))
    .where("o1.somefield = ", myval);
или
Код:
  List<ID> list = MyObject::ids().where("anotherfield is NULL");
или даже
Код:
  QString q = MyObject::queryText("as o1").join(ThirdObject::query("as third"))
    .where("third.third_field IN ", array)
    .deleteFrom("o1");
Ну и само собой, в качестве бонусов, были бы неплохи замечательные нотации вида
Код:
  MyObject().setFieldOne(valOne).setFieldTwo(valTwo).store();

  MyObject object = MyObject::byId(some_id);


Название: Re: QST: QsT SQL Tools
Отправлено: GraninAS от Май 11, 2010, 08:09
Уважаемый immerrr!

Ценю ваше внимание и приветствую ваш интерес к этой теме.

Очень хорошо, что вы написали "ORM вашей мечты", это поможет мне в направлении развития. На данный момент библиотека малоразвита и вещи, которые вы привели, маячат разве что на горизонте. Недавно я нашел еще один проект, содержащий в себе ORM. Развит он гораздо сильнее, чем мой, даром что появился недавно, - посмотрите, может, вам подойдет: QxOrm (http://sourceforge.net/projects/qxorm/). Было бы очень интересно послушать ваше сравнение QxOrm и Django. Вот тема, где я несколько озадачен "конкурентами": http://www.prog.org.ru/topic_13249_0.html.

Добро пожаловать! ;)


Название: Re: QST: QsT SQL Tools
Отправлено: GraninAS от Август 19, 2010, 10:34
Я обновил проект на SourceForge.net. Точнее, залил обновленную QST 0.4.2a beta (http://sourceforge.net/projects/qstsqltools/files/QST%200.4%20beta/QST%200.4.2a%20beta.rar/download). Будет ли версия 0.4 доведена до релиза? Скорее да, чем нет. Бета-версия уже вполне надежная, никаких особых глюков там нет. Но я хочу добавить еще несколько интересных вещей, которых в 0.4a beta нет, но они есть в моих проектах.

SVN обновлю чуть позже.

(Эта версия была готова уже несколько месяцев назад, но я программист был бедный, без толкового Интернета. К счастью, и моим мучениям пришел конец. Ныне у меня есть безлимитка.)

Да, кстати. Сейчас один проект пишется на Qt+PostgreSQL, соответственно, я тестирую библиотеку в работе с этим сервером. Работает, - но работает до тех пор, пока не встретятся различия между простыми запросами в диалектах T-SQL и pgSQL.

Еще я сделал программу-пример для версии QST 0.4 - TradeDB 0.4 example, аналогичный пример есть на сервере для версии QST 0.3. СУБД - MS SQL Server 2000 (или выше). Для успешной компиляции ресурсы надо скопировать в папку с исходниками. Для успешного подключения - настроить источник данных ODBC с именем Trade, который указывает на базу данных. Еще нужно в самой базе данных пересоздать пользователей. Точно не помню, но там, кажется, пользователь и пароль "user". В любом случае, все эти настройки можно поменять в main.cpp.

TradeDB example src (http://sourceforge.net/projects/qstsqltools/files/TradeDB%200.4%20example/TradeDB%200.4.2%20special%20src.rar/download)
TradeDB example - database (http://sourceforge.net/projects/qstsqltools/files/TradeDB%200.4%20example/TradeDB%200.4.2%20special%20-%20database.rar/download)
TradeDB 0.4 example - Resources (http://sourceforge.net/projects/qstsqltools/files/TradeDB%200.4%20example/TradeDB%200.4.2%20special%20-%20Resources.rar/download)


Какие изменения в бете по сравнению с альфой? Ну, их много.

0.4 pre-alpha to 0.4.2a beta Changes

- Документация кода обновлена.
- Добавлен класс QstIf.
- Изменены имена типов, перечислений:
* PurposeAllValued_Mask на PurposeValued_Mask
* QstFieldsVector на QstFieldVector
* QstValuesVector на QstValueVector
- Из модуля qstglobal.h убрана строка #include <QDebug>.
- Добавлен параметр QST_VALUE_NULL_SUBSTITUTE_BY_DEFAULT, установлен в #undefined.
- У перечислений уточнены числовые значения.
- Добавлено перечисление MatchPolicy.
- Добавлено перечисление QueryClause. (В будущих версиях перечисления FieldPurpose и QueryClause будут пересмотрены.)
- Добавлены типы QueryClauses, QueryClauseMap.
- Пересмотрены пространства имен.
- Удалена функция QstModelDescriptor::listView().

-= QstAbstractModelHandler =-

- У класса появился флаг _isLoaded, указывающий, была ли загружена модель.
- Косметические исправления внутри функций.
- Для генерирующих функий (_selector() и др.), а так же для функций вызова (Insert, Update и др.) у параметров queryNumber убрано значение по умолчанию. Поменяны местами 3 и 4 параметры.
- У функции _selector() убран параметр ModelType.

- Убраны функции:
* reload(QstPlainQueryModel*, QSqlDatabase &)
* reload(QstTreeQueryModel*, QSqlDatabase &)
* rowCount()
* DeleteCurrent(), SelectQuery(), InsertQuery(), UpdateQuery(), DeleteQuery(), ExecQuery()

- Добавлены функции:
* reload(QSqlDatabase &)
* isLoaded()
* setValuesMap()
* valuesMap()
* generateQuery()
* batch()

-= QstBatch =-

- Исправлена ошибка со строкой #include при подключении qstdefaultitemnameextractor.h и qstrolevisibility.h.
- Созданы классы QstFieldIf и QstSourceIf на основе QstIf.

Добавлены функции и операторы:
* addSource(QstSourceIf)
* addField(QstFieldIf)
* operator<<(QstSourceIf)
* operator<<(QstFieldIf)

-= QstDBConnection =-
- Добавлена возможность устанавливать порт. Для этого добавлены соответствующие варианты функций подключения и тестирования, а так же функция setPort().
- Конструктор класса теперь может принимать название драйвера.
- Название драйвера по умолчанию вынесено в константу QST_DEFAULT_DATABASE_DRIVER.

-= QstField =-
- Изменены параметры по умолчанию у некоторых конструкторов. (Ширина колонки, видимость поля и др.).
- Добавлен тип QstFieldNamesList (В последующих версиях имя может быть изменено на QstFieldNameList).

-= QstQueryComposer =-
- Исправлены ошибки, связаннае с генерацией секции WHERE и EXEC.
- Добавлена функция queryParts().
- Убраны классы EIllegalBetweenFoUsing и EInvalidSelectClause.


Название: Re: QST: QsT SQL Tools
Отправлено: GraninAS от Сентябрь 08, 2010, 04:51
Приветствую всех!
Я выпустил первый Release Candidate для свой библиотеки, а именно - QST 0.4.2a rc (http://sourceforge.net/projects/qstsqltools/files/QST%200.4%20rc/QST%200.4.2a%20rc.rar/download). SVN тоже обновил.

0.4.2a beta to 0.4.2a rc Changes

- Добавлен возврат по ошибке из функции QstAbstractModelHandler::selectToMap(), а так же вывод QSqlError в отладочную консоль.
- Добавлена функция ModelType QstAbstractModelHandler::modelType().
- Добавлен класс QstConnectionSettings - настройки подключения.
- Добавлена функция QSqlError QstTreeQueryModel::lastError().
- Обновлена документация.

-= QstDBConnection =-
- Класс переработан.
- Настрйки подключения можно передавать в QstDBConnection внутри QstConnectionSettings.
- Добавлена функция QSqlError QstDBConnection::lastError().
- Добавлена функция QstConnectionSettings QstDBConnection::connectionSettings(const QString &connectionName).

Это были последние изменения функциональности для QST 0.4. Перед релизом я хочу написать еще несколько модульных тестов, которые, возможно, помогут найти какие-нибудь ошибки. Таким образом, версия 0.4 близится к завершению.


Название: Re: QST: QsT SQL Tools
Отправлено: GraninAS от Сентябрь 27, 2010, 10:21
Добрый день, уважаемые!

Спешу сообщить, что сегодня у QST знаменательная дата: первый релиз, QST 0.4.2a release (https://sourceforge.net/projects/qstsqltools/files/QST%200.4%20release/QST%200.4.2a%20release.rar/download). Можно сказать, день рождения (поздравления принимаются!). Я с легким сердцем отпускаю QST 0.4 в массы и теперь могу работать над версией 0.5. Кстати же, в следующую версию я добавил уже несколько полезных вещей. В качестве подарка заинтересованным лицам выкладываю QST 0.5.1 pre-alpha (https://sourceforge.net/projects/qstsqltools/files/QST%200.5/QST%200.5.1%20pre-alpha.rar/download). Важно: в ней генерируется диалект PostgreSQL, и запросы еще тестируются. Ошибки более чем возможны.

P.S. SVN обновлю в ближайшие нескольких дней.

Список изменений в 0.4.2a release сравнении с 0.4.2a rc.

- Улучшена стабильность release-сборки внутри класса QstAbstractModelHandler.
- Функции pModel() классов QstAbstractModelHandler и QstModelDescriptor переименованы в model().
- В QstModelDescriptor убран код, связанный с QListView - он нигде не использовался, поскольку QListView интерпретируется как QAbstractItemView наравне с QTableView и QTreeView.
- Функция QstQueryComposer::queryParts() теперь возвращает simplified() строки внутри QueryClauseMap.

- Исправлена ошибка в документации по классу QstQueryGenerator.
- Добавлен модульный тест ut_QstConnectionSettings.
- Обновлен модульный тест ut_QstQueryGenerator.
- Незначительно обновлена документация.

Список изменений 0.5.1 pre-alpha в сравнении с 0.4.2a release.

-= QstGlobal =-
- Добавлен элемент перечисления NullType::NotNull.
- Почти все элементы перечисления CompareFunctor были переименованы.
- Добавлены битовые функторы BitwiseOr, BitwiseAnd, BitwiseXor, BitwiseNot, BitwiseShiftLeft, BitwiseShiftRight.

-= Общее =-
- Добавлен QstLimit, добавлена генерация секции LIMIT.
- Из класса QstQueryComposer выведен класс _StringTemplate, переименован в QstStringTemplate и помещен в QstSpecial.
- Генерация SQL частично адаптирована для PostgreSQL (изменения в QstQueryComposer, QstQueryGenerator, querygenconstants.h).
- Обновлена документация.
- Добавлена генерация побитовых операций and, or, xor, lshift, rshift в секции WHERE.

-= QstAbstractModelHandler =-
- Добавлены функции viewFieldValue(), comboBoxFieldValue(), возвращающие данные поля из модели, привязанной к view или comboBox.
- Улучшена стабильность release-версии путем возврата из процедур, если параметры невалидны.
- Изменена логика функции clear() в сторону увеличения стабильности.
- Добавлены функции setViewCurrentRow(), setComboBoxCurrentRow() (тестируются).
- Добавлены функции viewFieldsValueMap(), comboBoxFieldsValueMap().
- Функция pModel() переименована в model().
- Функция value() отслеживает значение NullType.
- Добавлена функция setVariantMap().

-= QstPlainQueryModel =-
- Класс теперь - не переопределение QSqlQueryModel, а наследник.
- Прописана функция match() с ограниченным функционалом.

-= QstConnectionSettings =-
- Добавлена функция isDatabaseSettingsValid().

-= QstDBConnection =-
- Переписана логика создания подключений. Теперь экземпляр QSqlDatabase не хранится.
- Многие функции класса подверглись рефакторингу.
- Добавлена функция closeAll().
- Добавлены функции removeConnection() и removeAllConnections().
- Убраны функции rdb() и pdb().

-= QstModelDescriptor =-
- Функция pModel() переименована в model().

-= QstTreeQueryItem =-
- Функция setQuery(QSqlQuery) перенесена в секцию private.
- Добавлена заглушка на функцию match().


Название: Re: QST: QsT SQL Tools
Отправлено: mapron от Ноябрь 06, 2010, 14:16
Здравствуйте, уважаемый Александр!
Прежде всего, хочу сказать что Вы делаете правильное и полезное дело. Пускай тут и пишут, что кроме Вас этого никому не надо, но я хочу сказать что это не так.
Просто большая часть людей просто берет и пользуется, и не говорит даже спасибо - менталитет такой.
Я последние два дня активно изучаю Вашу разработку, и хочу применить ее в образовательном проекте - ACM Server для нашего института (да я знаю что этих серверов - как грязи, но не монструозных и с понятным кодом ну и тем более на Qt - навряд ли ;) )
Поэтому желаю Вам дальнейших успехов и обещаю присылать баги и пожелания если таковые будут:)


Название: Re: QST: QsT SQL Tools
Отправлено: GraninAS от Ноябрь 08, 2010, 03:31
Приветствую и вас.

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

Большое спасибо!

Возможно, вам будет интересно узнать, что моя ORM для Qt - не единственная. Например, наибольшими возможностями из всех существующих обладает QxORM (http://www.qxorm.com/qxorm_en/home.html). Она очень специфическая, впрочем, как и любой инструмент. На главной странице этого продукта можно найти список других ORM, большая часть которых либо не для Qt, либо в самом зародыше.


Название: Re: QST: QsT SQL Tools
Отправлено: mapron от Ноябрь 08, 2010, 04:39
Что она не единственная, я знаю - сюда попал с Вашего обзора на Хабре (хабр для меня рид-онли, что нисколько не огорчает).
QxORM я посмотрел, код ппц просто :)
Глобальный недостаток всех этих ORM - удаление от принципа KISS. Чем, кстати, страдает и Ваша разработка.
Я поиспользовав немного QST, понял, что очень много времени занимает ковыряние в исходниках для написания простейших запросов. Для меня это далеко для идеала.
Я вообще работаю веб-разработчиком и мне по душе, как сделана работа с моделями в Zend_Db и CakePHP-Model. Во второй, кстати, полноценная ORM.
Так вот я сейчас пишу подобную по духу систему:
{
delet(array("last_hit<?",dt.toString("yyyy-MM-dd hh:mm:ss")));
 insert(array("sid", sid, "uid", 0, "last_hit", QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss")));

ModelSession sess;
sess.update(sess.array("uid",uid),sess.array("sid=?",req["sid"]));
QVariantHash mesess=sess.fetchRow(sess.array("sid",req["sid"]));
}

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


Название: Re: QST: QsT SQL Tools
Отправлено: mapron от Ноябрь 11, 2010, 17:29
 на стиль использования системы меня натолкнули популярные фреймворки для PHP Zend_Db и cakePHP .
Любой кто знаком с их принципом, без проблем освоит и мою систему
в общем и целом мой ORM представляет собой два класса (даже полтора).
 Первый - это модель. Второй - это запись или объект
запись является наследником от QVariant и просто предоставляет более удобную работу с многомерными массивами и хеш-массивами
 а вот модель предоставляет собой обертку над всеми нужными функциями: insert, update, select и delete
select aka fetchAll & fetchRow  работает в двух режимах. В одном он получает sql-запрос с плейсхолдерами и вторым аргументам биндинг на плейсхолдеры. все прозаично. Самый низкоуровневый вариант
во втором режиме он получает в качестве аргументов а) where - хеш массив с плейсхолдерами ? - они заменяются на :-плейсхолдеры потом. б) order, limit компоненты - это пока в разработке. Я доделывают возможность по мере надобности в проекте
 кроме того, работу со связями (join-ы и отображение в зависимые элементы) хочется сделать подобным образом как в cakePHP. Просто заполняются нужные поля в конструкторе - и теперь в запросе findAll/Row в одном из полей результата будет содержаться зависимые объекты.
 в чем плюс моей системы. Программисту не надо запоминать кучу различных констант которые управляют его запросом
они либо пишет навороченные запросы руками и просто забивает их данными через биндинг, передавая второй аргумент , либо работает опять-таки с хеш-массивами (QVariantMap аналог) для условий и данных
т.е. ему нужно изучить ОДИН элемент, если он до этого работал уже с Qt и Sql и знает что такое update/insert/delete
Var: http://pastebin.com/4RBvXurA
примеры использования: http://pastebin.com/D2BBezkQ
Саму модель не выкладываю, ибо сыро, бажно и стыдно. Нет комментов и могут быть критические баги :)


Название: Re: QST: QsT SQL Tools
Отправлено: GraninAS от Ноябрь 12, 2010, 03:04
Вы верно говорите об избыточности семантики многих ORM. И в большей части создатели стремятся уподобить код маперов SQL-языку, - по этому же пути идете и вы. Это интуитивный путь, его преимущество - в легкости восприятия. Не исключено, что в QST когда-нибудь так же появится что-то подобное. С другой стороны, в языках с динамической типизацией (PHP - самый яркий пример) сделать это проще, чем в С++, отчего для PHP существует, по крайней мере, две популярные и очень мощные ORM-системы. Будьте готовы к тому, что столкнетесь с трудностями синтаксического характера, когда будете достраивать свою ORM по аналогии с какой-нибудь другой навороченной ORM. Например, один из программистов Qt (если не ошибаюсь) хочет создать QDjango, - название этой ORM говорит само за себя. Благо, что С++ очень гибкий язык, и эту его гибкость в полной мере используют в библиотеке Qt; в противном случае создать свою Django было бы непросто. Могу еще сказать, что QST исповедует несколько иную философию. Когда все прочие проекты - это проекты по созданию ORM, то QST - это проект для создания библиотеки, облегчающей программирование БД. Отсюда и расхождения в подходах. Впрочем, пути примирения этих подходов есть, реальны и рассматриваются.

Ну а вам желаю успехов.


Название: Re: QST: QsT SQL Tools
Отправлено: vlad-mal от Ноябрь 12, 2010, 07:46
Как-то глубоко проникал в данную область, проект тянул (не на С++, на Delphi с использованием BoldForDelphi).
В какой-то момент понял, что занимаюсь не разработкой, а борьбой с ограничениями модели.
Игрался с DB4O (чисто ООСУБД для java/.net, не ОРМ) - то же самое. Красота в простых примерах и ад при усложнении бизнес-модели.

ИМХО, применение простых организационные решений вроде разделения кода доступа к СУБД и бизнес-логики по отдельным модулям плюс написание тестов дадут больше, чем использование костылей вроде ORM.

Впрочем, вещь увлекательная и развивающая, удачи и удовольствия.


Название: Проблемы моделей и борьба с вертряными мельницами.
Отправлено: mapron от Ноябрь 13, 2010, 13:15
В какой-то момент понял, что занимаюсь не разработкой, а борьбой с ограничениями модели.
я полностью согласен. В фреймворке CakePHP мне не нравится то же самое, поэтому я больше придерживаюсь концепции Zend. фреймворк должен помогать ускорять РУТИНУ, а не навязывать свой стиль. Я должен всегда иметь возможность все сделать вручную, а методы фреймворка использовать лишь для облегчения. Я об этом и писал выше.
Я могу написать Var rows=model.fetchAll("большой и огромный составленный вручную запрос", биндинг);


Название: Re: QST: QsT SQL Tools
Отправлено: mapron от Ноябрь 13, 2010, 13:21
ИМХО, применение простых организационные решений вроде разделения кода доступа к СУБД и бизнес-логики по отдельным модулям плюс написание тестов дадут больше, чем использование костылей вроде ORM.
Тут вроде никто и не говорил, что этого делать не нужно  и что ORM - панацея. Я еще раз повторюсь, что ORM нужна для рутинных задач вроде стандартных операций или извлечения зависимых объектов и заполнение в удобной форме.

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

Я бы назвал существенным минусом ORM - при генерации реально сложных запросов и моделей нагрузка далека от оптимальной: извлечь объекты А; извлечь объекты Б, зависимые от А; извлечь объекты В, зависимые от Б; ну и т.п.
У меня есть идея как сделать "правильную" генерацию таких запросов (в данном примере 3 SQL-запроса) и я попробую ее воплотить :)


Название: Re: QST: QsT SQL Tools
Отправлено: mapron от Ноябрь 13, 2010, 14:20
Будьте готовы к тому, что столкнетесь с трудностями синтаксического характера, когда будете достраивать свою ORM по аналогии с какой-нибудь другой навороченной ORM. Например, один из программистов Qt (если не ошибаюсь) хочет создать QDjango, ...
Вы меня так и не поняли до сих пор... я не хочу НАВОРОЧЕННУЮ ORM. я хочу ORM с минмумом возможностей, облегчающих написание кода, которая была бы МАКСИМУМ очевидна (в идеале - разобраться в которой 5-10 минут, почитав примеры). Заставлять пользователя курить маны для того чтобы городить кучу инициализаций с шаблонами и константами - это будет очень небольшой процент людей, да и то только если ORM будет предоставлять УНИКАЛЬНЫЕ возможности.

Надеюсь на Ваше понимание и жду дальнейшего обсуждения.


Название: Re: QST: QsT SQL Tools
Отправлено: vlad-mal от Ноябрь 13, 2010, 17:38
...
Судя по тому что Вы называете ORM костылем у Вас либо был неудачный опыт в этом деле и Вы его неправильно готовили, либо Вы просто не имеете большого опыта в этой теме.
...
Определенно, какие-то причины были. :)


Название: Re: QST: QsT SQL Tools
Отправлено: mapron от Ноябрь 13, 2010, 21:44
Итак, товарищи, свершилось! я закончил работу по реализации связи между моделями. Пока что поддерживается только HasMany, да и то только первого уровня, но сделано таким образом что доработать все остальное не составит проблем.
Как это работает?
1. Создаем реестр моделей в статичной функции init класса Model:
Код
C++ (Qt)
void Model::init(QString connection)
{
   collection.clear();
   collection.insert("user", new ModelUser(connection)); // пользователь
   collection.insert("session", new ModelSession(connection)); // у пользователя есть его сессии
   collection.insert("submission",new  ModelSubmission(connection)); // и его "решения"
}
 
Минус здесь в том, что используются указатели :(. Это теоретически возможные проблемы с памятью и тп.

2. Создаем нужную модель и связываем ее с другими
Код
C++ (Qt)
ModelUser::ModelUser(QString connection):Model(connection)
{
 useTable="users";
 addLink(LT_HasMany,"session", "id","uid");  // связываем модели здесь. Минус - использование константы
 addLink(LT_HasMany,"submission", "id","uid");
}
 
я уже подумываю об использовании различных методов для различных связей. т.е. addLinkHasMany и тп

3. Используем метод модели для получения зависимых данных (пока это тот же fetchAll)
Код
C++ (Qt)
ModelUser u;
Var res=u.fetchAll(Var(),1); // прототип Var Model::fetchAll(Var where,int depth)
 

На выходе получаем примерно такой объект (пользователь в данном случае один, но с многими тоже работает) (преобразован в JSON для наглядности)
Код
Javascript
[ {
"_session" : [ {
"id" : "1",
"last_hit" : "2010-11-14 01:46:43",
"sid" : "93968137971e79d5b7b0c9451ecb8bb2",
"uid" : "1"
}, {
"id" : "2",
"last_hit" : "2010-11-14 01:47:17",
"sid" : "77e70c5045398b09204af9e9d29002e9",
"uid" : "1"
} ],
"_submission" : [ {
"id" : "1",
"lang_id" : "1",
"message" : "undefined reference to `main`",
"send" : "2010-11-11 23:43:41",
"status" : "2",
"task_id" : "1",
"txt" : "#include <iostream>\nint main (int argc, char* argv [])\n{\nstd::cout << \"Hello, world!\" << std::endl;\nreturn 0;\n}",
"uid" : "1"
} ],
"famil" : "Фамилия",
"id" : "1",
"ima" : "Имя",
"login" : "user",
"otch" : "Отчество",
"passhash" : "d8578edf8458ce06fbc5bb76a58c5ca4",
"rights" : "1"
} ];
 

Что думаете, товарищи? Давайте вместе придумаем "идеальную" в использовании систему. Вы можете предложить удобный для вас синтаксис выполнения различных действий? В идеале крое автокоплита для написания кода больше ничего не нужно.


Название: Re: QST: QsT SQL Tools
Отправлено: GraninAS от Ноябрь 15, 2010, 11:31
Я думаю, что это правильно - много разных разработок с разной философией. Каждый выбирает себе по вкусу и потребностям.

Я так же не согласен с мнением, что ORM - это костыли. Это подход, инструмент. Все спорщики ORM vs. PlainSQL прекрасно это понимают, но холивары всё равно вспыхивают (http://stackoverflow.com/questions/494816/using-an-orm-or-plain-sql) тут (http://forums.whirlpool.net.au/archive/1170724) и там (http://www.cforcoding.com/2009/05/orm-or-sql.html). Подозреваю, что здесь вот-вот тоже готова будет завязаться драка. Я бы не хотел. Не в этой теме. Заведите другую тему, и я тоже присоединюсь к дискуссии, если позволит время.

Уважаемому mapron'у желаю всяческих успехов.

Пару вопросов я задам.

1. Вы говорите, что функция void Model::init(QString connection) статическая. Вероятно, она должна обращаться к статическому члену collection. Что это дает?

2. Передается некая строка connection. Что происходит с ней дальше? Вообще, как происходит подсоединение к базе данных и извлечение самих данных?


Название: Re: QST: QsT SQL Tools
Отправлено: mapron от Ноябрь 15, 2010, 14:06
Подозреваю, что здесь вот-вот тоже готова будет завязаться драка. Я бы не хотел. Не в этой теме.
Да такого вроде не было, мы пришли к общему мнению: vlad-mal, признался что у него был неудачный опыт. В чем сочувствую ему.
Так можно и отверткой себя в глаз нечаянно ткнуть и холиварить потом "отвертки ацтой!"

Пару вопросов я задам.
1. Вы говорите, что функция void Model::init(QString connection) статическая. Вероятно, она должна обращаться к статическому члену collection. Что это дает?
collection - это статический член, где содержатся все объекты всех используемых моделей. в QxORM тоже подобная штука есть, как выяснилась, только заполняется она с помощью создания шаблонных классов вроде.
Зачем статичная? чтобы не создавать объекты моделей при циклических/рекурсивных вызовах внутри ORM.
Зачем хранить их в списке? чтобы иметь соответствие имя модели=> объект.

2. Передается некая строка connection. Что происходит с ней дальше? Вообще, как происходит подсоединение к базе данных и извлечение самих данных?

Подсоединение к базе остается за рамками ORM. это DAL все же. поэтому акцент чисто на модель. Без отображения и т.п.
Вот пример кода соединения с базой данных
Код
C++ (Qt)
QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE",QLatin1String( QSqlDatabase::defaultConnection ));
db.setDatabaseName("db.sqlite");
   QSqlDatabase db1 = QSqlDatabase::addDatabase("QSQLITE","thread1");
   db1.setDatabaseName("db.sqlite");
   QSqlDatabase db2 = QSqlDatabase::addDatabase("QSQLITE","thread2");
   db2.setDatabaseName("db.sqlite");
 
Видно, конечно, что не правильно и не аккуратно. Здесь я использую встроенные возможность qt без оберток. все же баз данных и подключений в моем проекте не так уж и много.
Запуск статичного метода (при старте веб-сервера у меня) - это тоже уже детали.
Код:
Model::init();
То же самое при инициализации потока:
Код:
Model::init("thread1");
Это делать необязательно, только для работы именно с ORM-возможностями.

Извлечение самих данных происходит при вызове методов объекта
вот список публичных методов модели:
Код
C++ (Qt)
   // извлечение строки
   Var fetchRow(QString querytext, Var bind);
   Var fetchRow(Var where);
   Var fetchById(int id);
   Var fetchById(QString id);
 
   // извлечение набора строк
   Var fetchAll(Var where,QString order="",int limit=0,int offset=0, int depth=0);
   Var fetchAll(Var where,int depth);
   Var fetchAll(QString querytext, Var bind);
 
   // вставка записи
   int insert(Var record);
   // обновление записи
   int update(Var record,int id);
   int update(Var record,Var where);
   // удаление
   int delet(int id);
   int delet(Var where);
 
   void truncate();// очистка
   // добавление связи с другими моделями
   void addLink(LinkingType link_type, QString dest_model, QString source_key, QString dest_key);
 


PS. offtopic. вот интересно, пост Александра датирован сегодня 11:31, а мой ответ на него тоже сегодня 02:32. Интересные дела.


Название: Re: QST: QsT SQL Tools
Отправлено: mapron от Ноябрь 16, 2010, 14:11
Хм, я понял только что серьезную ошибку: потоко-небезопасность моего решения... Model::init() какой-то непрвильный метод. Подключение к бд - это не thread-safe, но шаринг я реализовал тоже неправильно. Буду делать работу над Ошибками.
Как все закончу, создам новый топик и выложу на всеобщее оборзение. И не буду больше мусроить здесь автору :) честно :)


Название: Re: QsT SQL Tools
Отправлено: pepsil от Июль 16, 2011, 16:14
Здравствуйте!
В аннотации к релизу 0.5.9.5a написано, что сделано компатибилити с Qt4.6

Changes from QST 0.5.9.5 release
- Compatibility errors with Qt 4.6.x are fixed.

При сборке на 4.6.2 есть ошибка:
qst\common\treeitem.cpp: In member function 'void Qst::Common::TreeItem::setData(const int&, const QVariant&, int)':
qst\common\treeitem.cpp:217: error: 'class QList<QVariant>' has no member named 'reserve'

смотрел документацию, таки да, функция-член reserve появилась с версии 4.7
Подскажите, пожалуйста, из какой версии QST можно выбрать код для TreeItem чтобы не использовать reverse (для сборки  с Qt 4.6.2)?


Название: Re: QST: QsT SQL Tools
Отправлено: GraninAS от Июль 17, 2011, 15:06
Здравствуйте!

Спасибо за отзыв. Я завтра посмотрю, - видимо, я очень плохо тестил эту версию. Думал, что исправил все несовместимости. Завтра исправлю и выложу для вас код, потому что, похоже, в других версиях всё так же.

С уважением.


Название: Re: QST: QsT SQL Tools
Отправлено: GraninAS от Июль 18, 2011, 07:28
Еще раз приветствую!

Я посмотрел свой код. В нем эта проблемная строчка закоменчена, код переписан. Компилируется. Значит, я мог забыть закомитить код в репозиторий или в архивы. Слил 7z-архив (http://sourceforge.net/projects/qstsqltools/files/QST%200.5/QST%200.5.9.5a%20release/QST%200.5.9.5a%20release.7z/download), там тоже код переписан. В репозитории  тоже свежая, с нужной правкой, ревизия 24 (http://qstsqltools.svn.sourceforge.net/viewvc/qstsqltools?view=revision&revision=24). Можете взять код в виде архива (tar.gz (http://sourceforge.net/projects/qstsqltools/files/QST%200.5/QST%200.5.9.5a%20release/QST%200.5.9.5a%20release.tar.gz/download), zip (http://sourceforge.net/projects/qstsqltools/files/QST%200.5/QST%200.5.9.5a%20release/QST%200.5.9.5a%20release.zip/download), rar (http://sourceforge.net/projects/qstsqltools/files/QST%200.5/QST%200.5.9.5a%20release/QST%200.5.9.5a%20release.rar/download)б 7z (http://sourceforge.net/projects/qstsqltools/files/QST%200.5/QST%200.5.9.5a%20release/QST%200.5.9.5a%20release.7z/download)) или слить его с SVN.

Спасибо!

---------------------

Не отходя от кассы, сообщаю, что наконец-то победил генерацию сложных запросов. За прошедшую неделю сделал то, что не мог сделать два месяца или около того. Основательно перерабатываю QST в версии 0.6, будут большие архитектурные изменения, без которых не получается. К сожалению, не все обратно совместимы, так что старый код будет нужно исправить.