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::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;
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
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: {
00427 long v = def.toLong(&ok);
00428
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: {
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445
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: {
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: {
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: {
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
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) {
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) {
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