diff --git a/auth/db/auth.php b/auth/db/auth.php
index 4f875b5..2075c7e 100644
--- a/auth/db/auth.php
+++ b/auth/db/auth.php
@@ -15,6 +15,7 @@ defined('MOODLE_INTERNAL') || die();
 
 require_once($CFG->libdir.'/authlib.php');
 require_once($CFG->libdir.'/adodb/adodb.inc.php');
+require_once($CFG->libdir.'/ddllib.php');
 
 /**
  * External database authentication plugin.
@@ -176,7 +177,7 @@ class auth_plugin_db extends auth_plugin_base {
                     $fields_obj = (object)array_change_key_case((array)$fields_obj , CASE_LOWER);
                     foreach ($selectfields as $localname=>$externalname) {
                         $result[$localname] = $textlib->convert($fields_obj->{$localname}, $this->config->extencoding, 'utf-8');
-                     }
+                    }
                  }
                  $rs->Close();
             }
@@ -220,27 +221,60 @@ class auth_plugin_db extends auth_plugin_base {
     function sync_users($do_updates=false) {
         global $CFG, $DB;
 
-/// list external users
-        $userlist = $this->get_userlist();
+        print_string('auth_dbconnecting', 'auth_db');
+        echo "\n";
+        $externaldbconnection = $this->db_init();
 
-/// delete obsolete internal users
-        if (!empty($this->config->removeuser)) {
+        $dbman = $DB->get_manager();
 
-            // find obsolete users
-            if (count($userlist)) {
-        		list($notin_sql, $params) = $DB->get_in_or_equal($userlist, SQL_PARAMS_NAMED, 'u0000', false);
-        		$params['authtype'] = $this->authtype;
-            	$sql = "SELECT u.id, u.username, u.email, u.auth
-                          FROM {user} u
-                         WHERE u.auth=:authtype AND u.deleted=0 AND u.username $notin_sql";
-            } else {
-                $sql = "SELECT u.id, u.username, u.email, u.auth
-                          FROM {user} u
-                         WHERE u.auth=:authtype AND u.deleted=0";
-                $params = array();
-        		$params['authtype'] = $this->authtype;
+    /// Define table user to be created
+        $table = new xmldb_table('tmp_extuser');
+        $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
+        $table->add_field('username', XMLDB_TYPE_CHAR, '100', null, XMLDB_NOTNULL, null, null);
+        $table->add_field('mnethostid', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null);
+        $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
+        $table->add_index('username', XMLDB_INDEX_UNIQUE, array('mnethostid', 'username'));
+
+        print_string('creatingtemptable', 'auth_ldap', 'tmp_extuser');
+        $dbman->create_temp_table($table);
+
+        /// get users from external database and store in temporary table
+        $rs = $externaldbconnection->Execute("SELECT {$this->config->fielduser} AS username FROM {$this->config->table}");
+
+        if (!$rs) {
+            print_error('auth_dbcantgetusers','auth_db');
+        } else if (!$rs->EOF) {
+            while ($rec = $rs->FetchRow()) {
+                $username = moodle_strtolower($rec['username']); // usernames are __always__ lowercase.
+                $DB->insert_record_raw('tmp_extuser', array('username'=>$username,
+                                                            'mnethostid'=>$CFG->mnet_localhost_id), false, true);
             }
-            $remove_users = $DB->get_records_sql($sql, $params);
+        }
+
+        /// preserve our user database
+        /// if the temp table is empty, it probably means that something went wrong, exit
+        /// so as to avoid mass deletion of users; which is hard to undo
+        $count = $DB->count_records_sql('SELECT COUNT(username) AS count, 1 FROM {tmp_extuser}');
+        if ($count < 1) {
+            print_string('auth_dbdidntgetusers', 'auth_db');
+            exit;
+        } else {
+            print_string('auth_dbcountrecords', 'auth_db', $count);
+        }
+
+/// User removal
+        // Find users in DB that aren't in external db -- to be removed!
+        // this is still not as scalable (but how often do we mass delete?)
+        if (!empty($this->config->removeuser) and $this->config->removeuser !== AUTH_REMOVEUSER_KEEP) {
+            $sql = 'SELECT u.id, u.username, u.email, u.auth
+                      FROM {user} u
+                 LEFT JOIN {tmp_extuser} e
+                        ON (u.username = e.username AND
+                            u.mnethostid = e.mnethostid)
+                     WHERE u.auth = ?
+                       AND u.deleted = 0
+                       AND e.username IS NULL';
+            $remove_users = $DB->get_records_sql($sql, array($this->authtype));
 
             if (!empty($remove_users)) {
                 print_string('auth_dbuserstoremove','auth_db', count($remove_users)); echo "\n";
@@ -260,19 +294,40 @@ class auth_plugin_db extends auth_plugin_base {
                         echo "\t"; print_string('auth_dbsuspenduser', 'auth_db', array('name'=>$user->username, 'id'=>$user->id)); echo "\n";
                     }
                 }
+            } else {
+                print_string('nouserentriestoremove', 'auth_ldap');
             }
             unset($remove_users); // free mem!
         }
+/// Revive suspended users
+        if (!empty($this->config->removeuser) and $this->config->removeuser == AUTH_REMOVEUSER_SUSPEND) {
+            $sql = "SELECT u.id, u.username
+                      FROM {user} u
+                      JOIN {tmp_extuser} e
+                        ON (u.username = e.username AND
+                            u.mnethostid = e.mnethostid)
+                     WHERE u.auth = 'nologin'
+                       AND u.deleted = 0";
+            $revive_users = $DB->get_records_sql($sql);
+
+            if (!empty($revive_users)) {
+                print_string('userentriestorevive', 'auth_ldap', count($revive_users));
+
+                foreach ($revive_users as $user) {
+                    $updateuser = new stdClass();
+                    $updateuser->id = $user->id;
+                    $updateuser->auth = $this->authtype;
+                    $DB->update_record('user', $updateuser);
+                    echo "\t"; print_string('auth_dbreviveduser', 'auth_db', array('name'=>$user->username, 'id'=>$user->id)); echo "\n";
+                }
+            } else {
+                print_string('nouserentriestorevive', 'auth_ldap');
+            }
 
-        if (!count($userlist)) {
-            // exit right here
-            // nothing else to do
-            return true;
+            unset($revive_users);
         }
 
-        ///
-        /// update existing accounts
-        ///
+/// User Updates
         if ($do_updates) {
             // narrow down what fields we need to update
             $all_keys = array_keys(get_object_vars($this->config));
@@ -284,62 +339,66 @@ class auth_plugin_db extends auth_plugin_base {
                     }
                 }
             }
-            // print_r($all_keys); print_r($updatekeys);
             unset($all_keys); unset($key);
-
-            // only go ahead if we actually
-            // have fields to update locally
-            if (!empty($updatekeys)) {
-            	list($in_sql, $params) = $DB->get_in_or_equal($userlist, SQL_PARAMS_NAMED, 'u0000', true);
-                $params['authtype'] = $this->authtype;
-                $sql = "SELECT u.id, u.username
-                          FROM {user} u
-                         WHERE u.auth=:authtype AND u.deleted=0 AND u.username {$in_sql}";
-                if ($update_users = $DB->get_records_sql($sql, $params)) {
-                    print "User entries to update: ". count($update_users). "\n";
-
-                    foreach ($update_users as $user) {
-                        echo "\t"; print_string('auth_dbupdatinguser', 'auth_db', array('name'=>$user->username, 'id'=>$user->id));
-                        if (!$this->update_user_record($user->username, $updatekeys)) {
-                            echo " - ".get_string('skipped');
-                        }
-                        echo "\n";
-                    }
-                    unset($update_users); // free memory
-                }
-            }
+        } else {
+            print_string('noupdatestobedone', 'auth_ldap');
         }
 
+        if ($do_updates and !empty($updatekeys)) { // run updates only if relevant
+            $users = $DB->get_records_sql('SELECT u.username, u.id
+                                             FROM {user} u
+                                            WHERE u.deleted = 0
+                                              AND u.auth = ?
+                                              AND u.mnethostid = ?',
+                                          array($this->authtype, $CFG->mnet_localhost_id));
 
-        ///
-        /// create missing accounts
-        ///
-        // NOTE: this is very memory intensive
-        // and generally inefficient
-        $sql = 'SELECT u.id, u.username
-                FROM {user} u
-                WHERE u.auth=\'' . $this->authtype . '\' AND u.deleted=\'0\'';
+            if (!empty($users)) {
+                print_string('userentriestoupdate', 'auth_ldap', count($users));
 
-        $users = $DB->get_records_sql($sql);
+                $transaction = $DB->start_delegated_transaction();
+                $xcount = 0;
+                $maxxcount = 100;
 
-        // simplify down to usernames
-        $usernames = array();
-        if (!empty($users)) {
-            foreach ($users as $user) {
-                array_push($usernames, $user->username);
+                foreach ($users as $user) {
+                    echo "\t"; print_string('auth_dbupdatinguser', 'auth_db', array('name'=>$user->username, 'id'=>$user->id));
+                    if (!$this->update_user_record($user->username, $updatekeys)) {
+                        echo " - ".get_string('skipped');
+                    }
+                    echo "\n";
+                    $xcount++;
+                }
+                $transaction->allow_commit();
+                unset($users); // free mem
             }
-            unset($users);
-        }
-
-        $add_users = array_diff($userlist, $usernames);
-        unset($usernames);
+        } else { // end do updates
+            print_string('noupdatestobedone', 'auth_ldap');
+        }
+
+/// User Additions
+        // Find users missing in DB that are in EXTERNAL DB
+        // and gives me a nifty object I don't want.
+        // note: we do not care about deleted accounts anymore, this feature was replaced by suspending to nologin auth plugin
+        $sql = 'SELECT e.id, e.username
+                  FROM {tmp_extuser} e
+             LEFT JOIN {user} u
+                    ON (e.username = u.username AND
+                        e.mnethostid = u.mnethostid)
+                 WHERE u.id IS NULL';
+        $add_users = $DB->get_records_sql($sql);
 
         if (!empty($add_users)) {
             print_string('auth_dbuserstoadd','auth_db',count($add_users)); echo "\n";
+
             $transaction = $DB->start_delegated_transaction();
             foreach($add_users as $user) {
-                $username = $user;
-                $user = $this->get_userinfo_asobj($user);
+                $username = $user->username;
+                $user = $this->get_userinfo_asobj($username);
+
+                if (!validate_email($user->email)) {
+                    print_string('auth_dbinvalidemail', 'auth_db', $user);
+                    echo "\n";
+                    continue;
+                }
 
                 // prep a few params
                 $user->username   = $username;
@@ -347,29 +406,31 @@ class auth_plugin_db extends auth_plugin_base {
                 $user->confirmed  = 1;
                 $user->auth       = $this->authtype;
                 $user->mnethostid = $CFG->mnet_localhost_id;
+                // get_userinfo_asobj() might have replaced $user->username with the value
+                // from the EXTERNAL DB server (which can be mixed-case). Make sure it's lowercase
+                $user->username = trim(moodle_strtolower($user->username));
                 if (empty($user->lang)) {
                     $user->lang = $CFG->lang;
                 }
 
-                // maybe the user has been deleted before
-                if ($old_user = $DB->get_record('user', array('username'=>$user->username, 'deleted'=>1, 'mnethostid'=>$user->mnethostid))) {
-                    $user->id = $old_user->id;
-                    $DB->set_field('user', 'deleted', 0, array('username'=>$user->username));
-                    echo "\t"; print_string('auth_dbreviveduser', 'auth_db', array('name'=>$user->username, 'id'=>$user->id)); echo "\n";
-
-                } else {
-                    $id = $DB->insert_record ('user',$user); // it is truly a new user
-                    echo "\t"; print_string('auth_dbinsertuser','auth_db',array('name'=>$user->username, 'id'=>$id)); echo "\n";
-                    // if relevant, tag for password generation
-                    if ($this->is_internal()) {
-                        set_user_preference('auth_forcepasswordchange', 1, $id);
-                        set_user_preference('create_password',          1, $id);
-                    }
+                $id = $DB->insert_record('user',$user);
+                echo "\t"; print_string('auth_dbinsertuser', 'auth_db', array('name'=>$user->username, 'id'=>$id)); echo "\n";
+                // if relevant, tag for password generation
+                if ($this->is_internal()) {
+                    set_user_preference('auth_forcepasswordchange', 1, $id);
+                    set_user_preference('create_password',          1, $id);
                 }
             }
             $transaction->allow_commit();
             unset($add_users); // free mem
+        } else {
+            print_string('nouserstobeadded', 'auth_db');
         }
+
+        print_string('auth_dbsuccess', 'auth_db'); echo "\n";
+
+        $dbman->drop_temp_table($table);
+        $externaldbconnection->Close();
         return true;
     }
 
@@ -398,30 +459,6 @@ class auth_plugin_db extends auth_plugin_base {
     }
 
 
-    function get_userlist() {
-
-    /// Init result value
-        $result = array();
-
-        $authdb = $this->db_init();
-
-        // fetch userlist
-        $rs = $authdb->Execute("SELECT {$this->config->fielduser} AS username
-                                FROM   {$this->config->table} ");
-
-        if (!$rs) {
-            print_error('auth_dbcantconnect','auth_db');
-        } else if (!$rs->EOF) {
-            while ($rec = $rs->FetchRow()) {
-                $rec = (object)array_change_key_case((array)$rec , CASE_LOWER);
-                array_push($result, $rec->username);
-            }
-        }
-
-        $authdb->Close();
-        return $result;
-    }
-
     /**
      * reads userinformation from DB and return it in an object
      *
diff --git a/auth/db/lang/en/auth_db.php b/auth/db/lang/en/auth_db.php
index 380e69a..a1ea8b7 100644
--- a/auth/db/lang/en/auth_db.php
+++ b/auth/db/lang/en/auth_db.php
@@ -24,11 +24,14 @@
  */
 
 $string['auth_dbcantconnect'] = 'Could not connect to the specified authentication database...';
+$string['auth_dbconnecting'] = 'Connecting to external database...';
+$string['auth_dbcountrecords'] = 'Got {$a} records from external database';
 $string['auth_dbdebugauthdb'] = 'Debug ADOdb';
 $string['auth_dbdebugauthdbhelp'] = 'Debug ADOdb connection to external database - use when getting empty page during login. Not suitable for production sites.';
 $string['auth_dbdeleteuser'] = 'Deleted user {$a->name} id {$a->id}';
 $string['auth_dbdeleteusererror'] = 'Error deleting user {$a}';
 $string['auth_dbdescription'] = 'This method uses an external database table to check whether a given username and password is valid.  If the account is a new one, then information from other fields may also be copied across into Moodle.';
+$string['auth_dbdidntgetusers'] = 'Did not get any users from external database -- error? -- exiting';
 $string['auth_dbextencoding'] = 'External db encoding';
 $string['auth_dbextencodinghelp'] = 'Encoding used in external database';
 $string['auth_dbextrafields'] = 'These fields are optional.  You can choose to pre-fill some Moodle user fields with information from the <b>external database fields</b> that you specify here. <p>If you leave these blank, then defaults will be used.</p><p>In either case, the user will be able to edit all of these fields after they log in.</p>';
@@ -41,6 +44,7 @@ $string['auth_dbhost_key'] = 'Host';
 $string['auth_dbchangepasswordurl_key'] = 'Password-change URL';
 $string['auth_dbinsertuser'] = 'Inserted user {$a->name} id {$a->id}';
 $string['auth_dbinsertusererror'] = 'Error inserting user {$a}';
+$string['auth_dbinvalidemail'] = 'Found invalid email ({$a->email}) for username {$a->username}, skipping';
 $string['auth_dbname'] = 'Name of the database itself';
 $string['auth_dbname_key'] = 'DB Name';
 $string['auth_dbpass'] = 'Password matching the above username';
@@ -51,6 +55,7 @@ $string['auth_dbreviveduser'] = 'Revived user {$a->name} id {$a->id}';
 $string['auth_dbrevivedusererror'] = 'Error reviving user {$a}';
 $string['auth_dbsetupsql'] = 'SQL setup command';
 $string['auth_dbsetupsqlhelp'] = 'SQL command for special database setup, often used to setup communication encoding - example for MySQL and PostgreSQL: <em>SET NAMES \'utf8\'</em>';
+$string['auth_dbsuccess'] = 'Terminated successfully';
 $string['auth_dbsuspenduser'] = 'Suspended user {$a->name} id {$a->id}';
 $string['auth_dbsuspendusererror'] = 'Error suspending user {$a}';
 $string['auth_dbsybasequoting'] = 'Use sybase quotes';
diff --git a/auth/db/version.php b/auth/db/version.php
index a744fca..446a846 100644
--- a/auth/db/version.php
+++ b/auth/db/version.php
@@ -1,3 +1,3 @@
 <?php
 
-$plugin->version = 2009112400;
+$plugin->version = 2010112200;
