LoginSignup
0
0

More than 5 years have passed since last update.

PostgreSQLを入れてからパスワード認証で使えるようにしてC言語で関数を作って取り込むまで

Posted at

C言語で実装した関数が使えないことが分かったので,ここに書き捨てることにする.
ついでに動作確認に手元へpsqlの環境を作ったので合わせてメモをしておく.

PostgreSQL

インストール

sudo apt-get install postgresql-9.5 postgresql-server-dev-9.5

設定

  • パスワードを設定するsqlを走らせる.
    パスワードがコマンドラインヒストリに残るのが気にするなら,ファイルを作って実行した方がいいかも.下の例はのパスワードは`postgres'

    create_password.sql
    ALTER ROLE postgres WITH PASSWORD 'postgres';
    
    sudo su postgres -c 'psql < create_password.sql'
    
  • パスワード認証するよう設定

    --- pg_hba.conf.orig
    +++ pg_hba.conf
    @@ -82,7 +82,7 @@
     # maintenance (custom daily cronjobs, replication, and similar tasks).
     #
     # Database administrative login by Unix domain socket
    -local   all             postgres                                peer
    +local   all             postgres                                md5
    
     # TYPE  DATABASE        USER            ADDRESS                 METHOD
    
  • postgresqlの再起動

    sudo systemctl restart postgresql.service
    
  • ログインできる

    psql -U postgres
    

関数

DB作る,TBL作る

-dオプションは-dをつけなくてもいいけど.

create_tbl.sql
DROP TABLE IF EXISTS _test;

CREATE TABLE _test (
    _value  REAL
);
sudo su postgres -c 'createdb testdb'
psql -U postgres -d testdb < create_test.sql

データを入れる

make_data.py
import numpy as np
from psycopg2 import connect

dbattr = {'user':'postgres',
        'password':'postgres',
        'host':'localhost',
        'dbname':'testdb'}

data = [[val] for val in map(float, np.random.normal(10,10,size=100))]
with connect(**dbattr) as con:
    cur = con.cursor()
    cur.executemany('INSERT INTO _test (_value) VALUES (%s)',data)
    con.commit()

関数実装してビルド

_idごとに_valueを合計して,和が大きい順に順位を返す関数を実装することにする.

mypos.c
#include "postgres.h"
#include "fmgr.h"

/* 値が
           <0   <-- -1 を返す
   0<= and <5   <--  0 を返す
   5<= and <10  <--  5 を返す
   10<=         <-- 10 を返す
   のいずれに該当するか判定して返す */

PG_FUNCTION_INFO_V1(mypos);

#ifdef PG_MODULE_MAGIC
PG_MODULE_MAGIC;
#endif

extern Datum mypos(PG_FUNCTION_ARGS);

/* 判定位置 */
int thresholds[3]   = {0, 5, 10};

/* 返り値リスト */
int returnvalues[4] = { -1, 0, 5, 10 };

Datum mypos(PG_FUNCTION_ARGS)
{
    float4 x = PG_GETARG_FLOAT4(0);

    int i;

    for (i=0; i<3; ++i)
        if (x<thresholds[i])
            break;

    PG_RETURN_INT32(returnvalues[i]);
}

Makefile
CC := gcc
CFLAGS := -shared -I /usr/include/postgresql/9.5/server -lpq -fPIC -O3

all: mypos.o

mypos.o: mypos.c
    $(CC) $(CFLAGS) -o $@ $^

clean:
    rm -f *.o

関数登録

mypos.sql
CREATE OR REPLACE FUNCTION mypos(REAL)
RETURNS INTEGER
AS '/tmp/mypos.o'
LANGUAGE C
WITH (isStrict);
make
psql -U postgres -d testdb < mypos.sql

使ってみる

psql -U postgres -d testdb -c 'SELECT _value, mypos(_value) from _test'

結果

  _value   | mypos 
-----------+-------
   24.7577 |    10
  -8.12542 |    -1
   3.29176 |     0
   10.6288 |    10
   5.76772 |     5
   8.46606 |     5
   8.84471 |     5
  -0.35494 |    -1
   25.6629 |    10
   11.2771 |    10
   6.81214 |     5
   4.78453 |     0
   5.88952 |     5
   25.6756 |    10
   3.30392 |     0
   1.73068 |     0
   1.61298 |     0
   27.7148 |    10
   4.05851 |     0
  0.154022 |     0
  -7.96923 |    -1
   21.3401 |    10
    8.5594 |     5
   16.3689 |    10
    14.203 |    10
     4.584 |     0
(stdin):
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0