Tja, hvis det "ser ud til at bruge", så giver det mening at lave lidt omvendt konstruktion og tjekke, hvad der præcist hedder, og adskille koden for funktionen.
Hvis du derimod ønsker at dykke ned i Oracle internals, kan følgende hjælpe.
Først og fremmest skal du finde ud af, hvad den interne C-funktion kaldes. For at gøre det kan du udføre en lang kørende kode i én session. Jeg kørte denne
vælg avg(ora_hash(rownum)) id fra(vælg rækkenumre fra dual connect by rownum <=1e4),(vælg rownum fra dual connect by rownum <=1e4);
Det kan også være PL/SQL-kode, du skal bare sørge for, at du konstant ringer til ora_hash.
Mens den kører
-
Hvis du er på Windows, kan du bruge ostackprof af TANEL PODER(https://blog.tanelpoder.com/2008/10/31/advanced-oracle-troubleshooting-guide-part-9-process-stack -profilering-fra-sqlplus-bruger-ostackprof/ )
-
Hvis du er på *nix, kan du bruge dtrace(http://www.oracle.com/technetwork/articles/servers-storage-dev/dtrace-on-linux-1956556.html ), Flame Graph (brugsscenarie https://blog.dbi -services.com/oracle-database-multilingual-engine-mle/ )
Jeg testede på Windows og ser ud som om, at ora_hash er ...->evaopn2()->evahash() ->...
Lad os nu google efter evahash. Vi var ekstremt heldige, fordi der er en header-fil på det officielle websted https://oss.oracle.com/projects/ocfs-tools/src/branches/new-dir-format/libocfs/Linux/inc/ocfshash.h med link til evahash.
Og endelig er der en side med den faktiske C-kode http://burtleburtle.net/bob/hash/ evahash.html
Så langt så godt, vi husker, at vi kan bruge ekstern C-funktion i Oracle, hvis vi indbygger det i biblioteket (DLL på Windows).
For eksempel på min Win x64, hvis jeg ændrer funktionssignatur til
ekstern "C" ub4 hash( ub1 *k, ub4 length, ub4 initval)
det kan udføres med succes fra Oracle. Men som du kan se, adskiller signaturen sig en smule fra ora_hash i Oracle. Denne funktion accepterer værdi, dens længde og initval (kan være seed), mens signatur i Oracle er ora_hash(expr, max_bucket, seed_value).
Lad os prøve at testeOracle
SQL> vælg 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 fra dual; OH1 OH2 OH3 OH4---------- ---------- ---------- ----------3517341953 3517341953 1475158189 4056412421
C
int main(){ ub1 ta[] ={0}; ub1* t =ta; cout <
Ingen af tallene matcher. Så hvad er problemet?ora_hash accepterer parametre af næsten enhver type (for eksempel vælg ora_hash(sys.odcinumberlist(1,2,3)) fra dual
) mens C-funktionen accepterer værdi som en række bytes. Det betyder, at en vis konvertering sker før funktionskald. Før du bruger den nævnte C-hash-funktion, skal du altså finde ud af, hvordan den faktiske værdi transformeres, før du går videre til den.
Du kan fortsætte med reverse engineering af Oracle-binære filer ved hjælp af IDA PRO + hex-stråler, men det kan tage dage. For ikke at nævne platformspecifikke detaljer.
Så hvis du vil efterligne ora_hash, ville den nemmeste mulighed være at installere Oracle Express edition og bruge den til at kalde ora_hash.
Jeg håber, det var interessant. Held og lykke.
Opdater
ora_hash og dbms_utility.get_hash_value kan kortlægges til hinanden (se https:/ /jonathanlewis.wordpress.com/2009/11/21/ora_hash-function/ )
SQL> vælg dbms_utility.get_hash_value('0', 0 + 1, 1e6 + 1) ha1, 2 ora_hash('0', 1e6, 0) + 1 ha2 3 fra dual; HA1 HA2---------- ---------- 338437 338437
Hvis vi udpakker pakketeksten af dbms_utility, vil vi se følgende erklæring
funktion get_hash_value(navn varchar2, basisnummer, hash_size nummer) returnummer er start return(icd_hash(navn, base, hash_size)); ende;
og
funktion icd_hash(navn varchar2, basis binært_heltal, hash_størrelse binært_heltal) returner binært_heltal; pragma interface(c, icd_hash);
Lad os google efter icd_hash
og vi kan finde ud af, at det er mappet til _psdhsh
(https://yurichev.com/blog/50/
). Nu er det tid til at skille oracle.exe ad og udtrække kode til _psdhsh
fra det. Måske vil jeg bruge lidt tid på dette næste år.