Project

General

Profile

Actions

Send Objective-C

-(void)sendLocalChanges:(NSString*)subscriberId error:(NSError **)error{
    sqlite3 *db;
    sqlite3_stmt *stmt;
    NSString *query;

    NSMutableString *builder = [NSMutableString string];

    [builder appendString:@"<?xml version=\"1.0\" encoding=\"utf-8\"?><SyncData xmlns=\"urn:sync-schema\">"];

    if(sqlite3_open([_databasePath UTF8String], &db) == SQLITE_OK){
        NSMutableArray<NSString*> *tables = [NSMutableArray array];

        query = @"select tbl_Name from sqlite_master where type='table' and sql like '%RowId%';";
        if(sqlite3_prepare_v2(db, [query UTF8String], -1, &stmt, NULL) == SQLITE_OK){
            while(sqlite3_step(stmt) == SQLITE_ROW) {
                [tables addObject:[NSString stringWithUTF8String:(char *)sqlite3_column_text(stmt, 0)]];
            }
        }
        else{
            *error = [NSError errorWithDomain:@"com.sqlite-sync" code:0 userInfo:[NSDictionary dictionaryWithObject:[NSString stringWithFormat:@"%s", sqlite3_errmsg(db)] forKey:NSLocalizedDescriptionKey]];
        }

        if(!*error){
            for(NSString *tableName in tables){
                if([tableName caseInsensitiveCompare:@"MergeDelete"] != NSOrderedSame){
                    [builder appendFormat:@"<tab n=\"%@\">", tableName];

                    [builder appendString:@"<ins>"];
                    query = [NSString stringWithFormat:@"select * from %@ where RowId is null;", tableName];
                    if(sqlite3_prepare_v2(db, [query UTF8String], -1, &stmt, NULL) == SQLITE_OK){
                        while(sqlite3_step(stmt) == SQLITE_ROW) {
                            [builder appendString:@"<r>"];
                            for(int i = 0; i < sqlite3_column_count(stmt); i++){
                                NSString *columnName = [NSString stringWithUTF8String:sqlite3_column_name(stmt, i)];
                                if([columnName caseInsensitiveCompare:@"MergeUpdate"] != NSOrderedSame){
                                    [builder appendFormat:@"<%1$@><![CDATA[%2$s]]></%1$@>", columnName, sqlite3_column_text(stmt, i)];
                                }
                            }
                            [builder appendString:@"</r>"];
                        }
                    }
                    else{
                        *error = [NSError errorWithDomain:@"com.sqlite-sync" code:0 userInfo:[NSDictionary dictionaryWithObject:[NSString stringWithFormat:@"%s", sqlite3_errmsg(db)] forKey:NSLocalizedDescriptionKey]];
                        break;
                    }
                    [builder appendString:@"</ins>"];

                    [builder appendString:@"<upd>"];
                    query = [NSString stringWithFormat:@"select * from %@ where MergeUpdate > 0 and RowId is not null;", tableName];
                    if(sqlite3_prepare_v2(db, [query UTF8String], -1, &stmt, NULL) == SQLITE_OK){
                        while(sqlite3_step(stmt) == SQLITE_ROW) {
                            [builder appendString:@"<r>"];
                            for(int i = 0; i < sqlite3_column_count(stmt); i++){
                                NSString *columnName = [NSString stringWithUTF8String:sqlite3_column_name(stmt, i)];
                                if([columnName caseInsensitiveCompare:@"MergeUpdate"] != NSOrderedSame){
                                    [builder appendFormat:@"<%1$@><![CDATA[%2$s]]></%1$@>", columnName, sqlite3_column_text(stmt, i)];
                                }
                            }
                            [builder appendString:@"</r>"];
                        }
                    }
                    else{
                        *error = [NSError errorWithDomain:@"com.sqlite-sync" code:0 userInfo:[NSDictionary dictionaryWithObject:[NSString stringWithFormat:@"%s", sqlite3_errmsg(db)] forKey:NSLocalizedDescriptionKey]];
                        break;
                    }
                    [builder appendString:@"</upd>"];

                    [builder appendString:@"</tab>"];
                }
            }
        }

        if(!*error){
            [builder appendString:@"<delete>"];
            query = @"select TableId,RowId from MergeDelete;";
            if(sqlite3_prepare_v2(db, [query UTF8String], -1, &stmt, NULL) == SQLITE_OK){
                while(sqlite3_step(stmt) == SQLITE_ROW) {
                    [builder appendFormat:@"<r><tb>%1$s</tb><id>%2$s</id></r>", sqlite3_column_text(stmt, 0), sqlite3_column_text(stmt, 1)];
                }
            }
            else{
                *error = [NSError errorWithDomain:@"com.sqlite-sync" code:0 userInfo:[NSDictionary dictionaryWithObject:[NSString stringWithFormat:@"%s", sqlite3_errmsg(db)] forKey:NSLocalizedDescriptionKey]];
            }
            [builder appendString:@"</delete>"];
        }

        if(stmt){
            sqlite3_finalize(stmt);
        }
        sqlite3_close(db);
    }
    else{
        *error = [NSError errorWithDomain:@"com.sqlite-sync" code:0 userInfo:[NSDictionary dictionaryWithObject:@"Failed to open database" forKey:NSLocalizedDescriptionKey]];
    }

    [builder appendString:@"</SyncData>"];

    if(*error) return;

    NSDictionary *inputObject = @{@"subscriber": subscriberId, @"content": builder, @"version": @"3"};
    NSData *inputData = [NSJSONSerialization dataWithJSONObject:inputObject options:NSJSONWritingPrettyPrinted error:error];

    if(*error) return;

    NSString *requestUrlString = [NSString stringWithFormat:@"%@/Send", _serverURL];
    NSURL *requestURL = [NSURL URLWithString:requestUrlString];
    NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];

    [request setURL:requestURL];
    [request setHTTPMethod:@"POST"];
    [request setHTTPBody:inputData];
    [request setValue:@"application/json; charset=utf-8" forHTTPHeaderField:@"Content-Type"];
    [request setValue:[NSString stringWithFormat:@"%lu", (unsigned long)inputData.length] forHTTPHeaderField:@"Content-Length"];

    NSHTTPURLResponse *response;

    NSData *data = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:error];

    if(!*error){
        switch (response.statusCode) {
            case 200:
                break;
            case 204:
                break;
            default:
                *error = [NSError errorWithDomain:@"com.sqlite-sync" code:0 userInfo:[NSDictionary dictionaryWithObject:[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding] forKey:NSLocalizedDescriptionKey]];
                break;
        }
    }
}

Updated by Tomek Dziemidowicz 5 months ago · 1 revisions