From 2f8ea7e4ea675702d017c081f5131bb16b2c03b8 Mon Sep 17 00:00:00 2001 From: Rafa de la Torre Date: Tue, 28 May 2019 15:39:02 +0200 Subject: [PATCH] Avoid tables name clashing when executing within same transaction Generate more unique temp table names when the CDB_SyncTable function is executed multiple times within the same transaction. When executed in isolation, there will be always an implicit surrounding transaction. But when executed several times within the same transaction it can give an `ERROR: relation "src_sync_718794" already exists`. E.g: ``` BEGIN; SELECT cartodb.CDB_SyncTable('source1', 'public', 'dest1'); SELECT cartodb.CDB_SyncTable('source12, 'public', 'dest2'); COMMIT; ``` --- scripts-available/CDB_SyncTable.sql | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/scripts-available/CDB_SyncTable.sql b/scripts-available/CDB_SyncTable.sql index 9c407a2..f56e71d 100644 --- a/scripts-available/CDB_SyncTable.sql +++ b/scripts-available/CDB_SyncTable.sql @@ -52,6 +52,22 @@ BEGIN END; $$ LANGUAGE plpgsql IMMUTABLE PARALLEL SAFE; + +/* + Given a prefix, generate a safe unique NAME for a temp table. + + Example of usage: + + SELECT __CDB_GenerateUniqueName('src_sync'); --> src_sync_718794_120106 + +*/ +CREATE OR REPLACE FUNCTION __CDB_GenerateUniqueName(prefix TEXT) +RETURNS NAME +AS $$ + SELECT format('%s_%s_%s', prefix, txid_current(), (random()*1000000)::int)::NAME; +$$ LANGUAGE sql VOLATILE PARALLEL UNSAFE; + + /* A Table Syncer @@ -94,8 +110,8 @@ BEGIN SELECT ARRAY(SELECT quote_ident(c) FROM _CDB_GetColumns(src_table) as c WHERE c <> 'cartodb_id') INTO colnames; quoted_colnames := array_to_string(colnames, ','); - src_hash_table_name := format('src_sync_%s', txid_current()); - dst_hash_table_name := format('dst_sync_%s', txid_current()); + src_hash_table_name := __CDB_GenerateUniqueName('src_sync'); + dst_hash_table_name := __CDB_GenerateUniqueName('dst_sync'); EXECUTE format('CREATE TEMP TABLE %I(cartodb_id BIGINT, hash TEXT) ON COMMIT DROP', src_hash_table_name); EXECUTE format('CREATE TEMP TABLE %I(cartodb_id BIGINT, hash TEXT) ON COMMIT DROP', dst_hash_table_name);