Re: Executing Dynamic DDL

Поиск
Список
Период
Сортировка
От Michael Fuhr
Тема Re: Executing Dynamic DDL
Дата
Msg-id 20050518132319.GA58577@winnie.fuhr.org
обсуждение исходный текст
Ответ на Executing Dynamic DDL  (Samer Abukhait <abukhait@gmail.com>)
Ответы Re: Executing Dynamic DDL  (Samer Abukhait <abukhait@gmail.com>)
Список pgsql-general
On Wed, May 18, 2005 at 09:07:55AM +0200, Samer Abukhait wrote:
>
> i am trying to execute an 'alter table' statement dynamically.. it
> seems that "execute" only works with DML..

A simple example shows that EXECUTE does indeed work with DDL:

CREATE TABLE foo (col1 integer);

CREATE FUNCTION execute_ddl() RETURNS void AS $$
BEGIN
    EXECUTE 'ALTER TABLE foo ADD col2 timestamp NOT NULL';
    RETURN;
END;
$$ LANGUAGE plpgsql VOLATILE;

\d foo
      Table "public.foo"
 Column |  Type   | Modifiers
--------+---------+-----------
 col1   | integer |

SELECT execute_ddl();

\d foo
                Table "public.foo"
 Column |            Type             | Modifiers
--------+-----------------------------+-----------
 col1   | integer                     |
 col2   | timestamp without time zone | not null

The problem appears to be in the function's logic:

> create or replace function em.process_table (
>     p_table              varchar)
> returns void as $$
> declare
>     v_check      bool;
> begin
>     -- Add Creation TimeStamp column if it is not there.
>     select count (*)
>     into   v_check
>     from   em.all_table_columns
>     where  tablename = p_table
>     and    columnname = 'creation_timestamp';

Count returns a bigint but you assign its value to a boolean.  This
should work if the return value is 0 (false) or 1 (true), which
presumably are the only possible counts in this case, but I probably
wouldn't coerce the value that way.  I'd either use EXISTS or assign
count's value to a bigint.

>     if v_check then
>         execute 'alter table em.' || p_table || ' add creation_timestamp
> timestamp not null';
>     end if;

You're saying that if the column exists (i.e., if v_check is true,
meaning that count returned 1), then add the column; you should be
checking if the column *doesn't* exist (i.e., if v_check is false,
meaning that count returned 0).  Also, it's a good idea to use
quote_ident() when building dynamic queries from data that comes
from outside the function.  And you might want to consider using
timestamp with time zone instead of timestamp.

>     return;
> end;$$ language plpgsql;

A function that has side effects should be declared VOLATILE.  And
if the function requires a non-NULL parameter then it should be
STRICT as well.

BTW, the all_table_columns table appears to duplicate information
already contained in the system catalogs.  Is this a contrived
example or are you really doing that?  Do you have a reason for
doing so?

--
Michael Fuhr
http://www.fuhr.org/~mfuhr/

В списке pgsql-general по дате отправления:

Предыдущее
От: Zlatko Matić
Дата:
Сообщение: double quotes inside VBA string ?
Следующее
От: Pascual De Ruvo
Дата:
Сообщение: Re: double quotes inside VBA string ?