Oracle
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> Oracle

Thuật toán được sử dụng bởi hàm ORA_HASH là gì?

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

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;

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.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Các chức năng ngày giờ của Oracle (Danh sách đầy đủ)

  2. cách gọi hàm oracle trong mybatis

  3. Tôi có chương trình mà tôi muốn so sánh các ngày mang theo và mang lại dữ liệu mong muốn

  4. Làm cách nào để chỉ trích xuất giá trị ngày tháng từ trường ngày tháng trong Oracle?

  5. Học các biến ràng buộc trong PL / SQL cùng với Đầu vào và Đầu ra Tính toán DBMS_OUTPUT.PUT_LINE