Vous n'êtes pas identifié(e).

#1 01/10/2010 23:30:13

Alexandre
Membre

INSERT RETURNING renvoie une valeur mais n'insère pas les données

Bonjour,

J'ai fait une fonction qui renvoie l'id d'une ligne correspondant aux valeurs passées en argument, en créant cette ligne si besoin est.

create table machine (                                                                                                                                       
id serial primary key,                                                                                                                                       
hostname text,
description text,
comments text
);
insert into machine(hostname) values ('exemple');

create table boot (
id serial primary key,
machine_id integer references machine,
last_boot_raw_output text,
UNIQUE(machine_id, last_boot_raw_output)
);

create or replace function get_boot_id(varchar, varchar) returns integer as $$
declare
  machine_hostname alias for $1;
  _last_boot_raw_output alias for $2;
  _machine_id integer;
  boot_id integer;
begin
  select id into _machine_id from machine where hostname = machine_hostname;
  if not found then
    raise exception  'machine with hostname ''%'' not found', machine_hostname;
  end if;
  select id into boot_id from boot where machine_id = machine_id and last_boot_raw_output = _last_boot_raw_output;
  if not found then
    insert into boot(machine_id, last_boot_raw_output) values (_machine_id, _last_boot_raw_output) returning id into boot_id;
  end if;
  return boot_id;
end;
$$ language plpgsql;

Tant que  j'appelle la fonction depuis le shell sql, tout se passe comme prévu. En revanche, lorsque j'appelle la fonction depuis python avec psycopg2, le comportement est assez surprenant : ça me renvoie un id à chaque fois différent pour les mêmes arguments, et aucune ligne n'est insérée dans la table. Pour que ça marche comme il faut, je dois mettre un COMMIT dans le code python :

cur.execute('select get_boot_id(%s, %s);', (hostname, last_boot_raw_output));
row = cur.fetchone()
cur.execute('commit;')
return row[0]

J'ai le même problème avec tous les INSERT avec psycopg2, mais là je trouve que c'est vexant. Est-ce que je peux faire en sorte, dans la définition de la fonction, que cette fonction ne renvoie rien tant que les données ne sont pas effectivement insérées ?

Dernière modification par Alexandre (02/10/2010 00:48:00)

Hors ligne

#2 01/10/2010 23:48:34

gleu
Administrateur

Re : INSERT RETURNING renvoie une valeur mais n'insère pas les données

Si vous avez besoin d'un COMMIT explicite, c'est que psycopg2 fait un BEGIN tout aussi explicite. Donc cherchez dans la documentation de psycopg2 pour désactiver ce comportement (http://initd.org/psycopg/docs/usage.html#transactions-control semble un bon début).


Guillaume.

Hors ligne

#3 02/10/2010 00:00:37

Alexandre
Membre

Re : INSERT RETURNING renvoie une valeur mais n'insère pas les données

Ah, voilà le point qui m'avait échappé. Dans ce cas il est naturel que je mette le commit dans le code python. Merci !

Hors ligne

Pied de page des forums