Backport(バックポート) #4067
完了検索時の日付の範囲指定にて存在しない日付を設定してしまう場合がある
100%
説明
Overview (現象)¶
日記が存在する場合に、カレンダーの日付にリンクが設定されるが12月だけリンクが設定されない。
Causes (原因)¶
https://github.com/tejimaya/opDiaryPlugin/blob/dev-1.5.x/lib/model/doctrine/PluginDiaryTable.class.php#L202-L217
上記箇所 addDateQuery() にて期間指定の where句 の生成を行っているが、$end に 引数の 日 または 月 に 1 を加算したものを設定しているため、$end が存在しない日付になることがある。
例: 引数の $month が 12 であった場合、 $end に 13 月 として設定される。
なお、下記のように MySQL の場合は存在しない日付を指定しても意図した結果が返却される(Warningが発生)が、MariaDB の場合は意図した結果が返却されない。
確認環境: MySQL 5.7.11 Homebrew, MariaDB 10.0.28
MySQLの場合
mysql> SELECT id, created_at FROM diary WHERE (member_id = 1 AND created_at >= '2015-12-01 00:00:00' AND created_at < '2015-13-01 00:00:00');
+----+---------------------+
| id | created_at |
+----+---------------------+
| 3 | 2015-12-06 09:54:52 |
+----+---------------------+
1 row in set, 3 warnings (0.00 sec)
MariaDBの場合
MariaDB [openpne]> SELECT id, created_at FROM diary WHERE (member_id = 1 AND created_at >= '2015-12-01 00:00:00' AND created_at < '2015-13-01 00:00:00');
Empty set, 1 warning (0.00 sec)
Way to fix (修正内容)¶
http://php.net/manual/ja/function.strtotime.php
strtotime を使用して計算するようにする。
(補足)
https://github.com/openpne/OpenPNE3/blob/master/doc/ja/OpenPNE3_Setup_Guide.txt#L25-L26
OpenPNEでは、MySQL で動作させることを想定しているため、MySQL で動作するのであれば修正対象とならないかもしれないが、
不正な日付が設定されてしまうと考えると、DBの種類にかかわらず修正すべきだと思います。
なお、 sql_mode に STRICT_ALL_TABLES を設定した場合でも、現在のところ特に影響はないようです。
・sql_mode に STRICT_ALL_TABLES が設定されていない場合
mysql> SHOW GLOBAL VARIABLES LIKE 'sql_mode';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| sql_mode | |
+---------------+-------+
1 row in set (0.00 sec)
mysql> SELECT id, created_at FROM diary WHERE (member_id = 1 AND created_at >= '2015-12-01 00:00:00' AND created_at < '2015-13-01 00:00:00');
+----+---------------------+
| id | created_at |
+----+---------------------+
| 3 | 2015-12-06 09:54:52 |
+----+---------------------+
1 row in set, 3 warnings (0.01 sec)
mysql> SHOW WARNINGS\G
*************************** 1. row ***************************
Level: Warning
Code: 1292
Message: Incorrect datetime value: '2015-13-01 00:00:00' for column 'created_at' at row 1
*************************** 2. row ***************************
Level: Warning
Code: 1292
Message: Incorrect datetime value: '2015-13-01 00:00:00' for column 'created_at' at row 1
*************************** 3. row ***************************
Level: Warning
Code: 1292
Message: Incorrect datetime value: '2015-13-01 00:00:00' for column 'created_at' at row 1
3 rows in set (0.00 sec)
・sql_mode に STRICT_ALL_TABLES が設定されている場合
mysql> SET GLOBAL sql_mode=STRICT_ALL_TABLES;
Query OK, 0 rows affected, 1 warning (0.00 sec)
mysql> SHOW GLOBAL VARIABLES LIKE 'sql_mode';
+---------------+-------------------+
| Variable_name | Value |
+---------------+-------------------+
| sql_mode | STRICT_ALL_TABLES |
+---------------+-------------------+
1 row in set (0.00 sec)
mysql> SELECT id, created_at FROM diary WHERE (member_id = 1 AND created_at >= '2015-12-01 00:00:00' AND created_at < '2015-13-01 00:00:00');
+----+---------------------+
| id | created_at |
+----+---------------------+
| 3 | 2015-12-06 09:54:52 |
+----+---------------------+
1 row in set, 3 warnings (0.00 sec)
mysql> SHOW WARNINGS\G
*************************** 1. row ***************************
Level: Warning
Code: 1292
Message: Incorrect datetime value: '2015-13-01 00:00:00' for column 'created_at' at row 1
*************************** 2. row ***************************
Level: Warning
Code: 1292
Message: Incorrect datetime value: '2015-13-01 00:00:00' for column 'created_at' at row 1
*************************** 3. row ***************************
Level: Warning
Code: 1292
Message: Incorrect datetime value: '2015-13-01 00:00:00' for column 'created_at' at row 1
3 rows in set (0.00 sec)
・MariaDBの場合
MariaDB [openpne]> set @sql_mode = 'ALLOW_INVALID_DATES';
Query OK, 0 rows affected (0.00 sec)
MariaDB [openpne]> select @sql_mode;
+---------------------+
| @sql_mode |
+---------------------+
| ALLOW_INVALID_DATES |
+---------------------+
1 row in set (0.00 sec)
MariaDB [openpne]> SELECT id, created_at FROM diary WHERE (member_id = 1 AND created_at >= '2015-12-01 00:00:00' AND created_at < '2015-13-01 00:00:00');
Empty set, 1 warning (0.00 sec)
Warning (Code 1292): Incorrect datetime value: '2015-13-01 00:00:00'
参考:
MySQLのStrict Modeを有効にした場合に生じる問題を調査
https://redmine.openpne.jp/issues/4033