File indexing completed on 2024-12-01 04:19:14
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 "KDbQuerySchema_p.h" 0021 #include "KDbConnection.h" 0022 #include "KDbConnection_p.h" 0023 #include "KDbOrderByColumn.h" 0024 #include "kdb_debug.h" 0025 0026 KDbQuerySchemaPrivate::KDbQuerySchemaPrivate(KDbQuerySchema* q, KDbQuerySchemaPrivate* copy) 0027 : query(q) 0028 , masterTable(nullptr) 0029 , fakeRecordIdField(nullptr) 0030 , fakeRecordIdCol(nullptr) 0031 , maxIndexWithAlias(-1) 0032 , visibility(64) 0033 , orderByColumnList(nullptr) 0034 , autoincFields(nullptr) 0035 , pkeyFieldsOrder(nullptr) 0036 , pkeyFieldCount(0) 0037 , tablesBoundToColumns(64, -1) // will be resized if needed 0038 , regenerateExprAliases(false) 0039 { 0040 visibility.fill(false); 0041 if (copy) { 0042 // deep copy 0043 *this = *copy; 0044 // <clear, so computeFieldsExpanded() will re-create it> 0045 orderByColumnList = nullptr; 0046 autoincFields = nullptr; 0047 autoIncrementSqlFieldsList.clear(); 0048 pkeyFieldsOrder = nullptr; 0049 fakeRecordIdCol = nullptr; 0050 fakeRecordIdField = nullptr; 0051 // </clear, so computeFieldsExpanded() will re-create it> 0052 if (!copy->whereExpr.isNull()) { 0053 whereExpr = copy->whereExpr.clone(); 0054 } 0055 // "*this = *copy" causes copying pointers; pull of them without destroying, 0056 // will be deep-copied in the KDbQuerySchema ctor. 0057 asterisks.setAutoDelete(false); 0058 asterisks.clear(); 0059 asterisks.setAutoDelete(true); 0060 } 0061 else { 0062 orderByColumnList = new KDbOrderByColumnList; 0063 } 0064 } 0065 0066 KDbQuerySchemaPrivate::~KDbQuerySchemaPrivate() 0067 { 0068 if (recentConnection) { 0069 recentConnection->d->removeFieldsExpanded(query); 0070 } 0071 delete orderByColumnList; 0072 delete autoincFields; 0073 delete pkeyFieldsOrder; 0074 delete fakeRecordIdCol; 0075 delete fakeRecordIdField; 0076 } 0077 0078 void KDbQuerySchemaPrivate::clear() 0079 { 0080 columnAliases.clear(); 0081 tableAliases.clear(); 0082 asterisks.clear(); 0083 relations.clear(); 0084 masterTable = nullptr; 0085 tables.clear(); 0086 clearCachedData(); 0087 delete pkeyFieldsOrder; 0088 pkeyFieldsOrder = nullptr; 0089 visibility.fill(false); 0090 tablesBoundToColumns = QVector<int>(64, -1); // will be resized if needed 0091 tablePositionsForAliases.clear(); 0092 columnPositionsForAliases.clear(); 0093 } 0094 0095 void KDbQuerySchemaPrivate::clearCachedData() 0096 { 0097 if (orderByColumnList) { 0098 orderByColumnList->clear(); 0099 } 0100 if (recentConnection) { 0101 recentConnection->d->removeFieldsExpanded(query); 0102 } 0103 delete autoincFields; 0104 autoincFields = nullptr; 0105 autoIncrementSqlFieldsList.clear(); 0106 } 0107 0108 bool KDbQuerySchemaPrivate::setColumnAlias(int position, const QString& alias) 0109 { 0110 if (alias.isEmpty()) { 0111 columnAliases.remove(position); 0112 maxIndexWithAlias = -1; 0113 return true; 0114 } 0115 return setColumnAliasInternal(position, alias); 0116 } 0117 0118 void KDbQuerySchemaPrivate::tryRegenerateExprAliases() 0119 { 0120 if (!regenerateExprAliases) 0121 return; 0122 //regenerate missing aliases for experessions 0123 int colNum = 0; //used to generate a name 0124 QString columnAlias; 0125 int p = -1; 0126 foreach(KDbField* f, *query->fields()) { 0127 p++; 0128 if (f->isExpression() && columnAliases.value(p).isEmpty()) { 0129 //missing 0130 do { //find 1st unused 0131 colNum++; 0132 columnAlias = tr("expr%1", "short for 'expression' word, it will expand " 0133 "to 'expr1', 'expr2', etc. Please use ONLY latin " 0134 "letters and DON'T use '.'").arg(colNum); 0135 columnAlias = KDb::stringToIdentifier(columnAlias); // sanity fix, translators make mistakes! 0136 } while (-1 != tablePositionForAlias(columnAlias)); 0137 0138 (void)setColumnAliasInternal(p, columnAlias); 0139 } 0140 } 0141 regenerateExprAliases = false; 0142 } 0143 0144 bool KDbQuerySchemaPrivate::setColumnAliasInternal(int position, const QString& alias) 0145 { 0146 const int currentPos = columnPositionsForAliases.value(alias.toLower(), -1); 0147 if (currentPos == position) { 0148 return true; // already set 0149 } 0150 if (currentPos == -1) { 0151 columnAliases.insert(position, alias.toLower()); 0152 columnPositionsForAliases.insert(alias.toLower(), position); 0153 maxIndexWithAlias = qMax(maxIndexWithAlias, position); 0154 return true; 0155 } 0156 kdbWarning() << "Alias" << alias << "for already set for column" << currentPos 0157 << ", cannot set to a new column. Remove old alias first."; 0158 return false; 0159 }