1 | /****************************************************************************
|
---|
2 | **
|
---|
3 | ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
|
---|
4 | ** Contact: Qt Software Information ([email protected])
|
---|
5 | **
|
---|
6 | ** This file is part of the Qt3Support module of the Qt Toolkit.
|
---|
7 | **
|
---|
8 | ** $QT_BEGIN_LICENSE:LGPL$
|
---|
9 | ** Commercial Usage
|
---|
10 | ** Licensees holding valid Qt Commercial licenses may use this file in
|
---|
11 | ** accordance with the Qt Commercial License Agreement provided with the
|
---|
12 | ** Software or, alternatively, in accordance with the terms contained in
|
---|
13 | ** a written agreement between you and Nokia.
|
---|
14 | **
|
---|
15 | ** GNU Lesser General Public License Usage
|
---|
16 | ** Alternatively, this file may be used under the terms of the GNU Lesser
|
---|
17 | ** General Public License version 2.1 as published by the Free Software
|
---|
18 | ** Foundation and appearing in the file LICENSE.LGPL included in the
|
---|
19 | ** packaging of this file. Please review the following information to
|
---|
20 | ** ensure the GNU Lesser General Public License version 2.1 requirements
|
---|
21 | ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
---|
22 | **
|
---|
23 | ** In addition, as a special exception, Nokia gives you certain
|
---|
24 | ** additional rights. These rights are described in the Nokia Qt LGPL
|
---|
25 | ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
|
---|
26 | ** 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 are unsure which license is appropriate for your use, please
|
---|
37 | ** contact the sales department at [email protected].
|
---|
38 | ** $QT_END_LICENSE$
|
---|
39 | **
|
---|
40 | ****************************************************************************/
|
---|
41 |
|
---|
42 | #include <qplatformdefs.h>
|
---|
43 | #include "q3sqlcursor.h"
|
---|
44 |
|
---|
45 | #ifndef QT_NO_SQL
|
---|
46 |
|
---|
47 | #include "qsqldriver.h"
|
---|
48 | #include "qsqlresult.h"
|
---|
49 | #include "qdatetime.h"
|
---|
50 | #include "qsqldatabase.h"
|
---|
51 | #include "qsql.h"
|
---|
52 | #include "q3sqlrecordinfo.h"
|
---|
53 | #include "q3sqlfieldinfo.h"
|
---|
54 |
|
---|
55 | QT_BEGIN_NAMESPACE
|
---|
56 |
|
---|
57 | class Q3SqlCursorPrivate
|
---|
58 | {
|
---|
59 | public:
|
---|
60 |
|
---|
61 | Q3SqlCursorPrivate(const QString& name, QSqlDatabase sdb)
|
---|
62 | : lastAt(QSql::BeforeFirst), nm(name), srt(name), md(0), db(sdb), q(0)
|
---|
63 | {}
|
---|
64 | ~Q3SqlCursorPrivate()
|
---|
65 | {
|
---|
66 | delete q;
|
---|
67 | }
|
---|
68 |
|
---|
69 | QSqlQuery* query()
|
---|
70 | {
|
---|
71 | if (!q)
|
---|
72 | q = new QSqlQuery(QString(), db);
|
---|
73 | return q;
|
---|
74 | }
|
---|
75 |
|
---|
76 | int lastAt;
|
---|
77 | QString nm; //name
|
---|
78 | QSqlIndex srt; //sort
|
---|
79 | QString ftr; //filter
|
---|
80 | int md; //mode
|
---|
81 | QSqlIndex priIndx; //primary index
|
---|
82 | QSqlRecord editBuffer;
|
---|
83 | // the primary index as it was before the user changed the values in editBuffer
|
---|
84 | QString editIndex;
|
---|
85 | Q3SqlRecordInfo infoBuffer;
|
---|
86 | QSqlDatabase db;
|
---|
87 | QSqlQuery *q;
|
---|
88 | };
|
---|
89 |
|
---|
90 | QString qOrderByClause(const QSqlIndex & i, const QString& prefix = QString())
|
---|
91 | {
|
---|
92 | QString str;
|
---|
93 | int k = i.count();
|
---|
94 | if(k == 0)
|
---|
95 | return QString();
|
---|
96 | str = QLatin1String(" order by ") + i.toString(prefix);
|
---|
97 | return str;
|
---|
98 | }
|
---|
99 |
|
---|
100 | QString qWhereClause(const QString& prefix, QSqlField* field, const QSqlDriver* driver)
|
---|
101 | {
|
---|
102 | QString f;
|
---|
103 | if (field && driver) {
|
---|
104 | if (!prefix.isEmpty())
|
---|
105 | f += prefix + QLatin1Char('.');
|
---|
106 | f += field->name();
|
---|
107 | if (field->isNull()) {
|
---|
108 | f += QLatin1String(" IS NULL");
|
---|
109 | } else {
|
---|
110 | f += QLatin1String(" = ") + driver->formatValue(field);
|
---|
111 | }
|
---|
112 | }
|
---|
113 | return f;
|
---|
114 | }
|
---|
115 |
|
---|
116 | QString qWhereClause(QSqlRecord* rec, const QString& prefix, const QString& sep,
|
---|
117 | const QSqlDriver* driver)
|
---|
118 | {
|
---|
119 | static QString blank(QLatin1Char(' '));
|
---|
120 | QString filter;
|
---|
121 | bool separator = false;
|
---|
122 | for (int j = 0; j < rec->count(); ++j) {
|
---|
123 | QSqlField f = rec->field(j);
|
---|
124 | if (rec->isGenerated(j)) {
|
---|
125 | if (separator)
|
---|
126 | filter += sep + blank;
|
---|
127 | filter += qWhereClause(prefix, &f, driver);
|
---|
128 | filter += blank;
|
---|
129 | separator = true;
|
---|
130 | }
|
---|
131 | }
|
---|
132 | return filter;
|
---|
133 | }
|
---|
134 |
|
---|
135 | /*!
|
---|
136 | \class Q3SqlCursor
|
---|
137 | \brief The Q3SqlCursor class provides browsing and editing of SQL
|
---|
138 | tables and views.
|
---|
139 |
|
---|
140 | \compat
|
---|
141 |
|
---|
142 | A Q3SqlCursor is a database record (see \l QSqlRecord) that
|
---|
143 | corresponds to a table or view within an SQL database (see \l
|
---|
144 | QSqlDatabase). There are two buffers in a cursor, one used for
|
---|
145 | browsing and one used for editing records. Each buffer contains a
|
---|
146 | list of fields which correspond to the fields in the table or
|
---|
147 | view.
|
---|
148 |
|
---|
149 | When positioned on a valid record, the browse buffer contains the
|
---|
150 | values of the current record's fields from the database. The edit
|
---|
151 | buffer is separate, and is used for editing existing records and
|
---|
152 | inserting new records.
|
---|
153 |
|
---|
154 | For browsing data, a cursor must first select() data from the
|
---|
155 | database. After a successful select() the cursor is active
|
---|
156 | (isActive() returns true), but is initially not positioned on a
|
---|
157 | valid record (isValid() returns false). To position the cursor on
|
---|
158 | a valid record, use one of the navigation functions, next(),
|
---|
159 | previous(), first(), last(), or seek(). Once positioned on a valid
|
---|
160 | record, data can be retrieved from the browse buffer using
|
---|
161 | value(). If a navigation function is not successful, it returns
|
---|
162 | false, the cursor will no longer be positioned on a valid record
|
---|
163 | and the values returned by value() are undefined.
|
---|
164 |
|
---|
165 | For example:
|
---|
166 |
|
---|
167 | \snippet doc/src/snippets/code/src_qt3support_sql_q3sqlcursor.cpp 0
|
---|
168 |
|
---|
169 | In the above example, a cursor is created specifying a table or
|
---|
170 | view name in the database. Then, select() is called, which can be
|
---|
171 | optionally parameterised to filter and order the records
|
---|
172 | retrieved. Each record in the cursor is retrieved using next().
|
---|
173 | When next() returns false, there are no more records to process,
|
---|
174 | and the loop terminates.
|
---|
175 |
|
---|
176 | For editing records (rows of data), a cursor contains a separate
|
---|
177 | edit buffer which is independent of the fields used when browsing.
|
---|
178 | The functions insert(), update() and del() operate on the edit
|
---|
179 | buffer. This allows the cursor to be repositioned to other
|
---|
180 | records while simultaneously maintaining a separate buffer for
|
---|
181 | edits. You can get a pointer to the edit buffer using
|
---|
182 | editBuffer(). The primeInsert(), primeUpdate() and primeDelete()
|
---|
183 | functions also return a pointer to the edit buffer and prepare it
|
---|
184 | for insert, update and delete respectively. Edit operations only
|
---|
185 | affect a single row at a time. Note that update() and del()
|
---|
186 | require that the table or view contain a primaryIndex() to ensure
|
---|
187 | that edit operations affect a unique record within the database.
|
---|
188 |
|
---|
189 | For example:
|
---|
190 |
|
---|
191 | \snippet doc/src/snippets/code/src_qt3support_sql_q3sqlcursor.cpp 1
|
---|
192 |
|
---|
193 | To edit an existing database record, first move to the record you
|
---|
194 | wish to update. Call primeUpdate() to get the pointer to the
|
---|
195 | cursor's edit buffer. Then use this pointer to modify the values
|
---|
196 | in the edit buffer. Finally, call update() to save the changes to
|
---|
197 | the database. The values in the edit buffer will be used to
|
---|
198 | locate the appropriate record when updating the database (see
|
---|
199 | primaryIndex()).
|
---|
200 |
|
---|
201 | Similarly, when deleting an existing database record, first move
|
---|
202 | to the record you wish to delete. Then, call primeDelete() to get
|
---|
203 | the pointer to the edit buffer. Finally, call del() to delete the
|
---|
204 | record from the database. Again, the values in the edit buffer
|
---|
205 | will be used to locate and delete the appropriate record.
|
---|
206 |
|
---|
207 | To insert a new record, call primeInsert() to get the pointer to
|
---|
208 | the edit buffer. Use this pointer to populate the edit buffer
|
---|
209 | with new values and then insert() the record into the database.
|
---|
210 |
|
---|
211 | After calling insert(), update() or del(), the cursor is no longer
|
---|
212 | positioned on a valid record and can no longer be navigated
|
---|
213 | (isValid() return false). The reason for this is that any changes
|
---|
214 | made to the database will not be visible until select() is called
|
---|
215 | to refresh the cursor. You can change this behavior by passing
|
---|
216 | false to insert(), update() or del() which will prevent the cursor
|
---|
217 | from becoming invalid. The edits will still not be visible when
|
---|
218 | navigating the cursor until select() is called.
|
---|
219 |
|
---|
220 | Q3SqlCursor contains virtual methods which allow editing behavior
|
---|
221 | to be customized by subclasses. This allows custom cursors to be
|
---|
222 | created that encapsulate the editing behavior of a database table
|
---|
223 | for an entire application. For example, a cursor can be customized
|
---|
224 | to always auto-number primary index fields, or provide fields with
|
---|
225 | suitable default values, when inserting new records. Q3SqlCursor
|
---|
226 | generates SQL statements which are sent to the database engine;
|
---|
227 | you can control which fields are included in these statements
|
---|
228 | using setGenerated().
|
---|
229 |
|
---|
230 | Note that Q3SqlCursor does not inherit from QObject. This means
|
---|
231 | that you are responsible for destroying instances of this class
|
---|
232 | yourself. However if you create a Q3SqlCursor and use it in a
|
---|
233 | \l Q3DataTable, \l Q3DataBrowser or a \l Q3DataView these classes will
|
---|
234 | usually take ownership of the cursor and destroy it when they
|
---|
235 | don't need it anymore. The documentation for Q3DataTable,
|
---|
236 | Q3DataBrowser and Q3DataView explicitly states which calls take
|
---|
237 | ownership of the cursor.
|
---|
238 | */
|
---|
239 |
|
---|
240 | /*!
|
---|
241 | \enum Q3SqlCursor::Mode
|
---|
242 |
|
---|
243 | This enum type describes how Q3SqlCursor operates on records in the
|
---|
244 | database.
|
---|
245 |
|
---|
246 | \value ReadOnly the cursor can only SELECT records from the
|
---|
247 | database.
|
---|
248 |
|
---|
249 | \value Insert the cursor can INSERT records into the database.
|
---|
250 |
|
---|
251 | \value Update the cursor can UPDATE records in the database.
|
---|
252 |
|
---|
253 | \value Delete the cursor can DELETE records from the database.
|
---|
254 |
|
---|
255 | \value Writable the cursor can INSERT, UPDATE and DELETE records
|
---|
256 | in the database.
|
---|
257 | */
|
---|
258 |
|
---|
259 | /*!
|
---|
260 | \fn QVariant Q3SqlCursor::value(const QString &name) const
|
---|
261 |
|
---|
262 | \overload
|
---|
263 |
|
---|
264 | Returns the value of the field named \a name.
|
---|
265 | */
|
---|
266 |
|
---|
267 | /*!
|
---|
268 | \fn void Q3SqlCursor::setValue(const QString &name, const QVariant &val)
|
---|
269 |
|
---|
270 | \overload
|
---|
271 |
|
---|
272 | Sets the value for the field named \a name to \a val.
|
---|
273 | */
|
---|
274 |
|
---|
275 | /*!
|
---|
276 | Constructs a cursor on database \a db using table or view \a name.
|
---|
277 |
|
---|
278 | If \a autopopulate is true (the default), the \a name of the
|
---|
279 | cursor must correspond to an existing table or view name in the
|
---|
280 | database so that field information can be automatically created.
|
---|
281 | If the table or view does not exist, the cursor will not be
|
---|
282 | functional.
|
---|
283 |
|
---|
284 | The cursor is created with an initial mode of Q3SqlCursor::Writable
|
---|
285 | (meaning that records can be inserted, updated or deleted using
|
---|
286 | the cursor). If the cursor does not have a unique primary index,
|
---|
287 | update and deletes cannot be performed.
|
---|
288 |
|
---|
289 | Note that \a autopopulate refers to populating the cursor with
|
---|
290 | meta-data, e.g. the names of the table's fields, not with
|
---|
291 | retrieving data. The select() function is used to populate the
|
---|
292 | cursor with data.
|
---|
293 |
|
---|
294 | \sa setName() setMode()
|
---|
295 | */
|
---|
296 |
|
---|
297 | Q3SqlCursor::Q3SqlCursor(const QString & name, bool autopopulate, QSqlDatabase db)
|
---|
298 | : QSqlRecord(), QSqlQuery(QString(), db)
|
---|
299 | {
|
---|
300 | d = new Q3SqlCursorPrivate(name, db);
|
---|
301 | setMode(Writable);
|
---|
302 | if (!d->nm.isEmpty())
|
---|
303 | setName(d->nm, autopopulate);
|
---|
304 | }
|
---|
305 |
|
---|
306 | /*!
|
---|
307 | Constructs a copy of \a other.
|
---|
308 | */
|
---|
309 |
|
---|
310 | Q3SqlCursor::Q3SqlCursor(const Q3SqlCursor & other)
|
---|
311 | : QSqlRecord(other), QSqlQuery(other)
|
---|
312 | {
|
---|
313 | d = new Q3SqlCursorPrivate(other.d->nm, other.d->db);
|
---|
314 | d->lastAt = other.d->lastAt;
|
---|
315 | d->nm = other.d->nm;
|
---|
316 | d->srt = other.d->srt;
|
---|
317 | d->ftr = other.d->ftr;
|
---|
318 | d->priIndx = other.d->priIndx;
|
---|
319 | d->editBuffer = other.d->editBuffer;
|
---|
320 | d->infoBuffer = other.d->infoBuffer;
|
---|
321 | d->q = 0; // do not share queries
|
---|
322 | setMode(other.mode());
|
---|
323 | }
|
---|
324 |
|
---|
325 | /*!
|
---|
326 | Destroys the object and frees any allocated resources.
|
---|
327 | */
|
---|
328 |
|
---|
329 | Q3SqlCursor::~Q3SqlCursor()
|
---|
330 | {
|
---|
331 | delete d;
|
---|
332 | }
|
---|
333 |
|
---|
334 | /*!
|
---|
335 | Sets the cursor equal to \a other.
|
---|
336 | */
|
---|
337 |
|
---|
338 | Q3SqlCursor& Q3SqlCursor::operator=(const Q3SqlCursor& other)
|
---|
339 | {
|
---|
340 | QSqlRecord::operator=(other);
|
---|
341 | QSqlQuery::operator=(other);
|
---|
342 | delete d;
|
---|
343 | d = new Q3SqlCursorPrivate(other.d->nm, other.d->db);
|
---|
344 | d->lastAt = other.d->lastAt;
|
---|
345 | d->nm = other.d->nm;
|
---|
346 | d->srt = other.d->srt;
|
---|
347 | d->ftr = other.d->ftr;
|
---|
348 | d->priIndx = other.d->priIndx;
|
---|
349 | d->editBuffer = other.d->editBuffer;
|
---|
350 | d->infoBuffer = other.d->infoBuffer;
|
---|
351 | d->q = 0; // do not share queries
|
---|
352 | setMode(other.mode());
|
---|
353 | return *this;
|
---|
354 | }
|
---|
355 |
|
---|
356 | /*!
|
---|
357 | Sets the current sort to \a sort. Note that no new records are
|
---|
358 | selected. To select new records, use select(). The \a sort will
|
---|
359 | apply to any subsequent select() calls that do not explicitly
|
---|
360 | specify a sort.
|
---|
361 | */
|
---|
362 |
|
---|
363 | void Q3SqlCursor::setSort(const QSqlIndex& sort)
|
---|
364 | {
|
---|
365 | d->srt = sort;
|
---|
366 | }
|
---|
367 |
|
---|
368 | /*!
|
---|
369 | Returns the current sort, or an empty index if there is no current
|
---|
370 | sort.
|
---|
371 | */
|
---|
372 | QSqlIndex Q3SqlCursor::sort() const
|
---|
373 | {
|
---|
374 | return d->srt;
|
---|
375 | }
|
---|
376 |
|
---|
377 | /*!
|
---|
378 | Sets the current filter to \a filter. Note that no new records are
|
---|
379 | selected. To select new records, use select(). The \a filter will
|
---|
380 | apply to any subsequent select() calls that do not explicitly
|
---|
381 | specify a filter.
|
---|
382 |
|
---|
383 | The filter is a SQL \c WHERE clause without the keyword 'WHERE',
|
---|
384 | e.g. \c{name='Dave'} which will be processed by the DBMS.
|
---|
385 | */
|
---|
386 | void Q3SqlCursor::setFilter(const QString& filter)
|
---|
387 | {
|
---|
388 | d->ftr = filter;
|
---|
389 | }
|
---|
390 |
|
---|
391 | /*!
|
---|
392 | Returns the current filter, or an empty string if there is no
|
---|
393 | current filter.
|
---|
394 | */
|
---|
395 | QString Q3SqlCursor::filter() const
|
---|
396 | {
|
---|
397 | return d->ftr;
|
---|
398 | }
|
---|
399 |
|
---|
400 | /*!
|
---|
401 | Sets the name of the cursor to \a name. If \a autopopulate is true
|
---|
402 | (the default), the \a name must correspond to a valid table or
|
---|
403 | view name in the database. Also, note that all references to the
|
---|
404 | cursor edit buffer become invalidated when fields are
|
---|
405 | auto-populated. See the Q3SqlCursor constructor documentation for
|
---|
406 | more information.
|
---|
407 | */
|
---|
408 | void Q3SqlCursor::setName(const QString& name, bool autopopulate)
|
---|
409 | {
|
---|
410 | d->nm = name;
|
---|
411 | if (autopopulate) {
|
---|
412 | if (driver()) {
|
---|
413 | d->infoBuffer = driver()->record(name);
|
---|
414 | *this = d->infoBuffer.toRecord();
|
---|
415 | d->editBuffer = *this;
|
---|
416 | d->priIndx = driver()->primaryIndex(name);
|
---|
417 | }
|
---|
418 | if (isEmpty())
|
---|
419 | qWarning("Q3SqlCursor::setName: unable to build record, does '%s' exist?", name.latin1());
|
---|
420 | }
|
---|
421 | }
|
---|
422 |
|
---|
423 | /*!
|
---|
424 | Returns the name of the cursor.
|
---|
425 | */
|
---|
426 |
|
---|
427 | QString Q3SqlCursor::name() const
|
---|
428 | {
|
---|
429 | return d->nm;
|
---|
430 | }
|
---|
431 |
|
---|
432 | /*! \internal
|
---|
433 | */
|
---|
434 |
|
---|
435 | QString Q3SqlCursor::toString(const QString& prefix, const QString& sep) const
|
---|
436 | {
|
---|
437 | QString pflist;
|
---|
438 | QString pfix = prefix.isEmpty() ? prefix : prefix + QLatin1Char('.');
|
---|
439 | bool comma = false;
|
---|
440 |
|
---|
441 | for (int i = 0; i < count(); ++i) {
|
---|
442 | const QString fname = fieldName(i);
|
---|
443 | if (isGenerated(i)) {
|
---|
444 | if(comma)
|
---|
445 | pflist += sep + QLatin1Char(' ');
|
---|
446 | pflist += pfix + driver()->escapeIdentifier(fname, QSqlDriver::FieldName);
|
---|
447 | comma = true;
|
---|
448 | }
|
---|
449 | }
|
---|
450 | return pflist;
|
---|
451 | }
|
---|
452 |
|
---|
453 | /*!
|
---|
454 | \internal
|
---|
455 |
|
---|
456 | Assigns the record \a list.
|
---|
457 |
|
---|
458 | */
|
---|
459 | QSqlRecord & Q3SqlCursor::operator=(const QSqlRecord & list)
|
---|
460 | {
|
---|
461 | return QSqlRecord::operator=(list);
|
---|
462 | }
|
---|
463 |
|
---|
464 | /*!
|
---|
465 | Append a copy of field \a fieldInfo to the end of the cursor. Note
|
---|
466 | that all references to the cursor edit buffer become invalidated.
|
---|
467 | */
|
---|
468 |
|
---|
469 | void Q3SqlCursor::append(const Q3SqlFieldInfo& fieldInfo)
|
---|
470 | {
|
---|
471 | d->editBuffer.append(fieldInfo.toField());
|
---|
472 | d->infoBuffer.append(fieldInfo);
|
---|
473 | QSqlRecord::append(fieldInfo.toField());
|
---|
474 | }
|
---|
475 |
|
---|
476 | /*!
|
---|
477 | Removes all fields from the cursor. Note that all references to
|
---|
478 | the cursor edit buffer become invalidated.
|
---|
479 | */
|
---|
480 | void Q3SqlCursor::clear()
|
---|
481 | {
|
---|
482 | d->editBuffer.clear();
|
---|
483 | d->infoBuffer.clear();
|
---|
484 | QSqlRecord::clear();
|
---|
485 | }
|
---|
486 |
|
---|
487 |
|
---|
488 | /*!
|
---|
489 | Insert a copy of \a fieldInfo at position \a pos. If a field
|
---|
490 | already exists at \a pos, it is removed. Note that all references
|
---|
491 | to the cursor edit buffer become invalidated.
|
---|
492 | */
|
---|
493 |
|
---|
494 | void Q3SqlCursor::insert(int pos, const Q3SqlFieldInfo& fieldInfo)
|
---|
495 | {
|
---|
496 | d->editBuffer.replace(pos, fieldInfo.toField());
|
---|
497 | d->infoBuffer[pos] = fieldInfo;
|
---|
498 | QSqlRecord::replace(pos, fieldInfo.toField());
|
---|
499 | }
|
---|
500 |
|
---|
501 | /*!
|
---|
502 | Removes the field at \a pos. If \a pos does not exist, nothing
|
---|
503 | happens. Note that all references to the cursor edit buffer become
|
---|
504 | invalidated.
|
---|
505 | */
|
---|
506 |
|
---|
507 | void Q3SqlCursor::remove(int pos)
|
---|
508 | {
|
---|
509 | d->editBuffer.remove(pos);
|
---|
510 | d->infoBuffer[pos] = Q3SqlFieldInfo();
|
---|
511 | QSqlRecord::remove(pos);
|
---|
512 | }
|
---|
513 |
|
---|
514 | /*!
|
---|
515 | Sets the generated flag for the field \a name to \a generated. If
|
---|
516 | the field does not exist, nothing happens. Only fields that have
|
---|
517 | \a generated set to true are included in the SQL that is
|
---|
518 | generated by insert(), update() or del().
|
---|
519 | */
|
---|
520 |
|
---|
521 | void Q3SqlCursor::setGenerated(const QString& name, bool generated)
|
---|
522 | {
|
---|
523 | int pos = indexOf(name);
|
---|
524 | if (pos == -1)
|
---|
525 | return;
|
---|
526 | QSqlRecord::setGenerated(name, generated);
|
---|
527 | d->editBuffer.setGenerated(name, generated);
|
---|
528 | d->infoBuffer[pos].setGenerated(generated);
|
---|
529 | }
|
---|
530 |
|
---|
531 | /*!
|
---|
532 | \overload
|
---|
533 |
|
---|
534 | Sets the generated flag for the field \a i to \a generated.
|
---|
535 | */
|
---|
536 | void Q3SqlCursor::setGenerated(int i, bool generated)
|
---|
537 | {
|
---|
538 | if (i < 0 || i >= (int)d->infoBuffer.count())
|
---|
539 | return;
|
---|
540 | QSqlRecord::setGenerated(i, generated);
|
---|
541 | d->editBuffer.setGenerated(i, generated);
|
---|
542 | d->infoBuffer[i].setGenerated(generated);
|
---|
543 | }
|
---|
544 |
|
---|
545 | /*!
|
---|
546 | Returns the primary index associated with the cursor as defined in
|
---|
547 | the database, or an empty index if there is no primary index. If
|
---|
548 | \a setFromCursor is true (the default), the index fields are
|
---|
549 | populated with the corresponding values in the cursor's current
|
---|
550 | record.
|
---|
551 | */
|
---|
552 |
|
---|
553 | QSqlIndex Q3SqlCursor::primaryIndex(bool setFromCursor) const
|
---|
554 | {
|
---|
555 | if (setFromCursor) {
|
---|
556 | for (int i = 0; i < d->priIndx.count(); ++i) {
|
---|
557 | const QString fn = d->priIndx.fieldName(i);
|
---|
558 | if (contains(fn))
|
---|
559 | d->priIndx.setValue(i, QSqlRecord::value(fn));
|
---|
560 | }
|
---|
561 | }
|
---|
562 | return d->priIndx;
|
---|
563 | }
|
---|
564 |
|
---|
565 | /*!
|
---|
566 | Sets the primary index associated with the cursor to the index \a
|
---|
567 | idx. Note that this index must contain a field or set of fields
|
---|
568 | which identify a unique record within the underlying database
|
---|
569 | table or view so that update() and del() will execute as expected.
|
---|
570 |
|
---|
571 | \sa update() del()
|
---|
572 | */
|
---|
573 |
|
---|
574 | void Q3SqlCursor::setPrimaryIndex(const QSqlIndex& idx)
|
---|
575 | {
|
---|
576 | d->priIndx = idx;
|
---|
577 | }
|
---|
578 |
|
---|
579 |
|
---|
580 | /*!
|
---|
581 | Returns an index composed of \a fieldNames, all in ASCending
|
---|
582 | order. Note that all field names must exist in the cursor,
|
---|
583 | otherwise an empty index is returned.
|
---|
584 |
|
---|
585 | \sa QSqlIndex
|
---|
586 | */
|
---|
587 |
|
---|
588 | QSqlIndex Q3SqlCursor::index(const QStringList& fieldNames) const
|
---|
589 | {
|
---|
590 | QSqlIndex idx;
|
---|
591 | for (QStringList::ConstIterator it = fieldNames.begin(); it != fieldNames.end(); ++it) {
|
---|
592 | QSqlField f = field((*it));
|
---|
593 | if (!f.isValid()) { /* all fields must exist */
|
---|
594 | idx.clear();
|
---|
595 | break;
|
---|
596 | }
|
---|
597 | idx.append(f);
|
---|
598 | }
|
---|
599 | return idx;
|
---|
600 | }
|
---|
601 |
|
---|
602 | /*!
|
---|
603 | \overload
|
---|
604 |
|
---|
605 | Returns an index based on \a fieldName.
|
---|
606 | */
|
---|
607 |
|
---|
608 | QSqlIndex Q3SqlCursor::index(const QString& fieldName) const
|
---|
609 | {
|
---|
610 | QStringList fl(fieldName);
|
---|
611 | return index(fl);
|
---|
612 | }
|
---|
613 |
|
---|
614 | /*!
|
---|
615 | Selects all fields in the cursor from the database matching the
|
---|
616 | filter criteria \a filter. The data is returned in the order
|
---|
617 | specified by the index \a sort. Returns true if the data was
|
---|
618 | successfully selected; otherwise returns false.
|
---|
619 |
|
---|
620 | The \a filter is a string containing a SQL \c WHERE clause but
|
---|
621 | without the 'WHERE' keyword. The cursor is initially positioned at
|
---|
622 | an invalid row after this function is called. To move to a valid
|
---|
623 | row, use seek(), first(), last(), previous() or next().
|
---|
624 |
|
---|
625 | Example:
|
---|
626 | \snippet doc/src/snippets/code/src_qt3support_sql_q3sqlcursor.cpp 2
|
---|
627 |
|
---|
628 | The filter will apply to any subsequent select() calls that do not
|
---|
629 | explicitly specify another filter. Similarly the sort will apply
|
---|
630 | to any subsequent select() calls that do not explicitly specify
|
---|
631 | another sort.
|
---|
632 |
|
---|
633 | \snippet doc/src/snippets/code/src_qt3support_sql_q3sqlcursor.cpp 3
|
---|
634 |
|
---|
635 | */
|
---|
636 |
|
---|
637 | bool Q3SqlCursor::select(const QString & filter, const QSqlIndex & sort)
|
---|
638 | {
|
---|
639 | QString fieldList(toString(d->nm));
|
---|
640 | if (fieldList.isEmpty())
|
---|
641 | return false;
|
---|
642 | QString str(QLatin1String("select ") + fieldList);
|
---|
643 | str += QLatin1String(" from ") + d->nm;
|
---|
644 | if (!filter.isEmpty()) {
|
---|
645 | d->ftr = filter;
|
---|
646 | str += QLatin1String(" where ") + filter;
|
---|
647 | } else
|
---|
648 | d->ftr.clear();
|
---|
649 | if (sort.count() > 0)
|
---|
650 | str += QLatin1String(" order by ") + sort.toString(d->nm);
|
---|
651 | d->srt = sort;
|
---|
652 | return exec(str);
|
---|
653 | }
|
---|
654 |
|
---|
655 | /*!
|
---|
656 | \overload
|
---|
657 |
|
---|
658 | Selects all fields in the cursor from the database. The rows are
|
---|
659 | returned in the order specified by the last call to setSort() or
|
---|
660 | the last call to select() that specified a sort, whichever is the
|
---|
661 | most recent. If there is no current sort, the order in which the
|
---|
662 | rows are returned is undefined. The records are filtered according
|
---|
663 | to the filter specified by the last call to setFilter() or the
|
---|
664 | last call to select() that specified a filter, whichever is the
|
---|
665 | most recent. If there is no current filter, all records are
|
---|
666 | returned. The cursor is initially positioned at an invalid row. To
|
---|
667 | move to a valid row, use seek(), first(), last(), previous() or
|
---|
668 | next().
|
---|
669 |
|
---|
670 | \sa setSort() setFilter()
|
---|
671 | */
|
---|
672 |
|
---|
673 | bool Q3SqlCursor::select()
|
---|
674 | {
|
---|
675 | return select(filter(), sort());
|
---|
676 | }
|
---|
677 |
|
---|
678 | /*!
|
---|
679 | \overload
|
---|
680 |
|
---|
681 | Selects all fields in the cursor from the database. The data is
|
---|
682 | returned in the order specified by the index \a sort. The records
|
---|
683 | are filtered according to the filter specified by the last call to
|
---|
684 | setFilter() or the last call to select() that specified a filter,
|
---|
685 | whichever is the most recent. The cursor is initially positioned
|
---|
686 | at an invalid row. To move to a valid row, use seek(), first(),
|
---|
687 | last(), previous() or next().
|
---|
688 | */
|
---|
689 |
|
---|
690 | bool Q3SqlCursor::select(const QSqlIndex& sort)
|
---|
691 | {
|
---|
692 | return select(filter(), sort);
|
---|
693 | }
|
---|
694 |
|
---|
695 | /*!
|
---|
696 | \overload
|
---|
697 |
|
---|
698 | Selects all fields in the cursor matching the filter index \a
|
---|
699 | filter. The data is returned in the order specified by the index
|
---|
700 | \a sort. The \a filter index works by constructing a WHERE clause
|
---|
701 | using the names of the fields from the \a filter and their values
|
---|
702 | from the current cursor record. The cursor is initially positioned
|
---|
703 | at an invalid row. To move to a valid row, use seek(), first(),
|
---|
704 | last(), previous() or next(). This function is useful, for example,
|
---|
705 | for retrieving data based upon a table's primary index:
|
---|
706 |
|
---|
707 | \snippet doc/src/snippets/code/src_qt3support_sql_q3sqlcursor.cpp 4
|
---|
708 |
|
---|
709 | In this example the QSqlIndex, pk, is used for two different
|
---|
710 | purposes. When used as the filter (first) argument, the field
|
---|
711 | names it contains are used to construct the WHERE clause, each set
|
---|
712 | to the current cursor value, \c{WHERE id=10}, in this case. When
|
---|
713 | used as the sort (second) argument the field names it contains are
|
---|
714 | used for the ORDER BY clause, \c{ORDER BY id} in this example.
|
---|
715 | */
|
---|
716 |
|
---|
717 | bool Q3SqlCursor::select(const QSqlIndex & filter, const QSqlIndex & sort)
|
---|
718 | {
|
---|
719 | return select(toString(filter, this, d->nm, QString(QLatin1Char('=')), QLatin1String("and")), sort);
|
---|
720 | }
|
---|
721 |
|
---|
722 | /*!
|
---|
723 | Sets the cursor mode to \a mode. This value can be an OR'ed
|
---|
724 | combination of \l Q3SqlCursor::Mode values. The default mode for a
|
---|
725 | cursor is Q3SqlCursor::Writable.
|
---|
726 |
|
---|
727 | \snippet doc/src/snippets/code/src_qt3support_sql_q3sqlcursor.cpp 5
|
---|
728 | */
|
---|
729 |
|
---|
730 | void Q3SqlCursor::setMode(int mode)
|
---|
731 | {
|
---|
732 | d->md = mode;
|
---|
733 | }
|
---|
734 |
|
---|
735 | /*!
|
---|
736 | Returns the current cursor mode.
|
---|
737 |
|
---|
738 | \sa setMode()
|
---|
739 | */
|
---|
740 |
|
---|
741 | int Q3SqlCursor::mode() const
|
---|
742 | {
|
---|
743 | return d->md;
|
---|
744 | }
|
---|
745 |
|
---|
746 | /*!
|
---|
747 | Sets field \a name to \a calculated. If the field \a name does not
|
---|
748 | exist, nothing happens. The value of a calculated field is set by
|
---|
749 | the calculateField() virtual function which you must reimplement
|
---|
750 | (or the field value will be an invalid QVariant). Calculated
|
---|
751 | fields do not appear in generated SQL statements sent to the
|
---|
752 | database.
|
---|
753 |
|
---|
754 | \sa calculateField()
|
---|
755 | */
|
---|
756 |
|
---|
757 | void Q3SqlCursor::setCalculated(const QString& name, bool calculated)
|
---|
758 | {
|
---|
759 | int pos = indexOf(name);
|
---|
760 | if (pos < 0)
|
---|
761 | return;
|
---|
762 | d->infoBuffer[pos].setCalculated(calculated);
|
---|
763 | if (calculated)
|
---|
764 | setGenerated(pos, false);
|
---|
765 | }
|
---|
766 |
|
---|
767 | /*!
|
---|
768 | Returns true if the field \a name exists and is calculated;
|
---|
769 | otherwise returns false.
|
---|
770 |
|
---|
771 | \sa setCalculated()
|
---|
772 | */
|
---|
773 |
|
---|
774 | bool Q3SqlCursor::isCalculated(const QString& name) const
|
---|
775 | {
|
---|
776 | int pos = indexOf(name);
|
---|
777 | if (pos < 0)
|
---|
778 | return false;
|
---|
779 | return d->infoBuffer[pos].isCalculated();
|
---|
780 | }
|
---|
781 |
|
---|
782 | /*!
|
---|
783 | Sets field \a{name}'s trimmed status to \a trim. If the field \a
|
---|
784 | name does not exist, nothing happens.
|
---|
785 |
|
---|
786 | When a trimmed field of type string is read from the
|
---|
787 | database any trailing (right-most) spaces are removed.
|
---|
788 |
|
---|
789 | \sa isTrimmed() QVariant
|
---|
790 | */
|
---|
791 |
|
---|
792 | void Q3SqlCursor::setTrimmed(const QString& name, bool trim)
|
---|
793 | {
|
---|
794 | int pos = indexOf(name);
|
---|
795 | if (pos < 0)
|
---|
796 | return;
|
---|
797 | d->infoBuffer[pos].setTrim(trim);
|
---|
798 | }
|
---|
799 |
|
---|
800 | /*!
|
---|
801 | Returns true if the field \a name exists and is trimmed; otherwise
|
---|
802 | returns false.
|
---|
803 |
|
---|
804 | When a trimmed field of type string or cstring is read from the
|
---|
805 | database any trailing (right-most) spaces are removed.
|
---|
806 |
|
---|
807 | \sa setTrimmed()
|
---|
808 | */
|
---|
809 |
|
---|
810 | bool Q3SqlCursor::isTrimmed(const QString& name) const
|
---|
811 | {
|
---|
812 | int pos = indexOf(name);
|
---|
813 | if (pos < 0)
|
---|
814 | return false;
|
---|
815 | return d->infoBuffer[pos].isTrim();
|
---|
|
---|