在捕获异常postgres后插入回滚


insert rollback after caught exception postgres

我有一个从php调用的postgres函数。函数的第一行在表中插入一些内容,将键返回到本地。

CREATE OR REPLACE FUNCTION uploadConfirm( bname text, ul text, pt text,  
                                          shp text, vzn integer, 
                                          gpsLoc double precision[], meta text ) RETURNS void   AS $uC$
DECLARE
        file Files%ROWTYPE;
        shape text[];
        locat_id integer;
        crl_id integer;
        uid integer DEFAULT(null);
        iid integer;
        make text;
        model text;
BEGIN
        insert into interact(webRequest) values(bname) RETURNING interact_id into iid;
        shape := regexp_split_to_array( shp, E'x' );  -- get info for single file
        --meta := encode( meta , 'base64' );
        RAISE NOTICE 'uploadConfirm: % : % : % : % : % : % : %' , bname, ul, pt, shp , vzn, gpsLoc , meta ;
        locat_id := getLocationId( gpsLoc[1],gpsLoc[2],gpsLoc[3] );
        --RAISE 'meta: %d' , meta;
        make := (regexp_matches( meta , $$Make's+='s+'([^']+)'$$ ))[1];
        model := (regexp_matches( meta , $$Model's+='s+'([^']+)'$$ ))[1];
        --RAISE  '>> shape , loc_id, make, model: % : % : % : % ' , shape, loc_id, make, model  ;
        crl_id := getCurlId( '' , ul, pt, vzn );
        select * into  file from Files  where Files.basename = bname;
        IF NOT FOUND THEN
               insert into Files 
               ( basename , curl_id  ) VALUES 
               ( bname , crl_id ) returning * into file;
           ELSE 
               update Files set ( curl_id  ) = 
                                ( crl_id  )
                                where basename = bname;
               update interact set ( uid ) = ( file.uid ) where interact_id = iid;
        END IF;          
        INSERT INTO Metadata VALUES ( meta , make , model , cast(shape[1] as integer), cast( shape[2] as integer) , file.file_id, locat_id );
     EXCEPTION 
         WHEN not_null_violation THEN
              perform reportError( 'File(bname='|| bname || ' no location data:' || SQLERRM, iid );
     END;
$uC$ LANGUAGE plpgsql;

此函数有一个异常子句,它调用如下所示的错误报告函数。

CREATE OR REPLACE FUNCTION reportError( msgX text, iidX integer default(null) ) returns void as $re$
       DECLARE
       BEGIN
        if iidX is null then
            SELECT currval(pg_get_serial_sequence('interact', 'interact_id')) into iidX;
        END IF;
        insert into err (msg,iid) values ( msgX,iidX );
       END;
$re$ LANGUAGE plpgsql;

它调用另一个函数reportError,该函数将有关异常的信息(包括文件名bname和关键字iid)放在表中。

当我查看时,尽管错误信息在表中,但它应该在表中。interact表中缺少带有相应键的条目。只有当bname为null时,插入interact才会失败;但是,bname(!=NULL)的值出现在错误消息中,因此我捕获的失败必须在代码的后面。

在我看来,插入交互不应该回滚,但显然是。

我不明白为什么这个条目不在interact表中。有人能解释为什么&帮我想办法把它送到那里。

谢谢。

postgres文档说这是应该发生的事情

When an error is caught by an EXCEPTION clause, the local variables 
of the PL/pgSQL function remain as they were when the error occurred, but 
all changes to persistent database state within the block are rolled back. 

我应该对自己说RTM。

我可以在异常处理程序中重做插入操作。

相关文章: