Going ahead and adding this field while other DB updates are pending.
authorBrion Vibber <brion@users.mediawiki.org>
Thu, 14 Dec 2006 13:22:52 +0000 (13:22 +0000)
committerBrion Vibber <brion@users.mediawiki.org>
Thu, 14 Dec 2006 13:22:52 +0000 (13:22 +0000)
Interfaces to use it can be added shortly.

* Add user_editcount field to provide data for heuristics on account use.
  Incremented on edit, with lazy initialization from past revision data.
  Can batch-initialize with maintenance/initEditCount.php (not yet friendly
  to replication environments, this will do all accounts in one query).
* Allow raw SQL subsections in Database::update() SET portion as well as
  for WHERE portion. Handy for increments and such.

RELEASE-NOTES
includes/Article.php
includes/Database.php
includes/User.php
maintenance/archives/patch-user_editcount.sql [new file with mode: 0644]
maintenance/initEditCount.php [new file with mode: 0644]
maintenance/mysql5/tables-binary.sql
maintenance/mysql5/tables.sql
maintenance/postgres/tables.sql
maintenance/tables.sql
maintenance/updaters.inc

index e02ed75..4485307 100644 (file)
@@ -310,6 +310,12 @@ it from source control: http://www.mediawiki.org/wiki/Download_from_SVN
   creation, so people don't immediately go off to request a second one.
 * Add a warning on Special:Confirmemail if a code was already sent and has
   not yet expired.
+* Add user_editcount field to provide data for heuristics on account use.
+  Incremented on edit, with lazy initialization from past revision data.
+  Can batch-initialize with maintenance/initEditCount.php (not yet friendly
+  to replication environments, this will do all accounts in one query).
+* Allow raw SQL subsections in Database::update() SET portion as well as
+  for WHERE portion. Handy for increments and such.
 
 
 == Languages updated ==
index edf7aea..e1242d3 100644 (file)
@@ -1339,6 +1339,7 @@ class Article {
                                                        RecentChange::markPatrolled( $rcid );
                                                }
                                        }
+                                       $wgUser->incEditCount();
                                        $dbw->commit();
                                }
                        } else {
@@ -1399,6 +1400,7 @@ class Article {
                                        RecentChange::markPatrolled( $rcid );
                                }
                        }
+                       $wgUser->incEditCount();
                        $dbw->commit();
 
                        # Update links, etc.
index f35aaaa..f2acd11 100644 (file)
@@ -1332,6 +1332,8 @@ class Database {
                        }
                        if ( ($mode == LIST_AND || $mode == LIST_OR) && is_numeric( $field ) ) {
                                $list .= "($value)";
+                       } elseif ( ($mode == LIST_SET) && is_numeric( $field ) ) {
+                               $list .= "$value";
                        } elseif ( ($mode == LIST_AND || $mode == LIST_OR) && is_array ($value) ) {
                                $list .= $field." IN (".$this->makeList($value).") ";
                        } else {
index 53b14ef..89b1dd0 100644 (file)
@@ -2451,6 +2451,48 @@ class User {
                        return $text;
                }
        }
+       
+       /**
+        * Increment the user's edit-count field.
+        * Will have no effect for anonymous users.
+        */
+       function incEditCount() {
+               if( !$this->isAnon() ) {
+                       $dbw = wfGetDB( DB_MASTER );
+                       $dbw->update( 'user',
+                               array( 'user_editcount=user_editcount+1' ),
+                               array( 'user_id' => $this->getId() ),
+                               __METHOD__ );
+                       
+                       // Lazy initialization check...
+                       if( $dbw->affectedRows() == 0 ) {
+                               // Pull from a slave to be less cruel to servers
+                               // Accuracy isn't the point anyway here
+                               $dbr = wfGetDB( DB_SLAVE );
+                               $count = $dbr->selectField( 'revision',
+                                       'COUNT(rev_user)',
+                                       array( 'rev_user' => $this->getId() ),
+                                       __METHOD__ );
+                               
+                               // Now here's a goddamn hack...
+                               if( $dbr !== $dbw ) {
+                                       // If we actually have a slave server, the count is
+                                       // at least one behind because the current transaction
+                                       // has not been committed and replicated.
+                                       $count++;
+                               } else {
+                                       // But if DB_SLAVE is selecting the master, then the
+                                       // count we just read includes the revision that was
+                                       // just added in the working transaction.
+                               }
+                               
+                               $dbw->update( 'user',
+                                       array( 'user_editcount' => $count ),
+                                       array( 'user_id' => $this->getId() ),
+                                       __METHOD__ );
+                       }
+               }
+       }
 }
 
 ?>
diff --git a/maintenance/archives/patch-user_editcount.sql b/maintenance/archives/patch-user_editcount.sql
new file mode 100644 (file)
index 0000000..cdde36d
--- /dev/null
@@ -0,0 +1,5 @@
+ALTER TABLE /*$wgDBprefix*/user
+  ADD COLUMN user_editcount int;
+
+-- Don't initialize values immediately... or should we?
+-- They will be lazy-evaluated, or batch-filled via maintenance/initEditCount.php
diff --git a/maintenance/initEditCount.php b/maintenance/initEditCount.php
new file mode 100644 (file)
index 0000000..a975f35
--- /dev/null
@@ -0,0 +1,40 @@
+<?php
+
+require_once "commandLine.inc";
+
+// @fixme: add replication-friendly batch mode
+
+$dbw = wfGetDB( DB_MASTER );
+$user = $dbw->tableName( 'user' );
+$revision = $dbw->tableName( 'revision' );
+
+$dbver = $dbw->getServerVersion();
+if( ($dbw instanceof DatabaseMySql && version_compare( $dbver, '4.1' ) < 0)
+       || isset( $options['force-mysql4'] ) ) {
+       
+       echo "Warning: MySQL $dbver; using hacky MySQL 4.0 compatibility query...\n";
+       $sql = "CREATE TEMPORARY TABLE temp_editcount (
+         temp_user_id INT,
+         temp_user_editcount INT
+       )";
+       $dbw->query( $sql );
+       
+       $sql = "INSERT INTO temp_editcount
+         (temp_user_id, temp_user_editcount)
+         SELECT rev_user, COUNT(rev_user)
+           FROM $revision GROUP BY rev_user";
+       $dbw->query( $sql );
+
+       $sql = "UPDATE $user
+         LEFT OUTER JOIN temp_editcount ON user_id=temp_user_id
+         SET user_editcount=IF(temp_user_editcount IS NULL,0,temp_user_editcount)";
+       $dbw->query( $sql );
+} else {
+       // Subselect should work on modern MySQLs etc
+       $sql = "UPDATE $user SET user_editcount=(SELECT COUNT(*) FROM $revision WHERE rev_user=user_id)";
+       $dbw->query( $sql );
+}
+
+echo "Done!\n";
+
+?>
index d9caafa..2ab3654 100644 (file)
@@ -135,6 +135,18 @@ CREATE TABLE /*$wgDBprefix*/user (
   -- Timestamp of account registration.
   -- Accounts predating this schema addition may contain NULL.
   user_registration char(14) binary,
+  
+  -- Count of edits and edit-like actions.
+  --
+  -- *NOT* intended to be an accurate copy of COUNT(*) WHERE rev_user=user_id
+  -- May contain NULL for old accounts if batch-update scripts haven't been
+  -- run, as well as listing deleted edits and other myriad ways it could be
+  -- out of sync.
+  --
+  -- Meant primarily for heuristic checks to give an impression of whether
+  -- the account has been used much.
+  --
+  user_editcount int,
 
   PRIMARY KEY user_id (user_id),
   UNIQUE INDEX user_name (user_name),
index cc624ba..356f3bb 100644 (file)
@@ -126,6 +126,18 @@ CREATE TABLE /*$wgDBprefix*/user (
   -- Timestamp of account registration.
   -- Accounts predating this schema addition may contain NULL.
   user_registration char(14) binary,
+  
+  -- Count of edits and edit-like actions.
+  --
+  -- *NOT* intended to be an accurate copy of COUNT(*) WHERE rev_user=user_id
+  -- May contain NULL for old accounts if batch-update scripts haven't been
+  -- run, as well as listing deleted edits and other myriad ways it could be
+  -- out of sync.
+  --
+  -- Meant primarily for heuristic checks to give an impression of whether
+  -- the account has been used much.
+  --
+  user_editcount int,
 
   PRIMARY KEY user_id (user_id),
   UNIQUE INDEX user_name (user_name),
index 3c507aa..bf0328b 100644 (file)
@@ -25,7 +25,8 @@ CREATE TABLE mwuser ( -- replace reserved word 'user'
   user_email_authenticated  TIMESTAMPTZ,
   user_options              TEXT,
   user_touched              TIMESTAMPTZ,
-  user_registration         TIMESTAMPTZ
+  user_registration         TIMESTAMPTZ,
+  user_editcount            INTEGER
 );
 CREATE INDEX user_email_token_idx ON mwuser (user_email_token);
 
index e2c6737..da19113 100644 (file)
@@ -113,6 +113,18 @@ CREATE TABLE /*$wgDBprefix*/user (
   -- Timestamp of account registration.
   -- Accounts predating this schema addition may contain NULL.
   user_registration char(14) binary,
+  
+  -- Count of edits and edit-like actions.
+  --
+  -- *NOT* intended to be an accurate copy of COUNT(*) WHERE rev_user=user_id
+  -- May contain NULL for old accounts if batch-update scripts haven't been
+  -- run, as well as listing deleted edits and other myriad ways it could be
+  -- out of sync.
+  --
+  -- Meant primarily for heuristic checks to give an impression of whether
+  -- the account has been used much.
+  --
+  user_editcount int,
 
   PRIMARY KEY user_id (user_id),
   UNIQUE INDEX user_name (user_name),
index 81481ec..86cfb3b 100644 (file)
@@ -62,6 +62,7 @@ $wgNewFields = array(
        array( 'site_stats',    'ss_images',        'patch-ss_images.sql' ),
        array( 'ipblocks',      'ipb_anon_only',    'patch-ipb_anon_only.sql' ),
        array( 'user',          'user_newpass_time','patch-user_newpass_time.sql' ),
+       array( 'user',          'user_editcount',   'patch-user_editcount.sql' ),
 );
 
 function rename_table( $from, $to, $patch ) {
@@ -1021,6 +1022,7 @@ ALTER TABLE revision ADD CONSTRAINT revision_rev_user_fkey
 
 -- New column for better password tracking:
 ALTER TABLE mwuser ADD user_newpass_time TIMESTAMPTZ;
+ALTER TABLE mwuser ADD user_editcount INTEGER;
 
 -- New column for autoblocking problem users
 ALTER TABLE ipblocks ADD ipb_enable_autoblock CHAR NOT NULL DEFAULT '1';