1 /* This file is part of the KDE project 2 Copyright (C) 2003-2016 Jarosław Staniek <staniek@kde.org> 3 4 This library is free software; you can redistribute it and/or 5 modify it under the terms of the GNU Library General Public 6 License as published by the Free Software Foundation; either 7 version 2 of the License, or (at your option) any later version. 8 9 This library is distributed in the hope that it will be useful, 10 but WITHOUT ANY WARRANTY; without even the implied warranty of 11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 Library General Public License for more details. 13 14 You should have received a copy of the GNU Library General Public License 15 along with this library; see the file COPYING.LIB. If not, write to 16 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 17 * Boston, MA 02110-1301, USA. 18 */ 19 20 #ifndef KDB_QUERYSCHEMA_P_H 21 #define KDB_QUERYSCHEMA_P_H 22 23 #include "KDbDriver.h" 24 #include "KDbExpression.h" 25 #include "KDbQueryColumnInfo.h" 26 #include "KDbQuerySchema.h" 27 28 #include <QBitArray> 29 #include <QWeakPointer> 30 31 class KDbConnection; 32 33 class Q_DECL_HIDDEN KDbQueryColumnInfo::Private 34 { 35 public: Private(KDbField * f,const QString & a,bool v,KDbQueryColumnInfo * foreign)36 Private(KDbField *f, const QString& a, bool v, KDbQueryColumnInfo *foreign) 37 : field(f) 38 , alias(a) 39 , visible(v) 40 , indexForVisibleLookupValue(-1) 41 , foreignColumn(foreign) 42 { 43 } 44 45 KDbConnection *connection = nullptr; //!< Used to relate KDbQueryColumnInfo with query. @since 3.2 46 const KDbQuerySchema *querySchema = nullptr; //!< Used to relate KDbQueryColumnInfo with query. @since 3.2 47 KDbField *field; 48 QString alias; 49 50 //! @c true if this column is visible to the user (and its data is fetched by the engine) 51 bool visible; 52 53 /*! Index of column with visible lookup value within the 'fields expanded' vector. 54 @see KDbQueryColumnInfo::indexForVisibleLookupValue() */ 55 int indexForVisibleLookupValue; 56 57 //! Non-nullptr if this column is a visible column for @a foreignColumn 58 KDbQueryColumnInfo *foreignColumn; 59 }; 60 61 class KDbQuerySchemaPrivate 62 { 63 Q_DECLARE_TR_FUNCTIONS(KDbQuerySchema) 64 public: 65 explicit KDbQuerySchemaPrivate(KDbQuerySchema* q, KDbQuerySchemaPrivate* copy = nullptr); 66 67 ~KDbQuerySchemaPrivate(); 68 69 //! @return a new query that's associated with @a conn. Used internally, e.g. by the parser. 70 //! Uses an internal KDbQuerySchema(KDbConnection*) ctor. 71 static KDbQuerySchema* createQuery(KDbConnection *conn); 72 73 void clear(); 74 75 void clearCachedData(); 76 77 bool setColumnAlias(int position, const QString& alias); 78 setTableAlias(int position,const QString & alias)79 inline bool setTableAlias(int position, const QString& alias) { 80 if (tablePositionsForAliases.contains(alias.toLower())) { 81 return false; 82 } 83 tableAliases.insert(position, alias.toLower()); 84 tablePositionsForAliases.insert(alias.toLower(), position); 85 return true; 86 } 87 columnAliasesCount()88 inline int columnAliasesCount() { 89 tryRegenerateExprAliases(); 90 return columnAliases.count(); 91 } 92 columnAlias(int position)93 inline QString columnAlias(int position) { 94 tryRegenerateExprAliases(); 95 return columnAliases.value(position); 96 } 97 hasColumnAlias(int position)98 inline bool hasColumnAlias(int position) { 99 tryRegenerateExprAliases(); 100 return columnAliases.contains(position); 101 } 102 removeTablePositionForAlias(const QString & alias)103 inline void removeTablePositionForAlias(const QString& alias) { 104 tablePositionsForAliases.remove(alias.toLower()); 105 } 106 tablePositionForAlias(const QString & alias)107 inline int tablePositionForAlias(const QString& alias) const { 108 return tablePositionsForAliases.value(alias.toLower(), -1); 109 } 110 columnPositionForAlias(const QString & alias)111 inline int columnPositionForAlias(const QString& alias) const { 112 return columnPositionsForAliases.value(alias.toLower(), -1); 113 } 114 115 //! Accessor for buildSelectQuery() setWhereExpressionInternal(KDbQuerySchema * query,const KDbExpression & expr)116 static void setWhereExpressionInternal(KDbQuerySchema *query, const KDbExpression &expr) 117 { 118 query->d->whereExpr = expr; 119 } 120 121 KDbQuerySchema *query; 122 123 /*! Master table of the query. Can be @c nullptr. 124 Any data modifications can be performed if we know master table. 125 If null, query's records cannot be modified. */ 126 KDbTableSchema *masterTable; 127 128 /*! List of tables used in this query */ 129 QList<KDbTableSchema*> tables; 130 131 KDbField *fakeRecordIdField; //! used to mark a place for record Id 132 KDbQueryColumnInfo *fakeRecordIdCol; //! used to mark a place for record Id 133 134 protected: 135 void tryRegenerateExprAliases(); 136 137 bool setColumnAliasInternal(int position, const QString& alias); 138 139 /*! Used to mapping columns to its aliases for this query */ 140 QHash<int, QString> columnAliases; 141 142 /*! Collects table positions for aliases: used in tablePositionForAlias(). */ 143 QHash<QString, int> tablePositionsForAliases; 144 145 /*! Collects column positions for aliases: used in columnPositionForAlias(). */ 146 QHash<QString, int> columnPositionsForAliases; 147 148 public: 149 /*! Used to mapping tables to its aliases for this query */ 150 QHash<int, QString> tableAliases; 151 152 /*! Helper used with aliases */ 153 int maxIndexWithAlias; 154 155 /*! Used to store visibility flag for every field */ 156 QBitArray visibility; 157 158 /*! List of asterisks defined for this query */ 159 KDbField::List asterisks; 160 161 /*! A list of fields for ORDER BY section. @see KDbQuerySchema::orderByColumnList(). */ 162 KDbOrderByColumnList* orderByColumnList; 163 164 /*! A cache for autoIncrementFields(). */ 165 KDbQueryColumnInfo::List *autoincFields; 166 167 /*! A cache for autoIncrementSqlFieldsList(). */ 168 KDbEscapedString autoIncrementSqlFieldsList; 169 QWeakPointer<const KDbDriver> lastUsedDriverForAutoIncrementSQLFieldsList; 170 171 /*! order of PKEY fields (e.g. for updateRecord() ) */ 172 QVector<int> *pkeyFieldsOrder; 173 174 /*! number of PKEY fields within the query */ 175 int pkeyFieldCount; 176 177 /*! Forced (predefined) raw SQL statement */ 178 KDbEscapedString sql; 179 180 /*! Relationships defined for this query. */ 181 QList<KDbRelationship*> relations; 182 183 /*! Information about columns bound to tables. 184 Used if table is used in FROM section more than once 185 (using table aliases). 186 187 This list is updated by insertField(int position, KDbField *field, 188 int bindToTable, bool visible), using bindToTable parameter. 189 190 Example: for this statement: 191 SELECT t1.a, othertable.x, t2.b FROM table t1, table t2, othertable; 192 tablesBoundToColumns list looks like this: 193 [ 0, -1, 1 ] 194 - first column is bound to table 0 "t1" 195 - second coulmn is not specially bound (othertable.x isn't ambiguous) 196 - third column is bound to table 1 "t2" 197 */ 198 QVector<int> tablesBoundToColumns; 199 200 /*! WHERE expression */ 201 KDbExpression whereExpr; 202 203 /*! Set by insertField(): true, if aliases for expression columns should 204 be generated on next columnAlias() call. */ 205 bool regenerateExprAliases; 206 207 //! Points to connection recently used for caching 208 //! @todo use equivalent of QPointer<KDbConnection> 209 KDbConnection *recentConnection = nullptr; 210 211 //! Owned fields created by KDbQuerySchema::addExpressionInternal() 212 KDbField::List ownedExpressionFields; 213 }; 214 215 //! Information about expanded fields for a single query schema, used for caching 216 class KDbQuerySchemaFieldsExpanded 217 { 218 public: KDbQuerySchemaFieldsExpanded()219 inline KDbQuerySchemaFieldsExpanded() 220 { 221 } 222 ~KDbQuerySchemaFieldsExpanded()223 inline ~KDbQuerySchemaFieldsExpanded() 224 { 225 qDeleteAll(fieldsExpanded); 226 qDeleteAll(internalFields); 227 } 228 229 /*! Temporary field vector for using in fieldsExpanded() */ 230 KDbQueryColumnInfo::Vector fieldsExpanded; 231 232 /*! Like fieldsExpanded but only visible column infos; infos are not owned. */ 233 KDbQueryColumnInfo::Vector visibleFieldsExpanded; 234 235 /*! Temporary field vector containing internal fields used for lookup columns. */ 236 KDbQueryColumnInfo::Vector internalFields; 237 238 /*! Temporary, used to cache sum of expanded fields and internal fields (+record Id) used for lookup columns. 239 Contains not auto-deleted items.*/ 240 KDbQueryColumnInfo::Vector fieldsExpandedWithInternalAndRecordId; 241 242 /*! Like fieldsExpandedWithInternalAndRecordId but only contains visible column infos; infos are not owned.*/ 243 KDbQueryColumnInfo::Vector visibleFieldsExpandedWithInternalAndRecordId; 244 245 /*! Temporary, used to cache sum of expanded fields and internal fields used for lookup columns. 246 Contains not auto-deleted items.*/ 247 KDbQueryColumnInfo::Vector fieldsExpandedWithInternal; 248 249 /*! Like fieldsExpandedWithInternal but only contains visible column infos; infos are not owned.*/ 250 KDbQueryColumnInfo::Vector visibleFieldsExpandedWithInternal; 251 252 /*! A hash for fast lookup of query columns' order (unexpanded version). */ 253 QHash<KDbQueryColumnInfo*, int> columnsOrder; 254 255 /*! A hash for fast lookup of query columns' order (unexpanded version without asterisks). */ 256 QHash<KDbQueryColumnInfo*, int> columnsOrderWithoutAsterisks; 257 258 /*! A hash for fast lookup of query columns' order. 259 This is exactly opposite information compared to vector returned 260 by fieldsExpanded() */ 261 QHash<KDbQueryColumnInfo*, int> columnsOrderExpanded; 262 263 QHash<QString, KDbQueryColumnInfo*> columnInfosByNameExpanded; 264 265 QHash<QString, KDbQueryColumnInfo*> columnInfosByName; //!< Same as columnInfosByNameExpanded but asterisks are skipped 266 267 //! Fields created for multiple joined columns like a||' '||b||' '||c 268 KDbField::List ownedVisibleFields; 269 }; 270 271 /** 272 * Return identifier string @a name escaped using @a conn connection and type @a escapingType 273 * 274 * @a conn is only used for KDb::DriverEscaping type. If @a conn is missing for this type, 275 * identifier is escaped using double quotes ("). 276 */ 277 QString escapeIdentifier(const QString& name, KDbConnection *conn, 278 KDb::IdentifierEscapingType escapingType); 279 280 #endif 281