捕获异常postgres后插入回滚

时间:2015-03-22 23:26:23

标签: php postgresql

我有一个从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;

此函数有一个exception子句,它调用下面显示的错误报告函数。

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 ,如上所示)表中的异常。

当我看时,虽然错误信息在表中应该是。 互动表中缺少具有相应键的条目。插入到交互中只能在bname为null时失败;但是,错误消息中存在bname(!= NULL)的值,因此我捕获的失败必须在代码中的后面按预期进行。

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

我不明白为什么此条目不在互动表中。有人可以解释为什么&帮我弄清楚如何到达那里。

感谢。

1 个答案:

答案 0 :(得分:0)

postgres docs说这究竟应该发生什么

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。

我可以在异常处理程序中重做我想要的插入。