commit-gnue
[Top][All Lists]
Advanced

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

r6545 - in trunk/gnue-common/src/datasources/drivers/sqlite/Schema: Crea


From: johannes
Subject: r6545 - in trunk/gnue-common/src/datasources/drivers/sqlite/Schema: Creation Discovery
Date: Fri, 22 Oct 2004 03:55:13 -0500 (CDT)

Author: johannes
Date: 2004-10-22 03:55:12 -0500 (Fri, 22 Oct 2004)
New Revision: 6545

Modified:
   trunk/gnue-common/src/datasources/drivers/sqlite/Schema/Creation/Creation.py
   
trunk/gnue-common/src/datasources/drivers/sqlite/Schema/Discovery/Introspection.py
Log:
Added index-introspection and creation to SQLite driver


Modified: 
trunk/gnue-common/src/datasources/drivers/sqlite/Schema/Creation/Creation.py
===================================================================
--- 
trunk/gnue-common/src/datasources/drivers/sqlite/Schema/Creation/Creation.py    
    2004-10-22 08:30:43 UTC (rev 6544)
+++ 
trunk/gnue-common/src/datasources/drivers/sqlite/Schema/Creation/Creation.py    
    2004-10-22 08:55:12 UTC (rev 6545)
@@ -1,6 +1,9 @@
+# GNU Enterprise Common - SQLite DB Driver - Schema creation
 #
-# This file is part of GNU Enterprise.
+# Copyright 2001-2004 Free Software Foundation
 #
+# This file is part of GNU Enterprise
+#
 # GNU Enterprise is free software; you can redistribute it
 # and/or modify it under the terms of the GNU General Public
 # License as published by the Free Software Foundation; either
@@ -16,20 +19,24 @@
 # write to the Free Software Foundation, Inc., 59 Temple Place
 # - Suite 330, Boston, MA 02111-1307, USA.
 #
-# Copyright 2001-2004 Free Software Foundation
-#
-# $Id: $
+# $Id$
 
 import os
 import re
 import string
+
+from gnue.common.apps import errors
 from gnue.common.datasources.drivers.DBSIG2.Schema.Creation import \
     Creation as Base
 
-class MissingTableError (gException):
+# =============================================================================
+# Excpetions
+# =============================================================================
+
+class MissingTableError (errors.AdminError):
   def __init__ (self, table):
     msg = u_("Cannot find table '%s' anymore") % table
-    gException.__init__ (self, msg)
+    errors.AdminError.__init__ (self, msg)
 
 # =============================================================================
 # Class implementing schema creation for SQLite
@@ -116,42 +123,68 @@
     res = ([], [], [])
     body = res [1]
 
-    tSchema = self.introspector.find (name = tableDefinition ['name'])
-    if tSchema is None:
-      raise MissingTableError, tableDefinition ['name']
+    table     = tableDefinition ['name']
+    hasFields = tableDefinition.has_key ('fields') and \
+        len (tableDefinition ['fields'])
 
-    parts = self._CMD.match (tSchema [0].sql)
-    if not parts:
-      raise gException, u_("Cannot split SQL command: '%s'") % tSchema [0].sql
+    # Remove old indices
+    if not hasFields and tableDefinition.has_key ('old_indices'):
+      for ixName in tableDefinition ['old_indices']:
+        self.mergeTuple (res, self.dropIndex (table, ixName, True))
 
-    fields = [f.name for f in tSchema [0].fields ()]
-    nfields = ["NULL" for f in tableDefinition ['fields']]
-    nfields.extend (fields)
+    if hasFields:
+      tSchema = self.introspector.find (name = tableDefinition ['name'])
+      if tSchema is None:
+        raise MissingTableError, tableDefinition ['name']
 
-    body.append (u"CREATE TEMPORARY TABLE t1_backup (%s)" \
-                 % string.join (fields, ","))
-    body.append (u"INSERT INTO t1_backup SELECT %(fields)s FROM %(table)s" \
-                 % {'fields': string.join (fields, ","),
-                    'table' : tableDefinition ['name']})
-    body.append (u"DROP TABLE %s" % tableDefinition ['name'])
+      parts = self._CMD.match (tSchema [0].sql)
+      if not parts:
+        raise gException, u_("Cannot split SQL command: '%s'") % tSchema 
[0].sql
 
-    fCode = self.createFields (tableDefinition ['name'],
-                               tableDefinition ['fields'])
-    self.mergeTuple (res, (fCode [0], [], fCode [2]))
+      fields = [f.name for f in tSchema [0].fields ()]
+      nfields = ["NULL" for f in tableDefinition ['fields']]
+      nfields.extend (fields)
 
-    oldSQL = parts.groups ()
-    newBody = [string.join (fCode [1], ", ")]
-    if len (oldSQL [1]):
-      newBody.append (oldSQL [1])
+      body.append (u"CREATE TEMPORARY TABLE t1_backup (%s)" \
+                   % string.join (fields, ","))
+      body.append (u"INSERT INTO t1_backup SELECT %(fields)s FROM %(table)s" \
+                   % {'fields': string.join (fields, ","),
+                      'table' : tableDefinition ['name']})
+      body.append (u"DROP TABLE %s" % tableDefinition ['name'])
 
-    cmd = u"%s (%s)%s" % (oldSQL [0], string.join (newBody, ", "), oldSQL [2])
+      fCode = self.createFields (tableDefinition ['name'],
+                                 tableDefinition ['fields'])
+      self.mergeTuple (res, (fCode [0], [], fCode [2]))
 
-    body.append (cmd)
-    body.append (u"INSERT INTO %(table)s SELECT %(fields)s FROM t1_backup" \
-                 % {'table' : tableDefinition ['name'],
-                    'fields': string.join (nfields, ",")})
-    body.append (u"DROP TABLE t1_backup")
+      oldSQL = parts.groups ()
+      newBody = [string.join (fCode [1], ", ")]
+      if len (oldSQL [1]):
+        newBody.append (oldSQL [1])
 
+      cmd = u"%s (%s)%s" % (oldSQL [0], string.join (newBody, ", "), oldSQL 
[2])
+
+      body.append (cmd)
+      body.append (u"INSERT INTO %(table)s SELECT %(fields)s FROM t1_backup" \
+                   % {'table' : tableDefinition ['name'],
+                      'fields': string.join (nfields, ",")})
+      body.append (u"DROP TABLE t1_backup")
+
+      # add all 'unchanged' indices
+      if tSchema [0].indices is not None:
+        for (indexName, index) in tSchema [0].indices.items ():
+          addIndices = tableDefinition.get ('indices')
+          if addIndices is None or indexName in addIndices:
+            continue
+
+          index ['name'] = indexName
+          self.mergeTuple (res, self.createIndex (table, index, True))
+
+
+    # Create all requested indices
+    if tableDefinition.has_key ('indices'):
+      for ixDef in tableDefinition ['indices']:
+        self.mergeTuple (res, self.createIndex (table, ixDef, True))
+
     if not codeOnly:
       self._executeCodeTuple (res)
 


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

Modified: 
trunk/gnue-common/src/datasources/drivers/sqlite/Schema/Discovery/Introspection.py
===================================================================
--- 
trunk/gnue-common/src/datasources/drivers/sqlite/Schema/Discovery/Introspection.py
  2004-10-22 08:30:43 UTC (rev 6544)
+++ 
trunk/gnue-common/src/datasources/drivers/sqlite/Schema/Discovery/Introspection.py
  2004-10-22 08:55:12 UTC (rev 6545)
@@ -1,10 +1,13 @@
+# GNU Enterprise Common - SQLite DB Driver - Schema Introspection
 #
-# This file is part of GNU Enterprise.
+# Copyright 2001-2004 Free Software Foundation
 #
+# This file is part of GNU Enterprise
+#
 # GNU Enterprise is free software; you can redistribute it
 # and/or modify it under the terms of the GNU General Public
 # License as published by the Free Software Foundation; either
-# version 2, or(at your option) any later version.
+# version 2, or (at your option) any later version.
 #
 # GNU Enterprise is distributed in the hope that it will be
 # useful, but WITHOUT ANY WARRANTY; without even the implied
@@ -16,13 +19,6 @@
 # write to the Free Software Foundation, Inc., 59 Temple Place
 # - Suite 330, Boston, MA 02111-1307, USA.
 #
-# Copyright 2000-2004 Free Software Foundation
-#
-# FILE:
-# Introspection.py
-#
-# DESCRIPTION:
-#
 # $Id$
 
 __all__ = ['Introspection']
@@ -32,6 +28,10 @@
 
 from gnue.common.datasources import GIntrospection
 
+# =============================================================================
+# This class implements schema introspection for SQLite backends
+# =============================================================================
+
 class Introspection (GIntrospection.Introspection):
 
   # list of the types of Schema objects this driver provides
@@ -45,6 +45,9 @@
   _NOTNULL   = re.compile ('(.*)(NOT NULL)(.*)', re.IGNORECASE)
   _CONSTRAINTS = re.compile ('.*?((UNIQUE|CHECK|PRIMARY KEY)\s*\(.*?\)).*', \
                              re.IGNORECASE)
+  _PRIMARYKEY  = re.compile ('.*?PRIMARY KEY\s*\((.*?)\).*', re.IGNORECASE)
+  _INDEX = re.compile ('CREATE\s*(\w+){0,1}\s*INDEX\s*(\w+)\s*ON\s*\w+\s*' \
+                       '\((.*?)\).*', re.IGNORECASE)
 
   # ---------------------------------------------------------------------------
   # Get a schema object matching name and type
@@ -63,7 +66,7 @@
     else:
       condition = "WHERE name = '%s'" % name
 
-    cmd = "SELECT type, name, sql FROM sqlite_master %s" % condition
+    cmd = u"SELECT type, name, sql FROM sqlite_master %s" % condition
     cursor = self._connection.makecursor (cmd)
 
     try:
@@ -75,6 +78,10 @@
                  'name': rs [1],
                  'type': rs [0],
                  'sql' : rs [2]}
+        
+        attrs ['primarykey'] = self.__getPrimaryKey (rs [2])
+        attrs ['indices']    = self.__getIndices (rs [1])
+
         result.append ( \
           GIntrospection.Schema (attrs, getChildSchema = self._getChildSchema))
 
@@ -156,3 +163,62 @@
       cursor.close ()
 
     return result
+
+
+  # ---------------------------------------------------------------------------
+  # Try to extract a primary key definition from SQL code
+  # ---------------------------------------------------------------------------
+
+  def __getPrimaryKey (self, sql):
+    """
+    This function extracts a primary key from the given SQL code.
+
+    @param sql: SQL code to extract primary key from
+    @return: sequence of fields building the primary key or None
+    """
+
+    result = None
+    pk     = self._PRIMARYKEY.match (sql)
+
+    if pk is not None:
+      result = [f.strip () for f in pk.groups () [0].split (',')]
+    
+    return result
+
+
+  # ---------------------------------------------------------------------------
+  # Try to extract all index definitions for a given table
+  # ---------------------------------------------------------------------------
+
+  def __getIndices (self, table):
+    """
+    This function fetches all indices for a given table and returns them as a
+    dictionary or None if no indices are available. NOTE: the primary key is
+    *NOT* listed as index.
+
+    @param table: name of the table to fetch indices from
+    @return: dictionary with index information or None
+    """
+
+    result = {}
+
+    cmd = u"SELECT name, sql FROM sqlite_master " \
+           "WHERE type = 'index' AND tbl_name = '%s' AND sql IS NOT NULL" \
+          % table
+
+    cursor = self._connection.makecursor (cmd)
+
+    try:
+      for rs in cursor.fetchall ():
+        ixm = self._INDEX.match (rs [1])
+        if ixm is not None:
+          (unique, name, fields) = ixm.groups ()
+          result [name] = { \
+              'unique' : unique is not None and unique.lower () == 'unique',
+              'primary': False,
+              'fields' : [f.strip () for f in fields.split (',')]}
+
+    finally:
+      cursor.close ()
+
+    return len (result.keys ()) and result or None





reply via email to

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