[Slashdotjp-dev 397] CVS update: slashjp/Slash/DB/Static/MySQL

Back to archive index

Tatsuki SUGIURA sugi****@users*****
2006年 7月 12日 (水) 20:41:39 JST


Index: slashjp/Slash/DB/Static/MySQL/MySQL.pm
diff -u slashjp/Slash/DB/Static/MySQL/MySQL.pm:1.3 slashjp/Slash/DB/Static/MySQL/MySQL.pm:1.4
--- slashjp/Slash/DB/Static/MySQL/MySQL.pm:1.3	Fri Dec 31 21:35:45 2004
+++ slashjp/Slash/DB/Static/MySQL/MySQL.pm	Wed Jul 12 20:41:39 2006
@@ -1,7 +1,7 @@
 # This code is a part of Slash, and is released under the GPL.
-# Copyright 1997-2004 by Open Source Development Network. See README
+# Copyright 1997-2005 by Open Source Technology Group. See README
 # and COPYING for more information, or see http://slashcode.com/.
-# $Id: MySQL.pm,v 1.3 2004/12/31 12:35:45 oliver Exp $
+# $Id: MySQL.pm,v 1.4 2006/07/12 11:41:39 sugi Exp $
 
 package Slash::DB::Static::MySQL;
 
@@ -19,7 +19,7 @@
 use vars qw($VERSION);
 use base 'Slash::DB::MySQL';
 
-($VERSION) = ' $Revision: 1.3 $ ' =~ /\$Revision:\s+([^\s]+)/;
+($VERSION) = ' $Revision: 1.4 $ ' =~ /\$Revision:\s+([^\s]+)/;
 
 # FRY: Hey, thinking hurts 'em! Maybe I can think of a way to use that.
 
@@ -72,10 +72,14 @@
 # For rss, rdf etc feeds, basically used by tasks.
 # Ultimately this should be subsumed into
 # getStoriesEssentials since they serve the same purpose.
-# XXXSECTIONTOPICS let's get the NOW() out of here
+# XXXSECTIONTOPICS let's get the NOW() out of here.
+# This is much slower than getStoriesEssentials but fortunately
+# is not called very often.  Its calling code really should be
+# rewritten to use getStoriesEssentials.
 sub getBackendStories {
 	my($self, $options) = @_;
 
+	my $limit = $options->{limit} || 10;
 	my $topic = $options->{topic} || getCurrentStatic('mainpage_nexus_tid');
 
 	my $select = "stories.stoid AS stoid, sid, title, stories.tid AS tid, primaryskid, time,
@@ -88,7 +92,7 @@
 		AND stories.stoid = story_topics_rendered.stoid
 		AND story_topics_rendered.tid=$topic";
 
-	my $other = "ORDER BY time DESC LIMIT 10";
+	my $other = "ORDER BY time DESC LIMIT $limit";
 
 	my $returnable = $self->sqlSelectAllHashrefArray($select, $from, $where, $other);
 
@@ -105,6 +109,11 @@
 		for my $key (qw( image width height )) {
 			$story->{image}{$key} = $topic_hr->{$key};
 		}
+
+		# so we can assign proper "creator" if story was posted
+		# originally as a journal
+		my $journal_id = $self->getStory($story->{stoid}, 'journal_id');
+		$story->{journal_id} = $journal_id if $journal_id;
 	}
 
 	return $returnable;
@@ -157,8 +166,8 @@
 
 	my $topics = $self->getTopics;
 	for my $topic (@$ar) {
-		@{ $topic                   }{qw(alttext image width height)} =
-		@{ $topics->{$topic->{tid}} }{qw(alttext image width height)};
+		@{ $topic                   }{qw(textname image width height)} =
+		@{ $topics->{$topic->{tid}} }{qw(textname image width height)};
 	}
 
 	return $ar;
@@ -223,6 +232,55 @@
 	return $returnable;
 }
 
+########################################################
+# For dbsparklines.pl
+# This is a bit tricky because some moments may not have rows in
+# the table, and times may not be exactly $resolution apart.
+# We get the key-value hashref and walk it looking for
+# appropriate rows.
+sub getSparklineData {
+	my($self, $dbid, $col, $now, $resolution, $secs_back, $max, $multiplier) = @_;
+	$multiplier ||= 1;
+ 
+	my $now_ut = timeCalc($now, "%s", 0);
+	my $start_ut = $now_ut - $secs_back;
+	my $now_q = $self->sqlQuote($now);
+	my $kv_hr = $self->sqlSelectAllKeyValue(
+		"UNIX_TIMESTAMP(ts) AS ut, $col",
+		"dbs_readerstatus",
+		"dbid=$dbid
+		 AND ts >= DATE_SUB($now_q, INTERVAL $secs_back SECOND)");
+	return [ ] unless %$kv_hr;
+
+	my @ut = sort { $a <=> $b } keys %$kv_hr;
+	my @quantized = ( );
+	my $t = $start_ut;
+	T: while ($t < $now_ut) {
+		my @q = ( );
+		for my $t1 ($t .. $t + $resolution-1) {
+			push @q, $kv_hr->{$t1} * $multiplier if defined $kv_hr->{$t1};
+		}
+
+		# If nothing was found, no value for this quantized
+		# time value, push undef (GD::Graph knows what to
+		# do with that).  Otherwise push the mean of the
+		# value(s) found.
+		my $q = undef;
+		for my $val (@q) {
+			$q ||= 0;
+			$q += $val;
+		}
+		if (defined $q) {
+			$q /= scalar @q;
+			$q = $max if $q > $max;
+		}
+		push @quantized, $q;
+
+		$t += $resolution;
+	}
+ 
+	return \@quantized;
+}
 
 ########################################################
 # For balance_readers.pl
@@ -241,6 +299,8 @@
 		"dbid",
 		"dbid,
 		 MIN(IF(was_alive='yes',1,0)) AS was_alive,
+		 MIN(IF(was_reachable='yes',1,0)) AS was_reachable,
+		 MIN(IF(was_running='yes',1,0)) AS was_running,
 		 AVG(slave_lag_secs) AS lag,
 		 AVG(query_bog_secs) AS bog",
 		"dbs_readerstatus",
@@ -324,7 +384,9 @@
 	my $days_back = $constants->{freshenup_text_render_daysback} || 7;
 	return $self->sqlUpdate(
 		"story_text, stories",
-		{ rendered => undef },
+		{ rendered => undef,
+		  -last_update => 'last_update'
+		},
 		"story_text.stoid = stories.stoid
 		 AND rendered IS NOT NULL
 		 AND time < DATE_SUB(NOW(), INTERVAL $days_back DAY)");
@@ -335,8 +397,9 @@
 sub forgetUsersLogtokens {
 	my($self) = @_;
 
+	# delete logtokens if they have been expired for a month
 	return $self->sqlDelete("users_logtokens",
-		"DATE_ADD(expires, INTERVAL 1 MONTH) < NOW()");
+		"public = 'no' AND DATE_ADD(expires, INTERVAL 1 MONTH) < NOW()");
 }
 
 ########################################################
@@ -347,7 +410,8 @@
 	my $reader = getObject('Slash::DB', { db_type => "reader" });
 	my $min_lastlooktime = time - ($constants->{lastlookmemory} + 86400*7);
 	my $uids = $reader->sqlSelectColArrayref("uid", "users_param",
-		"name='lastlooktime' AND value < '$min_lastlooktime'");
+		"name='lastlooktime' AND value < '$min_lastlooktime'") || [ ];
+	my $count = scalar @$uids;
 
 	my $splice_count = 2000;
 	while (@$uids) {
@@ -356,6 +420,7 @@
 		$self->sqlDelete("users_param",
 			"name IN ('lastlooktime', 'lastlookuid') AND uid IN ($uids_in)");
 	}
+	return $count;
 }
 
 ########################################################
@@ -367,7 +432,8 @@
 	my $max_hrs = $constants->{mailpass_max_hours} || 48;
 	my $min_mailpass_last_ts = time - ($max_hrs*3600 + 86400*7);
 	my $uids = $reader->sqlSelectColArrayref("uid", "users_param",
-		"name='mailpass_last_ts' AND value < '$min_mailpass_last_ts'");
+		"name='mailpass_last_ts' AND value < '$min_mailpass_last_ts'") || [ ];
+	my $count = scalar @$uids;
 
 	my $splice_count = 2000;
 	while (@$uids) {
@@ -376,6 +442,7 @@
 		$self->sqlDelete("users_param",
 			"name IN ('mailpass_last_ts', 'mailpass_num') AND uid IN ($uids_in)");
 	}
+	return $count;
 }
 
 ########################################################
@@ -515,7 +582,7 @@
 sub forgetRemarks {
 	my($self) = @_;
 	return $self->sqlDelete("remarks",
-		"time < DATE_SUB(NOW(), INTERVAL 365 DAY)");
+		"time < DATE_SUB(NOW(), INTERVAL 90 DAY)");
 }
 
 ########################################################
@@ -524,29 +591,68 @@
 	my($self) = @_;
 	my $constants = getCurrentStatic();
 
-# This is now done more efficiently, throughout the day, by the
-# counthits.pl task.
-#	$self->updateStoriesCounts();
-
 	$self->sqlDelete('badpasswords', "TO_DAYS(NOW()) - TO_DAYS(ts) > 2");
-
 	$self->sqlDelete('pollvoters');
+	$self->sqlDelete('discussions', "type='recycle' AND commentcount=0")
+		unless $constants->{noflush_empty_discussions};
+	return 0;
+}
 
+########################################################
+# For run_moderatord.pl
+# Pass in option "sleep_between" of a few seconds, maybe up to a
+# minute, if for some reason the deletion still makes slave
+# replication lag... (but it shouldn't, anymore) - 2005/01/06
+sub deleteOldModRows {
+	my($self, $options) = @_;
+
+	my $reader = getObject('Slash::DB', { db_type => "reader" });
+	my $constants = getCurrentStatic();
+	my $max_rows = $constants->{mod_delete_maxrows} || 1000;
 	my $archive_delay_mod =
 		   $constants->{archive_delay_mod}
 		|| $constants->{archive_delay}
 		|| 14;
-	$self->sqlDelete('moderatorlog',
-		"TO_DAYS(NOW()) - TO_DAYS(ts) > $archive_delay_mod");
-	$self->sqlDelete('metamodlog',
-		"TO_DAYS(NOW()) - TO_DAYS(ts) > $archive_delay_mod");
-
-# This is now done by the flush_formkeys task.
-#	my $delete_time = time() - $constants->{formkey_timeframe};
-#	$self->sqlDelete('formkeys', "ts < $delete_time");
+	my $sleep_between = $options->{sleep_between} || 0;
 
-	$self->sqlDelete('discussions', "type='recycle' AND commentcount=0")
-		unless $constants->{noflush_empty_discussions};
+	# Find the minimum ID in these tables that should remain, then
+	# delete everything before it.  We do it this way to keep the
+	# slave DBs tied up on the replication of the deletion query as
+	# little as possible.  Turning off foreign key checking here is
+	# just pretty lame, I know...
+
+	$self->sqlDo("SET FOREIGN_KEY_CHECKS=0");
+
+	# First delete from the bottom up for the moderatorlog.
+
+	my $junk_bottom = $reader->sqlSelect('MIN(id)', 'moderatorlog');
+	my $need_bottom = $reader->sqlSelectNumericKeyAssumingMonotonic(
+		'moderatorlog', 'min', 'id',
+		"ts >= DATE_SUB(NOW(), INTERVAL $archive_delay_mod DAY)");
+	while ($need_bottom && $junk_bottom < $need_bottom) {
+		$junk_bottom += $max_rows;
+		$junk_bottom = $need_bottom if $need_bottom < $junk_bottom;
+		$self->sqlDelete('moderatorlog', "id < $junk_bottom");
+		sleep $sleep_between
+			if $sleep_between;
+	}
+
+	# Now delete from the bottom up for the metamodlog.
+
+	$junk_bottom = $reader->sqlSelect('MIN(id)', 'metamodlog');
+	$need_bottom = $reader->sqlSelectNumericKeyAssumingMonotonic(
+		'metamodlog', 'min', 'id',
+		"ts >= DATE_SUB(NOW(), INTERVAL $archive_delay_mod DAY)");
+	while ($need_bottom && $junk_bottom < $need_bottom) {
+		$junk_bottom += $max_rows;
+		$junk_bottom = $need_bottom if $need_bottom < $junk_bottom;
+		$self->sqlDelete('metamodlog', "id < $junk_bottom");
+		sleep $sleep_between
+			if $sleep_between && $junk_bottom < $need_bottom;
+	}
+
+	$self->sqlDo("SET FOREIGN_KEY_CHECKS=1");
+	return 0;
 }
 
 ########################################################
@@ -569,16 +675,24 @@
 	my $splice_count = 200;
 	if ($constants->{subscribe} && !$constants->{subscribe_hits_only}) {
 		my @gmt = gmtime();
-		my $today = sprintf "%4d%02d%02d", $gmt[5] + 1900, $gmt[4] + 1, $gmt[3];
-		my $ar = $self->sqlSelectAll(
+		my $hr = $self->sqlSelectAllKeyValue(
 			"uid, lastclick",
 			"users_hits",
 			"TO_DAYS(NOW()) - TO_DAYS(lastclick) <= 1"
 		);
 		my %uids_day = ( );
-		for my $uid_ar (@$ar) {
-			my($uid, $lastclick) = @$uid_ar;
-			my $lastclick_day = substr($lastclick, 0, 8);
+		for my $uid (keys %$hr) {
+			my $lastclick = $hr->{$uid};
+			if ($lastclick =~ /^(\d{4})(\d{2})(\d{2})/) {
+				# Timestamp field users_hits.lastclick is
+				# being given to us in MySQL 4.0 format
+				# of YYYYMMDDhhmmss.  Convert it to the
+				# MySQL 4.1 and later format of
+				# YYYY-MM-DD.  See also getUser and
+				# _getUser_do_selects.
+				$lastclick = "$1-$2-$3";
+			}
+			my $lastclick_day = substr($lastclick, 0, 10);
 			$uids_day{$lastclick_day}{$uid} = 1;
 		}
 		for my $day (keys %uids_day) {
@@ -593,12 +707,12 @@
 				);
 				# If there is more to do, sleep for a moment so we don't
 				# hit the DB too hard.
-				sleep 2 if @uids;
+				sleep int($splice_count/20+0.5) if @uids;
 			}
 		}
 	} else {
 		my @gmt = gmtime(time-86400);
-		my $yesterday = sprintf "%4d%02d%02d", $gmt[5] + 1900, $gmt[4] + 1, $gmt[3];
+		my $yesterday = sprintf "%4d-%02d-%02d", $gmt[5] + 1900, $gmt[4] + 1, $gmt[3];
 		my $uids_ar = $self->sqlSelectColArrayref(
 			"uid",
 			"accesslog",
@@ -617,7 +731,7 @@
 			);
 			# If there is more to do, sleep for a moment so we don't
 			# hit the DB too hard.
-			Time::HiRes::sleep(0.2) if @uids;
+			sleep int($splice_count/20+0.5) if @uids;
 		}
 	}
 }
@@ -642,16 +756,24 @@
 		"(lastaccess < DATE_SUB(NOW(), INTERVAL $days DAY) OR karma < $min_k)
 		 AND tokens > 0"
 	);
-	my $uids_in = join(",", sort @$uids_ar);
-	my $rows = 0;
-	if ($uids_in) {
-		$rows = $self->sqlUpdate(
-			"users_info",
-			{ -tokens => "GREATEST(0, tokens - $perday)" },
-			"uid IN ($uids_in) AND tokens > 0"
-		);
+	my $decayed = 0;
+	my $splice_count = 200;
+	while (@$uids_ar) {
+		my @uid_chunk = splice @$uids_ar, 0, $splice_count;
+		my $uids_in = join(",", @uid_chunk);
+		my $rows = 0;
+		if ($uids_in) {
+			$rows = $self->sqlUpdate(
+				"users_info",
+				{ -tokens => "GREATEST(0, tokens - $perday)" },
+				"uid IN ($uids_in)"
+			);
+		}
+		$decayed += $rows * $perday;
+		# If there is more to do, sleep for a moment so we don't
+		# hit the DB too hard.
+		sleep int($splice_count/20+0.5) if @$uids_ar;
 	}
-	my $decayed = $rows * $perday;
 	return $decayed;
 }
 
@@ -940,10 +1062,15 @@
 
 		my $skinname = $skins->{ $tree->{$tid}{skid} }{name};
 		my $mp_tid = $constants->{mainpage_nexus_tid};
-		for my $child_tid (sort { lc $tree->{$a}{textname} cmp lc $tree->{$b}{textname} } keys %{$tree->{$tid}{child}}) {
+		my @children =
+			sort { lc $tree->{$a}{textname} cmp lc $tree->{$b}{textname} }
+			grep { $tree->{$tid}{child}{$_} > 0 } # poisoned children don't count
+			keys %{$tree->{$tid}{child}};
+		for my $child_tid (@children) {
 			next unless $tree->{$child_tid}{nexus} && $tree->{$child_tid}{skid};
+			$index{$skinname} ||= [ ];
 			if ($children{$child_tid}) {
-				push @{$index{$skinname}{$child_tid}}, $children{$child_tid};
+				push @{$index{$skinname}}, $children{$child_tid};
 				next;
 			}
 
@@ -1000,13 +1127,15 @@
 sub convert_tokens_to_points {
 	my($self, $n_wanted) = @_;
 
+	my $reader = getObject("Slash::DB", { db_type => 'reader' });
+
 	my $constants = getCurrentStatic();
 	my %granted = ( );
 
 	return unless $n_wanted;
 
 	# Sanity check.
-	my $n_users = $self->countUsers();
+	my $n_users = $reader->countUsers();
 	$n_wanted = int($n_users/10) if $n_wanted > int($n_users)/10;
 
 	my $maxtokens = $constants->{maxtokens} || 60;
@@ -1017,7 +1146,7 @@
 	$tokentrade = $maxtokens if $tokentrade > $maxtokens; # sanity check
 	my $half_tokentrade = int($tokentrade/2); # another sanity check
 
-	my $uids = $self->sqlSelectColArrayref(
+	my $uids = $reader->sqlSelectColArrayref(
 		"uid",
 		"users_info",
 		"tokens >= $half_tokentrade",
@@ -1044,16 +1173,30 @@
 	# and seclev < 100.  These aren't meaningful limitations, so these
 	# updates should work as well.  - Jamie 2002/08/08
 	# Actually I don't think these are needed at all. - Jamie 2003/09/09
-	$self->sqlUpdate(
-		"users_comments",
-		{ points => $maxpoints },
-		"points > $maxpoints"
-	);
-	$self->sqlUpdate(
-		"users_info",
-		{ tokens => $maxtokens },
-		"tokens > $maxtokens"
-	);
+	#
+	# 2006/02/09:  I still don't think they're needed, and they are
+	# causing lags in replication...
+	#   Searching rows for update:
+	#   The thread is doing a first phase to find all matching
+	#   rows before updating them. This has to be done if the UPDATE
+	#   is changing the index that is used to find the involved rows.
+	# ...so I'm removing these.  I believe wherever the existing code
+	# increases points or tokens, it updates the oldvalue to
+	# LEAST(newvalue, maxvalue), so these adjustments should never
+	# change anything.
+	# 2006/02/12:  The lag is due to a MySQL bug in 4.1.16 that is
+	# fixed in 4.1.18.  <http://bugs.mysql.com/bug.php?id=15935>
+	# Still, we shouldn't need these.
+#	$self->sqlUpdate(
+#		"users_comments",
+#		{ points => $maxpoints },
+#		"points > $maxpoints"
+#	);
+#	$self->sqlUpdate(
+#		"users_info",
+#		{ tokens => $maxtokens },
+#		"tokens > $maxtokens"
+#	);
 
 	return \%granted;
 }
@@ -1138,7 +1281,7 @@
 	return if $lastmaxid > $newmaxid;
 	my $ac_uid = getCurrentStatic('anonymous_coward_uid');
 	$self->sqlDo("INSERT INTO accesslog_artcom (uid, ts, c)"
-		. " SELECT uid, AVG(ts) AS ts, COUNT(*) AS c"
+		. " SELECT uid, FROM_UNIXTIME(FLOOR(AVG(UNIX_TIMESTAMP(ts)))) AS ts, COUNT(*) AS c"
 		. " FROM accesslog"
 		. " WHERE id BETWEEN $lastmaxid AND $newmaxid"
 			. " AND (op='article' OR op='comments')"
@@ -1623,7 +1766,7 @@
 	# Lampe, C. and Resnick, P. "Slash(dot) and Burn: Moderation in a
 	# Large Scale Conversation Space."  Proceedings of the Conference on
 	# Computer Human Interaction (SIGCHI).  April 2004. Vienna, Austria.
-	# ACM Press.  (Forthcoming.)
+	# ACM Press.
 	#
 	# The goal of _csq_bonuses is to reward moderators who take
 	# a little extra effort, by giving them their next set of
@@ -1656,21 +1799,23 @@
 	# conversation and 7% for late comments [fifth quintile]."
 	# Here, quintile 5 is the latest 20% of the discussion, and
 	# quintile 1 is the earliest 20%.
-	if ($mod_hr->{cid_percentile} > 80) {
-		$num *= $constants->{m2_consequences_bonus_quintile_5} || 1;
-		push @applied, 'quintile_5';
-	} elsif ($mod_hr->{cid_percentile} > 60) {
-		$num *= $constants->{m2_consequences_bonus_quintile_4} || 1;
-		push @applied, 'quintile_4';
-	} elsif ($mod_hr->{cid_percentile} > 40) {
-		$num *= $constants->{m2_consequences_bonus_quintile_3} || 1;
-		push @applied, 'quintile_3';
-	} elsif ($mod_hr->{cid_percentile} > 20) {
-		$num *= $constants->{m2_consequences_bonus_quintile_2} || 1;
-		push @applied, 'quintile_2';
-	} else {
-		$num *= $constants->{m2_consequences_bonus_quintile_1} || 1;
-		push @applied, 'quintile_1';
+	if (defined $mod_hr->{cid_percentile}) {
+		if ($mod_hr->{cid_percentile} > 80) {
+			$num *= $constants->{m2_consequences_bonus_quintile_5} || 1;
+			push @applied, 'quintile_5';
+		} elsif ($mod_hr->{cid_percentile} > 60) {
+			$num *= $constants->{m2_consequences_bonus_quintile_4} || 1;
+			push @applied, 'quintile_4';
+		} elsif ($mod_hr->{cid_percentile} > 40) {
+			$num *= $constants->{m2_consequences_bonus_quintile_3} || 1;
+			push @applied, 'quintile_3';
+		} elsif ($mod_hr->{cid_percentile} > 20) {
+			$num *= $constants->{m2_consequences_bonus_quintile_2} || 1;
+			push @applied, 'quintile_2';
+		} else {
+			$num *= $constants->{m2_consequences_bonus_quintile_1} || 1;
+			push @applied, 'quintile_1';
+		}
 	}
 
 	# If a Fair moderation was applied to a comment that was
@@ -1770,6 +1915,13 @@
         }
 }
 
+# XXXSRCID This needs to actually be, like, written.
+sub recalcAL2 {
+        my($self, $srcid) = @_;
+	my $log = $self->getAL2Log($srcid);
+	# remember to delete from memcached
+}
+
 ########################################################
 # For dailyStuff
 # 	This should only be run once per day, if this isn't
@@ -2011,10 +2163,25 @@
 # files rewritten (which mainly means they have a row present
 # in the story_dirty table), starting with the most recent.
 sub getStoriesToRefresh {
-	my($self, $limit, $tid) = @_;
+	my($self, $limit, $tid, $options) = @_;
+	$options ||= {};
 	$limit ||= 10;
 	my $tid_clause = "";
 	$tid_clause = " AND story_topics_rendered.tid = $tid" if $tid;
+	my $stoid_clause = "";
+	
+	if ($options->{stoid}) {
+		my @stoids = ( );
+		if (ref $options->{stoid} eq "ARRAY") {
+			@stoids = @{$options->{stoid}}
+		} elsif (!ref $options->{stoid}) {
+			push @stoids, $options->{stoid};
+		}
+		if (@stoids) {
+			my $stoid_in = join ',', map { $self->sqlQuote($_) } @stoids;
+			$stoid_clause = " AND stories.stoid IN ($stoid_in) ";
+		}
+	}
 
 	# Include story_topics_rendered in this select just to make
 	# sure there is at least one topic assigned to such stories.
@@ -2022,14 +2189,15 @@
 	# don't include neverdisplay stories.
 	my $retval = $self->sqlSelectAllHashrefArray(
 		"DISTINCT stories.stoid AS stoid, sid, primaryskid, title, time",
-		"stories, story_text, story_topics_rendered
-		 LEFT JOIN story_dirty ON stories.stoid=story_dirty.stoid",
+		"story_text, story_topics_rendered,
+		 stories LEFT JOIN story_dirty ON stories.stoid=story_dirty.stoid",
 		"time < NOW()
 		 AND stories.primaryskid > 0
 		 AND stories.stoid = story_text.stoid
 		 AND story_dirty.stoid IS NOT NULL
 		 AND stories.stoid = story_topics_rendered.stoid
-		 $tid_clause",
+		 $tid_clause
+		 $stoid_clause",
 		"ORDER BY time DESC LIMIT $limit");
 	return [ ] if !@$retval;
 
@@ -2101,7 +2269,17 @@
 		story_topics_chosen story_topics_rendered )) {
 		$rows += $self->sqlDelete($table, "stoid=$stoid");
 	}
-	$self->deleteDiscussion($discussion_id) if $discussion_id;
+
+	if ($discussion_id && $story->{journal_id}) {
+		# journal_fix.pl task will revert discussion data later
+		# (although maybe better to make this happen immediately)
+		$self->sqlUpdate('journal_transfer', {
+			stoid	=> 0,
+		}, 'id=' . $self->sqlQuote($story->{journal_id}));
+	} elsif ($discussion_id) {
+		$self->deleteDiscussion($discussion_id);
+	}
+
 	$self->sqlDo("COMMIT");
 	$self->sqlDo("SET AUTOCOMMIT=1");
 	return $rows;
@@ -2115,8 +2293,12 @@
 	my($self) = @_;
 	my $sql;
 	$sql  = "REPLACE INTO authors_cache ";
-	$sql .= "SELECT users.uid, nickname, GREATEST(fakeemail, ''),
-		GREATEST(homepage, ''), 0, GREATEST(bio, ''), author ";
+	$sql .= "SELECT users.uid, nickname,
+		GREATEST(IF(fakeemail IS NULL, '',	fakeemail), ''),
+		GREATEST(IF(homepage IS NULL, '',	homepage), ''),
+		0,
+		GREATEST(IF(bio IS NULL, '',		bio), ''),
+		author ";
 	$sql .= "FROM users, users_info ";
 	$sql .= "WHERE users.author=1 ";
 	$sql .= "AND users.uid=users_info.uid";
@@ -2124,9 +2306,12 @@
 	$self->sqlDo($sql);
 
 	$sql  = "REPLACE INTO authors_cache ";
-	$sql .= "SELECT users.uid, nickname, GREATEST(fakeemail, ''),
-		GREATEST(homepage, ''), count(stories.uid),
-		GREATEST(bio, ''), author ";
+	$sql .= "SELECT users.uid, nickname,
+		GREATEST(IF(fakeemail IS NULL, '',	fakeemail), ''),
+		GREATEST(IF(homepage IS NULL, '',	homepage), ''),
+		COUNT(stories.uid),
+		GREATEST(IF(bio IS NULL, '',		bio), ''),
+		author ";
 	$sql .= "FROM users, stories, users_info ";
 	$sql .= "WHERE stories.uid=users.uid ";
 	$sql .= "AND users.uid=users_info.uid GROUP BY stories.uid";
@@ -2213,11 +2398,13 @@
 	@uncommon_words = split / /, $uncommon_words;
 
 	$self->sqlDo("LOCK TABLES uncommonstorywords LOW_PRIORITY WRITE");
+	$self->sqlDo("SET AUTOCOMMIT=0");
 	$self->sqlDelete("uncommonstorywords");
 	for my $word (@uncommon_words) {
-		$self->sqlInsert("uncommonstorywords", { word => $word },
-			{ delayed => 1 });
+		$self->sqlInsert("uncommonstorywords", { word => $word });
 	}
+	$self->sqlDo("COMMIT");
+	$self->sqlDo("SET AUTOCOMMIT=1");
 	$self->sqlDo("UNLOCK TABLES");
 }
 
@@ -2259,12 +2446,6 @@
 }
 
 ########################################################
-sub countAccesslogDaily {
-	my($self) = @_;
-	return $self->sqlCount("accesslog", "TO_DAYS(NOW()) - TO_DAYS(ts)=1");
-}
-
-########################################################
 # For tasks/run_moderatord.pl
 sub countM2M1Ratios {
 	my($self, $longterm) = @_;
@@ -2288,6 +2469,13 @@
 }
 
 ########################################################
+# For tasks/topic_tree_draw.pl
+sub countStoriesWithTopic {
+	my($self, $tid) = @_;
+	return $self->sqlCount('story_topics_rendered', "tid=$tid");
+}
+
+########################################################
 # For portald
 sub createRSS {
 	my($self, $bid, $item) = @_;
@@ -2458,14 +2646,12 @@
 	$yesterday = substr($yesterday, 0, 10);
 	my $where = '';
 	if ($where) {
-		$where = "created_at < DATE_SUB('$yesterday 00:00',INTERVAL $num_days DAY)";
+		$where = "created_at < DATE_SUB('$yesterday 00:00', INTERVAL $num_days DAY)";
 	} else {
 		$where = "created_at < '$yesterday 00:00'";
 	}
-	return $self->sqlSelect(
-		"MAX(uid)",
-		"users_info",
-		$where);
+	return $self->sqlSelectNumericKeyAssumingMonotonic(
+		'users_info', 'max', 'uid', $where);
 }
 
 ########################################################
@@ -2503,9 +2689,9 @@
 	my $num = $options->{num_wanted} || 10;
 
 	my $min_uid = $self->getLastUIDCreatedBeforeDaysBack($daysback, $yesterday);
-	my $newaccounts = $self->sqlSelect('max(uid)','users') - $min_uid;
-	my $newnicks = {};
 	return [ ] unless $min_uid;
+	my $newaccounts = $self->countUsers({ max => 1 }) - $min_uid;
+	my $newnicks = {};
 	my $domains = $self->sqlSelectAllHashrefArray(
 		"initdomain, COUNT(*) AS c",
 		"users_info",
@@ -2513,14 +2699,21 @@
 		"GROUP BY initdomain ORDER BY c DESC, initdomain LIMIT $num");
 
 	foreach my $domain (@$domains) {
-		my $nicks = $self->sqlSelectAll('nickname','users, users_info',"users.uid=users_info.uid AND users_info.uid >= $min_uid AND initdomain=".$self->sqlQuote($domain->{initdomain}),'ORDER BY users.uid DESC');
-		my $length = 5 + length($domain->{initdomain});
+		my $dom = $domain->{initdomain};
+		my $dom_q = $self->sqlQuote($dom);
+		my $nicks = $self->sqlSelectAll(
+			'nickname',
+			'users, users_info',
+			"users.uid=users_info.uid AND users_info.uid >= $min_uid
+			 AND initdomain=$dom_q",
+			'ORDER BY users.uid DESC');
+		my $length = 5 + length($dom);
 		my $i = 0;
-		$newnicks->{$domain->{initdomain}} = "";
+		$newnicks->{$dom} = '';
 
-		while ($length + length($nicks->[$i][0]) + 2 < 78) {
-			$newnicks->{$domain->{initdomain}} .= ', ' unless !$i;
-			$newnicks->{$domain->{initdomain}} .= $nicks->[$i][0];
+		while ($nicks->[$i] && $length + length($nicks->[$i][0]) + 2 < 78) {
+			$newnicks->{$dom} .= ', ' unless !$i;
+			$newnicks->{$dom} .= $nicks->[$i][0];
 			$length += length($nicks->[$i][0]) + 2;
 			$i++;
 		}
@@ -2577,21 +2770,22 @@
 	my ($self, $options) = @_;
 	my $ac_uid = getCurrentStatic('anonymous_coward_uid');
 	$options ||= {};
-	my @where;
-	push @where, "ts > date_sub(NOW(),INTERVAL $options->{days_back} DAY)" if $options->{days_back};
+
+	my @where = ( );
+	push @where, "ts > DATE_SUB(NOW(), INTERVAL $options->{days_back} DAY)" if $options->{days_back};
 	push @where, "cuid != $ac_uid" if $options->{no_anon_comments};
 	push @where, "id >= $options->{start_at_id}" if $options->{start_at_id};
 	push @where, "id <= $options->{end_at_id}" if $options->{end_at_id};
-	push @where, "ipid is not null and ipid!=''" if $options->{need_defined_ipid};
+	push @where, "ipid IS NOT NULL AND ipid != ''" if $options->{need_ipid};
 
 	my $where = join(" AND ", @where);
 
 	my $mods = $self->sqlSelectAllHashref(
 			[qw(uid cuid)],
-			"uid,cuid,count(*) as count",
+			"uid, cuid, COUNT(*) AS count",
 			"moderatorlog",
 			$where,
-			"group by uid, cuid");
+			"GROUP BY uid, cuid");
 
 	return $mods;
 }
@@ -2601,21 +2795,24 @@
 	my ($self, $options) = @_;
 	my $ac_uid = getCurrentStatic('anonymous_coward_uid');
 	$options ||= {};
-	my @where = ("moderatorlog.cid=comments.cid");
+
+	my @where = ( "moderatorlog.cid=comments.cid" );
 	push @where, "ts > date_sub(NOW(),INTERVAL $options->{days_back} DAY)" if $options->{days_back};
 	push @where, "cuid != $ac_uid" if $options->{no_anon_comments};
 	push @where, "cuid = $ac_uid" if $options->{only_anon_comments};
 	push @where, "id >= $options->{start_at_id}" if $options->{start_at_id};
 	push @where, "id <= $options->{end_at_id}" if $options->{end_at_id};
-	push @where, "ipid is not null and ipid!=''" if $options->{need_defined_ipid};
+	push @where, "comments.ipid IS NOT NULL AND comments.ipid!=''" if $options->{need_ipid};
+
 	my $where = join(" AND ", @where);
+
 	my $mods = $self->sqlSelectAllHashref(
 			[qw(uid ipid)],
-			"moderatorlog.uid as uid, comments.ipid as ipid, count(*) as count",
-			"moderatorlog,comments",
+			"moderatorlog.uid AS uid, comments.ipid AS ipid, COUNT(*) AS count",
+			"moderatorlog, comments",
 			$where,
-			"group by uid, comments.ipid");
-			
+			"GROUP BY uid, comments.ipid");
+
 	return $mods;
 }
 
@@ -2730,6 +2927,24 @@
 	);
 }
 
+sub getUrlsNeedingFirstCheck {
+	my($self) = @_;
+	return $self->sqlSelectAllHashrefArray("*", "urls", "last_attempt IS NULL", "ORDER BY url_id ASC");
+}
+
+sub getUrlsNeedingRefresh {
+	my($self, $limit) = @_;
+	$limit ||= 50;
+	return $self->sqlSelectAllHashrefArray(
+		"*", 
+		"urls", 
+		"last_attempt IS NOT NULL 
+		 AND believed_fresh_until IS NOT NULL 
+		 AND believed_fresh_until < NOW()", 
+		"ORDER BY believed_fresh_until ASC LIMIT $limit"
+	);
+}
+
 1;
 
 __END__


Slashdotjp-dev メーリングリストの案内
Back to archive index