PostgreSQLでIPアドレスをソートする

PostgreSQL にて、IPアドレスをtext型に保存している場合、そのままソートしても意図したようにソートされない。

SELECT ip FROM nic ORDER BY ip;
      ip
--------------
 192.168.1.1
 192.168.10.1
 192.168.2.1
 192.168.20.1
 192.168.3.1


inet 型にCAST するだけ。

SELECT ip::inet FROM nic ORDER BY ip;
      ip
--------------
 192.168.1.1
 192.168.2.1
 192.168.3.1
 192.168.10.1
 192.168.20.1


参考:ネットワークアドレス型
http://www.postgresql.jp/document/8.4/html/datatype-net-types.html


という簡単な事なんだけど、以前に0詰めする方法書いてた。
shobon.hatenablog.com

何故0詰めしたのか・・・CSVに出力した後Excelでソートする時を考えての事だったか・・・

・・・覚えてない(´・ω・`)

UserAgent情報からSQLでOSとブラウザを簡易的に判別/集計する

PostgreSQLにて、DBに保存されたUserAgent情報からSQLでOSとブラウザを簡易的に判別/集計する。

  • ロボットの事は考慮していない。
  • ChromeのUserAgentには、「Safari」という文字列が含まれるので、Safariより先に判定する。
  • MSIE」は「IE 10」まで、「IE 11」は「MSIE」が削除されて「Trident」と「rv:11.0」と表示される。
  • 互換表示の場合、IE10:MSIE 7.0 と Trident/6.0 のように出てくるので、Tridentだけ判定して、「rv」があれば「rv」までを抽出。
  • Tridentとrevの間に、「Touch」「MALNJS」「MAFSJS」などが入っているものがあるが、そのまま抽出。
  • Mac OS Xのバージョンの表示は、FireFoxの場合「10.11」、その他の場合「10_11」と表記が異なる。
  • 期限切れの「Windows NT 5.1」=「Windows XP」が含まれているが、テストなので気にしない。

例えば、logテーブルのuser_agentというカラムにUserAgent情報が保存されている場合に、OSとブラウザの種類・バージョンをグループ化して件数を調べる。

db_name=> SELECT
  COUNT(*),
  CASE
    WHEN user_agent LIKE '%Macintosh%'  THEN SUBSTRING(user_agent from E'\(Mac OS[^)|;]*\)')
    WHEN user_agent LIKE '%iPad%'       THEN SUBSTRING(user_agent from E'\(iPad[^)]*\)')
    WHEN user_agent LIKE '%iPhone%'     THEN SUBSTRING(user_agent from E'\(iPhone[^)]*\)')
    WHEN user_agent LIKE '%Linux%'      THEN SUBSTRING(user_agent from E'\(X11[^)]*\)')
    WHEN user_agent LIKE '%Windows NT%' THEN SUBSTRING(user_agent from E'\(Windows NT [0-9.]+\)[)|;].*')
    ELSE user_agent
   END AS os,
  CASE
    WHEN user_agent LIKE '%Edge%'     THEN SUBSTRING(user_agent from E'\(Edge/[0-9.]+\)')
    WHEN user_agent LIKE '%Sleipnir%' THEN SUBSTRING(user_agent from E'\(Sleipnir/[0-9.]+\)')
    WHEN user_agent LIKE '%OPR%'      THEN SUBSTRING(user_agent from E'\(OPR/[0-9.]+\)')
    WHEN user_agent LIKE '%Vivaldi%'  THEN SUBSTRING(user_agent from E'\(Vivaldi/[0-9.]+\)')
    WHEN user_agent LIKE '%Firefox%'  THEN SUBSTRING(user_agent from E'\(Firefox/[0-9.]+\)')
    WHEN user_agent LIKE '%Chrome%'   THEN SUBSTRING(user_agent from E'\(Chrome/[0-9.]+\)')
    WHEN user_agent LIKE '%Trident%'  THEN SUBSTRING(user_agent from E'\(Trident/[0-9.]+;[^)]*\)')
    WHEN user_agent LIKE '%MSIE%'     THEN SUBSTRING(user_agent from E'\(MSIE [0-9.]+\)')
    WHEN user_agent LIKE '%Safari%'   THEN SUBSTRING(user_agent from E'\(Version/[0-9.]+ .*Safari/[0-9.]+\)')
    ELSE user_agent
   END AS browser
FROM
  log
GROUP BY
  os, browser
ORDER BY
  os, browser;


次のような結果になる。

 count |                 os                  |               browser
-------+-------------------------------------+-------------------------------------
     2 | Mac OS X 10.11                      | Firefox/46.0
     1 | Mac OS X 10_11_5                    | Chrome/50.0.2661.102
    10 | Mac OS X 10_11_5                    | Version/9.1.1 Safari/601.6.17
     9 | Windows NT 10.0                     | Chrome/50.0.2661.102
    19 | Windows NT 10.0                     | Edge/13.10586
     7 | Windows NT 10.0                     | Firefox/46.0
     1 | Windows NT 10.0                     | Sleipnir/6.1.11
     9 | Windows NT 10.0                     | Trident/7.0; rv:11.0
     1 | Windows NT 5.1                      | Chrome/49.0.2623.112
     1 | Windows NT 5.1                      | Firefox/46.0
     2 | Windows NT 6.0                      | Chrome/49.0.2623.112
     4 | Windows NT 6.1                      | Chrome/52.0.2743.10
    17 | Windows NT 6.1                      | Firefox/46.0
     1 | Windows NT 6.1                      | OPR/37.0.2178.43
     1 | Windows NT 6.1                      | Trident/7.0; MAFSJS; rv:11.0
    22 | Windows NT 6.1                      | Trident/7.0; rv:11.0
     1 | Windows NT 6.1                      | Vivaldi/1.1.453.59
     2 | Windows NT 6.3                      | Chrome/51.0.2704.63
     5 | Windows NT 6.3                      | Firefox/46.0
     1 | Windows NT 6.3                      | OPR/37.0.2178.43
     1 | Windows NT 6.3                      | Trident/7.0; MALNJS; rv:11.0
     3 | Windows NT 6.3                      | Trident/7.0; Touch; rv:11.0
     4 | Windows NT 6.3                      | Trident/7.0; rv:11.0
     1 | X11; Linux x86_64; rv:31.0          | Firefox/31.0
     1 | X11; Ubuntu; Linux x86_64; rv:46.0  | Firefox/46.0

CentOS 7のPHPでOCI関数を使うまで

【環境】
CentOS 7.2.1511

PHPのoci関数を利用するまでの手順。(PHP本体はインストール済みの状態)

最初に「Oracle Instant Client」を導入する。

Oracle社のWebサイトから、RPMファイルを入手する。アカウント登録が必要。

色々とパッケージがあるが、以下の2つで良い。
 ・Basic
 ・SDK

RPMコマンドでインストール。

# rpm -ivh oracle-instantclient12.1-basic-12.1.0.2.0-1.x86_64.rpm
# rpm -ivh oracle-instantclient12.1-devel-12.1.0.2.0-1.x86_64.rpm

必要なライブラリがインストールされる。

# rpm -ql oracle-instantclient12.1-basic
/usr/lib/oracle/12.1/client64/bin/adrci
/usr/lib/oracle/12.1/client64/bin/genezi
/usr/lib/oracle/12.1/client64/lib/libclntsh.so.12.1
/usr/lib/oracle/12.1/client64/lib/libclntshcore.so.12.1
/usr/lib/oracle/12.1/client64/lib/libipc1.so
/usr/lib/oracle/12.1/client64/lib/libmql1.so
/usr/lib/oracle/12.1/client64/lib/libnnz12.so
/usr/lib/oracle/12.1/client64/lib/libocci.so.12.1
/usr/lib/oracle/12.1/client64/lib/libociei.so
/usr/lib/oracle/12.1/client64/lib/libocijdbc12.so
/usr/lib/oracle/12.1/client64/lib/libons.so
/usr/lib/oracle/12.1/client64/lib/liboramysql12.so
/usr/lib/oracle/12.1/client64/lib/ojdbc6.jar
/usr/lib/oracle/12.1/client64/lib/ojdbc7.jar
/usr/lib/oracle/12.1/client64/lib/xstreams.jar

# rpm -ql oracle-instantclient12.1-devel
/usr/include/oracle/12.1/client64/ldap.h
/usr/include/oracle/12.1/client64/nzerror.h
/usr/include/oracle/12.1/client64/nzt.h
/usr/include/oracle/12.1/client64/occi.h
/usr/include/oracle/12.1/client64/occiAQ.h
/usr/include/oracle/12.1/client64/occiCommon.h
/usr/include/oracle/12.1/client64/occiControl.h
/usr/include/oracle/12.1/client64/occiData.h
/usr/include/oracle/12.1/client64/occiObjects.h
/usr/include/oracle/12.1/client64/oci.h
/usr/include/oracle/12.1/client64/oci1.h
/usr/include/oracle/12.1/client64/oci8dp.h
/usr/include/oracle/12.1/client64/ociap.h
/usr/include/oracle/12.1/client64/ociapr.h
/usr/include/oracle/12.1/client64/ocidef.h
/usr/include/oracle/12.1/client64/ocidem.h
/usr/include/oracle/12.1/client64/ocidfn.h
/usr/include/oracle/12.1/client64/ociextp.h
/usr/include/oracle/12.1/client64/ocikpr.h
/usr/include/oracle/12.1/client64/ocixmldb.h
/usr/include/oracle/12.1/client64/ocixstream.h
/usr/include/oracle/12.1/client64/odci.h
/usr/include/oracle/12.1/client64/oratypes.h
/usr/include/oracle/12.1/client64/ori.h
/usr/include/oracle/12.1/client64/orid.h
/usr/include/oracle/12.1/client64/orl.h
/usr/include/oracle/12.1/client64/oro.h
/usr/include/oracle/12.1/client64/ort.h
/usr/include/oracle/12.1/client64/xa.h
/usr/lib/oracle/12.1/client64/lib/libclntsh.so
/usr/lib/oracle/12.1/client64/lib/libclntshcore.so
/usr/lib/oracle/12.1/client64/lib/libocci.so
/usr/lib/oracle/12.1/client64/lib/ottclasses.zip
/usr/share/oracle/12.1/client64/admin/oraaccess.xsd
/usr/share/oracle/12.1/client64/demo/cdemo81.c
/usr/share/oracle/12.1/client64/demo/demo.mk
/usr/share/oracle/12.1/client64/demo/occidemo.sql
/usr/share/oracle/12.1/client64/demo/occidemod.sql
/usr/share/oracle/12.1/client64/demo/occidml.cpp
/usr/share/oracle/12.1/client64/demo/occiobj.cpp
/usr/share/oracle/12.1/client64/demo/occiobj.typ
/usr/share/oracle/12.1/client64/demo/oraaccess.xml
/usr/share/oracle/12.1/client64/demo/ott
/usr/share/oracle/12.1/client64/demo/setuporamysql.sh


次に、oci8モジュールを導入する。

PECLからoci8関数を導入。

# pecl install oci8

とするとエラーになる。

PHP 7未満の場合は、「oci8-2.0.11」を指定するようにとの事。
https://pecl.php.net/package/oci8

# pecl install oci8-2.0.11

/usr/lib64/php/modules/oci8.so が生成される。


モジュールを読み込むため、/etc/php.d/oci8.ini を作成する。

; Enable oci8 extension module
extension=oci8.so

httpdを再起動

# systemctl restart httpd

モジュールが読み込まれているか確認。

$ php -m | grep oci
oci8

phpinfo で確認する場合の例。

$ php -i | egrep -i 'oracle|oci'
/etc/php.d/oci8.ini,
oci8
OCI8 Support => enabled
OCI8 DTrace Support => disabled
OCI8 Version => 2.0.11
Oracle Run-time Client Library Version => 12.1.0.2.0
Oracle Compile-time Instant Client Version => 12.1
oci8.connection_class => no value => no value
oci8.default_prefetch => 100 => 100
oci8.events => Off => Off
oci8.max_persistent => -1 => -1
oci8.old_oci_close_semantics => Off => Off
oci8.persistent_timeout => -1 => -1
oci8.ping_interval => 60 => 60
oci8.privileged_connect => Off => Off
oci8.statement_cache_size => 20 => 20


「oci_connect」関数が存在するかチェック。

$ php --rf oci_connect
Function [ <internal:oci8> function oci_connect ] {

  - Parameters [5] {
    Parameter #0 [ <required> $username ]
    Parameter #1 [ <required> $password ]
    Parameter #2 [ <optional> $connection_string ]
    Parameter #3 [ <optional> $character_set ]
    Parameter #4 [ <optional> $session_mode ]
  }
}

存在しない場合。

$ php --rf oci_connect
Exception: Function oci_connect() does not exist

CentOS 7 へ Tigervnc Server を導入する

yum でインストール

# yum install tigervnc-server

VNCパスワードを設定(ユーザ毎)

$ vncpasswd

ディスプレイ番号「1」、解像度「1024x768」、色深度「24」でVNCプロセスを起動

$ vncserver :1 -geometry 1024x768 -depth 24

※上記はVNCサーバの起動ではなく、プロセスの起動。サービスとして扱うには、ユニットファイルを用意する必要がある。

停止する場合は、-killオプションを付けてディスプレイ番号を指定。

$ vncserver -kill :1

※上記の場合、VNCの待受けポートは5901番ポートなので、FWを適切に設定する。

Xfceを使うには、~/.vnc/xstartup の最後に以下を記載する。
「exec /etc/X11/xinit/xinitrc」の行はコメントアウト

#exec /etc/X11/xinit/xinitrc
exec xfce4-session &


Xface の導入は下記に記載しました。
shobon.hatenablog.com


CentOS 7を最小インストールした場合、日本語が文字化けするので、以下のようにする。

日本語関連のパッケージをインストール

# yum install ibus-kkc vlgothic-*

再ログインすれば良い。ダメならVNCプロセスを再起動してみる。

CentOS 7 でXfceを使う

CentOS 7にて、普段は「multi-user.target」な環境だけれど、VNC経由で一時的にGUI環境が欲しいだけの場合、インストーラで「Server With GUI」を指定すると、余計なものがたくさん入って困った。

CentOS 7を最小インストール → 後からXfceを導入、の方が余計なものが少なく、希望の要件を満たせたのでメモ。

X Windowのインストール

# yum groups install "X Window System"

epel-releaseのインストール(EPELからxfceをダウンロードするため)

# yum install epel-release

EPELリポジトリのデフォルトを無効に設定(/etc/yum.repos.d/epel.repo)

enabled=1
 ↓
enabled=0

xfceのインストール

# yum groups install --enablerepo=epel xfce

導入前後の容量は、GNOMEほど多くなく、500MBくらいの模様。

PHP5.4以降で削除される関数の一覧

一覧が欲しかったので、まとめてみた。

関数名 削除バージョン 非推奨バージョン PHPマニュアルURL  
define_syslog_variables 5.4 5.3 http://php.net/manual/ja/function.define-syslog-variables.php
import_request_variables 5.4 5.3 http://php.net/manual/ja/function.import-request-variables.php
mysqli_bind_param 5.4 5.3 http://php.net/manual/ja/function.mysqli-bind-param.php
mysqli_bind_result 5.4 5.3 http://php.net/manual/ja/function.mysqli-bind-result.php
mysqli_client_encoding 5.4 5.3 http://php.net/manual/ja/function.mysqli-client-encoding.php
mysqli_fetch 5.4 5.3 http://php.net/manual/ja/function.mysqli-fetch.php
mysqli_get_metadata 5.4 5.3 http://php.net/manual/ja/function.mysqli-get-metadata.php
mysqli_param_count 5.4 5.3 http://php.net/manual/ja/function.mysqli-param-count.php
mysqli_send_long_data 5.4 5.3 http://php.net/manual/ja/function.mysqli-send-long-data.php
session_is_registered 5.4 5.3 http://php.net/manual/ja/function.session-is-registered.php
session_register 5.4 5.3 http://php.net/manual/ja/function.session-register.php
session_unregister 5.4 5.3 http://php.net/manual/ja/function.session-unregister.php
php_logo_guid 5.5 http://php.net/manual/en/function.php-logo-guid.php
zend_logo_guid 5.5 http://php.net/manual/ja/function.zend-logo-guid.php
call_user_method 7.0 4.1 http://php.net/manual/ja/function.call-user-method.php
call_user_method_array 7.0 4.1 http://php.net/manual/ja/function.call-user-method-array.php
datefmt_set_timezone_id 7.0 5.5 http://php.net/manual/ja/intldateformatter.settimezoneid.php
dl 7.0 5.3 http://php.net/manual/ja/function.dl.php
ereg 7.0 5.3 http://php.net/manual/ja/function.ereg.php
ereg_replace 7.0 5.3 http://php.net/manual/ja/function.ereg-replace.php
eregi 7.0 5.3 http://php.net/manual/ja/function.eregi.php
eregi_replace 7.0 5.3 http://php.net/manual/ja/function.eregi-replace.php
magic_quotes_runtime 7.0 5.3 http://php.net/manual/ja/function.magic-quotes-runtime.php
mcrypt_cbc 7.0 5.5 http://php.net/manual/ja/function.mcrypt-cbc.php
mcrypt_cfb 7.0 5.5 http://php.net/manual/ja/function.mcrypt-cfb.php
mcrypt_ecb 7.0 5.5 http://php.net/manual/ja/function.mcrypt-ecb.php
mcrypt_generic_end 7.0 5.3 http://php.net/manual/ja/function.mcrypt-generic-end.php
mcrypt_ofb 7.0 5.5 http://php.net/manual/ja/function.mcrypt-ofb.php
mysql_db_query 7.0 5.3 http://php.net/manual/ja/function.mysql-db-query.php
mysql_escape_string 7.0 4.3 http://php.net/manual/ja/function.mysql-escape-string.php
mysql_list_dbs 7.0 5.4 http://php.net/manual/ja/function.mysql-list-dbs.php
set_magic_quotes_runtime 7.0 5.3 http://php.net/manual/ja/function.set-magic-quotes-runtime.php
set_socket_blocking 7.0 5.3 http://php.net/manual/ja/function.set-socket-blocking.php
split 7.0 5.3 http://php.net/manual/ja/function.split.php
spliti 7.0 5.3 http://php.net/manual/ja/function.spliti.php
sql_regcase 7.0 5.3 http://php.net/manual/ja/function.sql-regcase.php


【追記ここから(2016/4/8)】
CentOS 5/6/7 のBase.repo にあるPHPのバージョンも書いておく。

CentOS Base.repo にあるPHPのバージョン
5 5.1.6/5.3.3(php53)
6 5.3.3
7 5.4.16

【追記ここまで】

Firefoxで入力カーソルが表示されるキャレットブラウズモード

知人から、「ネット見てたら、いつのまにか入力カーソルみたいなのが出て消えないんだけど?」って聞かれた時のこと。

画面キャプチャを送って貰ったら、Firefoxのキャレットブラウズモードの事でした。

例えば、以下のような感じ。赤い矢印で指されてる部分。
f:id:savakan:20160312144613p:plain

入力フォームでもない場所で、図のような入力カーソルが表示される。

Firefox 45の場合、[オプション] - [詳細] - [一般] - [アクセシビリティ] にて、「ページ中の移動にカーソルを使用する(キャレットブラウズモード)」という項目で設定できるほか、「F7」キーを押しても切り替えが可能。

検索文字をF7でカタカナに変換してEnterを押したつもりが、検索フォームにカーソルが入っていない状態でF7を押してしまい、うっかりキャレットブラウズモードになってしまう事がある?

とは言っても、モードを切り替える注意書きが出るので、よく読まずに「はい」を選択していると思われる。(知人は多分これに該当)

f:id:savakan:20160312144607p:plain


ところで、キャレットブラウズモードになっていると、キーボードの「Home」と「End」の挙動が変わる。

通常のモード:Home→ページ最上部へ移動、End→ページ最下部へ移動

キャレットブラウズモード:Home→キャレットが行頭へ移動、End→キャレットが行末へ移動

「入力カーソルが表示されるようになった」とか「Home/Endで上下へ移動/スクロールできなくなった」事からモードが切り替わった事に気が付くので、気に入らなければ設定を戻すと良い。