1
/* This file is part of the KDE project
2
Copyright (C) 2002 Lucijan Busch <lucijan@gmx.at>
3
Copyright (C) 2002 Joseph Wenninger <jowenn@kde.org>
4
Copyright (C) 2003-2007 Jarosław Staniek <staniek@kde.org>
6
This library is free software; you can redistribute it and/or
7
modify it under the terms of the GNU Library General Public
8
License as published by the Free Software Foundation; either
9
version 2 of the License, or (at your option) any later version.
11
This library is distributed in the hope that it will be useful,
12
but WITHOUT ANY WARRANTY; without even the implied warranty of
13
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14
Library General Public License for more details.
16
You should have received a copy of the GNU Library General Public License
17
along with this library; see the file COPYING.LIB. If not, write to
18
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19
* Boston, MA 02110-1301, USA.
23
#include "connection.h"
25
#include "expression.h"
28
// we use here i18n() but this depends on kde libs: TODO: add #ifdefs
32
#include <qdatetime.h>
36
#include "kexidb_global.h"
38
using namespace KexiDB;
40
Field::FieldTypeNames Field::m_typeNames;
41
Field::FieldTypeGroupNames Field::m_typeGroupNames;
46
setConstraints(NoConstraints);
50
Field::Field(TableSchema *tableSchema)
53
m_parent = tableSchema;
54
m_order = tableSchema->fieldCount();
55
setConstraints(NoConstraints);
58
Field::Field(QuerySchema *querySchema, BaseExpr* expr)
61
m_parent = querySchema;
62
m_order = querySchema->fieldCount();
63
setConstraints(NoConstraints);
68
Field::Field(const QString& name, Type ctype,
69
uint cconst, uint options, uint length, uint precision,
70
QVariant defaultValue, const QString& caption, const QString& description,
73
, m_name(name.toLower())
75
, m_precision(precision)
76
, m_visibleDecimalPlaces(-1)
78
, m_defaultValue(defaultValue)
84
, m_customProperties(0)
87
setConstraints(cconst);
88
if (m_length == 0) {//0 means default length:
89
if (m_type == Field::Text)
90
m_length = defaultTextLength();
94
/*! Copy constructor. */
95
Field::Field(const Field& f)
98
if (f.m_customProperties)
99
m_customProperties = new CustomPropertiesMap(f.customProperties());
101
if (f.m_expr) {//deep copy the expression
102
//TODO m_expr = new BaseExpr(*f.m_expr);
104
// m_expr->m_field = this;
112
delete m_customProperties;
115
Field* Field::copy() const
117
return new Field(*this);
124
m_type = InvalidType;
127
m_visibleDecimalPlaces = -1;
128
m_options = NoOptions;
129
m_defaultValue = QVariant(QString());
133
m_customProperties = 0;
136
Field::Type Field::type() const
139
return m_expr->type();
143
QVariant::Type Field::variantType(uint type)
150
return QVariant::Int;
152
return QVariant::Bool;
154
return QVariant::Date;
156
return QVariant::DateTime;
158
return QVariant::Time;
161
return QVariant::Double;
164
return QVariant::String;
166
return QVariant::ByteArray;
168
return QVariant::Invalid;
171
return QVariant::Invalid;
174
QString Field::typeName(uint type)
177
return m_typeNames.value(type, QString::number(type));
180
QStringList Field::typeNames()
182
return m_typeNames.names;
185
QString Field::typeString(uint type)
188
return (type <= LastType) ? m_typeNames.at((int)LastType + 1 + type) : QString("Type%1").arg(type);
191
QString Field::typeGroupName(uint typeGroup)
193
m_typeGroupNames.init();
194
return (typeGroup <= LastTypeGroup) ? m_typeGroupNames.at(typeGroup) : typeGroupString(typeGroup);
197
QStringList Field::typeGroupNames()
199
return m_typeGroupNames.names;
202
QString Field::typeGroupString(uint typeGroup)
204
m_typeGroupNames.init();
205
return m_typeGroupNames.value((int)LastTypeGroup + 1 + typeGroup, QString("TypeGroup%1").arg(typeGroup));
208
Field::Type Field::typeForString(const QString& typeString)
211
return m_typeNames.str2num.value(typeString.toLower(), InvalidType);
214
Field::TypeGroup Field::typeGroupForString(const QString& typeGroupString)
216
m_typeGroupNames.init();
217
return m_typeGroupNames.str2num.value(typeGroupString.toLower(), InvalidGroup);
220
bool Field::isIntegerType(uint type)
224
case Field::ShortInteger:
226
case Field::BigInteger:
233
bool Field::isNumericType(uint type)
237
case Field::ShortInteger:
239
case Field::BigInteger:
248
bool Field::isFPNumericType(uint type)
250
return type == Field::Float || type == Field::Double;
253
bool Field::isDateTimeType(uint type)
257
case Field::DateTime:
265
bool Field::isTextType(uint type)
269
case Field::LongText:
276
bool Field::hasEmptyProperty(uint type)
278
return Field::isTextType(type) || type == BLOB;
281
bool Field::isAutoIncrementAllowed(uint type)
283
return Field::isIntegerType(type);
286
Field::TypeGroup Field::typeGroup(uint type)
288
if (Field::isTextType(type))
290
else if (Field::isIntegerType(type))
292
else if (Field::isFPNumericType(type))
294
else if (type == Boolean)
296
else if (Field::isDateTimeType(type))
297
return DateTimeGroup;
298
else if (type == BLOB)
301
return InvalidGroup; //unknown
307
return dynamic_cast<TableSchema*>(m_parent);
311
Field::setTable(TableSchema *tableSchema)
313
m_parent = tableSchema;
319
return dynamic_cast<QuerySchema*>(m_parent);
323
Field::setQuery(QuerySchema *querySchema)
325
m_parent = querySchema;
329
Field::setName(const QString& n)
331
m_name = n.toLower();
335
Field::setType(Type t)
338
KexiDBWarn << QString("Field::setType(%1)").arg(t)
339
<< " could not set type because the field has expression assigned!";
346
Field::setConstraints(uint c)
349
//pkey must be unique notnull
350
if (isPrimaryKey()) {
356
if (isAutoIncrement() && !isAutoIncrementAllowed()) {
357
setAutoIncrement(false);
362
Field::setLength(uint l)
364
if (type() != Field::Text)
370
Field::setPrecision(uint p)
372
if (!isFPNumericType())
378
Field::setScale(uint s)
380
if (!isFPNumericType())
386
Field::setVisibleDecimalPlaces(int p)
388
if (!KexiDB::supportsVisibleDecimalPlacesProperty(type()))
390
m_visibleDecimalPlaces = p < 0 ? -1 : p;
394
Field::setUnsigned(bool u)
396
m_options |= Unsigned;
397
m_options ^= (!u * Unsigned);
401
Field::setDefaultValue(const QVariant& def)
403
m_defaultValue = def;
407
Field::setDefaultValue(const QByteArray& def)
410
m_defaultValue = QVariant();
417
unsigned int v = def.toUInt(&ok);
419
m_defaultValue = QVariant();
421
m_defaultValue = QVariant(v);
425
int v = def.toInt(&ok);
426
if (!ok || (!(m_options & Unsigned) && (v < -32768 || v > 32767)) || ((m_options & Unsigned) && (v < 0 || v > 65535)))
427
m_defaultValue = QVariant();
429
m_defaultValue = QVariant(v);
432
case Integer: {//4 bytes
433
long v = def.toLong(&ok);
434
//js: FIXME if (!ok || (!(m_options & Unsigned) && (-v > 0x080000000 || v > (0x080000000-1))) || ((m_options & Unsigned) && (v < 0 || v > 0x100000000)))
435
if (!ok || (!(m_options & Unsigned) && (-v > (int)0x07FFFFFFF || v > (int)(0x080000000 - 1))))
436
m_defaultValue = QVariant();
438
m_defaultValue = QVariant((qint64)v);
441
case BigInteger: {//8 bytes
442
//! @todo BigInteger support
444
qint64 long v = def.toLongLong(&ok);
445
//TODO: 2-part decoding
446
if (!ok || (!(m_options & Unsigned) && (-v > 0x080000000 || v > (0x080000000-1))))
447
m_defaultValue = QVariant();
449
if (m_options & Unsigned)
450
m_defaultValue=QVariant((quint64) v);
452
m_defaultValue = QVariant((qint64)v);*/
456
unsigned short v = def.toUShort(&ok);
458
m_defaultValue = QVariant();
460
m_defaultValue = QVariant((bool)v);
463
case Date: {//YYYY-MM-DD
464
QDate date = QDate::fromString(def, Qt::ISODate);
466
m_defaultValue = QVariant();
468
m_defaultValue = QVariant(date);
471
case DateTime: {//YYYY-MM-DDTHH:MM:SS
472
QDateTime dt = QDateTime::fromString(def, Qt::ISODate);
474
m_defaultValue = QVariant();
476
m_defaultValue = QVariant(dt);
479
case Time: {//HH:MM:SS
480
QTime time = QTime::fromString(def, Qt::ISODate);
482
m_defaultValue = QVariant();
484
m_defaultValue = QVariant(time);
488
float v = def.toFloat(&ok);
489
if (!ok || ((m_options & Unsigned) && (v < 0.0)))
490
m_defaultValue = QVariant();
492
m_defaultValue = QVariant(v);
496
double v = def.toDouble(&ok);
497
if (!ok || ((m_options & Unsigned) && (v < 0.0)))
498
m_defaultValue = QVariant();
500
m_defaultValue = QVariant(v);
504
if (def.isNull() || (def.length() > 255))
505
m_defaultValue = QVariant();
507
m_defaultValue = QVariant((QString)def);
512
m_defaultValue = QVariant();
514
m_defaultValue = QVariant((QString)def);
520
m_defaultValue = QVariant();
522
m_defaultValue = QVariant(def);
526
m_defaultValue = QVariant();
528
return m_defaultValue.isNull();
532
Field::setAutoIncrement(bool a)
534
if (a && !isAutoIncrementAllowed())
536
if (isAutoIncrement() != a)
537
m_constraints = static_cast<Field::Constraints>(m_constraints ^ Field::AutoInc);
541
Field::setPrimaryKey(bool p)
543
if (isPrimaryKey() != p)
544
m_constraints = static_cast<Field::Constraints>(m_constraints ^ Field::PrimaryKey);
545
if (p) {//also set implied constraints
551
//! \todo is this ok for all engines?
552
setAutoIncrement(false);
557
Field::setUniqueKey(bool u)
559
if (isUniqueKey() != u) {
560
m_constraints = static_cast<Field::Constraints>(m_constraints ^ Field::Unique);
561
if (u) { //also set implied constraints
569
Field::setForeignKey(bool f)
571
if (isForeignKey() != f)
572
m_constraints = static_cast<Field::Constraints>(m_constraints ^ Field::ForeignKey);
576
Field::setNotNull(bool n)
578
if (isNotNull() != n)
579
m_constraints = static_cast<Field::Constraints>(m_constraints ^ Field::NotNull);
582
void Field::setNotEmpty(bool n)
584
if (isNotEmpty() != n)
585
m_constraints = static_cast<Field::Constraints>(m_constraints ^ Field::NotEmpty);
588
void Field::setIndexed(bool s)
590
if (isIndexed() != s)
591
m_constraints = static_cast<Field::Constraints>(m_constraints ^ Field::Indexed);
592
if (!s) {//also set implied constraints
593
setPrimaryKey(false);
601
QString Field::debugString() const
603
KexiDB::Connection *conn = table() ? table()->connection() : 0;
604
QString dbg = (m_name.isEmpty() ? "<NONAME> " : m_name + " ");
605
if (m_options & Field::Unsigned)
607
dbg += (conn && conn->driver()) ? conn->driver()->sqlTypeName(type()) : Driver::defaultSQLTypeName(type());
608
if (isFPNumericType() && m_precision > 0) {
610
dbg += QString::fromLatin1("(%1,%2)").arg(m_precision).arg(scale());
612
dbg += QString::fromLatin1("(%1)").arg(m_precision);
613
} else if (m_type == Field::Text && m_length > 0)
614
dbg += QString::fromLatin1("(%1)").arg(m_length);
615
if (m_constraints & Field::AutoInc)
617
if (m_constraints & Field::Unique)
619
if (m_constraints & Field::PrimaryKey)
621
if (m_constraints & Field::ForeignKey)
623
if (m_constraints & Field::NotNull)
625
if (m_constraints & Field::NotEmpty)
627
if (!m_defaultValue.isNull())
628
dbg += QString(" DEFAULT=[%1]").arg(m_defaultValue.typeName()) + KexiDB::variantToString(m_defaultValue);
630
dbg += " EXPRESSION=" + m_expr->debugString();
631
if (m_customProperties && !m_customProperties->isEmpty()) {
632
dbg += QString(" CUSTOM PROPERTIES (%1): ").arg(m_customProperties->count());
634
for (CustomPropertiesMap::ConstIterator it(m_customProperties->constBegin());
635
it != m_customProperties->constEnd(); ++it) {
640
dbg += QString("%1 = %2 (%3)").arg(QString(it.key())).arg(it.value().toString())
641
.arg(it.value().typeName());
649
KexiDBDbg << debugString();
652
void Field::setExpression(KexiDB::BaseExpr *expr)
654
assert(!m_parent || dynamic_cast<QuerySchema*>(m_parent));
663
QVariant Field::customProperty(const QByteArray& propertyName,
664
const QVariant& defaultValue) const
666
if (!m_customProperties)
668
return m_customProperties->value(propertyName, defaultValue);
671
void Field::setCustomProperty(const QByteArray& propertyName, const QVariant& value)
673
if (propertyName.isEmpty())
675
if (!m_customProperties)
676
m_customProperties = new CustomPropertiesMap();
677
m_customProperties->insert(propertyName, value);
680
//-------------------------------------------------------
681
#define ADDTYPE(type, i18, str) \
682
(*this)[Field::type] = i18; \
683
(*this)[Field::type+Field::LastType+1] = str; \
684
str2num[ QString::fromLatin1(str).toLower() ] = type; \
686
#define ADDGROUP(type, i18, str) \
687
(*this)[Field::type] = i18; \
688
(*this)[Field::type+Field::LastTypeGroup+1] = str; \
689
str2num[ QString::fromLatin1(str).toLower() ] = type; \
692
Field::FieldTypeNames::FieldTypeNames()
694
, m_initialized(false)
698
void Field::FieldTypeNames::init()
702
m_initialized = true;
703
resize((Field::LastType + 1)*2);
705
ADDTYPE(InvalidType, i18n("Invalid Type"), "InvalidType");
706
ADDTYPE(Byte, i18n("Byte"), "Byte");
707
ADDTYPE(ShortInteger, i18n("Short Integer Number"), "ShortInteger");
708
ADDTYPE(Integer, i18n("Integer Number"), "Integer");
709
ADDTYPE(BigInteger, i18n("Big Integer Number"), "BigInteger");
710
ADDTYPE(Boolean, i18n("Yes/No Value"), "Boolean");
711
ADDTYPE(Date, i18n("Date"), "Date");
712
ADDTYPE(DateTime, i18n("Date and Time"), "DateTime");
713
ADDTYPE(Time, i18n("Time"), "Time");
714
ADDTYPE(Float, i18n("Single Precision Number"), "Float");
715
ADDTYPE(Double, i18n("Double Precision Number"), "Double");
716
ADDTYPE(Text, i18n("Text"), "Text");
717
ADDTYPE(LongText, i18n("Long Text"), "LongText");
718
ADDTYPE(BLOB, i18n("Object"), "BLOB");
721
//-------------------------------------------------------
723
Field::FieldTypeGroupNames::FieldTypeGroupNames()
725
, m_initialized(false)
729
void Field::FieldTypeGroupNames::init()
733
m_initialized = true;
734
resize((Field::LastTypeGroup + 1)*2);
736
ADDGROUP(InvalidGroup, i18n("Invalid Group"), "InvalidGroup");
737
ADDGROUP(TextGroup, i18n("Text"), "TextGroup");
738
ADDGROUP(IntegerGroup, i18n("Integer Number"), "IntegerGroup");
739
ADDGROUP(FloatGroup, i18n("Floating Point Number"), "FloatGroup");
740
ADDGROUP(BooleanGroup, i18n("Yes/No"), "BooleanGroup");
741
ADDGROUP(DateTimeGroup, i18n("Date/Time"), "DateTimeGroup");
742
ADDGROUP(BLOBGroup, i18n("Object"), "BLOBGroup");
745
//-------------------------------------------------------