File indexing completed on 2024-03-24 16:11:21

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