2013-03-24 10 views
5

Podczas testowania PostgreSQL's md5() function zauważyłem bardzo dziwaczne zachowanie:md5() działa z dosłowne, ale nie z danych kolumn

działa zgodnie z oczekiwaniami

SELECT md5('abc') 
--"900150983cd24fb0d6963f7d28e17f72" 

ale przy użyciu funkcji md5() w zapytanie:

SELECT request_id, md5(request_id) 
FROM Request 
ORDER BY request_id 

skutkuje tym błędem:

ERROR: function md5(integer) does not exist 
LINE 1: SELECT request_id, md5(request_id) 
         ^
HINT: No function matches the given name and argument types. You might need to add explicit type casts. 

********** Error ********** 

ERROR: function md5(integer) does not exist 
SQL state: 42883 
Hint: No function matches the given name and argument types. You might need to add explicit type casts. 
Character: 20 

Jak może istnieć funkcja nie, jeśli zadziałała w pierwszym zapytaniu? Co robię źle; jaki jest prawidłowy sposób użycia md5() w zapytaniu SELECT?

+2

To nie wydaje się dziwne. W pierwszym zapytaniu przekazałeś tekst, podczas gdy w drugim próbujesz przekazać liczby całkowite. – us2012

+0

@ us2012: tak, to różnica. –

+0

Ogólnie nie ma większego sensu przyjmowanie wartości md5 liczby całkowitej, więc byłbym zainteresowany tym, dlaczego próbujesz to zrobić. –

Odpowiedz

10

Funkcja oczekuje, że tekst będzie parametrem. Rzucić go:

SELECT request_id, md5(request_id::text) 
FROM Request 
ORDER BY request_id 

funkcję o nazwie md5 przyjmującą parametr całkowitą nie istnieje, ale można go utworzyć:

create function md5(integer) 
returns text as $$ 

select md5($1::text); 

$$ language sql immutable; 

Wtedy nie będzie 3 podpisy dla md5:

=> \df md5 
          List of functions 
    Schema | Name | Result data type | Argument data types | Type 
------------+------+------------------+---------------------+-------- 
pg_catalog | md5 | text    | bytea    | normal 
pg_catalog | md5 | text    | text    | normal 
public  | md5 | text    | integer    | normal 

Jak wskazano w komentarzach do tej odpowiedzi, mieszanie md5 reprezentacji tekstowej liczby całkowitej może nie być tym, czego potrzebujesz. Aby mieć hash pliku binarnego podpis MD5 przyjmowanie parametru bytea powinien być stosowany:

select md5(('\x' || right('0000000' || to_hex(200), 8))::bytea); 
       md5     
---------------------------------- 
b7b436d004c1cc0501bee9e296d2eaa4 

i wymienić uprzednio utworzoną funkcję:

create or replace function md5(integer) 
returns text as $$ 

select md5(('\x' || right('0000000' || to_hex($1), 8))::bytea); 

$$ language sql immutable; 
+0

Prawdziwa historia. Zorientowałem to zaraz po tym, jak napisałem pytanie. Dzięki Clodoaldo. –

+2

Pamiętaj, że rzutowanie liczby całkowitej na tekst oznacza, że ​​bierzesz md5 * reprezentacji tekstowej liczby całkowitej *. To może nie być to, co zamierzacie, komunikując się z innymi systemami. Jeśli naprawdę chcesz pobrać md5 z binarnej reprezentacji liczby całkowitej, musisz użyć języka proceduralnego, takiego jak pl/perl, pl/python, itp., Aby pobrać md5 odpowiedniej reprezentacji binarnej (podpisany 32-bitowy mały endian, dla przykład). –

+1

@Craig Good point. Wygląda jednak na to, że język proceduralny nie jest konieczny. Czy może czegoś brakuje? –

0

błąd jest trochę mylące; funkcja md5() istnieje, po prostu nie działa dla liczb całkowitych. Użyj osadzonego CAST() funkcję konwersji całkowitą pole na tekst, a to będzie działać:

SELECT request_id, md5(CAST(request_id AS TEXT)) 
FROM Request 
ORDER BY request_id 

--1;"c4ca4238a0b923820dcc509a6f75849b" 
--2;"c81e728d9d4c2f636f067f89cc14862c" 
--etc 
3

W ogóle to nie ma sensu, aby wziąć MD5 całkowitej. Wydaje się prawdopodobne, że próbujesz ukryć sekwencję, aby pojawiła się ona częściowo losowo. Jeśli tak, to jest o wiele lepszy sposób:

Użyj pseudo_encrypt function listed on the PostgreSQL wiki. Jest to o wiele łatwiejsze niż próba pobrania md5 z liczby całkowitej, a następnie (prawdopodobnie) skrócenie tego.

Powyższe dane mają wartość , a nie - zapewniają dużą losowość kryptograficzną, ale nie umożliwiają również podejścia. Jeśli chcesz, aby identyfikatory Twoich żądań były naprawdę nieprzewidywalne ze względów bezpieczeństwa, a nie tylko nieoczywiste w zwykłym skrócie, powinieneś używać silnego generatora liczb losowych kryptograficznych i być przygotowanym na radzenie sobie z duplikatami za pomocą okien czasowych itp.

+0

Po prostu próbuję wygenerować nieoczywistą, nie powtarzającą się wartość, którą można wykorzystać do sprawdzenia rekordu. Tak więc moim jasnym (?) Pomysłem jest zrobienie jakiegoś szyfrowania na PL Tble. Wymagana jest anonimowość w zakresie bezpieczeństwa, ponieważ zwykli użytkownicy (osoby zgłaszające bilety) nie będą mieć loginu. W każdym razie, wylądowałem na użyciu 'REPLACE (request_id :: text, '1234567890', 'abcdefghij')' aby wykonać to "szyfrowanie". –

+0

PS - Twoja "Awooga! Awooga!" wciąż mnie pęka. –

+1

@JeromyFrench Co mogę powiedzieć, uwielbiam Holly i lubię robić dowcipy tylko my, starsi, dostaniemy ;-). Podobnie jak wykładowca, który miałam na uni, który w swoich rozmowach byłby niezwykle zabawnym odniesieniem do Małpy; czterech lub pięciu z nas w teatrze rozpłakałoby się ze śmiechu, a wszyscy inni patrzyliby na nas, jakbyśmy oszaleli. –

0

I'm just trying to generate a non-obvious, non-repeating, value which can be used to look-up a record.

Potrzebne jest hash bijective. Używam funkcji procesora CRC w niestandardowej funkcji C. Dla procesorów, które nie mają tej funkcji, można użyć tabeli odnośników.

Takie podejście gwarantuje unikalną liczbę "losowo wyglądającą" dla każdego unikalnego wejścia 32-bitowego.

Jeśli wiesz, jak generować funkcje C (nie jest to trywialne), łatwo będzie sprawdzić, jak używać CRC.

Powiązane problemy