1/****************************************************************************
2**
3** Copyright (C) 2016 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the QtSql module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU Lesser General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU Lesser
19** General Public License version 3 as published by the Free Software
20** Foundation and appearing in the file LICENSE.LGPL3 included in the
21** packaging of this file. Please review the following information to
22** ensure the GNU Lesser General Public License version 3 requirements
23** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24**
25** GNU General Public License Usage
26** Alternatively, this file may be used under the terms of the GNU
27** General Public License version 2.0 or (at your option) the GNU General
28** Public license version 3 or any later version approved by the KDE Free
29** Qt Foundation. The licenses are as published by the Free Software
30** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31** included in the packaging of this file. Please review the following
32** information to ensure the GNU General Public License requirements will
33** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34** https://www.gnu.org/licenses/gpl-3.0.html.
35**
36** $QT_END_LICENSE$
37**
38****************************************************************************/
39
40#include "qsqlrecord.h"
41
42#include "qdebug.h"
43#include "qstringlist.h"
44#include "qatomic.h"
45#include "qsqlfield.h"
46#include "qstring.h"
47#include "qvector.h"
48
49QT_BEGIN_NAMESPACE
50
51class QSqlRecordPrivate
52{
53public:
54 QSqlRecordPrivate();
55 QSqlRecordPrivate(const QSqlRecordPrivate &other);
56
57 inline bool contains(int index) { return index >= 0 && index < fields.count(); }
58 QString createField(int index, const QString &prefix) const;
59
60 QVector<QSqlField> fields;
61 QAtomicInt ref;
62};
63
64QSqlRecordPrivate::QSqlRecordPrivate() : ref(1)
65{
66}
67
68QSqlRecordPrivate::QSqlRecordPrivate(const QSqlRecordPrivate &other): fields(other.fields), ref(1)
69{
70}
71
72/*! \internal
73 Just for compat
74*/
75QString QSqlRecordPrivate::createField(int index, const QString &prefix) const
76{
77 QString f;
78 if (!prefix.isEmpty())
79 f = prefix + QLatin1Char('.');
80 f += fields.at(i: index).name();
81 return f;
82}
83
84/*!
85 \class QSqlRecord
86 \brief The QSqlRecord class encapsulates a database record.
87
88 \ingroup database
89 \ingroup shared
90 \inmodule QtSql
91
92 The QSqlRecord class encapsulates the functionality and
93 characteristics of a database record (usually a row in a table or
94 view within the database). QSqlRecord supports adding and
95 removing fields as well as setting and retrieving field values.
96
97 The values of a record's fields can be set by name or position
98 with setValue(); if you want to set a field to null use
99 setNull(). To find the position of a field by name use indexOf(),
100 and to find the name of a field at a particular position use
101 fieldName(). Use field() to retrieve a QSqlField object for a
102 given field. Use contains() to see if the record contains a
103 particular field name.
104
105 When queries are generated to be executed on the database only
106 those fields for which isGenerated() is true are included in the
107 generated SQL.
108
109 A record can have fields added with append() or insert(), replaced
110 with replace(), and removed with remove(). All the fields can be
111 removed with clear(). The number of fields is given by count();
112 all their values can be cleared (to null) using clearValues().
113
114 \sa QSqlField, QSqlQuery::record()
115*/
116
117
118/*!
119 Constructs an empty record.
120
121 \sa isEmpty(), append(), insert()
122*/
123
124QSqlRecord::QSqlRecord()
125{
126 d = new QSqlRecordPrivate();
127}
128
129/*!
130 Constructs a copy of \a other.
131
132 QSqlRecord is \l{implicitly shared}. This means you can make copies
133 of a record in \l{constant time}.
134*/
135
136QSqlRecord::QSqlRecord(const QSqlRecord& other)
137{
138 d = other.d;
139 d->ref.ref();
140}
141
142/*!
143 Sets the record equal to \a other.
144
145 QSqlRecord is \l{implicitly shared}. This means you can make copies
146 of a record in \l{constant time}.
147*/
148
149QSqlRecord& QSqlRecord::operator=(const QSqlRecord& other)
150{
151 qAtomicAssign(d, x: other.d);
152 return *this;
153}
154
155/*!
156 Destroys the object and frees any allocated resources.
157*/
158
159QSqlRecord::~QSqlRecord()
160{
161 if (!d->ref.deref())
162 delete d;
163}
164
165/*!
166 \fn bool QSqlRecord::operator!=(const QSqlRecord &other) const
167
168 Returns \c true if this object is not identical to \a other;
169 otherwise returns \c false.
170
171 \sa operator==()
172*/
173
174/*!
175 Returns \c true if this object is identical to \a other (i.e., has
176 the same fields in the same order); otherwise returns \c false.
177
178 \sa operator!=()
179*/
180bool QSqlRecord::operator==(const QSqlRecord &other) const
181{
182 return d->fields == other.d->fields;
183}
184
185/*!
186 Returns the value of the field located at position \a index in
187 the record. If \a index is out of bounds, an invalid QVariant
188 is returned.
189
190 \sa fieldName(), isNull()
191*/
192
193QVariant QSqlRecord::value(int index) const
194{
195 return d->fields.value(i: index).value();
196}
197
198/*!
199 \overload
200
201 Returns the value of the field called \a name in the record. If
202 field \a name does not exist an invalid variant is returned.
203
204 \sa indexOf()
205*/
206
207QVariant QSqlRecord::value(const QString& name) const
208{
209 return value(index: indexOf(name));
210}
211
212/*!
213 Returns the name of the field at position \a index. If the field
214 does not exist, an empty string is returned.
215
216 \sa indexOf()
217*/
218
219QString QSqlRecord::fieldName(int index) const
220{
221 return d->fields.value(i: index).name();
222}
223
224/*!
225 Returns the position of the field called \a name within the
226 record, or -1 if it cannot be found. Field names are not
227 case-sensitive. If more than one field matches, the first one is
228 returned.
229
230 \sa fieldName()
231*/
232
233int QSqlRecord::indexOf(const QString& name) const
234{
235 QStringRef tableName;
236 QStringRef fieldName(&name);
237 const int idx = name.indexOf(c: QLatin1Char('.'));
238 if (idx != -1) {
239 tableName = name.leftRef(n: idx);
240 fieldName = name.midRef(position: idx + 1);
241 }
242 const int cnt = count();
243 for (int i = 0; i < cnt; ++i) {
244 // Check the passed in name first in case it is an alias using a dot.
245 // Then check if both the table and field match when there is a table name specified.
246 const auto &currentField = d->fields.at(i);
247 const auto &currentFieldName = currentField.name();
248 if (currentFieldName.compare(s: name, cs: Qt::CaseInsensitive) == 0
249 || (idx != -1 && currentFieldName.compare(s: fieldName, cs: Qt::CaseInsensitive) == 0
250 && currentField.tableName().compare(s: tableName, cs: Qt::CaseInsensitive) == 0)) {
251 return i;
252 }
253 }
254 return -1;
255}
256
257/*!
258 Returns the field at position \a index. If the \a index
259 is out of range, function returns
260 a \l{default-constructed value}.
261 */
262QSqlField QSqlRecord::field(int index) const
263{
264 return d->fields.value(i: index);
265}
266
267/*! \overload
268 Returns the field called \a name.
269 */
270QSqlField QSqlRecord::field(const QString &name) const
271{
272 return field(index: indexOf(name));
273}
274
275
276/*!
277 Append a copy of field \a field to the end of the record.
278
279 \sa insert(), replace(), remove()
280*/
281
282void QSqlRecord::append(const QSqlField& field)
283{
284 detach();
285 d->fields.append(t: field);
286}
287
288/*!
289 Inserts the field \a field at position \a pos in the record.
290
291 \sa append(), replace(), remove()
292 */
293void QSqlRecord::insert(int pos, const QSqlField& field)
294{
295 detach();
296 d->fields.insert(i: pos, t: field);
297}
298
299/*!
300 Replaces the field at position \a pos with the given \a field. If
301 \a pos is out of range, nothing happens.
302
303 \sa append(), insert(), remove()
304*/
305
306void QSqlRecord::replace(int pos, const QSqlField& field)
307{
308 if (!d->contains(index: pos))
309 return;
310
311 detach();
312 d->fields[pos] = field;
313}
314
315/*!
316 Removes the field at position \a pos. If \a pos is out of range,
317 nothing happens.
318
319 \sa append(), insert(), replace()
320*/
321
322void QSqlRecord::remove(int pos)
323{
324 if (!d->contains(index: pos))
325 return;
326
327 detach();
328 d->fields.remove(i: pos);
329}
330
331/*!
332 Removes all the record's fields.
333
334 \sa clearValues(), isEmpty()
335*/
336
337void QSqlRecord::clear()
338{
339 detach();
340 d->fields.clear();
341}
342
343/*!
344 Returns \c true if there are no fields in the record; otherwise
345 returns \c false.
346
347 \sa append(), insert(), clear()
348*/
349
350bool QSqlRecord::isEmpty() const
351{
352 return d->fields.isEmpty();
353}
354
355
356/*!
357 Returns \c true if there is a field in the record called \a name;
358 otherwise returns \c false.
359*/
360
361bool QSqlRecord::contains(const QString& name) const
362{
363 return indexOf(name) >= 0;
364}
365
366/*!
367 Clears the value of all fields in the record and sets each field
368 to null.
369
370 \sa setValue()
371*/
372
373void QSqlRecord::clearValues()
374{
375 detach();
376 int count = d->fields.count();
377 for (int i = 0; i < count; ++i)
378 d->fields[i].clear();
379}
380
381/*!
382 Sets the generated flag for the field called \a name to \a
383 generated. If the field does not exist, nothing happens. Only
384 fields that have \a generated set to true are included in the SQL
385 that is generated by QSqlQueryModel for example.
386
387 \sa isGenerated()
388*/
389
390void QSqlRecord::setGenerated(const QString& name, bool generated)
391{
392 setGenerated(i: indexOf(name), generated);
393}
394
395/*!
396 \overload
397
398 Sets the generated flag for the field \a index to \a generated.
399
400 \sa isGenerated()
401*/
402
403void QSqlRecord::setGenerated(int index, bool generated)
404{
405 if (!d->contains(index))
406 return;
407 detach();
408 d->fields[index].setGenerated(generated);
409}
410
411/*!
412 \overload
413
414 Returns \c true if the field \a index is null or if there is no field at
415 position \a index; otherwise returns \c false.
416*/
417bool QSqlRecord::isNull(int index) const
418{
419 return d->fields.value(i: index).isNull();
420}
421
422/*!
423 Returns \c true if the field called \a name is null or if there is no
424 field called \a name; otherwise returns \c false.
425
426 \sa setNull()
427*/
428bool QSqlRecord::isNull(const QString& name) const
429{
430 return isNull(index: indexOf(name));
431}
432
433/*!
434 Sets the value of field \a index to null. If the field does not exist,
435 nothing happens.
436
437 \sa setValue()
438*/
439void QSqlRecord::setNull(int index)
440{
441 if (!d->contains(index))
442 return;
443 detach();
444 d->fields[index].clear();
445}
446
447/*!
448 \overload
449
450 Sets the value of the field called \a name to null. If the field
451 does not exist, nothing happens.
452*/
453void QSqlRecord::setNull(const QString& name)
454{
455 setNull(indexOf(name));
456}
457
458
459/*!
460 Returns \c true if the record has a field called \a name and this
461 field is to be generated (the default); otherwise returns \c false.
462
463 \sa setGenerated()
464*/
465bool QSqlRecord::isGenerated(const QString& name) const
466{
467 return isGenerated(i: indexOf(name));
468}
469
470/*! \overload
471
472 Returns \c true if the record has a field at position \a index and this
473 field is to be generated (the default); otherwise returns \c false.
474
475 \sa setGenerated()
476*/
477bool QSqlRecord::isGenerated(int index) const
478{
479 return d->fields.value(i: index).isGenerated();
480}
481
482/*!
483 Returns the number of fields in the record.
484
485 \sa isEmpty()
486*/
487
488int QSqlRecord::count() const
489{
490 return d->fields.count();
491}
492
493/*!
494 Sets the value of the field at position \a index to \a val. If the
495 field does not exist, nothing happens.
496
497 \sa setNull()
498*/
499
500void QSqlRecord::setValue(int index, const QVariant& val)
501{
502 if (!d->contains(index))
503 return;
504 detach();
505 d->fields[index].setValue(val);
506}
507
508
509/*!
510 \overload
511
512 Sets the value of the field called \a name to \a val. If the field
513 does not exist, nothing happens.
514*/
515
516void QSqlRecord::setValue(const QString& name, const QVariant& val)
517{
518 setValue(index: indexOf(name), val);
519}
520
521
522/*! \internal
523*/
524void QSqlRecord::detach()
525{
526 qAtomicDetach(d);
527}
528
529#ifndef QT_NO_DEBUG_STREAM
530QDebug operator<<(QDebug dbg, const QSqlRecord &r)
531{
532 QDebugStateSaver saver(dbg);
533 dbg.nospace();
534 const int count = r.count();
535 dbg << "QSqlRecord(" << count << ')';
536 for (int i = 0; i < count; ++i) {
537 dbg.nospace();
538 dbg << '\n' << qSetFieldWidth(width: 2) << Qt::right << i << Qt::left << qSetFieldWidth(width: 0) << ':';
539 dbg.space();
540 dbg << r.field(index: i) << r.value(index: i).toString();
541 }
542 return dbg;
543}
544#endif
545
546/*!
547 \since 5.1
548 Returns a record containing the fields represented in \a keyFields set to values
549 that match by field name.
550*/
551QSqlRecord QSqlRecord::keyValues(const QSqlRecord &keyFields) const
552{
553 QSqlRecord retValues(keyFields);
554
555 for (int i = retValues.count() - 1; i >= 0; --i)
556 retValues.setValue(index: i, val: value(name: retValues.fieldName(index: i)));
557
558 return retValues;
559}
560
561QT_END_NAMESPACE
562

source code of qtbase/src/sql/kernel/qsqlrecord.cpp