Skip to content

Commit 24e13d1

Browse files
committed
fix(postgresql): fix the PG_TRY/PG_CATCH exception stack, must not return inside PG_TRY block
1 parent d9236cc commit 24e13d1

File tree

1 file changed

+91
-62
lines changed

1 file changed

+91
-62
lines changed

src/postgresql/cloudsync_postgresql.c

Lines changed: 91 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -167,12 +167,16 @@ Datum cloudsync_db_version (PG_FUNCTION_ARGS) {
167167
UNUSED_PARAMETER(fcinfo);
168168

169169
cloudsync_context *data = get_cloudsync_context();
170+
int rc = DBRES_OK;
171+
int64_t version = 0;
172+
bool spi_connected = false;
170173

171174
// Connect SPI for database operations
172175
int spi_rc = SPI_connect();
173176
if (spi_rc != SPI_OK_CONNECT) {
174177
ereport(ERROR, (errcode(ERRCODE_INTERNAL_ERROR), errmsg("SPI_connect failed: %d", spi_rc)));
175178
}
179+
spi_connected = true;
176180

177181
PG_TRY();
178182
{
@@ -182,23 +186,25 @@ Datum cloudsync_db_version (PG_FUNCTION_ARGS) {
182186
ereport(ERROR, (errcode(ERRCODE_INTERNAL_ERROR), errmsg("Unable to retrieve db_version (%s)", database_errmsg(data))));
183187
}
184188

185-
int64_t version = cloudsync_dbversion(data);
186-
SPI_finish();
187-
188-
PG_RETURN_INT64(version);
189+
version = cloudsync_dbversion(data);
189190
}
190191
PG_CATCH();
191192
{
192-
SPI_finish();
193+
if (spi_connected) SPI_finish();
193194
PG_RE_THROW();
194195
}
195196
PG_END_TRY();
197+
198+
if (spi_connected) SPI_finish();
199+
PG_RETURN_INT64(version);
196200
}
197201

198202
// cloudsync_db_version_next([merging_version]) - Get next database version
199203
PG_FUNCTION_INFO_V1(cloudsync_db_version_next);
200204
Datum cloudsync_db_version_next (PG_FUNCTION_ARGS) {
201205
cloudsync_context *data = get_cloudsync_context();
206+
int64_t next_version = 0;
207+
bool spi_connected = false;
202208

203209
int64_t merging_version = CLOUDSYNC_VALUE_NOTSET;
204210
if (PG_NARGS() == 1 && !PG_ARGISNULL(0)) {
@@ -210,21 +216,22 @@ Datum cloudsync_db_version_next (PG_FUNCTION_ARGS) {
210216
if (spi_rc != SPI_OK_CONNECT) {
211217
ereport(ERROR, (errcode(ERRCODE_INTERNAL_ERROR), errmsg("SPI_connect failed: %d", spi_rc)));
212218
}
219+
spi_connected = true;
213220

214221
PG_TRY();
215222
{
216223
cloudsync_pg_ensure_initialized(data, true);
217-
int64_t next_version = cloudsync_dbversion_next(data, merging_version);
218-
SPI_finish();
219-
220-
PG_RETURN_INT64(next_version);
224+
next_version = cloudsync_dbversion_next(data, merging_version);
221225
}
222226
PG_CATCH();
223227
{
224-
SPI_finish();
228+
if (spi_connected) SPI_finish();
225229
PG_RE_THROW();
226230
}
227231
PG_END_TRY();
232+
233+
if (spi_connected) SPI_finish();
234+
PG_RETURN_INT64(next_version);
228235
}
229236

230237
// MARK: - Table Initialization -
@@ -381,30 +388,33 @@ Datum pg_cloudsync_cleanup (PG_FUNCTION_ARGS) {
381388

382389
const char *table = text_to_cstring(PG_GETARG_TEXT_PP(0));
383390
cloudsync_context *data = get_cloudsync_context();
391+
int rc = DBRES_OK;
392+
bool spi_connected = false;
384393

385394
int spi_rc = SPI_connect();
386395
if (spi_rc != SPI_OK_CONNECT) {
387396
ereport(ERROR, (errcode(ERRCODE_INTERNAL_ERROR), errmsg("SPI_connect failed: %d", spi_rc)));
388397
}
398+
spi_connected = true;
389399

390400
PG_TRY();
391401
{
392402
cloudsync_pg_ensure_initialized(data, true);
393-
int rc = cloudsync_cleanup(data, table);
394-
SPI_finish();
395-
396-
if (rc != DBRES_OK) {
397-
ereport(ERROR, (errcode(ERRCODE_INTERNAL_ERROR), errmsg("%s", cloudsync_errmsg(data))));
398-
}
399-
400-
PG_RETURN_BOOL(true);
403+
rc = cloudsync_cleanup(data, table);
401404
}
402405
PG_CATCH();
403406
{
404-
SPI_finish();
407+
if (spi_connected) SPI_finish();
405408
PG_RE_THROW();
406409
}
407410
PG_END_TRY();
411+
412+
if (spi_connected) SPI_finish();
413+
if (rc != DBRES_OK) {
414+
ereport(ERROR, (errcode(ERRCODE_INTERNAL_ERROR), errmsg("%s", cloudsync_errmsg(data))));
415+
}
416+
417+
PG_RETURN_BOOL(true);
408418
}
409419

410420
// cloudsync_terminate - Terminate CloudSync
@@ -413,25 +423,29 @@ Datum pg_cloudsync_terminate (PG_FUNCTION_ARGS) {
413423
UNUSED_PARAMETER(fcinfo);
414424

415425
cloudsync_context *data = get_cloudsync_context();
426+
int rc = DBRES_OK;
427+
bool spi_connected = false;
416428

417429
int spi_rc = SPI_connect();
418430
if (spi_rc != SPI_OK_CONNECT) {
419431
ereport(ERROR, (errcode(ERRCODE_INTERNAL_ERROR), errmsg("SPI_connect failed: %d", spi_rc)));
420432
}
433+
spi_connected = true;
421434

422435
PG_TRY();
423436
{
424437
cloudsync_pg_ensure_initialized(data, true);
425-
int rc = cloudsync_terminate(data);
426-
SPI_finish();
427-
PG_RETURN_INT32(rc);
438+
rc = cloudsync_terminate(data);
428439
}
429440
PG_CATCH();
430441
{
431-
SPI_finish();
442+
if (spi_connected) SPI_finish();
432443
PG_RE_THROW();
433444
}
434445
PG_END_TRY();
446+
447+
if (spi_connected) SPI_finish();
448+
PG_RETURN_INT32(rc);
435449
}
436450

437451
// MARK: - Settings Functions -
@@ -455,27 +469,30 @@ Datum cloudsync_set (PG_FUNCTION_ARGS) {
455469
}
456470

457471
cloudsync_context *data = get_cloudsync_context();
472+
bool spi_connected = false;
458473

459474
int spi_rc = SPI_connect();
460475
if (spi_rc != SPI_OK_CONNECT) {
461476
ereport(ERROR,
462477
(errcode(ERRCODE_INTERNAL_ERROR),
463478
errmsg("SPI_connect failed: %d", spi_rc)));
464479
}
480+
spi_connected = true;
465481

466482
PG_TRY();
467483
{
468484
cloudsync_pg_ensure_initialized(data, true);
469485
dbutils_settings_set_key_value(data, key, value);
470-
SPI_finish();
471-
PG_RETURN_BOOL(true);
472486
}
473487
PG_CATCH();
474488
{
475-
SPI_finish();
489+
if (spi_connected) SPI_finish();
476490
PG_RE_THROW();
477491
}
478492
PG_END_TRY();
493+
494+
if (spi_connected) SPI_finish();
495+
PG_RETURN_BOOL(true);
479496
}
480497

481498
// cloudsync_set_table - Set table-level configuration
@@ -496,25 +513,28 @@ Datum cloudsync_set_table (PG_FUNCTION_ARGS) {
496513
}
497514

498515
cloudsync_context *data = get_cloudsync_context();
516+
bool spi_connected = false;
499517

500518
int spi_rc = SPI_connect();
501519
if (spi_rc != SPI_OK_CONNECT) {
502520
ereport(ERROR, (errcode(ERRCODE_INTERNAL_ERROR), errmsg("SPI_connect failed: %d", spi_rc)));
503521
}
522+
spi_connected = true;
504523

505524
PG_TRY();
506525
{
507526
cloudsync_pg_ensure_initialized(data, true);
508527
dbutils_table_settings_set_key_value(data, tbl, "*", key, value);
509-
SPI_finish();
510-
PG_RETURN_BOOL(true);
511528
}
512529
PG_CATCH();
513530
{
514-
SPI_finish();
531+
if (spi_connected) SPI_finish();
515532
PG_RE_THROW();
516533
}
517534
PG_END_TRY();
535+
536+
if (spi_connected) SPI_finish();
537+
PG_RETURN_BOOL(true);
518538
}
519539

520540
// cloudsync_set_column - Set column-level configuration
@@ -539,27 +559,30 @@ Datum cloudsync_set_column (PG_FUNCTION_ARGS) {
539559
}
540560

541561
cloudsync_context *data = get_cloudsync_context();
562+
bool spi_connected = false;
542563

543564
int spi_rc = SPI_connect();
544565
if (spi_rc != SPI_OK_CONNECT) {
545566
ereport(ERROR,
546567
(errcode(ERRCODE_INTERNAL_ERROR),
547568
errmsg("SPI_connect failed: %d", spi_rc)));
548569
}
570+
spi_connected = true;
549571

550572
PG_TRY();
551573
{
552574
cloudsync_pg_ensure_initialized(data, true);
553575
dbutils_table_settings_set_key_value(data, tbl, col, key, value);
554-
SPI_finish();
555-
PG_RETURN_BOOL(true);
556576
}
557577
PG_CATCH();
558578
{
559-
SPI_finish();
579+
if (spi_connected) SPI_finish();
560580
PG_RE_THROW();
561581
}
562582
PG_END_TRY();
583+
584+
if (spi_connected) SPI_finish();
585+
PG_RETURN_BOOL(true);
563586
}
564587

565588
// MARK: - Schema Alteration -
@@ -573,32 +596,34 @@ Datum pg_cloudsync_begin_alter (PG_FUNCTION_ARGS) {
573596

574597
const char *table_name = text_to_cstring(PG_GETARG_TEXT_PP(0));
575598
cloudsync_context *data = get_cloudsync_context();
599+
int rc = DBRES_OK;
600+
bool spi_connected = false;
576601

577602
int spi_rc = SPI_connect();
578603
if (spi_rc != SPI_OK_CONNECT) {
579604
ereport(ERROR, (errcode(ERRCODE_INTERNAL_ERROR), errmsg("SPI_connect failed: %d", spi_rc)));
580605
}
606+
spi_connected = true;
581607

582608
PG_TRY();
583609
{
584610
cloudsync_pg_ensure_initialized(data, true);
585-
int rc = cloudsync_begin_alter(data, table_name);
586-
SPI_finish();
587-
588-
if (rc != DBRES_OK) {
589-
ereport(ERROR,
590-
(errcode(ERRCODE_INTERNAL_ERROR),
591-
errmsg("%s", cloudsync_errmsg(data))));
592-
}
593-
594-
PG_RETURN_BOOL(true);
611+
rc = cloudsync_begin_alter(data, table_name);
595612
}
596613
PG_CATCH();
597614
{
598-
SPI_finish();
615+
if (spi_connected) SPI_finish();
599616
PG_RE_THROW();
600617
}
601618
PG_END_TRY();
619+
620+
if (spi_connected) SPI_finish();
621+
if (rc != DBRES_OK) {
622+
ereport(ERROR,
623+
(errcode(ERRCODE_INTERNAL_ERROR),
624+
errmsg("%s", cloudsync_errmsg(data))));
625+
}
626+
PG_RETURN_BOOL(true);
602627
}
603628

604629
// cloudsync_commit_alter - Commit schema alteration
@@ -610,30 +635,32 @@ Datum pg_cloudsync_commit_alter (PG_FUNCTION_ARGS) {
610635

611636
const char *table_name = text_to_cstring(PG_GETARG_TEXT_PP(0));
612637
cloudsync_context *data = get_cloudsync_context();
638+
int rc = DBRES_OK;
639+
bool spi_connected = false;
613640

614641
int spi_rc = SPI_connect();
615642
if (spi_rc != SPI_OK_CONNECT) {
616643
ereport(ERROR, (errcode(ERRCODE_INTERNAL_ERROR), errmsg("SPI_connect failed: %d", spi_rc)));
617644
}
645+
spi_connected = true;
618646

619647
PG_TRY();
620648
{
621649
cloudsync_pg_ensure_initialized(data, true);
622-
int rc = cloudsync_commit_alter(data, table_name);
623-
SPI_finish();
624-
625-
if (rc != DBRES_OK) {
626-
ereport(ERROR, (errcode(ERRCODE_INTERNAL_ERROR), errmsg("%s", cloudsync_errmsg(data))));
627-
}
628-
629-
PG_RETURN_BOOL(true);
650+
rc = cloudsync_commit_alter(data, table_name);
630651
}
631652
PG_CATCH();
632653
{
633-
SPI_finish();
654+
if (spi_connected) SPI_finish();
634655
PG_RE_THROW();
635656
}
636657
PG_END_TRY();
658+
659+
if (spi_connected) SPI_finish();
660+
if (rc != DBRES_OK) {
661+
ereport(ERROR, (errcode(ERRCODE_INTERNAL_ERROR), errmsg("%s", cloudsync_errmsg(data))));
662+
}
663+
PG_RETURN_BOOL(true);
637664
}
638665

639666
// MARK: - Payload Functions -
@@ -731,31 +758,33 @@ Datum cloudsync_payload_decode (PG_FUNCTION_ARGS) {
731758

732759
const char *payload = VARDATA(payload_data);
733760
cloudsync_context *data = get_cloudsync_context();
761+
int rc = DBRES_OK;
762+
int nrows = 0;
763+
bool spi_connected = false;
734764

735765
int spi_rc = SPI_connect();
736766
if (spi_rc != SPI_OK_CONNECT) {
737767
ereport(ERROR, (errcode(ERRCODE_INTERNAL_ERROR), errmsg("SPI_connect failed: %d", spi_rc)));
738768
}
769+
spi_connected = true;
739770

740771
PG_TRY();
741772
{
742773
cloudsync_pg_ensure_initialized(data, true);
743-
int nrows = 0;
744-
int rc = cloudsync_payload_apply(data, payload, blen, &nrows);
745-
SPI_finish();
746-
747-
if (rc != DBRES_OK) {
748-
ereport(ERROR, (errcode(ERRCODE_INTERNAL_ERROR), errmsg("%s", cloudsync_errmsg(data))));
749-
}
750-
751-
PG_RETURN_INT32(nrows);
774+
rc = cloudsync_payload_apply(data, payload, blen, &nrows);
752775
}
753776
PG_CATCH();
754777
{
755-
SPI_finish();
778+
if (spi_connected) SPI_finish();
756779
PG_RE_THROW();
757780
}
758781
PG_END_TRY();
782+
783+
if (spi_connected) SPI_finish();
784+
if (rc != DBRES_OK) {
785+
ereport(ERROR, (errcode(ERRCODE_INTERNAL_ERROR), errmsg("%s", cloudsync_errmsg(data))));
786+
}
787+
PG_RETURN_INT32(nrows);
759788
}
760789

761790
// Alias for payload_decode

0 commit comments

Comments
 (0)