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 }