File indexing completed on 2024-09-08 04:16:12
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 #ifndef KDB_QUERYSCHEMA_P_H 0021 #define KDB_QUERYSCHEMA_P_H 0022 0023 #include "KDbDriver.h" 0024 #include "KDbExpression.h" 0025 #include "KDbQueryColumnInfo.h" 0026 #include "KDbQuerySchema.h" 0027 0028 #include <QBitArray> 0029 #include <QWeakPointer> 0030 0031 class KDbConnection; 0032 0033 class Q_DECL_HIDDEN KDbQueryColumnInfo::Private 0034 { 0035 public: 0036 Private(KDbField *f, const QString& a, bool v, KDbQueryColumnInfo *foreign) 0037 : field(f) 0038 , alias(a) 0039 , visible(v) 0040 , indexForVisibleLookupValue(-1) 0041 , foreignColumn(foreign) 0042 { 0043 } 0044 0045 KDbConnection *connection = nullptr; //!< Used to relate KDbQueryColumnInfo with query. @since 3.2 0046 const KDbQuerySchema *querySchema = nullptr; //!< Used to relate KDbQueryColumnInfo with query. @since 3.2 0047 KDbField *field; 0048 QString alias; 0049 0050 //! @c true if this column is visible to the user (and its data is fetched by the engine) 0051 bool visible; 0052 0053 /*! Index of column with visible lookup value within the 'fields expanded' vector. 0054 @see KDbQueryColumnInfo::indexForVisibleLookupValue() */ 0055 int indexForVisibleLookupValue; 0056 0057 //! Non-nullptr if this column is a visible column for @a foreignColumn 0058 KDbQueryColumnInfo *foreignColumn; 0059 }; 0060 0061 class KDbQuerySchemaPrivate 0062 { 0063 Q_DECLARE_TR_FUNCTIONS(KDbQuerySchema) 0064 public: 0065 explicit KDbQuerySchemaPrivate(KDbQuerySchema* q, KDbQuerySchemaPrivate* copy = nullptr); 0066 0067 ~KDbQuerySchemaPrivate(); 0068 0069 //! @return a new query that's associated with @a conn. Used internally, e.g. by the parser. 0070 //! Uses an internal KDbQuerySchema(KDbConnection*) ctor. 0071 static KDbQuerySchema* createQuery(KDbConnection *conn); 0072 0073 void clear(); 0074 0075 void clearCachedData(); 0076 0077 bool setColumnAlias(int position, const QString& alias); 0078 0079 inline bool setTableAlias(int position, const QString& alias) { 0080 if (tablePositionsForAliases.contains(alias.toLower())) { 0081 return false; 0082 } 0083 tableAliases.insert(position, alias.toLower()); 0084 tablePositionsForAliases.insert(alias.toLower(), position); 0085 return true; 0086 } 0087 0088 inline int columnAliasesCount() { 0089 tryRegenerateExprAliases(); 0090 return columnAliases.count(); 0091 } 0092 0093 inline QString columnAlias(int position) { 0094 tryRegenerateExprAliases(); 0095 return columnAliases.value(position); 0096 } 0097 0098 inline bool hasColumnAlias(int position) { 0099 tryRegenerateExprAliases(); 0100 return columnAliases.contains(position); 0101 } 0102 0103 inline void removeTablePositionForAlias(const QString& alias) { 0104 tablePositionsForAliases.remove(alias.toLower()); 0105 } 0106 0107 inline int tablePositionForAlias(const QString& alias) const { 0108 return tablePositionsForAliases.value(alias.toLower(), -1); 0109 } 0110 0111 inline int columnPositionForAlias(const QString& alias) const { 0112 return columnPositionsForAliases.value(alias.toLower(), -1); 0113 } 0114 0115 //! Accessor for buildSelectQuery() 0116 static void setWhereExpressionInternal(KDbQuerySchema *query, const KDbExpression &expr) 0117 { 0118 query->d->whereExpr = expr; 0119 } 0120 0121 KDbQuerySchema *query; 0122 0123 /*! Master table of the query. Can be @c nullptr. 0124 Any data modifications can be performed if we know master table. 0125 If null, query's records cannot be modified. */ 0126 KDbTableSchema *masterTable; 0127 0128 /*! List of tables used in this query */ 0129 QList<KDbTableSchema*> tables; 0130 0131 KDbField *fakeRecordIdField; //! used to mark a place for record Id 0132 KDbQueryColumnInfo *fakeRecordIdCol; //! used to mark a place for record Id 0133 0134 protected: 0135 void tryRegenerateExprAliases(); 0136 0137 bool setColumnAliasInternal(int position, const QString& alias); 0138 0139 /*! Used to mapping columns to its aliases for this query */ 0140 QHash<int, QString> columnAliases; 0141 0142 /*! Collects table positions for aliases: used in tablePositionForAlias(). */ 0143 QHash<QString, int> tablePositionsForAliases; 0144 0145 /*! Collects column positions for aliases: used in columnPositionForAlias(). */ 0146 QHash<QString, int> columnPositionsForAliases; 0147 0148 public: 0149 /*! Used to mapping tables to its aliases for this query */ 0150 QHash<int, QString> tableAliases; 0151 0152 /*! Helper used with aliases */ 0153 int maxIndexWithAlias; 0154 0155 /*! Used to store visibility flag for every field */ 0156 QBitArray visibility; 0157 0158 /*! List of asterisks defined for this query */ 0159 KDbField::List asterisks; 0160 0161 /*! A list of fields for ORDER BY section. @see KDbQuerySchema::orderByColumnList(). */ 0162 KDbOrderByColumnList* orderByColumnList; 0163 0164 /*! A cache for autoIncrementFields(). */ 0165 KDbQueryColumnInfo::List *autoincFields; 0166 0167 /*! A cache for autoIncrementSqlFieldsList(). */ 0168 KDbEscapedString autoIncrementSqlFieldsList; 0169 QWeakPointer<const KDbDriver> lastUsedDriverForAutoIncrementSQLFieldsList; 0170 0171 /*! order of PKEY fields (e.g. for updateRecord() ) */ 0172 QVector<int> *pkeyFieldsOrder; 0173 0174 /*! number of PKEY fields within the query */ 0175 int pkeyFieldCount; 0176 0177 /*! Forced (predefined) raw SQL statement */ 0178 KDbEscapedString sql; 0179 0180 /*! Relationships defined for this query. */ 0181 QList<KDbRelationship*> relations; 0182 0183 /*! Information about columns bound to tables. 0184 Used if table is used in FROM section more than once 0185 (using table aliases). 0186 0187 This list is updated by insertField(int position, KDbField *field, 0188 int bindToTable, bool visible), using bindToTable parameter. 0189 0190 Example: for this statement: 0191 SELECT t1.a, othertable.x, t2.b FROM table t1, table t2, othertable; 0192 tablesBoundToColumns list looks like this: 0193 [ 0, -1, 1 ] 0194 - first column is bound to table 0 "t1" 0195 - second coulmn is not specially bound (othertable.x isn't ambiguous) 0196 - third column is bound to table 1 "t2" 0197 */ 0198 QVector<int> tablesBoundToColumns; 0199 0200 /*! WHERE expression */ 0201 KDbExpression whereExpr; 0202 0203 /*! Set by insertField(): true, if aliases for expression columns should 0204 be generated on next columnAlias() call. */ 0205 bool regenerateExprAliases; 0206 0207 //! Points to connection recently used for caching 0208 //! @todo use equivalent of QPointer<KDbConnection> 0209 KDbConnection *recentConnection = nullptr; 0210 0211 //! Owned fields created by KDbQuerySchema::addExpressionInternal() 0212 KDbField::List ownedExpressionFields; 0213 }; 0214 0215 //! Information about expanded fields for a single query schema, used for caching 0216 class KDbQuerySchemaFieldsExpanded 0217 { 0218 public: 0219 inline KDbQuerySchemaFieldsExpanded() 0220 { 0221 } 0222 0223 inline ~KDbQuerySchemaFieldsExpanded() 0224 { 0225 qDeleteAll(fieldsExpanded); 0226 qDeleteAll(internalFields); 0227 } 0228 0229 /*! Temporary field vector for using in fieldsExpanded() */ 0230 KDbQueryColumnInfo::Vector fieldsExpanded; 0231 0232 /*! Like fieldsExpanded but only visible column infos; infos are not owned. */ 0233 KDbQueryColumnInfo::Vector visibleFieldsExpanded; 0234 0235 /*! Temporary field vector containing internal fields used for lookup columns. */ 0236 KDbQueryColumnInfo::Vector internalFields; 0237 0238 /*! Temporary, used to cache sum of expanded fields and internal fields (+record Id) used for lookup columns. 0239 Contains not auto-deleted items.*/ 0240 KDbQueryColumnInfo::Vector fieldsExpandedWithInternalAndRecordId; 0241 0242 /*! Like fieldsExpandedWithInternalAndRecordId but only contains visible column infos; infos are not owned.*/ 0243 KDbQueryColumnInfo::Vector visibleFieldsExpandedWithInternalAndRecordId; 0244 0245 /*! Temporary, used to cache sum of expanded fields and internal fields used for lookup columns. 0246 Contains not auto-deleted items.*/ 0247 KDbQueryColumnInfo::Vector fieldsExpandedWithInternal; 0248 0249 /*! Like fieldsExpandedWithInternal but only contains visible column infos; infos are not owned.*/ 0250 KDbQueryColumnInfo::Vector visibleFieldsExpandedWithInternal; 0251 0252 /*! A hash for fast lookup of query columns' order (unexpanded version). */ 0253 QHash<KDbQueryColumnInfo*, int> columnsOrder; 0254 0255 /*! A hash for fast lookup of query columns' order (unexpanded version without asterisks). */ 0256 QHash<KDbQueryColumnInfo*, int> columnsOrderWithoutAsterisks; 0257 0258 /*! A hash for fast lookup of query columns' order. 0259 This is exactly opposite information compared to vector returned 0260 by fieldsExpanded() */ 0261 QHash<KDbQueryColumnInfo*, int> columnsOrderExpanded; 0262 0263 QHash<QString, KDbQueryColumnInfo*> columnInfosByNameExpanded; 0264 0265 QHash<QString, KDbQueryColumnInfo*> columnInfosByName; //!< Same as columnInfosByNameExpanded but asterisks are skipped 0266 0267 //! Fields created for multiple joined columns like a||' '||b||' '||c 0268 KDbField::List ownedVisibleFields; 0269 }; 0270 0271 /** 0272 * Return identifier string @a name escaped using @a conn connection and type @a escapingType 0273 * 0274 * @a conn is only used for KDb::DriverEscaping type. If @a conn is missing for this type, 0275 * identifier is escaped using double quotes ("). 0276 */ 0277 QString escapeIdentifier(const QString& name, KDbConnection *conn, 0278 KDb::IdentifierEscapingType escapingType); 0279 0280 #endif