Thanks Adrian!  Changing the declaration row_data to be of type RECORD
(rather than pg_catalog.pg_class%ROWTYPE) resolved the error :)

- Will

*Will J Dunn*
*willjdunn.com <http://willjdunn.com/>*

On Thu, Apr 16, 2015 at 4:36 PM, Adrian Klaver <adrian.kla...@aklaver.com>
wrote:

> On 04/16/2015 07:52 AM, William Dunn wrote:
>
>> Hello list,
>>
>> I am creating a plpgsql procedure in Postgres 9.4 (also testing in
>> 9.3.6) to move all of the tables that are not in a default tablespace
>> (pg_default, pg_global, or 0) into the tablespace pg_default. However
>> when it executes I get an error 'ERROR:  invalid input syntax for type
>> oid:' which I do not know how to resolve..
>>
>> The procedure executes the following select query, which returns the
>> /relname
>> <http://www.postgresql.org/docs/devel/static/catalog-pg-class.html>
>> /(tablename, type /name/) and /nspname
>> <http://www.postgresql.org/docs/devel/static/catalog-pg-namespace.html>
>> /(schema name, type /name/) of each table that are not in the default
>> tablespaces, into a variable called /row_data/ (of type
>>
>> pg_catalog.pg_class%ROWTYPE):
>>
>>     SELECT pg_class.relname, pg_namespace.nspname
>>     FROM pg_class INNER JOIN pg_namespace ON
>> pg_class.relnamespace=pg_namespace.oid
>>     WHERE pg_class.reltablespace<>(SELECT oid FROM pg_tablespace WHERE
>> spcname='pg_default')
>>     AND pg_class.reltablespace<>(SELECT oid FROM pg_tablespace WHERE
>> spcname='pg_global')
>>     AND pg_class.reltablespace<>0
>>     AND pg_class.relkind='r'
>>     ORDER BY pg_class.relname;
>>
>> Using the example database EDBSTORE (example database provided by
>> Enterprise DB) the query returned the table 'inventory' which was in
>> schema 'edbstore' (which I had stored on tablespace 'edbstore', not
>> pg_default):
>>    relname  | nspname
>> -----------+----------
>>   inventory | edbstore
>> (1 row)
>>
>>
>> The procedure loops through each returned row and executes an ALTER
>> TABLE command to move them to the tablespace pg_default:
>> EXECUTE 'ALTER TABLE '|| row_data.nspname || '.' || row_data.relname ||'
>> SET TABLESPACE pg_default';
>>
>> (so in the above edbstore example it should execute "ALTER TABLE
>> edbstore.inventory SET TABLESPACE pg_default;")
>>
>> However, when I run the procedure it is returning the following error:
>>     ERROR:  invalid input syntax for type oid: "edbstore"
>>     CONTEXT:  PL/pgSQL function move_table_tablespaces_to_pg_default()
>> line 18 at FOR over SELECT rows
>>
>> Does anyone understand this error?
>>
>
> pg_class has a hidden field oid:
>
> http://www.postgresql.org/docs/9.3/interactive/catalog-pg-class.html
>
> When you are doing:
>
> row_data pg_catalog.pg_class%ROWTYPE;
>
> that is saying you want the whole row type for pg_class:
>
>
> http://www.postgresql.org/docs/9.3/interactive/plpgsql-declarations.html#PLPGSQL-DECLARATION-ROWTYPES
>
> You are not supplying the oid or the columns other then relname and
> nspname so the error is expected.
>
> If it where me I would use a RECORD type:
>
>
> http://www.postgresql.org/docs/9.3/interactive/plpgsql-declarations.html#PLPGSQL-DECLARATION-RECORDS
>
> It will adapt to the columns actually returned.
>
>
>> The full plpgsql function is as follows:
>> ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
>> CREATE FUNCTION move_table_tablespaces_to_pg_default () RETURNS INTEGER
>> AS $$
>> -- Loops through the tables not in the tablespace pg_default, pg_global,
>> or the default tablespace and moves them to the pg_default tablespace
>> -- Returns the number of tables that were moved
>>
>>     DECLARE
>>
>>        -- Declare a variable to hold the counter of tables moved
>>        objects_affected INTEGER = 0;
>>
>>        -- Declare a variable to hold rows from the pg_class table
>>        row_data pg_catalog.pg_class%ROWTYPE;
>>
>>     BEGIN
>>
>>        -- Iterate through the results of a query which lists all of the
>> tables not in the tablespace pg_default, pg_global, or the default
>> tablespace
>>        FOR row_data IN (SELECT pg_class.relname, pg_namespace.nspname
>> FROM pg_class INNER JOIN pg_namespace ON
>> pg_class.relnamespace=pg_namespace.oid
>>
>> WHERE pg_class.reltablespace<>(SELECT oid FROM pg_tablespace WHERE
>> spcname='pg_default') AND pg_class.reltablespace<>(SELECT oid FROM
>> pg_tablespace WHERE
>>
>> spcname='pg_global') AND pg_class.reltablespace<>0 AND
>> pg_class.relkind='r' ORDER BY pg_class.relname)  LOOP
>>
>>           -- execute ALTER TABLE statement on that table to move it to
>> tablespace pg_default
>>           EXECUTE 'ALTER TABLE '|| row_data.nspname || '.' ||
>> row_data.relname ||' SET TABLESPACE pg_default';
>>
>>           -- increment count of tables moved
>>           objects_affected := objects_affected + 1;
>>        END LOOP;
>>
>>        -- Return count of tables moved
>>        -- RETURN objects_affected;
>>     END;
>> $$ LANGUAGE 'plpgsql';
>>
>> Thanks!!
>> Will
>>
>> *Will J Dunn*
>> *willjdunn.com <http://willjdunn.com>*
>>
>
>
> --
> Adrian Klaver
> adrian.kla...@aklaver.com
>

Reply via email to