ユーザ用ツール

recently_commented_onが正しく機能しない

PostgreSQLをバックエンドにして、「最近のコメント」を作成しようとすると、おかしなエントリが表示されてしまいます。(MySQLの場合やSQLiteの場合はわかりません。ファイルをバックエンドにしている場合は大丈夫です。)

これは、DISTINCTの使い方が正しくないためです。大まかに言うと、MTはコメントの一覧を作成して、これを作成された日時で降順に(descend)ソートします。そしてその結果から、コメントされているエントリの一覧を作成します。このとき、ひとつのエントリに複数のコメントがあれば、当然、エントリが重複して抽出されますから、これを解消するために、DISTINCTを指定しています。ところが、DISTINCTは重複行は取り除くものの、その結果得られるエントリ一覧の順序は保証されないのです。従って、折角ソートして作った一覧を、DISTINCTが壊してしまっているのです。

とりあえず、以下のパッチをあてることで、この問題は解決します。但し、この修正を行なった後に、バックエンドをPostgreSQL以外に変更すると、おかしなことになりますので、その場合は lib/MT/Template/ContextHandlers.pm(MT-3.1xの場合はlib/MT/Template/Context.pm)をオリジナルのものに戻すようにしてください。なお、パッチはMT-3.2以降と、MT-3.1xとで微妙に違います。

余談ですが、「最近のコメント」を作るために、sort_order=“ascend”を指定するようにかいてある記事を見かけますが、このオプションは recently_commented_onには無効ですし、更にいうと、昇順(ascend)にしたら、それは最近のではなく最古のになってしまいますので、あらゆる意味で間違いです

パッチ(MT-3.2)

パッチファイル

*** MT-3.2-b1-ja.orig/lib/MT/ObjectDriver/DBI/postgres.pm       2005-09-02 16:13:00.000000000 +0900
--- MT-3.2-b1-ja/lib/MT/ObjectDriver/DBI/postgres.pm    2005-09-13 17:14:18.000000000 +0900
***************
*** 86,91 ****
--- 86,106 ----
              $sql = $s_sql . $sql;
              $w_sql .= ") t\n";
          }
+       elsif ($j_args->{'aggregate_sort'}) {
+           ## sorting with aggregate function,
+           my $as_args = $j_args->{'aggregate_sort'};
+           my $cols = $class->column_names;
+           my $s_sql = "from (select " .
+                         join(', ', map "${tbl}_$_", @$cols) .
+                       ", $as_args->{'function'}(${j_tbl}_$as_args->{'column'}) as ${tbl}_${j_tbl}_$as_args->{'column'}\n";
+           $sql = $s_sql . $sql;
+           $w_sql .= "group by " .
+                       join(',', map "${tbl}_$_", @$cols) . "\n";
+           $w_sql .= ") t\n";
+           my $dir = $as_args->{'direction'} &&
+                       $as_args->{'direction'} eq 'descend' ? 'desc' : 'asc';
+                       $w_sql .= "order by ${tbl}_${j_tbl}_$as_args->{'column'} $dir\n";
+       }
  
          if (my $n = $j_args->{limit}) {
              $n =~ s/\D//g;   ## Get rid of any non-numerics.
*** MT-3.2-b1-ja.orig/lib/MT/Template/ContextHandlers.pm        2005-09-02 16:13:00.000000000 +0900
--- MT-3.2-b1-ja/lib/MT/Template/ContextHandlers.pm     2005-09-13 17:17:15.000000000 +0900
***************
*** 866,875 ****
              require MT::Comment;
              $args{'join'} = [ 'MT::Comment', 'entry_id',
                  { blog_id => $blog_id, visible => 1 },
!                 { 'sort' => 'created_on',
!                   direction => 'descend',
!                   unique => 1,
!                   limit => $n } ];
              $no_resort = 1;
          }
          @entries = MT::Entry->load(\%terms, \%args);
--- 866,875 ----
              require MT::Comment;
              $args{'join'} = [ 'MT::Comment', 'entry_id',
                  { blog_id => $blog_id, visible => 1 },
!               { 'aggregate_sort' => { 'column' => 'created_on',
!                                         'function' => 'max',
!                                         'direction' => 'descend' },
!                    limit => $n } ];
              $no_resort = 1;
          }
          @entries = MT::Entry->load(\%terms, \%args);

パッチ(MT-3.1x)

パッチファイル

*** MT-3.121-full-ja.orig/lib/MT/ObjectDriver/DBI/postgres.pm	2004-10-01 15:18:37.000000000 +0900
--- MT-3.121-full-ja/lib/MT/ObjectDriver/DBI/postgres.pm	2005-01-18 09:54:25.000000000 +0900
***************
*** 78,83 ****
--- 78,98 ----
              $sql = $s_sql . $sql;
              $w_sql .= ") t\n";
          }
+ 	elsif ($j_args->{'aggregate_sort'}) {
+ 	    ## sorting with aggregate function,
+ 	    my $as_args = $j_args->{'aggregate_sort'};
+ 	    my $cols = $class->column_names;
+ 	    my $s_sql = "from (select " .
+                         join(', ', map "${tbl}_$_", @$cols) .
+ 			", $as_args->{'function'}(${j_tbl}_$as_args->{'column'}) as ${tbl}_${j_tbl}_$as_args->{'column'}\n";
+ 	    $sql = $s_sql . $sql;
+ 	    $w_sql .= "group by " .
+ 	    		join(',', map "${tbl}_$_", @$cols) . "\n";
+ 	    $w_sql .= ") t\n";
+ 	    my $dir = $as_args->{'direction'} &&
+ 	    		$as_args->{'direction'} eq 'descend' ? 'desc' : 'asc';
+ 			$w_sql .= "order by ${tbl}_${j_tbl}_$as_args->{'column'} $dir\n";
+ 	}
  
          if (my $n = $j_args->{limit}) {
              $n =~ s/\D//g;   ## Get rid of any non-numerics.
*** MT-3.121-full-ja.orig/lib/MT/Template/Context.pm	2004-10-26 17:27:53.000000000 +0900
--- MT-3.121-full-ja/lib/MT/Template/Context.pm	2005-01-18 09:52:01.000000000 +0900
***************
*** 741,749 ****
          } elsif (my $n = $args->{recently_commented_on}) {
              $args{'join'} = [ 'MT::Comment', 'entry_id',
                  { blog_id => $blog_id, visible => 1 },
!                 { 'sort' => 'created_on',
!                   direction => 'descend',
!                   unique => 1,
                    limit => $n } ];
              $no_resort = 1;
          }
--- 741,749 ----
          } elsif (my $n = $args->{recently_commented_on}) {
              $args{'join'} = [ 'MT::Comment', 'entry_id',
                  { blog_id => $blog_id, visible => 1 },
!                 { 'aggregate_sort' => { 'column' => 'created_on',
! 					'function' => 'max',
! 					'direction' => 'descend' },
                    limit => $n } ];
              $no_resort = 1;
          }

MovableTypeに関してへ戻る。

This website uses cookies. By using the website, you agree with storing cookies on your computer. Also, you acknowledge that you have read and understand our Privacy Policy. If you do not agree, please leave the website.

More information