kexi
relationship.cpp00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include <kexidb/relationship.h>
00021
00022 #include <kexidb/indexschema.h>
00023 #include <kexidb/tableschema.h>
00024 #include <kexidb/queryschema.h>
00025 #include <kexidb/driver.h>
00026
00027 #include <kdebug.h>
00028
00029 using namespace KexiDB;
00030
00031 Relationship::Relationship()
00032 : m_masterIndex(0)
00033 , m_detailsIndex(0)
00034 , m_masterIndexOwned(false)
00035 , m_detailsIndexOwned(false)
00036 {
00037 m_pairs.setAutoDelete(true);
00038 }
00039
00040 Relationship::Relationship(IndexSchema* masterIndex, IndexSchema* detailsIndex)
00041 : m_masterIndex(0)
00042 , m_detailsIndex(0)
00043 , m_masterIndexOwned(false)
00044 , m_detailsIndexOwned(false)
00045 {
00046 m_pairs.setAutoDelete(true);
00047 setIndices(masterIndex, detailsIndex);
00048 }
00049
00050 Relationship::Relationship( QuerySchema *query, Field *field1, Field *field2 )
00051 : m_masterIndex(0)
00052 , m_detailsIndex(0)
00053 , m_masterIndexOwned(false)
00054 , m_detailsIndexOwned(false)
00055 {
00056 m_pairs.setAutoDelete(true);
00057 createIndices( query, field1, field2 );
00058 }
00059
00060 Relationship::~Relationship()
00061 {
00062 if (m_masterIndexOwned)
00063 delete m_masterIndex;
00064 if (m_detailsIndexOwned)
00065 delete m_detailsIndex;
00066 }
00067
00068 void Relationship::createIndices( QuerySchema *query, Field *field1, Field *field2 )
00069 {
00070 if (!field1 || !field2 || !query) {
00071 KexiDBWarn << "Relationship::addRelationship(): !masterField || !detailsField || !query" << endl;
00072 return;
00073 }
00074 if (field1->isQueryAsterisk() || field2->isQueryAsterisk()) {
00075 KexiDBWarn << "Relationship::addRelationship(): relationship's fields cannot be asterisks" << endl;
00076 return;
00077 }
00078 if (field1->table() == field2->table()) {
00079 KexiDBWarn << "Relationship::addRelationship(): fields cannot belong to the same table" << endl;
00080 return;
00081 }
00082
00083 if (!query->contains(field1->table()) || !query->contains(field2->table())) {
00084 KexiDBWarn << "Relationship::addRelationship(): fields do not belong to this query" << endl;
00085 return;
00086 }
00087
00088
00089
00090 Field *masterField = 0, *detailsField = 0;
00091 bool p1 = field1->isPrimaryKey(), p2 = field2->isPrimaryKey();
00092 if (p1 && p2) {
00093
00094 masterField = field1;
00095 m_masterIndex = masterField->table()->primaryKey();
00096 detailsField = field2;
00097 m_detailsIndex = detailsField->table()->primaryKey();
00098 }
00099 else if (!p1 && p2) {
00100
00101 Field *tmp = field1;
00102 field1 = field2;
00103 field2 = tmp;
00104 p1 = !p1;
00105 p2 = !p2;
00106 }
00107
00108 if (p1 && !p2) {
00109
00110 masterField = field1;
00111 m_masterIndex = masterField->table()->primaryKey();
00112 detailsField = field2;
00113
00114
00115 m_detailsIndex = new IndexSchema(detailsField->table());
00116 m_detailsIndexOwned = true;
00117 m_detailsIndex->addField(detailsField);
00118 m_detailsIndex->setForeignKey(true);
00119 }
00120 else if (!p1 && !p2) {
00121 masterField = field1;
00122 m_masterIndex = new IndexSchema(masterField->table());
00123 m_masterIndexOwned = true;
00124 m_masterIndex->addField(masterField);
00125 m_masterIndex->setForeignKey(true);
00126
00127 detailsField = field2;
00128 m_detailsIndex = new IndexSchema(detailsField->table());
00129 m_detailsIndexOwned = true;
00130 m_detailsIndex->addField(detailsField);
00131 m_detailsIndex->setForeignKey(true);
00132 }
00133
00134 if (!m_masterIndex || !m_detailsIndex)
00135 return;
00136
00137 setIndices(m_masterIndex, m_detailsIndex, false);
00138 }
00139
00140 TableSchema* Relationship::masterTable() const
00141 {
00142 return m_masterIndex ? m_masterIndex->table() : 0;
00143 }
00144
00145 TableSchema* Relationship::detailsTable() const
00146 {
00147 return m_detailsIndex ? m_detailsIndex->table() : 0;
00148 }
00149
00150 void Relationship::setIndices(IndexSchema* masterIndex, IndexSchema* detailsIndex)
00151 {
00152 setIndices(masterIndex, detailsIndex, true);
00153 }
00154
00155 void Relationship::setIndices(IndexSchema* masterIndex, IndexSchema* detailsIndex, bool ownedByMaster)
00156 {
00157 m_masterIndex = 0;
00158 m_detailsIndex = 0;
00159 m_pairs.clear();
00160 if (!masterIndex || !detailsIndex || !masterIndex->table() || !detailsIndex->table()
00161 || masterIndex->table()==detailsIndex->table() || masterIndex->fieldCount()!=detailsIndex->fieldCount())
00162 return;
00163 Field::ListIterator it1(*masterIndex->fields());
00164 Field::ListIterator it2(*detailsIndex->fields());
00165 for (;it1.current() && it1.current(); ++it1, ++it2) {
00166 Field *f1 = it1.current();
00167 Field *f2 = it2.current();
00168
00169 if (f1->type()!=f1->type() && f1->isIntegerType()!=f2->isIntegerType() && f1->isTextType()!=f2->isTextType()) {
00170 KexiDBWarn << "Relationship::setIndices(INDEX on '"<<masterIndex->table()->name()
00171 <<"',INDEX on "<<detailsIndex->table()->name()<<"): !equal field types: "
00172 <<Driver::defaultSQLTypeName(f1->type())<<" "<<f1->name()<<", "
00173 <<Driver::defaultSQLTypeName(f2->type())<<" "<<f2->name() <<endl;
00174 m_pairs.clear();
00175 return;
00176 }
00177 #if 0 //too STRICT!
00178 if ((f1->isUnsigned() && !f2->isUnsigned()) || (!f1->isUnsigned() && f1->isUnsigned())) {
00179 KexiDBWarn << "Relationship::setIndices(INDEX on '"<<masterIndex->table()->name()
00180 <<"',INDEX on "<<detailsIndex->table()->name()<<"): !equal signedness of field types: "
00181 <<Driver::defaultSQLTypeName(f1->type())<<" "<<f1->name()<<", "
00182 <<Driver::defaultSQLTypeName(f2->type())<<" "<<f2->name() <<endl;
00183 m_pairs.clear();
00184 return;
00185 }
00186 #endif
00187 m_pairs.append( new Field::Pair(f1,f2) );
00188 }
00189
00190 if (m_masterIndex) {
00191 m_masterIndex->detachRelationship(this);
00192 }
00193 if (m_detailsIndex) {
00194 m_detailsIndex->detachRelationship(this);
00195 }
00196 m_masterIndex = masterIndex;
00197 m_detailsIndex = detailsIndex;
00198 m_masterIndex->attachRelationship(this, ownedByMaster);
00199 m_detailsIndex->attachRelationship(this, ownedByMaster);
00200 }
00201
|