summaryrefslogtreecommitdiffstats
path: root/doc/src/special-properties.qdoc
blob: d6c855ec52ff719b8a499e1708a6f9a38955613b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
/****************************************************************************
**
** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/
**
** This file is part of the documentation of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:FDL$
** GNU Free Documentation License
** Alternatively, this file may be used under the terms of the GNU Free
** Documentation License version 1.3 as published by the Free Software
** Foundation and appearing in the file included in the packaging of
** this file.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms
** and conditions contained in a signed written agreement between you
** and Nokia.
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/

/*!
\page special-properties.html
\title Special JSON Properties

JSON DB makes use of a number of special JSON properties for its own internal
use. These are always prefixed with an underscore.

\section1 Common Properties

\table
\row

\row
\li _type
\li All objects in the database must have a _type property assigned which
identifies the type of the object.
\row
\li _uuid
\li The _uuid property uniquely identifies an object. This can either be
automatically generated by the database or explicitly assigned by the client
(see \l {Deterministic UUIDs}).

\row
\li _version
\li Updating or removing an object will cause its version to change. The
version consists of two parts: a monotonically increasing counter and a hash.
Each time an object is updated the counter is incremented and the hash is
recalculated based on the properties of the object (see \l
{Stale Update Rejection}).

\row
\li _local
\li To enable master/master replication, JsonDb tracks all versions of an object.
For some objects this is simply overhead as they are not intended for replication
at all. Hence, version tracking can be disabled. All view objects have version
tracking disabled by default. For all other objects, you can manually disable
version tracking by setting _local to true.

\row
\li _deleted
\li If this property exists and is set to \c true, then the object has been
removed from the database.

\row
\li _owner
\li This property contains the name of the user (in the UNIX sense) that created the object.

\row
\li _meta
\li JSON DB uses \c _meta to store a variety of internal metadata, like the history of versions, which
is needed for conflict detection and resolution. This is a read-only property, client changes to this
property are ignored.

\endtable

\code

{
    "_deleted": true,
    "_meta": {
        "history": [
            "cc56ea320b",
            "da634c8a31"
        ]
    },
    "_owner": "root",
    "_type": "MyData",
    "_uuid": "{6ff8effc-cc53-4d6e-a6e2-62bcf34279e0}",
    "_version": "3-375a1ddfbc"
}

\endcode

\section1 Stale Update Rejection

When updating (or removing) an existing object in database, the calling client
must provide at least the _uuid and _version properties of that object. The value
of the _version property must match that of the object currently stored in the
database. If it does not (and if the JSON DB daemon has been started with the
-reject-stale-updates flag), the database will reject the write with an error
code \l {QJsonDbWriteRequest::UpdatingStaleVersion}. This eliminates race conditions
where client #1 reads an object from the database, client #2 reads the same object
and updates it, and then client #1 decides to update the object and overwrites
client #2's changes.

There are three main scenarios to consider when dealing with stale updates:

\list
\li The default (and by far the most common) is the scenario mentioned above,
where if some other client has updated an object between the first client reading
and updating an object, the write should be rejected. This means that clients need
to be prepared to handle the \l {QJsonDbWriteRequest::UpdatingStaleVersion} error
by re-querying and re-updating the object.
\li Another fairly common scenario is where the client wants to \e force an update,
regardless of the value of _version currently in the database. For this scenario,
the client should set \l {QJsonDbWriteRequest::conflictResolutionMode} to a
value of \l {QJsonDbWriteRequest::Replace} (or in the case of the QML API,
specify \c Partition.Replace for the \c mode when calling \l {Partition::update} or
\l {Partition::remove}). This will cause the version in the
database to be ignored and the object to be forcefully overwritten.
\li The final and least common scenario is when a client wants to create an
object in the database \e {unless it already exists}. This means that if there's
already an object there with the specified _uuid, the client wants the write to fail,
but otherwise it should create the object. No special handling is required for this
scenario. Simply create an object with a deterministic _uuid (see \l {Deterministic
UUIDs}) and no _version property. If there does not exist an object with the
specified _uuid, the write will succeed. Otherwise it will fail harmlessly
with a \l {QJsonDbWriteRequest::UpdatingStaleVersion} error.
\endlist

\section1 Deterministic UUIDs

Rather than letting the database assign a randomly generated UUID to an object,
it is possible for the \c _uuid property to be set in the client. Instead of
using a random value, the UUID can be generated based on a string value, and
every time the same string value is provided, the same UUID will be returned.
This is called a determinstic UUID and it has a number of important uses.
Deterministic UUIDs must still be globally unique, so creating the same
deterministic UUID for two different objects will result in a collision.

\section2 Generating a Deterministic UUID

From C++, UUIDS can be created from a string using
\l {QJsonDbObject::createUuidFromString()}. In QML, the module API provides a
\l {QtJsonDb1::JsonDatabase::uuidFromString()} method.

\section2 Fast Queries

Looking up an object by its \c _uuid property is faster than sending a complex
query. This means that if an object is stored using a determinstic UUID, it
can be looked up quickly by generating the same UUID (using the same
string input) and then querying for that UUID. In the case of View objects,
it's best to query on both _type and _uuid (see \l {Map and Join Views} and \l
{Reduce Views}).

\section2 Linking Objects in a Single Transaction

By using deterministic UUIDs, two objects can be linked in a single transaction.
This is because the UUIDs are known in advance and can therefore
"pointers" between two objects can be stored using their UUIDs.

\code
QJsonDbConnection *conn = new QJsonDbConnection();
conn->connectToServer();

QString name1 = QLatin1String("Bob");
QString name2 = QLatin1String("Joe");

QUuid uuid1 = QJsonDbObject::createUuidFromString(QString("name:%1").arg(name1));
QUuid uuid2 = QJsonDbObject::createUuidFromString(QString("name:%1").arg(name2));

QJsonDbObject object1;
object.setUuid(uuid1);
object.insert(QStringLiteral("name"), name1);
object.insert(QStringLiteral("knows"), uuid2.toString());

QJsonDbObject object2;
object.setUuid(uuid2);
object.insert(QStringLiteral("name"), name2);
object.insert(QStringLiteral("knows"), uuid1.toString());

QList<QJsonObject> toCreate;
toCreate << object1 << object2;

QJsonDbWriteRequest *request = new QJsonDbWriteRequest();
request->setObjects(toCreate);
conn->send(request);
\endcode
*/