mdl_generate_DB_schema.py :  » Database » Modeling-Framework » Modeling-0.9 » Modeling » scripts » Python Open Source

Home
Python Open Source
1.3.1.2 Python
2.Ajax
3.Aspect Oriented
4.Blog
5.Build
6.Business Application
7.Chart Report
8.Content Management Systems
9.Cryptographic
10.Database
11.Development
12.Editor
13.Email
14.ERP
15.Game 2D 3D
16.GIS
17.GUI
18.IDE
19.Installer
20.IRC
21.Issue Tracker
22.Language Interface
23.Log
24.Math
25.Media Sound Audio
26.Mobile
27.Network
28.Parser
29.PDF
30.Project Management
31.RSS
32.Search
33.Security
34.Template Engines
35.Test
36.UML
37.USB Serial
38.Web Frameworks
39.Web Server
40.Web Services
41.Web Unit
42.Wiki
43.Windows
44.XML
Python Open Source » Database » Modeling Framework 
Modeling Framework » Modeling 0.9 » Modeling » scripts » mdl_generate_DB_schema.py
#! /usr/bin/env python
# -*- coding: iso-8859-1 -*-

#-----------------------------------------------------------------------------
# Modeling Framework: an Object-Relational Bridge for python
#
# Copyright (c) 2001-2004 Sbastien Bigaret <sbigaret@users.sourceforge.net>
# All rights reserved.
#
# This file is part of the Modeling Framework.
#
# This code is distributed under a "3-clause BSD"-style license;
# see the LICENSE file for details.
#-----------------------------------------------------------------------------

"""
  TBD docstring
"""
__version__='$Revision: 945 $'[11:-2]

from Modeling.SchemaGeneration import SchemaGeneration,\
     DropPrimaryKeySupportKey, DropForeignKeyConstraintsKey,       \
     DropPrimaryKeyConstraintsKey, DropTablesKey, DropDatabaseKey, \
     CreateDatabaseKey, CreateTablesKey, PrimaryKeyConstraintsKey, \
     ForeignKeyConstraintsKey, CreatePrimaryKeySupportKey

import getopt, sys, time

def log(msg):
  if verbose:
    sys.stderr.write(msg+'\n')
err=lambda msg: sys.stderr.write(msg+'\n')

def tracebackInfoFromStack(exc_traceback):
  """
  """
  from traceback import extract_tb,format_list
  from Modeling.utils import isListOrTuple
  tb=None
  str='%s\n%s\n'%sys.exc_info()[:2]
  try:
    tb=sys.exc_info()[-1]
    str+=reduce(lambda a,b: a+b, format_list(extract_tb(tb)))
    return str
  finally:
    del tb

def databaseSchemaWithOptions(model,
                              options={},
                              administrativeConnectionDictionary={},
                              onlyStatements=0, continue_on_errors=0,
                              endStatementWith=';',
                              createUser=0, dropUser=0):
    from traceback import format_list
    #print str(options), options.__class__, dir(options)
    from Modeling import Adaptor
    adaptor=Adaptor.adaptorWithModel(model)

    str=''

    if options.get(DropDatabaseKey) and not onlyStatements:
      log('Drop Database...');
      try:
        adaptor.dropDatabaseWithAdministrativeConnectionDictionary(administrativeConnectionDictionary, dropUser)
        time.sleep(1)
      except:
        err('Drop Database FAILED\nReason:\n')
        err(tracebackInfoFromStack(sys.exc_traceback))
        if not continue_on_errors: return
      else:
        log(' OK')
    if options.get(CreateDatabaseKey) and not onlyStatements:
      log('Creating Database...')
      try:
        adaptor.createDatabaseWithAdministrativeConnectionDictionary(administrativeConnectionDictionary, createUser)
      except:
        err('Create Database FAILED\nReason:')
        err(tracebackInfoFromStack(sys.exc_traceback))
        if not continue_on_errors: return
      else:
        log(' OK')
        
    schemaGeneration = adaptor.schemaGenerationFactory()
    sqlExprs=schemaGeneration.schemaCreationStatementsForEntities(model.entities(), options)
    if onlyStatements:
      for sqlExpr in sqlExprs:
        str+='%s%s\n'%(sqlExpr.statement(),endStatementWith)
    else:
      context=adaptor.createAdaptorContext()
      channel=context.createAdaptorChannel()
      for sqlExpr in sqlExprs:
        try:
          log(sqlExpr.statement())
          channel.evaluateExpression(sqlExpr)
        except Exception, exc:
          err('FAILED to execute: %s\nReason:'%sqlExpr.statement())
          err(tracebackInfoFromStack(sys.exc_traceback))
          if not continue_on_errors: break
        else:
          log(' OK')
      if channel.isOpen():
        channel.closeChannel()

    return str

def usage(prgName):
  _usage="""
  %s [options] command(s) model.(xml|py)
  
Generates and/or executes the SQL code from a model, either an xml file or a
PyModel.

General options
---------------
  -c --stdout         write the SQL statements on stdout, do not execute them
  -e --end-with <str> appends <str> to each statement when option -c is
                      enabled (it has no effect otherwise). Default is ';'
  -v --verbose        verbose mode
  -h --help           gives this help
  -i --ignore-errors  ignore database errors (default is halt on error)
                      
  -f --force          By default, the script stops if the model has errors.
                      Setting this flag makes the script ignores the errors:
                      use at your own risks and expect errors to happen!

Commands for DB-schema generation
---------------------------------

Most commonly used commands:

  -A --all-but-database   Drops and recreate everything except the database
                          itself. Equivalent to: -T -t -P -p -S -s -F -f

  -C --create-database    Create the database from scratch
                          Equivalent to: -d -T -P -S -F
                          
  -R --recreate-database  Drop the database and recreate it from scratch
                          Equivalent to: -D -d -T -P -S -F
                          
  Last two options require '--admin-dsn' to be set as well (see below)

Additionally, the following commands are available:

  -D  drop database   (requires --admin-dsn)
  -d  create database (requires --admin-dsn)

  -t  drop tables
  -T  create tables
  -p  drop primary key constraints
  -P  create primary key constraints
  -s  drop primary key supports
  -S  create primary key supports
  -f  drop foreign key constraints
  -F  create foreign key constraints

Note: each of the 3 commands -A -C and -R (and their corresponding long
      options) discard any other commands that appear before.
      Example: '-D -C' is equivalent to '-C', and '-C -D' is equivalent to '-R'

Connecting to the database
--------------------------

  DSNs can be specified on the command-line as well. Valid DSNs are:
       <hostname>:<database>:<user>:<password>
    or <hostname>:<port>:<database>:<user>:<password>

  --dsn         overrides the connection dictionary stored in the model

  --admin-dsn   specifies the administrative DSN. It is required when one of
                the following options are used: -C, -R, -D and/or -d
  
""" % prgName
  sys.stderr.write(_usage)


# Global variables
verbose=to_stdout=continue_on_errors=0

_defaultOptions={
  DropPrimaryKeySupportKey     : 0,
  DropForeignKeyConstraintsKey : 0,
  DropPrimaryKeyConstraintsKey : 0,
  DropTablesKey                : 0,
  DropDatabaseKey              : 0,
  CreateDatabaseKey            : 0,
  CreateTablesKey              : 0,
  PrimaryKeyConstraintsKey     : 0,
  ForeignKeyConstraintsKey     : 0,
  CreatePrimaryKeySupportKey   : 0,
  }

_all_but_database_options={
  DropPrimaryKeySupportKey     : 1,
  DropForeignKeyConstraintsKey : 1,
  DropPrimaryKeyConstraintsKey : 1,
  DropTablesKey                : 1,
  DropDatabaseKey              : 0,
  CreateDatabaseKey            : 0,
  CreateTablesKey              : 1,
  PrimaryKeyConstraintsKey     : 1,
  ForeignKeyConstraintsKey     : 1,
  CreatePrimaryKeySupportKey   : 1,
  }

_create_database_options={
  DropPrimaryKeySupportKey     : 0,
  DropForeignKeyConstraintsKey : 0,
  DropPrimaryKeyConstraintsKey : 0,
  DropTablesKey                : 0,
  DropDatabaseKey              : 0,
  CreateDatabaseKey            : 1,
  CreateTablesKey              : 1,
  PrimaryKeyConstraintsKey     : 1,
  ForeignKeyConstraintsKey     : 1,
  CreatePrimaryKeySupportKey   : 1,
  }

_recreate_database_options=_create_database_options.copy()
_recreate_database_options[DropDatabaseKey]=1

_create_options_to_key={
  '-T': CreateTablesKey, '-P': PrimaryKeyConstraintsKey,
  '-S': CreatePrimaryKeySupportKey, '-F': ForeignKeyConstraintsKey }
_drop_options_to_key={
  '-t': DropTablesKey, '-p': DropPrimaryKeyConstraintsKey,
  '-s': DropPrimaryKeySupportKey, '-f': DropForeignKeyConstraintsKey }

def main(args):
  me=args[0]
  generation_options=_defaultOptions
  try: options, args = getopt.getopt(sys.argv[1:],
                                     'ce:hivACRDdTtPpSsFf',
                                     ["stdout", "end-with=", "help", "verbose",
                                      "ignore-errors",
                                      "all-but-database", "create-database",
                                      "recreate-database", "connection-dict",
                                      "admin-dsn=", "user-dsn="])
  except: usage(me); return 1
  global verbose, to_stdout, continue_on_errors
  admin_connection_dict={}
  user_connection_dict={}
  should_have_admin_dict=0 # set for options: -A, -C, -R, -D and -d
  end_with_str=';'
  force_flag=0
  for k, v in options:
    if k in ('-h', '--help'): usage(me); return 0
    if k in ('-v', '--verbose'): verbose=1; continue
    if k in ('-c', '--stdout'): to_stdout=1; continue
    if k in ('-i', '--ignore-errors'): continue_on_errors=1; continue
    if k in ('-e', '--end-with'): end_with_str=v; continue
    if k in ('-f', '--force'): force_flag=1; continue

    if k in ('-A', '--all-but-database'):
      generation_options.update(_all_but_database_options)
      continue

    if k in ('-C', '--create-database'):
      generation_options.update(_create_database_options)
      should_have_admin_dict=k
      continue

    if k in ('-R', '--recreate-database'):
      generation_options.update(_recreate_database_options)
      should_have_admin_dict=k
      continue

    if k in _create_options_to_key.keys():
      generation_options[_create_options_to_key[k]]=1; continue

    if k in _drop_options_to_key.keys():
      generation_options[_drop_options_to_key[k]]=1; continue

    if k == '-D':
      generation_options[DropDatabaseKey]=1
      should_have_admin_dict=k
      continue

    if k == '-d':
      generation_options[CreateDatabaseKey]=1
      should_have_admin_dict=k
      continue

    if k in ('--admin-dsn',):
      try:
        v=v.split(':')
        if len(v)==4:
          admin_connection_dict={'host': v[0], 'database': v[1], 
                                 'user':v[2], 'password':v[3]}
        elif len(v)==5:
          admin_connection_dict={'host': v[0],'port':int(v[1]),
                                 'database': v[2],
                                 'user':v[3], 'password':v[4]}
        else:
          sys.stderr.write("Error: invalid admin-dsn")
          return 1
      except:
        sys.stderr.write("Invalid admin-dsn")
        return 1

    if k in ('--user-dsn',):
      try:
        v=v.split(':')
        if len(v)==4:
          user_connection_dict={'host': v[0], 'database': v[1], 
                                 'user':v[2], 'password':v[3]}
        elif len(v)==5:
          user_connection_dict={'host': v[0],'port':int(v[1]),
                                 'database': v[2],
                                 'user':v[3], 'password':v[4]}
        else:
          sys.stderr.write("Error: invalid user-dsn")
          return 1
      except:
        sys.stderr.write("Invalid user-dsn")
        return 1
      
  if should_have_admin_dict and not admin_connection_dict:
    sys.stderr.write('Error: option %s requires --admin-connection-dict'%should_have_admin_dict)
    return 1
  
  if len(args)!=1: usage(me) ; return 1

  import operator
  if not reduce(operator.add, generation_options.values()):
    sys.stderr.write('Error: no command given, see --help for details\n')
    return 1

  model_file=args[0]
  # load the model
  log("Loading the model...")
  try:
    from Modeling import Model
    model=Model.loadModel(model_file)
    if not model:
      raise RuntimeError, "Abnormal: got no exception but Model is None"
  except Exception, exc:
    err("Serious: couldn't load the model")
    err(tracebackInfoFromStack(exc))
    return 3
  if user_connection_dict:
    model.setConnectionDictionary(user_connection_dict)

  # SQLite specifics, bug #785434 / #813297
  if model.adaptorName() == 'SQLite' and should_have_admin_dict:
    dsn_db_name = model.connectionDictionary()['database']
    admin_dsn_db_name = admin_connection_dict['database']
    if dsn_db_name != admin_dsn_db_name:
      raise ValueError, "Database name in the dsn (%s) and in the admin-dsn (%s) should be the same for SQLite"%(dsn_db_name, admin_dsn_db_name)
  
  from Modeling import ModelValidation
  from Modeling.ModelValidation import DEBUG,INFO,WARNING
  errors=MV.ModelValidationException(ignore_levels=[DEBUG,INFO,WARNING])
  MV.validateModel(model, errors)
  if errors.has_errors():
    _model_err_log=force_flag and log or err
    if verbose:
        _model_err_log("Error: model has errors:\n"+str(errors))
    else: _model_err_log("Error: model has errors (-v for details)")

    if not force_flag:
      err("Aborting")
      return 4
    else:
      log("Option --force set, continuing anyway...\n")

  result=databaseSchemaWithOptions(model, _defaultOptions,
                                   administrativeConnectionDictionary=admin_connection_dict,
                                   continue_on_errors=continue_on_errors,
                                   onlyStatements=to_stdout,
                                   endStatementWith=end_with_str)
  if to_stdout:
    print result

if __name__ == "__main__":
  status = main(sys.argv)
  sys.exit(status or 0)
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.