Monday, April 22, 2013

Oracle 11gR2'de C Fonksiyonlarının PL/SQL Fonksiyonu/Yordamı olarak Kullanımı

Oracle veritabanı üzerinde, sunucu tarafta uygulama geliştirmek için PL/SQL kullanıyoruz. PL/SQL,  yapısal sorgulama diline (SQL) programlama yeteneği kazandırmaktadır. PL/SQL, fonksiyon ve yordam tanımlamak, paket oluşturmak, kendi veri tipimizi tanımlamak, döngü ve akış denetimi gibi programlamaya ilişkin tüm yapıları barındırıyor. Ancak bazen daha karmışık algoritmaları C'de ya da Java programlama dillerinde çözümlerini oluşturmak zorunda kalabiliyoruz. Bazen de daha önce C'de ya da Java'da geliştirdiğimiz bir fonksiyonu PL/SQL'de yeniden gerçeklemek ile zaman kaybetmeden kullanmak isteriz. Bu durumda ilk olarak fonsiyonunun yer aldığı kütüphaneyi Oracle veritabanı yönetim sistemine tanıtmamız gerekir:
 CREATE OR REPLACE LIBRARY funlib as '$ORACLE_HOME/bin/libfun.so';  
Burada $ORACLE_HOME isimli sistem değişkeni oracle veritabanının kurulu olduğu dizini ifade ediyor. Benim makinamda bu değişken /u01/app/oracle/product/11.2.0/dbhome_1 dizinini gösteriyor. CREATE LIBRARY komutunu çalıştırabilmek için kullanıcının bu yetkiye sahip olması gerekir. Bu yetkiyi aşağıdaki gibi bir GRANT komutu ile tanımlayabiliriz:
 GRANT CREATE LIBRARY , RESOURCE to fundb ;  
Şimdi ise C'de örnek kütüphane oluşturalım. Burada öncelikle bir başlık dosyası oluşturalım.
fun.h
 #ifndef __fun__  
 #define __fun__  
   int havefun(int);  
   double l1_norm(double *,double *,int);  
 #endif  
Ardından gerçeklemeyi c dosyasında yapıyoruz:
fun.c
1:   #include "fun.h"   
2:   #include <stdlib.h>   
3:   #include <math.h>   
4:   double l1_norm(double *fv1,double *fv2,int size){   
5:    double l1_distance=0;   
6:    int i=0;   
7:    for (i=0;i<size;++i){   
8:     l1_distance += fabs(fv1[i]-fv2[2]);   
9:    }   
10:    return 1.0 / (1.0 + exp(-l1_distance));   
11:   }   
12:   int havefun(int n){   
13:    int len=1;   
14:    if (n<=1) return len;   
15:    while (n>1){   
16:     if (n%2 == 0) n=n/2;   
17:     else n=3*n+1;   
18:     len++;   
19:    }   
20:    return len;   
21:   }   
Paylaşılan kütüphane dosyasını oluşturmak için GNU C derleyecisi ile aşağıdaki gibi derliyoruz:
 gcc -fPIC -shared -o libfun.so fun.c  
Eğer 64-bitlik bir işletim sisteminde Oracle veritabanını kullanıyorsanız derleyiciye -m64 seçeneğini de vermeniz gerekir.
Şimdi PL/SQL'de kullanıcı tanımlı fonksiyon tanımlayacağız ve bunu yaparken PL/SQL fonksiyonunu libfun.so'da tanımlı C fonksiyonları ile eşleştireceğiz:
 CREATE OR REPLACE FUNCTION l1dist (  
  fv1 FEATURE_VECTOR, fv2 FEATURE_VECTOR , sz BINARY_INTEGER )  
   RETURN NUMBER  
   AS LANGUAGE C  
   LIBRARY mylib  
   NAME "l1norm" ;  
 CREATE OR REPLACE FUNCTION havefun ( num BINARY_INTEGER )  
  RETURN BINARY_INTEGER  
  AS LANGUAGE C  
  LIBRARY mylib  
  NAME "havefun" ;  
Tanımda gözüken FEATURE_VECTOR tipini ise daha önce aşağıdaki gibi tanımlamanız gerekir:
 CREATE OR REPLACE TYPE FEATURE_VECTOR IS VARRAY(2952) OF NUMBER;  
Artık havefun fonksiyonunu sınayabiliriz:

SQL> select havefun(7) from dual;
HAVEFUN(7)
---------- 17

No comments:

Post a Comment