Skip to content

Commit

Permalink
Support the tables with column GENERATED AS IDENTITY (new with PG 10)…
Browse files Browse the repository at this point in the history
…. In regression tests, add to a tables group a sequence associated to a GENERATED AS IDENTITY column.
  • Loading branch information
beaud76 committed May 25, 2017
1 parent 478b28a commit a5f5e11
Show file tree
Hide file tree
Showing 100 changed files with 10,526 additions and 9,517 deletions.
1 change: 1 addition & 0 deletions CHANGES
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ E-Maj - Release notes
Enhancements:
- Let E-Maj work with PostgreSQL 10.
- Support elementary partitions of partitionned tables (PostgreSQL 10+).
- Support tables with GENERATED AS IDENTITY columns (PostgreSQL 10+)
- The emaj_alter_group() function can process any attribute change
registered in the emaj_group_def table, among priority level, log schema
suffix, emaj names prefix, log data or index tablespace, for relations
Expand Down
2 changes: 1 addition & 1 deletion docs/en/mainFunctions.rst
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ On the contrary, if specific tablespaces are referenced for any log table or log

The *emaj_create_group()* function also checks the existence of application triggers on any tables of the group. If a trigger exists on a table of the group, a message is returned, suggesting the user to verify that this trigger does not update any tables that would not belong to the group.

If a sequence of the group is associated to a *SERIAL* or *BIGSERIAL* column and the table that owns this column does not belong to the same tables group, the function also issues a *WARNING* message.
If a sequence of the group is associated either to a *SERIAL* or *BIGSERIAL* column or to a column created with a *GENERATED AS IDENTITY* clause, and the table that owns this column does not belong to the same tables group, the function also issues a *WARNING* message.

A specific version of the function allows to create an empty tables group, i.e. without any table or sequence at creation time::

Expand Down
2 changes: 1 addition & 1 deletion docs/fr/mainFunctions.rst
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ En revanche, si des tablespaces spécifiques pour les tables de log ou pour leur

La fonction *emaj_create_group()* contrôle également l'existence de « triggers applicatifs » impliquant les tables du groupe. Si un trigger existe sur une table du groupe, un message d'avertissement est retourné incitant l'utilisateur à vérifier que ce trigger ne fait pas de mises à jour sur des tables n'appartenant pas au groupe.

Si une séquence du groupe est associée à une colonne de type *SERIAL* ou *BIGSERIAL* et que sa table d'appartenance ne fait pas partie du groupe, la fonction génère également un message de type *WARNING*.
Si une séquence du groupe est associée à une colonne soit de type *SERIAL* ou *BIGSERIAL* soit définie avec une clause *GENERATED AS IDENTITY*, et que sa table d'appartenance ne fait pas partie du groupe, la fonction génère également un message de type *WARNING*.

Une forme particulière de la fonction permet de créer un groupe de table vide, c’est à dire ne contenant à sa création aucune table ni séquence ::

Expand Down
66 changes: 66 additions & 0 deletions sql/emaj--2.0.1--next_version.sql
Original file line number Diff line number Diff line change
Expand Up @@ -841,6 +841,72 @@ $_create_seq$
END;
$_create_seq$;

CREATE OR REPLACE FUNCTION emaj._rlbk_tbl(r_rel emaj.emaj_relation, v_minGlobalSeq BIGINT, v_maxGlobalSeq BIGINT, v_nbSession INT, v_isLoggedRlbk BOOLEAN)
RETURNS BIGINT LANGUAGE plpgsql SECURITY DEFINER AS
$_rlbk_tbl$
-- This function rollbacks one table to a given point in time represented by the value of the global sequence
-- The function is called by emaj._rlbk_session_exec()
-- Input: row from emaj_relation corresponding to the appplication table to proccess
-- global sequence (non inclusive) lower and (inclusive) upper limits covering the rollback time frame
-- Output: number of rolled back primary keys
-- For unlogged rollback, the log triggers have been disabled previously and will be enabled later.
-- The function is defined as SECURITY DEFINER so that emaj_adm role can use it even if he is not the owner of the application table.
DECLARE
v_fullTableName TEXT;
v_logTableName TEXT;
v_tmpTable TEXT;
v_tableType TEXT;
v_insertClause TEXT = '';
v_nbPk BIGINT;
BEGIN
v_fullTableName = quote_ident(r_rel.rel_schema) || '.' || quote_ident(r_rel.rel_tblseq);
v_logTableName = quote_ident(r_rel.rel_log_schema) || '.' || quote_ident(r_rel.rel_log_table);
-- insert begin event in history
INSERT INTO emaj.emaj_hist (hist_function, hist_event, hist_object, hist_wording)
VALUES ('ROLLBACK_TABLE', 'BEGIN', v_fullTableName, 'All log rows with emaj_gid > ' || v_minGlobalSeq || ' and <= ' || v_maxGlobalSeq);
-- create the temporary table containing all primary key values with their earliest emaj_gid
IF v_nbSession = 1 THEN
v_tableType = 'TEMP';
v_tmpTable = 'emaj_tmp_' || pg_backend_pid();
ELSE
-- with multi session parallel rollbacks, the table cannot be a TEMP table because it would not be usable in 2PC
-- but it may be an UNLOGGED table
v_tableType = 'UNLOGGED';
v_tmpTable = 'emaj.emaj_tmp_' || pg_backend_pid();
END IF;
EXECUTE 'CREATE ' || v_tableType || ' TABLE ' || v_tmpTable || ' AS '
|| ' SELECT ' || r_rel.rel_sql_pk_columns || ', min(emaj_gid) as emaj_gid'
|| ' FROM ' || v_logTableName
|| ' WHERE emaj_gid > ' || v_minGlobalSeq || 'AND emaj_gid <= ' || v_maxGlobalSeq
|| ' GROUP BY ' || r_rel.rel_sql_pk_columns;
GET DIAGNOSTICS v_nbPk = ROW_COUNT;
-- delete all rows from the application table corresponding to each touched primary key
-- this deletes rows inserted or updated during the rolled back period
EXECUTE 'DELETE FROM ONLY ' || v_fullTableName || ' tbl USING ' || v_tmpTable || ' keys '
|| ' WHERE ' || r_rel.rel_sql_pk_eq_conditions;
-- for logged rollbacks, if the number of pkey to process is greater than 1.000, ANALYZE the log table to take into account
-- the impact of just inserted rows, avoiding a potentialy bad plan for the next INSERT statement
IF v_isLoggedRlbk AND v_nbPk > 1000 THEN
EXECUTE 'ANALYZE ' || v_logTableName;
END IF;
-- insert into the application table rows that were deleted or updated during the rolled back period
IF emaj._pg_version_num() >= 100000 THEN
v_insertClause = ' OVERRIDING SYSTEM VALUE';
END IF;
EXECUTE 'INSERT INTO ' || v_fullTableName || v_insertClause
|| ' SELECT ' || r_rel.rel_sql_columns
|| ' FROM ' || v_logTableName || ' tbl, ' || v_tmpTable || ' keys '
|| ' WHERE ' || r_rel.rel_sql_pk_eq_conditions || ' AND tbl.emaj_gid = keys.emaj_gid AND tbl.emaj_tuple = ''OLD'''
|| ' AND tbl.emaj_gid > ' || v_minGlobalSeq || 'AND tbl.emaj_gid <= ' || v_maxGlobalSeq;
-- drop the now useless temporary table
EXECUTE 'DROP TABLE ' || v_tmpTable;
-- insert end event in history
INSERT INTO emaj.emaj_hist (hist_function, hist_event, hist_object, hist_wording)
VALUES ('ROLLBACK_TABLE', 'END', v_fullTableName, v_nbPk || ' rolled back primary keys');
RETURN v_nbPk;
END;
$_rlbk_tbl$;

CREATE OR REPLACE FUNCTION emaj._delete_log_tbl(r_rel emaj.emaj_relation, v_beginTimeId BIGINT, v_endTimeId BIGINT, v_lastGlobalSeq BIGINT)
RETURNS BIGINT LANGUAGE plpgsql AS
$_delete_log_tbl$
Expand Down
8 changes: 6 additions & 2 deletions sql/emaj--next_version.sql
Original file line number Diff line number Diff line change
Expand Up @@ -1422,7 +1422,7 @@ $_create_seq$
v_tableGroup TEXT;
BEGIN
-- the checks on the sequence properties are performed by the calling functions
-- get the schema and the name of the table that contains a serial column this sequence is linked to, if one exists
-- get the schema and the name of the table that contains a serial or a "generated as identity" column this sequence is linked to, if one exists
SELECT nt.nspname, ct.relname INTO v_tableSchema, v_tableName
FROM pg_catalog.pg_class cs, pg_catalog.pg_namespace ns, pg_depend,
pg_catalog.pg_class ct, pg_catalog.pg_namespace nt
Expand Down Expand Up @@ -1480,6 +1480,7 @@ $_rlbk_tbl$
v_logTableName TEXT;
v_tmpTable TEXT;
v_tableType TEXT;
v_insertClause TEXT = '';
v_nbPk BIGINT;
BEGIN
v_fullTableName = quote_ident(r_rel.rel_schema) || '.' || quote_ident(r_rel.rel_tblseq);
Expand Down Expand Up @@ -1513,7 +1514,10 @@ $_rlbk_tbl$
EXECUTE 'ANALYZE ' || v_logTableName;
END IF;
-- insert into the application table rows that were deleted or updated during the rolled back period
EXECUTE 'INSERT INTO ' || v_fullTableName
IF emaj._pg_version_num() >= 100000 THEN
v_insertClause = ' OVERRIDING SYSTEM VALUE';
END IF;
EXECUTE 'INSERT INTO ' || v_fullTableName || v_insertClause
|| ' SELECT ' || r_rel.rel_sql_columns
|| ' FROM ' || v_logTableName || ' tbl, ' || v_tmpTable || ' keys '
|| ' WHERE ' || r_rel.rel_sql_pk_eq_conditions || ' AND tbl.emaj_gid = keys.emaj_gid AND tbl.emaj_tuple = ''OLD'''
Expand Down

0 comments on commit a5f5e11

Please sign in to comment.