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

Provided by KDAB

Privacy Policy
Learn to use CMake with our Intro Training
Find out more

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