プロジェクト

全般

プロフィール

Bug(バグ) #4066

kaoru n7年以上前に更新

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 の場合は存在しない日付を指定しても意図した結果が返却されるが、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 (修正内容)

https://dev.mysql.com/doc/refman/5.6/ja/date-and-time-functions.html#function_date-add
DATE_ADD 関数を使用して計算するようにする。

(補足)
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

戻る