File indexing completed on 2024-12-01 07:24:56

0001 /* This file is part of the KDE project
0002    Copyright (C) 2002 Lucijan Busch <lucijan@gmx.at>
0003    Copyright (C) 2002 Joseph Wenninger <jowenn@kde.org>
0004    Copyright (C) 2003-2017 Jarosław Staniek <staniek@kde.org>
0005 
0006    This library is free software; you can redistribute it and/or
0007    modify it under the terms of the GNU Library General Public
0008    License as published by the Free Software Foundation; either
0009    version 2 of the License, or (at your option) any later version.
0010 
0011    This library is distributed in the hope that it will be useful,
0012    but WITHOUT ANY WARRANTY; without even the implied warranty of
0013    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0014    Library General Public License for more details.
0015 
0016    You should have received a copy of the GNU Library General Public License
0017    along with this library; see the file COPYING.LIB.  If not, write to
0018    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
0019  * Boston, MA 02110-1301, USA.
0020  */
0021 
0022 #include "KDbField.h"
0023 #include "KDbField_p.h"
0024 #include "KDbConnection.h"
0025 #include "KDbDriver.h"
0026 #include "KDbExpression.h"
0027 #include "KDbQuerySchema.h"
0028 #include "KDb.h"
0029 #include "kdb_debug.h"
0030 
0031 #include <QDateTime>
0032 
0033 //! @todo make this configurable
0034 static int g_defaultMaxLength = 0; // unlimited
0035 
0036 //-------------------------------------------------------
0037 //! @internal Used in s_typeNames member to handle translated type names
0038 class FieldTypeNames
0039 {
0040 public:
0041     FieldTypeNames();
0042     QVector<QString> data;
0043     QHash<QString, KDbField::Type> str2num;
0044     QStringList names;
0045 private:
0046     Q_DISABLE_COPY(FieldTypeNames)
0047 };
0048 
0049 //! @internal Used in m_typeGroupNames member to handle translated type group names
0050 class FieldTypeGroupNames
0051 {
0052 public:
0053     FieldTypeGroupNames();
0054     QVector<QString> data;
0055     QHash<QString, KDbField::TypeGroup> str2num;
0056     QStringList names;
0057 private:
0058     Q_DISABLE_COPY(FieldTypeGroupNames)
0059 };
0060 
0061 //! real translated type names (and nontranslated type name strings)
0062 Q_GLOBAL_STATIC(FieldTypeNames, s_typeNames)
0063 
0064 //! real translated type group names (and nontranslated group name strings)
0065 Q_GLOBAL_STATIC(FieldTypeGroupNames, s_typeGroupNames)
0066 
0067 #define ADDTYPE(type, i18, str) \
0068     data[KDbField::type] = i18; \
0069     data[KDbField::type+KDbField::Null+1] = QStringLiteral(str); \
0070     str2num[ QString::fromLatin1(str).toLower() ] = KDbField::type; \
0071     names.append(i18)
0072 #define ADDGROUP(type, i18, str) \
0073     data[KDbField::type] = i18; \
0074     data[KDbField::type+KDbField::LastTypeGroup+1] = QStringLiteral(str); \
0075     str2num[ QString::fromLatin1(str).toLower() ] = KDbField::type; \
0076     names.append(i18)
0077 
0078 FieldTypeNames::FieldTypeNames()
0079     : data((KDbField::Null + 1)*2)
0080 {
0081     ADDTYPE(InvalidType, KDbField::tr("Invalid Type"), "InvalidType");
0082     ADDTYPE(Byte, KDbField::tr("Byte"), "Byte");
0083     ADDTYPE(ShortInteger, KDbField::tr("Short Integer Number"), "ShortInteger");
0084     ADDTYPE(Integer, KDbField::tr("Integer Number"), "Integer");
0085     ADDTYPE(BigInteger, KDbField::tr("Big Integer Number"), "BigInteger");
0086     ADDTYPE(Boolean, KDbField::tr("Yes/No Value"), "Boolean");
0087     ADDTYPE(Date, KDbField::tr("Date"), "Date");
0088     ADDTYPE(DateTime, KDbField::tr("Date and Time"), "DateTime");
0089     ADDTYPE(Time, KDbField::tr("Time"), "Time");
0090     ADDTYPE(Float, KDbField::tr("Single Precision Number"), "Float");
0091     ADDTYPE(Double, KDbField::tr("Double Precision Number"), "Double");
0092     ADDTYPE(Text, KDbField::tr("Text"), "Text");
0093     ADDTYPE(LongText, KDbField::tr("Long Text"), "LongText");
0094     ADDTYPE(BLOB, KDbField::tr("Object"), "BLOB");
0095     ADDTYPE(Null, QLatin1String("NULL")/*don't translate*/, "NULL");
0096 }
0097 
0098 //-------------------------------------------------------
0099 
0100 FieldTypeGroupNames::FieldTypeGroupNames()
0101         : data((KDbField::LastTypeGroup + 1)*2)
0102 {
0103     ADDGROUP(InvalidGroup, KDbField::tr("Invalid Group"), "InvalidGroup");
0104     ADDGROUP(TextGroup, KDbField::tr("Text"), "TextGroup");
0105     ADDGROUP(IntegerGroup, KDbField::tr("Integer Number"), "IntegerGroup");
0106     ADDGROUP(FloatGroup, KDbField::tr("Floating Point Number"), "FloatGroup");
0107     ADDGROUP(BooleanGroup, KDbField::tr("Yes/No"), "BooleanGroup");
0108     ADDGROUP(DateTimeGroup, KDbField::tr("Date/Time"), "DateTimeGroup");
0109     ADDGROUP(BLOBGroup, KDbField::tr("Object"), "BLOBGroup");
0110 }
0111 
0112 //-------------------------------------------------------
0113 
0114 class KDbFieldPrivate
0115 {
0116 public:
0117     static KDbConnection *connection(const KDbTableSchema &table)
0118     {
0119         return table.connection();
0120     }
0121 };
0122 
0123 
0124 class Q_DECL_HIDDEN KDbField::Private
0125 {
0126 public:
0127     Private(KDbFieldList *aParent = nullptr, int aOrder = -1)
0128         : parent(aParent)
0129         , type(KDbField::InvalidType)
0130         , precision(0)
0131         , options(KDbField::NoOptions)
0132         , defaultValue(QString())
0133         , order(aOrder)
0134     {
0135     }
0136     Private(const QString &aName, KDbField::Type aType, KDbField::Options aOptions, int aPrecision,
0137             const QVariant &aDefaultValue, const QString &aCaption, const QString &aDescription)
0138         : parent(nullptr)
0139         , type(aType)
0140         , name(aName)
0141         , caption(aCaption)
0142         , description(aDescription)
0143         , precision(aPrecision)
0144         , options(aOptions)
0145         , defaultValue(aDefaultValue)
0146         , order(-1)
0147     {
0148     }
0149     Private(const Private &o)
0150     {
0151         (*this) = o;
0152         if (o.customProperties) {
0153             customProperties = new CustomPropertiesMap(*o.customProperties);
0154         }
0155         if (!o.expr.isNull()) {//deep copy the expression
0156     //! @todo  expr = new KDbExpression(o.expr);
0157                 expr = KDbExpression(o.expr.clone());
0158         } else {
0159             expr = KDbExpression();
0160         }
0161     }
0162 
0163     ~Private() {
0164         delete customProperties;
0165     }
0166 
0167     //! In most cases this points to a KDbTableSchema object that field is assigned
0168     KDbFieldList *parent;
0169     KDbField::Type type;
0170     QString name;
0171     QString caption;
0172     QString description;
0173     QString subType;
0174     KDbField::Constraints constraints;
0175     KDbField::MaxLengthStrategy maxLengthStrategy;
0176     int maxLength; //!< also used for storing scale for floating point types
0177     int precision;
0178     int visibleDecimalPlaces = -1; //!< used in visibleDecimalPlaces()
0179     KDbField::Options options;
0180     QVariant defaultValue;
0181     int order;
0182     KDbExpression expr;
0183     KDbField::CustomPropertiesMap* customProperties = nullptr;
0184     QVector<QString> hints;
0185 };
0186 
0187 //-------------------------------------------------------
0188 
0189 KDbField::KDbField()
0190     : d(new Private)
0191 {
0192     setMaxLength(0); // do not move this line up!
0193     setMaxLengthStrategy(DefinedMaxLength); // do not move this line up!
0194     setConstraints(NoConstraints);
0195 }
0196 
0197 KDbField::KDbField(KDbFieldList *aParent, int aOrder)
0198     : d(new Private(aParent, aOrder))
0199 {
0200     setMaxLength(0); // do not move this line up!
0201     setMaxLengthStrategy(DefinedMaxLength); // do not move this line up!
0202     setConstraints(NoConstraints);
0203 }
0204 
0205 KDbField::KDbField(KDbTableSchema *tableSchema)
0206     : KDbField(tableSchema, tableSchema->fieldCount())
0207 {
0208 }
0209 
0210 KDbField::KDbField(KDbQuerySchema *querySchema, const KDbExpression& expr)
0211     : KDbField(querySchema, querySchema->fieldCount())
0212 {
0213     setExpression(expr);
0214 }
0215 
0216 KDbField::KDbField(KDbQuerySchema *querySchema)
0217     : KDbField(querySchema, querySchema->fieldCount())
0218 {
0219 }
0220 
0221 KDbField::KDbField(const QString &name, Type type, Constraints constr, Options options,
0222                    int maxLength, int precision, const QVariant &defaultValue,
0223                    const QString &caption, const QString &description)
0224     : d(new Private(name, type, options, precision, defaultValue, caption, description))
0225 {
0226     setMaxLength(maxLength);
0227     setConstraints(constr);
0228 }
0229 
0230 /*! Copy constructor. */
0231 KDbField::KDbField(const KDbField &f)
0232     : d(new Private(*f.d))
0233 {
0234 }
0235 
0236 KDbField::~KDbField()
0237 {
0238     delete d;
0239 }
0240 
0241 KDbFieldList *KDbField::parent()
0242 {
0243     return d->parent;
0244 }
0245 
0246 const KDbFieldList *KDbField::parent() const
0247 {
0248     return d->parent;
0249 }
0250 
0251 void KDbField::setParent(KDbFieldList *parent)
0252 {
0253     d->parent = parent;
0254 }
0255 
0256 QString KDbField::name() const
0257 {
0258     return d->name;
0259 }
0260 
0261 KDbField::Options KDbField::options() const
0262 {
0263     return d->options;
0264 }
0265 
0266 void KDbField::setOptions(Options options)
0267 {
0268     d->options = options;
0269 }
0270 
0271 QString KDbField::subType() const
0272 {
0273     return d->subType;
0274 }
0275 
0276 void KDbField::setSubType(const QString& subType)
0277 {
0278     d->subType = subType;
0279 }
0280 
0281 QVariant KDbField::defaultValue() const
0282 {
0283     return d->defaultValue;
0284 }
0285 
0286 int KDbField::precision() const
0287 {
0288     return d->precision;
0289 }
0290 
0291 int KDbField::scale() const
0292 {
0293     return d->maxLength;
0294 }
0295 
0296 int KDbField::visibleDecimalPlaces() const
0297 {
0298     return d->visibleDecimalPlaces;
0299 }
0300 
0301 KDbField::Constraints KDbField::constraints() const
0302 {
0303     return d->constraints;
0304 }
0305 
0306 int KDbField::order() const
0307 {
0308     return d->order;
0309 }
0310 
0311 void KDbField::setOrder(int order)
0312 {
0313     d->order = order;
0314 }
0315 
0316 QString KDbField::caption() const
0317 {
0318     return d->caption;
0319 }
0320 
0321 void KDbField::setCaption(const QString& caption)
0322 {
0323     d->caption = caption;
0324 }
0325 
0326 QString KDbField::captionOrName() const
0327 {
0328     return d->caption.isEmpty() ? d->name : d->caption;
0329 }
0330 
0331 QString KDbField::description() const
0332 {
0333     return d->description;
0334 }
0335 
0336 void KDbField::setDescription(const QString& description)
0337 {
0338     d->description = description;
0339 }
0340 
0341 QVector<QString> KDbField::enumHints() const
0342 {
0343     return d->hints;
0344 }
0345 
0346 QString KDbField::enumHint(int num)
0347 {
0348     return (num < d->hints.size()) ? d->hints.at(num) : QString();
0349 }
0350 
0351 void KDbField::setEnumHints(const QVector<QString> &hints)
0352 {
0353     d->hints = hints;
0354 }
0355 
0356 // static
0357 int KDbField::typesCount()
0358 {
0359     return LastType - InvalidType + 1;
0360 }
0361 
0362 // static
0363 int KDbField::specialTypesCount()
0364 {
0365     return LastSpecialType - Null + 1;
0366 }
0367 
0368 // static
0369 int KDbField::typeGroupsCount()
0370 {
0371     return LastTypeGroup - InvalidGroup + 1;
0372 }
0373 
0374 KDbField* KDbField::copy()
0375 {
0376     return new KDbField(*this);
0377 }
0378 
0379 KDbField::Type KDbField::type() const
0380 {
0381     if (!d->expr.isNull()) {
0382         return d->expr.type();
0383     }
0384     return d->type;
0385 }
0386 
0387 QVariant::Type KDbField::variantType(Type type)
0388 {
0389     switch (type) {
0390     case Byte:
0391     case ShortInteger:
0392     case Integer:
0393     case BigInteger:
0394         return QVariant::Int;
0395     case Boolean:
0396         return QVariant::Bool;
0397     case Date:
0398         return QVariant::Date;
0399     case DateTime:
0400         return QVariant::DateTime;
0401     case Time:
0402         return QVariant::Time;
0403     case Float:
0404     case Double:
0405         return QVariant::Double;
0406     case Text:
0407     case LongText:
0408         return QVariant::String;
0409     case BLOB:
0410         return QVariant::ByteArray;
0411     default:
0412         break;
0413     }
0414 
0415     return QVariant::Invalid;
0416 }
0417 
0418 template <typename T>
0419 static inline QVariant tryConvert(const QVariant &value)
0420 {
0421     return value.canConvert<T>() ? value.value<T>() : value;
0422 }
0423 
0424 //static
0425 //! @todo use an array of functions?
0426 QVariant KDbField::convertToType(const QVariant &value, Type type)
0427 {
0428     switch (type) {
0429     case Byte:
0430     case ShortInteger:
0431     case Integer:
0432         return tryConvert<int>(value);
0433     case BigInteger:
0434         return tryConvert<qlonglong>(value);
0435     case Boolean:
0436         return tryConvert<bool>(value);
0437     case Date:
0438         return tryConvert<QDate>(value);
0439     case DateTime:
0440         return tryConvert<QDateTime>(value);
0441     case Time:
0442         return tryConvert<QTime>(value);
0443     case Float:
0444         return tryConvert<float>(value);
0445     case Double:
0446         return tryConvert<double>(value);
0447     case Text:
0448     case LongText:
0449         return tryConvert<QString>(value);
0450     case BLOB:
0451         return tryConvert<QByteArray>(value);
0452     default:
0453         break;
0454     }
0455     return QVariant();
0456 }
0457 
0458 QString KDbField::typeName(Type type)
0459 {
0460     return s_typeNames->data.value(type, QString::number(type));
0461 }
0462 
0463 QStringList KDbField::typeNames()
0464 {
0465     return s_typeNames->names;
0466 }
0467 
0468 QString KDbField::typeString(Type type)
0469 {
0470     return (type <= Null) ? s_typeNames->data.at(int(Null) + 1 + type)
0471                           : (QLatin1String("Type") + QString::number(type));
0472 }
0473 
0474 QString KDbField::typeGroupName(TypeGroup typeGroup)
0475 {
0476     return (typeGroup <= LastTypeGroup) ? s_typeGroupNames->data.at(typeGroup)
0477                                         : typeGroupString(typeGroup);
0478 }
0479 
0480 QStringList KDbField::typeGroupNames()
0481 {
0482     return s_typeGroupNames->names;
0483 }
0484 
0485 QString KDbField::typeGroupString(TypeGroup typeGroup)
0486 {
0487     return s_typeGroupNames->data.value(int(LastTypeGroup) + 1 + typeGroup,
0488                                         QLatin1String("TypeGroup") + QString::number(typeGroup));
0489 }
0490 
0491 KDbField::Type KDbField::typeForString(const QString& typeString)
0492 {
0493     return s_typeNames->str2num.value(typeString.toLower(), InvalidType);
0494 }
0495 
0496 KDbField::TypeGroup KDbField::typeGroupForString(const QString& typeGroupString)
0497 {
0498     return s_typeGroupNames->str2num.value(typeGroupString.toLower(), InvalidGroup);
0499 }
0500 
0501 bool KDbField::isIntegerType(Type type)
0502 {
0503     switch (type) {
0504     case KDbField::Byte:
0505     case KDbField::ShortInteger:
0506     case KDbField::Integer:
0507     case KDbField::BigInteger:
0508         return true;
0509     default:;
0510     }
0511     return false;
0512 }
0513 
0514 bool KDbField::isNumericType(Type type)
0515 {
0516     switch (type) {
0517     case KDbField::Byte:
0518     case KDbField::ShortInteger:
0519     case KDbField::Integer:
0520     case KDbField::BigInteger:
0521     case KDbField::Float:
0522     case KDbField::Double:
0523         return true;
0524     default:;
0525     }
0526     return false;
0527 }
0528 
0529 bool KDbField::isFPNumericType(Type type)
0530 {
0531     return type == KDbField::Float || type == KDbField::Double;
0532 }
0533 
0534 bool KDbField::isDateTimeType(Type type)
0535 {
0536     switch (type) {
0537     case KDbField::Date:
0538     case KDbField::DateTime:
0539     case KDbField::Time:
0540         return true;
0541     default:;
0542     }
0543     return false;
0544 }
0545 
0546 bool KDbField::isTextType(Type type)
0547 {
0548     switch (type) {
0549     case KDbField::Text:
0550     case KDbField::LongText:
0551         return true;
0552     default:;
0553     }
0554     return false;
0555 }
0556 
0557 bool KDbField::hasEmptyProperty(Type type)
0558 {
0559     return KDbField::isTextType(type) || type == BLOB;
0560 }
0561 
0562 bool KDbField::isAutoIncrementAllowed(Type type)
0563 {
0564     return KDbField::isIntegerType(type);
0565 }
0566 
0567 KDbField::TypeGroup KDbField::typeGroup(Type type)
0568 {
0569     if (KDbField::isTextType(type))
0570         return TextGroup;
0571     else if (KDbField::isIntegerType(type))
0572         return IntegerGroup;
0573     else if (KDbField::isFPNumericType(type))
0574         return FloatGroup;
0575     else if (type == Boolean)
0576         return BooleanGroup;
0577     else if (KDbField::isDateTimeType(type))
0578         return DateTimeGroup;
0579     else if (type == BLOB)
0580         return BLOBGroup;
0581 
0582     return InvalidGroup; //unknown
0583 }
0584 
0585 KDbTableSchema* KDbField::table()
0586 {
0587     return dynamic_cast<KDbTableSchema*>(d->parent);
0588 }
0589 
0590 const KDbTableSchema* KDbField::table() const
0591 {
0592     return dynamic_cast<const KDbTableSchema*>(d->parent);
0593 }
0594 
0595 void KDbField::setTable(KDbTableSchema *tableSchema)
0596 {
0597     d->parent = tableSchema;
0598 }
0599 
0600 KDbQuerySchema* KDbField::query()
0601 {
0602     return dynamic_cast<KDbQuerySchema*>(d->parent);
0603 }
0604 
0605 const KDbQuerySchema* KDbField::query() const
0606 {
0607     return dynamic_cast<const KDbQuerySchema*>(d->parent);
0608 }
0609 
0610 void KDbField::setQuery(KDbQuerySchema *querySchema)
0611 {
0612     d->parent = querySchema;
0613 }
0614 
0615 void KDbField::setName(const QString& name)
0616 {
0617     d->name = name.toLower();
0618 }
0619 
0620 void KDbField::setType(Type t)
0621 {
0622     if (!d->expr.isNull()) {
0623         kdbWarning() << "Could not set type" << KDbField::typeName(t)
0624                      << "because the field has expression assigned!";
0625         return;
0626     }
0627     d->type = t;
0628 }
0629 
0630 void KDbField::setConstraints(Constraints c)
0631 {
0632     d->constraints = c;
0633     //pkey must be unique notnull
0634     if (isPrimaryKey()) {
0635         setPrimaryKey(true);
0636     }
0637     if (isIndexed()) {
0638         setIndexed(true);
0639     }
0640     if (isAutoIncrement() && !isAutoIncrementAllowed()) {
0641         setAutoIncrement(false);
0642     }
0643 }
0644 
0645 int KDbField::defaultMaxLength()
0646 {
0647     return g_defaultMaxLength;
0648 }
0649 
0650 void KDbField::setDefaultMaxLength(int maxLength)
0651 {
0652     g_defaultMaxLength = maxLength;
0653 }
0654 
0655 KDbField::MaxLengthStrategy KDbField::maxLengthStrategy() const
0656 {
0657     return d->maxLengthStrategy;
0658 }
0659 
0660 void KDbField::setMaxLengthStrategy(MaxLengthStrategy strategy)
0661 {
0662     d->maxLengthStrategy = strategy;
0663 }
0664 
0665 int KDbField::maxLength() const
0666 {
0667     return d->maxLength;
0668 }
0669 
0670 void KDbField::setMaxLength(int maxLength)
0671 {
0672     d->maxLength = maxLength;
0673     d->maxLengthStrategy = DefinedMaxLength;
0674 }
0675 
0676 void KDbField::setPrecision(int p)
0677 {
0678     if (!isFPNumericType()) {
0679         return;
0680     }
0681     d->precision = p;
0682 }
0683 
0684 void KDbField::setScale(int s)
0685 {
0686     if (!isFPNumericType()) {
0687         return;
0688     }
0689     d->maxLength = s;
0690 }
0691 
0692 void KDbField::setVisibleDecimalPlaces(int p)
0693 {
0694     if (!KDb::supportsVisibleDecimalPlacesProperty(type())) {
0695         return;
0696     }
0697     d->visibleDecimalPlaces = p < 0 ? -1 : p;
0698 }
0699 
0700 void KDbField::setUnsigned(bool u)
0701 {
0702     if (!isIntegerType()) {
0703         return;
0704     }
0705     d->options |= Unsigned;
0706     if (!u) {
0707         d->options ^= Unsigned;
0708     }
0709 }
0710 
0711 void KDbField::setDefaultValue(const QVariant& def)
0712 {
0713     d->defaultValue = def;
0714 }
0715 
0716 bool KDbField::setDefaultValue(const QByteArray& def)
0717 {
0718     if (def.isNull()) {
0719         d->defaultValue = QVariant();
0720         return true;
0721     }
0722 
0723     bool ok;
0724     switch (type()) {
0725     case Byte: {
0726         unsigned int v = def.toUInt(&ok);
0727         if (!ok || v > 255) {
0728             d->defaultValue = QVariant();
0729         } else {
0730             d->defaultValue = QVariant(v);
0731         }
0732         break;
0733     }
0734     case ShortInteger: {
0735         int v = def.toInt(&ok);
0736         if (!ok || (!(d->options & Unsigned) && (v < -32768 || v > 32767))
0737             || ((d->options & Unsigned) && (v < 0 || v > 65535)))
0738         {
0739             d->defaultValue = QVariant();
0740         } else {
0741             d->defaultValue = QVariant(v);
0742         }
0743         break;
0744     }
0745     case Integer: {//4 bytes
0746         long v = def.toLong(&ok);
0747         //! @todo    if (!ok || (!(d->options & Unsigned) && (-v > 0x080000000 || v >
0748         //! (0x080000000-1))) || ((d->options & Unsigned) && (v < 0 || v > 0x100000000)))
0749         if (!ok || (!(d->options & Unsigned)
0750                     && (-v > (int)0x07FFFFFFF || v > (int)(0x080000000 - 1))))
0751         {
0752             d->defaultValue = QVariant();
0753         } else {
0754             d->defaultValue = QVariant((qint64)v);
0755         }
0756         break;
0757     }
0758     case BigInteger: {//8 bytes
0759 //! @todo BigInteger support
0760         /*
0761               qint64 long v = def.toLongLong(&ok);
0762         //! @todo 2-part decoding
0763               if (!ok || (!(d->options & Unsigned) && (-v > 0x080000000 || v > (0x080000000-1))))
0764                 d->defaultValue = QVariant();
0765               else
0766                 if (d->options & Unsigned)
0767                   d->defaultValue=QVariant((quint64) v);
0768                 else
0769                   d->defaultValue = QVariant((qint64)v);*/
0770         break;
0771     }
0772     case Boolean: {
0773         unsigned short v = def.toUShort(&ok);
0774         if (!ok || v > 1) {
0775             d->defaultValue = QVariant();
0776         } else {
0777             d->defaultValue = QVariant((bool)v);
0778         }
0779         break;
0780     }
0781     case Date: {//YYYY-MM-DD
0782         QDate date = QDate::fromString(QLatin1String(def), Qt::ISODate);
0783         if (!date.isValid()) {
0784             d->defaultValue = QVariant();
0785         } else {
0786             d->defaultValue = QVariant(date);
0787         }
0788         break;
0789     }
0790     case DateTime: {//YYYY-MM-DDTHH:MM:SS.ms
0791         const QDateTime dt = KDbUtils::dateTimeFromISODateStringWithMs(QString::fromLatin1(def));
0792         if (!dt.isValid()) {
0793             d->defaultValue = QVariant();
0794         } else {
0795             d->defaultValue = QVariant(dt);
0796         }
0797         break;
0798     }
0799     case Time: {//HH:MM:SS.ms
0800         const QTime time = KDbUtils::timeFromISODateStringWithMs(QString::fromLatin1(def));
0801         if (!time.isValid()) {
0802             d->defaultValue = QVariant();
0803         } else {
0804             d->defaultValue = QVariant(time);
0805         }
0806         break;
0807     }
0808     case Float: {
0809         float v = def.toFloat(&ok);
0810         if (!ok || ((d->options & Unsigned) && (v < 0.0))) {
0811             d->defaultValue = QVariant();
0812         } else {
0813             d->defaultValue = QVariant(v);
0814         }
0815         break;
0816     }
0817     case Double: {
0818         double v = def.toDouble(&ok);
0819         if (!ok || ((d->options & Unsigned) && (v < 0.0))) {
0820             d->defaultValue = QVariant();
0821         } else {
0822             d->defaultValue = QVariant(v);
0823         }
0824         break;
0825     }
0826     case Text: {
0827         if (def.isNull() || def.length() > maxLength()) {
0828             d->defaultValue = QVariant();
0829         } else {
0830             d->defaultValue = QVariant(QLatin1String(def));
0831         }
0832         break;
0833     }
0834     case LongText: {
0835         if (def.isNull()) {
0836             d->defaultValue = QVariant();
0837         } else {
0838             d->defaultValue = QVariant(QLatin1String(def));
0839         }
0840         break;
0841     }
0842     case BLOB: {
0843 //! @todo
0844         if (def.isNull()) {
0845             d->defaultValue = QVariant();
0846         } else {
0847             d->defaultValue = QVariant(def);
0848         }
0849         break;
0850     }
0851     default:
0852         d->defaultValue = QVariant();
0853     }
0854     return d->defaultValue.isNull();
0855 }
0856 
0857 void KDbField::setAutoIncrement(bool a)
0858 {
0859     if (a && !isAutoIncrementAllowed()) {
0860         return;
0861     }
0862     if (isAutoIncrement() != a) {
0863         d->constraints ^= KDbField::AutoInc;
0864     }
0865 }
0866 
0867 void KDbField::setPrimaryKey(bool p)
0868 {
0869     if (isPrimaryKey() != p) {
0870         d->constraints ^= KDbField::PrimaryKey;
0871     }
0872     if (p) {//also set implied constraints
0873         setUniqueKey(true);
0874         setNotNull(true);
0875         setNotEmpty(true);
0876         setIndexed(true);
0877     } else {
0878 //! @todo is this ok for all engines?
0879         setAutoIncrement(false);
0880     }
0881 }
0882 
0883 void KDbField::setUniqueKey(bool u)
0884 {
0885     if (isUniqueKey() != u) {
0886         d->constraints ^= KDbField::Unique;
0887         if (u) { //also set implied constraints
0888             setNotNull(true);
0889             setIndexed(true);
0890         }
0891     }
0892 }
0893 
0894 void KDbField::setForeignKey(bool f)
0895 {
0896     if (isForeignKey() != f) {
0897         d->constraints ^= KDbField::ForeignKey;
0898     }
0899 }
0900 
0901 void KDbField::setNotNull(bool n)
0902 {
0903     if (isNotNull() != n) {
0904         d->constraints ^=KDbField::NotNull;
0905     }
0906 }
0907 
0908 void KDbField::setNotEmpty(bool n)
0909 {
0910     if (isNotEmpty() != n) {
0911         d->constraints ^= KDbField::NotEmpty;
0912     }
0913 }
0914 
0915 void KDbField::setIndexed(bool s)
0916 {
0917     if (isIndexed() != s) {
0918         d->constraints ^= KDbField::Indexed;
0919     }
0920     if (!s) {//also set implied constraints
0921         setPrimaryKey(false);
0922         setUniqueKey(false);
0923         setNotNull(false);
0924         setNotEmpty(false);
0925     }
0926 }
0927 
0928 void debug(QDebug dbg, const KDbField& field, KDbFieldDebugOptions options)
0929 {
0930     const KDbConnection *conn = field.table() ? KDbFieldPrivate::connection(*field.table()) : nullptr;
0931     if (options & KDbFieldDebugAddName) {
0932         if (field.name().isEmpty()) {
0933             dbg.nospace() << "<NONAME> ";
0934         } else {
0935             dbg.nospace() << field.name() << ' ';
0936         }
0937     }
0938     if (field.options() & KDbField::Unsigned)
0939         dbg.nospace() << " UNSIGNED";
0940     dbg.nospace() << ' ' << qPrintable((conn && conn->driver())
0941         ? conn->driver()->sqlTypeName(field.type(), field) : KDbDriver::defaultSqlTypeName(field.type()));
0942     if (field.isFPNumericType() && field.precision() > 0) {
0943         if (field.scale() > 0)
0944             dbg.nospace() << qPrintable(QString::fromLatin1("(%1,%2)").arg(field.precision()).arg(field.scale()));
0945         else
0946             dbg.nospace() << qPrintable(QString::fromLatin1("(%1)").arg(field.precision()));
0947     }
0948     else if (field.type() == KDbField::Text && field.maxLength() > 0)
0949         dbg.space() << qPrintable(QString::fromLatin1("(%1)").arg(field.maxLength()));
0950 
0951     if (field.constraints() & KDbField::AutoInc)
0952         dbg.nospace() << " AUTOINC";
0953     if (field.constraints() & KDbField::Unique)
0954         dbg.nospace() << " UNIQUE";
0955     if (field.constraints() & KDbField::PrimaryKey)
0956         dbg.nospace() << " PKEY";
0957     if (field.constraints() & KDbField::ForeignKey)
0958         dbg.nospace() << " FKEY";
0959     if (field.constraints() & KDbField::NotNull)
0960         dbg.nospace() << " NOTNULL";
0961     if (field.constraints() & KDbField::NotEmpty)
0962         dbg.nospace() << " NOTEMPTY";
0963     if (!field.defaultValue().isNull()) {
0964         dbg.nospace() << qPrintable(QString::fromLatin1(" DEFAULT=[%1]")
0965                            .arg(QLatin1String(field.defaultValue().typeName())));
0966         dbg.nospace() << qPrintable(KDb::variantToString(field.defaultValue()));
0967     }
0968     if (field.isExpression()) {
0969         dbg.nospace() << " EXPRESSION=";
0970         dbg.nospace() << field.expression();
0971     }
0972     const KDbField::CustomPropertiesMap customProperties(field.customProperties());
0973     if (!customProperties.isEmpty()) {
0974         dbg.space() << qPrintable(QString::fromLatin1("CUSTOM PROPERTIES (%1): ").arg(customProperties.count()));
0975         bool first = true;
0976         for (KDbField::CustomPropertiesMap::ConstIterator it(customProperties.constBegin());
0977                 it != customProperties.constEnd(); ++it)
0978         {
0979             if (first)
0980                 first = false;
0981             else
0982                 dbg.nospace() << ',';
0983             dbg.space() << qPrintable(QString::fromLatin1("%1 = %2 (%3)")
0984                 .arg(QLatin1String(it.key()), it.value().toString(),
0985                      QLatin1String(it.value().typeName())));
0986         }
0987     }
0988 }
0989 
0990 KDB_EXPORT QDebug operator<<(QDebug dbg, const KDbField& field)
0991 {
0992     debug(dbg, field, KDbFieldDebugAddName);
0993     return dbg.space();
0994 }
0995 
0996 KDB_EXPORT QDebug operator<<(QDebug dbg, KDbField::Type type)
0997 {
0998     return dbg.space() << qPrintable(KDbField::typeString(type));
0999 }
1000 
1001 KDB_EXPORT QDebug operator<<(QDebug dbg, KDbField::TypeGroup typeGroup)
1002 {
1003     return dbg.space() << qPrintable(KDbField::typeGroupString(typeGroup));
1004 }
1005 
1006 bool KDbField::isExpression() const
1007 {
1008     return !d->expr.isNull();
1009 }
1010 
1011 KDbExpression KDbField::expression()
1012 {
1013     return d->expr;
1014 }
1015 
1016 const KDbExpression KDbField::expression() const
1017 {
1018     return d->expr;
1019 }
1020 
1021 void KDbField::setExpression(const KDbExpression& expr)
1022 {
1023     if (d->parent && !dynamic_cast<KDbQuerySchema*>(d->parent)) {
1024         kdbWarning() << "Cannot set expression if parent is set and it is not a query";
1025         return;
1026     }
1027     if (d->expr == expr) {
1028         return;
1029     }
1030     d->expr = expr;
1031 }
1032 
1033 QVariant KDbField::customProperty(const QByteArray& propertyName,
1034                                const QVariant& defaultValue) const
1035 {
1036     if (!d->customProperties) {
1037         return defaultValue;
1038     }
1039     return d->customProperties->value(propertyName, defaultValue);
1040 }
1041 
1042 void KDbField::setCustomProperty(const QByteArray& propertyName, const QVariant& value)
1043 {
1044     if (propertyName.isEmpty()) {
1045         return;
1046     }
1047     if (!d->customProperties) {
1048         d->customProperties = new CustomPropertiesMap();
1049     }
1050     d->customProperties->insert(propertyName, value);
1051 }
1052 
1053 KDbField::CustomPropertiesMap KDbField::customProperties() const
1054 {
1055     return d->customProperties ? *d->customProperties : CustomPropertiesMap();
1056 }