Update of /cvsroot/webware/Webware/MiddleKit/Design
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv18752/Design
Modified Files:
Generate.py MSSQLSQLGenerator.py MySQLSQLGenerator.py
PythonGenerator.py SQLGenerator.py
Log Message:
- enable enums to be put in separate tables. this is for same database
servers that don't have an enum type.
- enable test models to have more than one Settings*.config file
Index: Generate.py
===================================================================
RCS file: /cvsroot/webware/Webware/MiddleKit/Design/Generate.py,v
retrieving revision 1.11
retrieving revision 1.12
diff -C2 -d -r1.11 -r1.12
*** Generate.py 5 Jan 2004 22:50:18 -0000 1.11
--- Generate.py 16 Feb 2004 22:14:52 -0000 1.12
***************
*** 22,26 ****
def databases(self):
! return ['MSSQL', 'MySQL', 'PostgreSQL' ] # @@ 2000-10-19 ce: should build this dynamically
def main(self, args=sys.argv):
--- 22,26 ----
def databases(self):
! return ['MSSQL', 'MySQL', 'PostgreSQL'] # @@ 2000-10-19 ce: should build this dynamically
def main(self, args=sys.argv):
***************
*** 40,43 ****
--- 40,44 ----
pyClass=opt['db']+'SQLGenerator',
model=opt['model'],
+ configFilename=opt.get('config'),
outdir=os.path.join(outdir, 'GeneratedSQL'))
if opt.has_key('py'):
***************
*** 46,49 ****
--- 47,51 ----
pyClass=opt['db']+'PythonGenerator',
model=opt['model'],
+ configFilename=opt.get('config'),
outdir=outdir)
***************
*** 52,56 ****
if errorMsg:
print '%s: error: %s' % (progName, errorMsg)
! print 'Usage: %s --db DBNAME --model FILENAME [--sql] [--py] [--outdir DIRNAME]' % progName
print ' %s -h | --help' % progName
print
--- 54,58 ----
if errorMsg:
print '%s: error: %s' % (progName, errorMsg)
! print 'Usage: %s --db DBNAME --model FILENAME [--sql] [--py] [--config FILENAME] [--outdir DIRNAME]' % progName
print ' %s -h | --help' % progName
print
***************
*** 58,61 ****
--- 60,65 ----
print ' * If neither --sql nor --py are specified, both are generated.'
print ' * If --outdir is not specified, then the base filename (sans extension) is used.'
+ print ' * --config lets you specify a different config filename inside the model.'
+ print ' This is mostly useful for the regression test suite.'
print
sys.exit(1)
***************
*** 65,69 ****
if type(args)==type(''):
args = args.split()
! optPairs, files = getopt(args[1:], 'h', ['help', 'db=', 'model=', 'sql', 'py', 'outdir='])
if len(optPairs)<1:
self.usage('Missing options.')
--- 69,73 ----
if type(args)==type(''):
args = args.split()
! optPairs, files = getopt(args[1:], 'h', ['help', 'db=', 'model=', 'sql', 'py', 'config=', 'outdir='])
if len(optPairs)<1:
self.usage('Missing options.')
***************
*** 95,99 ****
return opt
! def generate(self, pyClass, model, outdir):
""" Generates code using the given class, model and output directory. The pyClass may be a string, in which case a module of the same name is imported and the class extracted from that. The model may be a string, in which case it is considered a filename of a model. """
if isinstance(pyClass, StringTypes):
--- 99,103 ----
return opt
! def generate(self, pyClass, model, configFilename, outdir):
""" Generates code using the given class, model and output directory. The pyClass may be a string, in which case a module of the same name is imported and the class extracted from that. The model may be a string, in which case it is considered a filename of a model. """
if isinstance(pyClass, StringTypes):
***************
*** 102,106 ****
generator = pyClass()
if isinstance(model, StringTypes):
! generator.readModelFileNamed(model, havePythonClasses=0)
else:
generator.setModel(model)
--- 106,110 ----
generator = pyClass()
if isinstance(model, StringTypes):
! generator.readModelFileNamed(model, configFilename=configFilename, havePythonClasses=0)
else:
generator.setModel(model)
Index: MSSQLSQLGenerator.py
===================================================================
RCS file: /cvsroot/webware/Webware/MiddleKit/Design/MSSQLSQLGenerator.py,v
retrieving revision 1.14
retrieving revision 1.15
diff -C2 -d -r1.14 -r1.15
*** MSSQLSQLGenerator.py 18 Dec 2003 06:17:02 -0000 1.14
--- MSSQLSQLGenerator.py 16 Feb 2004 22:14:52 -0000 1.15
***************
*** 265,279 ****
- class EnumAttr:
-
- def sqlType(self):
- maxLen = max([len(e) for e in self.enums()])
- return 'varchar(%s)' % maxLen
-
- def sampleValue(self, value):
- assert value in self._enums, 'value = %r, enums = %r' % (value, self._enums)
- return repr(value)
-
-
class ObjRefAttr:
--- 265,268 ----
Index: MySQLSQLGenerator.py
===================================================================
RCS file: /cvsroot/webware/Webware/MiddleKit/Design/MySQLSQLGenerator.py,v
retrieving revision 1.10
retrieving revision 1.11
diff -C2 -d -r1.10 -r1.11
*** MySQLSQLGenerator.py 7 Mar 2003 17:38:36 -0000 1.10
--- MySQLSQLGenerator.py 16 Feb 2004 22:14:52 -0000 1.11
***************
*** 44,48 ****
class EnumAttr:
! def sqlType(self):
enums = ['"%s"' % enum for enum in self.enums()]
enums = ', '.join(enums)
--- 44,48 ----
class EnumAttr:
! def nativeEnumSQLType(self):
enums = ['"%s"' % enum for enum in self.enums()]
enums = ', '.join(enums)
***************
*** 50,57 ****
return enums
- def sampleValue(self, value):
- assert value in self._enums, 'value = %r, enums = %r' % (value, self._enums)
- return repr(value)
-
class StringAttr:
--- 50,53 ----
Index: PythonGenerator.py
===================================================================
RCS file: /cvsroot/webware/Webware/MiddleKit/Design/PythonGenerator.py,v
retrieving revision 1.28
retrieving revision 1.29
diff -C2 -d -r1.28 -r1.29
*** PythonGenerator.py 19 Dec 2003 05:26:55 -0000 1.28
--- PythonGenerator.py 16 Feb 2004 22:14:52 -0000 1.29
***************
*** 361,369 ****
def stringToValue(self, string):
! return string
def writePySetChecks(self, out):
Attr.writePySetChecks.im_func(self, out)
out.write('''\
if value is not None:
if not isinstance(value, types.StringType):
--- 361,391 ----
def stringToValue(self, string):
! if self.setting('ExternalEnumsTableName', None):
! return self.intValueForString(string)
! else:
! return string
def writePySetChecks(self, out):
Attr.writePySetChecks.im_func(self, out)
out.write('''\
+ global _%(name)sAttr
+ if _%(name)sAttr is None:
+ _%(name)sAttr = self.klass().lookupAttr('%(name)s')
+ ''' % {'name': self.name()})
+ if self.setting('ExternalEnumsTableName', None):
+ out.write('''
+ if value is not None:
+ if isinstance(value, types.StringType):
+ try:
+ value = _%(name)sAttr.intValueForString(value)
+ except KeyError:
+ raise ValueError, 'expecting one of %%r, but got %%r instead' %% (_%(name)sAttr.enums(), value)
+ elif not isinstance(value, (types.IntType, types.LongType)):
+ raise TypeError, 'expecting int type for enum, but got value %%r of type %%r instead' %% (value, type(value))
+ if not _%(name)sAttr.hasEnum(value):
+ raise ValueError, 'expecting one of %%r, but got %%r instead' %% (_%(name)sAttr.enums(), value)
+ ''' % {'name': self.name()})
+ else:
+ out.write('''
if value is not None:
if not isinstance(value, types.StringType):
***************
*** 373,377 ****
raise ValueError, 'expecting one of %%r, but got %%r instead' %% (attr.enums(), value)
''' % self.name())
! # @@ 2001-07-11 ce: could optimize above code
--- 395,416 ----
raise ValueError, 'expecting one of %%r, but got %%r instead' %% (attr.enums(), value)
''' % self.name())
! # @@ 2001-07-11 ce: could optimize above code
!
! def writePySetAssignment(self, write, name):
! write('''
! # set the attribute
! origValue = self._%(name)s
! self._%(name)s = value
!
! # MiddleKit machinery
! self._mk_changed = 1 # @@ original semantics, but I think this should be under "if not self._mk_initing..."
! if not self._mk_initing and self._mk_serialNum>0 and value is not origValue:
! # Record that it has been changed
! if self._mk_changedAttrs is None:
! self._mk_changedAttrs = {} # maps name to attribute
! self._mk_changedAttrs['%(name)s'] = _%(name)sAttr # changedAttrs is a set
! # Tell ObjectStore it happened
! self._mk_store.objectChanged(self)
! ''' % {'name': name})
Index: SQLGenerator.py
===================================================================
RCS file: /cvsroot/webware/Webware/MiddleKit/Design/SQLGenerator.py,v
retrieving revision 1.37
retrieving revision 1.38
diff -C2 -d -r1.37 -r1.38
*** SQLGenerator.py 5 Jan 2004 23:58:23 -0000 1.37
--- SQLGenerator.py 16 Feb 2004 22:14:52 -0000 1.38
***************
*** 62,66 ****
'PreSQL': '',
'PostSQL': '',
! 'DropStatements': 'database' # database, tables
})
return config
--- 62,68 ----
'PreSQL': '',
'PostSQL': '',
! 'DropStatements': 'database', # database, tables
! 'ExternalEnumsTableName': None, # '%(ClassName)s%(AttrName)sEnum'
! 'ExternalEnumsColumnName': 'name', # could use %(ClassName)s and %(AttrName)s
})
return config
***************
*** 384,413 ****
def writeCreateSQL(self, generator, out):
if not self.isAbstract():
! name = self.name()
! wr = out.write
! sqlIdName = self.sqlIdName()
! wr('create table %s (\n' % self.sqlTableName())
! wr(self.primaryKeySQLDef(generator))
! if generator.model().setting('DeleteBehavior', 'delete') == 'mark':
! wr(self.deletedSQLDef(generator))
! first = 1
! sqlAttrs = []
! nonSQLAttrs = []
! for attr in self.allAttrs():
! if attr.hasSQLColumn():
! sqlAttrs.append(attr)
! else:
! nonSQLAttrs.append(attr)
! for attr in sqlAttrs:
! if first:
! first = 0
! else:
! wr(',\n')
! attr.writeCreateSQL(generator, out)
! self.writeIndexSQLDefs(wr)
! for attr in nonSQLAttrs:
! attr.writeCreateSQL(generator, out)
! wr('\n')
! wr(');\n\n\n')
def primaryKeySQLDef(self, generator):
--- 386,420 ----
def writeCreateSQL(self, generator, out):
if not self.isAbstract():
! for attr in self.attrs():
! attr.writeAuxiliaryCreateTable(generator, out)
! self.writeCreateTable(generator, out)
!
! def writeCreateTable(self, generator, out):
! name = self.name()
! wr = out.write
! sqlIdName = self.sqlIdName()
! wr('create table %s (\n' % self.sqlTableName())
! wr(self.primaryKeySQLDef(generator))
! if generator.model().setting('DeleteBehavior', 'delete') == 'mark':
! wr(self.deletedSQLDef(generator))
! first = 1
! sqlAttrs = []
! nonSQLAttrs = []
! for attr in self.allAttrs():
! if attr.hasSQLColumn():
! sqlAttrs.append(attr)
! else:
! nonSQLAttrs.append(attr)
! for attr in sqlAttrs:
! if first:
! first = 0
! else:
! wr(',\n')
! attr.writeCreateSQL(generator, out)
! self.writeIndexSQLDefs(wr)
! for attr in nonSQLAttrs:
! attr.writeCreateSQL(generator, out)
! wr('\n')
! wr(');\n\n\n')
def primaryKeySQLDef(self, generator):
***************
*** 497,500 ****
--- 504,511 ----
raise
+ def writeAuxiliaryCreateTable(self, generator, out):
+ # most attribute types have no such beast
+ pass
+
def sqlNullSpec(self):
return ''
***************
*** 677,680 ****
--- 688,737 ----
+ class EnumAttr:
+
+ def sqlType(self):
+ if self.setting('ExternalEnumsTableName', None):
+ tableName, columnName = self.externalEnumsTableAndColumnName()
+ return 'int references %s(%sId)' % (tableName, tableName)
+ else:
+ return self.nativeEnumSQLType()
+
+ def nativeEnumSQLType(self):
+ maxLen = max([len(e) for e in self.enums()])
+ return 'varchar(%s)' % maxLen
+
+ def sampleValue(self, value):
+ if self.setting('ExternalEnumsTableName', None):
+ return self.intValueForString(value)
+ else:
+ assert value in self._enums, 'value = %r, enums = %r' % (value, self._enums)
+ return repr(value)
+
+ def externalEnumsTableAndColumnName(self):
+ values = {
+ 'ClassName': self.klass().name(),
+ 'AttrName': self.name()[0].upper() + self.name()[1:],
+ 'attrName': self.name(),
+ }
+ tableName = self.setting('ExternalEnumsTableName') % values # typical setting value is '%(ClassName)s%(AttrName)sEnum'. can use also use %(attrName)s for non-capped attr name
+ columnName = self.setting('ExternalEnumsColumnName') % values # typical setting value is simply 'name'
+ return tableName, columnName
+
+ def writeAuxiliaryCreateTable(self, generator, out):
+ if self.setting('ExternalEnumsTableName', None):
+ tableName, columnName = self.externalEnumsTableAndColumnName()
+ out.write('create table %s (\n' % tableName)
+ out.write('\t%sId int not null primary key,\n' % tableName)
+ out.write('\t%s varchar(255)\n' % columnName)
+ out.write(');\n')
+
+ i = 0
+ sep = ''
+ for enum in self.enums():
+ out.write("insert into %(tableName)s (%(tableName)sId, %(columnName)s) values (%(i)i, '%(enum)s');\n" % locals())
+ i += 1
+ out.write('\n')
+
+
class PrimaryKey:
"""
|