From 0d5f83b3c4db309e41863442416899b1dbe0903c Mon Sep 17 00:00:00 2001 From: Carla Iriberri Date: Tue, 1 Mar 2016 19:17:45 +0100 Subject: [PATCH] Rewriting function --- scripts-available/CDB_CartodbfyTable.sql | 58 +++++++++++++++++------- 1 file changed, 42 insertions(+), 16 deletions(-) diff --git a/scripts-available/CDB_CartodbfyTable.sql b/scripts-available/CDB_CartodbfyTable.sql index 3da1cf5..2e82e73 100644 --- a/scripts-available/CDB_CartodbfyTable.sql +++ b/scripts-available/CDB_CartodbfyTable.sql @@ -466,19 +466,33 @@ END; $$ LANGUAGE 'plpgsql'; + +DO $$ +BEGIN + IF NOT EXISTS (SELECT 1 FROM pg_type WHERE typname = '_cdb_has_usable_primary_id_record') THEN + CREATE TYPE _cdb_has_usable_primary_id_record + AS (has_usable_primary_key boolean, + text_key_column boolean); + END IF; +END$$; + -- Find out if the table already has a usable primary key -- If the table has both a usable key and usable geometry -- we can no-op on the table copy and just ensure that the -- indexes and triggers are in place -CREATE OR REPLACE FUNCTION _CDB_Has_Usable_Primary_ID(reloid REGCLASS) - RETURNS BOOLEAN +CREATE OR REPLACE FUNCTION cartodb._CDB_Has_Usable_Primary_ID(reloid REGCLASS) + RETURNS _cdb_has_usable_primary_id_record AS $$ DECLARE rec RECORD; const RECORD; + idc RECORD; i INTEGER; sql TEXT; useable_key BOOLEAN = false; + has_usable_primary_key BOOLEAN = false; + -- In case cartodb_id is a text column + text_key_column BOOLEAN = false; BEGIN RAISE DEBUG 'CDB(_CDB_Has_Usable_Primary_ID): %', 'entered function'; @@ -506,7 +520,8 @@ BEGIN -- And it's a unique primary key! Done! IF (rec.indisprimary OR rec.indisunique) AND rec.attnotnull THEN RAISE DEBUG 'CDB(_CDB_Has_Usable_Primary_ID): %', Format('found good ''%s''', const.pkey); - RETURN true; + SELECT true as has_usable_primary_key, text_key_column INTO idc; + RETURN idc; -- Check and see if the column values are unique and not null, -- if they are, we can use this column... @@ -520,9 +535,10 @@ BEGIN RAISE DEBUG 'CDB(_CDB_Has_Usable_Primary_ID): Found text column %', rec.atttypid; BEGIN - sql := Format('ALTER TABLE %s ALTER cartodb_id TYPE int USING %I::integer', reloid::text, rec.attname); + sql := Format('SELECT %I::integer FROM %s', rec.attname, reloid::text); RAISE DEBUG 'CDB(_CDB_Has_Usable_Primary_ID): Running %', sql; EXECUTE sql; + text_key_column := true EXCEPTION WHEN invalid_text_representation THEN RAISE DEBUG 'CDB(_CDB_Has_Usable_Primary_ID): Column % of type text is not a valid integer column', rec.attname; @@ -571,7 +587,8 @@ BEGIN END IF; - return useable_key; + SELECT useable_key as has_usable_primary_key, text_key_column INTO idc; + RETURN idc; END IF; @@ -604,7 +621,8 @@ BEGIN -- Yes! Ok, rename it. IF FOUND THEN PERFORM _CDB_SQL(Format('ALTER TABLE %s RENAME COLUMN %s TO %s', reloid::text, rec.attname, const.pkey),'_CDB_Has_Usable_Primary_ID'); - RETURN true; + SELECT true as has_usable_primary_key, text_key_column INTO idc; + RETURN idc; ELSE RAISE DEBUG 'CDB(_CDB_Has_Usable_Primary_ID): %', Format('found no useful column for ''%s''', const.pkey); @@ -615,8 +633,8 @@ BEGIN RAISE DEBUG 'CDB(_CDB_Has_Usable_Primary_ID): %', 'function complete'; -- Didn't find re-usable key, so return FALSE - RETURN false; - + SELECT false as has_usable_primary_key, text_key_column INTO idc; + RETURN idc; END; $$ LANGUAGE 'plpgsql'; @@ -819,7 +837,7 @@ $$ LANGUAGE 'plpgsql'; -- a "good" one, and the same for the geometry columns. If all the required -- columns are in place already, it no-ops and just renames the table to -- the destination if necessary. -CREATE OR REPLACE FUNCTION _CDB_Rewrite_Table(reloid REGCLASS, destschema TEXT DEFAULT NULL) +CREATE OR REPLACE FUNCTION cartodb._CDB_Rewrite_Table(reloid REGCLASS, destschema TEXT DEFAULT NULL) RETURNS BOOLEAN AS $$ DECLARE @@ -840,13 +858,13 @@ DECLARE rec RECORD; const RECORD; + idc RECORD; gc RECORD; sql TEXT; str TEXT; table_srid INTEGER; geom_srid INTEGER; - has_usable_primary_key BOOLEAN; has_usable_pk_sequence BOOLEAN; BEGIN @@ -870,15 +888,16 @@ BEGIN -- See if there is a primary key column we need to carry along to the -- new table. If this is true, it implies there is an indexed -- primary key of integer type named (by default) cartodb_id - SELECT _CDB_Has_Usable_Primary_ID(reloid) - INTO STRICT has_usable_primary_key; + SELECT has_usable_primary_key, text_key_column + FROM _CDB_Has_Usable_Primary_ID(reloid) + INTO STRICT idc; - RAISE DEBUG 'CDB(_CDB_Rewrite_Table): has_usable_primary_key %', has_usable_primary_key; + RAISE DEBUG 'CDB(_CDB_Rewrite_Table): has_usable_primary_key %', idc.has_usable_primary_key; -- See if the candidate primary key column has a sequence for default -- values. No usable pk implies has_usable_pk_sequence = false. has_usable_pk_sequence := false; - IF has_usable_primary_key THEN + IF idc.has_usable_primary_key THEN SELECT _CDB_Has_Usable_PK_Sequence(reloid) INTO STRICT has_usable_pk_sequence; END IF; @@ -913,9 +932,16 @@ BEGIN -- We can only avoid a rewrite if both the key and -- geometry are usable + -- If cartodb_id column is of type text, cast it + IF idc.text_key_column THEN + sql := Format('ALTER TABLE %s ALTER cartodb_id TYPE int USING %I::integer', reloid::text, 'cartodb_id'); + PERFORM _CDB_SQL(sql,'_CDB_Rewrite_Table'); + END IF; + + RAISE DEBUG 'idc %', idc; -- No table re-write is required, BUT a rename is required to -- a destination schema, so do that now - IF has_usable_primary_key AND has_usable_pk_sequence AND gc.has_usable_geoms THEN + IF idc.has_usable_primary_key AND has_usable_pk_sequence AND gc.has_usable_geoms THEN IF destschema != relschema THEN RAISE DEBUG 'CDB(_CDB_Rewrite_Table): perfect table needs to be moved to schema (%)', destschema; @@ -953,7 +979,7 @@ BEGIN sql := Format('CREATE TABLE %s AS SELECT ', copyname); -- Add cartodb ID! - IF has_usable_primary_key THEN + IF idc.has_usable_primary_key THEN sql := sql || const.pkey; ELSE sql := sql || 'nextval(''' || destseq || ''') AS ' || const.pkey;