|
49 | 49 | #define CLOUDSYNC_INIT_NTABLES 64 |
50 | 50 | #define CLOUDSYNC_MIN_DB_VERSION 0 |
51 | 51 |
|
52 | | -#define CLOUDSYNC_PAYLOAD_SKIP_SCHEMA_HASH_CHECK 1 |
53 | 52 | #define CLOUDSYNC_PAYLOAD_MINBUF_SIZE (512*1024) |
54 | 53 | #define CLOUDSYNC_PAYLOAD_SIGNATURE 0x434C5359 /* 'C','L','S','Y' */ |
55 | 54 | #define CLOUDSYNC_PAYLOAD_VERSION_ORIGNAL 1 |
56 | 55 | #define CLOUDSYNC_PAYLOAD_VERSION_1 CLOUDSYNC_PAYLOAD_VERSION_ORIGNAL |
57 | 56 | #define CLOUDSYNC_PAYLOAD_VERSION_2 2 |
| 57 | +#define CLOUDSYNC_PAYLOAD_VERSION_LATEST CLOUDSYNC_PAYLOAD_VERSION_2 |
58 | 58 | #define CLOUDSYNC_PAYLOAD_MIN_VERSION_WITH_CHECKSUM CLOUDSYNC_PAYLOAD_VERSION_2 |
59 | 59 |
|
60 | 60 | #ifndef MAX |
|
63 | 63 |
|
64 | 64 | #define DEBUG_DBERROR(_rc, _fn, _data) do {if (_rc != DBRES_OK) printf("Error in %s: %s\n", _fn, database_errmsg(_data));} while (0) |
65 | 65 |
|
66 | | -#if CLOUDSYNC_PAYLOAD_SKIP_SCHEMA_HASH_CHECK |
67 | | -bool schema_hash_disabled = true; |
68 | | -#endif |
69 | | - |
70 | 66 | typedef enum { |
71 | 67 | CLOUDSYNC_PK_INDEX_TBL = 0, |
72 | 68 | CLOUDSYNC_PK_INDEX_PK = 1, |
@@ -1208,18 +1204,20 @@ int merge_insert_col (cloudsync_context *data, cloudsync_table_context *table, c |
1208 | 1204 | return rc; |
1209 | 1205 | } |
1210 | 1206 |
|
1211 | | - // bind value |
| 1207 | + // bind value (always bind all expected parameters for correct prepared statement handling) |
1212 | 1208 | if (col_value) { |
1213 | 1209 | rc = databasevm_bind_value(vm, table->npks+1, col_value); |
1214 | 1210 | if (rc == DBRES_OK) rc = databasevm_bind_value(vm, table->npks+2, col_value); |
1215 | | - if (rc != DBRES_OK) { |
1216 | | - cloudsync_set_dberror(data); |
1217 | | - dbvm_reset(vm); |
1218 | | - return rc; |
1219 | | - } |
1220 | | - |
| 1211 | + } else { |
| 1212 | + rc = databasevm_bind_null(vm, table->npks+1); |
| 1213 | + if (rc == DBRES_OK) rc = databasevm_bind_null(vm, table->npks+2); |
1221 | 1214 | } |
1222 | | - |
| 1215 | + if (rc != DBRES_OK) { |
| 1216 | + cloudsync_set_dberror(data); |
| 1217 | + dbvm_reset(vm); |
| 1218 | + return rc; |
| 1219 | + } |
| 1220 | + |
1223 | 1221 | // perform real operation and disable triggers |
1224 | 1222 |
|
1225 | 1223 | // in case of GOS we reused the table->col_merge_stmt statement |
@@ -2358,15 +2356,17 @@ int cloudsync_payload_apply (cloudsync_context *data, const char *payload, int b |
2358 | 2356 | header.nrows = ntohl(header.nrows); |
2359 | 2357 | header.schema_hash = ntohll(header.schema_hash); |
2360 | 2358 |
|
2361 | | - #if !CLOUDSYNC_PAYLOAD_SKIP_SCHEMA_HASH_CHECK |
2362 | | - if (!data || header.schema_hash != data->schema_hash) { |
2363 | | - if (!database_check_schema_hash(data, header.schema_hash)) { |
2364 | | - char buffer[1024]; |
2365 | | - snprintf(buffer, sizeof(buffer), "Cannot apply the received payload because the schema hash is unknown %llu.", header.schema_hash); |
2366 | | - return cloudsync_set_error(data, buffer, DBRES_MISUSE); |
| 2359 | + // compare schema_hash only if not disabled and if the received payload was created with the current header version |
| 2360 | + // to avoid schema hash mismatch when processed by a peer with a different extension version during software updates. |
| 2361 | + if (dbutils_settings_get_int64_value(data, CLOUDSYNC_KEY_SKIP_SCHEMA_HASH_CHECK) == 0 && header.version == CLOUDSYNC_PAYLOAD_VERSION_LATEST ) { |
| 2362 | + if (header.schema_hash != data->schema_hash) { |
| 2363 | + if (!database_check_schema_hash(data, header.schema_hash)) { |
| 2364 | + char buffer[1024]; |
| 2365 | + snprintf(buffer, sizeof(buffer), "Cannot apply the received payload because the schema hash is unknown %llu.", header.schema_hash); |
| 2366 | + return cloudsync_set_error(data, buffer, DBRES_MISUSE); |
| 2367 | + } |
2367 | 2368 | } |
2368 | 2369 | } |
2369 | | - #endif |
2370 | 2370 |
|
2371 | 2371 | // sanity check header |
2372 | 2372 | if ((header.signature != CLOUDSYNC_PAYLOAD_SIGNATURE) || (header.ncols == 0)) { |
@@ -2539,8 +2539,8 @@ int cloudsync_payload_get (cloudsync_context *data, char **blob, int *blob_size, |
2539 | 2539 |
|
2540 | 2540 | // retrieve BLOB |
2541 | 2541 | char sql[1024]; |
2542 | | - snprintf(sql, sizeof(sql), "WITH max_db_version AS (SELECT MAX(db_version) AS max_db_version FROM cloudsync_changes) " |
2543 | | - "SELECT * FROM (SELECT cloudsync_payload_encode(tbl, pk, col_name, col_value, col_version, db_version, site_id, cl, seq) AS payload, max_db_version AS max_db_version, MAX(IIF(db_version = max_db_version, seq, NULL)) FROM cloudsync_changes, max_db_version WHERE site_id=cloudsync_siteid() AND (db_version>%d OR (db_version=%d AND seq>%d))) WHERE payload IS NOT NULL", *db_version, *db_version, *seq); |
| 2542 | + snprintf(sql, sizeof(sql), "WITH max_db_version AS (SELECT MAX(db_version) AS max_db_version FROM cloudsync_changes WHERE site_id=cloudsync_siteid()) " |
| 2543 | + "SELECT * FROM (SELECT cloudsync_payload_encode(tbl, pk, col_name, col_value, col_version, db_version, site_id, cl, seq) AS payload, max_db_version AS max_db_version, MAX(IIF(db_version = max_db_version, seq, 0)) FROM cloudsync_changes, max_db_version WHERE site_id=cloudsync_siteid() AND (db_version>%d OR (db_version=%d AND seq>%d))) WHERE payload IS NOT NULL", *db_version, *db_version, *seq); |
2544 | 2544 |
|
2545 | 2545 | int64_t len = 0; |
2546 | 2546 | int rc = database_select_blob_2int(data, sql, blob, &len, new_db_version, new_seq); |
|
0 commit comments