kexi

fieldlist.cpp

00001 /* This file is part of the KDE project
00002    Copyright (C) 2003-2007 Jaroslaw Staniek <js@iidea.pl>
00003 
00004    This library is free software; you can redistribute it and/or
00005    modify it under the terms of the GNU Library General Public
00006    License as published by the Free Software Foundation; either
00007    version 2 of the License, or (at your option) any later version.
00008 
00009    This library is distributed in the hope that it will be useful,
00010    but WITHOUT ANY WARRANTY; without even the implied warranty of
00011    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012    Library General Public License for more details.
00013 
00014    You should have received a copy of the GNU Library General Public License
00015    along with this library; see the file COPYING.LIB.  If not, write to
00016    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00017  * Boston, MA 02110-1301, USA.
00018 */
00019 
00020 #include <kexidb/fieldlist.h>
00021 #include <kexidb/object.h>
00022 
00023 #include <kdebug.h>
00024 
00025 #include <assert.h>
00026 
00027 using namespace KexiDB;
00028 
00029 FieldList::FieldList(bool owner)
00030  //reasonable sizes: TODO
00031  : m_fields_by_name(101, false)
00032 {
00033     m_fields.setAutoDelete( owner );
00034     m_fields_by_name.setAutoDelete( false );
00035     m_autoinc_fields = 0;
00036 }
00037 
00038 FieldList::FieldList(const FieldList& fl, bool deepCopyFields)
00039  : m_fields_by_name( fl.m_fields_by_name.size() )
00040 {
00041     m_fields.setAutoDelete( fl.m_fields.autoDelete() );
00042     m_fields_by_name.setAutoDelete( false );
00043     m_autoinc_fields = 0;
00044 
00045     if (deepCopyFields) {
00046         //deep copy for the fields
00047         for (Field::ListIterator f_it(fl.m_fields); f_it.current(); ++f_it) {
00048             Field *f = f_it.current()->copy();
00049             if (f_it.current()->m_parent == &fl)
00050                 f->m_parent = this;
00051             addField( f );
00052         }
00053     }
00054 }
00055 
00056 FieldList::~FieldList()
00057 {
00058     delete m_autoinc_fields;
00059 }
00060 
00061 void FieldList::clear()
00062 {
00063 //  m_name = QString::null;
00064     m_fields.clear();
00065     m_fields_by_name.clear();
00066     m_sqlFields = QString::null;
00067     delete m_autoinc_fields;
00068     m_autoinc_fields = 0;
00069 }
00070 
00071 FieldList& FieldList::insertField(uint index, KexiDB::Field *field)
00072 {
00073     assert(field);
00074     if (!field)
00075         return *this;
00076     if (index>m_fields.count()) {
00077         KexiDBFatal << "FieldList::insertField(): index (" << index << ") out of range" << endl;
00078         return *this;
00079     }
00080     if (!m_fields.insert(index, field))
00081         return *this;
00082     if (!field->name().isEmpty())
00083         m_fields_by_name.insert(field->name().lower(),field);
00084     m_sqlFields = QString::null;
00085     return *this;
00086 }
00087 
00088 void FieldList::renameField(const QString& oldName, const QString& newName)
00089 {
00090     renameField( m_fields_by_name[ oldName ], newName );
00091 }
00092 
00093 void FieldList::renameField(KexiDB::Field *field, const QString& newName)
00094 {
00095     if (!field || field != m_fields_by_name[ field->name() ]) {
00096         KexiDBFatal << "FieldList::renameField() no field found " 
00097             << (field ? QString("\"%1\"").arg(field->name()) : QString::null) << endl;
00098         return;
00099     }
00100     m_fields_by_name.take( field->name() );
00101     field->setName( newName );
00102     m_fields_by_name.insert( field->name(), field );
00103 }
00104 
00105 
00106 FieldList& FieldList::addField(KexiDB::Field *field)
00107 {
00108     return insertField(m_fields.count(), field);
00109 }
00110 
00111 void FieldList::removeField(KexiDB::Field *field)
00112 {
00113     assert(field);
00114     if (!field)
00115         return;
00116     m_fields_by_name.remove(field->name());
00117     m_fields.remove(field);
00118     m_sqlFields = QString::null;
00119 }
00120 
00121 Field* FieldList::field(const QString& name)
00122 {
00123     return m_fields_by_name[name];
00124 }
00125 
00126 QString FieldList::debugString()
00127 {
00128     QString dbg;
00129     dbg.reserve(512);
00130     Field::ListIterator it( m_fields );
00131     Field *field;
00132     bool start = true;
00133     if (!it.current())
00134         dbg = "<NO FIELDS>";
00135     for (; (field = it.current())!=0; ++it) {
00136         if (!start)
00137             dbg += ",\n";
00138         else
00139             start = false;
00140         dbg += "  ";
00141         dbg += field->debugString();
00142     }
00143     return dbg;
00144 }
00145 
00146 void FieldList::debug()
00147 {
00148     KexiDBDbg << debugString() << endl;
00149 }
00150 
00151 #define _ADD_FIELD(fname) \
00152 { \
00153     if (fname.isEmpty()) return fl; \
00154     f = m_fields_by_name[fname]; \
00155     if (!f) { KexiDBWarn << subListWarning1(fname) << endl; delete fl; return 0; } \
00156     fl->addField(f); \
00157 }
00158 
00159 static QString subListWarning1(const QString& fname) {
00160     return QString("FieldList::subList() could not find field \"%1\"").arg(fname);
00161 }
00162 
00163 FieldList* FieldList::subList(const QString& n1, const QString& n2, 
00164     const QString& n3, const QString& n4,
00165     const QString& n5, const QString& n6,
00166     const QString& n7, const QString& n8,
00167     const QString& n9, const QString& n10,
00168     const QString& n11, const QString& n12,
00169     const QString& n13, const QString& n14,
00170     const QString& n15, const QString& n16,
00171     const QString& n17, const QString& n18)
00172 {
00173     if (n1.isEmpty())
00174         return 0;
00175     Field *f;
00176     FieldList *fl = new FieldList(false);
00177     _ADD_FIELD(n1);
00178     _ADD_FIELD(n2);
00179     _ADD_FIELD(n3);
00180     _ADD_FIELD(n4);
00181     _ADD_FIELD(n5);
00182     _ADD_FIELD(n6);
00183     _ADD_FIELD(n7);
00184     _ADD_FIELD(n8);
00185     _ADD_FIELD(n9);
00186     _ADD_FIELD(n10);
00187     _ADD_FIELD(n11);
00188     _ADD_FIELD(n12);
00189     _ADD_FIELD(n13);
00190     _ADD_FIELD(n14);
00191     _ADD_FIELD(n15);
00192     _ADD_FIELD(n16);
00193     _ADD_FIELD(n17);
00194     _ADD_FIELD(n18);
00195     return fl;
00196 }
00197 
00198 FieldList* FieldList::subList(const QStringList& list)
00199 {
00200     Field *f;
00201     FieldList *fl = new FieldList(false);
00202     for(QStringList::ConstIterator it = list.constBegin(); it != list.constEnd(); ++it) {
00203         _ADD_FIELD( (*it) );
00204     }
00205     return fl;
00206 }
00207 
00208 FieldList* FieldList::subList(const QValueList<uint>& list)
00209 {
00210     Field *f;
00211     FieldList *fl = new FieldList(false);
00212     foreach(QValueList<uint>::ConstIterator, it, list) {
00213         f = field(*it);
00214         if (!f) {
00215             KexiDBWarn << QString("FieldList::subList() could not find field at position %1").arg(*it) << endl;
00216             delete fl;
00217             return 0;
00218         }
00219         fl->addField(f);
00220     }
00221     return fl;
00222 }
00223 
00224 QStringList FieldList::names() const
00225 {
00226     QStringList r;
00227 //  for (QDictIterator<Field> it(m_fields_by_name);it.current();++it) {
00228 //      r += it.currentKey().lower();
00229 //  }
00230     for (Field::ListIterator it(m_fields); it.current(); ++it) {
00231         r += it.current()->name().lower();
00232     }
00233     return r;
00234 }
00235 
00236 //static
00237 QString FieldList::sqlFieldsList(Field::List* list, Driver *driver, 
00238     const QString& separator, const QString& tableAlias, int drvEscaping)
00239 {
00240     if (!list)
00241         return QString::null;
00242     QString result;
00243     result.reserve(256);
00244     bool start = true;
00245     const QString tableAliasAndDot( tableAlias.isEmpty() ? QString::null : (tableAlias + ".") );
00246     for (Field::ListIterator it( *list ); it.current(); ++it) {
00247         if (!start)
00248             result += separator;
00249         else
00250             start = false;
00251         result += (tableAliasAndDot + driver->escapeIdentifier( it.current()->name(), drvEscaping ));
00252     }
00253     return result;
00254 }
00255 
00256 QString FieldList::sqlFieldsList(Driver *driver, 
00257     const QString& separator, const QString& tableAlias, int drvEscaping)
00258 {
00259     if (!m_sqlFields.isEmpty())
00260         return m_sqlFields;
00261 
00262     m_sqlFields = FieldList::sqlFieldsList( &m_fields, driver, separator, tableAlias, drvEscaping );
00263     return m_sqlFields;
00264 }
00265 
00266 Field::List* FieldList::autoIncrementFields()
00267 {
00268     if (!m_autoinc_fields) {
00269         m_autoinc_fields = new Field::List();
00270         Field *f;
00271         for (Field::ListIterator f_it(m_fields); (f = f_it.current()); ++f_it) {
00272             if (f->isAutoIncrement()) {
00273                 m_autoinc_fields->append( f_it.current() );
00274             }
00275         }
00276     }
00277     return m_autoinc_fields;
00278 }
KDE Home | KDE Accessibility Home | Description of Access Keys