<!--
Les sources pour ce sujet sont :

* https://git.postgresql.org/gitweb/?p=postgresql.git;a=commit;h=699586315704a8268808e3bdba4cb5924a038c49

Discussion :

* https://www.postgresql.org/message-id/flat/CAExHW5uOykuTC+C6R1yDSp=o8Q83jr8xJdZxgPkxfZ1Ue5RRGg@mail.gmail.com
-->

<div class="slide-content">

  * Les colonnes `IDENTITY` sont supportées pour les tables partitionnées
  * Les `INSERT` sont désormais possibles

</div>

<div class="notes">

Jusqu'à présent, une insertion dans une partition d'une table partitionnée
possédant une colonne `IDENTITY` n'était pas faisable. Les `INSERT` faits dans
la table parente eux passent sans problème, comme on peut le voir dans l'exemple
suivant avec la table `t1` : 

```sql
-- version 16
postgres=# create table t1 (i int, j int generated always as identity) partition by range (i);
CREATE TABLE
postgres=# create table t1_0 partition of t1 for values from (0) to (1000);
CREATE TABLE
postgres=# insert into t1 values (100);
INSERT 0 1
postgres=# insert into t1 values (200);
INSERT 0 1
postgres=# insert into t1 values (300);
INSERT 0 1
postgres=# select * from t1;
  i  | j 
-----+---
 100 | 1
 200 | 2
 300 | 3
(3 rows)
```

Un `INSERT` exécuté sur la partition `t1_0` ne fonctionnait pas :

```sql
-- version 16 :
postgres=# insert into t1_0 values (400);
ERROR:  null value in column "j" of relation "t1_0" violates not-null constraint
DETAIL:  Failing row contains (400, null).
```

Chose désormais acceptée dans la version 17 de PostgreSQL ...

```sql
-- version 17 :
postgres=# insert into t1_0 values (400);
INSERT 0 1
```

... et la valeur insérée dans la colonne `j` suit la séquence utilisée jusqu'à présent :

```sql
postgres=# select * from t1;
  i  | j 
-----+---
 100 | 1
 200 | 2
 300 | 3
 400 | 4
(4 rows)
```

Si une autre table doit être attachée à une table partitionnée ayant une colonne
`IDENTITY`, elle doit respecter les contraintes de la colonne `IDENTITY`, en
l’occurrence `NOT NULL`.

```sql
postgres=# create table t2 (i int, j int) partition by range (i);
CREATE TABLE
postgres=# create table t2_0 partition of t2 for values from (2000) to (3000);
CREATE TABLE
postgres=# insert into t2 values (2100);
INSERT 0 1
postgres=# alter table t1 attach partition t2 for values from (2000) to (3000);
ERROR:  column "j" in child table must be marked NOT NULL
```

Après avoir adapté les données et la table `t2` pour qu'elle respecte cette
contrainte, il est possible d'attacher cette table à `t1`.

```sql
postgres=# insert into t2 values (2100,1);
INSERT 0 1
postgres=# alter table t1 attach partition t2 for values from (2000) to (3000);
ALTER TABLE
postgres=# select * from t1;
  i   | j 
------+---
  100 | 1
  200 | 2
  300 | 3
  400 | 4
  600 | 9
 1100 | 6
 1200 | 7
 2100 | 1
(8 rows)
```

Maintenant, un ajout dans cette partition reprendra la suite de la séquence
utilisée par `IDENTITY`.

```sql
postgres=# insert into t2 values (2200);
INSERT 0 1
postgres=# select * from t1;
  i   | j  
------+----
  100 |  1
  200 |  2
  300 |  3
  400 |  4
  600 |  9
 1100 |  6
 1200 |  7
 2100 |  1
 2200 | 10
(9 rows)
```

Si une partition est détachée de la table parente, alors la clause `IDENTITY`
de la colonne (`j` dans notre exemple) est retirée. La clause `NOT NULL` est quant
à elle conservée.

```sql
postgres=# alter table t1 detach partition t1_0;
ALTER TABLE
postgres=# select * from t1_0;
  i  | j 
-----+---
 100 | 1
 200 | 2
 300 | 3
 400 | 4
 600 | 9
(5 rows)

postgres=# \d t1_0;
                Table "public.t1_0"
 Column |  Type   | Collation | Nullable | Default 
--------+---------+-----------+----------+---------
 i      | integer |           |          | 
 j      | integer |           | not null | 
```

</div>