2017年3月26日日曜日

[Emacs][Elisp]Hook

hook で定義されたアクションが実行される時に紐付けされた hook funcsion が実行される。例えば suspend-hook は Emacs が suspend される直前に実行される hook となる。
add-hook
add-hook 関数を使うことで定義済み hook 変数に関数を追加できる
(add-hook 'text-mode-hook 'turn-on-auto-fill)
text-mode の場合は disable truncate にする
(add-hook 'text-mode-hook
 (lambda() (setq truncate-lines nil)))

[Emacs][Elisp]HTTP 通信

scratch バッファで Elisp による HTTP 通信をしてみた
各命令の最後で Ctrl + j により実行
; TCP コネクション (localhost:80) をはる
; open-network-stream は返値に process 名を返してくるので、それを proc に格納する
(setq proc (open-network-stream "http-proc" "*test-http-buffer*" "localhost" 80))
#
; proc の状態を確認
(process-status proc)
open
; proc に対して送る coding を指定する
(set-process-coding-system proc 'binary 'binary)
nil
; proc に文字列を送る
(process-send-string
proc
(format(concat
"GET / HTTP/1.0\r\n"
"\r\n")))
nil
指定した *test-http-buffer* に結果が表示される
Process http-proc connection broken by remote peer
HTTP/1.1 200 OK
Date: Thu, 06 Aug 2009 13:59:44 GMT
Server: Apache/2.2.9 (Win32) DAV/2 mod_ssl/2.2.9 OpenSSL/0.9.8i mod_autoindex_color mod_python/3.3.1 Python/2.5.2 PHP/5.2.6
Last-Modified: Fri, 06 Mar 2009 23:42:57 GMT
ETag: "6000000000669-1bc-4647bd829e8db"
Accept-Ranges: bytes
Content-Length: 444
Connection: close
Content-Type: text/html
<html>
<head>
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; CHARSET=utf-8">
<title>Test page</title>
</head>
<body>
Hello, world
</body>
</html>
Process http-proc connection broken by remote peer

open-network-stream
open-network-stream NAME BUFFER-OR-NAME HOST SERVICE
TCP 接続を確立する
Table: open-network-stream の引数
引数内容
NAMEprocess 名を指定する
BUFFER-OR-NAMEこの TCP コネクションに割り付けられるバッファ名
HOST接続先ホスト
SERVICEネットワークサービス名 または ポート番号
process-status
process-status PROCESS-NAME
PROCESS-NAME で指定したプロセスの状態を返す
Table: process-status の引数
引数内容
PROCESS-NAMEプロセス名
Table: process-status の返値
返値意味
runプロセスは running 状態
stopプロセスは停止している、再開可能
exitプロセスは終了している
signalプロセスは fatal signal を受けた
openネットワークコネクションが open している
closedネットワークコネクションは close した
connectnon-blocking コネクション、完了待ち
failednon-blocking コネクション、失敗
listenネットワークサーバが listen 中
nil指定したプロセス名のプロセスは存在しない
set-process-coding-system
set-process-coding-system PROCESS &optional DECODING-SYSTEM ENCODING-SYSTEM
PROCESS で指定したプロセスとの output/input 用コーディングを指定する
Table: set-process-coding-system の引数
引数 内容
PROCESSプロセス名
DECODING-SYSTEMプロセスからの output コーディング
ENCODING-SYSTEMプロセスへの input コーディング
process-send-string
process-send-string PROCESS STRING
プロセスに対して文字列を送る
Table: process-send-string の引数
引数 内容
PROCESSプロセス名
STRING文字列

[Emacs][Elisp]プロセス

プロセス実行
start-process

プロセスの状態を監視
フォーマット
set-process-sentinel process sentinel
process が Finished, exited abnormally など特定のイベント状態になった場合に sentinel で渡した命令を実行する
(defun ls-test ()
  (interactive)
  (defun msg-me (process event)
  (princ
    (format "Process: %s had the event [%s]" process event)))
    (set-process-sentinel
    (start-process "ls" "*ls*" "ls" "-a")
    'msg-me)
  )

(defun ls-test2 ()
  (interactive)
  (set-process-sentinel
    (start-process "ls" "*ls*" "ls" "-a")
    (lambda (process event)
    (princ
      (format "Process: %s had the event [%s]" process event)))
    )
  )

*ls*
.
..
COPYING
addpm.exe
cmdproxy.exe
ctags.exe
ddeclient.exe
digest-doc.exe
ebrowse.exe
emacs.exe
emacsclient.exe
emacsclientw.exe
etags.exe
hexl.exe
movemail.exe
runemacs.exe
sorted-doc.exe
*Messages*
Process: ls<1> had the event [finished
]

[Emacs][Elisp]region 指定

(defun dosomething-region (pmin pmax)
  (interactive "r")
  (message "pmin:%d pmax:%d" pmin pmax)
)
region を選択して M-x dosomething-region を実行すると *Messages* バッファに以下のように表示される
pmin:405 pmax:423
interactive に "r" を渡すと選択した region の開始位置、終了位置が引数に格納される。

[Emacs][Elisp]HTTP Post の elisp を interactive 対応

POST 先のサーバ、渡すパラメータ (First name, Last name) を入力することができるようになる
(defun http-post (server fname lname)
  (interactive "sServer:\nsFirst name:\nsLast name:")
  (setq proc (open-network-stream "http-proc" "*http-buffer*" server 80))
  (set-process-coding-system proc 'binary 'binary)
  (setq content-len
    (+ (+ (+ (length "fname=") (length fname)) (length "&lname=")) (length lname)))
  (process-send-string
    proc
    (format (concat
    "POST /test.php HTTP/1.0\r\n"
    "Content-Type: application/x-www-form-urlencoded\r\n"
    "Content-Length: "
    (number-to-string content-len)
    "\r\n"
    "\r\n"
    "fname="
    fname
    "&lname="
    lname))))

[Emacs][Elisp]入力された文字列の長さを表示する

length 関数を使用して入力された文字列を表示する関数
(defun string-length (str)
  (interactive "sInput a string:")
  (setq len (length str))
  (message "String: %s (%d)" str len))
M-x string-length を実行すると mini-buffer に文字列の入力を求めるメッセージが表示される。文字列を入力すると入力した文字列とその文字数を表示する
String: hello (5)

[Emacs][Elisp]interactive 関数

コマンド実行時に質問してきてくれる interactive な関数の定義
(interactive "sWhat is your name: ")
これを実行すると mini-buffer に What is your name: と表示される。そこで文字列を入力すると結果が表示される
(interactive "sWhat your name: ")
("hoge")
数字を入力させる場合は下記のように n を先頭につける
(interactive "nInput your favorite number: ")
(5)
関数を定義して M-x 関数名 で実行すると mini-buffer に interactive で値を入力して渡すことができる
(defun add (a b)
  (interactive "nFirst argument:\nnSecond argument:")
  (setq ans (+ a b))
  (message "Ans: %d" ans))

add
M-x add を実行すると First argument:, Second argument: と mini-buffer に表示され、数値を入力する。計算結果は mini-buffer に出力される

[Emacs][Elisp]関数定義

defun を使って関数を定義する
(defun hello (a b)
  (setq ans (+ a b))
  (message "Ans: %d" ans))

hello
(hello 1 3)
"Ans: 4"
フォーマット
defun NAME ARGUMENT-LIST BODY-FORMS
Table: defun の引数
引数意味
NAME関数名
ARGUMENT-LIST引数リスト
BODY-FORMS関数の中身

HTTP Post する elisp を関数で定義すると下記のようになる
(defun http-post (server)
  (setq proc (open-network-stream "http-proc" "*http-buffer*" server 80))
  (set-process-coding-system proc 'binary 'binary)
  (process-send-string
    proc
    (format (concat
      "POST /test.php HTTP/1.0\r\n"
      "Content-Type: application/x-www-form-urlencoded\r\n"
      "Content-Length: 23\r\n"
      "\r\n"
      "fname=hello&lname=world"))))

http-post
(http-post "localhost")
nil

[Emacs][Elisp]文字列出力

message
message 関数を使用して *Message* バッファに出力する
(message "Hello, world")
*Message* バッファには次のように出力される
Hello, world

princ
文字列出力
*scratch* バッファでテスト
(princ "hello, world")
hello, world"hello, world"

[Emacs][Elisp]バイトコンパイル

M-x byte-compile-file で el ファイルを指定すると elc ファイルを生成してくれる

[Emacs][Elisp]基礎

演算
演算, 評価, evaluation と表現する時もある
(operand arg1 arg2)
例)
(+ 1 2) は 1 + 2 を表す

代入
(variable value)
例)
(auto-fill-mode 1) は auto-fill-mode という変数に 1 を代入する
Auto fill mode: 最大幅までで文字が到達したら自動的に改行を入れる

Labmda
フォーマット
(lambda (arg-variables...)
 [documentation-string]
 [interactive-declaration]
 body-forms ...)
  • 先頭は lambda シンボルを使用する
  • labmda により以下のリストが関数であることを表している。これにより他のリストとはっきり区別をつけている。
  • documentation-string は function 定義を記述する
  • interactive-declaration は interactive code-string を記述する。すなわち M-x で使用する時のコマンド名になる
  • body-form には Lisp コードを記載する
例)
((lambda (a b c) (+ a b c))
 1 2 3)
6
(a b c) という新しい関数を登録する。内容は (+ a b c) となる。その (a b c) という関数に (1 2 3) という引数を渡した結果は 1 + 2 + 3 となるので結果は 6 となる。

2017年3月17日金曜日

[PostgreSQL]データの挿入・参照

テストデータ

テーブル名: students
idname
1Albert
3Emily
14John
テーブル名: dates
iddate
12010-02-25
22010-07-20
32012-12-15
テーブル名: test_scores
idstudent_iddate_idmathphysicschemistry
111694274
231809385
3141354238
412725368
532758587
6142465446
713635465
833858892
9143435341

テーブル作成

testdb=# CREATE TABLE test_scores (id SERIAL PRIMARY KEY, student_id INTEGER NOT NULL, date_id INTEGER NOT NULL, math INTEGER, physics INTEGER, chemistry INTEGER);
testdb=# CREATE TABLE students (id SERIAL PRIMARY KEY, name TEXT);
testdb=# CREATE TABLE dates (id SERIAL PRIMARY KEY, date DATE);

データ挿入

studentsテーブルに登録。
testdb=# INSERT INTO students (id, name) VALUES (1, 'Albert');
INSERT 0 1
testdb=# INSERT INTO students (id, name) VALUES (3, 'Emily');
INSERT 0 1
testdb=# INSERT INTO students (id, name) VALUES (14, 'John');
datesテーブルに登録。
testdb=# INSERT INTO dates (date) VALUES (date('2010-02-25'));
INSERT 0 1
testdb=# INSERT INTO dates (date) VALUES (date('2010-07-20'));
INSERT 0 1
testdb=# INSERT INTO dates (date) VALUES (date('2012-12-15'));
INSERT 0 1
test_scoreテーブルに登録。
testdb=# INSERT INTO test_scores (student_id, date_id, math, physics, chemistry) VALUES (1, 1, 69, 42, 74);
INSERT 0 1
testdb=# INSERT INTO test_scores (student_id, date_id, math, physics, chemistry) VALUES (3, 1, 80, 93, 85);
INSERT 0 1
testdb=# INSERT INTO test_scores (student_id, date_id, math, physics, chemistry) VALUES (14, 1, 35, 42, 38);
INSERT 0 1
testdb=# INSERT INTO test_scores (student_id, date_id, math, physics, chemistry) VALUES (1, 2, 72, 53, 68);
INSERT 0 1
testdb=# INSERT INTO test_scores (student_id, date_id, math, physics, chemistry) VALUES (3, 2, 75, 85, 87);
INSERT 0 1
testdb=# INSERT INTO test_scores (student_id, date_id, math, physics, chemistry) VALUES (14, 2, 46, 54, 46);
INSERT 0 1
testdb=# INSERT INTO test_scores (student_id, date_id, math, physics, chemistry) VALUES (1, 3, 63, 54, 65);
INSERT 0 1
testdb=# INSERT INTO test_scores (student_id, date_id, math, physics, chemistry) VALUES (3, 3, 85, 88, 92);
INSERT 0 1
testdb=# INSERT INTO test_scores (student_id, date_id, math, physics, chemistry) VALUES (14, 3, 43, 53, 41);

参照

結合したテーブルを表示する。
testdb=# SELECT * FROM test_scores JOIN students ON test_scores.student_id = students.id JOIN dates ON test_scores.date_id = dates.id;
 id | student_id | date_id | math | physics | chemistry | id | name | id | date
----+------------+---------+------+---------+-----------+----+--------+----+---- --------
  1 | 1 | 1 | 69 | 42 | 74 | 1 | Albert | 1 | 2010-02-25
  2 | 3 | 1 | 80 | 93 | 85 | 3 | Emily | 1 | 2010-02-25
  3 | 14 | 1 | 35 | 42 | 38 | 14 | John | 1 | 2010-02-25
  4 | 1 | 2 | 72 | 53 | 68 | 1 | Albert | 2 | 2010-07-20
  5 | 3 | 2 | 75 | 85 | 87 | 3 | Emily | 2 | 2010-07-20
  6 | 14 | 2 | 46 | 54 | 46 | 14 | John | 2 | 2010-07-20
  7 | 1 | 3 | 63 | 54 | 65 | 1 | Albert | 3 | 2012-12-15
  8 | 3 | 3 | 85 | 88 | 92 | 3 | Emily | 3 | 2012-12-15
  9 | 14 | 3 | 43 | 53 | 41 | 14 | John | 3 | 2012-12-15
(9 行)
testdb=# SELECT test_scores.id, students.name, dates.date, test_scores.math, test_scores.physics, test_scores.chemistry FROM test_scores JOIN students ON test_scores.student_id = students.id JOIN dates ON test_scores.date_id = dates.id;
 id | name | date | math | physics | chemistry
----+--------+------------+------+---------+-----------
  1 | Albert | 2010-02-25 | 69 | 42 | 74
  2 | Emily | 2010-02-25 | 80 | 93 | 85
  3 | John | 2010-02-25 | 35 | 42 | 38
  4 | Albert | 2010-07-20 | 72 | 53 | 68
  5 | Emily | 2010-07-20 | 75 | 85 | 87
  6 | John | 2010-07-20 | 46 | 54 | 46
  7 | Albert | 2012-12-15 | 63 | 54 | 65
  8 | Emily | 2012-12-15 | 85 | 88 | 92
  9 | John | 2012-12-15 | 43 | 53 | 41
(9 行)

[PostgreSQL]基本操作

Database 作成

createuserコマンドで作成したユーザーで実行
$ createdb testdb (作成するデータベース名)
CREATE DATABASE

Databaseを使う

$ psql testdb
testdb=>

Database一覧表示

postgresユーザーで実行
$ psql
postgres=# \l
  List of databases
  Name | Owner | Encoding | Collate | Ctype | Access privileges
-----------+----------+----------+-------------+-------------+-----------------------
 postgres | postgres | UTF8 | en_US.UTF-8 | en_US.UTF-8 |
 template0 | postgres | UTF8 | en_US.UTF-8 | en_US.UTF-8 | =c/postgres +
  | | | | | postgres=CTc/postgres
 template1 | postgres | UTF8 | en_US.UTF-8 | en_US.UTF-8 | =c/postgres +
  | | | | | postgres=CTc/postgres
(3 rows)

Database削除

postgres=# drop database db_name;
DROP DATABASE

テーブルの作成

testdb=> CREATE TABLE tbl (id SERIAL PRIMARY KEY, date DATE NOT NULL, name TEXT NOT NULL, math INTEGER, physics INTEGER, chemistry INTEGER);

レコードの登録

testdb=> INSERT INTO tbl (date, name, math, physics, chemistry) VALUES (NULL, date('2010-02-25'), 'Albert', 69, 42, 74);
testdb=> INSERT INTO tbl (date, name, math, physics, chemistry) VALUES (NULL, date('2010-02-25'), 'Emily', 80, 93, 85);
testdb=> INSERT INTO tbl (date, name, math, physics, chemistry) VALUES (NULL, date('2010-02-25'), 'John', 35, 42, 38);

レコード一覧を表示

testdb=> SELECT * FROM tbl;
 id | date | name | math | physics | chemistry
----+------------+--------+------+---------+-----------
  1 | 2010-02-25 | Albert | 69 | 42 | 74
  2 | 2010-02-25 | Emily | 80 | 93 | 85
  3 | 2010-02-25 | John | 35 | 42 | 38
(3 rows)

テーブル定義の確認

testdb=> \d tbl
  Table "public.tbl"
  Column | Type | Modifiers
-----------+---------+--------------------------------------------------
 id | integer | not null default nextval('tbl_id_seq'::regclass)
 date | date | not null
 name | text | not null
 math | integer |
 physics | integer |
 chemistry | integer |
Indexes:
  "tbl_pkey" PRIMARY KEY, btree (id)

psqlコマンド終了

testdb=> \q

postgresqlを再起動

# service postgresql restart

[CentOS][PostgreSQL]インストール

インストール

# yum install postgresql
# yum install postgresql-server

サービスの起動

# service postgresql start
postgresql サービスを開始中:            [  OK  ]

データベースクラスタの作成

# su - postgres
$ echo $PGDATA
/var/lib/pgsql/data
$ initdb --encoding=UTF8 --no-locale

ユーザー作成

  1. postgresユーザーに移行
    $ su -  postgres
    
  2. ユーザー作成
  3. $ createuser
    Enter name of role to add: xxxx
    Shall the new role be a superuser? (y/n) n
    Shall the new role be allowed to create databases? (y/n) y
    Shall the new role be allowed to create more new roles? (y/n) n
    CREATE ROLE
    

一般ユーザーの作成

  1. postgresユーザーに移行
    $ su -  postgres
    
  2. ユーザー作成
  3. $ createuser username
    
  4. ユーザーが作成されていることを確認する
    $ psql
    postgres=# SELECT usename,usesuper from pg_user;
      usename | usesuper
     ----------+----------
      postgres | t
      xxxx | f
    (2 rows)
    
    postgres=# \q
    

phpPgAdminのインストール

  1. phpPgAdminのインストール
    $ sudo yum install phpPgAdmin
    
  2. 設定
    1. postgresユーザーでログインできるように、/etc/phpPgAdmin/config.inc.phpを編集する。
      # vi /etc/phpPgAdmin/config.inc.php
      $conf['extra_login_security'] = false; ← trueをfalseに変更する
      
    2. PostgreSQL, httpdを再起動する。
      # service postgresql restart
      # service httpd restart
      
  3. 動作確認
    http://localhost/phpPgAdmin/にブラウザでアクセスする。