~ubuntu-branches/ubuntu/hardy/gnue-common/hardy

« back to all changes in this revision

Viewing changes to src/datasources/drivers/mysql/Schema/Discovery/Introspection.py

  • Committer: Bazaar Package Importer
  • Author(s): Andrew Mitchell
  • Date: 2005-03-09 11:06:31 UTC
  • Revision ID: james.westby@ubuntu.com-20050309110631-8gvvn39q7tjz1kj6
Tags: upstream-0.5.14
ImportĀ upstreamĀ versionĀ 0.5.14

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# GNU Enterprise Common - MySQL DB driver - Schema Introspection
 
2
#
 
3
# Copyright 2001-2005 Free Software Foundation
 
4
#
 
5
# This file is part of GNU Enterprise
 
6
#
 
7
# GNU Enterprise is free software; you can redistribute it
 
8
# and/or modify it under the terms of the GNU General Public
 
9
# License as published by the Free Software Foundation; either
 
10
# version 2, or (at your option) any later version.
 
11
#
 
12
# GNU Enterprise is distributed in the hope that it will be
 
13
# useful, but WITHOUT ANY WARRANTY; without even the implied
 
14
# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
 
15
# PURPOSE. See the GNU General Public License for more details.
 
16
#
 
17
# You should have received a copy of the GNU General Public
 
18
# License along with program; see the file COPYING. If not,
 
19
# write to the Free Software Foundation, Inc., 59 Temple Place
 
20
# - Suite 330, Boston, MA 02111-1307, USA.
 
21
#
 
22
# $Id: Introspection.py 6851 2005-01-03 20:59:28Z jcater $
 
23
 
 
24
__all__ = ['Introspection']
 
25
 
 
26
import string
 
27
 
 
28
from gnue.common.datasources import GIntrospection
 
29
 
 
30
# =============================================================================
 
31
# This class implements schema introspection for MySQL backends
 
32
# =============================================================================
 
33
 
 
34
class Introspection (GIntrospection.Introspection):
 
35
 
 
36
  # list of the types of Schema objects this driver provides
 
37
  types = [('table', _('Tables'), 1)]
 
38
 
 
39
  _TYPES = {'number': ['int','integer','bigint','mediumint',
 
40
                       'smallint','tinyint','float','real', 'double','decimal'],
 
41
            'date'  : ['date','time','timestamp','datetime']}
 
42
 
 
43
  # ---------------------------------------------------------------------------
 
44
  # Find a schema element by name and/or type
 
45
  # ---------------------------------------------------------------------------
 
46
 
 
47
  def find (self, name = None, type = None):
 
48
    """
 
49
    This function searches the schema for an element by name and/or type. If no
 
50
    name and no type is given, all elements will be retrieved.
 
51
 
 
52
    @param name: look for an element with this name
 
53
    @param type: look for an element with this type
 
54
 
 
55
    @return: A sequence of schema instances, one per element found, or None if
 
56
        no element could be found.
 
57
    """
 
58
 
 
59
    result = []
 
60
 
 
61
    if name is None:
 
62
      cmd = u"SHOW TABLES"
 
63
 
 
64
    else:
 
65
      cmd = u"SHOW COLUMNS FROM %s" % name
 
66
 
 
67
    try:
 
68
      cursor = self._connection.makecursor (cmd)
 
69
 
 
70
    except:
 
71
      if name is not  None:
 
72
        return None
 
73
 
 
74
      else:
 
75
        raise
 
76
 
 
77
    try:
 
78
      for rs in cursor.fetchall ():
 
79
        attrs = {'id'        : name or rs [0],
 
80
                 'name'      : name or rs [0],
 
81
                 'type'      : 'table',
 
82
                 'primarykey': None,
 
83
                 'indices'   : self.__getIndices (name or rs [0])}
 
84
 
 
85
        if attrs ['indices'] is not None:
 
86
          for index in attrs ['indices'].values ():
 
87
            if index ['primary']:
 
88
              attrs ['primarykey'] = index ['fields']
 
89
              break
 
90
 
 
91
        result.append ( \
 
92
          GIntrospection.Schema (attrs, getChildSchema = self._getChildSchema))
 
93
 
 
94
        if name is not None:
 
95
          break
 
96
 
 
97
    finally:
 
98
      cursor.close ()
 
99
 
 
100
 
 
101
    return len (result) and result or None
 
102
 
 
103
 
 
104
  # ---------------------------------------------------------------------------
 
105
  # Get all fields of a table
 
106
  # ---------------------------------------------------------------------------
 
107
 
 
108
  def _getChildSchema (self, parent):
 
109
    """
 
110
    This function returns a list of all child elements for a given table.
 
111
 
 
112
    @param parent: schema object instance whose child elements should be
 
113
        fetched
 
114
    @return: sequence of schema instances
 
115
    """
 
116
 
 
117
    result = []
 
118
 
 
119
    cmd = u"SHOW COLUMNS FROM %s" % parent.id
 
120
    
 
121
    cursor = self._connection.makecursor (cmd)
 
122
 
 
123
    try:
 
124
      for rs in cursor.fetchall ():
 
125
        nativetype = string.split (string.replace (rs [1], ')', ''), '(')
 
126
 
 
127
        attrs = {'id'        : "%s.%s" % (parent.id, rs [0]),
 
128
                 'name'      : rs [0],
 
129
                 'type'      : 'field',
 
130
                 'nativetype': nativetype [0],
 
131
                 'required'  : rs [2] != 'YES',
 
132
                 'datatype'  : 'text'}
 
133
 
 
134
        for (group, natives) in self._TYPES.items ():
 
135
          if nativetype [0] in natives:
 
136
            attrs ['datatype'] = group
 
137
            break
 
138
 
 
139
        if len (nativetype) == 2:
 
140
          parts = []
 
141
          for item in nativetype [1].split (','):
 
142
            parts.extend (item.split ())
 
143
 
 
144
          if parts [0].strip ().isdigit ():
 
145
            attrs ['length'] = int (parts [0].strip ())
 
146
 
 
147
          if len (parts) > 1 and parts [1].strip ().isdigit ():
 
148
            attrs ['precision'] = int (parts [1].strip ())
 
149
 
 
150
        if rs [4] not in ('NULL', '0000-00-00 00:00:00', '', None):
 
151
          attrs ['defaulttype'] = 'constant'
 
152
          attrs ['defaultval']  = rs [4]
 
153
 
 
154
        if rs [5] == 'auto_increment':
 
155
          attrs ['defaulttype'] = 'serial'
 
156
 
 
157
        result.append (GIntrospection.Schema (attrs))
 
158
 
 
159
    finally:
 
160
      cursor.close ()
 
161
 
 
162
    return result
 
163
 
 
164
 
 
165
  # ---------------------------------------------------------------------------
 
166
  # Get a dictionary of all indices available for a given table
 
167
  # ---------------------------------------------------------------------------
 
168
 
 
169
  def __getIndices (self, table):
 
170
    """
 
171
    This function creates a dictionary with all indices of a given relation
 
172
    where the keys are the indexnames and the values are dictionaries
 
173
    describing the indices. Such a dictionary has the keys 'unique', 'primary'
 
174
    and 'fields', where 'unique' specifies whether the index is unique or not
 
175
    and 'primary' specifies wether the index is the primary key or not.
 
176
    'fields' holds a sequence with all field names building the index.
 
177
 
 
178
    @param table: name of the table to fetch indices for
 
179
    @return: dictionary with indices or None if no indices were found
 
180
    """
 
181
 
 
182
    result = {}
 
183
 
 
184
    cmd = u"SHOW INDEX FROM %s" % table
 
185
 
 
186
    cursor = self._connection.makecursor (cmd)
 
187
 
 
188
    try:
 
189
      for rs in cursor.fetchall ():
 
190
        ixName = rs [2]
 
191
        if not result.has_key (ixName):
 
192
          result [ixName] = {'unique': not rs [1],
 
193
                             'primary': ixName == 'PRIMARY',
 
194
                             'fields': []}
 
195
        result [ixName] ['fields'].append ((rs [3], rs [4]))
 
196
 
 
197
 
 
198
      # Sort the field lists according to their sequence number and remove the
 
199
      # sequences number from the list
 
200
      for index in result.values ():
 
201
        fields = index ['fields']
 
202
        fields.sort ()
 
203
        index ['fields'] = [field [1] for field in fields]
 
204
 
 
205
    finally:
 
206
      cursor.close ()
 
207
 
 
208
    return len (result.keys ()) and result or None