Pourquoi ?
PL/pgSQL exécute des requêtes SQL comme des instructions préparées . Le manuel sur la substitution de paramètres :
Notez le terme valeurs . Seules les valeurs réelles peuvent être paramétrées, mais pas les mots clés, les identificateurs ou les noms de type. 32
en bit(32)
il a l'air comme une valeur, mais le modificateur d'un type de données n'est qu'une "valeur" en interne et ne peut pas être paramétré. SQL exige de connaître les types de données au stade de la planification, il ne peut pas attendre le stade de l'exécution.
Vous pourriez atteignez votre objectif avec SQL dynamique et EXECUTE
. En tant que preuve de 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;
Appel :
SELECT lpad_bits(b'1001100111000', 32);
Notez la distinction entre sz
étant utilisé comme littéral pour construire l'instruction et sa seconde occurrence où elle est utilisée comme valeur , qui peut être passé en paramètre.
Alternatives plus rapides
Une solution supérieure pour cette tâche particulière consiste simplement à utiliser lpad()
comme @Abelisto a suggéré
:
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;
(Plus simple que la fonction SQL simple, qui permet également l'intégration de fonctions dans le contexte de requêtes externes.)
Plusieurs fois plus rapide que la fonction ci-dessus. Un défaut mineur :nous devons caster en text
et retour à varbit
. Malheureusement, lpad()
n'est actuellement pas implémenté pour varbit
. Le manuel :
overlay()
est disponible, nous pouvons avoir une fonction moins chère :
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;
Plus rapide si vous pouvez travailler avec varbit
valeurs pour commencer. (L'avantage est (partiellement) annulé, si vous devez caster text
en varbit
de toute façon.)
Appel :
SELECT lpad_bits3(b'1001100111000', '00000000000000000000000000000000');
SELECT lpad_bits3(b'1001100111000', repeat('0', 32)::varbit);
Nous pourrions surcharger la fonction avec une variante prenant un entier pour générer base
lui-même :
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;
Appel :
SELECT lpad_bits3(b'1001100111000', 32;
Connexe :
- Postgresql Convertir un bit variable en entier
- Convertir l'hex dans la représentation textuelle en nombre décimal