Project

General

Profile

Backport(バックポート) #4067

Updated by kaoru n about 6 years ago

h3. Overview (現象)

日記が存在する場合に、カレンダーの日付にリンクが設定されるが12月だけリンクが設定されない。

h3. Causes (原因)

https://github.com/tejimaya/opDiaryPlugin/blob/master/lib/model/doctrine/PluginDiaryTable.class.php#L202-L217
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の場合
<pre><code class="sql">
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)
</code></pre>

MariaDBの場合
<pre><code class="sql">
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)
</code></pre>

h3. 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 が設定されていない場合
<pre><code class="sql">
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)
</code></pre>

・sql_mode に STRICT_ALL_TABLES が設定されている場合
<pre><code class="sql">
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)
</code></pre>

・MariaDBの場合
<pre><code class="sql">
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'
</code></pre>

参考:
MySQLのStrict Modeを有効にした場合に生じる問題を調査
https://redmine.openpne.jp/issues/4033

Back