@@ -1261,6 +1261,8 @@ public synchronized boolean open() {
12611261 "key BLOB NOT NULL, " +
12621262 "type TEXT, " +
12631263 "length INTEGER NOT NULL, " +
1264+ "encoding INTEGER DEFAULT 0, " +
1265+ "encoded_length INTEGER, " +
12641266 "revpos INTEGER DEFAULT 0); " +
12651267 "CREATE INDEX attachments_by_sequence on attachments(sequence, filename); " +
12661268 "CREATE INDEX attachments_sequence ON attachments(sequence); " +
@@ -1289,9 +1291,16 @@ public synchronized boolean open() {
12891291 int revPos = (Integer ) attachment .get ("revpos" );
12901292 int length = (Integer ) attachment .get ("length" );
12911293 String digest = (String ) attachment .get ("digest" );
1294+ int encodedLength = -1 ;
1295+ if (attachment .containsKey ("encoded_length" ))
1296+ encodedLength = (Integer )attachment .get ("encoded_length" );
1297+ AttachmentInternal .AttachmentEncoding encoding = AttachmentInternal .AttachmentEncoding .AttachmentEncodingNone ;
1298+ if (attachment .containsKey ("encoding" ) && attachment .get ("encoding" ).equals ("gzip" )){
1299+ encoding = AttachmentInternal .AttachmentEncoding .AttachmentEncodingGZIP ;
1300+ }
12921301 BlobKey key = new BlobKey (digest );
12931302 try {
1294- insertAttachmentForSequenceWithNameAndType (sequence , name , contentType , revPos , key , length );
1303+ insertAttachmentForSequenceWithNameAndType (sequence , name , contentType , revPos , key , length , encoding , encodedLength );
12951304 } catch (CouchbaseLiteException e ) {
12961305 Log .e (Log .TAG_DATABASE , "Attachment information inserstion error: " + name + "=" + attachment .toString (), e );
12971306 return false ;
@@ -2846,10 +2855,15 @@ void insertAttachmentForSequence(AttachmentInternal attachment, long sequence) t
28462855 attachment .getName (),
28472856 attachment .getContentType (),
28482857 attachment .getRevpos (),
2849- attachment .getBlobKey ());
2858+ attachment .getBlobKey (),
2859+ attachment .getLength (),
2860+ attachment .getEncoding (),
2861+ attachment .getEncodedLength ());
28502862 }
28512863
28522864 /**
2865+ * Note: This method is used only from unit tests.
2866+ *
28532867 * @exclude
28542868 */
28552869 @ InterfaceAudience .Private
@@ -2874,37 +2888,28 @@ public void insertAttachmentForSequenceWithNameAndType(InputStream contentStream
28742888 */
28752889 @ InterfaceAudience .Private
28762890 public void insertAttachmentForSequenceWithNameAndType (long sequence , String name , String contentType , int revpos , BlobKey key ) throws CouchbaseLiteException {
2877- try {
2878- ContentValues args = new ContentValues ();
2879- args .put ("sequence" , sequence );
2880- args .put ("filename" , name );
2881- if (key != null ) {
2882- args .put ("key" , key .getBytes ());
2883- args .put ("length" , attachments .getSizeOfBlob (key ));
2884- }
2885- args .put ("type" , contentType );
2886- args .put ("revpos" , revpos );
2887- long result = database .insert ("attachments" , null , args );
2888- if (result == -1 ) {
2889- String msg = "Insert attachment failed (returned -1)" ;
2890- Log .e (Database .TAG , msg );
2891- throw new CouchbaseLiteException (msg , Status .INTERNAL_SERVER_ERROR );
2892- }
2893- } catch (SQLException e ) {
2894- Log .e (Database .TAG , "Error inserting attachment" , e );
2895- throw new CouchbaseLiteException (e , Status .INTERNAL_SERVER_ERROR );
2896- }
2891+ insertAttachmentForSequenceWithNameAndType (sequence , name , contentType , revpos , key , key != null ? attachments .getSizeOfBlob (key ): -1 , AttachmentInternal .AttachmentEncoding .AttachmentEncodingNone , -1 );
28972892 }
28982893
2899- private void insertAttachmentForSequenceWithNameAndType (long sequence , String name , String contentType , int revpos , BlobKey key , long length ) throws CouchbaseLiteException {
2894+ private void insertAttachmentForSequenceWithNameAndType (long sequence , String name , String contentType , int revpos , BlobKey key , long length , AttachmentInternal . AttachmentEncoding encoding , long encodedLength ) throws CouchbaseLiteException {
29002895 try {
29012896 ContentValues args = new ContentValues ();
29022897 args .put ("sequence" , sequence );
29032898 args .put ("filename" , name );
2904- args .put ("key" , key .getBytes ());
2905- args .put ("length" , length );
29062899 args .put ("type" , contentType );
29072900 args .put ("revpos" , revpos );
2901+ if (key != null ) {
2902+ args .put ("key" , key .getBytes ());
2903+ }
2904+ if (length >= 0 ) {
2905+ args .put ("length" , length );
2906+ }
2907+ if (encoding == AttachmentInternal .AttachmentEncoding .AttachmentEncodingGZIP ) {
2908+ args .put ("encoding" , encoding .ordinal ());
2909+ if (encodedLength >= 0 ) {
2910+ args .put ("encoded_length" , encodedLength );
2911+ }
2912+ }
29082913 long result = database .insert ("attachments" , null , args );
29092914 if (result == -1 ) {
29102915 String msg = "Insert attachment failed (returned -1)" ;
@@ -2916,6 +2921,7 @@ private void insertAttachmentForSequenceWithNameAndType(long sequence, String na
29162921 throw new CouchbaseLiteException (e , Status .INTERNAL_SERVER_ERROR );
29172922 }
29182923 }
2924+
29192925 /**
29202926 * @exclude
29212927 */
@@ -3108,7 +3114,7 @@ public Map<String,Object> getAttachmentsDictForSequenceWithContent(long sequence
31083114
31093115 String args [] = { Long .toString (sequence ) };
31103116 try {
3111- cursor = database .rawQuery ("SELECT filename, key, type, length, revpos FROM attachments WHERE sequence=?" , args );
3117+ cursor = database .rawQuery ("SELECT filename, key, type, encoding, length, encoded_length , revpos FROM attachments WHERE sequence=?" , args );
31123118
31133119 if (!cursor .moveToNext ()) {
31143120 return null ;
@@ -3119,7 +3125,10 @@ public Map<String,Object> getAttachmentsDictForSequenceWithContent(long sequence
31193125 while (!cursor .isAfterLast ()) {
31203126
31213127 boolean dataSuppressed = false ;
3122- int length = cursor .getInt (3 );
3128+ int length = cursor .getInt (4 );
3129+
3130+ AttachmentInternal .AttachmentEncoding encoding = AttachmentInternal .AttachmentEncoding .values ()[cursor .getInt (3 )];
3131+ int encodedLength = cursor .getInt (5 );
31233132
31243133 byte [] keyData = cursor .getBlob (1 );
31253134 BlobKey key = new BlobKey (keyData );
@@ -3132,39 +3141,42 @@ public Map<String,Object> getAttachmentsDictForSequenceWithContent(long sequence
31323141 }
31333142 else {
31343143 byte [] data = attachments .blobForKey (key );
3135-
31363144 if (data != null ) {
31373145 dataBase64 = Base64 .encodeBytes (data ); // <-- very expensive
31383146 }
31393147 else {
31403148 Log .w (Database .TAG , "Error loading attachment. Sequence: %s" , sequence );
31413149 }
3142-
31433150 }
3151+ }
31443152
3153+ String encodingStr = null ;
3154+ if (encoding == AttachmentInternal .AttachmentEncoding .AttachmentEncodingGZIP ) {
3155+ // NOTE: iOS decode if attachment is included int the dict.
3156+ encodingStr = "gzip" ;
31453157 }
31463158
31473159 Map <String , Object > attachment = new HashMap <String , Object >();
3148-
3149-
3150-
3151- if (!(dataBase64 != null || dataSuppressed )) {
3160+ if (!(dataBase64 != null || dataSuppressed )) {
31523161 attachment .put ("stub" , true );
31533162 }
3154-
3155- if (dataBase64 != null ) {
3163+ if (dataBase64 != null ) {
31563164 attachment .put ("data" , dataBase64 );
31573165 }
3158-
31593166 if (dataSuppressed == true ) {
31603167 attachment .put ("follows" , true );
31613168 }
3162-
31633169 attachment .put ("digest" , digestString );
31643170 String contentType = cursor .getString (2 );
31653171 attachment .put ("content_type" , contentType );
3172+ if (encodingStr != null ) {
3173+ attachment .put ("encoding" , encodingStr );
3174+ }
31663175 attachment .put ("length" , length );
3167- attachment .put ("revpos" , cursor .getInt (4 ));
3176+ if (encodingStr != null && encodedLength >= 0 ) {
3177+ attachment .put ("encoded_length" , encodedLength );
3178+ }
3179+ attachment .put ("revpos" , cursor .getInt (6 ));
31683180
31693181 String filename = cursor .getString (0 );
31703182 result .put (filename , attachment );
@@ -4254,7 +4266,7 @@ Map<String, AttachmentInternal> getAttachmentsFromRevision(RevisionInternal rev,
42544266 // If there's inline attachment data, decode and store it:
42554267 byte [] newContents ;
42564268 try {
4257- newContents = Base64 .decode (newContentBase64 );
4269+ newContents = Base64 .decode (newContentBase64 , Base64 . DONT_GUNZIP );
42584270 } catch (IOException e ) {
42594271 throw new CouchbaseLiteException (e , Status .BAD_ENCODING );
42604272 }
0 commit comments