commit-gnue
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

r5213 - in trunk/gnue-common/src/schema: . scripter scripter/processors


From: johannes
Subject: r5213 - in trunk/gnue-common/src/schema: . scripter scripter/processors
Date: Wed, 3 Mar 2004 10:47:54 -0600 (CST)

Author: johannes
Date: 2004-03-03 10:47:53 -0600 (Wed, 03 Mar 2004)
New Revision: 5213

Modified:
   trunk/gnue-common/src/schema/Objects.py
   trunk/gnue-common/src/schema/scripter/Definition.py
   trunk/gnue-common/src/schema/scripter/Scripter.py
   trunk/gnue-common/src/schema/scripter/processors/Base.py
   trunk/gnue-common/src/schema/scripter/processors/HTML.py
   trunk/gnue-common/src/schema/scripter/processors/SQL.py
Log:
Added Constraint-support to gnue-schema.


Modified: trunk/gnue-common/src/schema/Objects.py
===================================================================
--- trunk/gnue-common/src/schema/Objects.py     2004-03-03 16:47:06 UTC (rev 
5212)
+++ trunk/gnue-common/src/schema/Objects.py     2004-03-03 16:47:53 UTC (rev 
5213)
@@ -39,7 +39,6 @@
     text = _("Errors found while processing GSD file.")
     Exception.__init__ (self, text)
 
-
 class GSObject(GObj):
   pass
 
@@ -70,7 +69,7 @@
 class GSField(GSObject):
   def __init__(self, parent):
     GSObject.__init__(self, parent, type='GSField')
-  
+
   def _buildObject(self):
     # TODO: Added with Common 0.5.0; deprecate at some point
     if hasattr(self,'auto') and self.auto:
@@ -78,7 +77,7 @@
       self.auto = 0
 
     return GSObject._buildObject(self)
-
+  
 class GSPrimaryKey(GSObject):
   def __init__(self, parent):
     GSObject.__init__(self, parent, type='GSPrimaryKey')
@@ -94,7 +93,121 @@
 class GSConstraint(GSObject):
   def __init__(self, parent):
     GSObject.__init__(self, parent, type='GSConstraint')
+    self._inits.append (self._validate)
+    self.__tables = None
 
+
+  # ---------------------------------------------------------------------------
+  # Check a constraint definition
+  # ---------------------------------------------------------------------------
+
+  def _validate (self):
+    self.type = self.type.lower ()
+
+    try:
+      if not self.type in ["unique", "foreignkey"]:
+        raise Exception (_("Invalid constraint type '%s'.") % self.type)
+
+      csFields = self.findChildrenOfType ('GSConstraintField')
+      self.__checkFields (None, csFields)
+
+      if self.type == "foreignkey":
+        refFields = self.findChildrenOfType ('GSConstraintRef')
+        if refFields is None:
+          raise Exception (_("Constraint '%s' has no reference fields.") % \
+                             self.name)
+        self.__checkFields (refFields [0].table, refFields)
+
+        if len (refFields) <> len (csFields):
+          raise Exception (_("Constraint '%s' has unbalanced fields.") % \
+                            self.name)
+
+        self.__typeCheck (csFields, refFields)
+
+
+    except Exception, message:
+      print message
+      setErrorFlag (self)
+
+
+  # ---------------------------------------------------------------------------
+  # find a table definition in the object hierachy for @tablename
+  # ---------------------------------------------------------------------------
+
+  def __findTable (self, tablename = None):
+    # if no tablename is given we're looking for our parent table
+    if tablename is None:
+      return self.findParentOfType ('GSTable')
+
+    if self.__tables is None:
+      self.__tables = self.findParentOfType ('GSTables')
+
+    if self.__tables is not None:
+      for table in self.__tables.findChildrenOfType ('GSTable'):
+        if table.name == tablename:
+          return table
+
+    return None
+
+
+  # ---------------------------------------------------------------------------
+  # Check if the table 'tablename' has all fields listed in 'cFields'
+  # ---------------------------------------------------------------------------
+
+  def __checkFields (self, tablename, cFields):
+    """
+    This function raises an exception if the table @tablename has not all
+    fields listed in @cFields.
+    """
+    table = self.__findTable (tablename)
+    if table is None:
+      raise Exception (_("Cannot find table '%s'") % tablename)
+
+    tbFields = table.findChildrenOfType ('GSField', True, True)
+
+    if len (cFields) > len (tbFields):
+      raise Exception (_("Constraint '%s' has more fields than the " + \
+                         "table '%s'") % (self.name, table.name))
+
+    for check in cFields:
+      try:
+        for field in tbFields:
+          if field.name == check.name:
+            raise Exception ('found')
+
+      except:
+        pass
+
+      else:
+        raise Exception (_("Table '%s' has no field '%s'.") % \
+                           (table.name, check.name))
+
+
+  # ---------------------------------------------------------------------------
+  # Check if both sides of a reference matches in type
+  # ---------------------------------------------------------------------------
+
+  def __typeCheck (self, csFields, refFields):
+    csTable = self.__findTable ()
+    rfTable = self.__findTable (refFields [0].table)
+
+    rfFields = {}
+    myFields = {}
+
+    for item in csTable.findChildrenOfType ('GSField', True, True):
+      myFields [item.name] = item
+
+    for item in rfTable.findChildrenOfType ('GSField', True, True):
+      rfFields [item.name] = item
+
+
+    for ix in range (0, len (csFields)):
+      if myFields [csFields [ix].name].type != \
+         rfFields [refFields [ix].name].type:
+        raise Exception (_("Constraint '%s': typemismatch in reference " + \
+                           "field '%s'.") % (self.name, csFields [ix].name))
+
+
 class GSConstraintField(GSObject):
   def __init__(self, parent):
     GSObject.__init__(self, parent, type='GSConstraintField')
@@ -165,14 +278,9 @@
       self.value = None
 
       print message
+      setErrorFlag (self)
 
-      parent = self._parent
 
-      while parent is not None:
-        parent.foundErrors = True
-        parent = parent._parent
-
-
   # ---------------------------------------------------------------------------
   # Find a column definition either by it's index or by it's fieldname
   # ---------------------------------------------------------------------------
@@ -274,3 +382,17 @@
 
   def _validate (self):
     (self.typename, self.length, self.scale) = verifyDataType (self)
+
+
+# -----------------------------------------------------------------------------
+# recursively set an error flag in a object hierarchy
+# -----------------------------------------------------------------------------
+
+def setErrorFlag (aObject):
+  """
+  This function sets the property 'foundErrors' in a object and all its
+  parents.
+  """
+  if aObject is not None:
+    aObject.foundErrors = True
+    setErrorFlag (aObject._parent)

Modified: trunk/gnue-common/src/schema/scripter/Definition.py
===================================================================
--- trunk/gnue-common/src/schema/scripter/Definition.py 2004-03-03 16:47:06 UTC 
(rev 5212)
+++ trunk/gnue-common/src/schema/scripter/Definition.py 2004-03-03 16:47:53 UTC 
(rev 5213)
@@ -133,17 +133,32 @@
   # ---------------------------------------------------------------------------
   # Create a new IndexDefinition and add it to our index-sequence
   # ---------------------------------------------------------------------------
-  """
-  This function creates a new IndexDefinition instance, adds it into the
-  table definitions' index-dictionary and returns it as a function result.
-  """
+
   def newIndex (self, name, unique = False):
+    """
+    This function creates a new IndexDefinition instance, adds it into the
+    table definitions' index-dictionary and returns it as a function result.
+    """
     index = IndexDefinition (name, unique)
     self.indices [index.name] = index
     return index
 
 
   # ---------------------------------------------------------------------------
+  # Create a new ConstraintDefinition
+  # ---------------------------------------------------------------------------
+
+  def newConstraint (self, name, kind):
+    """
+    This function creates a new ConstraintDefinition instance, adds it into the
+    table definitions' constraint-dictionary and returns it.
+    """
+    constraint = ConstraintDefinition (name, kind)
+    self.constraints [constraint.name] = constraint
+    return constraint
+
+
+  # ---------------------------------------------------------------------------
   # Create a new primary key definition
   # ---------------------------------------------------------------------------
 
@@ -169,7 +184,21 @@
 
     return None
 
+# =============================================================================
+# Constraint definition
+# =============================================================================
 
+class ConstraintDefinition (SchemaDefinition):
+  """
+  """
+  def __init__ (self, name = None, kind = None):
+    SchemaDefinition.__init__ (self, name)
+    self.kind      = kind
+    self.reftable  = None
+    self.reffields = []
+
+
+
 # =============================================================================
 # Definition class for data rows
 # =============================================================================

Modified: trunk/gnue-common/src/schema/scripter/Scripter.py
===================================================================
--- trunk/gnue-common/src/schema/scripter/Scripter.py   2004-03-03 16:47:06 UTC 
(rev 5212)
+++ trunk/gnue-common/src/schema/scripter/Scripter.py   2004-03-03 16:47:53 UTC 
(rev 5213)
@@ -306,9 +306,20 @@
       # iterate over all index fields
       sObject.walk (self.__schema_index, tableDef = tableDef, indexDef = index)
 
-    # TODO: constraints 
+    # create constraints
+    elif sObject._type == "GSConstraint":
+      # for unique-constraints we use a 'unique index'
+      if sObject.type == "unique":
+        cDef = tableDef.newIndex (sObject.name, True)
 
+      # for all other types of constraints we use a ConstraintDefinition
+      else:
+        cDef = tableDef.newConstraint (sObject.name, sObject.type)
 
+      sObject.walk (self.__schema_constraint, constraint = cDef)
+      
+
+
   # ---------------------------------------------------------------------------
   # Iterate over all fields of a primary key
   # ---------------------------------------------------------------------------
@@ -326,6 +337,19 @@
 
 
   # ---------------------------------------------------------------------------
+  # Iterate over all children of a constraint definition
+  # ---------------------------------------------------------------------------
+
+  def __schema_constraint (self, sObject, constraint):
+    if sObject._type == "GSConstraintField":
+      constraint.fields.append (sObject)
+
+    elif sObject._type == "GSConstraintRef":
+      constraint.reftable = sObject.table
+      constraint.reffields.append (sObject)
+
+
+  # ---------------------------------------------------------------------------
   # Process a tabledata node
   # ---------------------------------------------------------------------------
   def __data_table (self, sObject):

Modified: trunk/gnue-common/src/schema/scripter/processors/Base.py
===================================================================
--- trunk/gnue-common/src/schema/scripter/processors/Base.py    2004-03-03 
16:47:06 UTC (rev 5212)
+++ trunk/gnue-common/src/schema/scripter/processors/Base.py    2004-03-03 
16:47:53 UTC (rev 5213)
@@ -239,7 +239,7 @@
 
 
   # ---------------------------------------------------------------------------
-  # Virtual: Process the constraints of a table definition
+  # Process the constraints of a table definition
   # ---------------------------------------------------------------------------
 
   def _processConstraints (self, tableDef):
@@ -247,6 +247,19 @@
     A processor can override this method to translate all constraints of a
     table definition.
     """
+    for constraint in tableDef.constraints.values ():
+      self._processConstraint (tableDef, constraint)
+
+
+  # ---------------------------------------------------------------------------
+  # Virtual: process a single constraint of a table definition
+  # ---------------------------------------------------------------------------
+
+  def _processConstraint (self, tableDef, constraint):
+    """
+    A processor can override this method to translate a single
+    constraintdefinition.
+    """
     pass
 
 

Modified: trunk/gnue-common/src/schema/scripter/processors/HTML.py
===================================================================
--- trunk/gnue-common/src/schema/scripter/processors/HTML.py    2004-03-03 
16:47:06 UTC (rev 5212)
+++ trunk/gnue-common/src/schema/scripter/processors/HTML.py    2004-03-03 
16:47:53 UTC (rev 5213)
@@ -128,8 +128,41 @@
     epi.append ('</UL>')
 
 
+  # ---------------------------------------------------------------------------
+  # Process a constraint definition
+  # ---------------------------------------------------------------------------
 
+  def _processConstraint (self, tableDef, constraint):
+    epi = tableDef.epilogue
 
+    epi.append ("")
+    epi.extend (self.comment ("Constraint '%s'" % constraint.name))
+    if constraint.kind == "foreignkey":
+      epi.append ('<H3 class="constraint">%s: %s</H3>' % 
+        (_("Foreign Key"), constraint.name))
+
+      epi.append ('<TABLE class="constraintdef" width="90%" border="0" ' + \
+                  'cellpadding="3" cellspacing="1">')
+      epi.append ('<TR>')
+      epi.append ('  <TH class="fields">%s</TH>' % tableDef.name)
+      epi.append ('  <TH class="fields">&nbsp;</TH>')
+      epi.append ('  <TH class="fields"><A HREF="#%s">%s</A></TH>' % \
+        (constraint.reftable, constraint.reftable))
+      epi.append ('</TR>')
+
+      epi.append ('<TR>')
+      epi.append ('  <TD class="fields">')
+      epi.extend (["    %s<BR>" % cf.name for cf in constraint.fields])
+      epi.append ('  </TD>')
+      epi.append ('  <TD class="fields">%s</TD>' % _("references"))
+      epi.append ('  <TD class="fields">')
+      epi.extend (["    %s<BR>" % rf.name for rf in constraint.reffields])
+      epi.append ('  </TD>')
+      epi.append ('</TR>')
+      epi.append ('</TABLE>')
+
+
+
   # ---------------------------------------------------------------------------
   # Create a sequence with a header row for field tables
   # ---------------------------------------------------------------------------

Modified: trunk/gnue-common/src/schema/scripter/processors/SQL.py
===================================================================
--- trunk/gnue-common/src/schema/scripter/processors/SQL.py     2004-03-03 
16:47:06 UTC (rev 5212)
+++ trunk/gnue-common/src/schema/scripter/processors/SQL.py     2004-03-03 
16:47:53 UTC (rev 5213)
@@ -141,15 +141,23 @@
   # ---------------------------------------------------------------------------
   # Integrate constraints into table definition
   # ---------------------------------------------------------------------------
-  def _processConstraints (self, tableDef):
+
+  def _processConstraint (self, tableDef, constraint):
     """
-    Constraints are NOT implemented at the moment
+    This function processes a foreign key constraint.
     """
-    for constraint in tableDef.constraints.values ():
-      pass
+    if constraint.kind == "foreignkey":
+      if len (tableDef.body) and tableDef.body [-1].strip () [-1] != ",":
+        tableDef.body [-1] += u","
 
+      tableDef.body.append ("  CONSTRAINT %s FOREIGN KEY (%s)" % \
+        (constraint.name, join ([cf.name for cf in constraint.fields], ", ")))
+      tableDef.body.append ("    REFERENCES %s (%s)" % \
+        (constraint.reftable, join ([rf.name for rf in constraint.reffields],
+                                    ", ")))
 
 
+
   # ---------------------------------------------------------------------------
   # Translate a data definition
   # ---------------------------------------------------------------------------





reply via email to

[Prev in Thread] Current Thread [Next in Thread]