Dlaczego?
PL/pgSQL wykonuje zapytania SQL, takie jak przygotowane instrukcje . Instrukcja zastępowania parametrów:
Zwróć uwagę na termin wartości . Sparametryzować można tylko wartości rzeczywiste, ale nie słowa kluczowe, identyfikatory lub nazwy typów. 32
w bit(32)
wygląda jak wartość, ale modyfikator typu danych jest tylko „wartością” wewnętrznie i nie można go sparametryzować. SQL wymaga znajomości typów danych na etapie planowania, nie może czekać na etap wykonania.
możesz osiągnij swój cel dzięki dynamicznemu SQL i EXECUTE
. Jako weryfikacja koncepcji :
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;
Zadzwoń:
SELECT lpad_bits(b'1001100111000', 32);
Zwróć uwagę na różnicę między sz
używane jako dosłowne do zbudowania instrukcji i jej drugiego wystąpienia, gdy jest używana jako wartość , który można przekazać jako parametr.
Szybsze alternatywy
Doskonałym rozwiązaniem dla tego konkretnego zadania jest po prostu użycie lpad()
jak Zasugerowano @Abelisto
:
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;
(Prostsza jak zwykła funkcja SQL, która umożliwia także wbudowanie funkcji w kontekście zapytań zewnętrznych).
Kilka razy szybciej niż powyższa funkcja. Mała wada:musimy rzutować do text
i wróć do varbit
. Niestety, lpad()
nie jest obecnie zaimplementowany dla varbit
. Podręcznik:
overlay()
jest dostępna, możemy mieć tańszą funkcję:
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;
Szybciej, jeśli możesz pracować z varbit
wartości na początek. (Zaleta jest (częściowo) unieważniona, jeśli musisz rzucić text
do varbit
w każdym razie.)
Zadzwoń:
SELECT lpad_bits3(b'1001100111000', '00000000000000000000000000000000');
SELECT lpad_bits3(b'1001100111000', repeat('0', 32)::varbit);
Możemy nałożyć funkcja z wariantem pobierającym liczbę całkowitą do wygenerowania base
sam:
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;
Zadzwoń:
SELECT lpad_bits3(b'1001100111000', 32;
Powiązane:
- Postgresql Konwertuj bit zmieniający się na liczbę całkowitą
- Konwertuj hex w reprezentacji tekstowej na liczbę dziesiętną