1 /* This file is part of the KDE project
2    Copyright (C) 2003-2018 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_ORDERBYCOLUMN_H
21 #define KDB_ORDERBYCOLUMN_H
22 
23 #include "KDbEscapedString.h"
24 #include "KDbGlobal.h"
25 
26 class KDbConnection;
27 class KDbField;
28 class KDbQueryColumnInfo;
29 class KDbQuerySchema;
30 
31 //! @short KDbOrderByColumn provides information about a single query column used for sorting
32 /*! The column can be expression or table field. */
33 class KDB_EXPORT KDbOrderByColumn
34 {
35 public:
36     //! Column sort order
37     //! @since 3.1
38     enum class SortOrder {
39         Ascending = Qt::AscendingOrder,
40         Descending = Qt::DescendingOrder
41     };
42 
43     //! Creates an empty information about a single query column.
44     KDbOrderByColumn();
45 
46     //! Creates a copy of the @a other
47     //! @since 3.1
48     KDbOrderByColumn(const KDbOrderByColumn &other);
49 
50     //! Creates information about a single query column @a column used for sorting.
51     explicit KDbOrderByColumn(KDbQueryColumnInfo* column,
52                               SortOrder order = SortOrder::Ascending, int pos = -1);
53 
54     //! Like above but used when the field @a field is not present on the list of columns.
55     //! (e.g. SELECT a FROM t ORDER BY b; where T is a table with fields (a,b)).
56     explicit KDbOrderByColumn(KDbField* field, SortOrder order = SortOrder::Ascending);
57 
58     ~KDbOrderByColumn();
59 
60     /*! @return copy of this KDbOrderByColumn object.
61      @a fromQuery and @a toQuery is needed if column() is assigned to this info.
62      Then, column info within @a toQuery will be assigned to the new KDbOrderByColumn object,
63      corresponding to column() from "this" KDbOrderByColumn object. */
64     KDbOrderByColumn *copy(KDbConnection *conn, KDbQuerySchema *fromQuery,
65                            KDbQuerySchema *toQuery) const Q_REQUIRED_RESULT;
66 
67     //! A column to sort.
68     KDbQueryColumnInfo* column() const;
69 
70     /*! A helper for column() that allows you to know that sorting column
71      was defined by providing its position. -1 by default.
72      Example query: SELECT a, b FROM T ORDER BY 2 */
73     int position() const;
74 
75     //! A field to sort, used only in case when the second constructor was used.
76     KDbField *field() const;
77 
78     //! @return sort order for the column
79     KDbOrderByColumn::SortOrder sortOrder() const;
80 
81     //! Assigns @a other to this object returns a reference to this object.
82     //! @since 3.1
83     KDbOrderByColumn& operator=(const KDbOrderByColumn &other);
84 
85     //! @return true if this column is the same as @a col
86     bool operator==(const KDbOrderByColumn& col) const;
87 
88     //! @return @c true if this object is not equal to @a other; otherwise returns @c false.
89     //! @since 3.1
90     inline bool operator!=(const KDbOrderByColumn &other) const { return !operator==(other); }
91 
92     /** Return an SQL string like "name ASC" or "2 DESC" usable for building an SQL statement
93      *
94      * If @a includeTableNames is @c true fields that are related to a table are
95      * printed as "tablename.fieldname".
96      *
97      * @a escapingType can be used to alter default escaping type.
98      * If @a conn is not provided for DriverEscaping, no escaping is performed.
99      * If @a query is provided, it can be used to obtain alias information.
100      *
101      * @since 3.2
102      */
103     KDbEscapedString toSqlString(bool includeTableName,
104                                  KDbConnection *conn, KDbQuerySchema *query,
105                                  KDb::IdentifierEscapingType escapingType = KDb::DriverEscaping) const;
106 
107     /*! @overload
108 
109      @deprecated since 3.2, use overload that also takes query schema
110     */
111     KDB_DEPRECATED KDbEscapedString toSqlString(bool includeTableName = true,
112                                  KDbConnection *conn = nullptr,
113                                  KDb::IdentifierEscapingType escapingType = KDb::DriverEscaping) const;
114 
115     //! Converts @a order to Qt::SortOrder type
toQt(SortOrder order)116     inline static Qt::SortOrder toQt(SortOrder order) { return static_cast<Qt::SortOrder>(order); }
117 
118     //! Converts @a order to SortOrder type
fromQt(Qt::SortOrder order)119     inline static SortOrder fromQt(Qt::SortOrder order) { return static_cast<SortOrder>(order); }
120 
121 private:
122     class Private;
123     Private * const d;
124 };
125 
126 //! @short KDbOrderByColumnList provides list of sorted columns for a query schema
127 class KDB_EXPORT KDbOrderByColumnList
128 {
129 public:
130     /*! Constructs empty list of ordered columns. */
131     KDbOrderByColumnList();
132 
133     /*! A copy constructor. */
134     KDbOrderByColumnList(const KDbOrderByColumnList& other, KDbConnection *conn,
135                          KDbQuerySchema* fromQuery, KDbQuerySchema* toQuery);
136 
137     ~KDbOrderByColumnList();
138 
139     //! @return @c true if this object is equal to @a other; otherwise returns @c false.
140     //! @since 3.1
141     bool operator==(const KDbOrderByColumnList &other) const;
142 
143     //! @return @c true if this object is not equal to @a other; otherwise returns @c false.
144     //! @since 3.1
145     inline bool operator!=(const KDbOrderByColumnList &other) const { return !operator==(other); }
146 
147     //! Returns column with given index.
148     //! @since 3.1
149     const KDbOrderByColumn* value(int index) const;
150 
151     //! @overload
152     KDbOrderByColumn* value(int index);
153 
154     /*! Appends multiple fields for sorting. @a querySchema
155      is used to find appropriate field or alias name.
156      @return false if there is at least one name for which a field or alias name does not exist
157      (all the newly appended fields are removed in this case)
158      Returns @c false if @a querySchema is @c nullptr. */
159     bool appendFields(KDbConnection *conn, KDbQuerySchema* querySchema,
160                       const QString& field1, KDbOrderByColumn::SortOrder order1 = KDbOrderByColumn::SortOrder::Ascending,
161                       const QString& field2 = QString(), KDbOrderByColumn::SortOrder order2 = KDbOrderByColumn::SortOrder::Ascending,
162                       const QString& field3 = QString(), KDbOrderByColumn::SortOrder order3 = KDbOrderByColumn::SortOrder::Ascending,
163                       const QString& field4 = QString(), KDbOrderByColumn::SortOrder order4 = KDbOrderByColumn::SortOrder::Ascending,
164                       const QString& field5 = QString(), KDbOrderByColumn::SortOrder order5 = KDbOrderByColumn::SortOrder::Ascending);
165 
166     /*! Appends column @a columnInfo.
167      Does nothing if @a columnInfo is @c nullptr. */
168     void appendColumn(KDbQueryColumnInfo* columnInfo,
169                       KDbOrderByColumn::SortOrder order = KDbOrderByColumn::SortOrder::Ascending);
170 
171     /*! Appends a field @a field.
172      Read documentation of @ref KDbOrderByColumn(KDbField* field, SortOrder order)
173      for more info.
174      Does nothing if @a field is @c nullptr. */
175     void appendField(KDbField* field,
176                      KDbOrderByColumn::SortOrder order = KDbOrderByColumn::SortOrder::Ascending);
177 
178     /*! Appends field with a name @a field.
179      @return @c true on successful appending, and @c false if there is no such field or alias
180      name in the @a querySchema.
181      Returns @c false if @a querySchema is @c nullptr. */
182     bool appendField(KDbConnection *conn, KDbQuerySchema* querySchema, const QString& fieldName,
183                      KDbOrderByColumn::SortOrder order = KDbOrderByColumn::SortOrder::Ascending);
184 
185     /*! Appends a column that is at position @a pos (counted from 0).
186      @return true on successful adding and false if there is no such position @a pos.
187      Returns @c false if @a querySchema is @c nullptr. */
188     bool appendColumn(KDbConnection *conn, KDbQuerySchema* querySchema,
189                       KDbOrderByColumn::SortOrder order = KDbOrderByColumn::SortOrder::Ascending,
190                       int pos = -1);
191 
192     /*! @return true if the list is empty. */
193     bool isEmpty() const;
194 
195     /*! @return number of elements of the list. */
196     int count() const;
197 
198     /*! Removes all elements from the list (deletes them). */
199     void clear();
200 
201     /*! Returns an STL-style iterator pointing to the first column in the list. */
202     QList<KDbOrderByColumn*>::Iterator begin();
203 
204     /*! Returns an STL-style iterator pointing to the imaginary item after the last column
205      * in the list.
206      */
207     QList<KDbOrderByColumn*>::Iterator end();
208 
209     /*! Returns an const STL-style iterator pointing to the first column in the list. */
210     QList<KDbOrderByColumn*>::ConstIterator constBegin() const;
211 
212     /*! Returns a const STL-style iterator pointing to the imaginary item after the last column
213      * in the list.
214      */
215     QList<KDbOrderByColumn*>::ConstIterator constEnd() const;
216 
217     /** Return an SQL string like "name ASC, 2 DESC" usable for building an SQL statement
218      *
219      * If @a includeTableNames is @c true (the default) fields that are related to a table are
220      * printed as "tablename.fieldname".
221      *
222      * @a escapingType can be used to alter default escaping type.
223      * If @a conn is not provided for DriverEscaping, no escaping is performed.
224      * If @a query is provided, it can be used to obtain alias information.
225      *
226      * @since 3.2
227      */
228     KDbEscapedString toSqlString(bool includeTableNames,
229                                  KDbConnection *conn, KDbQuerySchema *query,
230                                  KDb::IdentifierEscapingType escapingType = KDb::DriverEscaping) const;
231 
232     /*! @overload
233 
234      @deprecated since 3.2, use overload that also takes query schema
235     */
236     KDB_DEPRECATED KDbEscapedString toSqlString(bool includeTableNames = true,
237                                  KDbConnection *conn = nullptr,
238                                  KDb::IdentifierEscapingType escapingType = KDb::DriverEscaping) const;
239 
240 private:
241     class Private;
242     Private * const d;
243     Q_DISABLE_COPY(KDbOrderByColumnList)
244 };
245 
246 //! Sends order-by-column information @a order to debug output @a dbg.
247 KDB_EXPORT QDebug operator<<(QDebug dbg, const KDbOrderByColumn& order);
248 
249 //! Sends order-by-column-list information @a list to debug output @a dbg.
250 KDB_EXPORT QDebug operator<<(QDebug dbg, const KDbOrderByColumnList& list);
251 
252 #endif
253