2017-03-13 11 views
0

私はテーブル名の配列を受け取り、各テーブルのトリガーを作成するための配列を通してループする関数を持っています。関数はコンパイルされ、エラーなしで作成されます。 私は機能を実行しよう行くとき、私は次のエラーを取得しておくと、私は私の構文が間違って何Postgresqlの動的SQL構文エラー

ERRORを確認していない:

ERROR: unterminated quoted string at or near "'; 
ELSE 
    RAISE EXCEPTION ''[audit.if_modified_func] - Trigger func added as trigger for unhandled case: %, %'',TG_OP, TG_LEVEL; 
    RETURN NULL; 
END IF; 
INSERT INTO audit.Organization VALUES (audit_row.*); 
RETURN null; 
END; 
" 
LINE 53:   audit_row.statement_only = 't'; 
             ^ 

USAGE:

SELECT audit.temp_create_trigger(ARRAY['Organization']) 

ここで機能です:

CREATE OR REPLACE FUNCTION audit.temp_create_trigger(table_names character varying[]) 
RETURNS character varying AS 
$BODY$ 
DECLARE 
table_name varchar; 
i int; 
BEGIN 
FOR i in 1..array_upper(table_names, 1) LOOP 

EXECUTE format('CREATE OR REPLACE FUNCTION audit.trigger_function_%1$s() RETURNS TRIGGER AS $$ 
DECLARE 
    audit_row audit.%1$s; 
    include_values boolean; 
    log_diffs boolean; 
    h_old hstore; 
    h_new hstore; 
    excluded_cols text[] = ARRAY[]::text[]; 
BEGIN 
    IF TG_WHEN <> ''AFTER'' THEN 
     RAISE EXCEPTION ''audit.trigger_function_%1$s may only run as an AFTER trigger''; 
    END IF; 

    audit_row = ROW(
     nextval(''audit.%1$s_event_id_seq''), -- event_id 
     TG_TABLE_SCHEMA::text,      -- schema_name 
     TG_TABLE_NAME::text,       -- table_name 
     TG_RELID,          -- relation OID for much quicker searches 
     session_user::text,       -- session_user_name 
     current_timestamp,       -- action_tstamp_tx 
     statement_timestamp(),      -- action_tstamp_stm 
     clock_timestamp(),       -- action_tstamp_clk 
     txid_current(),        -- transaction ID 
     current_setting(''application_name''),   -- client application 
     inet_client_addr(),       -- client_addr 
     inet_client_port(),       -- client_port 
     current_query(),        -- top-level query or queries (if multistatement) from client 
     substring(TG_OP,1,1),       -- action 
     NULL, NULL,         -- row_data, changed_fields 
     ''f''           -- statement_only 
     ); 

    IF NOT TG_ARGV[0]::boolean IS DISTINCT FROM ''f''::boolean THEN 
     audit_row.client_query = NULL; 
    END IF; 

    IF TG_ARGV[1] IS NOT NULL THEN 
     excluded_cols = TG_ARGV[1]::text[]; 
    END IF; 

    IF (TG_OP = ''UPDATE'' AND TG_LEVEL = ''ROW'') THEN 
     audit_row.row_data = hstore(OLD.*) - excluded_cols; 
     audit_row.changed_fields = (hstore(NEW.*) - audit_row.row_data) - excluded_cols; 
     IF audit_row.changed_fields = hstore('') THEN 
      -- All changed fields are ignored. Skip this update. 
      RETURN NULL; 
     END IF; 
    ELSIF (TG_OP = ''DELETE'' AND TG_LEVEL = ''ROW'') THEN 
     audit_row.row_data = hstore(OLD.*) - excluded_cols; 
    ELSIF (TG_OP = ''INSERT'' AND TG_LEVEL = ''ROW'') THEN 
     audit_row.row_data = hstore(NEW.*) - excluded_cols; 
    ELSIF (TG_LEVEL = ''STATEMENT'' AND TG_OP IN (''INSERT'',''UPDATE'',''DELETE'',''TRUNCATE'')) THEN 
     audit_row.statement_only = ''t''; 
    ELSE 
     RAISE EXCEPTION ''''[audit.if_modified_func] - Trigger func added as trigger for unhandled case: %%, %%'''',TG_OP, TG_LEVEL; 
     RETURN NULL; 
    END IF; 
    INSERT INTO audit.%1$s VALUES (audit_row.*); 
RETURN null; 
END; 
$$ 
LANGUAGE plpgsql VOLATILE 
COST 100; 
ALTER FUNCTION audit.trigger_function_%1$s() 
OWNER TO postgres;', table_names[i]); 

EXECUTE format('CREATE TRIGGER audit.%1$s_trigg 
BEFORE INSERT OR UPDATE 
ON audit.%1$s 
FOR EACH ROW 
EXECUTE PROCEDURE audit.trigger_function_%1$s();', table_names[i]); 

END LOOP; 

RETURN 'SUCCESS'; 
END; 
$BODY$ 
LANGUAGE plpgsql 
COST 100; 
ALTER FUNCTION audit.temp_create_trigger(character varying[]) 
OWNER TO postgres; 
+1

' '... RAISE例外 '' ''[audit.if_modified_func] ... '[audit.if_modified_func] ...'、有効ではありません' が '' RAISE例外を実行しようとします' (必要以上に引用符がある)。もしあなたがそこにドルの引用符を使っていれば、それはいくらか清潔になります。 - Sidenote:単一のトリガー関数を作成することができます。実際にテーブルごとに関数を作成する必要はありません。 'TG_TABLE_SCHEMA'と' TG_TABLE_NAME'という特殊なトリガ変数を内部で使うことさえあります。これはそのために必要です。 – pozs

+0

@pozsあなたの提案を使用しようとしていますが、問題が発生しています。あなたは私の新しい投稿を見ることができます (https://stackoverflow.com/questions/43105974/postgresql-dynamic-function-with-current-table-name) – iambdot

答えて

0

不足している余分な引用:

--IF audit_row.changed_fields = hstore('') THEN -- missing quotes 
IF audit_row.changed_fields = hstore('''') THEN 

..... 

--RAISE EXCEPTION ''''[audit.if_modified_func] - Trigger func added as trigger for unhandled case: %%, %%'''',TG_OP, TG_LEVEL; --more quotes then needed 

RAISE EXCEPTION ''[audit.if_modified_func] - Trigger func added as trigger for unhandled case: %%, %%'',TG_OP, TG_LEVEL; 
+1

少なくとも$を使用して$を引用することをお勧めします関数コード –