diff --git a/scripts-available/CDB_FederatedServerTables.sql b/scripts-available/CDB_FederatedServerTables.sql index 39b0f2c..302b3bd 100644 --- a/scripts-available/CDB_FederatedServerTables.sql +++ b/scripts-available/CDB_FederatedServerTables.sql @@ -59,54 +59,62 @@ $$ LANGUAGE SQL STABLE PARALLEL UNSAFE; -- -- Returns the id column from a view definition +-- Note: The id is always of one of this forms: +-- SELECT t.cartodb_id, +-- SELECT t.my_id as cartodb_id, -- CREATE OR REPLACE FUNCTION @extschema@.__CDB_FS_Get_View_id_column(view_def TEXT) RETURNS TEXT AS $$ WITH column_definitions AS ( - SELECT regexp_split_to_array(regexp_split_to_table(view_def, '\n'), ' ') AS col_def + SELECT regexp_split_to_array(trim(leading from regexp_split_to_table(view_def, '\n')), ' ') AS col_def ) - SELECT split_part(col_def[array_length(col_def, 1) - 2], '.', 2) - FROM column_definitions where col_def[array_length(col_def, 1)] = 'cartodb_id,' + SELECT trim(trailing ',' FROM split_part(col_def[2], '.', 2)) + FROM column_definitions + WHERE trim(trailing ',' FROM col_def[array_length(col_def, 1)]) IN ('t.cartodb_id', 'cartodb_id') LIMIT 1; $$ LANGUAGE SQL IMMUTABLE PARALLEL SAFE; -- -- Returns the geom column from a view definition -- +-- Note: The the_geom is always of one of this forms: +-- t.the_geom, +-- t.my_geom as the_geom, +-- CREATE OR REPLACE FUNCTION @extschema@.__CDB_FS_Get_View_geom_column(view_def TEXT) RETURNS TEXT AS $$ WITH column_definitions AS ( - SELECT regexp_split_to_array(regexp_split_to_table(view_def, '\n'), ' ') AS col_def + SELECT regexp_split_to_array(trim(leading from regexp_split_to_table(view_def, '\n')), ' ') AS col_def ) - SELECT trim(trailing ',' FROM split_part( - CASE WHEN col_def[array_length(col_def, 1) - 2] = '4326)' THEN col_def[array_length(col_def, 1) - 3] - ELSE col_def[array_length(col_def, 1) - 2] - END, '.', 2)) + SELECT trim(trailing ',' FROM split_part(col_def[1], '.', 2)) FROM column_definitions - WHERE col_def[array_length(col_def, 1)] IN ('the_geom,', 'the_geom') + WHERE trim(trailing ',' FROM col_def[array_length(col_def, 1)]) IN ('t.the_geom', 'the_geom') LIMIT 1; $$ LANGUAGE SQL IMMUTABLE PARALLEL SAFE; -- -- Returns the webmercatorcolumn from a view definition +-- Note: The the_geom_webmercator is always of one of this forms: +-- t.the_geom_webmercator, +-- t.my_geom as the_geom_webmercator, +-- Or without the trailing comma: +-- t.the_geom_webmercator +-- t.my_geom as the_geom_webmercator -- CREATE OR REPLACE FUNCTION @extschema@.__CDB_FS_Get_View_webmercator_column(view_def TEXT) RETURNS TEXT AS $$ WITH column_definitions AS ( - SELECT regexp_split_to_array(regexp_split_to_table(view_def, '\n'), ' ') AS col_def + SELECT regexp_split_to_array(trim(leading from regexp_split_to_table(view_def, '\n')), ' ') AS col_def ) - SELECT trim(trailing ',' FROM split_part( - CASE WHEN col_def[array_length(col_def, 1) - 2] = '3857)' THEN col_def[array_length(col_def, 1) - 3] - ELSE col_def[array_length(col_def, 1) - 2] - END, '.', 2)) + SELECT trim(trailing ',' FROM split_part(col_def[1], '.', 2)) FROM column_definitions - WHERE col_def[array_length(col_def, 1)] IN ('the_geom_webmercator,', 'the_geom_webmercator') + WHERE trim(trailing ',' FROM col_def[array_length(col_def, 1)]) IN ('t.the_geom_webmercator', 'the_geom_webmercator') LIMIT 1; $$ LANGUAGE SQL IMMUTABLE PARALLEL SAFE; diff --git a/test/CDB_FederatedServerTables.sql b/test/CDB_FederatedServerTables.sql index 5941553..0982398 100644 --- a/test/CDB_FederatedServerTables.sql +++ b/test/CDB_FederatedServerTables.sql @@ -45,7 +45,7 @@ CREATE TABLE remote_schema.remote_geom(id int, another_field text, geom geometry INSERT INTO remote_schema.remote_geom VALUES (1, 'patata', 'SRID=4326;POINT(1 1)'::geometry); INSERT INTO remote_schema.remote_geom VALUES (2, 'patata2', 'SRID=4326;POINT(2 2)'::geometry); -CREATE TABLE remote_schema.remote_geom2(id bigint, another_field text, geom geometry(Geometry,4326), geom_mercator geometry(Geometry,3857)); +CREATE TABLE remote_schema.remote_geom2(cartodb_id bigint, another_field text, the_geom geometry(Geometry,4326), the_geom_webmercator geometry(Geometry,3857)); INSERT INTO remote_schema.remote_geom2 VALUES (3, 'patata', 'SRID=4326;POINT(3 3)'::geometry, 'SRID=3857;POINT(3 3)'); @@ -84,9 +84,9 @@ SELECT 'R2', cartodb.CDB_Federated_Table_Register( server => 'loopback', remote_schema => 'remote_schema', remote_table => 'remote_geom2', - id_column => 'id', - geom_column => 'geom', - webmercator_column => 'geom_mercator', + id_column => 'cartodb_id', + geom_column => 'the_geom', + webmercator_column => 'the_geom_webmercator', local_name => 'myFullTable' ); @@ -101,10 +101,10 @@ SELECT 'R3', cartodb.CDB_Federated_Table_Register( server => 'loopback', remote_schema => 'remote_schema', remote_table => 'remote_geom2', - id_column => 'id', + id_column => 'cartodb_id', -- Switch geom and geom_column on purpose to force ST_Transform to be used - geom_column => 'geom_mercator', - webmercator_column => 'geom', + geom_column => 'the_geom_webmercator', + webmercator_column => 'the_geom', local_name => 'different_name' ); diff --git a/test/CDB_FederatedServerTables_expect b/test/CDB_FederatedServerTables_expect index df646d8..6e02023 100644 --- a/test/CDB_FederatedServerTables_expect +++ b/test/CDB_FederatedServerTables_expect @@ -4,14 +4,14 @@ R1| S1|1|POINT(1 1)|patata S1|2|POINT(2 2)|patata2 t|remote_geom|cdb_fs_loopback.remote_geom|id|geom|geom|[{"Name" : "another_field", "Type" : "text"}, {"Name" : "geom", "Type" : "GEOMETRY,4326"}, {"Name" : "id", "Type" : "integer"}] -f|remote_geom2|||||[{"Name" : "another_field", "Type" : "text"}, {"Name" : "geom", "Type" : "GEOMETRY,4326"}, {"Name" : "geom_mercator", "Type" : "GEOMETRY,3857"}, {"Name" : "id", "Type" : "bigint"}] +f|remote_geom2|||||[{"Name" : "another_field", "Type" : "text"}, {"Name" : "cartodb_id", "Type" : "bigint"}, {"Name" : "the_geom", "Type" : "GEOMETRY,4326"}, {"Name" : "the_geom_webmercator", "Type" : "GEOMETRY,3857"}] f|remote_geom3|||||[{"Name" : "geom", "Type" : "GEOMETRY,4326"}, {"Name" : "geom_mercator", "Type" : "GEOMETRY,3857"}, {"Name" : "id", "Type" : "bigint"}] f|remote_other|||||[{"Name" : "field", "Type" : "text"}, {"Name" : "field2", "Type" : "text"}, {"Name" : "id", "Type" : "bigint"}] ## Registering another existing table works R2| S2|3|POINT(3 3)|patata t|remote_geom|cdb_fs_loopback.remote_geom|id|geom|geom|[{"Name" : "another_field", "Type" : "text"}, {"Name" : "geom", "Type" : "GEOMETRY,4326"}, {"Name" : "id", "Type" : "integer"}] -t|remote_geom2|cdb_fs_loopback."myFullTable"|id|geom|geom_mercator|[{"Name" : "another_field", "Type" : "text"}, {"Name" : "geom", "Type" : "GEOMETRY,4326"}, {"Name" : "geom_mercator", "Type" : "GEOMETRY,3857"}, {"Name" : "id", "Type" : "bigint"}] +t|remote_geom2|cdb_fs_loopback."myFullTable"|cartodb_id|the_geom|the_geom_webmercator|[{"Name" : "another_field", "Type" : "text"}, {"Name" : "cartodb_id", "Type" : "bigint"}, {"Name" : "the_geom", "Type" : "GEOMETRY,4326"}, {"Name" : "the_geom_webmercator", "Type" : "GEOMETRY,3857"}] f|remote_geom3|||||[{"Name" : "geom", "Type" : "GEOMETRY,4326"}, {"Name" : "geom_mercator", "Type" : "GEOMETRY,3857"}, {"Name" : "id", "Type" : "bigint"}] f|remote_other|||||[{"Name" : "field", "Type" : "text"}, {"Name" : "field2", "Type" : "text"}, {"Name" : "id", "Type" : "bigint"}] ## Re-registering a table works @@ -22,7 +22,7 @@ S3_new|3|patata U1| ERROR: relation "remote_geom" does not exist at character 71 f|remote_geom|||||[{"Name" : "another_field", "Type" : "text"}, {"Name" : "geom", "Type" : "GEOMETRY,4326"}, {"Name" : "id", "Type" : "integer"}] -t|remote_geom2|cdb_fs_loopback.different_name|id|geom_mercator|geom|[{"Name" : "another_field", "Type" : "text"}, {"Name" : "geom", "Type" : "GEOMETRY,4326"}, {"Name" : "geom_mercator", "Type" : "GEOMETRY,3857"}, {"Name" : "id", "Type" : "bigint"}] +t|remote_geom2|cdb_fs_loopback.different_name|cartodb_id|the_geom_webmercator|the_geom|[{"Name" : "another_field", "Type" : "text"}, {"Name" : "cartodb_id", "Type" : "bigint"}, {"Name" : "the_geom", "Type" : "GEOMETRY,4326"}, {"Name" : "the_geom_webmercator", "Type" : "GEOMETRY,3857"}] f|remote_geom3|||||[{"Name" : "geom", "Type" : "GEOMETRY,4326"}, {"Name" : "geom_mercator", "Type" : "GEOMETRY,3857"}, {"Name" : "id", "Type" : "bigint"}] f|remote_other|||||[{"Name" : "field", "Type" : "text"}, {"Name" : "field2", "Type" : "text"}, {"Name" : "id", "Type" : "bigint"}] ## Registering a table: Invalid server fails @@ -79,7 +79,7 @@ You are now connected to database "contrib_regression" as user "cdb_fs_tester". ## Listing remote tables works with granted permissions t|remote_geom|cdb_fs_loopback.localtable|id|geom|geom|[{"Name" : "another_field", "Type" : "text"}, {"Name" : "geom", "Type" : "GEOMETRY,4326"}, {"Name" : "id", "Type" : "integer"}] -t|remote_geom2|cdb_fs_loopback.different_name|id|geom_mercator|geom|[{"Name" : "another_field", "Type" : "text"}, {"Name" : "geom", "Type" : "GEOMETRY,4326"}, {"Name" : "geom_mercator", "Type" : "GEOMETRY,3857"}, {"Name" : "id", "Type" : "bigint"}] +t|remote_geom2|cdb_fs_loopback.different_name|cartodb_id|the_geom_webmercator|the_geom|[{"Name" : "another_field", "Type" : "text"}, {"Name" : "cartodb_id", "Type" : "bigint"}, {"Name" : "the_geom", "Type" : "GEOMETRY,4326"}, {"Name" : "the_geom_webmercator", "Type" : "GEOMETRY,3857"}] f|remote_geom3|||||[{"Name" : "geom", "Type" : "GEOMETRY,4326"}, {"Name" : "geom_mercator", "Type" : "GEOMETRY,3857"}, {"Name" : "id", "Type" : "bigint"}] f|remote_other|||||[{"Name" : "field", "Type" : "text"}, {"Name" : "field2", "Type" : "text"}, {"Name" : "id", "Type" : "bigint"}] ## Selecting from a registered table with granted permissions works @@ -99,7 +99,7 @@ You are now connected to database "contrib_regression" as user "postgres". You are now connected to database "contrib_regression" as user "cdb_fs_tester2". t|remote_geom|cdb_fs_loopback.localtable|id|geom|geom|[{"Name" : "another_field", "Type" : "text"}, {"Name" : "geom", "Type" : "GEOMETRY,4326"}, {"Name" : "id", "Type" : "integer"}] -t|remote_geom2|cdb_fs_loopback.different_name|id|geom_mercator|geom|[{"Name" : "another_field", "Type" : "text"}, {"Name" : "geom", "Type" : "GEOMETRY,4326"}, {"Name" : "geom_mercator", "Type" : "GEOMETRY,3857"}, {"Name" : "id", "Type" : "bigint"}] +t|remote_geom2|cdb_fs_loopback.different_name|cartodb_id|the_geom_webmercator|the_geom|[{"Name" : "another_field", "Type" : "text"}, {"Name" : "cartodb_id", "Type" : "bigint"}, {"Name" : "the_geom", "Type" : "GEOMETRY,4326"}, {"Name" : "the_geom_webmercator", "Type" : "GEOMETRY,3857"}] f|remote_geom3|||||[{"Name" : "geom", "Type" : "GEOMETRY,4326"}, {"Name" : "geom_mercator", "Type" : "GEOMETRY,3857"}, {"Name" : "id", "Type" : "bigint"}] f|remote_other|||||[{"Name" : "field", "Type" : "text"}, {"Name" : "field2", "Type" : "text"}, {"Name" : "id", "Type" : "bigint"}] 1|POINT(1 1) @@ -108,7 +108,7 @@ f|remote_other|||||[{"Name" : "field", "Type" : "text"}, {"Name" : "field2", "Ty NOTICE: drop cascades to view cdb_fs_loopback.localtable f|remote_geom|||||[{"Name" : "another_field", "Type" : "text"}, {"Name" : "geom", "Type" : "GEOMETRY,4326"}, {"Name" : "id", "Type" : "integer"}] -t|remote_geom2|cdb_fs_loopback.different_name|id|geom_mercator|geom|[{"Name" : "another_field", "Type" : "text"}, {"Name" : "geom", "Type" : "GEOMETRY,4326"}, {"Name" : "geom_mercator", "Type" : "GEOMETRY,3857"}, {"Name" : "id", "Type" : "bigint"}] +t|remote_geom2|cdb_fs_loopback.different_name|cartodb_id|the_geom_webmercator|the_geom|[{"Name" : "another_field", "Type" : "text"}, {"Name" : "cartodb_id", "Type" : "bigint"}, {"Name" : "the_geom", "Type" : "GEOMETRY,4326"}, {"Name" : "the_geom_webmercator", "Type" : "GEOMETRY,3857"}] f|remote_geom3|||||[{"Name" : "geom", "Type" : "GEOMETRY,4326"}, {"Name" : "geom_mercator", "Type" : "GEOMETRY,3857"}, {"Name" : "id", "Type" : "bigint"}] f|remote_other|||||[{"Name" : "field", "Type" : "text"}, {"Name" : "field2", "Type" : "text"}, {"Name" : "id", "Type" : "bigint"}] ## Only the owner can revoke permissions over the server