00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "field.h"
00023 #include "connection.h"
00024 #include "driver.h"
00025 #include "expression.h"
00026 #include "utils.h"
00027
00028
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) {
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) {
00100
00101
00102
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::isQueryAsterisk() const
00272 {
00273 return dynamic_cast<QueryAsterisk const *>(this);
00274 }
00275
00276 bool Field::hasEmptyProperty(uint type)
00277 {
00278 return Field::isTextType(type) || type==BLOB;
00279 }
00280
00281 bool Field::isAutoIncrementAllowed(uint type)
00282 {
00283 return Field::isIntegerType(type);
00284 }
00285
00286 Field::TypeGroup Field::typeGroup(uint type)
00287 {
00288 if (Field::isTextType(type))
00289 return TextGroup;
00290 else if (Field::isIntegerType(type))
00291 return IntegerGroup;
00292 else if (Field::isFPNumericType(type))
00293 return FloatGroup;
00294 else if (type==Boolean)
00295 return BooleanGroup;
00296 else if (Field::isDateTimeType(type))
00297 return DateTimeGroup;
00298 else if (type==BLOB)
00299 return BLOBGroup;
00300
00301 return InvalidGroup;
00302 }
00303
00304 TableSchema*
00305 Field::table() const
00306 {
00307 return dynamic_cast<TableSchema*>(m_parent);
00308 }
00309
00310 void
00311 Field::setTable(TableSchema *tableSchema)
00312 {
00313 m_parent = tableSchema;
00314 }
00315
00316 QuerySchema*
00317 Field::query() const
00318 {
00319 return dynamic_cast<QuerySchema*>(m_parent);
00320 }
00321
00322 void
00323 Field::setQuery(QuerySchema *querySchema)
00324 {
00325 m_parent = querySchema;
00326 }
00327
00328 void
00329 Field::setName(const QString& n)
00330 {
00331 m_name = n.lower();
00332 }
00333
00334 void
00335 Field::setType(Type t)
00336 {
00337 if (m_expr) {
00338 KexiDBWarn << QString("Field::setType(%1)").arg(t)
00339 << " could not set type because the field has expression assigned!" << endl;
00340 return;
00341 }
00342 m_type = t;
00343 }
00344
00345 void
00346 Field::setConstraints(uint c)
00347 {
00348 m_constraints = c;
00349
00350 if (isPrimaryKey()) {
00351 setPrimaryKey(true);
00352 }
00353 if (isIndexed()) {
00354 setIndexed(true);
00355 }
00356 if (isAutoIncrement() && !isAutoIncrementAllowed()) {
00357 setAutoIncrement(false);
00358 }
00359 }
00360
00361 void
00362 Field::setLength(uint l)
00363 {
00364 if (type()!=Field::Text)
00365 return;
00366 m_length = l;
00367 }
00368
00369 void
00370 Field::setPrecision(uint p)
00371 {
00372 if (!isFPNumericType())
00373 return;
00374 m_precision = p;
00375 }
00376
00377 void
00378 Field::setScale(uint s)
00379 {
00380 if (!isFPNumericType())
00381 return;
00382 m_length = s;
00383 }
00384
00385 void
00386 Field::setVisibleDecimalPlaces(int p)
00387 {
00388 if (!KexiDB::supportsVisibleDecimalPlacesProperty(type()))
00389 return;
00390 m_visibleDecimalPlaces = p < 0 ? -1 : p;
00391 }
00392
00393 void
00394 Field::setUnsigned(bool u)
00395 {
00396 m_options |= Unsigned;
00397 m_options ^= (!u * Unsigned);
00398 }
00399
00400 void
00401 Field::setDefaultValue(const QVariant& def)
00402 {
00403 m_defaultValue = def;
00404 }
00405
00406 bool
00407 Field::setDefaultValue(const QCString& def)
00408 {
00409 if (def.isNull()) {
00410 m_defaultValue = QVariant();
00411 return true;
00412 }
00413
00414 bool ok;
00415 switch(type())
00416 {
00417 case Byte: {
00418 unsigned int v = def.toUInt(&ok);
00419 if (!ok || v > 255)
00420 m_defaultValue = QVariant();
00421 else
00422 m_defaultValue = QVariant(v);
00423 break;
00424 }case ShortInteger: {
00425 int v = def.toInt(&ok);
00426 if (!ok || (!(m_options & Unsigned) && (v < -32768 || v > 32767)) || ((m_options & Unsigned) && (v < 0 || v > 65535)))
00427 m_defaultValue = QVariant();
00428 else
00429 m_defaultValue = QVariant(v);
00430 break;
00431 }case Integer: {
00432 long v = def.toLong(&ok);
00433
00434 if (!ok || (!(m_options & Unsigned) && (-v > (int)0x07FFFFFFF || v > (int)(0x080000000-1))))
00435 m_defaultValue = QVariant();
00436 else
00437 m_defaultValue = QVariant((Q_LLONG)v);
00438 break;
00439 }case BigInteger: {
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451 break;
00452 }case Boolean: {
00453 unsigned short v = def.toUShort(&ok);
00454 if (!ok || v > 1)
00455 m_defaultValue = QVariant();
00456 else
00457 m_defaultValue = QVariant((bool)v);
00458 break;
00459 }case Date: {
00460 QDate date = QDate::fromString( def, Qt::ISODate );
00461 if (!date.isValid())
00462 m_defaultValue = QVariant();
00463 else
00464 m_defaultValue = QVariant(date);
00465 break;
00466 }case DateTime: {
00467 QDateTime dt = QDateTime::fromString( def, Qt::ISODate );
00468 if (!dt.isValid())
00469 m_defaultValue = QVariant();
00470 else
00471 m_defaultValue = QVariant(dt);
00472 break;
00473 }case Time: {
00474 QTime time = QTime::fromString( def, Qt::ISODate );
00475 if (!time.isValid())
00476 m_defaultValue = QVariant();
00477 else
00478 m_defaultValue = QVariant(time);
00479 break;
00480 }case Float: {
00481 float v = def.toFloat(&ok);
00482 if (!ok || ((m_options & Unsigned) && (v < 0.0)))
00483 m_defaultValue = QVariant();
00484 else
00485 m_defaultValue = QVariant(v);
00486 break;
00487 }case Double: {
00488 double v = def.toDouble(&ok);
00489 if (!ok || ((m_options & Unsigned) && (v < 0.0)))
00490 m_defaultValue = QVariant();
00491 else
00492 m_defaultValue = QVariant(v);
00493 break;
00494 }case Text: {
00495 if (def.isNull() || (def.length() > 255))
00496 m_defaultValue = QVariant();
00497 else
00498 m_defaultValue = QVariant((QString)def);
00499 break;
00500 }case LongText: {
00501 if (def.isNull())
00502 m_defaultValue = QVariant();
00503 else
00504 m_defaultValue = QVariant((QString)def);
00505 break;
00506 }case BLOB: {
00507
00508 if (def.isNull())
00509 m_defaultValue = QVariant();
00510 else
00511 m_defaultValue = QVariant(def);
00512 break;
00513 }default:
00514 m_defaultValue = QVariant();
00515 }
00516 return m_defaultValue.isNull();
00517 }
00518
00519 void
00520 Field::setAutoIncrement(bool a)
00521 {
00522 if (a && !isAutoIncrementAllowed())
00523 return;
00524 if (isAutoIncrement() != a)
00525 m_constraints = static_cast<Field::Constraints>(m_constraints ^ Field::AutoInc);
00526 }
00527
00528 void
00529 Field::setPrimaryKey(bool p)
00530 {
00531 if(isPrimaryKey() != p)
00532 m_constraints = static_cast<Field::Constraints>(m_constraints ^ Field::PrimaryKey);
00533 if (p) {
00534 setUniqueKey(true);
00535 setNotNull(true);
00536 setNotEmpty(true);
00537 setIndexed(true);
00538 }
00539 else {
00541 setAutoIncrement(false);
00542 }
00543 }
00544
00545 void
00546 Field::setUniqueKey(bool u)
00547 {
00548 if(isUniqueKey() != u) {
00549 m_constraints = static_cast<Field::Constraints>(m_constraints ^ Field::Unique);
00550 if (u)
00551 setNotNull(true);
00552 }
00553 }
00554
00555 void
00556 Field::setForeignKey(bool f)
00557 {
00558 if (isForeignKey() != f)
00559 m_constraints = static_cast<Field::Constraints>(m_constraints ^ Field::ForeignKey);
00560 }
00561
00562 void
00563 Field::setNotNull(bool n)
00564 {
00565 if (isNotNull() != n)
00566 m_constraints = static_cast<Field::Constraints>(m_constraints ^ Field::NotNull);
00567 }
00568
00569 void Field::setNotEmpty(bool n)
00570 {
00571 if (isNotEmpty() != n)
00572 m_constraints = static_cast<Field::Constraints>(m_constraints ^ Field::NotEmpty);
00573 }
00574
00575 void Field::setIndexed(bool s)
00576 {
00577 if (isIndexed() != s)
00578 m_constraints = static_cast<Field::Constraints>(m_constraints ^ Field::Indexed);
00579 if (!s) {
00580 setPrimaryKey(false);
00581 setUniqueKey(false);
00582 setNotNull(false);
00583 setNotEmpty(false);
00584 }
00585 }
00586
00587
00588 QString Field::debugString() const
00589 {
00590 KexiDB::Connection *conn = table() ? table()->connection() : 0;
00591 QString dbg = (m_name.isEmpty() ? "<NONAME> " : m_name + " ");
00592 if (m_options & Field::Unsigned)
00593 dbg += " UNSIGNED ";
00594 dbg += (conn && conn->driver()) ? conn->driver()->sqlTypeName(type()) : Driver::defaultSQLTypeName(type());
00595 if (isFPNumericType() && m_precision>0) {
00596 if (scale()>0)
00597 dbg += QString::fromLatin1("(%1,%2)").arg(m_precision).arg(scale());
00598 else
00599 dbg += QString::fromLatin1("(%1)").arg(m_precision);
00600 }
00601 else if (m_type==Field::Text && m_length>0)
00602 dbg += QString::fromLatin1("(%1)").arg(m_length);
00603 if (m_constraints & Field::AutoInc)
00604 dbg += " AUTOINC";
00605 if (m_constraints & Field::Unique)
00606 dbg += " UNIQUE";
00607 if (m_constraints & Field::PrimaryKey)
00608 dbg += " PKEY";
00609 if (m_constraints & Field::ForeignKey)
00610 dbg += " FKEY";
00611 if (m_constraints & Field::NotNull)
00612 dbg += " NOTNULL";
00613 if (m_constraints & Field::NotEmpty)
00614 dbg += " NOTEMPTY";
00615 if (!m_defaultValue.isNull())
00616 dbg += QString(" DEFAULT=[%1]").arg(m_defaultValue.typeName()) + KexiDB::variantToString(m_defaultValue);
00617 if (m_expr)
00618 dbg += " EXPRESSION=" + m_expr->debugString();
00619 if (m_customProperties && !m_customProperties->isEmpty()) {
00620 dbg += QString(" CUSTOM PROPERTIES (%1): ").arg(m_customProperties->count());
00621 bool first = true;
00622 foreach (CustomPropertiesMap::ConstIterator, it, *m_customProperties) {
00623 if (first)
00624 first = false;
00625 else
00626 dbg += ", ";
00627 dbg += QString("%1 = %2 (%3)").arg(it.key()).arg(it.data().toString()).arg(it.data().typeName());
00628 }
00629 }
00630 return dbg;
00631 }
00632
00633 void Field::debug()
00634 {
00635 KexiDBDbg << debugString() << endl;
00636 }
00637
00638 void Field::setExpression(KexiDB::BaseExpr *expr)
00639 {
00640 assert(!m_parent || dynamic_cast<QuerySchema*>(m_parent));
00641 if (m_expr==expr)
00642 return;
00643 if (m_expr) {
00644 delete m_expr;
00645 }
00646 m_expr = expr;
00647 }
00648
00649 QVariant Field::customProperty(const QCString& propertyName,
00650 const QVariant& defaultValue) const
00651 {
00652 if (!m_customProperties)
00653 return defaultValue;
00654 CustomPropertiesMap::ConstIterator it(m_customProperties->find(propertyName));
00655 if (it==m_customProperties->constEnd())
00656 return defaultValue;
00657 return it.data();
00658 }
00659
00660 void Field::setCustomProperty(const QCString& propertyName, const QVariant& value)
00661 {
00662 if (propertyName.isEmpty())
00663 return;
00664 if (!m_customProperties)
00665 m_customProperties = new CustomPropertiesMap();
00666 m_customProperties->insert(propertyName, value);
00667 }
00668
00669
00670 #define ADDTYPE(type, i18, str) this->at(Field::type) = i18; \
00671 this->at(Field::type+Field::LastType+1) = str; \
00672 str2num.insert(QString::fromLatin1(str).lower(), type)
00673 #define ADDGROUP(type, i18, str) this->at(Field::type) = i18; \
00674 this->at(Field::type+Field::LastTypeGroup+1) = str; \
00675 str2num.insert(QString::fromLatin1(str).lower(), type)
00676
00677 Field::FieldTypeNames::FieldTypeNames()
00678 : QValueVector<QString>()
00679 , m_initialized(false)
00680 {
00681 }
00682
00683 void Field::FieldTypeNames::init()
00684 {
00685 if (m_initialized)
00686 return;
00687 m_initialized = true;
00688 resize((Field::LastType + 1)*2);
00689
00690 ADDTYPE( InvalidType, i18n("Invalid Type"), "InvalidType" );
00691 ADDTYPE( Byte, i18n("Byte"), "Byte" );
00692 ADDTYPE( ShortInteger, i18n("Short Integer Number"), "ShortInteger" );
00693 ADDTYPE( Integer, i18n("Integer Number"), "Integer" );
00694 ADDTYPE( BigInteger, i18n("Big Integer Number"), "BigInteger" );
00695 ADDTYPE( Boolean, i18n("Yes/No Value"), "Boolean" );
00696 ADDTYPE( Date, i18n("Date"), "Date" );
00697 ADDTYPE( DateTime, i18n("Date and Time"), "DateTime" );
00698 ADDTYPE( Time, i18n("Time"), "Time" );
00699 ADDTYPE( Float, i18n("Single Precision Number"), "Float" );
00700 ADDTYPE( Double, i18n("Double Precision Number"), "Double" );
00701 ADDTYPE( Text, i18n("Text"), "Text" );
00702 ADDTYPE( LongText, i18n("Long Text"), "LongText" );
00703 ADDTYPE( BLOB, i18n("Object"), "BLOB" );
00704 }
00705
00706
00707
00708 Field::FieldTypeGroupNames::FieldTypeGroupNames()
00709 : QValueVector<QString>()
00710 , m_initialized(false)
00711 {
00712 }
00713
00714 void Field::FieldTypeGroupNames::init()
00715 {
00716 if (m_initialized)
00717 return;
00718 m_initialized = true;
00719 resize((Field::LastTypeGroup + 1)*2);
00720
00721 ADDGROUP( InvalidGroup, i18n("Invalid Group"), "InvalidGroup" );
00722 ADDGROUP( TextGroup, i18n("Text"), "TextGroup" );
00723 ADDGROUP( IntegerGroup, i18n("Integer Number"), "IntegerGroup" );
00724 ADDGROUP( FloatGroup, i18n("Floating Point Number"), "FloatGroup" );
00725 ADDGROUP( BooleanGroup, i18n("Yes/No"), "BooleanGroup" );
00726 ADDGROUP( DateTimeGroup, i18n("Date/Time"), "DateTimeGroup" );
00727 ADDGROUP( BLOBGroup, i18n("Object"), "BLOBGroup" );
00728 }
00729
00730
00731