Warum?
PL/pgSQL führt SQL-Abfragen wie vorbereitete Anweisungen aus . Das Handbuch zur Parameterersetzung:
Beachten Sie den Begriff Werte . Es können nur Istwerte parametriert werden, nicht aber Schlüsselwörter, Bezeichner oder Typnamen. 32
in bit(32)
aussehen wie ein Wert, aber der Modifikator eines Datentyps ist intern nur ein "Wert" und kann nicht parametrisiert werden. SQL verlangt, Datentypen in der Planungsphase zu kennen, es kann nicht auf die Ausführungsphase warten.
Sie könnten Erreichen Sie Ihr Ziel mit dynamischem SQL und EXECUTE
. Als 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;
Aufruf:
SELECT lpad_bits(b'1001100111000', 32);
Beachten Sie die Unterscheidung zwischen sz
als literal verwendet um die Anweisung und ihr zweites Vorkommen zu erstellen, wo sie als Wert verwendet wird , der als Parameter übergeben werden kann.
Schnellere Alternativen
Eine überlegene Lösung für diese spezielle Aufgabe ist die einfache Verwendung von lpad()
wie @Abelito vorgeschlagen
:
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;
(Einfacher als einfache SQL-Funktion, die auch Funktions-Inlining erlaubt im Kontext äußerer Abfragen.)
Mehrfach schneller als die obige Funktion. Ein kleiner Fehler:Wir müssen in text
umwandeln und zurück zu varbit
. Leider lpad()
ist derzeit nicht für varbit
implementiert . Das Handbuch:
overlay()
verfügbar ist, können wir eine billigere Funktion haben:
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;
Schneller, wenn Sie mit varbit
arbeiten können Werte zu Beginn. (Der Vorteil entfällt (teilweise), wenn text
gecastet werden muss zu varbit
sowieso.)
Aufruf:
SELECT lpad_bits3(b'1001100111000', '00000000000000000000000000000000');
SELECT lpad_bits3(b'1001100111000', repeat('0', 32)::varbit);
Wir könnten überladen die Funktion mit einer Variante, die eine ganze Zahl nimmt, um base
zu generieren selbst:
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;
Aufruf:
SELECT lpad_bits3(b'1001100111000', 32;
Verwandte:
- Postgresql Konvertiert bitvariable in ganze Zahl
- Hex konvertieren in Textdarstellung als Dezimalzahl