Varför?
PL/pgSQL kör SQL-frågor som förberedda satser . Handboken om parameterbyte:
Notera termen värden . Endast verkliga värden kan parametreras, men inte nyckelord, identifierare eller typnamn. 32
i bit(32)
utseende som ett värde, men modifieraren av en datatyp är endast ett "värde" internt och kan inte parametreras. SQL kräver att känna till datatyper i planeringsstadiet, den kan inte vänta på exekveringsstadiet.
Du kunde nå ditt mål med dynamisk SQL och EXECUTE
. Som proof of concept :
CREATE OR REPLACE FUNCTION lpad_bits(val varbit, sz int = 32, OUT outval varbit) AS
$func$
BEGIN
EXECUTE format('SELECT $1::bit(%s) >> $2', sz) -- literal
USING val, sz - length(val) -- values
INTO outval;
END
$func$ LANGUAGE plpgsql IMMUTABLE;
Ring:
SELECT lpad_bits(b'1001100111000', 32);
Notera skillnaden mellan sz
används som bokstavlig för att bygga påståendet och dess andra förekomst där det används som värde , som kan skickas som parameter.
Snabbare alternativ
En överlägsen lösning för just denna uppgift är att bara använda lpad()
gillar @Abelisto föreslog
:
CREATE OR REPLACE FUNCTION lpad_bits2(val varbit, sz int = 32)
RETURNS varbit AS
$func$
SELECT lpad(val::text, sz, '0')::varbit;
$func$ LANGUAGE sql IMMUTABLE;
(Enklare som en vanlig SQL-funktion, som även tillåter funktionsinlining i samband med yttre frågor.)
Flera gånger snabbare än ovanstående funktion. Ett mindre fel:vi måste casta till text
och tillbaka till varbit
. Tyvärr, lpad()
är för närvarande inte implementerat för varbit
. Handboken:
overlay()
finns tillgänglig kan vi ha en billigare funktion:
CREATE OR REPLACE FUNCTION lpad_bits3(val varbit, base varbit = '00000000000000000000000000000000')
RETURNS varbit AS
$func$
SELECT overlay(base PLACING val FROM bit_length(base) - bit_length(val))
$func$ LANGUAGE sql IMMUTABLE;
Snabbare om du kan arbeta med varbit
värden till att börja med. (Fördelen är (delvis) ogiltig om du måste casta text
till varbit
i alla fall.)
Ring:
SELECT lpad_bits3(b'1001100111000', '00000000000000000000000000000000');
SELECT lpad_bits3(b'1001100111000', repeat('0', 32)::varbit);
Vi kanske överlappar funktionen med en variant som tar ett heltal för att generera base
själv:
CREATE OR REPLACE FUNCTION lpad_bits3(val varbit, sz int = 32)
RETURNS varbit AS
$func$
SELECT overlay(repeat('0', sz)::varbit PLACING val FROM sz - bit_length(val))
$func$ LANGUAGE sql IMMUTABLE;
Ring:
SELECT lpad_bits3(b'1001100111000', 32;
Relaterat:
- Postgresql-konvertera bitar som varierar till heltal
- Konvertera hex i textrepresentation till decimaltal