kexi

field.cpp

00001 /* This file is part of the KDE project
00002    Copyright (C) 2002 Lucijan Busch <lucijan@gmx.at>
00003    Copyright (C) 2002 Joseph Wenninger <jowenn@kde.org>
00004    Copyright (C) 2003-2004 Jaroslaw Staniek <js@iidea.pl>
00005 
00006    This library is free software; you can redistribute it and/or
00007    modify it under the terms of the GNU Library General Public
00008    License as published by the Free Software Foundation; either
00009    version 2 of the License, or (at your option) any later version.
00010 
00011    This library is distributed in the hope that it will be useful,
00012    but WITHOUT ANY WARRANTY; without even the implied warranty of
00013    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014    Library General Public License for more details.
00015 
00016    You should have received a copy of the GNU Library General Public License
00017    along with this library; see the file COPYING.LIB.  If not, write to
00018    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00019  * Boston, MA 02110-1301, USA.
00020  */
00021 
00022 #include <kexidb/field.h>
00023 #include <kexidb/connection.h>
00024 #include <kexidb/driver.h>
00025 #include <kexidb/expression.h>
00026 
00027 // we use here i18n() but this depends on kde libs: TODO: add #ifdefs
00028 #include <kdebug.h>
00029 #include <klocale.h>
00030 
00031 #include <qdatetime.h>
00032 
00033 #include <assert.h>
00034 
00035 using namespace KexiDB;
00036 
00037 Field::FieldTypeNames Field::m_typeNames;
00038 Field::FieldTypeGroupNames Field::m_typeGroupNames;
00039 
00040 Field::Field()
00041 {
00042     init();
00043     setConstraints(NoConstraints);
00044 }
00045 
00046 
00047 Field::Field(TableSchema *tableSchema)
00048 {
00049     init();
00050     m_parent = tableSchema;
00051     m_order = tableSchema->fieldCount();
00052     setConstraints(NoConstraints);
00053 }
00054 
00055 Field::Field(QuerySchema *querySchema, BaseExpr* expr)
00056 {
00057     init();
00058     m_parent = querySchema;
00059     m_order = querySchema->fieldCount();
00060     setConstraints(NoConstraints);
00061     if (expr)
00062         setExpression(expr);
00063 }
00064 
00065 Field::Field(const QString& name, Type ctype,
00066  uint cconst, uint options, uint length, uint precision,
00067  QVariant defaultValue, const QString& caption, const QString& description,
00068  uint width)
00069     : m_parent(0)
00070     ,m_name(name.lower())
00071     ,m_length(length)
00072     ,m_precision(precision)
00073     ,m_options(options)
00074     ,m_defaultValue(defaultValue)
00075     ,m_order(-1)
00076     ,m_caption(caption)
00077     ,m_desc(description)
00078     ,m_width(width)
00079     ,m_expr(0)
00080     ,m_type(ctype)
00081 {
00082     setConstraints(cconst);
00083     if (m_length==0) {//0 means default length:
00084         if (m_type==Field::Text)
00085             m_length = defaultTextLength();
00086     }
00087 }
00088 
00090 Field::Field(const Field& f)
00091 {
00092     (*this) = f;
00093     if (f.m_expr) {//deep copy the expresion
00094 //TODO      m_expr = new BaseExpr(*f.m_expr);
00095 
00096 //      m_expr->m_field = this;
00097     } else
00098         m_expr = 0;
00099 }
00100 
00101 Field::~Field()
00102 {
00103     delete m_expr;
00104 }
00105 
00106 void Field::init()
00107 {
00108     m_parent = 0;
00109     m_name = "";
00110     m_type = InvalidType;
00111     m_length = 0;
00112     m_precision = 0;
00113     m_options = NoOptions;
00114     m_defaultValue = QVariant(QString::null);
00115     m_order = -1;
00116     m_width = 0;
00117     m_expr = 0;
00118 }
00119 
00120 Field::Type Field::type() const
00121 {
00122     if (m_expr)
00123         return m_expr->type();
00124     return m_type;
00125 }
00126 
00127 QVariant::Type Field::variantType(uint type)
00128 {
00129     switch(type)
00130     {
00131         case Byte:
00132         case ShortInteger:
00133         case Integer:
00134         case BigInteger:
00135 //      case AutoIncrement:
00136             return QVariant::Int;
00137         case Boolean:
00138             return QVariant::Bool;
00139         case Date:
00140             return QVariant::Date;
00141         case DateTime:
00142             return QVariant::DateTime;
00143         case Time:
00144             return QVariant::Time;
00145         case Float:
00146         case Double:
00147             return QVariant::Double;
00148         case Text:
00149         case LongText:
00150             return QVariant::String;
00151         case BLOB:
00152             return QVariant::ByteArray;
00153         default:
00154             return QVariant::Invalid;
00155     }
00156 
00157     return QVariant::Invalid;
00158 }
00159 
00160 QString Field::typeName(uint type)
00161 {
00162     m_typeNames.init();
00163     return (type <= LastType) ? m_typeNames.at(type) : QString::number(type);
00164 }
00165 
00166 QString Field::typeString(uint type)
00167 {
00168     m_typeNames.init();
00169     return (type <= LastType) ? m_typeNames.at((int)LastType+1 + type) : QString("Type%1").arg(type);
00170 }
00171 
00172 QString Field::typeGroupName(uint typeGroup)
00173 {
00174     m_typeGroupNames.init();
00175     return (typeGroup <= LastTypeGroup) ? m_typeGroupNames.at(typeGroup) : typeGroupString(typeGroup);
00176 }
00177 
00178 QString Field::typeGroupString(uint typeGroup)
00179 {
00180     m_typeGroupNames.init();
00181     return (typeGroup <= LastTypeGroup) ? m_typeGroupNames.at((int)LastTypeGroup+1 + typeGroup) : QString("TypeGroup%1").arg(typeGroup);
00182 }
00183 
00184 Field::Type Field::typeForString(const QString typeString)
00185 {
00186     m_typeNames.init();
00187     if (m_typeNames.str2num.find(typeString)==m_typeNames.str2num.end())
00188         return InvalidType;
00189     return m_typeNames.str2num[typeString];
00190 }
00191 
00192 Field::TypeGroup Field::typeGroupForString(const QString typeGroupString)
00193 {
00194     m_typeGroupNames.init();
00195     if (m_typeGroupNames.str2num.find(typeGroupString)==m_typeGroupNames.str2num.end())
00196         return InvalidGroup;
00197     return m_typeGroupNames.str2num[typeGroupString];
00198 }
00199 
00200 bool Field::isIntegerType( uint type )
00201 {
00202     switch (type) {
00203     case Field::Byte:
00204     case Field::ShortInteger:
00205     case Field::Integer:
00206     case Field::BigInteger:
00207         return true;
00208     default:;
00209     }
00210     return false;
00211 }
00212 
00213 bool Field::isNumericType( uint type )
00214 {
00215     switch (type) {
00216     case Field::Byte:
00217     case Field::ShortInteger:
00218     case Field::Integer:
00219     case Field::BigInteger:
00220     case Field::Float:
00221     case Field::Double:
00222         return true;
00223     default:;
00224     }
00225     return false;
00226 }
00227 
00228 bool Field::isFPNumericType( uint type )
00229 {
00230     return type==Field::Float || type==Field::Double;
00231 }
00232 
00233 bool Field::isDateTimeType(uint type)
00234 {
00235     switch (type) {
00236     case Field::Date:
00237     case Field::DateTime:
00238     case Field::Time:
00239         return true;
00240     default:;
00241     }
00242     return false;
00243 }
00244 
00245 bool Field::isTextType( uint type )
00246 {
00247     switch (type) {
00248     case Field::Text:
00249     case Field::LongText:
00250         return true;
00251     default:;
00252     }
00253     return false;
00254 }
00255 
00256 bool Field::hasEmptyProperty(uint type)
00257 {
00258     return Field::isTextType(type) || type==BLOB;
00259 }
00260 
00261 bool Field::isAutoIncrementAllowed(uint type)
00262 {
00263     return Field::isIntegerType(type);
00264 }
00265 
00266 Field::TypeGroup Field::typeGroup(uint type)
00267 {
00268     if (Field::isTextType(type))
00269         return TextGroup;
00270     else if (Field::isIntegerType(type))
00271         return IntegerGroup;
00272     else if (Field::isFPNumericType(type))
00273         return FloatGroup;
00274     else if (type==Boolean)
00275         return BooleanGroup;
00276     else if (Field::isDateTimeType(type))
00277         return DateTimeGroup;
00278     else if (type==BLOB)
00279         return BLOBGroup;
00280 
00281     return InvalidGroup; //unknown
00282 }
00283 
00284 TableSchema*
00285 Field::table() const
00286 {
00287     return dynamic_cast<TableSchema*>(m_parent);
00288 }
00289 
00290 void
00291 Field::setTable(TableSchema *tableSchema)
00292 {
00293     m_parent = tableSchema;
00294 }
00295 
00296 QuerySchema*
00297 Field::query() const
00298 {
00299     return dynamic_cast<QuerySchema*>(m_parent);
00300 }
00301 
00302 void
00303 Field::setQuery(QuerySchema *querySchema)
00304 {
00305     m_parent = querySchema;
00306 }
00307 
00308 void
00309 Field::setName(const QString& n)
00310 {
00311     m_name = n.lower();
00312 }
00313 
00314 void
00315 Field::setType(Type t)
00316 {
00317     if (m_expr) {
00318         KexiDBWarn << QString("Field::setType(%1)").arg(t) 
00319             << " could not set type because the field has expression assigned!" << endl;
00320         return;
00321     }
00322     m_type = t;
00323 }
00324 
00325 void
00326 Field::setConstraints(uint c)
00327 {
00328     m_constraints = c;
00329     //pkey must be unique notnull
00330     if (isPrimaryKey()) {
00331         setPrimaryKey(true);
00332     }
00333     if (isIndexed()) {
00334         setIndexed(true);
00335     }
00336     if (isAutoIncrement() && !isAutoIncrementAllowed()) {
00337         setAutoIncrement(false);
00338     }
00339 }
00340 
00341 void
00342 Field::setLength(uint l)
00343 {
00344     if (type()!=Field::Text)
00345         return;
00346     m_length = l;
00347 }
00348 
00349 void
00350 Field::setPrecision(uint p)
00351 {
00352     if (!isFPNumericType())
00353         return;
00354     m_precision = p;
00355 }
00356 
00357 void
00358 Field::setScale(uint s)
00359 {
00360     if (!isFPNumericType())
00361         return;
00362     m_length = s;
00363 }
00364 
00365 void
00366 Field::setUnsigned(bool u)
00367 {
00368     m_options |= Unsigned;
00369     m_options ^= (!u * Unsigned);
00370 }
00371 
00372 void
00373 Field::setDefaultValue(const QVariant& def)
00374 {
00375     m_defaultValue = def;
00376 }
00377 
00378 bool
00379 Field::setDefaultValue(const QCString& def)
00380 {
00381     if (def.isNull()) {
00382         m_defaultValue = QVariant();
00383         return true;
00384     }
00385     
00386     bool ok;
00387     switch(type())
00388     {
00389         case Byte: {
00390             unsigned int v = def.toUInt(&ok);
00391             if (!ok || v > 255)
00392                 m_defaultValue = QVariant();
00393             else
00394                 m_defaultValue = QVariant(v);
00395             break;
00396         }case ShortInteger: {
00397             int v = def.toInt(&ok);
00398             if (!ok || (!(m_options & Unsigned) && (v < -32768 || v > 32768)) || ((m_options & Unsigned) && (v < 0 || v > 65535)))
00399                 m_defaultValue = QVariant();
00400             else
00401                 m_defaultValue = QVariant(v);
00402             break;
00403         }case Integer: {//4 bytes
00404             long v = def.toLong(&ok);
00405 //js: FIXME         if (!ok || (!(m_options & Unsigned) && (-v > 0x080000000 || v > (0x080000000-1))) || ((m_options & Unsigned) && (v < 0 || v > 0x100000000)))
00406             if (!ok || (!(m_options & Unsigned) && (-v > (int)0x07FFFFFFF || v > (int)(0x080000000-1))))
00407                 m_defaultValue = QVariant();
00408             else
00409                 m_defaultValue = QVariant((Q_LLONG)v);
00410             break;
00411         }case BigInteger: {//8 bytes
00413 /*
00414             Q_LLONG long v = def.toLongLong(&ok);
00415 //TODO: 2-part decoding
00416             if (!ok || (!(m_options & Unsigned) && (-v > 0x080000000 || v > (0x080000000-1))))
00417                 m_defaultValue = QVariant();
00418             else
00419                 if (m_options & Unsigned)
00420                     m_defaultValue=QVariant((Q_ULLONG) v);
00421                 else
00422                     m_defaultValue = QVariant((Q_LLONG)v);*/
00423             break;
00424         }case Boolean: {
00425             unsigned short v = def.toUShort(&ok);
00426             if (!ok || v > 1)
00427                 m_defaultValue = QVariant();
00428             else
00429                 m_defaultValue = QVariant((bool)v);
00430             break;
00431         }case Date: {//YYYY-MM-DD
00432             QDate date = QDate::fromString( def, Qt::ISODate );
00433             if (!date.isValid())
00434                 m_defaultValue = QVariant();
00435             else
00436                 m_defaultValue = QVariant(date);
00437             break;
00438         }case DateTime: {//YYYY-MM-DDTHH:MM:SS
00439             QDateTime dt = QDateTime::fromString( def, Qt::ISODate );
00440             if (!dt.isValid())
00441                 m_defaultValue = QVariant();
00442             else
00443                 m_defaultValue = QVariant(dt);
00444             break;
00445         }case Time: {//HH:MM:SS
00446             QTime time = QTime::fromString( def, Qt::ISODate );
00447             if (!time.isValid())
00448                 m_defaultValue = QVariant();
00449             else
00450                 m_defaultValue = QVariant(time);
00451             break;
00452         }case Float: {
00453             float v = def.toFloat(&ok);
00454             if (!ok || ((m_options & Unsigned) && (v < 0.0)))
00455                 m_defaultValue = QVariant();
00456             else
00457                 m_defaultValue = QVariant(v);
00458             break;
00459         }case Double: {
00460             double v = def.toDouble(&ok);
00461             if (!ok || ((m_options & Unsigned) && (v < 0.0)))
00462                 m_defaultValue = QVariant();
00463             else
00464                 m_defaultValue = QVariant(v);
00465             break;
00466         }case Text: {
00467             if (def.isNull() || (def.length() > 255))
00468                 m_defaultValue = QVariant();
00469             else
00470                 m_defaultValue = QVariant((QString)def);
00471             break;
00472         }case LongText: {
00473             if (def.isNull())
00474                 m_defaultValue = QVariant();
00475             else
00476                 m_defaultValue = QVariant((QString)def);
00477             break;
00478         }case BLOB: {
00479 //TODO
00480             if (def.isNull())
00481                 m_defaultValue = QVariant();
00482             else
00483                 m_defaultValue = QVariant(def);
00484             break;
00485         }default:
00486             m_defaultValue = QVariant();
00487     }
00488     return m_defaultValue.isNull();
00489 }
00490 
00491 void
00492 Field::setAutoIncrement(bool a)
00493 {
00494     if (a && !isAutoIncrementAllowed())
00495         return;
00496     if (isAutoIncrement() != a)
00497         m_constraints = static_cast<Field::Constraints>(m_constraints ^ Field::AutoInc);
00498 }
00499 
00500 void
00501 Field::setPrimaryKey(bool p)
00502 {
00503     if(isPrimaryKey() != p)
00504         m_constraints = static_cast<Field::Constraints>(m_constraints ^ Field::PrimaryKey);
00505     if (p) {//also set implied constraints
00506         setUniqueKey(true);
00507         setNotNull(true);
00508         setNotEmpty(true);
00509         setIndexed(true);
00510     }
00511     else {
00513         setAutoIncrement(false);
00514     }
00515 }
00516 
00517 void
00518 Field::setUniqueKey(bool u)
00519 {
00520     if(isUniqueKey() != u) {
00521         m_constraints = static_cast<Field::Constraints>(m_constraints ^ Field::Unique);
00522         if (u)
00523             setNotNull(true);
00524     }
00525 }
00526 
00527 void
00528 Field::setForeignKey(bool f)
00529 {
00530     if (isForeignKey() != f)
00531         m_constraints = static_cast<Field::Constraints>(m_constraints ^ Field::ForeignKey);
00532 }
00533 
00534 void
00535 Field::setNotNull(bool n)
00536 {
00537     if (isNotNull() != n)
00538         m_constraints = static_cast<Field::Constraints>(m_constraints ^ Field::NotNull);
00539 }
00540 
00541 void Field::setNotEmpty(bool n)
00542 {
00543     if (isNotEmpty() != n)
00544         m_constraints = static_cast<Field::Constraints>(m_constraints ^ Field::NotEmpty);
00545 }
00546 
00547 void Field::setIndexed(bool s)
00548 {
00549     if (isIndexed() != s)
00550         m_constraints = static_cast<Field::Constraints>(m_constraints ^ Field::Indexed);
00551     if (!s) {//also set implied constraints
00552         setPrimaryKey(false);
00553         setUniqueKey(false);
00554         setNotNull(false);
00555         setNotEmpty(false);
00556     }
00557 }
00558 
00559 
00560 QString Field::debugString()
00561 {
00562     KexiDB::Connection *conn = table() ? table()->connection() : 0;
00563     QString dbg = (m_name.isEmpty() ? "<NONAME> " : m_name + " ");
00564     if (m_options & Field::Unsigned)
00565         dbg += " UNSIGNED ";
00566     dbg += (conn && conn->driver()) ? conn->driver()->sqlTypeName(type()) : Driver::defaultSQLTypeName(type());
00567     if (isFPNumericType() && m_precision>0) {
00568         if (scale()>0)
00569             dbg += QString::fromLatin1("(%1,%2)").arg(m_precision).arg(scale());
00570         else 
00571             dbg += QString::fromLatin1("(%1)").arg(m_precision);
00572     }
00573     else if (m_type==Field::Text && m_length>0)
00574         dbg += QString::fromLatin1("(%1)").arg(m_length);
00575     if (m_constraints & Field::AutoInc)
00576         dbg += " AUTOINC";
00577     if (m_constraints & Field::Unique)
00578         dbg += " UNIQUE";
00579     if (m_constraints & Field::PrimaryKey)
00580         dbg += " PKEY";
00581     if (m_constraints & Field::ForeignKey)
00582         dbg += " FKEY";
00583     if (m_constraints & Field::NotNull)
00584         dbg += " NOTNULL";
00585     if (m_constraints & Field::NotEmpty)
00586         dbg += " NOTEMPTY";
00587     if (m_expr)
00588         dbg += " EXPRESSION=" + m_expr->debugString();
00589     return dbg;
00590 }
00591 
00592 void Field::debug()
00593 {
00594     KexiDBDbg << debugString() << endl;
00595 }
00596 
00597 void Field::setExpression(KexiDB::BaseExpr *expr)
00598 {
00599     assert(!m_parent || dynamic_cast<QuerySchema*>(m_parent));
00600     if (m_expr==expr)
00601         return;
00602     if (m_expr) {
00603         delete m_expr;
00604     }
00605     m_expr = expr;
00606 }
00607 
00608 //-------------------------------------------------------
00609 #define ADDTYPE(type, i18, str) this->at(Field::type) = i18; \
00610     this->at(Field::type+Field::LastType+1) = str; \
00611     str2num.insert(str, type)
00612 #define ADDGROUP(type, i18, str) this->at(Field::type) = i18; \
00613     this->at(Field::type+Field::LastTypeGroup+1) = str; \
00614     str2num.insert(str, type)
00615 
00616 Field::FieldTypeNames::FieldTypeNames()
00617  : QValueVector<QString>()
00618  , m_initialized(false)
00619 {
00620 }
00621 
00622 void Field::FieldTypeNames::init()
00623 {
00624     if (m_initialized)
00625         return;
00626     m_initialized = true;
00627     resize((Field::LastType + 1)*2);
00628 
00629     ADDTYPE( InvalidType, i18n("Invalid Type"), "InvalidType" );
00630     ADDTYPE( Byte, i18n("Byte"), "Byte" );
00631     ADDTYPE( ShortInteger, i18n("Short Integer Number"), "ShortInteger" );
00632     ADDTYPE( Integer, i18n("Integer Number"), "Integer" );
00633     ADDTYPE( BigInteger, i18n("Big Integer Number"), "BigInteger" );
00634     ADDTYPE( Boolean, i18n("Yes/No Value"), "Boolean" );
00635     ADDTYPE( Date, i18n("Date"), "Date" );
00636     ADDTYPE( DateTime, i18n("Date and Time"), "DateTime" );
00637     ADDTYPE( Time, i18n("Time"), "Time" );
00638     ADDTYPE( Float, i18n("Single Precision Number"), "Float" );
00639     ADDTYPE( Double, i18n("Double Precision Number"), "Double" );
00640     ADDTYPE( Text, i18n("Text"), "Text" );
00641     ADDTYPE( LongText, i18n("Long Text"), "LongText" );
00642     ADDTYPE( BLOB, i18n("Object"), "BLOB" );
00643 }
00644 
00645 //-------------------------------------------------------
00646 
00647 Field::FieldTypeGroupNames::FieldTypeGroupNames()
00648  : QValueVector<QString>()
00649  , m_initialized(false)
00650 {
00651 }
00652 
00653 void Field::FieldTypeGroupNames::init()
00654 {
00655     if (m_initialized)
00656         return;
00657     m_initialized = true;
00658     resize((Field::LastTypeGroup + 1)*2);
00659 
00660     ADDGROUP( InvalidGroup, i18n("Invalid Group"), "InvalidGroup" );
00661     ADDGROUP( TextGroup, i18n("Text"), "TextGroup" );
00662     ADDGROUP( IntegerGroup, i18n("Integer Number"), "IntegerGroup" );
00663     ADDGROUP( FloatGroup, i18n("Floating Point Number"), "FloatGroup" );
00664     ADDGROUP( BooleanGroup, i18n("Yes/No"), "BooleanGroup" );
00665     ADDGROUP( DateTimeGroup, i18n("Date/Time"), "DateTimeGroup" );
00666     ADDGROUP( BLOBGroup, i18n("Object"), "BLOBGroup" );
00667 }
00668 
00669 //-------------------------------------------------------
00670 
KDE Home | KDE Accessibility Home | Description of Access Keys