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 }