2017-11-21 14 views
0

Mein Algorithmus funktionierte gut, aber mit einer neuen großen Datenbank überschreitet meine Ganzzahlvariable die maximale Grenzgröße. (Ich benutze den Powerset-Algorithmus: https://www.postgresql.org/message-id/20060924054759.GA71934%40winnie.fuhr.org)Postgresql FEHLER: Operator existiert nicht: bigint << bigint

Also habe ich beschlossen, alle meine Ganzzahl zu Bigint zu ändern, aber jetzt habe ich ein Problem mit dem Vergleichsoperator ... Ich weiß nicht, wie es zu verwalten:

CREATE OR REPLACE FUNCTION powerset(a anyarray) 
    RETURNS SETOF anyarray AS 
$BODY$ 
DECLARE 
    retval a%TYPE; 
    alower bigint := array_lower(a, 1); 
    aupper bigint := array_upper(a, 1); 
    j  bigint; 
    k  bigint; 
BEGIN 
    FOR i IN 1 .. COALESCE((CAST(1 AS BIGINT) << (aupper - alower + 1)) - 1, 0) LOOP 
     retval := '{}'; 
     j := alower; 
     k := i; 

     WHILE k > CAST(0 AS BIGINT) LOOP 
      IF k & CAST(1 AS BIGINT) = CAST(1 AS BIGINT) THEN 
       retval := array_append(retval, a[j]); 
      END IF; 

      j := j + CAST(1 AS BIGINT); 
      k := k >> CAST(1 AS BIGINT); 
     END LOOP; 

     RETURN NEXT retval; 
    END LOOP; 

    RETURN; 
END; 
$BODY$ 
    LANGUAGE plpgsql IMMUTABLE STRICT 
    COST 100 
    ROWS 1000; 
ALTER FUNCTION powerset(anyarray) 
    OWNER TO postgres; 

ich habe den Fehler in Zeile bekam:

FOR i IN 1 .. COALESCE((CAST(1 AS BIGINT) << (aupper - alower + 1)) - 1, 0) LOOP 

Fehler 42883 Postgresql eRROR: Operator existiert nicht: Bigint < < Bigint

Antwort

1

Die Art des rechten Operanden bitweise Shift-Operatoren ist integer. Leider ist dies nicht in the documentation. erwähnt

Sie sollten den rechten Operanden der Shift-Operatoren zu integer:

-- instead of 
-- COALESCE((CAST(1 AS BIGINT) << (aupper - alower + 1)) - 1, 0) 
-- use 
select COALESCE(1 << (aupper - alower + 1)::int- 1, 0)::bigint 

-- instead of 
-- k := k >> CAST(1 AS BIGINT); 
--- use 
k := k >> 1; 
-- etc 

Sie können mögliche Arten werfen überprüfen die Operanden von dem Systemkatalog pg_operator, zB Abfrage:

select oprname, oprleft::regtype, oprright::regtype 
from pg_operator 
where oprname = '<<' 
and oprcode::text like '%shl%' -- shift left functions 

oprname | oprleft | oprright 
---------+----------+---------- 
<<  | smallint | integer 
<<  | integer | integer 
<<  | bigint | integer 
(3 rows)  

Das obige Ergebnis zeigt, dass le ft Operanden des Operators << (bitweise Verschiebung links) können smallint,integer oder bigint und rechten Operanden muss integer.

+0

Dank sein! Was ist der Unterschied zwischen int2shl, int4shl, int8shl so? Also muss ich es für alle meine Algorithmus tun? Jeder Vergleichsoperator muss in seiner Funktion geändert werden? –

+0

Siehe die aktualisierte Antwort. – klin