2015-01-26 4 views
0

Я пытаюсь создать функцию, и я не могу найти ошибку в следующем коде:ошибка синтаксиса Postgres в функции

CREATE OR REPLACE FUNCTION qwat_od.fn_label_create_fields(table_name varchar, position boolean = true, rotation boolean = true) RETURNS void AS 
$BODY$ 
    BEGIN 
     /* Creates columns */ 
     EXECUTE 'ALTER TABLE qwat_od.'||table_name||' ADD COLUMN label_1_visible smallint default 1;   '; 
     IF position IS TRUE THEN 
      EXECUTE 'ALTER TABLE qwat_od.'||table_name||' ADD COLUMN label_1_x  double precision default null;'; 
      EXECUTE 'ALTER TABLE qwat_od.'||table_name||' ADD COLUMN label_1_y  double precision default null;'; 
     END IF; 
     IF rotation IS TRUE THEN 
      EXECUTE 'ALTER TABLE qwat_od.'||table_name||' ADD COLUMN label_1_rotation double precision default null;'; 
     END IF; 
     EXECUTE 'ALTER TABLE qwat_od.'||table_name||' ADD COLUMN label_1_text  varchar(120);'; 

     EXECUTE 'ALTER TABLE qwat_od.'||table_name||' ADD COLUMN label_2_visible smallint default 1;   '; 
     IF position IS TRUE THEN 
      EXECUTE 'ALTER TABLE qwat_od.'||table_name||' ADD COLUMN label_2_x  double precision default null;'; 
      EXECUTE 'ALTER TABLE qwat_od.'||table_name||' ADD COLUMN label_2_y  double precision default null;'; 
     END IF; 
     IF rotation IS TRUE THEN 
      EXECUTE 'ALTER TABLE qwat_od.'||table_name||' ADD COLUMN label_2_rotation double precision default null;'; 
     END IF; 

     EXECUTE 'ALTER TABLE qwat_od.'||table_name||' ADD COLUMN label_2_text  varchar(120);'; 
     /* Creates constraints */ 
     EXECUTE 'ALTER TABLE qwat_od.'||table_name||' ADD CONSTRAINT '||table_name||'_label_1_visible FOREIGN KEY (label_1_visible) REFERENCES qwat_vl.visible(vl_code_int) MATCH FULL; CREATE INDEX fki_'||table_name||'_label_1_visible ON qwat_od.'||table_name||'(label_1_visible);'; 
     EXECUTE 'ALTER TABLE qwat_od.'||table_name||' ADD CONSTRAINT '||table_name||'_label_2_visible FOREIGN KEY (label_2_visible) REFERENCES qwat_vl.visible(vl_code_int) MATCH FULL; CREATE INDEX fki_'||table_name||'_label_2_visible ON qwat_od.'||table_name||'(label_2_visible);'; 
    END; 
$BODY$ 
LANGUAGE 'plpgsql'; 

я получаю это:

ERROR: syntax error at or near "position" 
LINE 4: ...wat_od.fn_label_create_fields(table_name varchar, position b... 

Я сделал что-то не так в декларации аргументов?

+0

@a_horse_with_no_name он поддерживает (в основном это поддерживает любые SQL выражения http://www.postgresql.org/docs/current/static/plpgsql-expressions.html) - но, конечно, 'IF <булева переменная> THEN' является более понятным. – pozs

+0

@a_horse_with_no_name: [эта страница документации] (http://www.postgresql.org/docs/9.1/static/functions-comparison.html) предполагает, что поддерживается 'is true' – Andomar

+3

' position' является зарезервированным словом SQL, вы должны указать его http://www.postgresql.org/docs/current/static/sql-keywords-appendix.html – pozs

ответ

2

@pozs already provided an explanation за ошибки, которые вы видели.
Но есть еще. Самое главное, вы широко открыты для SQL injection.

CREATE OR REPLACE FUNCTION qwat_od.fn_label_create_fields(_tbl text, _position bool = true, _rotation bool = true) 
    RETURNS void AS 
$func$ 
BEGIN 
    /* Creates columns */ 
    EXECUTE format('ALTER TABLE qwat_od.%I ADD COLUMN label_1_visible smallint default 1', _tbl); 

    IF _position THEN 
     EXECUTE format('ALTER TABLE qwat_od.%I 
      ADD COLUMN label_1_x double precision default null 
     , ADD COLUMN label_1_y double precision default null', _tbl); 
    END IF; 
    IF _rotation THEN 
     EXECUTE format('ALTER TABLE qwat_od.%I ADD COLUMN label_1_rotation double precision default null' , _tbl); 
    END IF; 

    EXECUTE format('ALTER TABLE qwat_od.%I 
      ADD COLUMN label_1_text varchar(120)  
     , ADD COLUMN label_2_visible smallint default 1', _tbl); 

    IF _position THEN 
     EXECUTE format('ALTER TABLE qwat_od.%I 
      ADD COLUMN label_2_x double precision default null 
     , ADD COLUMN label_2_y double precision default null', _tbl); 
    END IF; 
    IF _rotation THEN 
     EXECUTE format('ALTER TABLE qwat_od.%I ADD COLUMN label_2_rotation double precision default null', _tbl); 
    END IF; 

    EXECUTE format('ALTER TABLE qwat_od.%I ADD COLUMN label_2_text varchar(120)', _tbl); 

    /* Creates constraints */ 
    EXECUTE format('ALTER TABLE qwat_od.%$1I 
      ADD CONSTRAINT %$2I FOREIGN KEY (label_1_visible) REFERENCES qwat_vl.visible(vl_code_int) 
     , ADD CONSTRAINT %$3I FOREIGN KEY (label_2_visible) REFERENCES qwat_vl.visible(vl_code_int); 
    CREATE INDEX %$4I ON qwat_od.%$1I(label_1_visible); 
    CREATE INDEX %$5I ON qwat_od.%$1I(label_2_visible)' 
    , _tbl 
    , _tbl || '_label_1_visible' 
    , _tbl || '_label_2_visible' 
    , 'fki_' || _tbl || '_label_1_visible' 
    , 'fki_' || _tbl || '_label_2_visible'); 
END 
$func$ LANGUAGE plpgsql; 
  • Обязательно используйте однозначные, действительные имена параметров (position будучи reserved word был основной ошибкой).

  • Я исправил проблемы с SQL-инъекциями с помощью format() (так как простое решение с regclass не охватывало ваши конкатенированные имена, как прокомментировал @pozs). Подробное описание:

  • _tbl должен быть неквалифицированное имя таблицы ("tbl", не "schema.tbl").

  • Не указывайте название языка, это идентификатор: LANGUAGE plpgsql

  • Это дешевле, чтобы добавить несколько столбцов/sonstraints в одном ALTER TABLE заявлении.

  • Другие упрощенные упрощения/оптимизации.

+1

Хотя я обычно согласен с использованием 'regclass', этот случай будет генерировать синтаксические ошибки (около имен ограничений) с помощью специальных имен таблиц, таких как' '$ t" '(он будет генерировать f.ex.' CREATE INDEX fki _ "$ t" _label_1_visible ... '- для устранения этого нужно использовать уродливые выборки из каталогов pg или использовать' format() '/' quote_ident() 'для простоты – pozs

+0

@pozs: вы правы. Я не обратил внимания на конкатенированные имена. Стандартные идентификаторы были бы проблемой. 'format()' это путь. –

+0

Большое спасибо за эту детальную ревизию, и я узнал несколько полезных вещей !!! –

Смежные вопросы