Chà, nếu nó "có vẻ sử dụng" thì bạn nên thực hiện một chút kỹ thuật đảo ngược và kiểm tra chính xác những gì được gọi và mã phân tách của hàm.
Tuy nhiên, nếu bạn muốn tìm hiểu sâu hơn về nội bộ của Oracle thì cách làm sau có thể hữu ích.
Trước hết, bạn phải tìm ra hàm C bên trong được gọi là gì, để làm được điều đó, bạn có thể thực thi một số đoạn mã chạy dài trong một phiên. Tôi đã chạy cái này
select avg(ora_hash(rownum)) id from
(select rownum from dual connect by rownum <= 1e4),
(select rownum from dual connect by rownum <= 1e4);
Nó cũng có thể là mã PL / SQL, bạn chỉ cần đảm bảo rằng bạn liên tục gọi ora_hash.
Trong khi nó đang chạy
-
Nếu bạn trên Windows thì bạn có thể sử dụng ostackprof của TANEL PODER ( https://blog.tanelpoder.com/2008/10/31/advanced-oracle-troubleshooting-guide-part-9-process-stack -profiling-from-sqlplus-using-ostackprof / )
-
Nếu bạn trên * nix thì bạn có thể sử dụng dtrace ( http://www.oracle.com/technetwork/articles/servers-storage-dev/dtrace-on-linux-1956556.html ), Đồ thị ngọn lửa (kịch bản sử dụng https://blog.dbi -services.com/oracle-database-multilingual-engine-mle/ )
Tôi đã thử nghiệm trên Windows và có vẻ như ora_hash là ...-> evaopn2 () -> evahash () -> ...
Bây giờ hãy google cho evahash. Chúng tôi rất may mắn vì có một tệp tiêu đề trên trang web chính thức https://oss.oracle.com/projects/ocfs-tools/src/braches/new-dir-format/libocfs/Linux/inc/ocfshash.h có liên kết tới evahash.
Và cuối cùng là trang có mã C thực tế http://burtleburtle.net/bob/hash/ evahash.html
Cho đến nay rất tốt, chúng tôi nhớ rằng chúng tôi có thể sử dụng hàm C bên ngoài trong Oracle nếu chúng tôi xây dựng nó thành thư viện (DLL trên Windows).
Ví dụ trên Win x64 của tôi nếu tôi thay đổi chữ ký hàm thành
extern "C" ub4 hash( ub1 *k, ub4 length, ub4 initval)
nó có thể được thực thi thành công từ Oracle, nhưng như bạn thấy, chữ ký hơi khác so với ora_hash trong Oracle. Hàm này chấp nhận giá trị, độ dài và initval của nó (có thể là hạt giống) trong khi chữ ký trong Oracle là ora_hash (expr, max_bucket, seed_value).
Hãy thử kiểm tra Oracle
SQL> select ora_hash(utl_raw.cast_to_raw('0'), power(2, 32) - 1, 0) oh1,
2 ora_hash('0', power(2, 32) - 1, 0) oh2,
3 ora_hash(0, power(2, 32) - 1, 0) oh3,
4 ora_hash(chr(0), power(2, 32) - 1, 0) oh4
5 from dual;
OH1 OH2 OH3 OH4
---------- ---------- ---------- ----------
3517341953 3517341953 1475158189 4056412421
C
int main()
{
ub1 ta[] = {0};
ub1* t = ta;
cout << hash(t, 1, 0) << endl;
ub1 ta0[] = {'0'};
ub1* t0 = ta0;
cout << hash(t0, 1, 0) << endl;
return 0;
}
1843378377
4052366646
Không có số nào phù hợp. Vậy vấn đề là gì? Ora_hash chấp nhận các tham số thuộc hầu hết mọi loại (ví dụ:select ora_hash(sys.odcinumberlist(1,2,3)) from dual
) trong khi hàm C nhận giá trị dưới dạng mảng byte. Điều này có nghĩa là một số chuyển đổi xảy ra trước khi gọi hàm. Vì vậy, trước khi sử dụng hàm băm C đã đề cập, bạn phải tìm ra cách giá trị thực được chuyển đổi trước khi chuyển cho nó.
Bạn có thể tiến hành thiết kế ngược các mã nhị phân Oracle bằng cách sử dụng tia hex IDA PRO + nhưng có thể mất vài ngày. Không đề cập đến các chi tiết cụ thể về nền tảng.
Vì vậy, nếu bạn muốn bắt chước ora_hash, tùy chọn dễ nhất là cài đặt phiên bản Oracle express và sử dụng nó để gọi ora_hash.
Tôi hy vọng điều đó thật thú vị. Chúc các bạn thành công.
Cập nhật
ora_hash và dbms_utility.get_hash_value có thể được ánh xạ với nhau (xem https:/ /jonathanlewis.wordpress.com/2009/11/21/ora_hash- Chức năng/ )
SQL> select dbms_utility.get_hash_value('0', 0 + 1, 1e6 + 1) ha1,
2 ora_hash('0', 1e6, 0) + 1 ha2
3 from dual;
HA1 HA2
---------- ----------
338437 338437
Nếu chúng ta mở gói phần thân của dbms_utility, chúng ta sẽ thấy khai báo sau
function get_hash_value(name varchar2, base number, hash_size number)
return number is
begin
return(icd_hash(name, base, hash_size));
end;
và
Hàm function icd_hash(name varchar2,
base binary_integer,
hash_size binary_integer) return binary_integer;
pragma interface(c, icd_hash);
Hãy google cho icd_hash
và chúng tôi có thể thấy rằng nó được ánh xạ tới _psdhsh
( https://yurichev.com/blog/50/
). Bây giờ là lúc để tháo rời oracle.exe và trích xuất mã cho _psdhsh
từ nó. Có lẽ tôi sẽ dành một chút thời gian cho việc này vào năm sau.