File indexing completed on 2024-12-08 07:18:24
0001 /* This file is part of the KDE project 0002 Copyright (C) 2003-2017 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_H 0021 #define KDB_QUERYSCHEMA_H 0022 0023 #include <QVector> 0024 #include <QHash> 0025 0026 #include "KDbFieldList.h" 0027 #include "KDbObject.h" 0028 #include "KDbQueryColumnInfo.h" 0029 #include "KDbToken.h" 0030 0031 class KDbConnection; 0032 class KDbOrderByColumn; 0033 class KDbOrderByColumnList; 0034 class KDbQueryAsterisk; 0035 class KDbQuerySchemaFieldsExpanded; 0036 class KDbQuerySchemaParameter; 0037 class KDbQuerySchemaPrivate; 0038 class KDbRelationship; 0039 class KDbTableSchema; 0040 0041 //! @short KDbQuerySchema provides information about database query 0042 /*! The query that can be executed using KDb-compatible SQL database engine 0043 or used as an introspection tool. KDb parser builds KDbQuerySchema objects 0044 by parsing SQL statements. */ 0045 class KDB_EXPORT KDbQuerySchema : public KDbFieldList, public KDbObject 0046 { 0047 public: 0048 /*! Creates empty query object (without columns). */ 0049 KDbQuerySchema(); 0050 0051 /*! Creates query schema object that is equivalent to "SELECT * FROM table" 0052 sql command. Schema of @a table is used to contruct this query -- 0053 it is defined by just adding all the fields to the query in natural order. 0054 To avoid problems (e.g. with fields added outside of Kexi using ALTER TABLE) 0055 we do not use "all-tables query asterisk" (see KDbQueryAsterisk) item to achieve 0056 this effect. 0057 0058 Properties such as the name and caption of the query are inherited 0059 from table schema. 0060 0061 We consider that query schema based on @a table is not (a least yet) stored 0062 in a system table, so query connection is set to @c nullptr 0063 (even if @a tableSchema's connection is not @c nullptr). 0064 Id of the created query is set to 0. */ 0065 explicit KDbQuerySchema(KDbTableSchema *tableSchema); 0066 0067 /*! Copy constructor. Creates deep copy of @a querySchema. 0068 KDbQueryAsterisk objects are deeply copied while only pointers to KDbField objects are copied. */ 0069 KDbQuerySchema(const KDbQuerySchema& querySchema, KDbConnection *conn); 0070 0071 ~KDbQuerySchema() override; 0072 0073 /*! Inserts @a field to the columns list at @a position. 0074 Inserted field will not be owned by this KDbQuerySchema object, 0075 but by the corresponding KDbTableSchema. 0076 0077 KDbQueryAsterisk can be also passed as @a field. See the KDbQueryAsterisk class 0078 description. 0079 0080 @note After inserting a field, corresponding table will be automatically 0081 added to query's tables list if it is not present there (see tables()). 0082 KDbField must have its table assigned. 0083 0084 The inserted field will be visible. Use insertInvisibleField(position, field) 0085 to add an invisible field. 0086 0087 The field is not bound to any particular table within the query. 0088 */ 0089 bool insertField(int position, KDbField *field) override; 0090 0091 /** 0092 * @overload bool insertField(int position, KDbField *field) 0093 * Inserts @a field to the columns list at @a position. 0094 * @a bindToTable is a table index within the query for which the field should be bound. 0095 * If @a bindToTable is -1, no particular table will be bound. 0096 * @see tableBoundToColumn(int columnPosition) 0097 */ 0098 bool insertField(int position, KDbField *field, int bindToTable); 0099 0100 /** 0101 * @overload bool insertField(int position, KDbField *field) 0102 * Inserts @a field to the columns list at @a position. 0103 * In addition sets field's visibility to @c false. It will not be bound to any table in this query. 0104 * @since 3.1 0105 */ 0106 bool insertInvisibleField(int position, KDbField *field); 0107 0108 /** 0109 * @overload bool insertInvisibleField(int position, KDbField *field) 0110 * Inserts @a field to the columns list at @a position. 0111 * In addition sets field's visibility to @c false. 0112 * @a bindToTable is a table index within the query for which the field should be bound. 0113 * If @a bindToTable is -1, no particular table will be bound. 0114 * @see tableBoundToColumn(int columnPosition) 0115 * @since 3.1 0116 */ 0117 bool insertInvisibleField(int position, KDbField *field, int bindToTable); 0118 0119 /** 0120 * Appends @a field to the columns list. 0121 * The field will be visible. Use addInvisibleField(field) to add an invisible field. 0122 * The field is not bound to any particular table within the query. 0123 * @see insertField() 0124 */ 0125 bool addField(KDbField* field); 0126 0127 /*! Appends @a field to the columns list. Also binds to a table at @a bindToTable position. 0128 * Use bindToTable==-1 if no table should be bound. 0129 * The field will be visible. Use addInvisibleField(field, bindToTable) to add 0130 * an invisible field. 0131 * @see insertField() 0132 * @see tableBoundToColumn(int columnPosition) 0133 */ 0134 bool addField(KDbField* field, int bindToTable); 0135 0136 /** 0137 * @overload bool addField(KDbField* field) 0138 * Appends @a field to the columns list. 0139 * The field is not bound to any particular table within the query. 0140 * In addition sets field's visibility to @c false. It will not be bound to any table in this query. 0141 * @since 3.1 0142 */ 0143 bool addInvisibleField(KDbField* field); 0144 0145 /** 0146 * @overload bool addField(KDbField* field, int bindToTable) 0147 * Appends @a field to the columns list. Also binds to a table at @a bindToTable position. 0148 * In addition sets field's visibility to @c false. 0149 * @see tableBoundToColumn(int columnPosition) 0150 * @since 3.1 0151 */ 0152 bool addInvisibleField(KDbField* field, int bindToTable); 0153 0154 /*! Removes field from the columns list. Use with care. */ 0155 bool removeField(KDbField *field) override; 0156 0157 /** 0158 * Appends a column built on top of @a expr expression. 0159 * This creates a new KDbField object and adds it to the query schema using addField(). 0160 */ 0161 bool addExpression(const KDbExpression& expr); 0162 0163 /** 0164 * @overload bool addExpression(const KDbExpression& expr) 0165 * Appends a column built on top of @a expr expression. 0166 * In addition sets column's visibility to @c false. 0167 * @since 3.1 0168 */ 0169 bool addInvisibleExpression(const KDbExpression& expr); 0170 0171 /*! @return visibility flag for column at @a position. 0172 By default column is visible. */ 0173 bool isColumnVisible(int position) const; 0174 0175 //! Sets visibility flag for column at @a position to @a visible. 0176 void setColumnVisible(int position, bool visible); 0177 0178 /*! Appends @a asterisk at the and of columns list. */ 0179 bool addAsterisk(KDbQueryAsterisk *asterisk); 0180 0181 /** 0182 * @overload bool addAsterisk(KDbQueryAsterisk *asterisk) 0183 * Appends @a asterisk at the and of columns list. 0184 * Sets the asterisk as invisible. 0185 * @since 3.1 0186 */ 0187 bool addInvisibleAsterisk(KDbQueryAsterisk *asterisk); 0188 0189 /*! Removes all columns and their aliases from the columns list, 0190 removes all tables and their aliases from the tables list within this query. 0191 Sets master table information to @c nullptr. 0192 Does not destroy any objects though. Clears name and all other properties. 0193 @see KDbFieldList::clear() */ 0194 void clear() override; 0195 0196 /*! @return table that is master to this query. 0197 All potentially-editable columns within this query belong just to this table. 0198 This method also can return @c nullptr if there are no tables at all, 0199 or if previously assigned master table schema has been removed 0200 with removeTable(). 0201 Every query that has at least one table defined, should have 0202 assigned a master table. 0203 If no master table is assigned explicitly, but only one table used in this query, 0204 a single table is returned here, even if there are table aliases, 0205 (e.g. "T" table is returned for "SELECT T1.A, T2.B FROM T T1, T T2" statement). */ 0206 KDbTableSchema* masterTable() const; 0207 0208 /*! Sets master table of this query to @a table. 0209 This table should be also added to query's tables list 0210 using addTable(). If @a table equals @c nullptr, nothing is performed. 0211 @see masterTable() */ 0212 void setMasterTable(KDbTableSchema *table); 0213 0214 /*! @return list of tables used in this query. 0215 It is never @c nullptr. The list also includes master table. 0216 @see masterTable() */ 0217 QList<KDbTableSchema*>* tables() const; 0218 0219 /*! Appends @a table schema as one of tables used in a query. 0220 If @a alias is not empty, it will be assigned to this table 0221 using setTableAlias(position, alias). */ 0222 void addTable(KDbTableSchema *table, const QString& alias = QString()); 0223 0224 /*! Removes @a table schema from this query. 0225 This does not destroy @a table object but only takes it out of the list. 0226 If this table was master for the query, master table information is also 0227 invalidated. */ 0228 void removeTable(KDbTableSchema *table); 0229 0230 /*! @return table with name @a tableName or 0 if this query has no such table. */ 0231 KDbTableSchema* table(const QString& tableName) const; 0232 0233 /*! @return @c true if the query uses @a table. */ 0234 bool contains(KDbTableSchema *table) const; 0235 0236 /*! Convenience function. 0237 @return table field by searching through all tables in this query. 0238 The field does not need to be included on the list of query columns. 0239 Similarly, query aliases are not taken into account. 0240 0241 @a fieldOrTableAndFieldName string may contain table name and field name 0242 with '.' character between them, e.g. "mytable.myfield". 0243 This is recommended way to avoid ambiguity. 0244 0 is returned if the query has no such 0245 table defined of the table has no such field defined. 0246 If you do not provide a table name, the first field found is returned. 0247 0248 KDbQuerySchema::table("mytable")->field("myfield") could be 0249 alternative for findTableField("mytable.myfield") but it can crash 0250 if "mytable" is not defined in the query. 0251 0252 @see KDb::splitToTableAndFieldParts() 0253 */ 0254 KDbField* findTableField(const QString &fieldOrTableAndFieldName) const; 0255 0256 /*! @return alias of a column at @a position or empty string if there is no alias for this column 0257 or if there is no such column within the query defined. If the column is an expression and has 0258 no alias defined, a new unique alias will be generated automatically on this call. 0259 */ 0260 QString columnAlias(int position) const; 0261 0262 /*! @return number of column aliases */ 0263 int columnAliasesCount() const; 0264 0265 /*! Provided for convenience. 0266 @return @c true if a column at @a position has non empty alias defined 0267 within the query. 0268 If there is no alias for this column, 0269 or if there is no such column in the query defined, @c false is returned. */ 0270 bool hasColumnAlias(int position) const; 0271 0272 /*! Sets @a alias for a column at @a position, within the query. 0273 Passing empty string to @a alias clears alias for a given column. */ 0274 bool setColumnAlias(int position, const QString& alias); 0275 0276 /*! @return a table position (within FROM section), 0277 that is bound to column at @a columnPosition (within SELECT section). 0278 This information can be used to find if there is alias defined for 0279 a table that is referenced by a given column. 0280 0281 For example, for "SELECT t2.id FROM table1 t1, table2 t2" query statement, 0282 columnBoundToTable(0) returns 1, what means that table at position 1 0283 (within FROM section) is bound to column at position 0, so we can 0284 now call tableAlias(1) to see if we have used alias for this column (t2.id) 0285 or just a table name (table2.id). 0286 0287 These checks are performed e.g. by KDbConnection::selectStatement() 0288 to construct a statement string maximally identical to originally 0289 defined query statement. 0290 0291 -1 is returned if: 0292 - @a columnPosition is out of range (i.e. < 0 or >= fieldCount()) 0293 - a column at @a columnPosition is not bound to any table (i.e. 0294 no database field is used for this column, 0295 e.g. "1" constant for "SELECT 1 from table" query statement) 0296 */ 0297 int tableBoundToColumn(int columnPosition) const; 0298 0299 /*! @return number of table aliases */ 0300 int tableAliasesCount() const; 0301 0302 /*! @return alias of a table at @a position (within FROM section) 0303 or null string if there is no alias for this table 0304 or if there is no such table within the query defined. */ 0305 QString tableAlias(int position) const; 0306 0307 /*! @return alias of a table @a tableName (within FROM section) 0308 or empty value if there is no alias for this table 0309 or if there is no such table within the query defined. */ 0310 QString tableAlias(const QString& tableName) const; 0311 0312 /*! @return alias of a table @a tableName (within FROM section). 0313 If there is no alias for this table, its name is returned. 0314 Empty value is returned if there is no such table within the query defined. */ 0315 QString tableAliasOrName(const QString& tableName) const; 0316 0317 /*! @return table position (within FROM section) that has attached 0318 alias @a name. 0319 If there is no such alias, -1 is returned. 0320 Only first table's position attached for this alias is returned. 0321 It is not especially bad, since aliases rarely can be duplicated, 0322 what leads to ambiguity. 0323 Duplicated aliases are only allowed for trivial queries that have 0324 no database fields used within their columns, 0325 e.g. "SELECT 1 from table1 t, table2 t" is ok 0326 but "SELECT t.id from table1 t, table2 t" is not. 0327 */ 0328 int tablePositionForAlias(const QString& name) const; 0329 0330 /*! @return position (within the FROM section) of table @a tableName. 0331 -1 is returned if there's no such table declared in the FROM section. 0332 @see tablePositions() 0333 */ 0334 int tablePosition(const QString& tableName) const; 0335 0336 /*! @return a list of all occurrences of table @a tableName (within the FROM section). 0337 E.g. for "SELECT * FROM table t, table t2" tablePositions("table") returns {0, 1} list. 0338 Empty list is returned if there's no table @a tableName used in the FROM section at all. 0339 @see tablePosition() */ 0340 QList<int> tablePositions(const QString& tableName) const; 0341 0342 /*! Provided for convenience. 0343 @return @c true if a table at @a position (within FROM section of the query) 0344 has non empty alias defined. 0345 If there is no alias for this table, 0346 or if there is no such table in the query defined, @c false is returned. */ 0347 bool hasTableAlias(int position) const; 0348 0349 /*! Provided for convenience. 0350 @return @c true if non empty table alias @a name is defined for a table. */ 0351 bool hasTableAlias(const QString &name) const; 0352 0353 /*! @return column position that has defined alias @a name. 0354 If there is no such alias, -1 is returned. */ 0355 int columnPositionForAlias(const QString& name) const; 0356 0357 /*! Provided for convenience. 0358 @return @c true if non empty alias @a name is defined for any column. */ 0359 bool hasColumnAlias(const QString &name) const; 0360 0361 /*! Sets @a alias for a table at @a position (within FROM section 0362 of the query). 0363 Passing empty sting to @a alias clears alias for a given table 0364 (only for specified @a position). */ 0365 bool setTableAlias(int position, const QString& alias); 0366 0367 /*! @return a list of relationships defined for this query. 0368 It is never @c nullptr.*/ 0369 QList<KDbRelationship*>* relationships() const; 0370 0371 /*! Appends a new relationship defined by @a field1 and @a field2. 0372 Both fields should belong to two different tables of this query. 0373 This is convenience function useful for a typical cases. 0374 It automatically creates KDbRelationship object for this query. 0375 If one of the fields are primary keys, it will be detected 0376 and appropriate master-detail relation will be established. 0377 This functiuon does nothing if the arguments are invalid. */ 0378 KDbRelationship* addRelationship(KDbField *field1, KDbField *field2); 0379 0380 /*! @return list of KDbQueryAsterisk objects defined for this query. 0381 It is never @c nullptr. */ 0382 KDbField::List* asterisks() const; 0383 0384 //! Mode for field() and columnInfo() 0385 //! @since 3.1 0386 enum class ExpandMode { 0387 Unexpanded, //!< All fields are returned even if duplicated 0388 Expanded //!< Expanded list of the query fields is computed so queries with asterisks 0389 //!< are processed well 0390 }; 0391 0392 /*! @return field for @a identifier or @c nullptr if no field for this name 0393 was found within the query. fieldsExpanded() method is used 0394 to lookup expanded list of the query fields, so queries with asterisks 0395 are processed well. 0396 If a field has alias defined, name is not taken into account, 0397 but only its alias. If a field has no alias: 0398 - field's name is checked 0399 - field's table and field's name are checked in a form of "tablename.fieldname", 0400 so you can provide @a identifier in this form to avoid ambiguity. 0401 0402 If there are more than one fields with the same name equal to @a identifier, 0403 first-found is returned (checking is performed from first to last query field). 0404 Structures needed to compute result of this method are cached, 0405 so only first usage costs o(n) - another usages cost o(1). 0406 0407 Example: 0408 Let query be defined by "SELECT T.B AS X, T.* FROM T" statement and let T 0409 be table containing fields A, B, C. 0410 Expanded list of columns for the query is: T.B AS X, T.A, T.B, T.C. 0411 - Calling field("B") will return a pointer to third query column (not the first, 0412 because it is covered by "X" alias). Additionally, calling field("X") 0413 will return the same pointer. 0414 - Calling field("T.A") will return the same pointer as field("A"). 0415 0416 This method is also a product of inheritance from KDbFieldList. 0417 */ 0418 const KDbField *field(KDbConnection *conn, const QString &identifier, 0419 ExpandMode mode = ExpandMode::Expanded) const; 0420 0421 /** 0422 * @overload 0423 */ 0424 KDbField *field(KDbConnection *conn, const QString &identifier, 0425 ExpandMode mode = ExpandMode::Expanded); 0426 0427 /*! @return field id or @c nullptr if there is no such a field. */ 0428 KDbField* field(int id) override; 0429 0430 using KDbFieldList::field; 0431 0432 /*! @overload KDbField* field(int id) */ 0433 const KDbField* field(int id) const override; 0434 0435 /*! Like KDbQuerySchema::field(const QString& name) but returns not only KDbField 0436 object for @a identifier but entire KDbQueryColumnInfo object. 0437 @a identifier can be: 0438 - a fieldname 0439 - an aliasname 0440 - a tablename.fieldname 0441 - a tablename.aliasname 0442 Note that if there are two occurrrences of the same name, 0443 only the first is accessible using this method. For instance, 0444 calling columnInfo("name") for "SELECT t1.name, t2.name FROM t1, t2" statement 0445 will only return the column related to t1.name and not t2.name, so you'll need to 0446 explicitly specify "t2.name" as the identifier to get the second column. */ 0447 KDbQueryColumnInfo *columnInfo(KDbConnection *conn, const QString &identifier, 0448 ExpandMode mode = ExpandMode::Expanded) const; 0449 0450 //! Mode for fieldsExpanded() and visibleFieldsExpanded() 0451 //! @since 3.1 0452 enum class FieldsExpandedMode { 0453 Default, //!< All fields are returned even if duplicated 0454 Unique, //!< Unique list of fields is returned 0455 WithInternalFields, //!< Like Default but internal fields (for lookup) are appended 0456 WithInternalFieldsAndRecordId //!< Like WithInternalFields but record ID (big int type) field 0457 //!< is appended after internal fields 0458 }; 0459 0460 /*! @return fully expanded list of fields. 0461 KDbQuerySchema::fields() returns vector of fields used for the query columns, 0462 but in a case when there are asterisks defined for the query, 0463 it does not expand KDbQueryAsterisk objects to field lists but return every 0464 asterisk as-is. 0465 This could be inconvenient when you need just a fully expanded list of fields, 0466 so this method does the work for you. 0467 0468 If @a options is Unique, each field is returned in the vector only once 0469 (first found field is selected). 0470 Note however, that the same field can be returned more than once if it has attached 0471 a different alias. 0472 For example, let t be TABLE( a, b ) and let query be defined 0473 by "SELECT *, a AS alfa FROM t" statement. Both fieldsExpanded(Default) 0474 and fieldsExpanded(Unique) will return [ a, b, a (alfa) ] list. 0475 On the other hand, for query defined by "SELECT *, a FROM t" statement, 0476 fieldsExpanded(Default) will return [ a, b, a ] list while 0477 fieldsExpanded(Unique) will return [ a, b ] list. 0478 0479 If @a options is WithInternalFields or WithInternalFieldsAndRecordID, 0480 additional internal fields are also appended to the vector. 0481 0482 If @a options is WithInternalFieldsAndRecordId, 0483 one fake BigInteger column is appended to make space for Record ID column used 0484 by KDbCursor implementations. For example, let city_id in TABLE persons(surname, city_id) 0485 reference cities.id in TABLE cities(id, name) and let query q be defined 0486 by "SELECT * FROM persons" statement. We want to display persons' city names instead of city_id's. 0487 To do this, cities.name has to be retrieved as well, so the following statement should be used: 0488 "SELECT * FROM persons, cities.name LEFT OUTER JOIN cities ON persons.city_id=cities.id". 0489 Thus, calling fieldsExpanded(WithInternalFieldsAndRecordId) will return 4 elements instead of 2: 0490 persons.surname, persons.city_id, cities.name, {ROWID}. The {ROWID} item is the placeholder 0491 used for fetching ROWID by KDb cursors. 0492 0493 By default, all fields are returned in the vector even 0494 if there are multiple occurrences of one or more (options == Default). 0495 0496 Note: You should assign the resulted vector in your space - it will be shared 0497 and implicity copied on any modification. 0498 This method's result is cached by KDbQuerySchema object. 0499 @todo js: UPDATE CACHE! 0500 */ 0501 inline KDbQueryColumnInfo::Vector fieldsExpanded( 0502 KDbConnection *conn, FieldsExpandedMode mode = FieldsExpandedMode::Default) const 0503 { 0504 return fieldsExpandedInternal(conn, mode, false); 0505 } 0506 0507 /*! Like fieldsExpanded() but returns only visible fields. */ 0508 inline KDbQueryColumnInfo::Vector visibleFieldsExpanded( 0509 KDbConnection *conn, FieldsExpandedMode options = FieldsExpandedMode::Default) const 0510 { 0511 return fieldsExpandedInternal(conn, options, true); 0512 } 0513 0514 /*! @return list of internal fields used for lookup columns. */ 0515 KDbQueryColumnInfo::Vector internalFields(KDbConnection *conn) const; 0516 0517 /*! @return info for expanded of internal field at index @a index. 0518 The returned field can be either logical or internal (for lookup), 0519 the latter case is @c true if @a index >= fieldsExpanded().count(). 0520 Equivalent of KDbQuerySchema::fieldsExpanded(WithInternalFields).at(index). */ 0521 KDbQueryColumnInfo* expandedOrInternalField(KDbConnection *conn, int index) const; 0522 0523 //! Mode for columnsOrder() 0524 //! @since 3.1 0525 enum class ColumnsOrderMode { 0526 UnexpandedList, //!< A map for unexpanded list is created 0527 UnexpandedListWithoutAsterisks, //!< A map for unexpanded list is created, with asterisks skipped 0528 ExpandedList //!< A map for expanded list is created 0529 }; 0530 0531 /*! @return a hash for fast lookup of query columns' order. 0532 - If @a options is UnexpandedList, each KDbQueryColumnInfo pointer is mapped to the index 0533 within (unexpanded) list of fields, i.e. "*" or "table.*" asterisks are considered 0534 to be single items. 0535 - If @a options is UnexpandedListWithoutAsterisks, each KDbQueryColumnInfo pointer 0536 is mapped to the index within (unexpanded) list of columns that come from asterisks 0537 like "*" or "table.*" are not included in the map at all. 0538 - If @a options is ExpandedList (the default) this method provides is exactly opposite 0539 information compared to vector returned by fieldsExpanded(). 0540 0541 This method's result is cached by the KDbQuerySchema object. 0542 Note: indices of internal fields (see internalFields()) are also returned 0543 here - in this case the index is counted as a sum of size(e) + i (where "e" is 0544 the list of expanded fields and i is the column index within internal fields list). 0545 This feature is used eg. at the end of KDbConnection::updateRecord() where need indices of 0546 fields (including internal) to update all the values in memory. 0547 0548 Example use: let t be table (int id, name text, surname text) and q be query 0549 defined by a statement "select * from t". 0550 0551 - columnsOrder(ExpandedList) will return the following map: KDbQueryColumnInfo(id)->0, 0552 KDbQueryColumnInfo(name)->1, KDbQueryColumnInfo(surname)->2. 0553 - columnsOrder(UnexpandedList) will return the following map: KDbQueryColumnInfo(id)->0, 0554 KDbQueryColumnInfo(name)->0, KDbQueryColumnInfo(surname)->0 because the column 0555 list is not expanded. This way you can use the returned index to get KDbField* 0556 pointer using field(int) method of KDbFieldList superclass. 0557 - columnsOrder(UnexpandedListWithoutAsterisks) will return the following map: 0558 KDbQueryColumnInfo(id)->0, 0559 */ 0560 QHash<KDbQueryColumnInfo *, int> columnsOrder(KDbConnection *conn, 0561 ColumnsOrderMode mode = ColumnsOrderMode::ExpandedList) const; 0562 0563 /*! @return table describing order of primary key (PKEY) fields within the query. 0564 Indexing is performed against vector returned by fieldsExpanded(). 0565 It is usable for e.g. Connection::updateRecord(), when we need 0566 to locate each primary key's field in a constant time. 0567 0568 Returned vector is owned and cached by KDbQuerySchema object. When you assign it, 0569 it is implicity shared. Its size is equal to number of primary key 0570 fields defined for master table (masterTable()->primaryKey()->fieldCount()). 0571 0572 Each element of the returned vector: 0573 - can belong to [0..fieldsExpanded().count()-1] if there is such 0574 primary key's field in the fieldsExpanded() list. 0575 - can be equal to -1 if there is no such primary key's field 0576 in the fieldsExpanded() list. 0577 0578 If there are more than one primary key's field included in the query, 0579 only first-found column (oin the fieldsExpanded() list) for each pkey's field is included. 0580 0581 Returns empty vector if there is no master table or no master table's pkey. 0582 @see example for pkeyFieldCount(). 0583 @todo js: UPDATE CACHE! 0584 */ 0585 QVector<int> pkeyFieldsOrder(KDbConnection *conn) const; 0586 0587 /*! @return number of master table's primary key fields included in this query. 0588 This method is useful to quickly check whether the vector returned by pkeyFieldsOrder() 0589 if filled completely. 0590 0591 User e.g. in KDbConnection::updateRecord() to check if entire primary 0592 key information is specified. 0593 0594 Examples: let table T has (ID1 INTEGER, ID2 INTEGER, A INTEGER) fields, 0595 and let (ID1, ID2) is T's primary key. 0596 -# The query defined by "SELECT * FROM T" statement contains all T's 0597 primary key's fields as T is the master table, and thus pkeyFieldCount() 0598 will return 2 (both primary key's fields are in the fieldsExpanded() list), 0599 and pkeyFieldsOrder() will return vector {0, 1}. 0600 -# The query defined by "SELECT A, ID2 FROM T" statement, and thus pkeyFieldCount() 0601 will return 1 (only one primary key's field is in the fieldsExpanded() list), 0602 and pkeyFieldsOrder() will return vector {-1, 1}, as second primary key's field 0603 is at position #1 and first field is not specified at all within the query. 0604 */ 0605 int pkeyFieldCount(KDbConnection *conn); 0606 0607 /*! @return a list of field infos for all auto-incremented fields 0608 from master table of this query. This result is cached for efficiency. 0609 fieldsExpanded() is used for that. 0610 */ 0611 KDbQueryColumnInfo::List* autoIncrementFields(KDbConnection *conn) const; 0612 0613 /*! @return a preset statement (if any). */ 0614 KDbEscapedString statement() const; 0615 0616 /*! Forces a raw SQL statement @a sql for the query. This means that no statement is composed 0617 * from KDbQuerySchema's content. */ 0618 void setStatement(const KDbEscapedString& sql); 0619 0620 /*! @return a string that is a result of concatenating all column names 0621 for @a infolist, with "," between each one. 0622 This is usable e.g. as argument like "field1,field2" 0623 for "INSERT INTO (xxx) ..". The result of this method is effectively cached, 0624 and it is invalidated when set of fields changes (e.g. using clear() 0625 or addField()). 0626 0627 This method is similar to KDbFieldList::sqlFieldsList() it just uses 0628 KDbQueryColumnInfo::List instead of KDbField::List. 0629 0630 @a escapingType can be used to alter default escaping type. 0631 If @a conn is not provided for DriverEscaping, no escaping is performed. */ 0632 static KDbEscapedString 0633 sqlColumnsList(const KDbQueryColumnInfo::List &infolist, KDbConnection *conn = nullptr, 0634 KDb::IdentifierEscapingType escapingType = KDb::DriverEscaping); 0635 0636 /*! @return cached list of autoincrement fields created using sqlColumnsList() 0637 on a list returned by autoIncrementFields(). The field names are escaped using 0638 driver escaping. */ 0639 KDbEscapedString autoIncrementSqlFieldsList(KDbConnection *conn) const; 0640 0641 /** 0642 * @brief Sets a WHERE expression @a exp. 0643 * 0644 * Previously set WHERE expression will be removed. A null expression 0645 * (KDbExpression()) can be passed to remove existing WHERE expresssion. 0646 * @return @c false if @a expr is not a valid WHERE expression. validate() is called 0647 * to check this. On failure the WHERE expression for this query is cleared. In this 0648 * case a string pointed by @a errorMessage (if provided) is set to a general error 0649 * message and a string pointed by @a errorDescription (if provided) is set to a 0650 * detailed description of the error. 0651 */ 0652 bool setWhereExpression(const KDbExpression &expr, QString *errorMessage = nullptr, 0653 QString *errorDescription = nullptr); 0654 0655 /*! @return WHERE expression or 0 if this query has no WHERE expression */ 0656 KDbExpression whereExpression() const; 0657 0658 /** 0659 * @brief Appends a part to WHERE expression. 0660 * 0661 * Simplifies creating of WHERE expression if used instead of setWhereExpression(). 0662 * @return @c false if the newly constructed WHERE expression is not valid. 0663 * validate() is called to check this. On failure the WHERE expression for this query 0664 * is left unchanged. In this case a string pointed by @a errorMessage (if provided) 0665 * is set to a general error message and a string pointed by @a errorDescription 0666 * (if provided) is set to a detailed description of the error. 0667 */ 0668 bool addToWhereExpression(KDbField *field, const QVariant &value, 0669 KDbToken relation = '=', QString *errorMessage = nullptr, 0670 QString *errorDescription = nullptr); 0671 0672 /*! Sets a list of columns for ORDER BY section of the query. 0673 Each name on the list must be a field or alias present within the query 0674 and must not be covered by aliases. If one or more names cannot be found 0675 within the query, the method will have no effect. 0676 Any previous ORDER BY settings will be removed. 0677 0678 Note that this information is cleared whenever you call methods that 0679 modify list of columns (KDbQueryColumnInfo), i.e. insertField(), 0680 addField(), removeField(), addExpression(), etc. 0681 (because KDbOrderByColumn items can point to a KDbQueryColumnInfo that's removed by these 0682 methods), so you should use setOrderByColumnList() method after the query 0683 is completely built. */ 0684 void setOrderByColumnList(const KDbOrderByColumnList& list); 0685 0686 /*! @return a list of columns listed in ORDER BY section of the query. 0687 Read notes for @ref setOrderByColumnList(). */ 0688 KDbOrderByColumnList* orderByColumnList(); 0689 0690 /*! @see orderByColumnList() */ 0691 const KDbOrderByColumnList* orderByColumnList() const; 0692 0693 /*! @return query schema parameters. These are taked from the WHERE section 0694 (a tree of expression items). */ 0695 QList<KDbQuerySchemaParameter> parameters(KDbConnection *conn) const; 0696 0697 //! @return @c true if this query is valid 0698 /*! Detailed validation is performed in the same way as parsing of query statements 0699 * by the KDbParser. 0700 * Example :Let the query be "SELECT <fields> FROM <tables> WHERE <whereExpression>". 0701 * First each field from <fields> (@see fields()) is validated using 0702 * KDbField::expression().validate(). Then the <whereExpression> (@see 0703 * whereExpression()) 0704 * is validated using KDbExpression::validate(). 0705 * 0706 * On error a string pointed by @a errorMessage (if provided) is set to a general 0707 * error message and a string pointed by @a errorDescription (if provided) is set to a 0708 * detailed description of the error. 0709 */ 0710 //! @todo add tests 0711 bool validate(QString *errorMessage = nullptr, QString *errorDescription = nullptr); 0712 0713 protected: 0714 KDbQuerySchemaFieldsExpanded *computeFieldsExpanded(KDbConnection *conn) const; 0715 0716 //! Used by fieldsExpanded(KDbConnection*, FieldsExpandedMode) 0717 //! and visibleFieldsExpanded(KDbConnection*, FieldsExpandedMode). 0718 KDbQueryColumnInfo::Vector fieldsExpandedInternal(KDbConnection *conn, 0719 FieldsExpandedMode mode, 0720 bool onlyVisible) const; 0721 0722 /** Internal method used by all insert*Field methods. 0723 * The new column can also be explicitly bound to a specific position on tables list. 0724 * @a bindToTable is a table index within the query for which the field should be bound. 0725 * If @a bindToTable is -1, no particular table will be bound. 0726 * @see tableBoundToColumn(int columnPosition) 0727 */ 0728 bool insertFieldInternal(int position, KDbField *field, int bindToTable, bool visible); 0729 0730 /** 0731 * Internal method used by add*Asterisk() methods. 0732 * Appends @a asterisk at the and of columns list, sets visibility. 0733 */ 0734 bool addAsteriskInternal(KDbQueryAsterisk *asterisk, bool visible); 0735 0736 /** Internal method used by all add*Expression methods. 0737 * Appends expression @a expr at the and of columns list, sets visibility. 0738 */ 0739 bool addExpressionInternal(const KDbExpression& expr, bool visible); 0740 0741 /** Internal method used by a query parser. 0742 */ 0743 void setWhereExpressionInternal(const KDbExpression &expr); 0744 0745 friend class KDbQuerySchemaPrivate; 0746 0747 Q_DISABLE_COPY(KDbQuerySchema) 0748 KDbQuerySchemaPrivate * const d; 0749 }; 0750 0751 //! A pair (connection, table-or-schema) for QDebug operator<< 0752 //! @since 3.1 0753 typedef std::tuple<KDbConnection*, const KDbQuerySchema&> KDbConnectionAndQuerySchema; 0754 0755 //! Sends connection and query schema information @a connectionAndSchema to debug output @a dbg. 0756 //! @since 3.1 0757 KDB_EXPORT QDebug operator<<(QDebug dbg, 0758 const KDbConnectionAndQuerySchema &connectionAndSchema); 0759 0760 #endif