Remove pg_audit
authorStephen Frost <sfrost@snowman.net>
Thu, 28 May 2015 16:41:26 +0000 (12:41 -0400)
committerStephen Frost <sfrost@snowman.net>
Thu, 28 May 2015 16:41:26 +0000 (12:41 -0400)
This removes pg_audit, per discussion:

20150528082038.GU26667@tamriel.snowman.net

contrib/pg_audit/.gitignore [deleted file]
contrib/pg_audit/Makefile [deleted file]
contrib/pg_audit/expected/pg_audit.out [deleted file]
contrib/pg_audit/pg_audit--1.0.sql [deleted file]
contrib/pg_audit/pg_audit.c [deleted file]
contrib/pg_audit/pg_audit.control [deleted file]
contrib/pg_audit/sql/pg_audit.sql [deleted file]

diff --git a/contrib/pg_audit/.gitignore b/contrib/pg_audit/.gitignore
deleted file mode 100644 (file)
index a5267cf..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-log/
-results/
-tmp_check/
-regression.diffs
-regression.out
diff --git a/contrib/pg_audit/Makefile b/contrib/pg_audit/Makefile
deleted file mode 100644 (file)
index 9ba2e4d..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-# contrib/pg_audit/Makefile
-
-MODULE_big = pg_audit
-OBJS = pg_audit.o $(WIN32RES)
-
-EXTENSION = pg_audit
-DATA = pg_audit--1.0.sql
-PGFILEDESC = "pg_audit - An audit logging extension for PostgreSQL"
-
-REGRESS = pg_audit
-
-ifdef USE_PGXS
-PG_CONFIG = pg_config
-PGXS := $(shell $(PG_CONFIG) --pgxs)
-include $(PGXS)
-else
-subdir = contrib/pg_audit
-top_builddir = ../..
-include $(top_builddir)/src/Makefile.global
-include $(top_srcdir)/contrib/contrib-global.mk
-endif
diff --git a/contrib/pg_audit/expected/pg_audit.out b/contrib/pg_audit/expected/pg_audit.out
deleted file mode 100644 (file)
index e870f06..0000000
+++ /dev/null
@@ -1,1074 +0,0 @@
--- Load pg_audit module
-create extension pg_audit;
---
--- Audit log fields are:
---     AUDIT_TYPE - SESSION or OBJECT
---     STATEMENT_ID - ID of the statement in the current backend
---     SUBSTATEMENT_ID - ID of the substatement in the current backend
---     CLASS - Class of statement being logged (e.g. ROLE, READ, WRITE)
---     COMMAND - e.g. SELECT, CREATE ROLE, UPDATE
---     OBJECT_TYPE - When available, type of object acted on (e.g. TABLE, VIEW)
---     OBJECT_NAME - When available, fully-qualified table of object
---     STATEMENT - The statement being logged
---     PARAMETER - If parameter logging is requested, they will follow the
---                 statement
-select current_user \gset
---
--- Set pg_audit parameters for the current (super)user.
-ALTER ROLE :current_user SET pg_audit.log = 'Role';
-ALTER ROLE :current_user SET pg_audit.log_level = 'notice';
-CREATE FUNCTION load_pg_audit( )
- RETURNS VOID
- LANGUAGE plpgsql
-SECURITY DEFINER
-AS $function$
-declare
-begin
-LOAD 'pg_audit';
-end;
-$function$;
--- After each connect, we need to load pg_audit, as if it was
--- being loaded from shared_preload_libraries.  Otherwise, the hooks
--- won't be set up and called correctly, leading to lots of ugly
--- errors.
-\connect - :current_user;
-select load_pg_audit();
- load_pg_audit 
----------------
-(1 row)
-
---
--- Create auditor role
-CREATE ROLE auditor;
-NOTICE:  AUDIT: SESSION,1,1,ROLE,CREATE ROLE,,,CREATE ROLE auditor;,<not logged>
---
--- Create first test user
-CREATE USER user1;
-NOTICE:  AUDIT: SESSION,2,1,ROLE,CREATE ROLE,,,CREATE USER user1;,<not logged>
-ALTER ROLE user1 SET pg_audit.log = 'ddl, ROLE';
-NOTICE:  AUDIT: SESSION,3,1,ROLE,ALTER ROLE,,,"ALTER ROLE user1 SET pg_audit.log = 'ddl, ROLE';",<not logged>
-ALTER ROLE user1 SET pg_audit.log_level = 'notice';
-NOTICE:  AUDIT: SESSION,4,1,ROLE,ALTER ROLE,,,ALTER ROLE user1 SET pg_audit.log_level = 'notice';,<not logged>
---
--- Create, select, drop (select will not be audited)
-\connect - user1
-select load_pg_audit();
- load_pg_audit 
----------------
-(1 row)
-
-CREATE TABLE public.test (id INT);
-NOTICE:  AUDIT: SESSION,1,1,DDL,CREATE TABLE,TABLE,public.test,CREATE TABLE public.test (id INT);,<not logged>
-SELECT * FROM test;
- id 
-----
-(0 rows)
-
-DROP TABLE test;
-NOTICE:  AUDIT: SESSION,2,1,DDL,DROP TABLE,TABLE,public.test,DROP TABLE test;,<not logged>
---
--- Create second test user
-\connect - :current_user
-select load_pg_audit();
- load_pg_audit 
----------------
-(1 row)
-
-CREATE USER user2;
-NOTICE:  AUDIT: SESSION,1,1,ROLE,CREATE ROLE,,,CREATE USER user2;,<not logged>
-ALTER ROLE user2 SET pg_audit.log = 'Read, writE';
-NOTICE:  AUDIT: SESSION,2,1,ROLE,ALTER ROLE,,,"ALTER ROLE user2 SET pg_audit.log = 'Read, writE';",<not logged>
-ALTER ROLE user2 SET pg_audit.log_catalog = OFF;
-NOTICE:  AUDIT: SESSION,3,1,ROLE,ALTER ROLE,,,ALTER ROLE user2 SET pg_audit.log_catalog = OFF;,<not logged>
-ALTER ROLE user2 SET pg_audit.log_level = 'warning';
-NOTICE:  AUDIT: SESSION,4,1,ROLE,ALTER ROLE,,,ALTER ROLE user2 SET pg_audit.log_level = 'warning';,<not logged>
-ALTER ROLE user2 SET pg_audit.role = auditor;
-NOTICE:  AUDIT: SESSION,5,1,ROLE,ALTER ROLE,,,ALTER ROLE user2 SET pg_audit.role = auditor;,<not logged>
-ALTER ROLE user2 SET pg_audit.log_statement_once = ON;
-NOTICE:  AUDIT: SESSION,6,1,ROLE,ALTER ROLE,,,ALTER ROLE user2 SET pg_audit.log_statement_once = ON;,<not logged>
-\connect - user2
-select load_pg_audit();
- load_pg_audit 
----------------
-(1 row)
-
-CREATE TABLE test2 (id INT);
-GRANT SELECT ON TABLE public.test2 TO auditor;
---
--- Role-based tests
-CREATE TABLE test3
-(
-       id INT
-);
-SELECT count(*)
-  FROM
-(
-       SELECT relname
-         FROM pg_class
-         LIMIT 1
-) SUBQUERY;
- count 
--------
-     1
-(1 row)
-
-SELECT *
-  FROM test3, test2;
-WARNING:  AUDIT: SESSION,1,1,READ,SELECT,,,"SELECT *
-  FROM test3, test2;",<not logged>
-WARNING:  AUDIT: OBJECT,1,1,READ,SELECT,TABLE,public.test2,<previously logged>,<previously logged>
- id | id 
-----+----
-(0 rows)
-
-GRANT INSERT
-   ON TABLE public.test3
-   TO auditor;
---
--- Create a view to test logging
-CREATE VIEW vw_test3 AS
-SELECT *
-  FROM test3;
-GRANT SELECT
-   ON vw_test3
-   TO auditor;
---
--- Object logged because of:
--- select on vw_test3
--- select on test2
-SELECT *
-  FROM vw_test3, test2;
-WARNING:  AUDIT: SESSION,2,1,READ,SELECT,,,"SELECT *
-  FROM vw_test3, test2;",<not logged>
-WARNING:  AUDIT: OBJECT,2,1,READ,SELECT,TABLE,public.test2,<previously logged>,<previously logged>
-WARNING:  AUDIT: OBJECT,2,1,READ,SELECT,VIEW,public.vw_test3,<previously logged>,<previously logged>
- id | id 
-----+----
-(0 rows)
-
---
--- Object logged because of:
--- insert on test3
--- select on test2
-WITH CTE AS
-(
-       SELECT id
-         FROM test2
-)
-INSERT INTO test3
-SELECT id
-  FROM cte;
-WARNING:  AUDIT: SESSION,3,1,WRITE,INSERT,,,"WITH CTE AS
-(
-       SELECT id
-         FROM test2
-)
-INSERT INTO test3
-SELECT id
-  FROM cte;",<not logged>
-WARNING:  AUDIT: OBJECT,3,1,WRITE,INSERT,TABLE,public.test3,<previously logged>,<previously logged>
-WARNING:  AUDIT: OBJECT,3,1,READ,SELECT,TABLE,public.test2,<previously logged>,<previously logged>
---
--- Object logged because of:
--- insert on test3
-WITH CTE AS
-(
-       INSERT INTO test3 VALUES (1)
-                                  RETURNING id
-)
-INSERT INTO test2
-SELECT id
-  FROM cte;
-WARNING:  AUDIT: SESSION,4,1,WRITE,INSERT,,,"WITH CTE AS
-(
-       INSERT INTO test3 VALUES (1)
-                                  RETURNING id
-)
-INSERT INTO test2
-SELECT id
-  FROM cte;",<not logged>
-WARNING:  AUDIT: OBJECT,4,1,WRITE,INSERT,TABLE,public.test3,<previously logged>,<previously logged>
-GRANT UPDATE ON TABLE public.test2 TO auditor;
---
--- Object logged because of:
--- insert on test3
--- update on test2
-WITH CTE AS
-(
-       UPDATE test2
-          SET id = 1
-       RETURNING id
-)
-INSERT INTO test3
-SELECT id
-  FROM cte;
-WARNING:  AUDIT: SESSION,5,1,WRITE,INSERT,,,"WITH CTE AS
-(
-       UPDATE test2
-          SET id = 1
-       RETURNING id
-)
-INSERT INTO test3
-SELECT id
-  FROM cte;",<not logged>
-WARNING:  AUDIT: OBJECT,5,1,WRITE,INSERT,TABLE,public.test3,<previously logged>,<previously logged>
-WARNING:  AUDIT: OBJECT,5,1,WRITE,UPDATE,TABLE,public.test2,<previously logged>,<previously logged>
---
--- Object logged because of:
--- insert on test2
-WITH CTE AS
-(
-       INSERT INTO test2 VALUES (1)
-                                  RETURNING id
-)
-UPDATE test3
-   SET id = cte.id
-  FROM cte
- WHERE test3.id <> cte.id;
-WARNING:  AUDIT: SESSION,6,1,WRITE,UPDATE,,,"WITH CTE AS
-(
-       INSERT INTO test2 VALUES (1)
-                                  RETURNING id
-)
-UPDATE test3
-   SET id = cte.id
-  FROM cte
- WHERE test3.id <> cte.id;",<not logged>
-WARNING:  AUDIT: OBJECT,6,1,WRITE,INSERT,TABLE,public.test2,<previously logged>,<previously logged>
---
--- Change permissions of user 2 so that only object logging will be done
-\connect - :current_user
-select load_pg_audit();
- load_pg_audit 
----------------
-(1 row)
-
-alter role user2 set pg_audit.log = 'NONE';
-NOTICE:  AUDIT: SESSION,1,1,ROLE,ALTER ROLE,,,alter role user2 set pg_audit.log = 'NONE';,<not logged>
-\connect - user2
-select load_pg_audit();
- load_pg_audit 
----------------
-(1 row)
-
---
--- Create test4 and add permissions
-CREATE TABLE test4
-(
-       id int,
-       name text
-);
-GRANT SELECT (name)
-   ON TABLE public.test4
-   TO auditor;
-GRANT UPDATE (id)
-   ON TABLE public.test4
-   TO auditor;
-GRANT insert (name)
-   ON TABLE public.test4
-   TO auditor;
---
--- Not object logged
-SELECT id
-  FROM public.test4;
- id 
-----
-(0 rows)
-
---
--- Object logged because of:
--- select (name) on test4
-SELECT name
-  FROM public.test4;
-WARNING:  AUDIT: OBJECT,1,1,READ,SELECT,TABLE,public.test4,"SELECT name
-  FROM public.test4;",<not logged>
- name 
-------
-(0 rows)
-
---
--- Not object logged
-INSERT INTO public.test4 (id)
-                                 VALUES (1);
---
--- Object logged because of:
--- insert (name) on test4
-INSERT INTO public.test4 (name)
-                                 VALUES ('test');
-WARNING:  AUDIT: OBJECT,2,1,WRITE,INSERT,TABLE,public.test4,"INSERT INTO public.test4 (name)
-                                 VALUES ('test');",<not logged>
---
--- Not object logged
-UPDATE public.test4
-   SET name = 'foo';
---
--- Object logged because of:
--- update (id) on test4
-UPDATE public.test4
-   SET id = 1;
-WARNING:  AUDIT: OBJECT,3,1,WRITE,UPDATE,TABLE,public.test4,"UPDATE public.test4
-   SET id = 1;",<not logged>
---
--- Object logged because of:
--- update (name) on test4
--- update (name) takes precedence over select (name) due to ordering
-update public.test4 set name = 'foo' where name = 'bar';
-WARNING:  AUDIT: OBJECT,4,1,WRITE,UPDATE,TABLE,public.test4,update public.test4 set name = 'foo' where name = 'bar';,<not logged>
---
--- Drop test tables
-DROP TABLE test2;
-DROP VIEW vw_test3;
-DROP TABLE test3;
-DROP TABLE test4;
---
--- Change permissions of user 1 so that session logging will be done
-\connect - :current_user
-select load_pg_audit();
- load_pg_audit 
----------------
-(1 row)
-
-alter role user1 set pg_audit.log = 'DDL, READ';
-NOTICE:  AUDIT: SESSION,1,1,ROLE,ALTER ROLE,,,"alter role user1 set pg_audit.log = 'DDL, READ';",<not logged>
-\connect - user1
-select load_pg_audit();
- load_pg_audit 
----------------
-(1 row)
-
---
--- Create table is session logged
-CREATE TABLE public.account
-(
-       id INT,
-       name TEXT,
-       password TEXT,
-       description TEXT
-);
-NOTICE:  AUDIT: SESSION,1,1,DDL,CREATE TABLE,TABLE,public.account,"CREATE TABLE public.account
-(
-       id INT,
-       name TEXT,
-       password TEXT,
-       description TEXT
-);",<not logged>
---
--- Select is session logged
-SELECT *
-  FROM account;
-NOTICE:  AUDIT: SESSION,2,1,READ,SELECT,,,"SELECT *
-  FROM account;",<not logged>
- id | name | password | description 
-----+------+----------+-------------
-(0 rows)
-
---
--- Insert is not logged
-INSERT INTO account (id, name, password, description)
-                        VALUES (1, 'user1', 'HASH1', 'blah, blah');
---
--- Change permissions of user 1 so that only object logging will be done
-\connect - :current_user
-select load_pg_audit();
- load_pg_audit 
----------------
-(1 row)
-
-alter role user1 set pg_audit.log = 'none';
-NOTICE:  AUDIT: SESSION,1,1,ROLE,ALTER ROLE,,,alter role user1 set pg_audit.log = 'none';,<not logged>
-alter role user1 set pg_audit.role = 'auditor';
-NOTICE:  AUDIT: SESSION,2,1,ROLE,ALTER ROLE,,,alter role user1 set pg_audit.role = 'auditor';,<not logged>
-\connect - user1
-select load_pg_audit();
- load_pg_audit 
----------------
-(1 row)
-
---
--- ROLE class not set, so auditor grants not logged
-GRANT SELECT (password),
-         UPDATE (name, password)
-   ON TABLE public.account
-   TO auditor;
---
--- Not object logged
-SELECT id,
-          name
-  FROM account;
- id | name  
-----+-------
-  1 | user1
-(1 row)
-
---
--- Object logged because of:
--- select (password) on account
-SELECT password
-  FROM account;
-NOTICE:  AUDIT: OBJECT,1,1,READ,SELECT,TABLE,public.account,"SELECT password
-  FROM account;",<not logged>
- password 
-----------
- HASH1
-(1 row)
-
---
--- Not object logged
-UPDATE account
-   SET description = 'yada, yada';
---
--- Object logged because of:
--- update (password) on account
-UPDATE account
-   SET password = 'HASH2';
-NOTICE:  AUDIT: OBJECT,2,1,WRITE,UPDATE,TABLE,public.account,"UPDATE account
-   SET password = 'HASH2';",<not logged>
---
--- Change permissions of user 1 so that session relation logging will be done
-\connect - :current_user
-select load_pg_audit();
- load_pg_audit 
----------------
-(1 row)
-
-alter role user1 set pg_audit.log_relation = on;
-NOTICE:  AUDIT: SESSION,1,1,ROLE,ALTER ROLE,,,alter role user1 set pg_audit.log_relation = on;,<not logged>
-alter role user1 set pg_audit.log = 'read, WRITE';
-NOTICE:  AUDIT: SESSION,2,1,ROLE,ALTER ROLE,,,"alter role user1 set pg_audit.log = 'read, WRITE';",<not logged>
-\connect - user1
-select load_pg_audit();
- load_pg_audit 
----------------
-(1 row)
-
---
--- Not logged
-create table ACCOUNT_ROLE_MAP
-(
-       account_id INT,
-       role_id INT
-);
---
--- ROLE class not set, so auditor grants not logged
-GRANT SELECT
-   ON TABLE public.account_role_map
-   TO auditor;
---
--- Object logged because of:
--- select (password) on account
--- select on account_role_map
--- Session logged on all tables because log = read and log_relation = on
-SELECT account.password,
-          account_role_map.role_id
-  FROM account
-          INNER JOIN account_role_map
-                       on account.id = account_role_map.account_id;
-NOTICE:  AUDIT: OBJECT,1,1,READ,SELECT,TABLE,public.account,"SELECT account.password,
-          account_role_map.role_id
-  FROM account
-          INNER JOIN account_role_map
-                       on account.id = account_role_map.account_id;",<not logged>
-NOTICE:  AUDIT: SESSION,1,1,READ,SELECT,TABLE,public.account,"SELECT account.password,
-          account_role_map.role_id
-  FROM account
-          INNER JOIN account_role_map
-                       on account.id = account_role_map.account_id;",<not logged>
-NOTICE:  AUDIT: OBJECT,1,1,READ,SELECT,TABLE,public.account_role_map,"SELECT account.password,
-          account_role_map.role_id
-  FROM account
-          INNER JOIN account_role_map
-                       on account.id = account_role_map.account_id;",<not logged>
-NOTICE:  AUDIT: SESSION,1,1,READ,SELECT,TABLE,public.account_role_map,"SELECT account.password,
-          account_role_map.role_id
-  FROM account
-          INNER JOIN account_role_map
-                       on account.id = account_role_map.account_id;",<not logged>
- password | role_id 
-----------+---------
-(0 rows)
-
---
--- Object logged because of:
--- select (password) on account
--- Session logged on all tables because log = read and log_relation = on
-SELECT password
-  FROM account;
-NOTICE:  AUDIT: OBJECT,2,1,READ,SELECT,TABLE,public.account,"SELECT password
-  FROM account;",<not logged>
-NOTICE:  AUDIT: SESSION,2,1,READ,SELECT,TABLE,public.account,"SELECT password
-  FROM account;",<not logged>
- password 
-----------
- HASH2
-(1 row)
-
---
--- Not object logged
--- Session logged on all tables because log = read and log_relation = on
-UPDATE account
-   SET description = 'yada, yada';
-NOTICE:  AUDIT: SESSION,3,1,WRITE,UPDATE,TABLE,public.account,"UPDATE account
-   SET description = 'yada, yada';",<not logged>
---
--- Object logged because of:
--- select (password) on account (in the where clause)
--- Session logged on all tables because log = read and log_relation = on
-UPDATE account
-   SET description = 'yada, yada'
- where password = 'HASH2';
-NOTICE:  AUDIT: OBJECT,4,1,WRITE,UPDATE,TABLE,public.account,"UPDATE account
-   SET description = 'yada, yada'
- where password = 'HASH2';",<not logged>
-NOTICE:  AUDIT: SESSION,4,1,WRITE,UPDATE,TABLE,public.account,"UPDATE account
-   SET description = 'yada, yada'
- where password = 'HASH2';",<not logged>
---
--- Object logged because of:
--- update (password) on account
--- Session logged on all tables because log = read and log_relation = on
-UPDATE account
-   SET password = 'HASH2';
-NOTICE:  AUDIT: OBJECT,5,1,WRITE,UPDATE,TABLE,public.account,"UPDATE account
-   SET password = 'HASH2';",<not logged>
-NOTICE:  AUDIT: SESSION,5,1,WRITE,UPDATE,TABLE,public.account,"UPDATE account
-   SET password = 'HASH2';",<not logged>
---
--- Change back to superuser to do exhaustive tests
-\connect - :current_user
-select load_pg_audit();
- load_pg_audit 
----------------
-(1 row)
-
-SET pg_audit.log = 'ALL';
-NOTICE:  AUDIT: SESSION,1,1,MISC,SET,,,SET pg_audit.log = 'ALL';,<not logged>
-SET pg_audit.log_level = 'notice';
-NOTICE:  AUDIT: SESSION,2,1,MISC,SET,,,SET pg_audit.log_level = 'notice';,<not logged>
-SET pg_audit.log_relation = ON;
-NOTICE:  AUDIT: SESSION,3,1,MISC,SET,,,SET pg_audit.log_relation = ON;,<not logged>
-SET pg_audit.log_parameter = ON;
-NOTICE:  AUDIT: SESSION,4,1,MISC,SET,,,SET pg_audit.log_parameter = ON;,<none>
---
--- Simple DO block
-DO $$
-BEGIN
-       raise notice 'test';
-END $$;
-NOTICE:  AUDIT: SESSION,5,1,FUNCTION,DO,,,"DO $$
-BEGIN
-       raise notice 'test';
-END $$;",<none>
-NOTICE:  test
---
--- Create test schema
-CREATE SCHEMA test;
-NOTICE:  AUDIT: SESSION,6,1,DDL,CREATE SCHEMA,SCHEMA,test,CREATE SCHEMA test;,<none>
---
--- Copy account to stdout
-COPY account TO stdout;
-NOTICE:  AUDIT: SESSION,7,1,READ,SELECT,TABLE,public.account,COPY account TO stdout;,<none>
-1      user1   HASH2   yada, yada
---
--- Create a table from a query
-CREATE TABLE test.account_copy AS
-SELECT *
-  FROM account;
-NOTICE:  AUDIT: SESSION,8,1,READ,SELECT,TABLE,public.account,"CREATE TABLE test.account_copy AS
-SELECT *
-  FROM account;",<none>
-NOTICE:  AUDIT: SESSION,8,1,WRITE,INSERT,TABLE,test.account_copy,"CREATE TABLE test.account_copy AS
-SELECT *
-  FROM account;",<none>
-NOTICE:  AUDIT: SESSION,8,2,DDL,CREATE TABLE AS,TABLE,test.account_copy,"CREATE TABLE test.account_copy AS
-SELECT *
-  FROM account;",<none>
---
--- Copy from stdin to account copy
-COPY test.account_copy from stdin;
-NOTICE:  AUDIT: SESSION,9,1,WRITE,INSERT,TABLE,test.account_copy,COPY test.account_copy from stdin;,<none>
---
--- Test prepared statement
-PREPARE pgclassstmt (oid) AS
-SELECT *
-  FROM account
- WHERE id = $1;
-NOTICE:  AUDIT: SESSION,10,1,READ,PREPARE,,,"PREPARE pgclassstmt (oid) AS
-SELECT *
-  FROM account
- WHERE id = $1;",<none>
-EXECUTE pgclassstmt (1);
-NOTICE:  AUDIT: SESSION,11,1,READ,SELECT,TABLE,public.account,"PREPARE pgclassstmt (oid) AS
-SELECT *
-  FROM account
- WHERE id = $1;",1
-NOTICE:  AUDIT: SESSION,11,2,MISC,EXECUTE,,,EXECUTE pgclassstmt (1);,<none>
- id | name  | password | description 
-----+-------+----------+-------------
-  1 | user1 | HASH2    | yada, yada
-(1 row)
-
-DEALLOCATE pgclassstmt;
-NOTICE:  AUDIT: SESSION,12,1,MISC,DEALLOCATE,,,DEALLOCATE pgclassstmt;,<none>
---
--- Test cursor
-BEGIN;
-NOTICE:  AUDIT: SESSION,13,1,MISC,BEGIN,,,BEGIN;,<none>
-DECLARE ctest SCROLL CURSOR FOR
-SELECT count(*)
-  FROM
-(
-       SELECT relname
-         FROM pg_class
-        LIMIT 1
- ) subquery;
-NOTICE:  AUDIT: SESSION,14,1,READ,SELECT,TABLE,pg_catalog.pg_class,"DECLARE ctest SCROLL CURSOR FOR
-SELECT count(*)
-  FROM
-(
-       SELECT relname
-         FROM pg_class
-        LIMIT 1
- ) subquery;",<none>
-NOTICE:  AUDIT: SESSION,14,2,READ,DECLARE CURSOR,,,"DECLARE ctest SCROLL CURSOR FOR
-SELECT count(*)
-  FROM
-(
-       SELECT relname
-         FROM pg_class
-        LIMIT 1
- ) subquery;",<none>
-FETCH NEXT FROM ctest;
-NOTICE:  AUDIT: SESSION,15,1,MISC,FETCH,,,FETCH NEXT FROM ctest;,<none>
- count 
--------
-     1
-(1 row)
-
-CLOSE ctest;
-NOTICE:  AUDIT: SESSION,16,1,MISC,CLOSE CURSOR,,,CLOSE ctest;,<none>
-COMMIT;
-NOTICE:  AUDIT: SESSION,17,1,MISC,COMMIT,,,COMMIT;,<none>
---
--- Turn off log_catalog and pg_class will not be logged
-SET pg_audit.log_catalog = OFF;
-NOTICE:  AUDIT: SESSION,18,1,MISC,SET,,,SET pg_audit.log_catalog = OFF;,<none>
-SELECT count(*)
-  FROM
-(
-       SELECT relname
-         FROM pg_class
-        LIMIT 1
- ) subquery;
- count 
--------
-     1
-(1 row)
-
---
--- Test prepared insert
-CREATE TABLE test.test_insert
-(
-       id INT
-);
-NOTICE:  AUDIT: SESSION,19,1,DDL,CREATE TABLE,TABLE,test.test_insert,"CREATE TABLE test.test_insert
-(
-       id INT
-);",<none>
-PREPARE pgclassstmt (oid) AS
-INSERT INTO test.test_insert (id)
-                                         VALUES ($1);
-NOTICE:  AUDIT: SESSION,20,1,WRITE,PREPARE,,,"PREPARE pgclassstmt (oid) AS
-INSERT INTO test.test_insert (id)
-                                         VALUES ($1);",<none>
-EXECUTE pgclassstmt (1);
-NOTICE:  AUDIT: SESSION,21,1,WRITE,INSERT,TABLE,test.test_insert,"PREPARE pgclassstmt (oid) AS
-INSERT INTO test.test_insert (id)
-                                         VALUES ($1);",1
-NOTICE:  AUDIT: SESSION,21,2,MISC,EXECUTE,,,EXECUTE pgclassstmt (1);,<none>
---
--- Check that primary key creation is logged
-CREATE TABLE public.test
-(
-       id INT,
-       name TEXT,
-       description TEXT,
-       CONSTRAINT test_pkey PRIMARY KEY (id)
-);
-NOTICE:  AUDIT: SESSION,22,1,DDL,CREATE TABLE,TABLE,public.test,"CREATE TABLE public.test
-(
-       id INT,
-       name TEXT,
-       description TEXT,
-       CONSTRAINT test_pkey PRIMARY KEY (id)
-);",<none>
-NOTICE:  AUDIT: SESSION,22,1,DDL,CREATE TABLE,INDEX,public.test_pkey,"CREATE TABLE public.test
-(
-       id INT,
-       name TEXT,
-       description TEXT,
-       CONSTRAINT test_pkey PRIMARY KEY (id)
-);",<none>
---
--- Check that analyze is logged
-ANALYZE test;
-NOTICE:  AUDIT: SESSION,23,1,MISC,ANALYZE,,,ANALYZE test;,<none>
---
--- Grants to public should not cause object logging (session logging will
--- still happen)
-GRANT SELECT
-  ON TABLE public.test
-  TO PUBLIC;
-NOTICE:  AUDIT: SESSION,24,1,ROLE,GRANT,TABLE,,"GRANT SELECT
-  ON TABLE public.test
-  TO PUBLIC;",<none>
-SELECT *
-  FROM test;
-NOTICE:  AUDIT: SESSION,25,1,READ,SELECT,TABLE,public.test,"SELECT *
-  FROM test;",<none>
- id | name | description 
-----+------+-------------
-(0 rows)
-
--- Check that statements without columns log
-SELECT
-  FROM test;
-NOTICE:  AUDIT: SESSION,26,1,READ,SELECT,TABLE,public.test,"SELECT
-  FROM test;",<none>
---
-(0 rows)
-
-SELECT 1,
-          substring('Thomas' from 2 for 3);
-NOTICE:  AUDIT: SESSION,27,1,READ,SELECT,,,"SELECT 1,
-          substring('Thomas' from 2 for 3);",<none>
- ?column? | substring 
-----------+-----------
-        1 | hom
-(1 row)
-
-DO $$
-DECLARE
-       test INT;
-BEGIN
-       SELECT 1
-         INTO test;
-END $$;
-NOTICE:  AUDIT: SESSION,28,1,FUNCTION,DO,,,"DO $$
-DECLARE
-       test INT;
-BEGIN
-       SELECT 1
-         INTO test;
-END $$;",<none>
-NOTICE:  AUDIT: SESSION,28,2,READ,SELECT,,,SELECT 1,<none>
-CONTEXT:  SQL statement "SELECT 1"
-PL/pgSQL function inline_code_block line 5 at SQL statement
-explain select 1;
-NOTICE:  AUDIT: SESSION,29,1,READ,SELECT,,,explain select 1;,<none>
-NOTICE:  AUDIT: SESSION,29,2,MISC,EXPLAIN,,,explain select 1;,<none>
-                QUERY PLAN                
-------------------------------------------
- Result  (cost=0.00..0.01 rows=1 width=0)
-(1 row)
-
---
--- Test that looks inside of do blocks log
-INSERT INTO TEST (id)
-                 VALUES (1);
-NOTICE:  AUDIT: SESSION,30,1,WRITE,INSERT,TABLE,public.test,"INSERT INTO TEST (id)
-                 VALUES (1);",<none>
-INSERT INTO TEST (id)
-                 VALUES (2);
-NOTICE:  AUDIT: SESSION,31,1,WRITE,INSERT,TABLE,public.test,"INSERT INTO TEST (id)
-                 VALUES (2);",<none>
-INSERT INTO TEST (id)
-                 VALUES (3);
-NOTICE:  AUDIT: SESSION,32,1,WRITE,INSERT,TABLE,public.test,"INSERT INTO TEST (id)
-                 VALUES (3);",<none>
-DO $$
-DECLARE
-       result RECORD;
-BEGIN
-       FOR result IN
-               SELECT id
-                 FROM test
-       LOOP
-               INSERT INTO test (id)
-                        VALUES (result.id + 100);
-       END LOOP;
-END $$;
-NOTICE:  AUDIT: SESSION,33,1,FUNCTION,DO,,,"DO $$
-DECLARE
-       result RECORD;
-BEGIN
-       FOR result IN
-               SELECT id
-                 FROM test
-       LOOP
-               INSERT INTO test (id)
-                        VALUES (result.id + 100);
-       END LOOP;
-END $$;",<none>
-NOTICE:  AUDIT: SESSION,33,2,READ,SELECT,TABLE,public.test,"SELECT id
-                 FROM test",<none>
-CONTEXT:  PL/pgSQL function inline_code_block line 5 at FOR over SELECT rows
-NOTICE:  AUDIT: SESSION,33,3,WRITE,INSERT,TABLE,public.test,"INSERT INTO test (id)
-                        VALUES (result.id + 100)",",,"
-CONTEXT:  SQL statement "INSERT INTO test (id)
-                        VALUES (result.id + 100)"
-PL/pgSQL function inline_code_block line 9 at SQL statement
-NOTICE:  AUDIT: SESSION,33,4,WRITE,INSERT,TABLE,public.test,"INSERT INTO test (id)
-                        VALUES (result.id + 100)",",,"
-CONTEXT:  SQL statement "INSERT INTO test (id)
-                        VALUES (result.id + 100)"
-PL/pgSQL function inline_code_block line 9 at SQL statement
-NOTICE:  AUDIT: SESSION,33,5,WRITE,INSERT,TABLE,public.test,"INSERT INTO test (id)
-                        VALUES (result.id + 100)",",,"
-CONTEXT:  SQL statement "INSERT INTO test (id)
-                        VALUES (result.id + 100)"
-PL/pgSQL function inline_code_block line 9 at SQL statement
---
--- Test obfuscated dynamic sql for clean logging
-DO $$
-DECLARE
-       table_name TEXT = 'do_table';
-BEGIN
-       EXECUTE 'CREATE TABLE ' || table_name || ' ("weird name" INT)';
-       EXECUTE 'DROP table ' || table_name;
-END $$;
-NOTICE:  AUDIT: SESSION,34,1,FUNCTION,DO,,,"DO $$
-DECLARE
-       table_name TEXT = 'do_table';
-BEGIN
-       EXECUTE 'CREATE TABLE ' || table_name || ' (""weird name"" INT)';
-       EXECUTE 'DROP table ' || table_name;
-END $$;",<none>
-NOTICE:  AUDIT: SESSION,34,2,DDL,CREATE TABLE,TABLE,public.do_table,"CREATE TABLE do_table (""weird name"" INT)",<none>
-CONTEXT:  SQL statement "CREATE TABLE do_table ("weird name" INT)"
-PL/pgSQL function inline_code_block line 5 at EXECUTE statement
-NOTICE:  AUDIT: SESSION,34,3,DDL,DROP TABLE,TABLE,public.do_table,DROP table do_table,<none>
-CONTEXT:  SQL statement "DROP table do_table"
-PL/pgSQL function inline_code_block line 6 at EXECUTE statement
---
--- Generate an error and make sure the stack gets cleared
-DO $$
-BEGIN
-       CREATE TABLE bogus.test_block
-       (
-               id INT
-       );
-END $$;
-NOTICE:  AUDIT: SESSION,35,1,FUNCTION,DO,,,"DO $$
-BEGIN
-       CREATE TABLE bogus.test_block
-       (
-               id INT
-       );
-END $$;",<none>
-ERROR:  schema "bogus" does not exist
-LINE 1: CREATE TABLE bogus.test_block
-                     ^
-QUERY:  CREATE TABLE bogus.test_block
-       (
-               id INT
-       )
-CONTEXT:  PL/pgSQL function inline_code_block line 3 at SQL statement
---
--- Test alter table statements
-ALTER TABLE public.test
-       DROP COLUMN description ;
-NOTICE:  AUDIT: SESSION,36,1,DDL,ALTER TABLE,TABLE COLUMN,public.test.description,"ALTER TABLE public.test
-       DROP COLUMN description ;",<none>
-NOTICE:  AUDIT: SESSION,36,1,DDL,ALTER TABLE,TABLE,public.test,"ALTER TABLE public.test
-       DROP COLUMN description ;",<none>
-ALTER TABLE public.test
-       RENAME TO test2;
-NOTICE:  AUDIT: SESSION,37,1,DDL,ALTER TABLE,TABLE,public.test2,"ALTER TABLE public.test
-       RENAME TO test2;",<none>
-ALTER TABLE public.test2
-       SET SCHEMA test;
-NOTICE:  AUDIT: SESSION,38,1,DDL,ALTER TABLE,TABLE,test.test2,"ALTER TABLE public.test2
-       SET SCHEMA test;",<none>
-ALTER TABLE test.test2
-       ADD COLUMN description TEXT;
-NOTICE:  AUDIT: SESSION,39,1,DDL,ALTER TABLE,TABLE,test.test2,"ALTER TABLE test.test2
-       ADD COLUMN description TEXT;",<none>
-ALTER TABLE test.test2
-       DROP COLUMN description;
-NOTICE:  AUDIT: SESSION,40,1,DDL,ALTER TABLE,TABLE COLUMN,test.test2.description,"ALTER TABLE test.test2
-       DROP COLUMN description;",<none>
-NOTICE:  AUDIT: SESSION,40,1,DDL,ALTER TABLE,TABLE,test.test2,"ALTER TABLE test.test2
-       DROP COLUMN description;",<none>
-DROP TABLE test.test2;
-NOTICE:  AUDIT: SESSION,41,1,DDL,DROP TABLE,TABLE,test.test2,DROP TABLE test.test2;,<none>
-NOTICE:  AUDIT: SESSION,41,1,DDL,DROP TABLE,TABLE CONSTRAINT,test_pkey on test.test2,DROP TABLE test.test2;,<none>
-NOTICE:  AUDIT: SESSION,41,1,DDL,DROP TABLE,INDEX,test.test_pkey,DROP TABLE test.test2;,<none>
---
--- Test multiple statements with one semi-colon
-CREATE SCHEMA foo
-       CREATE TABLE foo.bar (id int)
-       CREATE TABLE foo.baz (id int);
-NOTICE:  AUDIT: SESSION,42,1,DDL,CREATE SCHEMA,SCHEMA,foo,"CREATE SCHEMA foo
-       CREATE TABLE foo.bar (id int)
-       CREATE TABLE foo.baz (id int);",<none>
-NOTICE:  AUDIT: SESSION,42,1,DDL,CREATE SCHEMA,TABLE,foo.bar,"CREATE SCHEMA foo
-       CREATE TABLE foo.bar (id int)
-       CREATE TABLE foo.baz (id int);",<none>
-NOTICE:  AUDIT: SESSION,42,1,DDL,CREATE SCHEMA,TABLE,foo.baz,"CREATE SCHEMA foo
-       CREATE TABLE foo.bar (id int)
-       CREATE TABLE foo.baz (id int);",<none>
---
--- Test aggregate
-CREATE FUNCTION public.int_add
-(
-       a INT,
-       b INT
-)
-       RETURNS INT LANGUAGE plpgsql AS $$
-BEGIN
-       return a + b;
-END $$;
-NOTICE:  AUDIT: SESSION,43,1,DDL,CREATE FUNCTION,FUNCTION,"public.int_add(integer,integer)","CREATE FUNCTION public.int_add
-(
-       a INT,
-       b INT
-)
-       RETURNS INT LANGUAGE plpgsql AS $$
-BEGIN
-       return a + b;
-END $$;",<none>
-SELECT int_add(1, 1);
-NOTICE:  AUDIT: SESSION,44,1,READ,SELECT,,,"SELECT int_add(1, 1);",<none>
-NOTICE:  AUDIT: SESSION,44,2,FUNCTION,EXECUTE,FUNCTION,public.int_add,"SELECT int_add(1, 1);",<none>
- int_add 
----------
-       2
-(1 row)
-
-CREATE AGGREGATE public.sum_test(INT) (SFUNC=public.int_add, STYPE=INT, INITCOND='0');
-NOTICE:  AUDIT: SESSION,45,1,DDL,CREATE AGGREGATE,AGGREGATE,public.sum_test(integer),"CREATE AGGREGATE public.sum_test(INT) (SFUNC=public.int_add, STYPE=INT, INITCOND='0');",<none>
-ALTER AGGREGATE public.sum_test(integer) RENAME TO sum_test2;
-NOTICE:  AUDIT: SESSION,46,1,DDL,ALTER AGGREGATE,AGGREGATE,public.sum_test2(integer),ALTER AGGREGATE public.sum_test(integer) RENAME TO sum_test2;,<none>
---
--- Test conversion
-CREATE CONVERSION public.conversion_test FOR 'SQL_ASCII' TO 'MULE_INTERNAL' FROM pg_catalog.ascii_to_mic;
-NOTICE:  AUDIT: SESSION,47,1,DDL,CREATE CONVERSION,CONVERSION,public.conversion_test,CREATE CONVERSION public.conversion_test FOR 'SQL_ASCII' TO 'MULE_INTERNAL' FROM pg_catalog.ascii_to_mic;,<none>
-ALTER CONVERSION public.conversion_test RENAME TO conversion_test2;
-NOTICE:  AUDIT: SESSION,48,1,DDL,ALTER CONVERSION,CONVERSION,public.conversion_test2,ALTER CONVERSION public.conversion_test RENAME TO conversion_test2;,<none>
---
--- Test create/alter/drop database
-CREATE DATABASE contrib_regression_pgaudit;
-NOTICE:  AUDIT: SESSION,49,1,DDL,CREATE DATABASE,,,CREATE DATABASE contrib_regression_pgaudit;,<none>
-ALTER DATABASE contrib_regression_pgaudit RENAME TO contrib_regression_pgaudit2;
-NOTICE:  AUDIT: SESSION,50,1,DDL,ALTER DATABASE,,,ALTER DATABASE contrib_regression_pgaudit RENAME TO contrib_regression_pgaudit2;,<none>
-DROP DATABASE contrib_regression_pgaudit2;
-NOTICE:  AUDIT: SESSION,51,1,DDL,DROP DATABASE,,,DROP DATABASE contrib_regression_pgaudit2;,<none>
---
--- Test that frees a memory context earlier than expected
-CREATE TABLE hoge
-(
-       id int
-);
-NOTICE:  AUDIT: SESSION,52,1,DDL,CREATE TABLE,TABLE,public.hoge,"CREATE TABLE hoge
-(
-       id int
-);",<none>
-CREATE FUNCTION test()
-       RETURNS INT AS $$
-DECLARE
-       cur1 cursor for select * from hoge;
-       tmp int;
-BEGIN
-       OPEN cur1;
-       FETCH cur1 into tmp;
-       RETURN tmp;
-END $$
-LANGUAGE plpgsql ;
-NOTICE:  AUDIT: SESSION,53,1,DDL,CREATE FUNCTION,FUNCTION,public.test(),"CREATE FUNCTION test()
-       RETURNS INT AS $$
-DECLARE
-       cur1 cursor for select * from hoge;
-       tmp int;
-BEGIN
-       OPEN cur1;
-       FETCH cur1 into tmp;
-       RETURN tmp;
-END $$
-LANGUAGE plpgsql ;",<none>
-SELECT test();
-NOTICE:  AUDIT: SESSION,54,1,READ,SELECT,,,SELECT test();,<none>
-NOTICE:  AUDIT: SESSION,54,2,FUNCTION,EXECUTE,FUNCTION,public.test,SELECT test();,<none>
-NOTICE:  AUDIT: SESSION,54,3,READ,SELECT,TABLE,public.hoge,select * from hoge,<none>
-CONTEXT:  PL/pgSQL function test() line 6 at OPEN
- test 
-------
-     
-(1 row)
-
---
--- Delete all rows then delete 1 row
-SET pg_audit.log = 'write';
-SET pg_audit.role = 'auditor';
-create table bar
-(
-       col int
-);
-grant delete
-   on bar
-   to auditor;
-insert into bar (col)
-                values (1);
-NOTICE:  AUDIT: SESSION,55,1,WRITE,INSERT,TABLE,public.bar,"insert into bar (col)
-                values (1);",<none>
-delete from bar;
-NOTICE:  AUDIT: OBJECT,56,1,WRITE,DELETE,TABLE,public.bar,delete from bar;,<none>
-NOTICE:  AUDIT: SESSION,56,1,WRITE,DELETE,TABLE,public.bar,delete from bar;,<none>
-insert into bar (col)
-                values (1);
-NOTICE:  AUDIT: SESSION,57,1,WRITE,INSERT,TABLE,public.bar,"insert into bar (col)
-                values (1);",<none>
-delete from bar
- where col = 1;
-NOTICE:  AUDIT: OBJECT,58,1,WRITE,DELETE,TABLE,public.bar,"delete from bar
- where col = 1;",<none>
-NOTICE:  AUDIT: SESSION,58,1,WRITE,DELETE,TABLE,public.bar,"delete from bar
- where col = 1;",<none>
-drop table bar;
---
--- Grant roles to each other
-SET pg_audit.log = 'role';
-GRANT user1 TO user2;
-NOTICE:  AUDIT: SESSION,59,1,ROLE,GRANT ROLE,,,GRANT user1 TO user2;,<none>
-REVOKE user1 FROM user2;
-NOTICE:  AUDIT: SESSION,60,1,ROLE,REVOKE ROLE,,,REVOKE user1 FROM user2;,<none>
--- Cleanup
--- Set client_min_messages up to warning to avoid noise
-SET client_min_messages = 'warning';
-ALTER ROLE :current_user RESET pg_audit.log;
-ALTER ROLE :current_user RESET pg_audit.log_level;
-DROP TABLE test.account_copy;
-DROP TABLE test.test_insert;
-DROP SCHEMA test;
-DROP TABLE foo.bar;
-DROP TABLE foo.baz;
-DROP SCHEMA foo;
-DROP TABLE hoge;
-DROP TABLE account;
-DROP TABLE account_role_map;
-DROP USER user2;
-DROP USER user1;
-DROP ROLE auditor;
-RESET client_min_messages;
diff --git a/contrib/pg_audit/pg_audit--1.0.sql b/contrib/pg_audit/pg_audit--1.0.sql
deleted file mode 100644 (file)
index 457f2c6..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-/* pg_audit/pg_audit--1.0.sql */
-
--- complain if script is sourced in psql, rather than via CREATE EXTENSION
-\echo Use "CREATE EXTENSION pg_audit" to load this file.\quit
-
-CREATE FUNCTION pg_audit_ddl_command_end()
-       RETURNS event_trigger
-       LANGUAGE C
-       AS 'MODULE_PATHNAME', 'pg_audit_ddl_command_end';
-
-CREATE EVENT TRIGGER pg_audit_ddl_command_end
-       ON ddl_command_end
-       EXECUTE PROCEDURE pg_audit_ddl_command_end();
-
-CREATE FUNCTION pg_audit_sql_drop()
-       RETURNS event_trigger
-       LANGUAGE C
-       AS 'MODULE_PATHNAME', 'pg_audit_sql_drop';
-
-CREATE EVENT TRIGGER pg_audit_sql_drop
-       ON sql_drop
-       EXECUTE PROCEDURE pg_audit_sql_drop();
diff --git a/contrib/pg_audit/pg_audit.c b/contrib/pg_audit/pg_audit.c
deleted file mode 100644 (file)
index ffe13eb..0000000
+++ /dev/null
@@ -1,1855 +0,0 @@
-/*------------------------------------------------------------------------------
- * pg_audit.c
- *
- * An audit logging extension for PostgreSQL. Provides detailed logging classes,
- * object level logging, and fully-qualified object names for all DML and DDL
- * statements where possible (See pgaudit.sgml for details).
- *
- * Copyright (c) 2014-2015, PostgreSQL Global Development Group
- *
- * IDENTIFICATION
- *               contrib/pg_audit/pg_audit.c
- *------------------------------------------------------------------------------
- */
-#include "postgres.h"
-
-#include "access/htup_details.h"
-#include "access/sysattr.h"
-#include "access/xact.h"
-#include "catalog/catalog.h"
-#include "catalog/objectaccess.h"
-#include "catalog/pg_class.h"
-#include "catalog/namespace.h"
-#include "commands/dbcommands.h"
-#include "catalog/pg_proc.h"
-#include "commands/event_trigger.h"
-#include "executor/executor.h"
-#include "executor/spi.h"
-#include "miscadmin.h"
-#include "libpq/auth.h"
-#include "nodes/nodes.h"
-#include "tcop/utility.h"
-#include "utils/acl.h"
-#include "utils/builtins.h"
-#include "utils/guc.h"
-#include "utils/lsyscache.h"
-#include "utils/memutils.h"
-#include "utils/rel.h"
-#include "utils/syscache.h"
-#include "utils/timestamp.h"
-
-PG_MODULE_MAGIC;
-
-void           _PG_init(void);
-
-PG_FUNCTION_INFO_V1(pg_audit_ddl_command_end);
-PG_FUNCTION_INFO_V1(pg_audit_sql_drop);
-
-/*
- * Log Classes
- *
- * pgAudit categorizes actions into classes (eg: DDL, FUNCTION calls, READ
- * queries, WRITE queries).  A GUC is provided for the administrator to
- * configure which class (or classes) of actions to include in the
- * audit log.  We track the currently active set of classes using
- * auditLogBitmap.
- */
-
-/* Bits within auditLogBitmap, defines the classes we understand */
-#define LOG_DDL                        (1 << 0)        /* CREATE/DROP/ALTER objects */
-#define LOG_FUNCTION   (1 << 1)        /* Functions and DO blocks */
-#define LOG_MISC               (1 << 2)        /* Statements not covered */
-#define LOG_READ               (1 << 3)        /* SELECTs */
-#define LOG_ROLE               (1 << 4)        /* GRANT/REVOKE, CREATE/ALTER/DROP ROLE */
-#define LOG_WRITE              (1 << 5)        /* INSERT, UPDATE, DELETE, TRUNCATE */
-
-#define LOG_NONE               0               /* nothing */
-#define LOG_ALL                        (0xFFFFFFFF)    /* All */
-
-/* GUC variable for pg_audit.log, which defines the classes to log. */
-char      *auditLog = NULL;
-
-/* Bitmap of classes selected */
-static int     auditLogBitmap = LOG_NONE;
-
-/*
- * String constants for log classes - used when processing tokens in the
- * pg_audit.log GUC.
- */
-#define CLASS_DDL                      "DDL"
-#define CLASS_FUNCTION         "FUNCTION"
-#define CLASS_MISC                     "MISC"
-#define CLASS_READ                     "READ"
-#define CLASS_ROLE                     "ROLE"
-#define CLASS_WRITE                    "WRITE"
-
-#define CLASS_NONE                     "NONE"
-#define CLASS_ALL                      "ALL"
-
-/*
- * GUC variable for pg_audit.log_catalog
- *
- * Administrators can choose to NOT log queries when all relations used in
- * the query are in pg_catalog.  Interactive sessions (eg: psql) can cause
- * a lot of noise in the logs which might be uninteresting.
- */
-bool           auditLogCatalog = true;
-
-/*
- * GUC variable for pg_audit.log_level
- *
- * Administrators can choose which log level the audit log is to be logged
- * at.  The default level is LOG, which goes into the server log but does
- * not go to the client.  Set to NOTICE in the regression tests.
- */
-char      *auditLogLevelString = NULL;
-int                    auditLogLevel = LOG;
-
-/*
- * GUC variable for pg_audit.log_parameter
- *
- * Administrators can choose if parameters passed into a statement are
- * included in the audit log.
- */
-bool           auditLogParameter = false;
-
-/*
- * GUC variable for pg_audit.log_relation
- *
- * Administrators can choose, in SESSION logging, to log each relation involved
- * in READ/WRITE class queries.  By default, SESSION logs include the query but
- * do not have a log entry for each relation.
- */
-bool           auditLogRelation = false;
-
-/*
- * GUC variable for pg_audit.log_statement_once
- *
- * Administrators can choose to have the statement run logged only once instead
- * of on every line.  By default, the statement is repeated on every line of
- * the audit log to facilitate searching, but this can cause the log to be
- * unnecessairly bloated in some environments.
- */
-bool           auditLogStatementOnce = false;
-
-/*
- * GUC variable for pg_audit.role
- *
- * Administrators can choose which role to base OBJECT auditing off of.
- * Object-level auditing uses the privileges which are granted to this role to
- * determine if a statement should be logged.
- */
-char      *auditRole = NULL;
-
-/*
- * String constants for the audit log fields.
- */
-
-/*
- * Audit type, which is responsbile for the log message
- */
-#define AUDIT_TYPE_OBJECT      "OBJECT"
-#define AUDIT_TYPE_SESSION     "SESSION"
-
-/*
- * Command, used for SELECT/DML and function calls.
- *
- * We hook into the executor, but we do not have access to the parsetree there.
- * Therefore we can't simply call CreateCommandTag() to get the command and have
- * to build it ourselves based on what information we do have.
- *
- * These should be updated if new commands are added to what the exectuor
- * currently handles.  Note that most of the interesting commands do not go
- * through the executor but rather ProcessUtility, where we have the parsetree.
- */
-#define COMMAND_SELECT                         "SELECT"
-#define COMMAND_INSERT                         "INSERT"
-#define COMMAND_UPDATE                         "UPDATE"
-#define COMMAND_DELETE                         "DELETE"
-#define COMMAND_EXECUTE                                "EXECUTE"
-#define COMMAND_UNKNOWN                                "UNKNOWN"
-
-/*
- * Object type, used for SELECT/DML statements and function calls.
- *
- * For relation objects, this is essentially relkind (though we do not have
- * access to a function which will just return a string given a relkind;
- * getRelationTypeDescription() comes close but is not public currently).
- *
- * We also handle functions, so it isn't quite as simple as just relkind.
- *
- * This should be kept consistent with what is returned from
- * pg_event_trigger_ddl_commands(), as that's what we use for DDL.
- */
-#define OBJECT_TYPE_TABLE                      "TABLE"
-#define OBJECT_TYPE_INDEX                      "INDEX"
-#define OBJECT_TYPE_SEQUENCE           "SEQUENCE"
-#define OBJECT_TYPE_TOASTVALUE         "TOAST TABLE"
-#define OBJECT_TYPE_VIEW                       "VIEW"
-#define OBJECT_TYPE_MATVIEW                    "MATERIALIZED VIEW"
-#define OBJECT_TYPE_COMPOSITE_TYPE     "COMPOSITE TYPE"
-#define OBJECT_TYPE_FOREIGN_TABLE      "FOREIGN TABLE"
-#define OBJECT_TYPE_FUNCTION           "FUNCTION"
-
-#define OBJECT_TYPE_UNKNOWN                    "UNKNOWN"
-
-/*
- * String constants for testing role commands.  Rename and drop role statements
- * are assigned the nodeTag T_RenameStmt and T_DropStmt respectively.  This is
- * not very useful for classification, so we resort to comparing strings
- * against the result of CreateCommandTag(parsetree).
- */
-#define COMMAND_ALTER_ROLE                     "ALTER ROLE"
-#define COMMAND_DROP_ROLE                      "DROP ROLE"
-
-/*
- * An AuditEvent represents an operation that potentially affects a single
- * object.  If a statement affects multiple objects then multiple AuditEvents
- * are created to represent them.
- */
-typedef struct
-{
-       int64           statementId;    /* Simple counter */
-       int64           substatementId; /* Simple counter */
-
-       LogStmtLevel logStmtLevel;      /* From GetCommandLogLevel when possible,
-                                                                * generated when not. */
-       NodeTag         commandTag;             /* same here */
-       const char *command;            /* same here */
-       const char *objectType;         /* From event trigger when possible, generated
-                                                                * when not. */
-       char       *objectName;         /* Fully qualified object identification */
-       const char *commandText;        /* sourceText / queryString */
-       ParamListInfo paramList;        /* QueryDesc/ProcessUtility parameters */
-
-       bool            granted;                /* Audit role has object permissions? */
-       bool            logged;                 /* Track if we have logged this event, used
-                                                                * post-ProcessUtility to make sure we log */
-       bool            statementLogged;        /* Track if we have logged the statement */
-} AuditEvent;
-
-/*
- * A simple FIFO queue to keep track of the current stack of audit events.
- */
-typedef struct AuditEventStackItem
-{
-       struct AuditEventStackItem *next;
-
-       AuditEvent      auditEvent;
-
-       int64           stackId;
-
-       MemoryContext contextAudit;
-       MemoryContextCallback contextCallback;
-} AuditEventStackItem;
-
-AuditEventStackItem *auditEventStack = NULL;
-
-/*
- * pgAudit runs queries of its own when using the event trigger system.
- *
- * Track when we are running a query and don't log it.
- */
-static bool internalStatement = false;
-
-/*
- * Track running total for statements and substatements and whether or not
- * anything has been logged since the current statement began.
- */
-static int64 statementTotal = 0;
-static int64 substatementTotal = 0;
-static int64 stackTotal = 0;
-
-static bool statementLogged = false;
-
-/*
- * Stack functions
- *
- * Audit events can go down to multiple levels so a stack is maintained to keep
- * track of them.
- */
-
-/*
- * Respond to callbacks registered with MemoryContextRegisterResetCallback().
- * Removes the event(s) off the stack that have become obsolete once the
- * MemoryContext has been freed.  The callback should always be freeing the top
- * of the stack, but the code is tolerant of out-of-order callbacks.
- */
-static void
-stack_free(void *stackFree)
-{
-       AuditEventStackItem *nextItem = auditEventStack;
-
-       /* Only process if the stack contains items */
-       while (nextItem != NULL)
-       {
-               /* Check if this item matches the item to be freed */
-               if (nextItem == (AuditEventStackItem *) stackFree)
-               {
-                       /* Move top of stack to the item after the freed item */
-                       auditEventStack = nextItem->next;
-
-                       /* If the stack is not empty */
-                       if (auditEventStack == NULL)
-                       {
-                               /*
-                                * Reset internal statement to false.  Normally this will be
-                                * reset but in case of an error it might be left set.
-                                */
-                               internalStatement = false;
-
-                               /*
-                                * Reset sub statement total so the next statement will start
-                                * from 1.
-                                */
-                               substatementTotal = 0;
-
-                               /*
-                                * Reset statement logged so that next statement will be
-                                * logged.
-                                */
-                               statementLogged = false;
-                       }
-
-                       return;
-               }
-
-               nextItem = nextItem->next;
-       }
-}
-
-/*
- * Push a new audit event onto the stack and create a new memory context to
- * store it.
- */
-static AuditEventStackItem *
-stack_push()
-{
-       MemoryContext contextAudit;
-       MemoryContext contextOld;
-       AuditEventStackItem *stackItem;
-
-       /*
-        * Create a new memory context to contain the stack item.  This will be
-        * free'd on stack_pop, or by our callback when the parent context is
-        * destroyed.
-        */
-       contextAudit = AllocSetContextCreate(CurrentMemoryContext,
-                                                                                "pg_audit stack context",
-                                                                                ALLOCSET_DEFAULT_MINSIZE,
-                                                                                ALLOCSET_DEFAULT_INITSIZE,
-                                                                                ALLOCSET_DEFAULT_MAXSIZE);
-
-       /* Save the old context to switch back to at the end */
-       contextOld = MemoryContextSwitchTo(contextAudit);
-
-       /* Create our new stack item in our context */
-       stackItem = palloc0(sizeof(AuditEventStackItem));
-       stackItem->contextAudit = contextAudit;
-       stackItem->stackId = ++stackTotal;
-
-       /*
-        * Setup a callback in case an error happens.  stack_free() will truncate
-        * the stack at this item.
-        */
-       stackItem->contextCallback.func = stack_free;
-       stackItem->contextCallback.arg = (void *) stackItem;
-       MemoryContextRegisterResetCallback(contextAudit,
-                                                                          &stackItem->contextCallback);
-
-       /* Push new item onto the stack */
-       if (auditEventStack != NULL)
-               stackItem->next = auditEventStack;
-       else
-               stackItem->next = NULL;
-
-       auditEventStack = stackItem;
-
-       MemoryContextSwitchTo(contextOld);
-
-       return stackItem;
-}
-
-/*
- * Pop an audit event from the stack by deleting the memory context that
- * contains it.  The callback to stack_free() does the actual pop.
- */
-static void
-stack_pop(int64 stackId)
-{
-       /* Make sure what we want to delete is at the top of the stack */
-       if (auditEventStack != NULL && auditEventStack->stackId == stackId)
-               MemoryContextDelete(auditEventStack->contextAudit);
-       else
-               elog(ERROR, "pg_audit stack item " INT64_FORMAT " not found on top - cannot pop",
-                        stackId);
-}
-
-/*
- * Check that an item is on the stack.  If not, an error will be raised since
- * this is a bad state to be in and it might mean audit records are being lost.
- */
-static void
-stack_valid(int64 stackId)
-{
-       AuditEventStackItem *nextItem = auditEventStack;
-
-       /* Look through the stack for the stack entry */
-       while (nextItem != NULL && nextItem->stackId != stackId)
-               nextItem = nextItem->next;
-
-       /* If we didn't find it, something went wrong. */
-       if (nextItem == NULL)
-               elog(ERROR, "pg_audit stack item " INT64_FORMAT " not found - top of stack is " INT64_FORMAT "",
-                        stackId,
-                        auditEventStack == NULL ? (int64) -1 : auditEventStack->stackId);
-}
-
-/*
- * Appends a properly quoted CSV field to StringInfo.
- */
-static void
-append_valid_csv(StringInfoData *buffer, const char *appendStr)
-{
-       const char *pChar;
-
-       /*
-        * If the append string is null then do nothing.  NULL fields are not
-        * quoted in CSV.
-        */
-       if (appendStr == NULL)
-               return;
-
-       /* Only format for CSV if appendStr contains: ", comma, \n, \r */
-       if (strstr(appendStr, ",") || strstr(appendStr, "\"") ||
-               strstr(appendStr, "\n") || strstr(appendStr, "\r"))
-       {
-               appendStringInfoCharMacro(buffer, '"');
-
-               for (pChar = appendStr; *pChar; pChar++)
-               {
-                       if (*pChar == '"')      /* double single quotes */
-                               appendStringInfoCharMacro(buffer, *pChar);
-
-                       appendStringInfoCharMacro(buffer, *pChar);
-               }
-
-               appendStringInfoCharMacro(buffer, '"');
-       }
-       /* Else just append */
-       else
-               appendStringInfoString(buffer, appendStr);
-}
-
-/*
- * Takes an AuditEvent, classifies it, then logs it if appropriate.
- *
- * Logging is decided based on if the statement is in one of the classes being
- * logged or if an object used has been marked for auditing.
- *
- * Objects are marked for auditing by the auditor role being granted access
- * to the object.  The kind of access (INSERT, UPDATE, etc) is also considered
- * and logging is only performed when the kind of access matches the granted
- * right on the object.
- *
- * This will need to be updated if new kinds of GRANTs are added.
- */
-static void
-log_audit_event(AuditEventStackItem *stackItem)
-{
-       /* By default, put everything in the MISC class. */
-       int                     class = LOG_MISC;
-       const char *className = CLASS_MISC;
-       MemoryContext contextOld;
-       StringInfoData auditStr;
-
-
-       /* Classify the statement using log stmt level and the command tag */
-       switch (stackItem->auditEvent.logStmtLevel)
-       {
-                       /* All mods go in WRITE class, except EXECUTE */
-               case LOGSTMT_MOD:
-                       className = CLASS_WRITE;
-                       class = LOG_WRITE;
-
-                       switch (stackItem->auditEvent.commandTag)
-                       {
-                                       /* Currently, only EXECUTE is different */
-                               case T_ExecuteStmt:
-                                       className = CLASS_MISC;
-                                       class = LOG_MISC;
-                                       break;
-                               default:
-                                       break;
-                       }
-                       break;
-
-                       /* These are DDL, unless they are ROLE */
-               case LOGSTMT_DDL:
-                       className = CLASS_DDL;
-                       class = LOG_DDL;
-
-                       /* Identify role statements */
-                       switch (stackItem->auditEvent.commandTag)
-                       {
-                                       /* We know these are all role statements */
-                               case T_GrantStmt:
-                               case T_GrantRoleStmt:
-                               case T_CreateRoleStmt:
-                               case T_DropRoleStmt:
-                               case T_AlterRoleStmt:
-                               case T_AlterRoleSetStmt:
-                                       className = CLASS_ROLE;
-                                       class = LOG_ROLE;
-                                       break;
-
-                                       /*
-                                        * Rename and Drop are general and therefore we have to do
-                                        * an additional check against the command string to see
-                                        * if they are role or regular DDL.
-                                        */
-                               case T_RenameStmt:
-                               case T_DropStmt:
-                                       if (pg_strcasecmp(stackItem->auditEvent.command,
-                                                                         COMMAND_ALTER_ROLE) == 0 ||
-                                               pg_strcasecmp(stackItem->auditEvent.command,
-                                                                         COMMAND_DROP_ROLE) == 0)
-                                       {
-                                               className = CLASS_ROLE;
-                                               class = LOG_ROLE;
-                                       }
-                                       break;
-
-                               default:
-                                       break;
-                       }
-                       break;
-
-                       /* Classify the rest */
-               case LOGSTMT_ALL:
-                       switch (stackItem->auditEvent.commandTag)
-                       {
-                                       /* READ statements */
-                               case T_CopyStmt:
-                               case T_SelectStmt:
-                               case T_PrepareStmt:
-                               case T_PlannedStmt:
-                                       className = CLASS_READ;
-                                       class = LOG_READ;
-                                       break;
-
-                                       /* FUNCTION statements */
-                               case T_DoStmt:
-                                       className = CLASS_FUNCTION;
-                                       class = LOG_FUNCTION;
-                                       break;
-
-                               default:
-                                       break;
-                       }
-                       break;
-
-               case LOGSTMT_NONE:
-                       break;
-       }
-
-       /*----------
-        * Only log the statement if:
-        *
-        * 1. If object was selected for audit logging (granted), or
-        * 2. The statement belongs to a class that is being logged
-        *
-        * If neither of these is true, return.
-        *----------
-        */
-       if (!stackItem->auditEvent.granted && !(auditLogBitmap & class))
-               return;
-
-       /*
-        * Use audit memory context in case something is not free'd while
-        * appending strings and parameters.
-        */
-       contextOld = MemoryContextSwitchTo(stackItem->contextAudit);
-
-       /* Set statement and substatement IDs */
-       if (stackItem->auditEvent.statementId == 0)
-       {
-               /* If nothing has been logged yet then create a new statement Id */
-               if (!statementLogged)
-               {
-                       statementTotal++;
-                       statementLogged = true;
-               }
-
-               stackItem->auditEvent.statementId = statementTotal;
-               stackItem->auditEvent.substatementId = ++substatementTotal;
-       }
-
-       /*
-        * Create the audit substring
-        *
-        * The type-of-audit-log and statement/substatement ID are handled below,
-        * this string is everything else.
-        */
-       initStringInfo(&auditStr);
-       append_valid_csv(&auditStr, stackItem->auditEvent.command);
-
-       appendStringInfoCharMacro(&auditStr, ',');
-       append_valid_csv(&auditStr, stackItem->auditEvent.objectType);
-
-       appendStringInfoCharMacro(&auditStr, ',');
-       append_valid_csv(&auditStr, stackItem->auditEvent.objectName);
-
-       /*
-        * If auditLogStatmentOnce is true, then only log the statement and
-        * parameters if they have not already been logged for this substatement.
-        */
-       appendStringInfoCharMacro(&auditStr, ',');
-       if (!stackItem->auditEvent.statementLogged || !auditLogStatementOnce)
-       {
-               append_valid_csv(&auditStr, stackItem->auditEvent.commandText);
-
-               appendStringInfoCharMacro(&auditStr, ',');
-
-               /* Handle parameter logging, if enabled. */
-               if (auditLogParameter)
-               {
-                       int                     paramIdx;
-                       int                     numParams;
-                       StringInfoData paramStrResult;
-                       ParamListInfo paramList = stackItem->auditEvent.paramList;
-
-                       numParams = paramList == NULL ? 0 : paramList->numParams;
-
-                       /* Create the param substring */
-                       initStringInfo(&paramStrResult);
-
-                       /* Iterate through all params */
-                       for (paramIdx = 0; paramList != NULL && paramIdx < numParams;
-                                paramIdx++)
-                       {
-                               ParamExternData *prm = &paramList->params[paramIdx];
-                               Oid                     typeOutput;
-                               bool            typeIsVarLena;
-                               char       *paramStr;
-
-                               /* Add a comma for each param */
-                               if (paramIdx != 0)
-                                       appendStringInfoCharMacro(&paramStrResult, ',');
-
-                               /* Skip if null or if oid is invalid */
-                               if (prm->isnull || !OidIsValid(prm->ptype))
-                                       continue;
-
-                               /* Output the string */
-                               getTypeOutputInfo(prm->ptype, &typeOutput, &typeIsVarLena);
-                               paramStr = OidOutputFunctionCall(typeOutput, prm->value);
-
-                               append_valid_csv(&paramStrResult, paramStr);
-                               pfree(paramStr);
-                       }
-
-                       if (numParams == 0)
-                               appendStringInfoString(&auditStr, "<none>");
-                       else
-                               append_valid_csv(&auditStr, paramStrResult.data);
-               }
-               else
-                       appendStringInfoString(&auditStr, "<not logged>");
-
-               stackItem->auditEvent.statementLogged = true;
-       }
-       else
-               /* we were asked to not log it */
-               appendStringInfoString(&auditStr,
-                                                          "<previously logged>,<previously logged>");
-
-       /*
-        * Log the audit entry.  Note: use of INT64_FORMAT here is bad for
-        * translatability, but we currently haven't got translation support in
-        * pg_audit anyway.
-        */
-       ereport(auditLogLevel,
-                       (errmsg("AUDIT: %s," INT64_FORMAT "," INT64_FORMAT ",%s,%s",
-                                       stackItem->auditEvent.granted ?
-                                       AUDIT_TYPE_OBJECT : AUDIT_TYPE_SESSION,
-                                       stackItem->auditEvent.statementId,
-                                       stackItem->auditEvent.substatementId,
-                                       className,
-                                       auditStr.data)));
-
-       stackItem->auditEvent.logged = true;
-
-       MemoryContextSwitchTo(contextOld);
-}
-
-/*
- * Check if the role or any inherited role has any permission in the mask.  The
- * public role is excluded from this check and superuser permissions are not
- * considered.
- */
-static bool
-audit_on_acl(Datum aclDatum,
-                        Oid auditOid,
-                        AclMode mask)
-{
-       bool            result = false;
-       Acl                *acl;
-       AclItem    *aclItemData;
-       int                     aclIndex;
-       int                     aclTotal;
-
-       /* Detoast column's ACL if necessary */
-       acl = DatumGetAclP(aclDatum);
-
-       /* Get the acl list and total number of items */
-       aclTotal = ACL_NUM(acl);
-       aclItemData = ACL_DAT(acl);
-
-       /* Check privileges granted directly to auditOid */
-       for (aclIndex = 0; aclIndex < aclTotal; aclIndex++)
-       {
-               AclItem    *aclItem = &aclItemData[aclIndex];
-
-               if (aclItem->ai_grantee == auditOid &&
-                       aclItem->ai_privs & mask)
-               {
-                       result = true;
-                       break;
-               }
-       }
-
-       /*
-        * Check privileges granted indirectly via role memberships. We do this in
-        * a separate pass to minimize expensive indirect membership tests.  In
-        * particular, it's worth testing whether a given ACL entry grants any
-        * privileges still of interest before we perform the has_privs_of_role
-        * test.
-        */
-       if (!result)
-       {
-               for (aclIndex = 0; aclIndex < aclTotal; aclIndex++)
-               {
-                       AclItem    *aclItem = &aclItemData[aclIndex];
-
-                       /* Don't test public or auditOid (it has been tested already) */
-                       if (aclItem->ai_grantee == ACL_ID_PUBLIC ||
-                               aclItem->ai_grantee == auditOid)
-                               continue;
-
-                       /*
-                        * Check that the role has the required privileges and that it is
-                        * inherited by auditOid.
-                        */
-                       if (aclItem->ai_privs & mask &&
-                               has_privs_of_role(auditOid, aclItem->ai_grantee))
-                       {
-                               result = true;
-                               break;
-                       }
-               }
-       }
-
-       /* if we have a detoasted copy, free it */
-       if (acl && (Pointer) acl != DatumGetPointer(aclDatum))
-               pfree(acl);
-
-       return result;
-}
-
-/*
- * Check if a role has any of the permissions in the mask on a relation.
- */
-static bool
-audit_on_relation(Oid relOid,
-                                 Oid auditOid,
-                                 AclMode mask)
-{
-       bool            result = false;
-       HeapTuple       tuple;
-       Datum           aclDatum;
-       bool            isNull;
-
-       /* Get relation tuple from pg_class */
-       tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(relOid));
-       if (!HeapTupleIsValid(tuple))
-               return false;
-
-       /* Get the relation's ACL */
-       aclDatum = SysCacheGetAttr(RELOID, tuple, Anum_pg_class_relacl,
-                                                          &isNull);
-
-       /* Only check if non-NULL, since NULL means no permissions */
-       if (!isNull)
-               result = audit_on_acl(aclDatum, auditOid, mask);
-
-       /* Free the relation tuple */
-       ReleaseSysCache(tuple);
-
-       return result;
-}
-
-/*
- * Check if a role has any of the permissions in the mask on a column.
- */
-static bool
-audit_on_attribute(Oid relOid,
-                                  AttrNumber attNum,
-                                  Oid auditOid,
-                                  AclMode mask)
-{
-       bool            result = false;
-       HeapTuple       attTuple;
-       Datum           aclDatum;
-       bool            isNull;
-
-       /* Get the attribute's ACL */
-       attTuple = SearchSysCache2(ATTNUM,
-                                                          ObjectIdGetDatum(relOid),
-                                                          Int16GetDatum(attNum));
-       if (!HeapTupleIsValid(attTuple))
-               return false;
-
-       /* Only consider attributes that have not been dropped */
-       if (!((Form_pg_attribute) GETSTRUCT(attTuple))->attisdropped)
-       {
-               aclDatum = SysCacheGetAttr(ATTNUM, attTuple, Anum_pg_attribute_attacl,
-                                                                  &isNull);
-
-               if (!isNull)
-                       result = audit_on_acl(aclDatum, auditOid, mask);
-       }
-
-       /* Free attribute */
-       ReleaseSysCache(attTuple);
-
-       return result;
-}
-
-/*
- * Check if a role has any of the permissions in the mask on a column in
- * the provided set.  If the set is empty, then all valid columns in the
- * relation will be tested.
- */
-static bool
-audit_on_any_attribute(Oid relOid,
-                                          Oid auditOid,
-                                          Bitmapset *attributeSet,
-                                          AclMode mode)
-{
-       bool            result = false;
-       AttrNumber      col;
-       Bitmapset  *tmpSet;
-
-       /* If bms is empty then check for any column match */
-       if (bms_is_empty(attributeSet))
-       {
-               HeapTuple       classTuple;
-               AttrNumber      nattrs;
-               AttrNumber      curr_att;
-
-               /* Get relation to determine total columns */
-               classTuple = SearchSysCache1(RELOID, ObjectIdGetDatum(relOid));
-
-               if (!HeapTupleIsValid(classTuple))
-                       return false;
-
-               nattrs = ((Form_pg_class) GETSTRUCT(classTuple))->relnatts;
-               ReleaseSysCache(classTuple);
-
-               /* Check each column */
-               for (curr_att = 1; curr_att <= nattrs; curr_att++)
-                       if (audit_on_attribute(relOid, curr_att, auditOid, mode))
-                               return true;
-       }
-
-       /* bms_first_member is destructive, so make a copy before using it. */
-       tmpSet = bms_copy(attributeSet);
-
-       /* Check each column */
-       while ((col = bms_first_member(tmpSet)) >= 0)
-       {
-               col += FirstLowInvalidHeapAttributeNumber;
-
-               if (col != InvalidAttrNumber &&
-                       audit_on_attribute(relOid, col, auditOid, mode))
-               {
-                       result = true;
-                       break;
-               }
-       }
-
-       bms_free(tmpSet);
-
-       return result;
-}
-
-/*
- * Create AuditEvents for SELECT/DML operations via executor permissions checks.
- */
-static void
-log_select_dml(Oid auditOid, List *rangeTabls)
-{
-       ListCell   *lr;
-       bool            first = true;
-       bool            found = false;
-
-       /* Do not log if this is an internal statement */
-       if (internalStatement)
-               return;
-
-       foreach(lr, rangeTabls)
-       {
-               Oid                     relOid;
-               Relation        rel;
-               RangeTblEntry *rte = lfirst(lr);
-
-               /* We only care about tables, and can ignore subqueries etc. */
-               if (rte->rtekind != RTE_RELATION)
-                       continue;
-
-               found = true;
-
-               /*
-                * If we are not logging all-catalog queries (auditLogCatalog is
-                * false) then filter out any system relations here.
-                */
-               relOid = rte->relid;
-               rel = relation_open(relOid, NoLock);
-
-               if (!auditLogCatalog && IsSystemNamespace(RelationGetNamespace(rel)))
-               {
-                       relation_close(rel, NoLock);
-                       continue;
-               }
-
-               /*
-                * Default is that this was not through a grant, to support session
-                * logging.  Will be updated below if a grant is found.
-                */
-               auditEventStack->auditEvent.granted = false;
-
-               /*
-                * If this is the first RTE then session log unless auditLogRelation
-                * is set.
-                */
-               if (first && !auditLogRelation)
-               {
-                       log_audit_event(auditEventStack);
-
-                       first = false;
-               }
-
-               /*
-                * We don't have access to the parsetree here, so we have to generate
-                * the node type, object type, and command tag by decoding
-                * rte->requiredPerms and rte->relkind.
-                */
-               if (rte->requiredPerms & ACL_INSERT)
-               {
-                       auditEventStack->auditEvent.logStmtLevel = LOGSTMT_MOD;
-                       auditEventStack->auditEvent.commandTag = T_InsertStmt;
-                       auditEventStack->auditEvent.command = COMMAND_INSERT;
-               }
-               else if (rte->requiredPerms & ACL_UPDATE)
-               {
-                       auditEventStack->auditEvent.logStmtLevel = LOGSTMT_MOD;
-                       auditEventStack->auditEvent.commandTag = T_UpdateStmt;
-                       auditEventStack->auditEvent.command = COMMAND_UPDATE;
-               }
-               else if (rte->requiredPerms & ACL_DELETE)
-               {
-                       auditEventStack->auditEvent.logStmtLevel = LOGSTMT_MOD;
-                       auditEventStack->auditEvent.commandTag = T_DeleteStmt;
-                       auditEventStack->auditEvent.command = COMMAND_DELETE;
-               }
-               else if (rte->requiredPerms & ACL_SELECT)
-               {
-                       auditEventStack->auditEvent.logStmtLevel = LOGSTMT_ALL;
-                       auditEventStack->auditEvent.commandTag = T_SelectStmt;
-                       auditEventStack->auditEvent.command = COMMAND_SELECT;
-               }
-               else
-               {
-                       auditEventStack->auditEvent.logStmtLevel = LOGSTMT_ALL;
-                       auditEventStack->auditEvent.commandTag = T_Invalid;
-                       auditEventStack->auditEvent.command = COMMAND_UNKNOWN;
-               }
-
-               /* Use the relation type to assign object type */
-               switch (rte->relkind)
-               {
-                       case RELKIND_RELATION:
-                               auditEventStack->auditEvent.objectType = OBJECT_TYPE_TABLE;
-                               break;
-
-                       case RELKIND_INDEX:
-                               auditEventStack->auditEvent.objectType = OBJECT_TYPE_INDEX;
-                               break;
-
-                       case RELKIND_SEQUENCE:
-                               auditEventStack->auditEvent.objectType = OBJECT_TYPE_SEQUENCE;
-                               break;
-
-                       case RELKIND_TOASTVALUE:
-                               auditEventStack->auditEvent.objectType = OBJECT_TYPE_TOASTVALUE;
-                               break;
-
-                       case RELKIND_VIEW:
-                               auditEventStack->auditEvent.objectType = OBJECT_TYPE_VIEW;
-                               break;
-
-                       case RELKIND_COMPOSITE_TYPE:
-                               auditEventStack->auditEvent.objectType = OBJECT_TYPE_COMPOSITE_TYPE;
-                               break;
-
-                       case RELKIND_FOREIGN_TABLE:
-                               auditEventStack->auditEvent.objectType = OBJECT_TYPE_FOREIGN_TABLE;
-                               break;
-
-                       case RELKIND_MATVIEW:
-                               auditEventStack->auditEvent.objectType = OBJECT_TYPE_MATVIEW;
-                               break;
-
-                       default:
-                               auditEventStack->auditEvent.objectType = OBJECT_TYPE_UNKNOWN;
-                               break;
-               }
-
-               /* Get a copy of the relation name and assign it to object name */
-               auditEventStack->auditEvent.objectName =
-                       quote_qualified_identifier(get_namespace_name(
-                                                                                                 RelationGetNamespace(rel)),
-                                                                          RelationGetRelationName(rel));
-               relation_close(rel, NoLock);
-
-               /* Perform object auditing only if the audit role is valid */
-               if (auditOid != InvalidOid)
-               {
-                       AclMode         auditPerms = (ACL_SELECT | ACL_UPDATE | ACL_INSERT | ACL_DELETE) & rte->requiredPerms;
-
-                       /*
-                        * If any of the required permissions for the relation are granted
-                        * to the audit role then audit the relation
-                        */
-                       if (audit_on_relation(relOid, auditOid, auditPerms))
-                               auditEventStack->auditEvent.granted = true;
-
-                       /*
-                        * Else check if the audit role has column-level permissions for
-                        * select, insert, or update.
-                        */
-                       else if (auditPerms != 0)
-                       {
-                               /*
-                                * Check the select columns
-                                */
-                               if (auditPerms & ACL_SELECT)
-                                       auditEventStack->auditEvent.granted =
-                                               audit_on_any_attribute(relOid, auditOid,
-                                                                                          rte->selectedCols,
-                                                                                          ACL_SELECT);
-
-                               /*
-                                * Check the insert columns
-                                */
-                               if (!auditEventStack->auditEvent.granted &&
-                                       auditPerms & ACL_INSERT)
-                                       auditEventStack->auditEvent.granted =
-                                               audit_on_any_attribute(relOid, auditOid,
-                                                                                          rte->insertedCols,
-                                                                                          auditPerms);
-
-                               /*
-                                * Check the update columns
-                                */
-                               if (!auditEventStack->auditEvent.granted &&
-                                       auditPerms & ACL_UPDATE)
-                                       auditEventStack->auditEvent.granted =
-                                               audit_on_any_attribute(relOid, auditOid,
-                                                                                          rte->updatedCols,
-                                                                                          auditPerms);
-                       }
-               }
-
-               /* Do relation level logging if a grant was found */
-               if (auditEventStack->auditEvent.granted)
-               {
-                       auditEventStack->auditEvent.logged = false;
-                       log_audit_event(auditEventStack);
-               }
-
-               /* Do relation level logging if auditLogRelation is set */
-               if (auditLogRelation)
-               {
-                       auditEventStack->auditEvent.logged = false;
-                       auditEventStack->auditEvent.granted = false;
-                       log_audit_event(auditEventStack);
-               }
-
-               pfree(auditEventStack->auditEvent.objectName);
-       }
-
-       /*
-        * If no tables were found that means that RangeTbls was empty or all
-        * relations were in the system schema.  In that case still log a session
-        * record.
-        */
-       if (!found)
-       {
-               auditEventStack->auditEvent.granted = false;
-               auditEventStack->auditEvent.logged = false;
-
-               log_audit_event(auditEventStack);
-       }
-}
-
-/*
- * Create AuditEvents for non-catalog function execution, as detected by
- * log_object_access() below.
- */
-static void
-log_function_execute(Oid objectId)
-{
-       HeapTuple       proctup;
-       Form_pg_proc proc;
-       AuditEventStackItem *stackItem;
-
-       /* Get info about the function. */
-       proctup = SearchSysCache1(PROCOID, ObjectIdGetDatum(objectId));
-
-       if (!proctup)
-               elog(ERROR, "cache lookup failed for function %u", objectId);
-
-       proc = (Form_pg_proc) GETSTRUCT(proctup);
-
-       /*
-        * Logging execution of all pg_catalog functions would make the log
-        * unusably noisy.
-        */
-       if (IsSystemNamespace(proc->pronamespace))
-       {
-               ReleaseSysCache(proctup);
-               return;
-       }
-
-       /* Push audit event onto the stack */
-       stackItem = stack_push();
-
-       /* Generate the fully-qualified function name. */
-       stackItem->auditEvent.objectName =
-               quote_qualified_identifier(get_namespace_name(proc->pronamespace),
-                                                                  NameStr(proc->proname));
-       ReleaseSysCache(proctup);
-
-       /* Log the function call */
-       stackItem->auditEvent.logStmtLevel = LOGSTMT_ALL;
-       stackItem->auditEvent.commandTag = T_DoStmt;
-       stackItem->auditEvent.command = COMMAND_EXECUTE;
-       stackItem->auditEvent.objectType = OBJECT_TYPE_FUNCTION;
-       stackItem->auditEvent.commandText = stackItem->next->auditEvent.commandText;
-
-       log_audit_event(stackItem);
-
-       /* Pop audit event from the stack */
-       stack_pop(stackItem->stackId);
-}
-
-/*
- * Hook functions
- */
-static ExecutorCheckPerms_hook_type next_ExecutorCheckPerms_hook = NULL;
-static ProcessUtility_hook_type next_ProcessUtility_hook = NULL;
-static object_access_hook_type next_object_access_hook = NULL;
-static ExecutorStart_hook_type next_ExecutorStart_hook = NULL;
-
-/*
- * Hook ExecutorStart to get the query text and basic command type for queries
- * that do not contain a table and so can't be idenitified accurately in
- * ExecutorCheckPerms.
- */
-static void
-pg_audit_ExecutorStart_hook(QueryDesc *queryDesc, int eflags)
-{
-       AuditEventStackItem *stackItem = NULL;
-
-       if (!internalStatement)
-       {
-               /* Push the audit even onto the stack */
-               stackItem = stack_push();
-
-               /* Initialize command using queryDesc->operation */
-               switch (queryDesc->operation)
-               {
-                       case CMD_SELECT:
-                               stackItem->auditEvent.logStmtLevel = LOGSTMT_ALL;
-                               stackItem->auditEvent.commandTag = T_SelectStmt;
-                               stackItem->auditEvent.command = COMMAND_SELECT;
-                               break;
-
-                       case CMD_INSERT:
-                               stackItem->auditEvent.logStmtLevel = LOGSTMT_MOD;
-                               stackItem->auditEvent.commandTag = T_InsertStmt;
-                               stackItem->auditEvent.command = COMMAND_INSERT;
-                               break;
-
-                       case CMD_UPDATE:
-                               stackItem->auditEvent.logStmtLevel = LOGSTMT_MOD;
-                               stackItem->auditEvent.commandTag = T_UpdateStmt;
-                               stackItem->auditEvent.command = COMMAND_UPDATE;
-                               break;
-
-                       case CMD_DELETE:
-                               stackItem->auditEvent.logStmtLevel = LOGSTMT_MOD;
-                               stackItem->auditEvent.commandTag = T_DeleteStmt;
-                               stackItem->auditEvent.command = COMMAND_DELETE;
-                               break;
-
-                       default:
-                               stackItem->auditEvent.logStmtLevel = LOGSTMT_ALL;
-                               stackItem->auditEvent.commandTag = T_Invalid;
-                               stackItem->auditEvent.command = COMMAND_UNKNOWN;
-                               break;
-               }
-
-               /* Initialize the audit event */
-               stackItem->auditEvent.commandText = queryDesc->sourceText;
-               stackItem->auditEvent.paramList = queryDesc->params;
-       }
-
-       /* Call the previous hook or standard function */
-       if (next_ExecutorStart_hook)
-               next_ExecutorStart_hook(queryDesc, eflags);
-       else
-               standard_ExecutorStart(queryDesc, eflags);
-
-       /*
-        * Move the stack memory context to the query memory context.  This needs
-        * to be done here because the query context does not exist before the
-        * call to standard_ExecutorStart() but the stack item is required by
-        * pg_audit_ExecutorCheckPerms_hook() which is called during
-        * standard_ExecutorStart().
-        */
-       if (stackItem)
-               MemoryContextSetParent(stackItem->contextAudit,
-                                                          queryDesc->estate->es_query_cxt);
-}
-
-/*
- * Hook ExecutorCheckPerms to do session and object auditing for DML.
- */
-static bool
-pg_audit_ExecutorCheckPerms_hook(List *rangeTabls, bool abort)
-{
-       Oid                     auditOid;
-
-       /* Get the audit oid if the role exists */
-       auditOid = get_role_oid(auditRole, true);
-
-       /* Log DML if the audit role is valid or session logging is enabled */
-       if ((auditOid != InvalidOid || auditLogBitmap != 0) &&
-               !IsAbortedTransactionBlockState())
-               log_select_dml(auditOid, rangeTabls);
-
-       /* Call the next hook function */
-       if (next_ExecutorCheckPerms_hook &&
-               !(*next_ExecutorCheckPerms_hook) (rangeTabls, abort))
-               return false;
-
-       return true;
-}
-
-/*
- * Hook ProcessUtility to do session auditing for DDL and utility commands.
- */
-static void
-pg_audit_ProcessUtility_hook(Node *parsetree,
-                                                        const char *queryString,
-                                                        ProcessUtilityContext context,
-                                                        ParamListInfo params,
-                                                        DestReceiver *dest,
-                                                        char *completionTag)
-{
-       AuditEventStackItem *stackItem = NULL;
-       int64           stackId = 0;
-
-       /*
-        * Don't audit substatements.  All the substatements we care about should
-        * be covered by the event triggers.
-        */
-       if (context <= PROCESS_UTILITY_QUERY && !IsAbortedTransactionBlockState())
-       {
-               /* Process top level utility statement */
-               if (context == PROCESS_UTILITY_TOPLEVEL)
-               {
-                       if (auditEventStack != NULL)
-                               elog(ERROR, "pg_audit stack is not empty");
-
-                       stackItem = stack_push();
-                       stackItem->auditEvent.paramList = params;
-               }
-               else
-                       stackItem = stack_push();
-
-               stackId = stackItem->stackId;
-               stackItem->auditEvent.logStmtLevel = GetCommandLogLevel(parsetree);
-               stackItem->auditEvent.commandTag = nodeTag(parsetree);
-               stackItem->auditEvent.command = CreateCommandTag(parsetree);
-               stackItem->auditEvent.commandText = queryString;
-
-               /*
-                * If this is a DO block log it before calling the next ProcessUtility
-                * hook.
-                */
-               if (auditLogBitmap & LOG_FUNCTION &&
-                       stackItem->auditEvent.commandTag == T_DoStmt &&
-                       !IsAbortedTransactionBlockState())
-                       log_audit_event(stackItem);
-       }
-
-       /* Call the standard process utility chain. */
-       if (next_ProcessUtility_hook)
-               (*next_ProcessUtility_hook) (parsetree, queryString, context,
-                                                                        params, dest, completionTag);
-       else
-               standard_ProcessUtility(parsetree, queryString, context,
-                                                               params, dest, completionTag);
-
-       /*
-        * Process the audit event if there is one.  Also check that this event
-        * was not popped off the stack by a memory context being free'd
-        * elsewhere.
-        */
-       if (stackItem && !IsAbortedTransactionBlockState())
-       {
-               /*
-                * Make sure the item we want to log is still on the stack - if not
-                * then something has gone wrong and an error will be raised.
-                */
-               stack_valid(stackId);
-
-               /*
-                * Log the utility command if logging is on, the command has not
-                * already been logged by another hook, and the transaction is not
-                * aborted.
-                */
-               if (auditLogBitmap != 0 && !stackItem->auditEvent.logged)
-                       log_audit_event(stackItem);
-       }
-}
-
-/*
- * Hook object_access_hook to provide fully-qualified object names for function
- * calls.
- */
-static void
-pg_audit_object_access_hook(ObjectAccessType access,
-                                                       Oid classId,
-                                                       Oid objectId,
-                                                       int subId,
-                                                       void *arg)
-{
-       if (auditLogBitmap & LOG_FUNCTION && access == OAT_FUNCTION_EXECUTE &&
-               auditEventStack && !IsAbortedTransactionBlockState())
-               log_function_execute(objectId);
-
-       if (next_object_access_hook)
-               (*next_object_access_hook) (access, classId, objectId, subId, arg);
-}
-
-/*
- * Event trigger functions
- */
-
-/*
- * Supply additional data for (non drop) statements that have event trigger
- * support and can be deparsed.
- *
- * Drop statements are handled below through the older sql_drop event trigger.
- */
-Datum
-pg_audit_ddl_command_end(PG_FUNCTION_ARGS)
-{
-       EventTriggerData *eventData;
-       int                     result,
-                               row;
-       TupleDesc       spiTupDesc;
-       const char *query;
-       MemoryContext contextQuery;
-       MemoryContext contextOld;
-
-       /* Continue only if session DDL logging is enabled */
-       if (~auditLogBitmap & LOG_DDL)
-               PG_RETURN_NULL();
-
-       /* Be sure the module was loaded */
-       if (!auditEventStack)
-               elog(ERROR, "pg_audit not loaded before call to "
-                        "pg_audit_ddl_command_end()");
-
-       /* This is an internal statement - do not log it */
-       internalStatement = true;
-
-       /* Make sure the fuction was fired as a trigger */
-       if (!CALLED_AS_EVENT_TRIGGER(fcinfo))
-               elog(ERROR, "not fired by event trigger manager");
-
-       /* Switch memory context for query */
-       contextQuery = AllocSetContextCreate(
-                                                                                CurrentMemoryContext,
-                                                  "pg_audit_func_ddl_command_end temporary context",
-                                                                                ALLOCSET_DEFAULT_MINSIZE,
-                                                                                ALLOCSET_DEFAULT_INITSIZE,
-                                                                                ALLOCSET_DEFAULT_MAXSIZE);
-       contextOld = MemoryContextSwitchTo(contextQuery);
-
-       /* Get information about triggered events */
-       eventData = (EventTriggerData *) fcinfo->context;
-
-       auditEventStack->auditEvent.logStmtLevel =
-               GetCommandLogLevel(eventData->parsetree);
-       auditEventStack->auditEvent.commandTag =
-               nodeTag(eventData->parsetree);
-       auditEventStack->auditEvent.command =
-               CreateCommandTag(eventData->parsetree);
-
-       /* Return objects affected by the (non drop) DDL statement */
-       query = "SELECT UPPER(object_type), object_identity\n"
-               "  FROM pg_event_trigger_ddl_commands()";
-
-       /* Attempt to connect */
-       result = SPI_connect();
-       if (result < 0)
-               elog(ERROR, "pg_audit_ddl_command_end: SPI_connect returned %d",
-                        result);
-
-       /* Execute the query */
-       result = SPI_execute(query, true, 0);
-       if (result != SPI_OK_SELECT)
-               elog(ERROR, "pg_audit_ddl_command_end: SPI_execute returned %d",
-                        result);
-
-       /* Iterate returned rows */
-       spiTupDesc = SPI_tuptable->tupdesc;
-       for (row = 0; row < SPI_processed; row++)
-       {
-               HeapTuple       spiTuple;
-
-               spiTuple = SPI_tuptable->vals[row];
-
-               /* Supply object name and type for audit event */
-               auditEventStack->auditEvent.objectType =
-                       SPI_getvalue(spiTuple, spiTupDesc, 1);
-               auditEventStack->auditEvent.objectName =
-                       SPI_getvalue(spiTuple, spiTupDesc, 2);
-
-               /* Log the audit event */
-               log_audit_event(auditEventStack);
-       }
-
-       /* Complete the query */
-       SPI_finish();
-
-       MemoryContextSwitchTo(contextOld);
-       MemoryContextDelete(contextQuery);
-
-       /* No longer in an internal statement */
-       internalStatement = false;
-
-       PG_RETURN_NULL();
-}
-
-/*
- * Supply additional data for drop statements that have event trigger support.
- */
-Datum
-pg_audit_sql_drop(PG_FUNCTION_ARGS)
-{
-       int                     result,
-                               row;
-       TupleDesc       spiTupDesc;
-       const char *query;
-       MemoryContext contextQuery;
-       MemoryContext contextOld;
-
-       if (~auditLogBitmap & LOG_DDL)
-               PG_RETURN_NULL();
-
-       /* Be sure the module was loaded */
-       if (!auditEventStack)
-               elog(ERROR, "pg_audit not loaded before call to "
-                        "pg_audit_sql_drop()");
-
-       /* This is an internal statement - do not log it */
-       internalStatement = true;
-
-       /* Make sure the fuction was fired as a trigger */
-       if (!CALLED_AS_EVENT_TRIGGER(fcinfo))
-               elog(ERROR, "not fired by event trigger manager");
-
-       /* Switch memory context for the query */
-       contextQuery = AllocSetContextCreate(
-                                                                                CurrentMemoryContext,
-                                                  "pg_audit_func_ddl_command_end temporary context",
-                                                                                ALLOCSET_DEFAULT_MINSIZE,
-                                                                                ALLOCSET_DEFAULT_INITSIZE,
-                                                                                ALLOCSET_DEFAULT_MAXSIZE);
-       contextOld = MemoryContextSwitchTo(contextQuery);
-
-       /* Return objects affected by the drop statement */
-       query = "SELECT UPPER(object_type),\n"
-               "       object_identity\n"
-               "  FROM pg_event_trigger_dropped_objects()\n"
-               " WHERE lower(object_type) <> 'type'\n"
-               "   AND schema_name <> 'pg_toast'";
-
-       /* Attempt to connect */
-       result = SPI_connect();
-       if (result < 0)
-               elog(ERROR, "pg_audit_ddl_drop: SPI_connect returned %d",
-                        result);
-
-       /* Execute the query */
-       result = SPI_execute(query, true, 0);
-       if (result != SPI_OK_SELECT)
-               elog(ERROR, "pg_audit_ddl_drop: SPI_execute returned %d",
-                        result);
-
-       /* Iterate returned rows */
-       spiTupDesc = SPI_tuptable->tupdesc;
-       for (row = 0; row < SPI_processed; row++)
-       {
-               HeapTuple       spiTuple;
-
-               spiTuple = SPI_tuptable->vals[row];
-
-               auditEventStack->auditEvent.objectType =
-                       SPI_getvalue(spiTuple, spiTupDesc, 1);
-               auditEventStack->auditEvent.objectName =
-                       SPI_getvalue(spiTuple, spiTupDesc, 2);
-
-               log_audit_event(auditEventStack);
-       }
-
-       /* Complete the query */
-       SPI_finish();
-
-       MemoryContextSwitchTo(contextOld);
-       MemoryContextDelete(contextQuery);
-
-       /* No longer in an internal statement */
-       internalStatement = false;
-
-       PG_RETURN_NULL();
-}
-
-/*
- * GUC check and assign functions
- */
-
-/*
- * Take a pg_audit.log value such as "read, write, dml", verify that each of the
- * comma-separated tokens corresponds to a LogClass value, and convert them into
- * a bitmap that log_audit_event can check.
- */
-static bool
-check_pg_audit_log(char **newVal, void **extra, GucSource source)
-{
-       List       *flagRawList;
-       char       *rawVal;
-       ListCell   *lt;
-       int                *flags;
-
-       /* Make sure newval is a comma-separated list of tokens. */
-       rawVal = pstrdup(*newVal);
-       if (!SplitIdentifierString(rawVal, ',', &flagRawList))
-       {
-               GUC_check_errdetail("List syntax is invalid");
-               list_free(flagRawList);
-               pfree(rawVal);
-               return false;
-       }
-
-       /*
-        * Check that we recognise each token, and add it to the bitmap we're
-        * building up in a newly-allocated int *f.
-        */
-       if (!(flags = (int *) malloc(sizeof(int))))
-               return false;
-
-       *flags = 0;
-
-       foreach(lt, flagRawList)
-       {
-               char       *token = (char *) lfirst(lt);
-               bool            subtract = false;
-               int                     class;
-
-               /* If token is preceded by -, then the token is subtractive */
-               if (token[0] == '-')
-               {
-                       token++;
-                       subtract = true;
-               }
-
-               /* Test each token */
-               if (pg_strcasecmp(token, CLASS_NONE) == 0)
-                       class = LOG_NONE;
-               else if (pg_strcasecmp(token, CLASS_ALL) == 0)
-                       class = LOG_ALL;
-               else if (pg_strcasecmp(token, CLASS_DDL) == 0)
-                       class = LOG_DDL;
-               else if (pg_strcasecmp(token, CLASS_FUNCTION) == 0)
-                       class = LOG_FUNCTION;
-               else if (pg_strcasecmp(token, CLASS_MISC) == 0)
-                       class = LOG_MISC;
-               else if (pg_strcasecmp(token, CLASS_READ) == 0)
-                       class = LOG_READ;
-               else if (pg_strcasecmp(token, CLASS_ROLE) == 0)
-                       class = LOG_ROLE;
-               else if (pg_strcasecmp(token, CLASS_WRITE) == 0)
-                       class = LOG_WRITE;
-               else
-               {
-                       free(flags);
-                       pfree(rawVal);
-                       list_free(flagRawList);
-                       return false;
-               }
-
-               /* Add or subtract class bits from the log bitmap */
-               if (subtract)
-                       *flags &= ~class;
-               else
-                       *flags |= class;
-       }
-
-       pfree(rawVal);
-       list_free(flagRawList);
-
-       /* Store the bitmap for assign_pg_audit_log */
-       *extra = flags;
-
-       return true;
-}
-
-/*
- * Set pg_audit_log from extra (ignoring newVal, which has already been
- * converted to a bitmap above). Note that extra may not be set if the
- * assignment is to be suppressed.
- */
-static void
-assign_pg_audit_log(const char *newVal, void *extra)
-{
-       if (extra)
-               auditLogBitmap = *(int *) extra;
-}
-
-/*
- * Take a pg_audit.log_level value such as "debug" and check that is is valid.
- * Return the enum value so it does not have to be checked again in the assign
- * function.
- */
-static bool
-check_pg_audit_log_level(char **newVal, void **extra, GucSource source)
-{
-       int                *logLevel;
-
-       /* Allocate memory to store the log level */
-       if (!(logLevel = (int *) malloc(sizeof(int))))
-               return false;
-
-       /* Find the log level enum */
-       if (pg_strcasecmp(*newVal, "debug") == 0)
-               *logLevel = DEBUG2;
-       else if (pg_strcasecmp(*newVal, "debug5") == 0)
-               *logLevel = DEBUG5;
-       else if (pg_strcasecmp(*newVal, "debug4") == 0)
-               *logLevel = DEBUG4;
-       else if (pg_strcasecmp(*newVal, "debug3") == 0)
-               *logLevel = DEBUG3;
-       else if (pg_strcasecmp(*newVal, "debug2") == 0)
-               *logLevel = DEBUG2;
-       else if (pg_strcasecmp(*newVal, "debug1") == 0)
-               *logLevel = DEBUG1;
-       else if (pg_strcasecmp(*newVal, "info") == 0)
-               *logLevel = INFO;
-       else if (pg_strcasecmp(*newVal, "notice") == 0)
-               *logLevel = NOTICE;
-       else if (pg_strcasecmp(*newVal, "warning") == 0)
-               *logLevel = WARNING;
-       else if (pg_strcasecmp(*newVal, "error") == 0)
-               *logLevel = ERROR;
-       else if (pg_strcasecmp(*newVal, "log") == 0)
-               *logLevel = LOG;
-       else if (pg_strcasecmp(*newVal, "fatal") == 0)
-               *logLevel = FATAL;
-       else if (pg_strcasecmp(*newVal, "panic") == 0)
-               *logLevel = PANIC;
-
-       /* Error if the log level enum is not found */
-       else
-       {
-               free(logLevel);
-               return false;
-       }
-
-       /* Return the log level enum */
-       *extra = logLevel;
-
-       return true;
-}
-
-/*
- * Set pg_audit_log from extra (ignoring newVal, which has already been
- * converted to an enum above). Note that extra may not be set if the
- * assignment is to be suppressed.
- */
-static void
-assign_pg_audit_log_level(const char *newVal, void *extra)
-{
-       if (extra)
-               auditLogLevel = *(int *) extra;
-}
-
-/*
- * Define GUC variables and install hooks upon module load.
- */
-void
-_PG_init(void)
-{
-       /* Define pg_audit.log */
-       DefineCustomStringVariable(
-                                                          "pg_audit.log",
-
-        "Specifies which classes of statements will be logged by session audit "
-                "logging. Multiple classes can be provided using a comma-separated "
-                 "list and classes can be subtracted by prefacing the class with a "
-                                                          "- sign.",
-
-                                                          NULL,
-                                                          &auditLog,
-                                                          "none",
-                                                          PGC_SUSET,
-                                                          GUC_LIST_INPUT | GUC_NOT_IN_SAMPLE,
-                                                          check_pg_audit_log,
-                                                          assign_pg_audit_log,
-                                                          NULL);
-
-       /* Define pg_audit.log_catalog */
-       DefineCustomBoolVariable(
-                                                        "pg_audit.log_catalog",
-
-               "Specifies that session logging should be enabled in the case where "
-                  "all relations in a statement are in pg_catalog.  Disabling this "
-        "setting will reduce noise in the log from tools like psql and PgAdmin "
-                                                        "that query the catalog heavily.",
-
-                                                        NULL,
-                                                        &auditLogCatalog,
-                                                        true,
-                                                        PGC_SUSET,
-                                                        GUC_NOT_IN_SAMPLE,
-                                                        NULL, NULL, NULL);
-
-       /* Define pg_audit.log_level */
-       DefineCustomStringVariable(
-                                                          "pg_audit.log_level",
-
-                  "Specifies the log level that will be used for log entries. This "
-         "setting is used for regression testing and may also be useful to end "
-          "users for testing or other purposes.  It is not intended to be used "
-        "in a production environment as it may leak which statements are being "
-                                                          "logged to the user.",
-
-                                                          NULL,
-                                                          &auditLogLevelString,
-                                                          "log",
-                                                          PGC_SUSET,
-                                                          GUC_LIST_INPUT | GUC_NOT_IN_SAMPLE,
-                                                          check_pg_audit_log_level,
-                                                          assign_pg_audit_log_level,
-                                                          NULL);
-
-       /* Define pg_audit.log_parameter */
-       DefineCustomBoolVariable(
-                                                        "pg_audit.log_parameter",
-
-         "Specifies that audit logging should include the parameters that were "
-          "passed with the statement. When parameters are present they will be "
-                                          "be included in CSV format after the statement text.",
-
-                                                        NULL,
-                                                        &auditLogParameter,
-                                                        false,
-                                                        PGC_SUSET,
-                                                        GUC_NOT_IN_SAMPLE,
-                                                        NULL, NULL, NULL);
-
-       /* Define pg_audit.log_relation */
-       DefineCustomBoolVariable(
-                                                        "pg_audit.log_relation",
-
-         "Specifies whether session audit logging should create a separate log "
-                 "entry for each relation referenced in a SELECT or DML statement. "
-        "This is a useful shortcut for exhaustive logging without using object "
-                                                        "audit logging.",
-
-                                                        NULL,
-                                                        &auditLogRelation,
-                                                        false,
-                                                        PGC_SUSET,
-                                                        GUC_NOT_IN_SAMPLE,
-                                                        NULL, NULL, NULL);
-
-       /* Define pg_audit.log_statement_once */
-       DefineCustomBoolVariable(
-                                                        "pg_audit.log_statement_once",
-
-                        "Specifies whether logging will include the statement text and "
-                 "parameters with the first log entry for a statement/substatement "
-         "combination or with every entry.  Disabling this setting will result "
-          "in less verbose logging but may make it more difficult to determine "
-                                         "the statement that generated a log entry, though the "
-         "statement/substatement pair along with the process id should suffice "
-                         "to identify the statement text logged with a previous entry.",
-
-                                                        NULL,
-                                                        &auditLogStatementOnce,
-                                                        false,
-                                                        PGC_SUSET,
-                                                        GUC_NOT_IN_SAMPLE,
-                                                        NULL, NULL, NULL);
-
-       /* Define pg_audit.role */
-       DefineCustomStringVariable(
-                                                          "pg_audit.role",
-
-          "Specifies the master role to use for object audit logging.  Muliple "
-         "audit roles can be defined by granting them to the master role. This "
-         "allows multiple groups to be in charge of different aspects of audit "
-                                                          "logging.",
-
-                                                          NULL,
-                                                          &auditRole,
-                                                          "",
-                                                          PGC_SUSET,
-                                                          GUC_NOT_IN_SAMPLE,
-                                                          NULL, NULL, NULL);
-
-       /*
-        * Install our hook functions after saving the existing pointers to
-        * preserve the chains.
-        */
-       next_ExecutorStart_hook = ExecutorStart_hook;
-       ExecutorStart_hook = pg_audit_ExecutorStart_hook;
-
-       next_ExecutorCheckPerms_hook = ExecutorCheckPerms_hook;
-       ExecutorCheckPerms_hook = pg_audit_ExecutorCheckPerms_hook;
-
-       next_ProcessUtility_hook = ProcessUtility_hook;
-       ProcessUtility_hook = pg_audit_ProcessUtility_hook;
-
-       next_object_access_hook = object_access_hook;
-       object_access_hook = pg_audit_object_access_hook;
-}
diff --git a/contrib/pg_audit/pg_audit.control b/contrib/pg_audit/pg_audit.control
deleted file mode 100644 (file)
index 40c0b0a..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-# pg_audit extension
-comment = 'provides auditing functionality'
-default_version = '1.0'
-module_pathname = '$libdir/pg_audit'
-relocatable = true
diff --git a/contrib/pg_audit/sql/pg_audit.sql b/contrib/pg_audit/sql/pg_audit.sql
deleted file mode 100644 (file)
index d4d6b6f..0000000
+++ /dev/null
@@ -1,669 +0,0 @@
--- Load pg_audit module
-create extension pg_audit;
-
---
--- Audit log fields are:
---     AUDIT_TYPE - SESSION or OBJECT
---     STATEMENT_ID - ID of the statement in the current backend
---     SUBSTATEMENT_ID - ID of the substatement in the current backend
---     CLASS - Class of statement being logged (e.g. ROLE, READ, WRITE)
---     COMMAND - e.g. SELECT, CREATE ROLE, UPDATE
---     OBJECT_TYPE - When available, type of object acted on (e.g. TABLE, VIEW)
---     OBJECT_NAME - When available, fully-qualified table of object
---     STATEMENT - The statement being logged
---     PARAMETER - If parameter logging is requested, they will follow the
---                 statement
-
-select current_user \gset
-
---
--- Set pg_audit parameters for the current (super)user.
-ALTER ROLE :current_user SET pg_audit.log = 'Role';
-ALTER ROLE :current_user SET pg_audit.log_level = 'notice';
-
-CREATE FUNCTION load_pg_audit( )
- RETURNS VOID
- LANGUAGE plpgsql
-SECURITY DEFINER
-AS $function$
-declare
-begin
-LOAD 'pg_audit';
-end;
-$function$;
-
--- After each connect, we need to load pg_audit, as if it was
--- being loaded from shared_preload_libraries.  Otherwise, the hooks
--- won't be set up and called correctly, leading to lots of ugly
--- errors.
-\connect - :current_user;
-select load_pg_audit();
-
---
--- Create auditor role
-CREATE ROLE auditor;
-
---
--- Create first test user
-CREATE USER user1;
-ALTER ROLE user1 SET pg_audit.log = 'ddl, ROLE';
-ALTER ROLE user1 SET pg_audit.log_level = 'notice';
-
---
--- Create, select, drop (select will not be audited)
-\connect - user1
-select load_pg_audit();
-CREATE TABLE public.test (id INT);
-SELECT * FROM test;
-DROP TABLE test;
-
---
--- Create second test user
-\connect - :current_user
-select load_pg_audit();
-
-CREATE USER user2;
-ALTER ROLE user2 SET pg_audit.log = 'Read, writE';
-ALTER ROLE user2 SET pg_audit.log_catalog = OFF;
-ALTER ROLE user2 SET pg_audit.log_level = 'warning';
-ALTER ROLE user2 SET pg_audit.role = auditor;
-ALTER ROLE user2 SET pg_audit.log_statement_once = ON;
-
-\connect - user2
-select load_pg_audit();
-CREATE TABLE test2 (id INT);
-GRANT SELECT ON TABLE public.test2 TO auditor;
-
---
--- Role-based tests
-CREATE TABLE test3
-(
-       id INT
-);
-
-SELECT count(*)
-  FROM
-(
-       SELECT relname
-         FROM pg_class
-         LIMIT 1
-) SUBQUERY;
-
-SELECT *
-  FROM test3, test2;
-
-GRANT INSERT
-   ON TABLE public.test3
-   TO auditor;
-
---
--- Create a view to test logging
-CREATE VIEW vw_test3 AS
-SELECT *
-  FROM test3;
-
-GRANT SELECT
-   ON vw_test3
-   TO auditor;
-
---
--- Object logged because of:
--- select on vw_test3
--- select on test2
-SELECT *
-  FROM vw_test3, test2;
-
---
--- Object logged because of:
--- insert on test3
--- select on test2
-WITH CTE AS
-(
-       SELECT id
-         FROM test2
-)
-INSERT INTO test3
-SELECT id
-  FROM cte;
-
---
--- Object logged because of:
--- insert on test3
-WITH CTE AS
-(
-       INSERT INTO test3 VALUES (1)
-                                  RETURNING id
-)
-INSERT INTO test2
-SELECT id
-  FROM cte;
-
-GRANT UPDATE ON TABLE public.test2 TO auditor;
-
---
--- Object logged because of:
--- insert on test3
--- update on test2
-WITH CTE AS
-(
-       UPDATE test2
-          SET id = 1
-       RETURNING id
-)
-INSERT INTO test3
-SELECT id
-  FROM cte;
-
---
--- Object logged because of:
--- insert on test2
-WITH CTE AS
-(
-       INSERT INTO test2 VALUES (1)
-                                  RETURNING id
-)
-UPDATE test3
-   SET id = cte.id
-  FROM cte
- WHERE test3.id <> cte.id;
-
---
--- Change permissions of user 2 so that only object logging will be done
-\connect - :current_user
-select load_pg_audit();
-alter role user2 set pg_audit.log = 'NONE';
-
-\connect - user2
-select load_pg_audit();
-
---
--- Create test4 and add permissions
-CREATE TABLE test4
-(
-       id int,
-       name text
-);
-
-GRANT SELECT (name)
-   ON TABLE public.test4
-   TO auditor;
-
-GRANT UPDATE (id)
-   ON TABLE public.test4
-   TO auditor;
-
-GRANT insert (name)
-   ON TABLE public.test4
-   TO auditor;
-
---
--- Not object logged
-SELECT id
-  FROM public.test4;
-
---
--- Object logged because of:
--- select (name) on test4
-SELECT name
-  FROM public.test4;
-
---
--- Not object logged
-INSERT INTO public.test4 (id)
-                                 VALUES (1);
-
---
--- Object logged because of:
--- insert (name) on test4
-INSERT INTO public.test4 (name)
-                                 VALUES ('test');
-
---
--- Not object logged
-UPDATE public.test4
-   SET name = 'foo';
-
---
--- Object logged because of:
--- update (id) on test4
-UPDATE public.test4
-   SET id = 1;
-
---
--- Object logged because of:
--- update (name) on test4
--- update (name) takes precedence over select (name) due to ordering
-update public.test4 set name = 'foo' where name = 'bar';
-
---
--- Drop test tables
-DROP TABLE test2;
-DROP VIEW vw_test3;
-DROP TABLE test3;
-DROP TABLE test4;
-
---
--- Change permissions of user 1 so that session logging will be done
-\connect - :current_user
-select load_pg_audit();
-alter role user1 set pg_audit.log = 'DDL, READ';
-\connect - user1
-select load_pg_audit();
-
---
--- Create table is session logged
-CREATE TABLE public.account
-(
-       id INT,
-       name TEXT,
-       password TEXT,
-       description TEXT
-);
-
---
--- Select is session logged
-SELECT *
-  FROM account;
-
---
--- Insert is not logged
-INSERT INTO account (id, name, password, description)
-                        VALUES (1, 'user1', 'HASH1', 'blah, blah');
-
---
--- Change permissions of user 1 so that only object logging will be done
-\connect - :current_user
-select load_pg_audit();
-alter role user1 set pg_audit.log = 'none';
-alter role user1 set pg_audit.role = 'auditor';
-\connect - user1
-select load_pg_audit();
-
---
--- ROLE class not set, so auditor grants not logged
-GRANT SELECT (password),
-         UPDATE (name, password)
-   ON TABLE public.account
-   TO auditor;
-
---
--- Not object logged
-SELECT id,
-          name
-  FROM account;
-
---
--- Object logged because of:
--- select (password) on account
-SELECT password
-  FROM account;
-
---
--- Not object logged
-UPDATE account
-   SET description = 'yada, yada';
-
---
--- Object logged because of:
--- update (password) on account
-UPDATE account
-   SET password = 'HASH2';
-
---
--- Change permissions of user 1 so that session relation logging will be done
-\connect - :current_user
-select load_pg_audit();
-alter role user1 set pg_audit.log_relation = on;
-alter role user1 set pg_audit.log = 'read, WRITE';
-\connect - user1
-select load_pg_audit();
-
---
--- Not logged
-create table ACCOUNT_ROLE_MAP
-(
-       account_id INT,
-       role_id INT
-);
-
---
--- ROLE class not set, so auditor grants not logged
-GRANT SELECT
-   ON TABLE public.account_role_map
-   TO auditor;
-
---
--- Object logged because of:
--- select (password) on account
--- select on account_role_map
--- Session logged on all tables because log = read and log_relation = on
-SELECT account.password,
-          account_role_map.role_id
-  FROM account
-          INNER JOIN account_role_map
-                       on account.id = account_role_map.account_id;
-
---
--- Object logged because of:
--- select (password) on account
--- Session logged on all tables because log = read and log_relation = on
-SELECT password
-  FROM account;
-
---
--- Not object logged
--- Session logged on all tables because log = read and log_relation = on
-UPDATE account
-   SET description = 'yada, yada';
-
---
--- Object logged because of:
--- select (password) on account (in the where clause)
--- Session logged on all tables because log = read and log_relation = on
-UPDATE account
-   SET description = 'yada, yada'
- where password = 'HASH2';
-
---
--- Object logged because of:
--- update (password) on account
--- Session logged on all tables because log = read and log_relation = on
-UPDATE account
-   SET password = 'HASH2';
-
---
--- Change back to superuser to do exhaustive tests
-\connect - :current_user
-select load_pg_audit();
-SET pg_audit.log = 'ALL';
-SET pg_audit.log_level = 'notice';
-SET pg_audit.log_relation = ON;
-SET pg_audit.log_parameter = ON;
-
---
--- Simple DO block
-DO $$
-BEGIN
-       raise notice 'test';
-END $$;
-
---
--- Create test schema
-CREATE SCHEMA test;
-
---
--- Copy account to stdout
-COPY account TO stdout;
-
---
--- Create a table from a query
-CREATE TABLE test.account_copy AS
-SELECT *
-  FROM account;
-
---
--- Copy from stdin to account copy
-COPY test.account_copy from stdin;
-1      user1   HASH2   yada, yada
-\.
-
---
--- Test prepared statement
-PREPARE pgclassstmt (oid) AS
-SELECT *
-  FROM account
- WHERE id = $1;
-
-EXECUTE pgclassstmt (1);
-DEALLOCATE pgclassstmt;
-
---
--- Test cursor
-BEGIN;
-
-DECLARE ctest SCROLL CURSOR FOR
-SELECT count(*)
-  FROM
-(
-       SELECT relname
-         FROM pg_class
-        LIMIT 1
- ) subquery;
-
-FETCH NEXT FROM ctest;
-CLOSE ctest;
-COMMIT;
-
---
--- Turn off log_catalog and pg_class will not be logged
-SET pg_audit.log_catalog = OFF;
-
-SELECT count(*)
-  FROM
-(
-       SELECT relname
-         FROM pg_class
-        LIMIT 1
- ) subquery;
-
---
--- Test prepared insert
-CREATE TABLE test.test_insert
-(
-       id INT
-);
-
-PREPARE pgclassstmt (oid) AS
-INSERT INTO test.test_insert (id)
-                                         VALUES ($1);
-EXECUTE pgclassstmt (1);
-
---
--- Check that primary key creation is logged
-CREATE TABLE public.test
-(
-       id INT,
-       name TEXT,
-       description TEXT,
-       CONSTRAINT test_pkey PRIMARY KEY (id)
-);
-
---
--- Check that analyze is logged
-ANALYZE test;
-
---
--- Grants to public should not cause object logging (session logging will
--- still happen)
-GRANT SELECT
-  ON TABLE public.test
-  TO PUBLIC;
-
-SELECT *
-  FROM test;
-
--- Check that statements without columns log
-SELECT
-  FROM test;
-
-SELECT 1,
-          substring('Thomas' from 2 for 3);
-
-DO $$
-DECLARE
-       test INT;
-BEGIN
-       SELECT 1
-         INTO test;
-END $$;
-
-explain select 1;
-
---
--- Test that looks inside of do blocks log
-INSERT INTO TEST (id)
-                 VALUES (1);
-INSERT INTO TEST (id)
-                 VALUES (2);
-INSERT INTO TEST (id)
-                 VALUES (3);
-
-DO $$
-DECLARE
-       result RECORD;
-BEGIN
-       FOR result IN
-               SELECT id
-                 FROM test
-       LOOP
-               INSERT INTO test (id)
-                        VALUES (result.id + 100);
-       END LOOP;
-END $$;
-
---
--- Test obfuscated dynamic sql for clean logging
-DO $$
-DECLARE
-       table_name TEXT = 'do_table';
-BEGIN
-       EXECUTE 'CREATE TABLE ' || table_name || ' ("weird name" INT)';
-       EXECUTE 'DROP table ' || table_name;
-END $$;
-
---
--- Generate an error and make sure the stack gets cleared
-DO $$
-BEGIN
-       CREATE TABLE bogus.test_block
-       (
-               id INT
-       );
-END $$;
-
---
--- Test alter table statements
-ALTER TABLE public.test
-       DROP COLUMN description ;
-
-ALTER TABLE public.test
-       RENAME TO test2;
-
-ALTER TABLE public.test2
-       SET SCHEMA test;
-
-ALTER TABLE test.test2
-       ADD COLUMN description TEXT;
-
-ALTER TABLE test.test2
-       DROP COLUMN description;
-
-DROP TABLE test.test2;
-
---
--- Test multiple statements with one semi-colon
-CREATE SCHEMA foo
-       CREATE TABLE foo.bar (id int)
-       CREATE TABLE foo.baz (id int);
-
---
--- Test aggregate
-CREATE FUNCTION public.int_add
-(
-       a INT,
-       b INT
-)
-       RETURNS INT LANGUAGE plpgsql AS $$
-BEGIN
-       return a + b;
-END $$;
-
-SELECT int_add(1, 1);
-
-CREATE AGGREGATE public.sum_test(INT) (SFUNC=public.int_add, STYPE=INT, INITCOND='0');
-ALTER AGGREGATE public.sum_test(integer) RENAME TO sum_test2;
-
---
--- Test conversion
-CREATE CONVERSION public.conversion_test FOR 'SQL_ASCII' TO 'MULE_INTERNAL' FROM pg_catalog.ascii_to_mic;
-ALTER CONVERSION public.conversion_test RENAME TO conversion_test2;
-
---
--- Test create/alter/drop database
-CREATE DATABASE contrib_regression_pgaudit;
-ALTER DATABASE contrib_regression_pgaudit RENAME TO contrib_regression_pgaudit2;
-DROP DATABASE contrib_regression_pgaudit2;
-
---
--- Test that frees a memory context earlier than expected
-CREATE TABLE hoge
-(
-       id int
-);
-
-CREATE FUNCTION test()
-       RETURNS INT AS $$
-DECLARE
-       cur1 cursor for select * from hoge;
-       tmp int;
-BEGIN
-       OPEN cur1;
-       FETCH cur1 into tmp;
-       RETURN tmp;
-END $$
-LANGUAGE plpgsql ;
-
-SELECT test();
-
---
--- Delete all rows then delete 1 row
-SET pg_audit.log = 'write';
-SET pg_audit.role = 'auditor';
-
-create table bar
-(
-       col int
-);
-
-grant delete
-   on bar
-   to auditor;
-
-insert into bar (col)
-                values (1);
-delete from bar;
-
-insert into bar (col)
-                values (1);
-delete from bar
- where col = 1;
-
-drop table bar;
-
---
--- Grant roles to each other
-SET pg_audit.log = 'role';
-GRANT user1 TO user2;
-REVOKE user1 FROM user2;
-
--- Cleanup
--- Set client_min_messages up to warning to avoid noise
-SET client_min_messages = 'warning';
-
-ALTER ROLE :current_user RESET pg_audit.log;
-ALTER ROLE :current_user RESET pg_audit.log_level;
-
-DROP TABLE test.account_copy;
-DROP TABLE test.test_insert;
-DROP SCHEMA test;
-DROP TABLE foo.bar;
-DROP TABLE foo.baz;
-DROP SCHEMA foo;
-DROP TABLE hoge;
-DROP TABLE account;
-DROP TABLE account_role_map;
-DROP USER user2;
-DROP USER user1;
-DROP ROLE auditor;
-
-RESET client_min_messages;