MySQL C Uygulama Geliştirme Arayüzleri

ArticleCategory:

SoftwareDevelopment

AuthorImage:

Ozcan Gungor

TranslationInfo:

original in tr: Özcan Güngör

tr to en: Özcan Güngör

AboutTheAuthor:

1997'den beri Linux kullanıyorum. Özgürlük, esneklik ve açık-kod Linux'ta en sevdiğim özelliklerdir.

Abstract:

Bu makalede, MySQL ile birlikte gelen C Uygulama Geliştirme Arayüzlerinin (UGA) (API=Application Programming Interface) nasıl kullanabileceğimizi öğreneceğiz. Bu makaleyi anlayabilmek için C programlama dilinde şu konuların bilimesi gerekmektedir:

ArticleIllustration:

mysql logo

ArticleBody:

Giriş

C UGA kodları MySQL ile birlikte dağıtılır.mysqlclient kütüphanesinde bulunur ve C programlarıyla veritabanına ulaşmamızı sağlar.Birçok örneği MySQL'in kaynak kodları içindeki clients dizininde bulabilirsiniz.

MySQL C Değişken Tipleri

Aşağıda MySQL kütüphaesinde tamımlanmış değişken tipleri vardır.MySQL fonksiyonlarını kullanabilmek için bu değişkenlere gereksinimimiz var.Her değişkenin ayrıntıları mevcut ancak progmlama yaparken bu ayrıntıların çoğunu kullanmayacağız.

MYSQL
Bu yapı, bir veritabanına bağlanmak için kullanlan bir değişkendir.Hemen hemen her MySQL fonksiyonu tarafından kullanılır.

typedef struct st_mysql {
  NET           net;           /* Bağlantı parametreleri*/
  gptr          connector_fd;  /* SSL için bağlayıcı alan taımlayıcısı */
  char          *host,*user,*passwd,*unix_socket,*server_version,*host_info,
                *info,*db;
  unsigned int  port,client_flag,server_capabilities;
  unsigned int  protocol_version;
  unsigned int  field_count;
  unsigned int  server_status;
  unsigned long thread_id;     /* Sunucudaki bağlanıtının tanımlayıcısı(ID) */
  my_ulonglong affected_rows;
  my_ulonglong insert_id;      /* NEXTNR ile tabloya giriş 
                                yapıldığı zaman ki tanımlayıcı */
  my_ulonglong extra_info;     /* Used by mysqlshow */
  unsigned long packet_length;
  enum mysql_status status;
  MYSQL_FIELD   *fields;
  MEM_ROOT      field_alloc;
  my_bool       free_me;       /* mysql_close içinde serbest ise*/
  my_bool       reconnect;     /* 1'e eşitle eğer otomatik yeniden 
                                  bağlanma isteniyorsa */
  struct st_mysql_options options;
  char          scramble_buff[9];
  struct charset_info_st *charset;
  unsigned int  server_language;
} MYSQL;

MYSQL_RES
Bu yapı satır döndüren (SELECT, SHOW, DESCRIBE, EXPLAIN) sorguların sonuçlarını temsil eder.Bir sorgudan dönen bilgi sonuç kğmesi olarak adlandırılır.

typedef struct st_mysql_res {
  my_ulonglong row_count;
  unsigned int  field_count, current_field;
  MYSQL_FIELD   *fields;
  MYSQL_DATA    *data;
  MYSQL_ROWS    *data_cursor;
  MEM_ROOT      field_alloc;
  MYSQL_ROW     row;              /* tamponlanmamış okuma varsa*/
  MYSQL_ROW     current_row;      /* şu anki satırın tamponu*/
  unsigned long *lengths;         /* şu anki sıranın sütun uzunlukları*/
  MYSQL         *handle;          /* tamponlanmamış okumalar için*/
  my_bool       eof;              /* mysql_fetch_row tarafından kullanılır */
} MYSQL_RES;

MYSQL_ROW
Bu değişken, varinin bir satırının güvenli-tip gösterimidir ve sayılı byte katarlarının(string) bir dizisidir yani bu dizinin elemanlarını sonu \0(null) karakteriyle biten bir katar olarak kullamazsınız çünkü bu bilgiler ikilik sistem(binary) bilgiler olabilir ve içinde \0 karakterini içerebilir.

typedef char **MYSQL_ROW;   /* verileri bir katar dizisi olarak döndürür. */

MYSQL_FIELD
Bu yapı bir alan hakkındaki bilgileri tutar.Örenğin; alan adı, tipi ve uzunluğu...).mysql_fetch_field() fonksiyonunu ardarda çağırarak her alana ulaşabilirsiniz.

typedef struct st_mysql_field {
  char *name;                   /* sütunun ismi */
  char *table;                  /* sütun bir alan ise sütünun tablosu*/
  char *def;                    /* Varsayılan değer (mysql_list_fields tarafından atanır)*/
  enum enum_field_types type;   /* Alan tipi mysql_com.h'a bakın*/
  unsigned int length;          /* Sütunun uzunluğu*/
  unsigned int max_length;      /* Seçilen kümenin maksimum genişliği*/
  unsigned int flags;           /* Div bayrakları*/
  unsigned int decimals;        /* Alandaki numaraların sayısı*/
} MYSQL_FIELD;

my_ulonglong
Bu tip, satırların sayısını ve mysql_affected_rows(), mysql_num_rows ve mysql_insert_id() fonksiyonları için kullanılır.0-1.84e19 aralığındadır.Bu değeri yazdırabilmek için, bu tipi önce unsigned long tipine dönüştürüp sonra %lu biçimini kullanmalısınız.Örneğin
printf (Sütun sayısı: %lu\n", (unsigned long) mysql_num_rows(result));

typedef unsigned long my_ulonglong;

MySQL'e Bağlanma ve Bir Sorgulama Yapma

Şu anda, makinanızda MySQL'in yüklü olduğunu, bir kullanıcı ve bir veritabanı içinde bir tablonun oluşturulduğunu vasrsayıyorum.Eğer bu istenenlerle ilgili bir sorun varsa lütfen www.mysql.com adresine bakınız.

MySQL C UGA'lerini mysqlclient kütüphanesinin içinde olduğunu daha önce söylemiştik.Bu nedenle MySQL kodlarını derlerken gcc komutuna -lmysqlclient argümanını eklememiz gerkmektedir.MySQL başlık dosyaları ise /usr/include/mysql (bu yol sistemden sisteme değişebilir) altında bulunmaktadır.Kodumuza MySQL'in ana başlık dosyasını eklemek için aşağıdaki satır gerklidir:

#include <mysql/mysql.h>

Bu başlık dosyasında MySQL değşken tipleri ve temel fonksiyonlar bulunmaktadır.

Daha sonra yapmamız gereken MYSQL tipinde istediğimiz veritabanına bağlanmakta kullanacağımız bir değişken oluşturmak.Bunun için basitçe

MYSQL *mysql;

satırı yeterlidir.

Veritabanına bağlanmadan önce

mysql_init(MYSQL *mysql)

fonksiyonunu çağırarak mysql değişkenimizi başlatalım.Daha sonra

MYSQL * STDCALL mysql_real_connect(MYSQL *mysql, 
				   const char *host, 
				   const char *user,
                                   const char *passwd,
                                   const char *db,
                                   unsigned int port,
                                   const char *unix_socket,
                                   unsigned int clientflag);

fonksiyonu ile bağlatı gerçekleşir.Buradaki mysql değişkeni, mysql_init içinde kullandığımız mysql ile aynıdır.host, MySQL'in üzerinde çalıştığı makinanın adı; user, MySQL'e bağlanırken kullanacağımız kullanıcı adı; passwd, bu kulanıcıya ait şifre; db, kullancağımız veritabanının adı; port, TCP/IP bağlantsı için port numarası; unix_socket, bağlantı tipi; clientflag, mysqld'nin daha ODBC'ye benzer çalışması için gerekli bayraklar.Şimdilik 0 değerini kullanacağız.Eğer bağlantı geçekleşirse, bu fonksiyon 0 değerini döner.

Artık veritabanına bağlandık ve sorgulama yapabiliriz.Bunun için bir query katarı(string) oluşturalım:

char *query;

Bu katarı kullanarak istediğimiz SQL cümleciğini kurabilir ve sorgualamayı yapabiliriz.Sorgulama yapan fonksiyon:

int STDCALL mysql_real_query(MYSQL *mysql, 
		             const char *q,
                             unsigned int length);
Burada mysql, daha önce kullandığımız değer ile aynı.q, yapacak olduğumuz sorguya ait SQL cümleciği.Bu değer için oluturmuş olduğumuz query değerini kullanacağız.length ise sorgu cümleciğinin uzunluğudur.Eğer bir sorun çıkmaz ise fonksiyon 0 değerini döner.

Sorgu yapıldıktan sonra sonuçları kullanabilmemiz için öncelikle MYSQL_RES tipinde bir değişkene gereksinim vardır.Aşağıdaki satır bu değişkeni oluşturur:

MYSQL_RES *res;
Daha sonra
mysql_use_result(MYSQL *query)
fonksiyonu ile sorgudan çıkan sonuçları kullanabiliriz.

Sorguları kolayca yapabiliyoruz ancak onları kullanabilme için birkaç fonksiyona daha ihtiyacımız var.Bunlardan ilki

MYSQL_ROW STDCALL mysql_fetch_row(MYSQL_RES *result);
Bu fonksiyon ile elde ettiğimiz sonucu satırlar halinde alabiliyoruz.Ama farkedeceğiniz gibi bu fonksiyon MYSQL_ROW tipinde bir değişken döndürüyor.Böyle bir değişken oluşturabilmek için
MYSQL_ROW row;
satırı yeterlidir.Böylece sonucun ilk satırını row değişkenine atmış oluyoruz.Yukarıda da açıkladığım gibi bu row değişkeni katar dizisidir.Yani İlk satırın ilk sütununu row[0], ikinci sütununu row[1],... tutmaktadır.mysql_fetch_row fonksiyonunu her kullanışımızda bir sonraki satıra geçeriz.Eğer son satıra gelmiş isek fonksiyon negatif değer üretir. İşimiz bittikten sonra yapacağımız tek şey bağlantıyı kaptmaktır.Bunu için
mysql_close(MYSQL *mysql)
fonksiyonunu kullanırız.

Bir Kaç Özellik

Yapılan sorgulamadan elde ettiğimiz sonuçlar hakkında biraz bilgi edinmeye çalışalım."Yapılan sorgulamadan kaç alan elde ettik ?" sorusu ile başlayalım:Bu sorunun yanıtını
unsigned int STDCALL mysql_num_fields(MYSQL *mysql);
fonksiyonu vermektedir.Fonsiyon yapılan sorgudan çıkan alan sayısın vermektedir.Aslında fonksiyon, hangi tabloda arama yaptıysak o tablonun alan sayısını verir.

Aynı şekilde elde ettiğimiz sonuçta kaç tane satır olduğunu öğrenmek için

my_ulonglong STDCALL mysql_num_rows(MYSQL_RES *res);

fonksiyonunu kullanırız.

my_ulonglong STDCALL mysql_affected_rows(MYSQL *mysql);

fonksiyonu ekleme, silme, değiştirme işlemlerinden etkilenen satır sayısını verir.Fonksiyonun my_ulonglong tipinde veri döndürdüğüne dikkat edin.

Örnek bir kod ile bitirelim:

#include <mysql/mysql.h>
#include <stdio.h>

void main(){
	MYSQL *mysql;
        MYSQL_RES *res;
        MYSQL_ROW row;
        char *query;
        int t,r;

        mysql_init(mysql);
        if (!mysql_real_connect(mysql,"localhost",
                   "mysql","mysql","deneme",0,NULL,0))
        {
            printf( "Veritabanına bağlanırken hata oluştu.Hata kodu: %s\n",
                       mysql_error(mysql));
        }
        else printf("Bağlandı...\n");

        query="select * from Deneme";

        t=mysql_real_query(mysql,query,(unsigned int) strlen(query));
        if (t)
        {
           printf("Sorgulama yaparken hata oluştu.Hata kodu: %s\n",
                   mysql_error(mysql));
        }
        else printf("Sorguladı...\n");
        res=mysql_use_result(mysql);
        for(r=0;r<=mysql_field_count(mysql);r++){
                row=mysql_fetch_row(res);
                if(row<0) break;
                for(t=0;t<mysql_num_fields(res);t++){
                        printf("%s ",row[t]);
                }
                printf("\n");
        }
	mysql_close(mysql);
}

Önerilen Kaynaklar