File indexing completed on 2024-11-03 07:28:54
0001 /* This file is part of the KDE project 0002 Copyright (C) 2003-2016 Jarosław Staniek <staniek@kde.org> 0003 0004 This library is free software; you can redistribute it and/or 0005 modify it under the terms of the GNU Library General Public 0006 License as published by the Free Software Foundation; either 0007 version 2 of the License, or (at your option) any later version. 0008 0009 This library is distributed in the hope that it will be useful, 0010 but WITHOUT ANY WARRANTY; without even the implied warranty of 0011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0012 Library General Public License for more details. 0013 0014 You should have received a copy of the GNU Library General Public License 0015 along with this library; see the file COPYING.LIB. If not, write to 0016 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 0017 * Boston, MA 02110-1301, USA. 0018 */ 0019 0020 #include "KDbConnection.h" 0021 #include "KDbDriver.h" 0022 #include "KDbIndexSchema.h" 0023 #include "KDbRelationship.h" 0024 #include "KDbTableSchema.h" 0025 #include "kdb_debug.h" 0026 0027 class Q_DECL_HIDDEN KDbIndexSchema::Private 0028 { 0029 public: 0030 Private() 0031 : tableSchema(nullptr) 0032 , isPrimary(false) 0033 , isUnique(false) 0034 , isAutoGenerated(false) 0035 , isForeignKey(false) 0036 { 0037 } 0038 ~Private() 0039 { 0040 /* It's a list of relationships to the table (of this index), i.e. any such 0041 * relationship in which the table is at 'master' side will be cleared and 0042 * relationships will be destroyed. 0043 * So all these relationships must be detached from details-side, corresponding 0044 * indices. 0045 */ 0046 for (KDbRelationship* rel : qAsConst(masterOwnedRelationships)) { 0047 if (rel->detailsIndex()) { 0048 rel->detailsIndex()->detachRelationship(rel); 0049 } 0050 } 0051 qDeleteAll(masterOwnedRelationships); 0052 } 0053 0054 //! table on that index is built 0055 KDbTableSchema *tableSchema; 0056 0057 /*! A set of master relationships for the table (of this index), 0058 this index is a master key for these relationships 0059 and therefore - owner of these */ 0060 QSet<KDbRelationship*> masterOwnedRelationships; 0061 0062 /*! A list of master relationships that are not owned by this schema */ 0063 QList<const KDbRelationship*> masterRelationships; 0064 0065 /*! A list of relationships to table (of this index) */ 0066 QList<const KDbRelationship*> detailsRelationships; 0067 0068 bool isPrimary; 0069 bool isUnique; 0070 bool isAutoGenerated; 0071 bool isForeignKey; 0072 }; 0073 0074 KDbIndexSchema::KDbIndexSchema() 0075 : KDbFieldList(false)//fields are not owned by KDbIndexSchema object 0076 , KDbObject(KDb::IndexObjectType) 0077 , d(new Private) 0078 { 0079 } 0080 0081 KDbIndexSchema::KDbIndexSchema(const KDbIndexSchema& index, KDbTableSchema* parentTable) 0082 : KDbFieldList(false)//fields are not owned by KDbIndexSchema object 0083 , KDbObject(static_cast<const KDbObject&>(index)) 0084 , d(new Private) 0085 { 0086 d->isPrimary = index.isPrimaryKey(); 0087 d->isUnique = index.isUnique(); 0088 d->isAutoGenerated = index.isAutoGenerated(); 0089 d->isForeignKey = index.isForeignKey(); 0090 // deep copy the field references 0091 for(KDbField *f : *index.fields()) { 0092 KDbField *parentTableField = parentTable->field(f->name()); 0093 if (!parentTableField) { 0094 kdbWarning() << "Could not find field" << f->name() << "in parentTable. Empty index will be created!"; 0095 KDbFieldList::clear(); 0096 break; 0097 } 0098 (void)KDbFieldList::addField(f); 0099 } 0100 0101 //! @todo copy relationships! 0102 // Reference::List m_refs_to; //! list of references to table (of this index) 0103 // Reference::List m_refs_from; //! list of references from the table (of this index), 0104 // //! this index is foreign key for these references 0105 // //! and therefore - owner of these 0106 } 0107 0108 KDbIndexSchema::~KDbIndexSchema() 0109 { 0110 delete d; 0111 } 0112 0113 void KDbIndexSchema::setTable(KDbTableSchema *table) 0114 { 0115 if (this->table()) { 0116 kdbWarning() << "Table is already assigned to this index"; 0117 return; 0118 } 0119 if (table) { 0120 d->tableSchema = table; 0121 } 0122 } 0123 0124 bool KDbIndexSchema::addField(KDbField *field) 0125 { 0126 if (!d->tableSchema || field->table() != d->tableSchema) { 0127 kdbWarning() << (field ? field->name() : QString()) 0128 << "WARNING: field does not belong to the same table" 0129 << (field && field->table() ? field->table()->name() : QString()) 0130 << "as index!"; 0131 return false; 0132 } 0133 return KDbFieldList::addField(field); 0134 } 0135 0136 const KDbTableSchema* KDbIndexSchema::table() const 0137 { 0138 return d->tableSchema; 0139 } 0140 0141 KDbTableSchema* KDbIndexSchema::table() 0142 { 0143 return d->tableSchema; 0144 } 0145 0146 QList<const KDbRelationship*> KDbIndexSchema::masterRelationships() const 0147 { 0148 return d->masterRelationships; 0149 } 0150 0151 QList<const KDbRelationship*> KDbIndexSchema::detailsRelationships() const 0152 { 0153 return d->detailsRelationships; 0154 } 0155 0156 bool KDbIndexSchema::isAutoGenerated() const 0157 { 0158 return d->isAutoGenerated; 0159 } 0160 0161 void KDbIndexSchema::setAutoGenerated(bool set) 0162 { 0163 d->isAutoGenerated = set; 0164 } 0165 0166 bool KDbIndexSchema::isPrimaryKey() const 0167 { 0168 return d->isPrimary; 0169 } 0170 0171 void KDbIndexSchema::setPrimaryKey(bool set) 0172 { 0173 d->isPrimary = set; 0174 if (d->isPrimary) 0175 d->isUnique = true; 0176 } 0177 0178 bool KDbIndexSchema::isUnique() const 0179 { 0180 return d->isUnique; 0181 } 0182 0183 void KDbIndexSchema::setUnique(bool set) 0184 { 0185 d->isUnique = set; 0186 if (!d->isUnique) 0187 d->isPrimary = false; 0188 } 0189 0190 bool KDbIndexSchema::isForeignKey() const 0191 { 0192 return d->isForeignKey; 0193 } 0194 0195 void KDbIndexSchema::setForeignKey(bool set) 0196 { 0197 d->isForeignKey = set; 0198 if (d->isForeignKey) { 0199 setUnique(false); 0200 } 0201 if (fieldCount() == 1) { 0202 fields()->first()->setForeignKey(true); 0203 } 0204 } 0205 0206 KDB_EXPORT QDebug operator<<(QDebug dbg, const KDbIndexSchema& index) 0207 { 0208 dbg.nospace() << QLatin1String("INDEX"); 0209 dbg.space() << static_cast<const KDbObject&>(index) << '\n'; 0210 dbg.space() << (index.isForeignKey() ? "FOREIGN KEY" : ""); 0211 dbg.space() << (index.isAutoGenerated() ? "AUTOGENERATED" : ""); 0212 dbg.space() << (index.isPrimaryKey() ? "PRIMARY" : ""); 0213 dbg.space() << ((!index.isPrimaryKey()) && index.isUnique() ? "UNIQUE" : ""); 0214 dbg.space() << static_cast<const KDbFieldList&>(index); 0215 return dbg.space(); 0216 } 0217 0218 void KDbIndexSchema::attachRelationship(KDbRelationship *rel) 0219 { 0220 attachRelationship(rel, true); 0221 } 0222 0223 void KDbIndexSchema::attachRelationship(KDbRelationship *rel, bool ownedByMaster) 0224 { 0225 if (!rel) 0226 return; 0227 if (rel->masterIndex() == this) { 0228 if (ownedByMaster) { 0229 if (!d->masterOwnedRelationships.contains(rel)) { 0230 d->masterOwnedRelationships.insert(rel); 0231 } 0232 } else {//not owned 0233 if (!d->masterRelationships.contains(rel)) { 0234 d->masterRelationships.append(rel); 0235 } 0236 } 0237 } else if (rel->detailsIndex() == this) { 0238 if (!d->detailsRelationships.contains(rel)) { 0239 d->detailsRelationships.append(rel); 0240 } 0241 } 0242 } 0243 0244 void KDbIndexSchema::detachRelationship(KDbRelationship *rel) 0245 { 0246 if (!rel) 0247 return; 0248 d->masterOwnedRelationships.remove(rel); //for sanity 0249 d->masterRelationships.takeAt(d->masterRelationships.indexOf(rel)); //for sanity 0250 d->detailsRelationships.takeAt(d->detailsRelationships.indexOf(rel)); //for sanity 0251 }