Index: pykota/trunk/pykota/storages/sql.py
===================================================================
--- pykota/trunk/pykota/storages/sql.py (revision 3489)
+++ pykota/trunk/pykota/storages/sql.py (revision 3521)
@@ -28,4 +28,6 @@
 
 from pykota.utils import *
+
+MAXINNAMES = 500 # Maximum number of non-patterns names to use in a single IN statement
 
 class SQLStorage :
@@ -445,4 +447,12 @@
         return pgroups
 
+    def hasWildCards(self, pattern) :
+        """Returns True if the pattern contains wildcards, else False."""
+        specialchars = "*?[!" # no need to check for ] since [ would be there first
+        for specialchar in specialchars :
+            if specialchar in pattern :
+                return True
+        return False
+
     def getMatchingPrinters(self, printerpattern) :
         """Returns the list of all printers for which name matches a certain pattern."""
@@ -454,11 +464,5 @@
         if result :
             patterns = printerpattern.split(",")
-            try :
-                patdict = {}.fromkeys(patterns)
-            except AttributeError :
-                # Python v2.2 or earlier
-                patdict = {}
-                for p in patterns :
-                    patdict[p] = None
+            patdict = {}.fromkeys(patterns)
             for record in result :
                 pname = databaseToUnicode(record["printername"])
@@ -475,20 +479,39 @@
         # but we don't because other storages semantics may be different, so every
         # storage should use fnmatch to match patterns and be storage agnostic
-        result = self.doSearch("SELECT * FROM users")
-        if result :
-            patterns = userpattern.split(",")
-            try :
-                patdict = {}.fromkeys(patterns)
-            except AttributeError :
-                # Python v2.2 or earlier
-                patdict = {}
-                for p in patterns :
-                    patdict[p] = None
-            for record in result :
-                uname = databaseToUnicode(record["username"])
-                if patdict.has_key(uname) or self.tool.matchString(uname, patterns) :
-                    user = self.storageUserFromRecord(uname, record)
-                    users.append(user)
-                    self.cacheEntry("USERS", user.Name, user)
+        #
+        # This doesn't prevent us from being smarter, thanks to bse@chalmers.se
+        userpattern = userpattern or "*"
+        patterns = userpattern.split(",")
+        patdict = {}.fromkeys(patterns)
+        patterns = patdict.keys() # Ensures the uniqueness of each pattern, but we lose the cmd line ordering
+        # BEWARE : if a single pattern contains wild cards, we'll still use the slow route.
+        if self.hasWildCards(userpattern) :
+            # Slow route
+            result = self.doSearch("SELECT * FROM users")
+            if result :
+                for record in result :
+                    uname = databaseToUnicode(record["username"])
+                    if patdict.has_key(uname) or self.tool.matchString(uname, patterns) :
+                        user = self.storageUserFromRecord(uname, record)
+                        users.append(user)
+                        self.cacheEntry("USERS", user.Name, user)
+        else :
+            # Fast route (probably not faster with a few users)
+            while patterns :
+                subset = patterns[:MAXINNAMES]
+                nbpatterns = len(subset)
+                if nbpatterns == 1 :
+                    wherestmt = "username=%s" % self.doQuote(unicodeToDatabase(subset[0]))
+                else :
+                    wherestmt = "username IN (%s)" % ",".join([self.doQuote(unicodeToDatabase(p)) for p in subset])
+                result = self.doSearch("SELECT * FROM users WHERE %s" % wherestmt)
+                if result :
+                    for record in result :
+                        uname = databaseToUnicode(record["username"])
+                        user = self.storageUserFromRecord(uname, record)
+                        users.append(user)
+                        self.cacheEntry("USERS", user.Name, user)
+                patterns = patterns[MAXINNAMES:]
+        users.sort(key=lambda u : u.Name) # Adds some ordering, we've already lost the cmd line one anyway.
         return users
 
@@ -502,11 +525,5 @@
         if result :
             patterns = grouppattern.split(",")
-            try :
-                patdict = {}.fromkeys(patterns)
-            except AttributeError :
-                # Python v2.2 or earlier
-                patdict = {}
-                for p in patterns :
-                    patdict[p] = None
+            patdict = {}.fromkeys(patterns)
             for record in result :
                 gname = databaseToUnicode(record["groupname"])
@@ -523,11 +540,5 @@
         if result :
             patterns = billingcodepattern.split(",")
-            try :
-                patdict = {}.fromkeys(patterns)
-            except AttributeError :
-                # Python v2.2 or earlier
-                patdict = {}
-                for p in patterns :
-                    patdict[p] = None
+            patdict = {}.fromkeys(patterns)
             for record in result :
                 codename = databaseToUnicode(record["billingcode"])
