psycopg2 のインストールとテストエラー

##きっかけ

CodeIQ 「進捗まあまあマーク」問題 闇落ち解答版(現在未公開) 作成中に、
sqlite3 の parametarized query でパラメータの渡し方に不審なところがあった。

で、他ではどうだ？　と考え、とりあえず PostgreSQL を試してみることにした。

##Python から PostgreSQL にどうやって繋げるの?

ググって [PythonからPostgreSQLに接続する方法] (https://www.ashisuto.co.jp/db_blog/article/20160308_postgresql_with_python.html) を見て「psycopg2」を入れることにした。

##Psycopg2 のインストール
[Psycopg2](http://initd.org/psycopg/docs/install.html#binary-install-from-pypi) のドキュメントをみて --no-binary オプションを付けてインストールすることに。

```
sudo python3 -m pip install --no-binary --allow-external psycopg2
```

python が python2 へのシンボリックリンクになっているので python3 コマンドで実行。--alow-external を付けないと入らなかったので付けた。

##テストの実行
その後、うまくインストールされているか確認するために
[Running the test suite](http://initd.org/psycopg/docs/install.html#running-the-test-suite
)
見て既存のローカルの PostgreSQL に接続してテストしようとしたがどうもうまくいかない。
既存DBを汚されるのも嫌なので psycopg2_test という DB を作成し、この DB には local から trust接続できるよう pg_hba.conf を設定し、Postgresql を restart。
環境変数 PSYCOPG2_TESTDB と PSYCOPG2_TESTDB_USER も設定したらテストが動いた。

```
python3 -c "from psycopg2 import tests; tests.unittest.main(defaultTest='tests.test_suite')" --verbose
```

##テストで失敗
でテスト結果は・・・ Fail

```
======================================================================
FAIL: test_date_value_error_sec_59_99 (psycopg2.tests.test_dates.FromTicksTestCase)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/usr/lib64/python3.6/site-packages/psycopg2/tests/test_dates.py", line 641, in test_date_value_error_sec_59_99
    self.assertEqual(s.adapted, date(2010, 5, 6))
AssertionError: datetime.date(2010, 5, 7) != datetime.date(2010, 5, 6)

----------------------------------------------------------------------
```

なんでやねん・・・って思ったがまぁロケールの問題やろと考えた。
とりあえず、対応するテストコードを確認

```test_dates.py 
    def test_date_value_error_sec_59_99(self):
        from datetime import date
        s = psycopg2.DateFromTicks(1273173119.99992)
        self.assertEqual(s.adapted, date(2010, 5, 6))

    def test_time_value_error_sec_59_99(self):
        from datetime import time
        s = psycopg2.TimeFromTicks(1273173119.99992)
        self.assertEqual(s.adapted.replace(hour=0),
            time(0, 11, 59, 999920))
```

この　`psycopg2.DateFromTicks` はローカルの時間を返すので
日本(UTC +9)では psycopg2.DateFromTicks(1273173119.99992) は 2010年5月7日になる。

```
>>> import psycopg2
>>> psycopg2.DateFromTicks(1273173119.99992).adapted
datetime.date(2010, 5, 7)
```

なお、psycopg2.TimeFromTicks のテストの方も日本では pass するがインド(UTC +5:30)では Fail する。

##とりあえず、issue に書き込み
まぁ、テストでどうでもいいことだろうけど一応 pyscopg の issue に登録した。

[Test for "DateFromTicks" and "TimeFromTicks" are failing in some region.](https://github.com/psycopg/psycopg2/issues/652)

##psycopg のパラメータ渡しのテスト。。。

で、肝心のパラメータ渡しのテスト。

```
>>> import psycopg2
>>> conn = psycopg2.connect("dbname=postgres user=naruto password=naruoka01a!")
>>> cur = conn.cursor()
>>> strSQL = "SELECT :1, :2;"
>>> cur.execute(strSQL,(1,2));
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
psycopg2.ProgrammingError: syntax error at or near ":"
LINE 1: SELECT :1, :2;
               ^
```

psycopg2 はテストしたかったパラメータのプレースフォルダの形式(`:1`)に対応していませんでしたっ orz

psycopg2 のSQL のパラメータのプレースフォルダは `%s` で名前付きの場合は `%(name)s` です。

```
>>> conn.rollback()
>>> cur.close()
>>> cur = conn.cursor()
>>> strSQL = "SELECT %s, %s;"
>>> cur.execute(strSQL,(1,2));
>>> cur.fetchall();
[(1, 2)]
>>> strSQL = "SELECT %(a)s, %(b)s;"
>>> cur.execute(strSQL,{'a':1, 'b':2})
>>> cur.fetchall()
[(1, 2)]
>>> strSQL = "SELECT %(b)s, %(a)s;"
>>> cur.execute(strSQL,{'a':1, 'b':2})
>>> cur.fetchall()
[(2, 1)]
>>> cur.close()
>>> conn.close()
```