@@ -62,42 +62,47 @@ static cloudsync_context *get_cloudsync_context(void) {
6262
6363// MARK: - Extension Entry Points -
6464
65- void _PG_init (void ) {
66- // Extension initialization
67- // SPI will be connected per-function call
68- elog (DEBUG1 , "CloudSync extension loading" );
69-
70- // Initialize memory debugger (NOOP in production)
71- cloudsync_memory_init (1 );
72-
73- // load config, if exists
74- cloudsync_context * data = get_cloudsync_context ();
75-
76- int spi_rc = SPI_connect ();
77- if (spi_rc != SPI_OK_CONNECT ) {
78- ereport (ERROR , (errcode (ERRCODE_INTERNAL_ERROR ), errmsg ("SPI_connect failed: %d" , spi_rc )));
65+ static void cloudsync_pg_ensure_initialized (cloudsync_context * data , bool spi_connected ) {
66+ if (!data ) return ;
67+ if (data -> site_id [0 ] != 0 ) return ;
68+
69+ if (!spi_connected ) {
70+ int spi_rc = SPI_connect ();
71+ if (spi_rc != SPI_OK_CONNECT ) {
72+ ereport (ERROR , (errcode (ERRCODE_INTERNAL_ERROR ), errmsg ("SPI_connect failed: %d" , spi_rc )));
73+ }
7974 }
80-
75+
8176 PG_TRY ();
8277 {
8378 if (cloudsync_config_exists (data )) {
8479 if (cloudsync_context_init (data ) == NULL ) {
8580 ereport (ERROR , (errcode (ERRCODE_INTERNAL_ERROR ), errmsg ("An error occurred while trying to initialize context" )));
8681 }
87-
82+
8883 // make sure to update internal version to current version
8984 dbutils_settings_set_key_value (data , CLOUDSYNC_KEY_LIBVERSION , CLOUDSYNC_VERSION );
9085 }
91- SPI_finish ();
86+
87+ if (!spi_connected ) SPI_finish ();
9288 }
9389 PG_CATCH ();
9490 {
95- SPI_finish ();
91+ if (! spi_connected ) SPI_finish ();
9692 PG_RE_THROW ();
9793 }
9894 PG_END_TRY ();
9995}
10096
97+ void _PG_init (void ) {
98+ // Extension initialization
99+ // SPI will be connected per-function call
100+ elog (DEBUG1 , "CloudSync extension loading" );
101+
102+ // Initialize memory debugger (NOOP in production)
103+ cloudsync_memory_init (1 );
104+ }
105+
101106void _PG_fini (void ) {
102107 // Extension cleanup
103108 elog (DEBUG1 , "CloudSync extension unloading" );
@@ -124,6 +129,7 @@ Datum pg_cloudsync_siteid (PG_FUNCTION_ARGS) {
124129 UNUSED_PARAMETER (fcinfo );
125130
126131 cloudsync_context * data = get_cloudsync_context ();
132+ cloudsync_pg_ensure_initialized (data , false);
127133 const void * siteid = cloudsync_siteid (data );
128134
129135 if (!siteid ) {
@@ -169,6 +175,7 @@ Datum cloudsync_db_version (PG_FUNCTION_ARGS) {
169175
170176 PG_TRY ();
171177 {
178+ cloudsync_pg_ensure_initialized (data , true);
172179 int rc = cloudsync_dbversion_check_uptodate (data );
173180 if (rc != DBRES_OK ) {
174181 ereport (ERROR , (errcode (ERRCODE_INTERNAL_ERROR ), errmsg ("Unable to retrieve db_version (%s)" , database_errmsg (data ))));
@@ -205,6 +212,7 @@ Datum cloudsync_db_version_next (PG_FUNCTION_ARGS) {
205212
206213 PG_TRY ();
207214 {
215+ cloudsync_pg_ensure_initialized (data , true);
208216 int64_t next_version = cloudsync_dbversion_next (data , merging_version );
209217 SPI_finish ();
210218
@@ -233,6 +241,7 @@ static bytea *cloudsync_init_internal (cloudsync_context *data, const char *tabl
233241
234242 PG_TRY ();
235243 {
244+ cloudsync_pg_ensure_initialized (data , true);
236245 // Begin savepoint for transactional init
237246 int rc = database_begin_savepoint (data , "cloudsync_init" );
238247 if (rc != DBRES_OK ) {
@@ -258,11 +267,10 @@ static bytea *cloudsync_init_internal (cloudsync_context *data, const char *tabl
258267
259268 cloudsync_update_schema_hash (data );
260269
261- // Build site_id as TEXT to return
262- char buffer [UUID_STR_MAXLEN ];
263- cloudsync_uuid_v7_stringify (cloudsync_siteid (data ), buffer , false);
264- result = cstring_to_text (buffer );
265- ereport (DEBUG1 , (errmsg ("cloudsync_init_internal uuid %s" , buffer )));
270+ // Build site_id as bytea to return
271+ result = (bytea * )palloc (UUID_LEN + VARHDRSZ );
272+ SET_VARSIZE (result , UUID_LEN + VARHDRSZ );
273+ memcpy (VARDATA (result ), cloudsync_siteid (data ), UUID_LEN );
266274
267275 SPI_finish ();
268276 }
@@ -325,6 +333,8 @@ Datum cloudsync_enable (PG_FUNCTION_ARGS) {
325333 }
326334
327335 const char * table = text_to_cstring (PG_GETARG_TEXT_PP (0 ));
336+ cloudsync_context * data = get_cloudsync_context ();
337+ cloudsync_pg_ensure_initialized (data , false);
328338 cloudsync_enable_disable (table , true);
329339 PG_RETURN_BOOL (true);
330340}
@@ -337,6 +347,8 @@ Datum cloudsync_disable (PG_FUNCTION_ARGS) {
337347 }
338348
339349 const char * table = text_to_cstring (PG_GETARG_TEXT_PP (0 ));
350+ cloudsync_context * data = get_cloudsync_context ();
351+ cloudsync_pg_ensure_initialized (data , false);
340352 cloudsync_enable_disable (table , false);
341353 PG_RETURN_BOOL (true);
342354}
@@ -349,6 +361,7 @@ Datum cloudsync_is_enabled (PG_FUNCTION_ARGS) {
349361 }
350362
351363 cloudsync_context * data = get_cloudsync_context ();
364+ cloudsync_pg_ensure_initialized (data , false);
352365 const char * table_name = text_to_cstring (PG_GETARG_TEXT_PP (0 ));
353366 cloudsync_table_context * table = table_lookup (data , table_name );
354367
@@ -375,6 +388,7 @@ Datum pg_cloudsync_cleanup (PG_FUNCTION_ARGS) {
375388
376389 PG_TRY ();
377390 {
391+ cloudsync_pg_ensure_initialized (data , true);
378392 int rc = cloudsync_cleanup (data , table );
379393 SPI_finish ();
380394
@@ -406,6 +420,7 @@ Datum pg_cloudsync_terminate (PG_FUNCTION_ARGS) {
406420
407421 PG_TRY ();
408422 {
423+ cloudsync_pg_ensure_initialized (data , true);
409424 int rc = cloudsync_terminate (data );
410425 SPI_finish ();
411426 PG_RETURN_INT32 (rc );
@@ -449,6 +464,7 @@ Datum cloudsync_set (PG_FUNCTION_ARGS) {
449464
450465 PG_TRY ();
451466 {
467+ cloudsync_pg_ensure_initialized (data , true);
452468 dbutils_settings_set_key_value (data , key , value );
453469 SPI_finish ();
454470 PG_RETURN_BOOL (true);
@@ -487,6 +503,7 @@ Datum cloudsync_set_table (PG_FUNCTION_ARGS) {
487503
488504 PG_TRY ();
489505 {
506+ cloudsync_pg_ensure_initialized (data , true);
490507 dbutils_table_settings_set_key_value (data , tbl , "*" , key , value );
491508 SPI_finish ();
492509 PG_RETURN_BOOL (true);
@@ -531,6 +548,7 @@ Datum cloudsync_set_column (PG_FUNCTION_ARGS) {
531548
532549 PG_TRY ();
533550 {
551+ cloudsync_pg_ensure_initialized (data , true);
534552 dbutils_table_settings_set_key_value (data , tbl , col , key , value );
535553 SPI_finish ();
536554 PG_RETURN_BOOL (true);
@@ -562,6 +580,7 @@ Datum pg_cloudsync_begin_alter (PG_FUNCTION_ARGS) {
562580
563581 PG_TRY ();
564582 {
583+ cloudsync_pg_ensure_initialized (data , true);
565584 int rc = cloudsync_begin_alter (data , table_name );
566585 SPI_finish ();
567586
@@ -598,6 +617,7 @@ Datum pg_cloudsync_commit_alter (PG_FUNCTION_ARGS) {
598617
599618 PG_TRY ();
600619 {
620+ cloudsync_pg_ensure_initialized (data , true);
601621 int rc = cloudsync_commit_alter (data , table_name );
602622 SPI_finish ();
603623
@@ -639,6 +659,7 @@ Datum cloudsync_payload_encode_transfn (PG_FUNCTION_ARGS) {
639659
640660 int argc = 0 ;
641661 cloudsync_context * data = get_cloudsync_context ();
662+ cloudsync_pg_ensure_initialized (data , false);
642663 pgvalue_t * * argv = pgvalues_from_args (fcinfo , 1 , & argc );
643664
644665 // Wrap variadic args into pgvalue_t so pk/payload helpers can read types safely.
@@ -667,6 +688,7 @@ Datum cloudsync_payload_encode_finalfn (PG_FUNCTION_ARGS) {
667688
668689 cloudsync_payload_context * payload = (cloudsync_payload_context * )PG_GETARG_POINTER (0 );
669690 cloudsync_context * data = get_cloudsync_context ();
691+ cloudsync_pg_ensure_initialized (data , false);
670692
671693 int rc = cloudsync_payload_encode_final (payload , data );
672694 if (rc != DBRES_OK ) {
@@ -716,6 +738,7 @@ Datum cloudsync_payload_decode (PG_FUNCTION_ARGS) {
716738
717739 PG_TRY ();
718740 {
741+ cloudsync_pg_ensure_initialized (data , true);
719742 int nrows = 0 ;
720743 int rc = cloudsync_payload_apply (data , payload , blen , & nrows );
721744 SPI_finish ();
@@ -777,6 +800,7 @@ static void cloudsync_pg_cleanup(int code, Datum arg) {
777800PG_FUNCTION_INFO_V1 (cloudsync_is_sync );
778801Datum cloudsync_is_sync (PG_FUNCTION_ARGS ) {
779802 cloudsync_context * data = get_cloudsync_context ();
803+ cloudsync_pg_ensure_initialized (data , false);
780804
781805 if (cloudsync_insync (data )) {
782806 PG_RETURN_BOOL (true);
@@ -799,6 +823,7 @@ Datum cloudsync_seq (PG_FUNCTION_ARGS) {
799823 UNUSED_PARAMETER (fcinfo );
800824
801825 cloudsync_context * data = get_cloudsync_context ();
826+ cloudsync_pg_ensure_initialized (data , false);
802827 int seq = cloudsync_bumpseq (data );
803828
804829 PG_RETURN_INT32 (seq );
@@ -930,9 +955,7 @@ Datum cloudsync_insert (PG_FUNCTION_ARGS) {
930955
931956 PG_ENSURE_ERROR_CLEANUP (cloudsync_pg_cleanup , PointerGetDatum (& cleanup ));
932957 {
933- if (cloudsync_context_init (data ) == NULL ) {
934- ereport (ERROR , (errcode (ERRCODE_INTERNAL_ERROR ), errmsg ("Unable to initialize cloudsync context" )));
935- }
958+ cloudsync_pg_ensure_initialized (data , true);
936959
937960 // Lookup table (load from settings if needed)
938961 cloudsync_table_context * table = table_lookup (data , table_name );
@@ -1029,9 +1052,7 @@ Datum cloudsync_delete (PG_FUNCTION_ARGS) {
10291052
10301053 PG_ENSURE_ERROR_CLEANUP (cloudsync_pg_cleanup , PointerGetDatum (& cleanup ));
10311054 {
1032- if (cloudsync_context_init (data ) == NULL ) {
1033- ereport (ERROR , (errcode (ERRCODE_INTERNAL_ERROR ), errmsg ("Unable to initialize cloudsync context" )));
1034- }
1055+ cloudsync_pg_ensure_initialized (data , true);
10351056
10361057 cloudsync_table_context * table = table_lookup (data , table_name );
10371058 if (!table ) {
0 commit comments