diff --git a/src/nut/generators/abstractsqlgenerator.cpp b/src/nut/generators/abstractsqlgenerator.cpp index a7d43ee..98c9459 100644 --- a/src/nut/generators/abstractsqlgenerator.cpp +++ b/src/nut/generators/abstractsqlgenerator.cpp @@ -616,10 +616,10 @@ QString AbstractSqlGenerator::selectCommand(const QString &tableName, QString sql = QStringLiteral("SELECT ") + selectText + QStringLiteral(" FROM ") + fromText; - if (whereText != QStringLiteral("")) + if (!whereText.isEmpty()) sql.append(QStringLiteral(" WHERE ") + whereText); - if (orderText != QStringLiteral("")) + if (!orderText.isEmpty()) sql.append(QStringLiteral(" ORDER BY ") + orderText); // for (int i = 0; i < _database->model().count(); i++) @@ -648,7 +648,7 @@ QString AbstractSqlGenerator::selectCommand(const QString &tableName, QString sql = QStringLiteral("SELECT ") + selectText + QStringLiteral(" FROM ") + fromText; - if (whereText != QStringLiteral("")) + if (!whereText.isEmpty()) sql.append(QStringLiteral(" WHERE ") + whereText); for (int i = 0; i < _database->model().count(); i++) diff --git a/src/nut/nut.pro b/src/nut/nut.pro index 0b4bdeb..7beb4ab 100644 --- a/src/nut/nut.pro +++ b/src/nut/nut.pro @@ -46,9 +46,11 @@ HEADERS += \ $$PWD/phrases/phrasedata.h \ $$PWD/phrases/phrasedatalist.h \ $$PWD/phrases/phraselist.h \ - $$PWD/phrases/datephrase.h \ + $$PWD/phrases/fieldphrase_date.h \ $$PWD/table_p.h \ - bulkinserter_p.h + $$PWD/bulkinserter_p.h \ + $$PWD/phrases/fieldphrase_bool.h \ + $$PWD/phrases/fieldphrase_qstring.h SOURCES += \ $$PWD/generators/abstractsqlgenerator.cpp \ @@ -77,7 +79,9 @@ SOURCES += \ $$PWD/phrases/phrasedata.cpp \ $$PWD/phrases/phrasedatalist.cpp \ $$PWD/phrases/phraselist.cpp \ - $$PWD/phrases/datephrase.cpp + $$PWD/phrases/fieldphrase_date.cpp \ + $$PWD/phrases/fieldphrase_bool.cpp \ + $$PWD/phrases/fieldphrase_qstring.cpp load(qt_module) diff --git a/src/nut/phrase.h b/src/nut/phrase.h index 30fb6df..ab9d4f9 100644 --- a/src/nut/phrase.h +++ b/src/nut/phrase.h @@ -30,7 +30,9 @@ #include #include #include -#include +#include +#include +#include NUT_BEGIN_NAMESPACE diff --git a/src/nut/phrases/abstractfieldphrase.cpp b/src/nut/phrases/abstractfieldphrase.cpp index 616384e..4d51091 100644 --- a/src/nut/phrases/abstractfieldphrase.cpp +++ b/src/nut/phrases/abstractfieldphrase.cpp @@ -19,6 +19,7 @@ **************************************************************************/ #include "abstractfieldphrase.h" +#include NUT_BEGIN_NAMESPACE @@ -34,22 +35,26 @@ AbstractFieldPhrase::AbstractFieldPhrase(const char *className, AbstractFieldPhrase::AbstractFieldPhrase(const AbstractFieldPhrase &other) { data = other.data; - data->parents++; + data->ref.ref(); } AbstractFieldPhrase::AbstractFieldPhrase(AbstractFieldPhrase &&other) { data = other.data; - data->parents++; other.data = nullptr; } AbstractFieldPhrase::~AbstractFieldPhrase() { if (data) { - --data->parents; - if (data->parents <= 0) + if (!data->ref.deref()) { + qDebug() << "deleted" << data->className + << data->fieldName; delete data; + } + else + qDebug() << "more parents for" << data->className + << data->fieldName; } } @@ -87,6 +92,14 @@ AssignmentPhrase AbstractFieldPhrase::operator <<(const QVariant &other) return AssignmentPhrase(this, other); } +void AbstractFieldPhrase::detach() +{ + auto clone = data->clone(); + if (!data->ref.deref()) + delete data; + data = clone; +} + #define AbstractFieldPhraseOperatorVariant(class, op, cond) \ ConditionalPhrase class::operator op(const QVariant &other) \ { \ diff --git a/src/nut/phrases/abstractfieldphrase.h b/src/nut/phrases/abstractfieldphrase.h index 0745fa5..a4340be 100644 --- a/src/nut/phrases/abstractfieldphrase.h +++ b/src/nut/phrases/abstractfieldphrase.h @@ -80,6 +80,9 @@ public: AssignmentPhrase operator =(const QVariant &other); AssignmentPhrase operator =(const ConditionalPhrase &other); AssignmentPhrase operator <<(const QVariant &other); + +protected: + void detach(); }; NUT_END_NAMESPACE diff --git a/src/nut/phrases/assignmentphrase.cpp b/src/nut/phrases/assignmentphrase.cpp index 6b49426..f74d458 100644 --- a/src/nut/phrases/assignmentphrase.cpp +++ b/src/nut/phrases/assignmentphrase.cpp @@ -26,7 +26,7 @@ NUT_BEGIN_NAMESPACE AssignmentPhrase::AssignmentPhrase(PhraseData *d) : data(d) { - d->parents++; + d->ref.ref(); } AssignmentPhrase::AssignmentPhrase(AbstractFieldPhrase *l, const QVariant r) @@ -56,9 +56,8 @@ AssignmentPhrase::AssignmentPhrase(AssignmentPhrase *ph, const QVariant &v) AssignmentPhrase::~AssignmentPhrase() { - if (data) - if (!--data->parents) - delete data; + if (data && data->ref.deref()) + delete data; } NUT_END_NAMESPACE diff --git a/src/nut/phrases/assignmentphraselist.cpp b/src/nut/phrases/assignmentphraselist.cpp index b65c8fa..08a1ef6 100644 --- a/src/nut/phrases/assignmentphraselist.cpp +++ b/src/nut/phrases/assignmentphraselist.cpp @@ -68,9 +68,9 @@ AssignmentPhraseList AssignmentPhraseList::operator &(const AssignmentPhrase AssignmentPhraseList::~AssignmentPhraseList() { - foreach (PhraseData *d, data) - if (!--d->parents) - delete d; +// foreach (PhraseData *d, data) +// if (!d->ref.deref()) +// delete d; // qDeleteAll(data); // data.clear(); } @@ -78,7 +78,7 @@ AssignmentPhraseList::~AssignmentPhraseList() void AssignmentPhraseList::incAllDataParents() { foreach (PhraseData *d, data) - d->parents++; + d->ref.ref(); } diff --git a/src/nut/phrases/conditionalphrase.cpp b/src/nut/phrases/conditionalphrase.cpp index 1fe6b27..248d6e9 100644 --- a/src/nut/phrases/conditionalphrase.cpp +++ b/src/nut/phrases/conditionalphrase.cpp @@ -18,6 +18,8 @@ ** **************************************************************************/ +#include + #include "abstractfieldphrase.h" #include "conditionalphrase.h" #include "phrasedata.h" @@ -30,21 +32,21 @@ ConditionalPhrase::ConditionalPhrase() : data(nullptr) ConditionalPhrase::ConditionalPhrase(const ConditionalPhrase &other) { data = other.data; - data->parents++; -// const_cast(other).data = 0; + data->ref.ref(); } #ifdef Q_COMPILER_RVALUE_REFS ConditionalPhrase::ConditionalPhrase(ConditionalPhrase &&other) { - this->data = qMove(other.data); + data = other.data; + other.data = nullptr; } #endif ConditionalPhrase::ConditionalPhrase(const PhraseData *data) { - this->data = const_cast(data); - this->data->parents++; + data = const_cast(data); + data->ref.ref(); } ConditionalPhrase::ConditionalPhrase(AbstractFieldPhrase *l, @@ -104,8 +106,10 @@ ConditionalPhrase::~ConditionalPhrase() { if (data) { data->cleanUp(); - if (!--data->parents) + if (!data->ref.deref()) { + qDebug() << "deleted for cond"; delete data; + } } } @@ -113,7 +117,7 @@ ConditionalPhrase &ConditionalPhrase::operator =(const ConditionalPhrase &other) { data = other.data; if (data) - data->parents++; + data->ref.ref(); return *this; } @@ -122,23 +126,6 @@ ConditionalPhrase ConditionalPhrase::operator ==(const QVariant &other) return ConditionalPhrase(this, PhraseData::Equal, other); } -//ConditionalPhrase ConditionalPhrase::operator ==(const AbstractFieldPhrase &other) -//{ -// return ConditionalPhrase(this, PhraseData::Equal, other); -//} - -//ConditionalPhrase ConditionalPhrase::operator &&(const ConditionalPhrase &other) -//{ -// return ConditionalPhrase(this, PhraseData::And, -// const_cast(other)); -//} - -//ConditionalPhrase ConditionalPhrase::operator ||(const ConditionalPhrase &other) -//{ -// return ConditionalPhrase(this, PhraseData::Or, -// const_cast(other)); -//} - #define DECLARE_CONDITIONALPHRASE_OPERATORS_IMPL(op, cond) \ ConditionalPhrase operator op(const ConditionalPhrase &l, \ const ConditionalPhrase &r) \ @@ -149,8 +136,8 @@ ConditionalPhrase operator op(const ConditionalPhrase &l, \ p.data->operatorCond = cond; \ p.data->left = l.data; \ p.data->right = r.data; \ - l.data->parents++; \ - r.data->parents++; \ + l.data->ref.ref(); \ + r.data->ref.ref(); \ return p; \ } \ ConditionalPhrase operator op(const ConditionalPhrase &l, \ @@ -162,8 +149,8 @@ ConditionalPhrase operator op(const ConditionalPhrase &l, \ p.data->operatorCond = cond; \ p.data->left = l.data; \ p.data->right = r.data; \ - l.data->parents++; \ - r.data->parents++; \ + l.data->ref.ref(); \ + r.data = nullptr; \ return p; \ } \ ConditionalPhrase operator op(ConditionalPhrase &&l, \ @@ -175,8 +162,8 @@ ConditionalPhrase operator op(ConditionalPhrase &&l, \ p.data->operatorCond = cond; \ p.data->left = l.data; \ p.data->right = r.data; \ - l.data->parents++; \ - r.data->parents++; \ + r.data->ref.ref(); \ + l.data = nullptr; \ return p; \ } \ ConditionalPhrase operator op(ConditionalPhrase &&l, ConditionalPhrase &&r) \ @@ -187,8 +174,8 @@ ConditionalPhrase operator op(ConditionalPhrase &&l, ConditionalPhrase &&r) \ p.data->operatorCond = cond; \ p.data->left = l.data; \ p.data->right = r.data; \ - l.data->parents++; \ - r.data->parents++; \ + l.data = nullptr; \ + r.data = nullptr; \ return p; \ } diff --git a/src/nut/phrases/fieldphrase.h b/src/nut/phrases/fieldphrase.h index 7ef4b6d..5071668 100644 --- a/src/nut/phrases/fieldphrase.h +++ b/src/nut/phrases/fieldphrase.h @@ -50,29 +50,6 @@ Q_OUTOFLINE_TEMPLATE ConditionalPhrase FieldPhrase::operator ==(const QVarian return ConditionalPhrase(this, PhraseData::Equal, other); } - -template<> -class FieldPhrase : public AbstractFieldPhrase -{ -public: - FieldPhrase(const char *className, const char *s) : - AbstractFieldPhrase(className, s) - {} - - ConditionalPhrase like(const QString &term) { - return ConditionalPhrase(this, PhraseData::Like, term); - } - - ConditionalPhrase contains(const QString &term) { - return ConditionalPhrase(this, PhraseData::Like, - QVariant(QStringLiteral("%") + term + QStringLiteral("%"))); - } - - AssignmentPhrase operator =(const QVariant &v) { - return AssignmentPhrase(this, v); - } -}; - //Date and time #define CONDITIONAL_VARIANT_METHOD(name, cond) \ ConditionalPhrase name(int val) \ @@ -80,31 +57,6 @@ public: return ConditionalPhrase(this, cond, val); \ } -template<> -class FieldPhrase : public AbstractFieldPhrase -{ -public: - FieldPhrase(const char *className, const char *s) : - AbstractFieldPhrase(className, s) - {} - - AssignmentPhrase operator =(const bool &other) { - return AssignmentPhrase(this, other); - } - - FieldPhrase operator !() - { - FieldPhrase f(data->className, data->fieldName); -// f.data = new PhraseData(data); - f.data->isNot = !data->isNot; - return f; - } - - operator ConditionalPhrase() - { - return ConditionalPhrase(this, PhraseData::Equal, !data->isNot); - } -}; NUT_END_NAMESPACE diff --git a/src/nut/phrases/fieldphrase_bool.cpp b/src/nut/phrases/fieldphrase_bool.cpp new file mode 100644 index 0000000..c8d6716 --- /dev/null +++ b/src/nut/phrases/fieldphrase_bool.cpp @@ -0,0 +1,6 @@ +#include "fieldphrase_bool.h" + +NUT_BEGIN_NAMESPACE + + +NUT_END_NAMESPACE diff --git a/src/nut/phrases/fieldphrase_bool.h b/src/nut/phrases/fieldphrase_bool.h new file mode 100644 index 0000000..ad3e111 --- /dev/null +++ b/src/nut/phrases/fieldphrase_bool.h @@ -0,0 +1,38 @@ +#ifndef NUT_FIELDPHRASE_BOOL_H +#define NUT_FIELDPHRASE_BOOL_H + +#include +#include +#include + +NUT_BEGIN_NAMESPACE + +template<> +class FieldPhrase : public AbstractFieldPhrase +{ +public: + FieldPhrase(const char *className, const char *s) : + AbstractFieldPhrase(className, s) + {} + + AssignmentPhrase operator =(const bool &other) { + return AssignmentPhrase(this, other); + } + + FieldPhrase operator !() + { + FieldPhrase f(data->className, data->fieldName); + // f.data = new PhraseData(data); + f.data->isNot = !data->isNot; + return f; + } + + operator ConditionalPhrase() + { + return ConditionalPhrase(this, PhraseData::Equal, !data->isNot); + } +}; + +NUT_END_NAMESPACE + +#endif // NUT_FIELDPHRASE_BOOL_H diff --git a/src/nut/phrases/datephrase.cpp b/src/nut/phrases/fieldphrase_date.cpp similarity index 99% rename from src/nut/phrases/datephrase.cpp rename to src/nut/phrases/fieldphrase_date.cpp index 0355377..aae3bf4 100644 --- a/src/nut/phrases/datephrase.cpp +++ b/src/nut/phrases/fieldphrase_date.cpp @@ -18,7 +18,7 @@ ** **************************************************************************/ -#include "datephrase.h" +#include "fieldphrase_date.h" NUT_BEGIN_NAMESPACE diff --git a/src/nut/phrases/datephrase.h b/src/nut/phrases/fieldphrase_date.h similarity index 100% rename from src/nut/phrases/datephrase.h rename to src/nut/phrases/fieldphrase_date.h diff --git a/src/nut/phrases/fieldphrase_qstring.cpp b/src/nut/phrases/fieldphrase_qstring.cpp new file mode 100644 index 0000000..5692eed --- /dev/null +++ b/src/nut/phrases/fieldphrase_qstring.cpp @@ -0,0 +1,2 @@ +#include "fieldphrase_qstring.h" + diff --git a/src/nut/phrases/fieldphrase_qstring.h b/src/nut/phrases/fieldphrase_qstring.h new file mode 100644 index 0000000..ede4490 --- /dev/null +++ b/src/nut/phrases/fieldphrase_qstring.h @@ -0,0 +1,39 @@ +#ifndef NUT_FIELDPHRASE_QSTRING_H +#define NUT_FIELDPHRASE_QSTRING_H + +#include +#include +#include + +NUT_BEGIN_NAMESPACE + +template<> +class FieldPhrase : public AbstractFieldPhrase +{ +public: + FieldPhrase(const char *className, const char *s) + : AbstractFieldPhrase(className, s) + {} + + ConditionalPhrase like(const QString &term) + { + return ConditionalPhrase(this, PhraseData::Like, term); + } + + ConditionalPhrase contains(const QString &term) + { + return ConditionalPhrase(this, + PhraseData::Like, + QVariant(QStringLiteral("%") + term + + QStringLiteral("%"))); + } + + AssignmentPhrase operator=(const QVariant &v) + { + return AssignmentPhrase(this, v); + } +}; + +NUT_END_NAMESPACE + +#endif // NUT_FIELDPHRASE_QSTRING_H diff --git a/src/nut/phrases/phrasedata.cpp b/src/nut/phrases/phrasedata.cpp index 2316fd4..cc04aca 100644 --- a/src/nut/phrases/phrasedata.cpp +++ b/src/nut/phrases/phrasedata.cpp @@ -22,52 +22,57 @@ NUT_BEGIN_NAMESPACE -PhraseData::PhraseData() : - className(""), fieldName(""), - type(Field), operatorCond(NotAssign), - left(nullptr), right(nullptr), operand(QVariant::Invalid), isNot(false), parents(1) +PhraseData::PhraseData() + : className(""), fieldName(""), type(Field), operatorCond(NotAssign), + left(nullptr), right(nullptr), operand(QVariant::Invalid), isNot(false), + ref(1) { } -PhraseData::PhraseData(const char *className, const char *fieldName) : - className(className), fieldName(fieldName), - type(Field), operatorCond(NotAssign), - left(nullptr), right(nullptr), operand(QVariant::Invalid), isNot(false), parents(1) +PhraseData::PhraseData(const char *className, const char *fieldName) + : className(className), fieldName(fieldName), type(Field), + operatorCond(NotAssign), left(nullptr), right(nullptr), + operand(QVariant::Invalid), isNot(false), ref(1) { } PhraseData::PhraseData(PhraseData *l, PhraseData::Condition o) - : className(nullptr), fieldName(nullptr), - type(WithoutOperand), operatorCond(o), left(l), right(nullptr), - isNot(false), parents(1) + : className(nullptr), fieldName(nullptr), type(WithoutOperand), + operatorCond(o), left(l), right(nullptr), isNot(false), ref(1) { - l->parents++; + l->ref.ref(); } -PhraseData::PhraseData(PhraseData *l, PhraseData::Condition o, - PhraseData *r) - : className(nullptr), fieldName(nullptr), - type(WithOther), operatorCond(o), - left(l), right(r), - isNot(false), parents(1) +PhraseData::PhraseData(PhraseData *l, PhraseData::Condition o, PhraseData *r) + : className(nullptr), fieldName(nullptr), type(WithOther), operatorCond(o), + left(l), right(r), isNot(false), ref(1) { - l->parents++; - r->parents++; + l->ref.ref(); + r->ref.ref(); } PhraseData::PhraseData(PhraseData *l, PhraseData::Condition o, QVariant r) - : className(nullptr), fieldName(nullptr), - type(WithVariant), operatorCond(o), left(l), - right(nullptr), operand(r), isNot(false), parents(1) + : className(nullptr), fieldName(nullptr), type(WithVariant), + operatorCond(o), left(l), right(nullptr), operand(r), isNot(false), + ref(1) { } +PhraseData::~PhraseData() +{ +// if (left && !left->ref.deref()) +// delete left; + +// if (right && !right->ref.deref()) +// delete right; +} + PhraseData *PhraseData::operator =(PhraseData *other) { - other->parents++; + other->ref.ref(); return other; } PhraseData &PhraseData::operator =(PhraseData &other) { - other.parents++; + other.ref.ref(); return other; } @@ -81,6 +86,26 @@ void PhraseData::cleanUp() { } +PhraseData *PhraseData::clone() const +{ + auto c = new PhraseData; + c->className = className; + c->fieldName = fieldName; + + c->type = type; + + c->operatorCond = operatorCond; + + c->left = left; + c->right = right; + + c->operand = operand; + c->isNot = isNot; +// c->parents = parents; + + return c; +} + void PhraseData::cleanUp(PhraseData *d) { if (d->left) diff --git a/src/nut/phrases/phrasedata.h b/src/nut/phrases/phrasedata.h index 0af3d7b..11fe522 100644 --- a/src/nut/phrases/phrasedata.h +++ b/src/nut/phrases/phrasedata.h @@ -97,24 +97,25 @@ public: QVariant operand; bool isNot; - quint16 parents; +// quint16 parents; + + mutable QAtomicInt ref; PhraseData(); PhraseData(const char *className, const char *fieldName); PhraseData(PhraseData *l, Condition o); PhraseData(PhraseData *l, Condition o, PhraseData *r); PhraseData(PhraseData *l, Condition o, QVariant r); -// explicit PhraseData(const PhraseData &other); -// explicit PhraseData(const PhraseData *other); + + virtual ~PhraseData(); PhraseData *operator =(PhraseData *other); PhraseData &operator =(PhraseData &other); QString toString() const; - ~PhraseData() = default; - void cleanUp(); + PhraseData *clone() const; private: void cleanUp(PhraseData *d); }; diff --git a/src/nut/phrases/phrasedatalist.cpp b/src/nut/phrases/phrasedatalist.cpp index e1858ed..1d359b1 100644 --- a/src/nut/phrases/phrasedatalist.cpp +++ b/src/nut/phrases/phrasedatalist.cpp @@ -37,14 +37,14 @@ PhraseDataList::PhraseDataList(const PhraseDataList &other) : QList void PhraseDataList::append(PhraseData *d) { - d->parents++; + d->ref.ref(); QList::append(d); } void PhraseDataList::append(QList &dl) { foreach (PhraseData *d, dl) - d->parents++; + d->ref.ref(); QList::append(dl); } @@ -53,7 +53,7 @@ PhraseDataList::~PhraseDataList() QList::iterator i; for (i = begin(); i != end(); ++i) { (*i)->cleanUp(); - if (!--(*i)->parents) + if (!(*i)->ref.deref()) delete *i; } } diff --git a/tests/auto/tst_phrases/tst_phrases.cpp b/tests/auto/tst_phrases/tst_phrases.cpp index d319c58..bdb7ed3 100644 --- a/tests/auto/tst_phrases/tst_phrases.cpp +++ b/tests/auto/tst_phrases/tst_phrases.cpp @@ -3,6 +3,7 @@ #include "tst_phrases.h" #include "phrase.h" +#include "sqlitegenerator.h" using namespace Nut; @@ -17,11 +18,15 @@ void PhrasesTest::initTestCase() void PhrasesTest::no1() { - FieldPhrase id("main", "id"); - FieldPhrase name("main", "name"); - FieldPhrase last_name("main", "last_name"); - FieldPhrase date("main", "date"); - auto w = (id == 4 && name == "hi"); + { + FieldPhrase id("main", "id"); + FieldPhrase name("main", "name"); + FieldPhrase last_name("main", "last_name"); + FieldPhrase date("main", "date"); + auto w = (id == 4 && name == QStringLiteral("hi")); + + SqliteGenerator g; + } } void PhrasesTest::numeric()