CodeGen_MySQL_UDFでh-indexな集計関数

はてブ指数
h-index を Ruby で書いてみた
h-indexっておもしろそうなので、CodeGEN_MySQL_UDFを使って、MySQLの集計関数を作ってみることにしました。

Easy, isn't it? Your first UDF is only 5 minutes away ... :)

ってな感じで、XMLから自動生成してくれるのは相当ラクなのだが、自分のところの環境・・・CentOS5.0 + MySQL5.0(RPM版)ではそのままだと動作しなくてちょっとだけ参った。

一応、作ってはみたが。
my_hindex_mysql50.tar.gz
「select hindex(columnA) from hoge group by userid」とかそんな感じで使用可能。

なお、自動生成されたC のソースファイルは以下を修正している。

  • DBUG_ENTER はコメントアウト、DBUG_RETURN、DBUG_VOID_RETURNも通常のreturn文に置換する。おそらく元のMySQLのインストールに原因があると思うのだけど、CREATE FUNCTION の際に _db_enter_ がないというエラーが出る。
  • CodeGen_MySQL_UDF(0.9.8 ) は <start>(集計群単位の初期化処理) の内容を xxx_reset に記述してくれるが、MySQL5.0 だとここは呼び出されないので、xxx_clear に移す。


あと XMLファイル。
(なんかあれこれ試行錯誤している間によりいい算出のロジックが出てきたみたいだけどまぁいいや) [xml] <?xml version="1.0"?>

<![CDATA[ typedef struct { void *pre_p; int v; } node;

static int compare_ints(const void a, const void b) { const int da = (const int ) a; const int db = (const int ) b;

return (da < db) - (da > db); }

]]> <![CDATA[ data->p = (node ) calloc(1, sizeof(node)); data->p->pre_p = NULL; data->count = 0; ]]> <![CDATA[ node p_wk; data->p->v = val; p_wk = (node ) calloc(1, sizeof(node)); p_wk->pre_p = (void ) data->p; data->p = (node *) p_wk; data->count++; ]]> <![CDATA[ if (data->count == 0) { free(data->p); return 0; }

// nidodema kamone
int *list;
list = (int *) calloc(data->count, sizeof(int));

int i = 0;
node *p_wk;
while(data->p->pre_p != NULL) {
  p_wk = data->p->pre_p;
  list[i++] = p_wk->v;
  free(data->p);
  data->p = p_wk;
}
free(data->p);

qsort(list, data->count, sizeof(int), compare_ints);

int index = 0;
for (i=0;i<data->count;i++) {
  index++;
  if (list[i] < index) {
    index--;
    break;
  }
}
free(list);

return index;

]]> [/xml]