Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qsqlrecord.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3// Qt-Security score:significant reason:default
4
5#include "qsqlrecord.h"
6
7#include "qatomic.h"
8#include "qdebug.h"
9#include "qlist.h"
10#include "qsqlfield.h"
11#include "qstring.h"
12
14
16{
17public:
18 inline bool contains(qsizetype index) const
19 {
20 return index >= 0 && index < fields.size();
21 }
22
23 template <typename T>
25 {
26 T tableName;
27 T fieldName;
28 const auto it = std::find(name.begin(), name.end(), u'.');
29 const auto idx = (it == name.end()) ? -1 : it - name.begin();
30 if (idx != -1) {
31 tableName = name.left(idx);
32 fieldName = name.mid(idx + 1);
33 }
34 const auto cnt = fields.size();
35 for (qsizetype i = 0; i < cnt; ++i) {
36 // Check the passed in name first in case it is an alias using a dot.
37 // Then check if both the table and field match when there is a table name specified.
38 const auto &currentField = fields.at(i);
39 const auto &currentFieldName = currentField.name();
40 if (name.compare(currentFieldName, Qt::CaseInsensitive) == 0)
41 return i;
42 if (idx != -1 &&
43 tableName.compare(currentField.tableName(), Qt::CaseInsensitive) == 0 &&
44 fieldName.compare(currentFieldName, Qt::CaseInsensitive) == 0)
45 return i;
46 }
47 return -1;
48 }
49
50 QList<QSqlField> fields;
51};
52QT_DEFINE_QESDP_SPECIALIZATION_DTOR(QSqlRecordPrivate)
53
54/*!
55 \class QSqlRecord
56 \brief The QSqlRecord class encapsulates a database record.
57
58 \ingroup database
59 \ingroup shared
60 \inmodule QtSql
61
62 The QSqlRecord class encapsulates the functionality and
63 characteristics of a database record (usually a row in a table or
64 view within the database). QSqlRecord supports adding and
65 removing fields as well as setting and retrieving field values.
66
67 The values of a record's fields can be set by name or position
68 with setValue(); if you want to set a field to null use
69 setNull(). To find the position of a field by name use indexOf(),
70 and to find the name of a field at a particular position use
71 fieldName(). Use field() to retrieve a QSqlField object for a
72 given field. Use contains() to see if the record contains a
73 particular field name.
74
75 When queries are generated to be executed on the database only
76 those fields for which isGenerated() is true are included in the
77 generated SQL.
78
79 A record can have fields added with append() or insert(), replaced
80 with replace(), and removed with remove(). All the fields can be
81 removed with clear(). The number of fields is given by count();
82 all their values can be cleared (to null) using clearValues().
83
84 \sa QSqlField, QSqlQuery::record()
85*/
86
87
88/*!
89 Constructs an empty record.
90
91 \sa isEmpty(), append(), insert()
92*/
93
94QSqlRecord::QSqlRecord()
95 : d(new QSqlRecordPrivate)
96{
97}
98
99/*!
100 Constructs a copy of \a other.
101
102 QSqlRecord is \l{implicitly shared}. This means you can make copies
103 of a record in \l{constant time}.
104*/
105
106QSqlRecord::QSqlRecord(const QSqlRecord &other)
107 = default;
108
109/*!
110 \fn QSqlRecord::QSqlRecord(QSqlRecord &&other)
111 \since 6.6
112
113 Move-constructs a new QSqlRecord from \a other.
114
115 \note The moved-from object \a other is placed in a partially-formed state,
116 in which the only valid operations are destruction and assignment of a new
117 value.
118*/
119
120/*!
121 \fn QSqlRecord &QSqlRecord::operator=(QSqlRecord &&other)
122 \since 6.6
123
124 Move-assigns \a other to this QSqlRecord instance.
125
126 \note The moved-from object \a other is placed in a partially-formed state,
127 in which the only valid operations are destruction and assignment of a new
128 value.
129*/
130
131/*!
132 \fn void QSqlRecord::swap(QSqlRecord &other)
133 \since 6.6
134 \memberswap{SQL record}
135*/
136
137
138/*!
139 Sets the record equal to \a other.
140
141 QSqlRecord is \l{implicitly shared}. This means you can make copies
142 of a record in \l{constant time}.
143*/
144
145QSqlRecord& QSqlRecord::operator=(const QSqlRecord &other)
146 = default;
147
148/*!
149 Destroys the object and frees any allocated resources.
150*/
151
152QSqlRecord::~QSqlRecord()
153 = default;
154
155
156/*!
157 \fn bool QSqlRecord::operator!=(const QSqlRecord &other) const
158
159 Returns \c true if this object is not identical to \a other;
160 otherwise returns \c false.
161
162 \sa operator==()
163*/
164
165/*!
166 Returns \c true if this object is identical to \a other (i.e., has
167 the same fields in the same order); otherwise returns \c false.
168
169 \sa operator!=()
170*/
171bool QSqlRecord::operator==(const QSqlRecord &other) const
172{
173 return d->fields == other.d->fields;
174}
175
176/*!
177 Returns the value of the field located at position \a index in
178 the record. If \a index is out of bounds, an invalid QVariant
179 is returned.
180
181 \sa fieldName(), isNull()
182*/
183
184QVariant QSqlRecord::value(int index) const
185{
186 return d->fields.value(index).value();
187}
188
189/*!
190 \overload
191
192 Returns the value of the field called \a name in the record. If
193 field \a name does not exist an invalid variant is returned.
194
195 \note In Qt versions prior to 6.8, this function took QString, not
196 QAnyStringView.
197
198 \sa indexOf(), isNull()
199*/
200QVariant QSqlRecord::value(QAnyStringView name) const
201{
202 return value(indexOf(name));
203}
204
205/*!
206 Returns the name of the field at position \a index. If the field
207 does not exist, an empty string is returned.
208
209 \sa indexOf()
210*/
211
212QString QSqlRecord::fieldName(int index) const
213{
214 return d->fields.value(index).name();
215}
216
217/*!
218 Returns the position of the field called \a name within the
219 record, or -1 if it cannot be found. Field names are not
220 case-sensitive. If more than one field matches, the first one is
221 returned.
222
223 \note In Qt versions prior to 6.8, this function took QString, not
224 QAnyStringView.
225
226 \sa fieldName()
227 */
228int QSqlRecord::indexOf(QAnyStringView name) const
229{
230 return name.visit([&](auto v)
231 {
232 return d->indexOfImpl(v);
233 });
234}
235
236/*!
237 Returns the field at position \a index. If the \a index
238 is out of range, function returns
239 a \l{default-constructed value}.
240 */
241QSqlField QSqlRecord::field(int index) const
242{
243 return d->fields.value(index);
244}
245
246/*!
247 \overload
248
249 Returns the field called \a name. If the field called
250 \a name is not found, function returns
251 a \l{default-constructed value}.
252
253 \note In Qt versions prior to 6.8, this function took QString, not
254 QAnyStringView.
255 */
256QSqlField QSqlRecord::field(QAnyStringView name) const
257{
258 return field(indexOf(name));
259}
260
261
262/*!
263 Append a copy of field \a field to the end of the record.
264
265 \sa insert(), replace(), remove()
266*/
267
268void QSqlRecord::append(const QSqlField &field)
269{
270 detach();
271 d->fields.append(field);
272}
273
274/*!
275 Inserts the field \a field at position \a pos in the record.
276
277 \sa append(), replace(), remove()
278 */
279void QSqlRecord::insert(int pos, const QSqlField &field)
280{
281 detach();
282 d->fields.insert(pos, field);
283}
284
285/*!
286 Replaces the field at position \a pos with the given \a field. If
287 \a pos is out of range, nothing happens.
288
289 \sa append(), insert(), remove()
290*/
291
292void QSqlRecord::replace(int pos, const QSqlField &field)
293{
294 if (!d->contains(pos))
295 return;
296
297 detach();
298 d->fields[pos] = field;
299}
300
301/*!
302 Removes the field at position \a pos. If \a pos is out of range,
303 nothing happens.
304
305 \sa append(), insert(), replace()
306*/
307
308void QSqlRecord::remove(int pos)
309{
310 if (!d->contains(pos))
311 return;
312
313 detach();
314 d->fields.remove(pos);
315}
316
317/*!
318 Removes all the record's fields.
319
320 \sa clearValues(), isEmpty()
321*/
322
323void QSqlRecord::clear()
324{
325 detach();
326 d->fields.clear();
327}
328
329/*!
330 Returns \c true if there are no fields in the record; otherwise
331 returns \c false.
332
333 \sa append(), insert(), clear()
334*/
335
336bool QSqlRecord::isEmpty() const
337{
338 return d->fields.isEmpty();
339}
340
341/*!
342 Returns \c true if there is a field in the record called \a name;
343 otherwise returns \c false.
344
345 \note In Qt versions prior to 6.8, this function took QString, not
346 QAnyStringView.
347*/
348bool QSqlRecord::contains(QAnyStringView name) const
349{
350 return indexOf(name) >= 0;
351}
352
353/*!
354 Clears the value of all fields in the record and sets each field
355 to null.
356
357 \sa setValue()
358*/
359
360void QSqlRecord::clearValues()
361{
362 detach();
363 for (QSqlField &f : d->fields)
364 f.clear();
365}
366
367/*!
368 Sets the generated flag for the field called \a name to \a
369 generated. If the field does not exist, nothing happens. Only
370 fields that have \a generated set to true are included in the SQL
371 that is generated by QSqlQueryModel for example.
372
373 \note In Qt versions prior to 6.8, this function took QString, not
374 QAnyStringView.
375
376 \sa isGenerated()
377*/
378void QSqlRecord::setGenerated(QAnyStringView name, bool generated)
379{
380 setGenerated(indexOf(name), generated);
381}
382
383/*!
384 Sets the generated flag for the field \a index to \a generated.
385
386 \sa isGenerated()
387*/
388
389void QSqlRecord::setGenerated(int index, bool generated)
390{
391 if (!d->contains(index))
392 return;
393 detach();
394 d->fields[index].setGenerated(generated);
395}
396
397/*!
398 Returns \c true if the field \a index is null or if there is no field at
399 position \a index; otherwise returns \c false.
400
401 \sa setNull()
402*/
403bool QSqlRecord::isNull(int index) const
404{
405 return d->fields.value(index).isNull();
406}
407
408/*!
409 \overload
410
411 Returns \c true if the field called \a name is null or if there is no
412 field called \a name; otherwise returns \c false.
413
414 \note In Qt versions prior to 6.8, this function took QString, not
415 QAnyStringView.
416
417 \sa setNull()
418*/
419bool QSqlRecord::isNull(QAnyStringView name) const
420{
421 return isNull(indexOf(name));
422}
423
424/*!
425 Sets the value of field \a index to null. If the field does not exist,
426 nothing happens.
427
428 \sa setValue()
429*/
430void QSqlRecord::setNull(int index)
431{
432 if (!d->contains(index))
433 return;
434 detach();
435 d->fields[index].clear();
436}
437
438/*!
439 \overload
440
441 Sets the value of the field called \a name to null. If the field
442 does not exist, nothing happens.
443
444 \note In Qt versions prior to 6.8, this function took QString, not
445 QAnyStringView.
446*/
447void QSqlRecord::setNull(QAnyStringView name)
448{
449 setNull(indexOf(name));
450}
451
452/*!
453 \overload
454
455 Returns \c true if the record has a field called \a name and this
456 field is to be generated (the default); otherwise returns \c false.
457
458 \note In Qt versions prior to 6.8, this function took QString, not
459 QAnyStringView.
460
461 \sa setGenerated()
462*/
463bool QSqlRecord::isGenerated(QAnyStringView name) const
464{
465 return isGenerated(indexOf(name));
466}
467
468/*!
469 Returns \c true if the record has a field at position \a index and this
470 field is to be generated (the default); otherwise returns \c false.
471
472 \sa setGenerated()
473*/
474bool QSqlRecord::isGenerated(int index) const
475{
476 return d->fields.value(index).isGenerated();
477}
478
479/*!
480 Returns the number of fields in the record.
481
482 \sa isEmpty()
483*/
484
485int QSqlRecord::count() const
486{
487 return d->fields.size();
488}
489
490/*!
491 Sets the value of the field at position \a index to \a val. If the
492 field does not exist, nothing happens.
493
494 \sa setNull()
495*/
496
497void QSqlRecord::setValue(int index, const QVariant &val)
498{
499 if (!d->contains(index))
500 return;
501 detach();
502 d->fields[index].setValue(val);
503}
504
505/*!
506 \overload
507
508 Sets the value of the field called \a name to \a val. If the field
509 does not exist, nothing happens.
510
511 \note In Qt versions prior to 6.8, this function took QString, not
512 QAnyStringView.
513
514 \sa setNull()
515*/
516void QSqlRecord::setValue(QAnyStringView name, const QVariant &val)
517{
518 setValue(indexOf(name), val);
519}
520
521
522/*! \internal
523*/
524void QSqlRecord::detach()
525{
526 d.detach();
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(2) << Qt::right << i << Qt::left << qSetFieldWidth(0) << ':';
539 dbg.space();
540 dbg << r.field(i) << r.value(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(i, value(retValues.fieldName(i)));
557
558 return retValues;
559}
560
561QT_END_NAMESPACE
Definition qlist.h:80
bool contains(qsizetype index) const
QList< QSqlField > fields
qsizetype indexOfImpl(T name)
QDebug operator<<(QDebug dbg, const QFileInfo &fi)