Skip to content

Instantly share code, notes, and snippets.

@aanari
Created March 21, 2012 14:38
Show Gist options
  • Save aanari/2147574 to your computer and use it in GitHub Desktop.
Save aanari/2147574 to your computer and use it in GitHub Desktop.
Informix Schema to Fluent nHibernate
import os, re, string
from collections import defaultdict
types = {'char': 'string',
'nchar': 'string',
'varchar': 'string',
'lvchar': 'string',
'text': 'string',
'clob': 'string',
'bigint': 'long',
'int8': 'long',
'int': 'int',
'integer': 'int',
'smallint': 'short',
'serial': 'int',
'bigserial': 'long',
'serial8': 'long',
'decimal': 'decimal',
'numeric': 'decimal',
'float': 'double',
'real': 'float',
'smallfloat': 'float',
'double precision': 'double',
'date': 'DateTime',
'datetime': 'DateTime',
'boolean': 'bool',
'money': 'decimal'
}
reserved = ['abstract', 'event', 'new', 'struct', 'as', 'explicit', 'null',
'switch', 'base', 'extern', 'object', 'this', 'bool', 'false',
'operator', 'throw', 'break', 'finally', 'out', 'true', 'byte',
'fixed', 'override', 'try', 'case', 'float', 'params', 'typeof',
'catch', 'for', 'private', 'uint', 'char', 'foreach', 'protected',
'ulong', 'checked', 'goto', 'public', 'unchecked', 'class', 'if',
'readonly', 'unsafe', 'const', 'implicit', 'ref', 'ushort',
'continue', 'in', 'return', 'using', 'decimal', 'int', 'sbyte',
'virtual', 'default', 'interface', 'sealed', 'volatile', 'delegate',
'internal', 'short', 'void', 'do', 'is', 'sizeof', 'while', 'double',
'lock', 'stackalloc', 'else', 'long', 'static', 'enum', 'namespace',
'string']
index_regex = re.compile("""create\s?unique\s?index\s?\"(?:\S+)?\"\.?(?:\S+)?\s?on?\s?\"(?:\S+)\"\.(?P<table>\S+)\s*\((?P<id>\S+)\)""", re.S)
schema_regex = re.compile("""create\s?table\s?\"(?:\S+)?\"\.?(?P<table>\S+)\r?\n?\s*\((?P<fields>.*?)[^,0-9]\)""", re.S)
field_regex = re.compile("""(?P<field>\S+)\s(?P<type>""" + '|'.join(types.keys()) + """)(?:\((?P<length>\d+)\))?(?:\s(not null))?""", re.I)
_wsh = lambda n: ''.join([' ' for x in range(n)])
_titlecase = lambda s: string.capwords(s, '_').replace('_','')
def _field(cfield, className):
cfield = _titlecase(cfield)
if cfield == className:
cfield = '_' + cfield
elif cfield in reserved:
cfield = '@' + cfield
return cfield
def convert_schema(input, indices):
schema = re.search(schema_regex, input)
if not schema: return ''
tableName = schema.group("table")
className = _titlecase(tableName)
converted_schema = 'public partial class {0}\n{{\n'.format(className)
class_mappings = 'public partial class {0}Map : ClassMap<{0}>\n{{\n{1}public {0}Map()\n{1}{{\n'\
.format(className, _wsh(4))
temp_schema = ''
temp_mappings = ''
class_mappings += '{1}Table("{0}");\n'.format(tableName, _wsh(8))
if len(indices) > 1:
temp_schema = ('\n{0}public override bool Equals(object obj)\n{0}{{\n'.format(_wsh(4)) +
'{0}if (obj == null) return false;\n'.format(_wsh(8)) +
'{1}{0} t = obj as {0};\n'.format(className, _wsh(8)) +
'{0}if (t == null) return false;\n'.format(_wsh(8))
)
temp_schema += ('{0}if ('.format(_wsh(8)) + (' && '.join(_field(index, className) + ' == t.' + _field(index, className) for index in indices)) + ') return true;\n')
temp_schema += ('{0}else return false;\n'.format(_wsh(8)))
temp_schema += ('{0}}}\n'.format(_wsh(4)))
#temp_schema += ('\n{0}public partial int GetHashCode();\n'.format(_wsh(4)))
class_mappings += '{0}CompositeId()\n'.format(_wsh(8))
for field in re.findall(field_regex, schema.group("fields")):
cfield = _field(field[0], className)
converted_line = _wsh(4) + "public virtual "
if field[1] != 'char' or field[2] != '1':
converted_line += types[field[1]]
else:
converted_line += 'char'
converted_schema += (converted_line + ' ' + cfield + ' { get; set; }\n')
if len(indices) > 1 and field[0] in indices:
class_mappings += '{1}.KeyProperty(x => x.{0}, "{0}"){2}\n'.format(cfield, \
_wsh(12),\
';' if indices[-1] == field[0] else ''
)
if len(indices) == 1 and field[0] in indices:
class_mapping = '{1}Id(x => x.{0})\n'.format(cfield, _wsh(8))
class_mapping += ('{1}.GeneratedBy.{0}()\n'\
.format('Native' if field[1] == 'serial' else 'Assigned', _wsh(12)))
else:
class_mapping = '{1}Map(x => x.{0})\n'.format(cfield, _wsh(8))
class_mapping += ('{1}.Column("{0}")\n'.format(field[0], _wsh(12)))
if field[1] == 'char' and field[2] != None:
class_mapping += ('{1}.Length({0})\n'.format(field[2], _wsh(12)))
if field[3] != None and field[3] == 'not null':
class_mapping += ('{0}.Not.Nullable();\n'.format(_wsh(12)))
else:
class_mapping += ('{0}.Nullable();\n'.format(_wsh(12)))
temp_mappings += class_mapping
return (converted_schema + temp_schema + '}\n\n' + class_mappings + temp_mappings + _wsh(4) + '}\n' + '}\n\n')
def informix_schema(stream):
splitname = stream.name.split('.')
del splitname[-1]
outname = '.'.join(splitname)+'.cs'
outfile = open(outname, 'w')
outfile.write('')
outfile.close()
outfile = open(outname, 'a')
full_schema = stream.read()
idx = defaultdict(list)
indices = re.finditer(index_regex, full_schema)
tables = re.finditer(schema_regex, full_schema)
[idx[index.group('table')].extend(index.group('id').split(',')) for index in indices]
[outfile.write(convert_schema(table.group(0), idx.get(table.group('table'), []))) for table in tables]
outfile.close()
informix_schema(open('dental.sql', 'r'))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment