Sorry, its so similar that I overlooked. lol. Cool! On Monday, June 20, 2016 at 11:34:28 AM UTC-4, Kyle Flanagan wrote: > > Ron, > > This is for Microsoft SQL Server databases. To extract models from MySQL > use the extract_mysql_models.py script from the scripts folder: > https://github.com/web2py/web2py/blob/master/scripts/extract_mysql_models.py > > > On Saturday, June 18, 2016 at 12:53:07 PM UTC-5, Ron Chatterjee wrote: >> >> Little clarification: >> >> name of the dbase: "nameofmydb". Port is 80. username is root and no >> password. What would the equivalent call to this routine? I did this but >> didn't get any results: >> >> python extract_mysql_models.py nameofmydb localhost 80 root > db_model.py >> >> Am I missing anything? But I do the following in python and it works >> fine. >> >> >> import MySQLdb >> import sys >> import os >> >> try: >> db = MySQLdb.connect(host = 'localhost',user ='root',passwd = '',db = >> 'nameofmydb') >> except Exception as e: >> sys.exit('we cant get into the db'); >> >> cursor = db.cursor() >> #Lets put some values into the db >> cursor.execute('INSERT INTO catagory(name,id,text) VALUES("Peggy", "2", >> "Missing Tom here")') >> >> #lets fetch and output >> cursor.execute('SELECT *FROM catagory') >> results = cursor.fetchall() >> print results >> >> >> >>>(('Peggy', 2L, 'Missing Tom here')) >> >> >> >> I do get a db_model.py but its says the following: >> >> USAGE: extract_mssql_models db host port user passwd >> Call with SQL Server database connection parameters, >> web2py model will be printed on standard output. >> EXAMPLE: python extract_mssql_models.py mydb localhost 3306 kflanaga pass >> or >> python extract_mssql_models.py mydb localhost 3306 kflanaga pass > >> db_model.py >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> On Saturday, June 18, 2016 at 9:12:17 AM UTC-4, Massimo Di Pierro wrote: >>> >>> Nice. In trunk! >>> >>> On Thursday, 16 June 2016 16:54:20 UTC-5, Kyle Flanagan wrote: >>>> >>>> I needed the ability to extract a DAL model from SQL Server. I based >>>> the script below on extract_pgsql_models by Mariano Reingart, based in >>>> turn >>>> on a script to "generate schemas from dbs" (mysql) by Alexandre Andrade. >>>> I'm posting it here in hopes that it will be useful for others. >>>> >>>> Tested on Windows 7 on a SQL Server 2012 database. Make sure to replace >>>> "mssql4://..." with the appropriate connection string if using a legacy >>>> SQL >>>> Server database. You might also need to modify the pyodbc.connect >>>> connection string driver to match a driver on your local PC. >>>> >>>> """Create web2py model (python code) to represent MS SQL Server tables. >>>> Features: >>>> * Uses ANSI Standard INFORMATION_SCHEMA (might work with other RDBMS) >>>> * Detects legacy "keyed" tables (not having an "id" PK) >>>> * Handles 'funny' column names. web2py requires all column names be valid >>>> python identifiers. This script uses rname >>>> * for column names that have spaces or are otherwise invalid python >>>> identifiers. >>>> * Connects directly to running databases, no need to do a SQL dump >>>> * Handles notnull, unique and referential constraints >>>> * Detects most common datatypes and default values >>>> * Supports running from the command line as well as from an IDE's debug >>>> menu. See the COMMAND_LINE_MODE constant below >>>> * for more info. >>>> >>>> Requirements: >>>> * Needs pyodbc python connector >>>> >>>> Created by Kyle Flanagan. Based on a script by Mariano Reingart which was >>>> based on a script to "generate schemas from dbs" (mysql) by Alexandre >>>> Andrade >>>> """ >>>> >>>> _author__ = "Kyle Flanagan <[email protected]>" >>>> >>>> HELP = """ >>>> USAGE: extract_mssql_models db host port user passwd >>>> Call with SQL Server database connection parameters, >>>> web2py model will be printed on standard output. >>>> EXAMPLE: python extract_mssql_models.py mydb localhost 3306 kflanaga pass >>>> or >>>> python extract_mssql_models.py mydb localhost 3306 kflanaga pass > >>>> db_model.py >>>> """ >>>> >>>> # Config options >>>> DEBUG = False # print debug messages to STDERR >>>> SCHEMA = 'dbo' >>>> COMMAND_LINE_MODE = True # running from command prompt. Disable to >>>> specify variables and use in IDE >>>> DB = None >>>> HOST = None >>>> USER = None >>>> PASSWD = None >>>> PORT = None >>>> >>>> # Constant for Field keyword parameter order (and filter): >>>> KWARGS = ('type', 'length', 'default', 'required', 'ondelete', >>>> 'notnull', 'unique', 'label', 'comment', 'rname') >>>> >>>> import sys >>>> import re >>>> # This is from pydal/helpers/regex.py as of 2016-06-16 >>>> # Use this to recognize if a field name need to have an rname >>>> representation >>>> REGEX_VALID_TB_FLD = re.compile(r'^[^\d_][_0-9a-zA-Z]*\Z') >>>> # For replacing invalid characters in field names >>>> INVALID_CHARS = re.compile(r'[^a-zA-Z0-9_]') >>>> >>>> >>>> def get_valid_column_name(field): >>>> """Return a valid column name that follows Python's rules for >>>> identifiers, which is what web2py requires for column >>>> names. Replaces invalid characters with underscores and leading digits >>>> with their associated English word.""" >>>> if not REGEX_VALID_TB_FLD.match(field): >>>> # If the first character is a digit, replace it with its word >>>> counterpart >>>> if re.match(r'^[0-9]', field): >>>> numbers = ['Zero', 'One', 'Two', 'Three', 'Four', >>>> 'Five', 'Six', 'Seven', 'Eight', 'Nine'] >>>> field = numbers[int(field[0])] + field[1:] >>>> >>>> field = INVALID_CHARS.sub('_', field) >>>> return field >>>> >>>> >>>> def query(conn, sql, *args): >>>> "Execute a SQL query and return rows as a list of dicts" >>>> cur = conn.cursor() >>>> ret = [] >>>> try: >>>> if DEBUG: print >> sys.stderr, "QUERY: ", sql % args >>>> cur.execute(sql % args) >>>> for row in cur: >>>> dic = {} >>>> for i, value in enumerate(row): >>>> field = cur.description[i][0] >>>> dic[field] = value >>>> if DEBUG: print >> sys.stderr, "RET: ", dic >>>> ret.append(dic) >>>> return ret >>>> finally: >>>> cur.close() >>>> >>>> >>>> def get_tables(conn, schema=SCHEMA): >>>> "List table names in a given schema" >>>> rows = query(conn, """SELECT table_name FROM information_schema.tables >>>> WHERE table_schema = '%s' >>>> ORDER BY table_name""", schema) >>>> return [row['table_name'] for row in rows] >>>> >>>> >>>> def get_fields(conn, table): >>>> "Retrieve field list for a given table" >>>> if DEBUG: print >> sys.stderr, "Processing TABLE", table >>>> rows = query(conn, """ >>>> SELECT column_name, data_type, >>>> is_nullable, >>>> character_maximum_length, >>>> numeric_precision, numeric_precision_radix, numeric_scale, >>>> column_default >>>> FROM information_schema.columns >>>> WHERE table_name='%s' >>>> ORDER BY ordinal_position""", table) >>>> return rows >>>> >>>> >>>> def define_field(conn, table, field, pks): >>>> "Determine field type, default value, references, etc." >>>> f = {} >>>> ref = references(conn, table, field['column_name']) >>>> if ref: >>>> f.update(ref) >>>> elif field['column_default'] and \ >>>> field['column_default'].startswith("nextval") and \ >>>> field['column_name'] in pks: >>>> f['type'] = "'id'" >>>> elif field['data_type'].startswith('character'): >>>> f['type'] = "'string'" >>>> if field['character_maximum_length']: >>>> f['length'] = field['character_maximum_length'] >>>> elif field['data_type'] in ('text', 'ntext'): >>>> f['type'] = "'text'" >>>> elif field['data_type'] in ('boolean', 'bit'): >>>> f['type'] = "'boolean'" >>>> elif field['data_type'] in ('tinyint', 'smallint', 'bigint', 'int'): >>>> f['type'] = "'integer'" >>>> elif field['data_type'] in ('real', 'float'): >>>> f['type'] = "'double'" >>>> elif field['data_type'] in ('datetime', 'datetime2', 'smalldatetime'): >>>> f['type'] = "'datetime'" >>>> elif field['data_type'] in ('timestamp',): >>>> f['type'] = "'datetime'" >>>> f['default'] = "request.now" >>>> f['update'] = "request.now" >>>> elif field['data_type'] in ('date',): >>>> f['type'] = "'date'" >>>> elif field['data_type'] in ('time',): >>>> f['type'] = "'time'" >>>> elif field['data_type'] in ('numeric', 'money', 'smallmoney', >>>> 'decimal'): >>>> f['type'] = "'decimal'" >>>> f['precision'] = field['numeric_precision'] >>>> f['scale'] = field['numeric_scale'] or 0 >>>> elif field['data_type'] in ('binary', 'varbinary', 'image'): >>>> f['type'] = "'blob'" >>>> elif field['data_type'] in ('point', 'lseg', 'polygon', 'unknown', >>>> 'USER-DEFINED', 'sql_variant'): >>>> f['type'] = "" # unsupported? >>>> elif field['data_type'] in ('varchar', 'char', 'nchar', 'nvarchar', >>>> 'uniqueidentifer'): >>>> f['type'] = "'string'" >>>> else: >>>> raise RuntimeError("Data Type not supported: %s " % str(field)) >>>> >>>> try: >>>> if field['column_default']: >>>> if field['column_default'] == "now()": >>>> d = "request.now" >>>> elif field['column_default'] == "true": >>>> d = "True" >>>> elif field['column_default'] == "false": >>>> d = "False" >>>> else: >>>> d = repr(eval(field['column_default'])) >>>> f['default'] = str(d) >>>> except (ValueError, SyntaxError): >>>> pass >>>> except Exception, e: >>>> raise RuntimeError("Default unsupported '%s'" % >>>> field['column_default']) >>>> >>>> if not field['is_nullable']: >>>> f['notnull'] = "True" >>>> >>>> # For field names that are not valid python identifiers, we need to >>>> add a reference to their actual name >>>> # in the back end database >>>> if not REGEX_VALID_TB_FLD.match(field['column_name']): >>>> f['rname'] = "'[%s]'" % field['column_name'] >>>> >>>> return f >>>> >>>> >>>> def is_unique(conn, table, field): >>>> "Find unique columns (incomplete support)" >>>> rows = query(conn, """ >>>> SELECT c.column_name >>>> FROM information_schema.table_constraints t >>>> INNER JOIN information_schema.constraint_column_usage c >>>> ON (t.CONSTRAINT_CATALOG = c.CONSTRAINT_CATALOG >>>> AND t.CONSTRAINT_NAME = c.CONSTRAINT_NAME >>>> AND t.CONSTRAINT_SCHEMA = c.CONSTRAINT_SCHEMA >>>> AND t.TABLE_CATALOG = c.TABLE_CATALOG >>>> AND t.TABLE_NAME = c.TABLE_NAME >>>> AND t.TABLE_SCHEMA = c.TABLE_SCHEMA) >>>> WHERE t.table_name='%s' >>>> AND c.column_name='%s' >>>> AND t.constraint_type='UNIQUE' >>>> ;""", table, field['column_name']) >>>> return rows and True or False >>>> >>>> >>>> def primarykeys(conn, table): >>>> "Find primary keys" >>>> rows = query(conn, """ >>>> SELECT c.column_name >>>> FROM information_schema.table_constraints t >>>> INNER JOIN information_schema.constraint_column_usage c >>>> ON (t.CONSTRAINT_CATALOG = c.CONSTRAINT_CATALOG >>>> AND t.CONSTRAINT_NAME = c.CONSTRAINT_NAME >>>> AND t.CONSTRAINT_SCHEMA = c.CONSTRAINT_SCHEMA >>>> AND t.TABLE_CATALOG = c.TABLE_CATALOG >>>> AND t.TABLE_NAME = c.TABLE_NAME >>>> AND t.TABLE_SCHEMA = c.TABLE_SCHEMA) >>>> WHERE t.table_name='%s' >>>> AND t.constraint_type='PRIMARY KEY' >>>> ;""", table) >>>> return [row['column_name'] for row in rows] >>>> >>>> >>>> def references(conn, table, field): >>>> "Find a FK (fails if multiple)" >>>> rows1 = query(conn, """ >>>> SELECT k.table_name, k.column_name, k.constraint_name, >>>> r.update_rule, r.delete_rule, k.ordinal_position >>>> FROM information_schema.key_column_usage k >>>> INNER JOIN information_schema.referential_constraints r >>>> ON (k.CONSTRAINT_CATALOG = r.CONSTRAINT_CATALOG >>>> AND k.CONSTRAINT_NAME = r.CONSTRAINT_NAME >>>> AND k.CONSTRAINT_SCHEMA = r.CONSTRAINT_SCHEMA) >>>> INNER JOIN information_schema.table_constraints t >>>> ON (r.CONSTRAINT_CATALOG = t.CONSTRAINT_CATALOG >>>> AND r.CONSTRAINT_NAME = t.CONSTRAINT_NAME >>>> AND r.CONSTRAINT_SCHEMA = t.CONSTRAINT_SCHEMA) >>>> >>>> WHERE k.table_name='%s' >>>> AND k.column_name='%s' >>>> AND t.constraint_type='FOREIGN KEY' >>>> ;""", table, field) >>>> if len(rows1) == 1: >>>> rows2 = query(conn, """ >>>> SELECT table_name, column_name, * >>>> FROM information_schema.constraint_column_usage >>>> WHERE constraint_name='%s' >>>> """, rows1[0]['constraint_name']) >>>> row = None >>>> if len(rows2) > 1: >>>> row = rows2[int(rows1[0]['ordinal_position']) - 1] >>>> keyed = True >>>> if len(rows2) == 1: >>>> row = rows2[0] >>>> keyed = False >>>> if row: >>>> if keyed: # THIS IS BAD, DON'T MIX "id" and primarykey!!! >>>> ref = {'type': "'reference %s.%s'" % (row['table_name'], >>>> row['column_name'])} >>>> else: >>>> ref = {'type': "'reference %s'" % (row['table_name'],)} >>>> if rows1[0]['delete_rule'] != "NO ACTION": >>>> ref['ondelete'] = repr(rows1[0]['delete_rule']) >>>> return ref >>>> elif rows2: >>>> raise RuntimeError("Unsupported foreign key reference: %s" % >>>> str(rows2)) >>>> >>>> elif rows1: >>>> raise RuntimeError("Unsupported referential constraint: %s" % >>>> str(rows1)) >>>> >>>> >>>> def define_table(conn, table): >>>> "Output single table definition" >>>> fields = get_fields(conn, table) >>>> pks = primarykeys(conn, table) >>>> print "db.define_table('%s'," % (table,) >>>> for field in fields: >>>> fname = field['column_name'] >>>> fdef = define_field(conn, table, field, pks) >>>> if fname not in pks and is_unique(conn, table, field): >>>> fdef['unique'] = "True" >>>> if fdef['type'] == "'id'" and fname in pks: >>>> pks.pop(pks.index(fname)) >>>> print " Field('%s', %s)," % (get_valid_column_name(fname), >>>> ', '.join(["%s=%s" % (k, fdef[k]) >>>> for k in KWARGS >>>> if k in fdef and >>>> fdef[k]])) >>>> if pks: >>>> print " primarykey=[%s]," % ", ".join(["'%s'" % pk for pk in >>>> pks]) >>>> print " migrate=migrate)" >>>> print >>>> >>>> >>>> def define_db(conn, db, host, port, user, passwd): >>>> "Output database definition (model)" >>>> dal = 'db = DAL("mssql4://%s:%s@%s:%s/%s", pool_size=10, >>>> decode_credentials=True)' >>>> print dal % ( >>>> user.replace('@', '%40').replace(':', '%3A'), passwd.replace('@', >>>> '%40').replace(':', '%3A'), host, port, db) >>>> print >>>> print "migrate = False" >>>> print >>>> for table in get_tables(conn): >>>> define_table(conn, table) >>>> >>>> >>>> if __name__ == "__main__": >>>> # Parse arguments from command line: >>>> if len(sys.argv) < 6 and COMMAND_LINE_MODE: >>>> print HELP >>>> else: >>>> # Parse arguments from command line: >>>> if COMMAND_LINE_MODE: >>>> db, host, port, user, passwd = sys.argv[1:6] >>>> else: >>>> db = DB >>>> host = HOST >>>> user = USER >>>> passwd = PASSWD >>>> port = PORT >>>> >>>> # Make the database connection (change driver if required) >>>> import pyodbc >>>> # cnn = pyodbc.connect(database=db, host=host, port=port, >>>> # user=user, password=passwd, >>>> # ) >>>> cnn = pyodbc.connect( >>>> r'DRIVER={{SQL Server Native Client >>>> 11.0}};SERVER={server};PORT={port};DATABASE={db};UID={user};PWD={passwd}'.format( >>>> server=host, port=port, db=db, user=user, passwd=passwd) >>>> ) >>>> # Start model code generation: >>>> define_db(cnn, db, host, port, user, passwd) >>>> >>>>
-- Resources: - http://web2py.com - http://web2py.com/book (Documentation) - http://github.com/web2py/web2py (Source code) - https://code.google.com/p/web2py/issues/list (Report Issues) --- You received this message because you are subscribed to the Google Groups "web2py-users" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected]. For more options, visit https://groups.google.com/d/optout.

