source: trunk/src/sql/kernel/qsqlrecord.cpp@ 890

Last change on this file since 890 was 846, checked in by Dmitry A. Kuminov, 14 years ago

trunk: Merged in qt 4.7.2 sources from branches/vendor/nokia/qt.

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