- use Filter to select rows
authorMark Huang <mlhuang@cs.princeton.edu>
Wed, 8 Nov 2006 23:02:39 +0000 (23:02 +0000)
committerMark Huang <mlhuang@cs.princeton.edu>
Wed, 8 Nov 2006 23:02:39 +0000 (23:02 +0000)
- psycopg2 obviates the need for manual aggregation

PLC/ConfFiles.py
PLC/ForeignNodes.py
PLC/NodeGroups.py
PLC/PCUs.py
PLC/Peers.py
PLC/Sites.py

index ef0e301..2244bcf 100644 (file)
@@ -4,11 +4,12 @@
 # Mark Huang <mlhuang@cs.princeton.edu>
 # Copyright (C) 2006 The Trustees of Princeton University
 #
-# $Id: ConfFiles.py,v 1.6 2006/11/02 18:32:55 mlhuang Exp $
+# $Id: ConfFiles.py,v 1.7 2006/11/06 20:48:33 mlhuang Exp $
 #
 
 from PLC.Faults import *
 from PLC.Parameter import Parameter
+from PLC.Filter import Filter
 from PLC.Table import Row, Table
 from PLC.Nodes import Node, Nodes
 from PLC.NodeGroups import NodeGroup, NodeGroups
@@ -35,8 +36,8 @@ class ConfFile(Row):
         'error_cmd': Parameter(str, "Shell command to execute if any error occurs", max = 1024, nullok = True),
         'ignore_cmd_errors': Parameter(bool, "Install file anyway even if an error occurs"),
         'always_update': Parameter(bool, "Always attempt to install file even if unchanged"),
-        'node_ids': Parameter(int, "List of nodes linked to this file", ro = True),
-        'nodegroup_ids': Parameter(int, "List of node groups linked to this file", ro = True),
+        'node_ids': Parameter(int, "List of nodes linked to this file"),
+        'nodegroup_ids': Parameter(int, "List of node groups linked to this file"),
         }
 
     def add_node(self, node, commit = True):
@@ -138,27 +139,17 @@ class ConfFiles(Table):
     Representation of the conf_files table in the database.
     """
 
-    def __init__(self, api, conf_file_ids = None, enabled = None):
+    def __init__(self, api, conf_file_filter = None):
+       Table.__init__(self, api, ConfFile)
+
         sql = "SELECT %s FROM view_conf_files WHERE True" % \
               ", ".join(ConfFile.fields)
-        
-        if conf_file_ids:
-            # Separate the list into integers and strings
-            sql += " AND conf_file_id IN (%s)" % ", ".join(map(str, api.db.quote(conf_file_ids)))
-
-        if enabled is not None:
-            sql += " AND enabled = %(enabled)s"
-
-        rows = api.db.selectall(sql, locals())
-
-        for row in rows:
-            self[row['conf_file_id']] = ConfFile(api, row)
 
+        if conf_file_filter is not None:
+            if isinstance(conf_file_filter, list):
+                conf_file_filter = Filter(ConfFile.fields, {'conf_file_id': conf_file_filter})
+            elif isinstance(conf_file_filter, dict):
+                conf_file_filter = Filter(ConfFile.fields, conf_file_filter)
+            sql += " AND (%s)" % conf_file_filter.sql(api)
 
-        for row in rows:
-            self[row['conf_file_id']] = conf_file = ConfFile(api, row)
-            for aggregate in ['node_ids', 'nodegroup_ids']:
-                if not conf_file.has_key(aggregate) or conf_file[aggregate] is None:
-                    conf_file[aggregate] = []
-                else:
-                    conf_file[aggregate] = map(int, conf_file[aggregate].split(','))
+        self.selectall(sql)
index 9bc0c63..ba482e4 100644 (file)
@@ -6,6 +6,7 @@ from types import StringTypes
 
 from PLC.Table import Row, Table
 from PLC.Parameter import Parameter
+from PLC.Filter import Filter
 
 class ForeignNode (Row) :
     """
@@ -42,31 +43,21 @@ class ForeignNode (Row) :
 
 class ForeignNodes (Table):
 
-    def __init__ (self, api, foreign_node_id_or_hostname_list=None):
+    def __init__ (self, api, foreign_node_filter = None):
+        Table.__init__(self, api, ForeignNode)
 
-       self.api=api
+       sql = "SELECT %s FROM view_foreign_nodes WHERE deleted IS False" % \
+              ", ".join(ForeignNode.fields)
 
-       sql =""
-       sql += "SELECT %s FROM view_foreign_nodes " % ", ".join(ForeignNode.fields)
-       sql += "WHERE view_foreign_nodes.deleted IS False " 
+        if foreign_node_filter is not None:
+            if isinstance(foreign_node_filter, list):
+                # Separate the list into integers and strings
+                ints = filter(lambda x: isinstance(x, (int, long)), foreign_node_filter)
+                strs = filter(lambda x: isinstance(x, StringTypes), foreign_node_filter)
+                foreign_node_filter = Filter(ForeignNode.fields, {'node_id': ints, 'hostname': strs})
+                sql += " AND (%s)" % foreign_node_filter.sql(api, "OR")
+            elif isinstance(foreign_node_filter, dict):
+                foreign_node_filter = Filter(ForeignNode.fields, foreign_node_filter)
+                sql += " AND (%s)" % foreign_node_filter.sql(api, "AND")
 
-       if foreign_node_id_or_hostname_list:
-           foreign_node_id_list = [ str(x) for x in foreign_node_id_or_hostname_list 
-                                    if isinstance(x, (int,long))]
-           hostname_list = [ x for x in foreign_node_id_or_hostname_list
-                             if isinstance(x, StringTypes)]
-           sql += " AND (False"
-           if foreign_node_id_list:
-               sql += " OR node_id in (%s)" % ", ".join(foreign_node_id_list)
-           if hostname_list:
-               ## figure how to retrieve peer_id from the hostname(s)
-               sql += " OR hostname IN (%s)" % ", ".join(api.db.quote(hostname_list))
-           sql += ")"
-
-       rows = self.api.db.selectall (sql)
-
-       for row in rows:
-           self[row['hostname']] = ForeignNode (api,row)
-
-
-       
+       self.selectall(sql)
index b27c3a0..34d73b0 100644 (file)
@@ -4,13 +4,14 @@
 # Mark Huang <mlhuang@cs.princeton.edu>
 # Copyright (C) 2006 The Trustees of Princeton University
 #
-# $Id: NodeGroups.py,v 1.15 2006/10/25 14:29:13 mlhuang Exp $
+# $Id: NodeGroups.py,v 1.16 2006/11/02 18:32:55 mlhuang Exp $
 #
 
 from types import StringTypes
 
 from PLC.Faults import *
 from PLC.Parameter import Parameter
+from PLC.Filter import Filter
 from PLC.Debug import profile
 from PLC.Table import Row, Table
 from PLC.Nodes import Node, Nodes
@@ -103,31 +104,21 @@ class NodeGroups(Table):
     database.
     """
 
-    def __init__(self, api, nodegroup_id_or_name_list = None):
-       self.api = api
+    def __init__(self, api, nodegroup_filter = None):
+        Table.__init__(self, api, NodeGroup)
 
-        sql = "SELECT %s FROM view_nodegroups" % \
+        sql = "SELECT %s FROM view_nodegroups WHERE True" % \
               ", ".join(NodeGroup.fields)
 
-        if nodegroup_id_or_name_list:
-            # Separate the list into integers and strings
-            nodegroup_ids = filter(lambda nodegroup_id: isinstance(nodegroup_id, (int, long)),
-                                   nodegroup_id_or_name_list)
-            names = filter(lambda name: isinstance(name, StringTypes),
-                           nodegroup_id_or_name_list)
-            sql += " WHERE (False"
-            if nodegroup_ids:
-                sql += " OR nodegroup_id IN (%s)" % ", ".join(map(str, nodegroup_ids))
-            if names:
-                sql += " OR name IN (%s)" % ", ".join(api.db.quote(names))
-            sql += ")"
-
-        rows = self.api.db.selectall(sql)
-
-        for row in rows:
-            self[row['nodegroup_id']] = nodegroup = NodeGroup(api, row)
-            for aggregate in ['node_ids', 'conf_file_ids']:
-                if not nodegroup.has_key(aggregate) or nodegroup[aggregate] is None:
-                    nodegroup[aggregate] = []
-                else:
-                    nodegroup[aggregate] = map(int, nodegroup[aggregate].split(','))
+        if nodegroup_filter is not None:
+            if isinstance(nodegroup_filter, list):
+                # Separate the list into integers and strings
+                ints = filter(lambda x: isinstance(x, (int, long)), nodegroup_filter)
+                strs = filter(lambda x: isinstance(x, StringTypes), nodegroup_filter)
+                nodegroup_filter = Filter(NodeGroup.fields, {'nodegroup_id': ints, 'name': strs})
+                sql += " AND (%s)" % nodegroup_filter.sql(api, "OR")
+            elif isinstance(nodegroup_filter, dict):
+                nodegroup_filter = Filter(NodeGroup.fields, nodegroup_filter)
+                sql += " AND (%s)" % nodegroup_filter.sql(api, "AND")
+
+        self.selectall(sql)
index aa047c0..e3d9292 100644 (file)
@@ -4,11 +4,12 @@
 # Mark Huang <mlhuang@cs.princeton.edu>
 # Copyright (C) 2006 The Trustees of Princeton University
 #
-# $Id: PCUs.py,v 1.6 2006/10/25 14:29:13 mlhuang Exp $
+# $Id: PCUs.py,v 1.7 2006/11/02 18:32:55 mlhuang Exp $
 #
 
 from PLC.Faults import *
 from PLC.Parameter import Parameter
+from PLC.Filter import Filter
 from PLC.Debug import profile
 from PLC.Table import Row, Table
 from PLC.NodeNetworks import valid_ip, NodeNetwork, NodeNetworks
@@ -33,8 +34,8 @@ class PCU(Row):
         'password': Parameter(str, "PCU username", max = 254, nullok = True),
         'notes': Parameter(str, "Miscellaneous notes", max = 254, nullok = True),
         'model': Parameter(str, "PCU model string", max = 32, nullok = True),
-        'node_ids': Parameter([int], "List of nodes that this PCU controls", ro = True),
-        'ports': Parameter([int], "List of the port numbers that each node is connected to", ro = True),
+        'node_ids': Parameter([int], "List of nodes that this PCU controls"),
+        'ports': Parameter([int], "List of the port numbers that each node is connected to"),
         }
 
     def validate_ip(self, ip):
@@ -99,22 +100,17 @@ class PCUs(Table):
     database.
     """
 
-    def __init__(self, api, pcu_ids = None):
-        self.api = api
+    def __init__(self, api, pcu_filter = None):
+        Table.__init__(self, api, PCU)
 
-        # N.B.: Node IDs returned may be deleted.
-        sql = "SELECT %s FROM view_pcus" % \
+        sql = "SELECT %s FROM view_pcus WHERE True" % \
               ", ".join(PCU.fields)
 
-        if pcu_ids:
-            sql += " WHERE pcu_id IN (%s)" % ", ".join(map(str, pcu_ids))
+        if pcu_filter is not None:
+            if isinstance(pcu_filter, list):
+                pcu_filter = Filter(PCU.fields, {'pcu_id': pcu_filter})
+            elif isinstance(pcu_filter, dict):
+                pcu_filter = Filter(PCU.fields, pcu_filter)
+            sql += " AND (%s)" % pcu_filter.sql(api)
 
-        rows = self.api.db.selectall(sql)
-
-        for row in rows:
-            self[row['pcu_id']] = pcu = PCU(api, row)
-            for aggregate in ['node_ids', 'ports']:
-                if not pcu.has_key(aggregate) or pcu[aggregate] is None:
-                    pcu[aggregate] = []
-                else:
-                    pcu[aggregate] = map(int, pcu[aggregate].split(','))
+        self.selectall(sql)
index c887702..d4fed75 100644 (file)
@@ -8,6 +8,7 @@ from types import StringTypes
 
 from PLC.Faults import *
 from PLC.Parameter import Parameter
+from PLC.Filter import Filter
 from PLC.Table import Row, Table
 
 class Peer (Row):
@@ -50,29 +51,21 @@ class Peers (Table):
     Maps to the peers table in the database
     """
     
-    def __init__ (self, api, peer_id_or_peername_list = None):
-       self.api = api
+    def __init__ (self, api, peer_filter = None):
+        Table.__init__(self, api, Peer)
 
-       sql="SELECT %s FROM view_peers WHERE deleted IS False" % \
-           ", ".join(Peer.fields)
-       if peer_id_or_peername_list:
-            peer_ids = [x for x in peer_id_or_peername_list if isinstance(x, (int, long))]
-            peernames = [x for x in peer_id_or_peername_list if isinstance(x, StringTypes)]
-           sql += " AND (False"
-           if peer_ids:
-               sql += " OR peer_id in (%s)"% ", ".join([str(i) for i in peer_ids])
-           if peernames:
-               sql += " OR peername in (%s)"% ". ".join(api.db.quote(peernames)).lower()
-           sql += ")"
-
-       rows = self.api.db.selectall(sql)
-
-       for row in rows:
-           self[row['peer_id']] = peer = Peer(api,row)
-            for aggregate in ['node_ids']:
-                if not peer.has_key(aggregate) or peer[aggregate] is None:
-                    peer[aggregate] = []
-                else:
-                    peer[aggregate] = map(int, peer[aggregate].split(','))
+       sql = "SELECT %s FROM view_peers WHERE deleted IS False" % \
+              ", ".join(Peer.fields)
 
+        if peer_filter is not None:
+            if isinstance(peer_filter, list):
+                # Separate the list into integers and strings
+                ints = filter(lambda x: isinstance(x, (int, long)), peer_filter)
+                strs = filter(lambda x: isinstance(x, StringTypes), peer_filter)
+                peer_filter = Filter(Peer.fields, {'peer_id': ints, 'peername': strs})
+                sql += " AND (%s)" % peer_filter.sql(api, "OR")
+            elif isinstance(peer_filter, dict):
+                peer_filter = Filter(Peer.fields, peer_filter)
+                sql += " AND (%s)" % peer_filter.sql(api, "AND")
 
+       self.selectall(sql)
index 00fc964..05f480e 100644 (file)
@@ -3,6 +3,7 @@ import string
 
 from PLC.Faults import *
 from PLC.Parameter import Parameter
+from PLC.Filter import Filter
 from PLC.Debug import profile
 from PLC.Table import Row, Table
 from PLC.Slices import Slice, Slices
@@ -34,11 +35,11 @@ class Site(Row):
         'last_updated': Parameter(int, "Date and time when site entry was last updated, in seconds since UNIX epoch", ro = True),
         'max_slices': Parameter(int, "Maximum number of slices that the site is able to create"),
         'max_slivers': Parameter(int, "Maximum number of slivers that the site is able to create"),
-        'person_ids': Parameter([int], "List of account identifiers", ro = True),
-        'slice_ids': Parameter([int], "List of slice identifiers", ro = True),
-        'address_ids': Parameter([int], "List of address identifiers", ro = True),
-        'pcu_ids': Parameter([int], "List of PCU identifiers", ro = True),
-        'node_ids': Parameter([int], "List of site node identifiers", ro = True),
+        'person_ids': Parameter([int], "List of account identifiers"),
+        'slice_ids': Parameter([int], "List of slice identifiers"),
+        'address_ids': Parameter([int], "List of address identifiers"),
+        'pcu_ids': Parameter([int], "List of PCU identifiers"),
+        'node_ids': Parameter([int], "List of site node identifiers"),
         }
 
     def validate_name(self, name):
@@ -228,36 +229,24 @@ class Site(Row):
 class Sites(Table):
     """
     Representation of row(s) from the sites table in the
-    database. Specify fields to limit columns to just the specified
-    fields.
+    database.
     """
 
-    def __init__(self, api, site_id_or_login_base_list = None):
-        self.api = api
+    def __init__(self, api, site_filter = None):
+        Table.__init__(self, api, Site)
 
         sql = "SELECT %s FROM view_sites WHERE deleted IS False" % \
               ", ".join(Site.fields)
 
-        if site_id_or_login_base_list:
-            # Separate the list into integers and strings
-            site_ids = filter(lambda site_id: isinstance(site_id, (int, long)),
-                              site_id_or_login_base_list)
-            login_bases = filter(lambda login_base: isinstance(login_base, StringTypes),
-                                 site_id_or_login_base_list)
-            sql += " AND (False"
-            if site_ids:
-                sql += " OR site_id IN (%s)" % ", ".join(map(str, site_ids))
-            if login_bases:
-                sql += " OR login_base IN (%s)" % ", ".join(api.db.quote(login_bases))
-            sql += ")"
-
-        rows = self.api.db.selectall(sql)
-
-        for row in rows:
-            self[row['site_id']] = site = Site(api, row)
-            for aggregate in ['person_ids', 'slice_ids', 'address_ids',
-                              'pcu_ids', 'node_ids']:
-                if not site.has_key(aggregate) or site[aggregate] is None:
-                    site[aggregate] = []
-                else:
-                    site[aggregate] = map(int, site[aggregate].split(','))
+        if site_filter is not None:
+            if isinstance(site_filter, list):
+                # Separate the list into integers and strings
+                ints = filter(lambda x: isinstance(x, (int, long)), site_filter)
+                strs = filter(lambda x: isinstance(x, StringTypes), site_filter)
+                site_filter = Filter(Site.fields, {'site_id': ints, 'login_base': strs})
+                sql += " AND (%s)" % site_filter.sql(api, "OR")
+            elif isinstance(site_filter, dict):
+                site_filter = Filter(Site.fields, site_filter)
+                sql += " AND (%s)" % site_filter.sql(api, "AND")
+
+        self.selectall(sql)