Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Support getting attachment data inline with a document

i.e. GET /db/docid?attachments=true
  • Loading branch information...
commit ce5ddd82ecab2098d2de1490bc55dd3f51380458 1 parent ccb04b6
@snej snej authored
View
12 Source/TDDatabase+Insertion.m
@@ -165,11 +165,13 @@ - (TDRevision*) putRevision: (TDRevision*)rev
if (docNumericID <= 0)
return nil;
parentSequence = [_fmdb longLongForQuery: @"SELECT sequence FROM revs "
- "WHERE doc_id=? AND revid=? and current=1 LIMIT 1",
- $object(docNumericID), prevRevID];
+ "WHERE doc_id=? AND revid=? and current=1 LIMIT 1",
+ $object(docNumericID), prevRevID];
if (parentSequence == 0) {
- // Not found: either a 404 or a 409, depending on whether there is any current revision
- *outStatus = [self getDocumentWithID: docID] ? 409 : 404;
+ // Not found: 404 or a 409, depending on whether there is any current revision
+ TDRevision* cur = [self getDocumentWithID: docID revisionID: nil
+ withAttachments: NO];
+ *outStatus = cur ? 409 : 404;
return nil;
}
@@ -430,7 +432,7 @@ - (void)dealloc {
- (TDRevision*) currentRevision {
if (_currentRevision)
- [_db loadRevisionBody: _currentRevision andAttachments: NO];
+ [_db loadRevisionBody: _currentRevision withAttachments: NO];
return _currentRevision;
}
View
7 Source/TDDatabase.h
@@ -67,10 +67,11 @@ typedef BOOL (^TDValidationBlock) (TDRevision* newRevision,
@property (readonly) NSUInteger documentCount;
@property (readonly) SequenceNumber lastSequence;
-- (TDRevision*) getDocumentWithID: (NSString*)docID;
-- (TDRevision*) getDocumentWithID: (NSString*)docID revisionID: (NSString*)revID;
+- (TDRevision*) getDocumentWithID: (NSString*)docID
+ revisionID: (NSString*)revID
+ withAttachments: (BOOL)withAttachments;
- (TDStatus) loadRevisionBody: (TDRevision*)rev
- andAttachments: (BOOL)andAttachments;
+ withAttachments: (BOOL)andAttachments;
/** Returns an array of TDRevs in reverse chronological order,
starting with the given revision. */
View
13 Source/TDDatabase.m
@@ -343,11 +343,10 @@ - (NSDictionary*) documentPropertiesFromJSON: (NSData*)json
}
-- (TDRevision*) getDocumentWithID: (NSString*)docID {
- return [self getDocumentWithID: docID revisionID: nil];
-}
-
-- (TDRevision*) getDocumentWithID: (NSString*)docID revisionID: (NSString*)revID {
+- (TDRevision*) getDocumentWithID: (NSString*)docID
+ revisionID: (NSString*)revID
+ withAttachments: (BOOL)withAttachments
+{
TDRevision* result = nil;
NSString* sql;
if (revID)
@@ -365,7 +364,7 @@ - (TDRevision*) getDocumentWithID: (NSString*)docID revisionID: (NSString*)revID
NSData* json = [r dataForColumnIndex: 2];
result = [[[TDRevision alloc] initWithDocID: docID revID: revID deleted: deleted] autorelease];
result.sequence = [r longLongIntForColumnIndex: 3];
- [self expandStoredJSON: json intoRevision: result withAttachments: NO];
+ [self expandStoredJSON: json intoRevision: result withAttachments: withAttachments];
}
[r close];
return result;
@@ -373,7 +372,7 @@ - (TDRevision*) getDocumentWithID: (NSString*)docID revisionID: (NSString*)revID
- (TDStatus) loadRevisionBody: (TDRevision*)rev
- andAttachments: (BOOL)withAttachments
+ withAttachments: (BOOL)withAttachments
{
if (rev.body)
return 200;
View
37 Source/TDDatabase_Tests.m
@@ -62,7 +62,7 @@
CAssert([rev1.revID hasPrefix: @"1-"]);
// Read it back:
- TDRevision* readRev = [db getDocumentWithID: rev1.docID];
+ TDRevision* readRev = [db getDocumentWithID: rev1.docID revisionID: nil withAttachments: NO];
CAssert(readRev != nil);
CAssertEqual(userProperties(readRev.properties), userProperties(doc.properties));
@@ -79,7 +79,7 @@
CAssert([rev2.revID hasPrefix: @"2-"]);
// Read it back:
- readRev = [db getDocumentWithID: rev2.docID];
+ readRev = [db getDocumentWithID: rev2.docID revisionID: nil withAttachments: NO];
CAssert(readRev != nil);
CAssertEqual(userProperties(readRev.properties), userProperties(doc.properties));
@@ -95,7 +95,7 @@
CAssert([revD.revID hasPrefix: @"3-"]);
// Read it back (should fail):
- readRev = [db getDocumentWithID: revD.docID];
+ readRev = [db getDocumentWithID: revD.docID revisionID: nil withAttachments: NO];
CAssertNil(readRev);
TDRevisionList* changes = [db changesSinceSequence: 0 options: NULL];
@@ -111,7 +111,7 @@
static void verifyHistory(TDDatabase* db, TDRevision* rev, NSArray* history) {
- TDRevision* gotRev = [db getDocumentWithID: rev.docID];
+ TDRevision* gotRev = [db getDocumentWithID: rev.docID revisionID: nil withAttachments: NO];
CAssertEqual(gotRev, rev);
CAssertEqual(gotRev.properties, rev.properties);
@@ -149,7 +149,7 @@ static void verifyHistory(TDDatabase* db, TDRevision* rev, NSArray* history) {
verifyHistory(db, conflict, history);
// Fetch one of those phantom revisions with no body:
- TDRevision* rev2 = [db getDocumentWithID: rev.docID revisionID: @"2-too"];
+ TDRevision* rev2 = [db getDocumentWithID: rev.docID revisionID: @"2-too" withAttachments: NO];
CAssertEqual(rev2.docID, rev.docID);
CAssertEqual(rev2.revID, @"2-too");
CAssertEqual(rev2.body, nil);
@@ -158,7 +158,7 @@ static void verifyHistory(TDDatabase* db, TDRevision* rev, NSArray* history) {
CAssertEq(db.lastSequence, 7u);
// Make sure the revision with the higher revID wins the conflict:
- TDRevision* current = [db getDocumentWithID: rev.docID];
+ TDRevision* current = [db getDocumentWithID: rev.docID revisionID: nil withAttachments: NO];
CAssertEqual(current, conflict);
}
@@ -192,13 +192,23 @@ static void verifyHistory(TDDatabase* db, TDRevision* rev, NSArray* history) {
CAssertEqual(type, @"text/plain");
// Check the attachment dict:
- NSDictionary* attachmentDict = $dict({@"attach", $dict({@"content_type", @"text/plain"},
- {@"digest", @"sha1-gOHUOBmIMoDCrMuGyaLWzf1hQTE="},
- {@"length", $object(27)},
- {@"stub", $true},
- {@"revpos", $object(1)})});
+ NSMutableDictionary* itemDict = $mdict({@"content_type", @"text/plain"},
+ {@"digest", @"sha1-gOHUOBmIMoDCrMuGyaLWzf1hQTE="},
+ {@"length", $object(27)},
+ {@"stub", $true},
+ {@"revpos", $object(1)});
+ NSDictionary* attachmentDict = $dict({@"attach", itemDict});
CAssertEqual([db getAttachmentDictForSequence: rev1.sequence withContent: NO], attachmentDict);
- TDRevision* gotRev1 = [db getDocumentWithID: rev1.docID revisionID: rev1.revID];
+ TDRevision* gotRev1 = [db getDocumentWithID: rev1.docID revisionID: rev1.revID
+ withAttachments: NO];
+ CAssertEqual([gotRev1.properties objectForKey: @"_attachments"], attachmentDict);
+
+ // Check the attachment dict, with attachments included:
+ [itemDict removeObjectForKey: @"stub"];
+ [itemDict setObject: [TDBase64 encode: attach1] forKey: @"data"];
+ CAssertEqual([db getAttachmentDictForSequence: rev1.sequence withContent: YES], attachmentDict);
+ gotRev1 = [db getDocumentWithID: rev1.docID revisionID: rev1.revID
+ withAttachments: YES];
CAssertEqual([gotRev1.properties objectForKey: @"_attachments"], attachmentDict);
// Add a second revision that doesn't update the attachment:
@@ -273,7 +283,8 @@ static void verifyHistory(TDDatabase* db, TDRevision* rev, NSArray* history) {
// Examine the attachment store:
CAssertEq(db.attachmentStore.count, 1u);
- TDRevision* gotRev1 = [db getDocumentWithID: rev1.docID revisionID: rev1.revID];
+ TDRevision* gotRev1 = [db getDocumentWithID: rev1.docID revisionID: rev1.revID
+ withAttachments: NO];
attachmentDict = [gotRev1.properties objectForKey: @"_attachments"];
CAssertEqual(attachmentDict, $dict({@"attach", $dict({@"content_type", @"text/plain"},
{@"digest", @"sha1-gOHUOBmIMoDCrMuGyaLWzf1hQTE="},
View
2  Source/TDPusher.m
@@ -93,7 +93,7 @@ - (void) processInbox: (TDRevisionList*)changes {
else {
// OPT: Shouldn't include all attachment bodies, just ones that have changed
// OPT: Should send docs with many or big attachments as multipart/related
- if (![_db loadRevisionBody: rev andAttachments: YES]) {
+ if (![_db loadRevisionBody: rev withAttachments: YES]) {
Warn(@"%@: Couldn't get local contents of %@", self, rev);
return nil;
}
View
16 Source/TDRouter.m
@@ -87,6 +87,11 @@ - (NSString*) query: (NSString*)param {
return [self.queries objectForKey: param];
}
+- (BOOL) boolQuery: (NSString*)param {
+ NSString* value = [self.queries objectForKey: param];
+ return value && !$equal(value, @"false") && !$equal(value, @"0");
+}
+
- (TDStatus) openDB {
if (!_db.exists)
@@ -352,9 +357,9 @@ - (BOOL) getQueryOptions: (TDQueryOptions*)options {
param = [self query: @"skip"];
if (param)
options->skip = param.intValue;
- options->descending = $equal([self query: @"descending"], @"true");
- options->includeDocs = $equal([self query: @"include_docs"], @"true");
- options->updateSeq = $equal([self query: @"update_seq"], @"true");
+ options->descending = [self boolQuery: @"descending"];
+ options->includeDocs = [self boolQuery: @"include_docs"];
+ options->updateSeq = [self boolQuery: @"update_seq"];
return YES;
}
@@ -469,8 +474,9 @@ - (NSString*) setResponseEtag: (TDRevision*)rev {
- (TDStatus) do_GET: (TDDatabase*)db docID: (NSString*)docID {
- NSString* revID = [self query: @"rev"]; // often nil
- TDRevision* rev = [db getDocumentWithID: docID revisionID: revID];
+ TDRevision* rev = [db getDocumentWithID: docID
+ revisionID: [self query: @"rev"] // often nil
+ withAttachments: [self boolQuery: @"attachments"]];
if (!rev)
return 404;
View
10 Source/TDRouter_Tests.m
@@ -296,6 +296,16 @@ static id Send(TDServer* server, NSString* method, NSString* path,
response = SendRequest(server, @"GET", @"/db/missingdoc/bogus", nil);
CAssertEq(response.status, 404);
+
+ // Get the document with attachment data:
+ response = SendRequest(server, @"GET", @"/db/doc1?attachments=true", nil);
+ CAssertEq(response.status, 200);
+ CAssertEqual([response.body.properties objectForKey: @"_attachments"],
+ $dict({@"attach", $dict({@"data", [TDBase64 encode: attach1]},
+ {@"content_type", @"text/plain"},
+ {@"length", $object(attach1.length)},
+ {@"digest", @"sha1-gOHUOBmIMoDCrMuGyaLWzf1hQTE="},
+ {@"revpos", $object(1)})}));
}
Please sign in to comment.
Something went wrong with that request. Please try again.