@@ -45,6 +45,7 @@ const char* kQueryTargetsTable = "query_target";
45
45
const char * kTargetDocumentsTable = " target_document" ;
46
46
const char * kDocumentTargetsTable = " document_target" ;
47
47
const char * kRemoteDocumentsTable = " remote_document" ;
48
+ const char * kCollectionParentsTable = " collection_parent" ;
48
49
49
50
/* *
50
51
* Labels for the components of keys. These serve to make keys self-describing.
@@ -89,6 +90,12 @@ enum ComponentLabel {
89
90
/* * A component containing a user Id. */
90
91
UserId = 13 ,
91
92
93
+ /* *
94
+ * A component containing a standalone collection ID (e.g. as used by the
95
+ * collection_parent table, but not for collection IDs within paths).
96
+ */
97
+ CollectionId = 14 ,
98
+
92
99
/* *
93
100
* A path segment describes just a single segment in a resource path. Path
94
101
* segments that occur sequentially in a key represent successive segments in
@@ -159,6 +166,23 @@ class Reader {
159
166
return ReadLabeledString (ComponentLabel::UserId);
160
167
}
161
168
169
+ std::string ReadCollectionId () {
170
+ return ReadLabeledString (ComponentLabel::CollectionId);
171
+ }
172
+
173
+ /* *
174
+ * Reads component labels and strings from the key until it finds a component
175
+ * label other than ComponentLabel::PathSegment (or the key is exhausted).
176
+ * All matched path segments are assembled into a ResourcePath.
177
+ *
178
+ * If the read is unsuccessful, returns a default ResourcePath and fails the
179
+ * Reader.
180
+ *
181
+ * Otherwise returns the decoded ResourcePath and the Reader advances to the
182
+ * next unread byte.
183
+ */
184
+ ResourcePath ReadResourcePath ();
185
+
162
186
/* *
163
187
* Reads component labels and strings from the key until it finds a component
164
188
* label other than ComponentLabel::PathSegment (or the key is exhausted).
@@ -358,7 +382,7 @@ class Reader {
358
382
bool ok_;
359
383
};
360
384
361
- DocumentKey Reader::ReadDocumentKey () {
385
+ ResourcePath Reader::ReadResourcePath () {
362
386
std::vector<std::string> path_segments;
363
387
while (!empty ()) {
364
388
// Advance a temporary slice to avoid advancing contents into the next key
@@ -375,7 +399,16 @@ DocumentKey Reader::ReadDocumentKey() {
375
399
path_segments.push_back (std::move (segment));
376
400
}
377
401
378
- ResourcePath path{std::move (path_segments)};
402
+ if (ok_) {
403
+ return ResourcePath{std::move (path_segments)};
404
+ } else {
405
+ return ResourcePath{};
406
+ }
407
+ }
408
+
409
+ DocumentKey Reader::ReadDocumentKey () {
410
+ ResourcePath path = ReadResourcePath ();
411
+
379
412
if (ok_ && !path.empty () && DocumentKey::IsDocumentKey (path)) {
380
413
return DocumentKey{std::move (path)};
381
414
}
@@ -419,10 +452,10 @@ std::string Reader::Describe() {
419
452
src_ = saved_source;
420
453
421
454
if (label == ComponentLabel::PathSegment) {
422
- DocumentKey document_key = ReadDocumentKey ();
455
+ ResourcePath resource_path = ReadResourcePath ();
423
456
if (ok_) {
424
457
absl::StrAppend (&description,
425
- " key =" , document_key. path () .CanonicalString ());
458
+ " path =" , resource_path .CanonicalString ());
426
459
}
427
460
428
461
} else if (label == ComponentLabel::TableName) {
@@ -455,6 +488,12 @@ std::string Reader::Describe() {
455
488
absl::StrAppend (&description, " user_id=" , user_id);
456
489
}
457
490
491
+ } else if (label == ComponentLabel::CollectionId) {
492
+ std::string collection_id = ReadCollectionId ();
493
+ if (ok_) {
494
+ absl::StrAppend (&description, " collection_id=" , collection_id);
495
+ }
496
+
458
497
} else {
459
498
absl::StrAppend (&description, " unknown label=" , static_cast <int >(label));
460
499
Fail ();
@@ -502,6 +541,10 @@ class Writer {
502
541
WriteLabeledString (ComponentLabel::UserId, user_id);
503
542
}
504
543
544
+ void WriteCollectionId (absl::string_view collection_id) {
545
+ WriteLabeledString (ComponentLabel::CollectionId, collection_id);
546
+ }
547
+
505
548
/* *
506
549
* For each segment in the given resource path writes a
507
550
* ComponentLabel::PathSegment component label and a string containing the
@@ -848,6 +891,39 @@ bool LevelDbRemoteDocumentKey::Decode(absl::string_view key) {
848
891
return reader.ok ();
849
892
}
850
893
894
+ std::string LevelDbCollectionParentKey::KeyPrefix () {
895
+ Writer writer;
896
+ writer.WriteTableName (kCollectionParentsTable );
897
+ return writer.result ();
898
+ }
899
+
900
+ std::string LevelDbCollectionParentKey::KeyPrefix (
901
+ absl::string_view collection_id) {
902
+ Writer writer;
903
+ writer.WriteTableName (kCollectionParentsTable );
904
+ writer.WriteCollectionId (collection_id);
905
+ return writer.result ();
906
+ }
907
+
908
+ std::string LevelDbCollectionParentKey::Key (absl::string_view collection_id,
909
+ const ResourcePath& parent) {
910
+ Writer writer;
911
+ writer.WriteTableName (kCollectionParentsTable );
912
+ writer.WriteCollectionId (collection_id);
913
+ writer.WriteResourcePath (parent);
914
+ writer.WriteTerminator ();
915
+ return writer.result ();
916
+ }
917
+
918
+ bool LevelDbCollectionParentKey::Decode (absl::string_view key) {
919
+ Reader reader{key};
920
+ reader.ReadTableNameMatching (kCollectionParentsTable );
921
+ collection_id_ = reader.ReadCollectionId ();
922
+ parent_ = reader.ReadResourcePath ();
923
+ reader.ReadTerminator ();
924
+ return reader.ok ();
925
+ }
926
+
851
927
} // namespace local
852
928
} // namespace firestore
853
929
} // namespace firebase
0 commit comments