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