commit-gnue
[Top][All Lists]
Advanced

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

r5944 - in trunk/gnue-common/src/datasources/drivers: interbase/Schema/D


From: johannes
Subject: r5944 - in trunk/gnue-common/src/datasources/drivers: interbase/Schema/Discovery interbase/interbase postgresql/Schema/Discovery
Date: Wed, 7 Jul 2004 17:14:22 -0500 (CDT)

Author: johannes
Date: 2004-07-06 08:19:38 -0500 (Tue, 06 Jul 2004)
New Revision: 5944

Modified:
   
trunk/gnue-common/src/datasources/drivers/interbase/Schema/Discovery/Introspection.py
   trunk/gnue-common/src/datasources/drivers/interbase/interbase/Connection.py
   
trunk/gnue-common/src/datasources/drivers/postgresql/Schema/Discovery/Introspection.py
Log:
Rebuilt introspection for interbase


Modified: 
trunk/gnue-common/src/datasources/drivers/interbase/Schema/Discovery/Introspection.py
===================================================================
--- 
trunk/gnue-common/src/datasources/drivers/interbase/Schema/Discovery/Introspection.py
       2004-07-06 08:45:14 UTC (rev 5943)
+++ 
trunk/gnue-common/src/datasources/drivers/interbase/Schema/Discovery/Introspection.py
       2004-07-06 13:19:38 UTC (rev 5944)
@@ -18,173 +18,170 @@
 #
 # Copyright 2000-2004 Free Software Foundation
 #
-# FILE:
-# Introspection.py
-#
-# DESCRIPTION:
-#
-# NOTES:
-#
+# $Id$
 
 __all__ = ['Introspection']
 
 import string
-from string import lower, join, rstrip, upper
-import sys
+import re
 
-from gnue.common.apps import GDebug, GConfig
 from gnue.common.datasources import GIntrospection
 
-DESCRIPTION_NAME            = 0
-DESCRIPTION_TYPE_CODE       = 1
-DESCRIPTION_DISPLAY_SIZE    = 2
-DESCRIPTION_INTERNAL_SIZE   = 3
-DESCRIPTION_PRECISION       = 4
-DESCRIPTION_SCALE           = 5
-DESCRIPTION_NULL_OK         = 6
+# =============================================================================
+# This class implements schema introspection for Interbase / Firebird
+# =============================================================================
 
 class Introspection(GIntrospection.Introspection):
-  _primaryKeyFields = []
 
   # list of the types of Schema objects this driver provides
-  types =[ ('table',_('Tables'),1),
-           ('view',_('Views'),1)]
+  types = [('table', _('Tables'), 1),
+           ('view' , _('Views') , 1)]
 
-  #
-  # TODO: This is a quick hack to get this class
-  # TODO: into the new-style schema format.
-  # TODO: getSchema* should be merged into find()
-  #
-  def find(self, name=None, type=None):
-    if name is None:
-      return self.getSchemaList(type)
-    else:
-      rs = self.getSchemaByName(name, type)
-      if rs:
-        return [rs]
-      else:
-        return None
+  _NOW = re.compile ("'(NOW\s*\(\)\s*)'", re.IGNORECASE)
 
 
-  # TODO: Merge into find()
-  # Return a list of Schema objects
+  # ---------------------------------------------------------------------------
+  # Find a schema element by name and/or type
+  # ---------------------------------------------------------------------------
 
-  #
-  # Schema (metadata) functions
-  #
+  def find (self, name = None, type = None):
+    """
+    This function searches the schema for an element by name and/or type. If no
+    name and no type is given, all elements will be retrieved.
 
-  # Return a list of Schema objects
-  def getSchemaList(self, type=None):
+    @param name: look for an element with this name
+    @param type: look for an element with this type
+    @return: A sequence of schema instances, one per element found, or None if
+        no element could be found.
+    """
 
-  # This excludes any system tables and views.
-    statement = "select rdb$relation_name, rdb$view_source "+\
-                       "from rdb$relations " + \
-                       "where rdb$system_flag=0 " + \
-                       "order by rdb$relation_name"
+    result = []
+    cond   = ["rdb$system_flag = 0"]
 
-    cursor = self._connection.native.cursor()
-    cursor.execute(statement)
+    if name is not None:
+      cond.append (u"rdb$relation_name = '%s'" \
+                   % self._connection.identifier (name))
 
-  # TODO: rdb$view_source is null for table and rdb$view_source is not null 
for view
-    list = []
-    for rs in cursor.fetchall():
-      list.append(GIntrospection.Schema(attrs={'id':rs[0], 
'name':rstrip(rs[0]),
-                         'type':'table',
-                        'primarykey': self.__getPrimaryKey(rstrip(rs[0]))},
-                         getChildSchema=self.__getFieldSchema))
+    if type == 'table':
+      cond.append (u"rdb$view_source IS NULL")
+    elif type == 'view':
+      cond.append (u"rdb$view_source IS NOT NULL")
 
-    cursor.close()
-    return list
+    cmd = u"SELECT rdb$relation_name, rdb$view_source FROM RDB$RELATIONS " \
+           "WHERE %s ORDER BY rdb$relation_name" % string.join (cond, " AND ")
 
-  # Find a schema object with specified name
-  def getSchemaByName(self, name, type=None):
+    cursor = self._connection.makecursor (cmd)
 
-    statement = "select rdb$relation_name, rdb$view_source "+\
-                       "from rdb$relations " + \
-                       "where rdb$relation_name = '%s'" % (name.upper ())
+    try:
+      for rs in cursor.fetchall ():
+        relname = self._connection.identifier (string.strip (rs [0]))
 
-    cursor = self._connection.native.cursor()
-    cursor.execute(statement)
+        attrs = {'id'        : relname,
+                 'name'      : relname,
+                 'type'      : rs [1] is None and 'table' or 'view',
+                 'primarykey': self.__getPrimaryKey (relname)}
 
-    rs = cursor.fetchone()
-    if rs:
-      schema = GIntrospection.Schema(attrs={'id':rs[0], 'name':rstrip(rs[0]),
-                           'type':'table',
-                          'primarykey': self.__getPrimaryKey(rstrip(rs[0]))},
-                           getChildSchema=self.__getFieldSchema)
-    else:
-      schema = None
+        result.append ( \
+          GIntrospection.Schema (attrs, getChildSchema = self._getChildSchema))
 
-    cursor.close()
-    return schema
+    finally:
+      cursor.close ()
 
-  # Return a list of fields (for _buildDeleteStatement and for 
_buildUpdateStatement)
-  def __getPrimaryKey(self, relname):
-    statement = "select rdb$relation_name, rdb$field_name, "+\
-                                  "rdb$constraint_name, rdb$field_position "+\
-                                   "from rdb$relation_constraints rc, 
rdb$index_segments ri "+\
-                                   "where ri.rdb$index_name = 
rc.rdb$index_name "+\
-                                           "and rc.rdb$constraint_type = 
'PRIMARY KEY' "+\
-                                           "and rc.rdb$relation_name = '%s' " 
% (relname)+\
-                                   "order by ri.rdb$field_position"
+    return len (result) and result or None
 
-    cursor = self._connection.native.cursor()
-    cursor.execute(statement)
 
-    list = []
-    for rs in cursor.fetchall():
-      list.append(lower(rstrip(rs[1])))
+  # ---------------------------------------------------------------------------
+  # Get all fields of a relation / view
+  # ---------------------------------------------------------------------------
 
-    cursor.close()
-    return list
+  def _getChildSchema (self, parent):
+    """
+    This function returns a list of all child elements of a given parent
+    relation.
 
-  # Get fields for a table
-  def __getFieldSchema(self, parent):
+    @param parent: schema object instance whose child elements should be
+        fetched.
+    @return: sequence of schema instances, one per element found
+    """
 
-    statement = "select * from %s"%(parent.name) + " where (0=1)"
+    result = []
 
-    cursor = self._connection.native.cursor()
-    cursor.execute(statement)
+    cmd = u"SELECT rf.rdb$field_name, tp.rdb$type_name, rf.rdb$null_flag, " \
+             "rf.rdb$default_source, fs.rdb$field_length, " \
+             "fs.rdb$field_scale, fs.rdb$field_precision " \
+           "FROM rdb$relation_fields rf, rdb$fields fs, rdb$types tp " \
+           "WHERE rf.rdb$relation_name = '%s' AND " \
+             "fs.rdb$field_name = rf.rdb$field_source AND " \
+             "tp.rdb$type = fs.rdb$field_type AND " \
+             "tp.rdb$field_name = 'RDB$FIELD_TYPE'" \
+           "ORDER BY rf.rdb$field_name" % parent.name
 
-    list = []
+    cursor = self._connection.makecursor (cmd)
 
-    for d in cursor.description:
-      try:
-        nativetype = lower(d[DESCRIPTION_TYPE_CODE].__name__)
-      except AttributeError:
-        nativetype='unknown'
-      
-      attrs={'id':d[DESCRIPTION_NAME],
-                 'name':lower (d[DESCRIPTION_NAME]),
-                 'type':'field',
+    try:
+      for rs in cursor.fetchall ():
+        nativetype = rs [1].strip ()
+        attrs = {'id'        : "%s.%s" % (parent.name, rs [0].strip ()),
+                 'name'      : self._connection.identifier (rs [0].strip ()),
+                 'type'      : 'field',
                  'nativetype': nativetype,
-                 'required': d[DESCRIPTION_NULL_OK]==0,
-                 'length': d[DESCRIPTION_DISPLAY_SIZE]}
+                 'required'  : rs [2] is not None}
 
-      if nativetype in ('int','float','long'):
-        attrs['datatype']='number'
-        attrs['precision']=d[DESCRIPTION_SCALE]
-      elif nativetype == 'tuple':
-        attrs['datatype']='date'
-      else:
-        attrs['datatype']='text'
+        if nativetype in ['DATE', 'TIME', 'TIMESTAMP']:
+          attrs ['datatype'] = 'date'
 
-      cursor.execute("select rdb$default_source from rdb$relation_fields"+ \
-                  " where rdb$relation_name = '%s' " % (parent.name.upper ())+ 
\
-                  " and rdb$field_name = '%s'" % (upper(attrs['name'])))
-      defrs = cursor.fetchone()
-      try:
-        if defrs[0]:
-          dflt = defrs[0]
-          if dflt[9:12] == "NOW":
-            attrs['defaulttype'] = 'timestamp'
+        elif nativetype in ['DOUBLE', 'FLOAT', 'INT64', 'LONG', 'QUAD', \
+            'SHORT']:
+          attrs ['datatype']  = 'number'
+          attrs ['length']    = rs [6]
+          attrs ['precision'] = abs (rs [5])
+
+        else:
+          attrs ['datatype'] = 'text'
+          attrs ['length'] = rs [4]
+
+        if rs [3] is not None:
+          default = rs [3]
+          if self._NOW.search (default) is not None:
+            attrs ['defaulttype'] = 'timestamp'
           else:
-            attrs['defaulttype'] = 'constant'
-            attrs['defaultval'] = dflt[8:]
-      except:
-        pass
+            attrs ['defaulttype'] = 'constant'
+            attrs ['defaultval']  = default [8:]
 
-      list.append(GIntrospection.Schema(attrs=attrs))
+        result.append (GIntrospection.Schema (attrs))
 
-    cursor.close()
-    return list
+    finally:
+      cursor.close ()
+
+    return result
+
+
+  # ---------------------------------------------------------------------------
+  # Get all parts of a primary key
+  # ---------------------------------------------------------------------------
+
+  def __getPrimaryKey (self, relname):
+    """
+    This function fetches all fields of a primary key for the given relation.
+
+    @param relid: object id of the relation in question
+    @return: sequence with the fieldnames of the primary key or None, if the
+        relation has no primary key.
+    """
+
+    cmd = u"SELECT rdb$field_name " \
+           "FROM rdb$relation_constraints rc, rdb$index_segments ri " \
+           "WHERE ri.rdb$index_name = rc.rdb$index_name " \
+              "AND rc.rdb$constraint_type = 'PRIMARY KEY' " \
+              "AND rc.rdb$relation_name = '%s'" \
+           "ORDER BY ri.rdb$field_position" % relname
+
+    cursor = self._connection.makecursor (cmd)
+    
+    try:
+      result = [rs [0].strip () for rs in cursor.fetchall ()]
+
+    finally:
+      cursor.close ()
+
+    return len (result) and result or None


Property changes on: 
trunk/gnue-common/src/datasources/drivers/interbase/Schema/Discovery/Introspection.py
___________________________________________________________________
Name: svn:keywords
   + Id

Modified: 
trunk/gnue-common/src/datasources/drivers/interbase/interbase/Connection.py
===================================================================
--- trunk/gnue-common/src/datasources/drivers/interbase/interbase/Connection.py 
2004-07-06 08:45:14 UTC (rev 5943)
+++ trunk/gnue-common/src/datasources/drivers/interbase/interbase/Connection.py 
2004-07-06 13:19:38 UTC (rev 5944)
@@ -169,8 +169,12 @@
       return None
 
 
+  # ---------------------------------------------------------------------------
+  # convert an identifier to be safely used
+  # ---------------------------------------------------------------------------
+
   def identifier (self, identifier):
-    return identifier.lower ()
+    return identifier.upper ()
 
 
 


Property changes on: 
trunk/gnue-common/src/datasources/drivers/postgresql/Schema/Discovery/Introspection.py
___________________________________________________________________
Name: svn:keywords
   - +Id
   + Id





reply via email to

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