Skip to content

Commit f246981

Browse files
committed
fix(postgresql): resolve commit_alter crash and BYTEA handling in column_text
Guard savepoint commit/rollback against missing subtransactions to prevent segfault in autocommit mode. Add BYTEA support to database_column_text so encoded PKs are readable during refill_metatable after ALTER TABLE. Enable alter table sync test (31).
1 parent 01b315a commit f246981

File tree

6 files changed

+51
-36
lines changed

6 files changed

+51
-36
lines changed

src/cloudsync.c

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -258,7 +258,7 @@ bool force_uncompressed_blob = false;
258258
#endif
259259

260260
// Internal prototypes
261-
int local_mark_insert_or_update_meta (cloudsync_table_context *table, const char *pk, size_t pklen, const char *col_name, int64_t db_version, int seq);
261+
int local_mark_insert_or_update_meta (cloudsync_table_context *table, const void *pk, size_t pklen, const char *col_name, int64_t db_version, int seq);
262262

263263
// MARK: - CRDT algos -
264264

@@ -1472,7 +1472,7 @@ static int merge_flush_pending (cloudsync_context *data) {
14721472
return rc;
14731473
}
14741474

1475-
int merge_insert_col (cloudsync_context *data, cloudsync_table_context *table, const char *pk, int pklen, const char *col_name, dbvalue_t *col_value, int64_t col_version, int64_t db_version, const char *site_id, int site_len, int64_t seq, int64_t *rowid) {
1475+
int merge_insert_col (cloudsync_context *data, cloudsync_table_context *table, const void *pk, int pklen, const char *col_name, dbvalue_t *col_value, int64_t col_version, int64_t db_version, const char *site_id, int site_len, int64_t seq, int64_t *rowid) {
14761476
int index;
14771477
dbvm_t *vm = table_column_lookup(table, col_name, true, &index);
14781478
if (vm == NULL) return cloudsync_set_error(data, "Unable to retrieve column merge precompiled statement in merge_insert_col", DBRES_MISUSE);
@@ -1655,7 +1655,7 @@ int merge_did_cid_win (cloudsync_context *data, cloudsync_table_context *table,
16551655

16561656
rc = databasevm_step(vm);
16571657
if (rc == DBRES_ROW) {
1658-
const void *local_site_id = database_column_blob(vm, 0);
1658+
const void *local_site_id = database_column_blob(vm, 0, NULL);
16591659
if (!local_site_id) {
16601660
dbvm_reset(vm);
16611661
return cloudsync_set_error(data, "NULL site_id in cloudsync table, table is probably corrupted", DBRES_ERROR);
@@ -2235,13 +2235,13 @@ int cloudsync_refill_metatable (cloudsync_context *data, const char *table_name)
22352235

22362236
rc = databasevm_bind_text(vm, 1, col_name, -1);
22372237
if (rc != DBRES_OK) goto finalize;
2238-
2238+
22392239
while (1) {
22402240
rc = databasevm_step(vm);
22412241
if (rc == DBRES_ROW) {
2242-
const char *pk = (const char *)database_column_text(vm, 0);
2242+
size_t pklen = 0;
2243+
const void *pk = (const char *)database_column_blob(vm, 0, &pklen);
22432244
if (!pk) { rc = DBRES_ERROR; break; }
2244-
size_t pklen = strlen(pk);
22452245
rc = local_mark_insert_or_update_meta(table, pk, pklen, col_name, db_version, cloudsync_bumpseq(data));
22462246
} else if (rc == DBRES_DONE) {
22472247
rc = DBRES_OK;
@@ -2264,7 +2264,7 @@ int cloudsync_refill_metatable (cloudsync_context *data, const char *table_name)
22642264

22652265
// MARK: - Local -
22662266

2267-
int local_update_sentinel (cloudsync_table_context *table, const char *pk, size_t pklen, int64_t db_version, int seq) {
2267+
int local_update_sentinel (cloudsync_table_context *table, const void *pk, size_t pklen, int64_t db_version, int seq) {
22682268
dbvm_t *vm = table->meta_sentinel_update_stmt;
22692269
if (!vm) return -1;
22702270

@@ -2286,7 +2286,7 @@ int local_update_sentinel (cloudsync_table_context *table, const char *pk, size_
22862286
return rc;
22872287
}
22882288

2289-
int local_mark_insert_sentinel_meta (cloudsync_table_context *table, const char *pk, size_t pklen, int64_t db_version, int seq) {
2289+
int local_mark_insert_sentinel_meta (cloudsync_table_context *table, const void *pk, size_t pklen, int64_t db_version, int seq) {
22902290
dbvm_t *vm = table->meta_sentinel_insert_stmt;
22912291
if (!vm) return -1;
22922292

@@ -2314,7 +2314,7 @@ int local_mark_insert_sentinel_meta (cloudsync_table_context *table, const char
23142314
return rc;
23152315
}
23162316

2317-
int local_mark_insert_or_update_meta_impl (cloudsync_table_context *table, const char *pk, size_t pklen, const char *col_name, int col_version, int64_t db_version, int seq) {
2317+
int local_mark_insert_or_update_meta_impl (cloudsync_table_context *table, const void *pk, size_t pklen, const char *col_name, int col_version, int64_t db_version, int seq) {
23182318

23192319
dbvm_t *vm = table->meta_row_insert_update_stmt;
23202320
if (!vm) return -1;
@@ -2349,15 +2349,15 @@ int local_mark_insert_or_update_meta_impl (cloudsync_table_context *table, const
23492349
return rc;
23502350
}
23512351

2352-
int local_mark_insert_or_update_meta (cloudsync_table_context *table, const char *pk, size_t pklen, const char *col_name, int64_t db_version, int seq) {
2352+
int local_mark_insert_or_update_meta (cloudsync_table_context *table, const void *pk, size_t pklen, const char *col_name, int64_t db_version, int seq) {
23532353
return local_mark_insert_or_update_meta_impl(table, pk, pklen, col_name, 1, db_version, seq);
23542354
}
23552355

2356-
int local_mark_delete_meta (cloudsync_table_context *table, const char *pk, size_t pklen, int64_t db_version, int seq) {
2356+
int local_mark_delete_meta (cloudsync_table_context *table, const void *pk, size_t pklen, int64_t db_version, int seq) {
23572357
return local_mark_insert_or_update_meta_impl(table, pk, pklen, NULL, 2, db_version, seq);
23582358
}
23592359

2360-
int local_drop_meta (cloudsync_table_context *table, const char *pk, size_t pklen) {
2360+
int local_drop_meta (cloudsync_table_context *table, const void *pk, size_t pklen) {
23612361
dbvm_t *vm = table->meta_row_drop_stmt;
23622362
if (!vm) return -1;
23632363

@@ -2373,7 +2373,7 @@ int local_drop_meta (cloudsync_table_context *table, const char *pk, size_t pkle
23732373
return rc;
23742374
}
23752375

2376-
int local_update_move_meta (cloudsync_table_context *table, const char *pk, size_t pklen, const char *pk2, size_t pklen2, int64_t db_version) {
2376+
int local_update_move_meta (cloudsync_table_context *table, const void *pk, size_t pklen, const void *pk2, size_t pklen2, int64_t db_version) {
23772377
/*
23782378
* This function moves non-sentinel metadata entries from an old primary key (OLD.pk)
23792379
* to a new primary key (NEW.pk) when a primary key change occurs.

src/cloudsync.h

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -104,15 +104,15 @@ int table_remove (cloudsync_context *data, cloudsync_table_context *table);
104104
void table_free (cloudsync_table_context *table);
105105

106106
// local merge/apply
107-
int local_mark_insert_sentinel_meta (cloudsync_table_context *table, const char *pk, size_t pklen, int64_t db_version, int seq);
108-
int local_update_sentinel (cloudsync_table_context *table, const char *pk, size_t pklen, int64_t db_version, int seq);
109-
int local_mark_insert_or_update_meta (cloudsync_table_context *table, const char *pk, size_t pklen, const char *col_name, int64_t db_version, int seq);
110-
int local_mark_delete_meta (cloudsync_table_context *table, const char *pk, size_t pklen, int64_t db_version, int seq);
111-
int local_drop_meta (cloudsync_table_context *table, const char *pk, size_t pklen);
112-
int local_update_move_meta (cloudsync_table_context *table, const char *pk, size_t pklen, const char *pk2, size_t pklen2, int64_t db_version);
107+
int local_mark_insert_sentinel_meta (cloudsync_table_context *table, const void *pk, size_t pklen, int64_t db_version, int seq);
108+
int local_update_sentinel (cloudsync_table_context *table, const void *pk, size_t pklen, int64_t db_version, int seq);
109+
int local_mark_insert_or_update_meta (cloudsync_table_context *table, const void *pk, size_t pklen, const char *col_name, int64_t db_version, int seq);
110+
int local_mark_delete_meta (cloudsync_table_context *table, const void *pk, size_t pklen, int64_t db_version, int seq);
111+
int local_drop_meta (cloudsync_table_context *table, const void *pk, size_t pklen);
112+
int local_update_move_meta (cloudsync_table_context *table, const void *pk, size_t pklen, const void *pk2, size_t pklen2, int64_t db_version);
113113

114114
// used by changes virtual table
115-
int merge_insert_col (cloudsync_context *data, cloudsync_table_context *table, const char *pk, int pklen, const char *col_name, dbvalue_t *col_value, int64_t col_version, int64_t db_version, const char *site_id, int site_len, int64_t seq, int64_t *rowid);
115+
int merge_insert_col (cloudsync_context *data, cloudsync_table_context *table, const void *pk, int pklen, const char *col_name, dbvalue_t *col_value, int64_t col_version, int64_t db_version, const char *site_id, int site_len, int64_t seq, int64_t *rowid);
116116
int merge_insert (cloudsync_context *data, cloudsync_table_context *table, const char *insert_pk, int insert_pk_len, int64_t insert_cl, const char *insert_name, dbvalue_t *insert_value, int64_t insert_col_version, int64_t insert_db_version, const char *insert_site_id, int insert_site_id_len, int64_t insert_seq, int64_t *rowid);
117117

118118
// filter rewrite

src/database.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ void database_value_free (dbvalue_t *value);
119119
void *database_value_dup (dbvalue_t *value);
120120

121121
// COLUMN
122-
const void *database_column_blob (dbvm_t *vm, int index);
122+
const void *database_column_blob (dbvm_t *vm, int index, size_t *len);
123123
double database_column_double (dbvm_t *vm, int index);
124124
int64_t database_column_int (dbvm_t *vm, int index);
125125
const char *database_column_text (dbvm_t *vm, int index);

src/postgresql/cloudsync_postgresql.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1984,8 +1984,8 @@ Datum cloudsync_col_value(PG_FUNCTION_ARGS) {
19841984
PG_RETURN_BYTEA_P(result);
19851985
} else if (rc == DBRES_ROW) {
19861986
// copy value before reset invalidates SPI tuple memory
1987-
const void *blob = database_column_blob(vm, 0);
1988-
int blob_len = database_column_bytes(vm, 0);
1987+
size_t blob_len = 0;
1988+
const void *blob = database_column_blob(vm, 0, &blob_len);
19891989
bytea *result = NULL;
19901990
if (blob && blob_len > 0) {
19911991
result = (bytea *)palloc(VARHDRSZ + blob_len);

src/postgresql/database_postgresql.c

Lines changed: 26 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2476,7 +2476,7 @@ Datum database_column_datum (dbvm_t *vm, int index) {
24762476
return (isnull) ? (Datum)0 : d;
24772477
}
24782478

2479-
const void *database_column_blob (dbvm_t *vm, int index) {
2479+
const void *database_column_blob (dbvm_t *vm, int index, size_t *len) {
24802480
if (!vm) return NULL;
24812481
pg_stmt_t *stmt = (pg_stmt_t*)vm;
24822482
if (!stmt->last_tuptable || !stmt->current_tupdesc) return NULL;
@@ -2498,16 +2498,17 @@ const void *database_column_blob (dbvm_t *vm, int index) {
24982498
return NULL;
24992499
}
25002500

2501-
Size len = VARSIZE(ba) - VARHDRSZ;
2502-
void *out = palloc(len);
2501+
Size blen = VARSIZE(ba) - VARHDRSZ;
2502+
void *out = palloc(blen);
25032503
if (!out) {
25042504
MemoryContextSwitchTo(old);
25052505
return NULL;
25062506
}
25072507

2508-
memcpy(out, VARDATA(ba), (size_t)len);
2508+
memcpy(out, VARDATA(ba), (size_t)blen);
25092509
MemoryContextSwitchTo(old);
25102510

2511+
if (len) *len = (size_t)blen;
25112512
return out;
25122513
}
25132514

@@ -2569,15 +2570,26 @@ const char *database_column_text (dbvm_t *vm, int index) {
25692570
Datum d = get_datum(stmt, index, &isnull, &type);
25702571
if (isnull) return NULL;
25712572

2572-
if (type != TEXTOID && type != VARCHAROID && type != BPCHAROID)
2573-
return NULL; // or convert via output function if you want
2574-
25752573
MemoryContext old = MemoryContextSwitchTo(stmt->row_mcxt);
2576-
text *t = DatumGetTextP(d);
2577-
int len = VARSIZE(t) - VARHDRSZ;
2578-
char *out = palloc(len + 1);
2579-
memcpy(out, VARDATA(t), len);
2580-
out[len] = 0;
2574+
char *out = NULL;
2575+
2576+
if (type == BYTEAOID) {
2577+
bytea *b = DatumGetByteaP(d);
2578+
int len = VARSIZE(b) - VARHDRSZ;
2579+
out = palloc(len + 1);
2580+
memcpy(out, VARDATA(b), len);
2581+
out[len] = 0;
2582+
} else if (type == TEXTOID || type == VARCHAROID || type == BPCHAROID) {
2583+
text *t = DatumGetTextP(d);
2584+
int len = VARSIZE(t) - VARHDRSZ;
2585+
out = palloc(len + 1);
2586+
memcpy(out, VARDATA(t), len);
2587+
out[len] = 0;
2588+
} else {
2589+
MemoryContextSwitchTo(old);
2590+
return NULL;
2591+
}
2592+
25812593
MemoryContextSwitchTo(old);
25822594

25832595
return out;
@@ -2892,6 +2904,7 @@ int database_begin_savepoint (cloudsync_context *data, const char *savepoint_nam
28922904

28932905
int database_commit_savepoint (cloudsync_context *data, const char *savepoint_name) {
28942906
cloudsync_reset_error(data);
2907+
if (GetCurrentTransactionNestLevel() <= 1) return DBRES_OK;
28952908
int rc = DBRES_OK;
28962909

28972910
MemoryContext oldcontext = CurrentMemoryContext;
@@ -2916,6 +2929,7 @@ int database_commit_savepoint (cloudsync_context *data, const char *savepoint_na
29162929

29172930
int database_rollback_savepoint (cloudsync_context *data, const char *savepoint_name) {
29182931
cloudsync_reset_error(data);
2932+
if (GetCurrentTransactionNestLevel() <= 1) return DBRES_OK;
29192933
int rc = DBRES_OK;
29202934

29212935
MemoryContext oldcontext = CurrentMemoryContext;

src/sqlite/database_sqlite.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1289,7 +1289,8 @@ void *database_value_dup (dbvalue_t *value) {
12891289

12901290
// MARK: - COLUMN -
12911291

1292-
const void *database_column_blob (dbvm_t *vm, int index) {
1292+
const void *database_column_blob (dbvm_t *vm, int index, size_t *len) {
1293+
if (len) *len = sqlite3_column_bytes((sqlite3_stmt *)vm, index);
12931294
return sqlite3_column_blob((sqlite3_stmt *)vm, index);
12941295
}
12951296

0 commit comments

Comments
 (0)