- 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
 #
 # 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.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
 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"),
         '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):
         }
 
     def add_node(self, node, commit = True):
@@ -138,27 +139,17 @@ class ConfFiles(Table):
     Representation of the conf_files table in the database.
     """
 
     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)
         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.Table import Row, Table
 from PLC.Parameter import Parameter
+from PLC.Filter import Filter
 
 class ForeignNode (Row) :
     """
 
 class ForeignNode (Row) :
     """
@@ -42,31 +43,21 @@ class ForeignNode (Row) :
 
 class ForeignNodes (Table):
 
 
 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
 #
 # 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 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
 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.
     """
 
     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)
 
               ", ".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
 #
 # 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.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
 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),
         '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):
         }
 
     def validate_ip(self, ip):
@@ -99,22 +100,17 @@ class PCUs(Table):
     database.
     """
 
     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)
 
               ", ".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.Faults import *
 from PLC.Parameter import Parameter
+from PLC.Filter import Filter
 from PLC.Table import Row, Table
 
 class Peer (Row):
 from PLC.Table import Row, Table
 
 class Peer (Row):
@@ -50,29 +51,21 @@ class Peers (Table):
     Maps to the peers table in the database
     """
     
     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.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
 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"),
         '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):
         }
 
     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
 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)
 
 
         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)