Kaarsemaker.net


sqlviews.py
4.59 KB

102 lines

Download

sqlfixtables.py
auth_ldap.py

Preview

 1 # Copyright (c) 2009 Dennis Kaarsemaker <dennis@kaarsemaker.net>
 2 # All rights reserved.
 3 # 
 4 # Redistribution and use in source and binary forms, with or without modification,
 5 # are permitted provided that the following conditions are met:
 6 # 
 7 #     1. Redistributions of source code must retain the above copyright notice, 
 8 #        this list of conditions and the following disclaimer.
 9 #     
10 #     2. Redistributions in binary form must reproduce the above copyright 
11 #        notice, this list of conditions and the following disclaimer in the
12 #        documentation and/or other materials provided with the distribution.
13 # 
14 #     3. Neither the name of Django nor the names of its contributors may be used
15 #        to endorse or promote products derived from this software without
  1 # Copyright (c) 2009 Dennis Kaarsemaker <dennis@kaarsemaker.net>
  2 # All rights reserved.
  3 # 
  4 # Redistribution and use in source and binary forms, with or without modification,
  5 # are permitted provided that the following conditions are met:
  6 # 
  7 #     1. Redistributions of source code must retain the above copyright notice, 
  8 #        this list of conditions and the following disclaimer.
  9 #     
 10 #     2. Redistributions in binary form must reproduce the above copyright 
 11 #        notice, this list of conditions and the following disclaimer in the
 12 #        documentation and/or other materials provided with the distribution.
 13 # 
 14 #     3. Neither the name of Django nor the names of its contributors may be used
 15 #        to endorse or promote products derived from this software without
 16 #        specific prior written permission.
 17 # 
 18 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 19 # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 20 # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 21 # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
 22 # ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 23 # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 24 # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
 25 # ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 26 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 27 # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 28 
 29 from django.core.management.base import AppCommand
 30 
 31 def sql_create_views(app, style):
 32     from django.db import connection, models
 33     from django.conf import settings
 34 
 35     if settings.DATABASE_ENGINE == 'dummy':
 36         # This must be the "dummy" database backend, which means the user
 37         # hasn't set DATABASE_ENGINE.
 38         raise CommandError("Django doesn't know which syntax to use for your SQL statements,\n" +
 39             "because you haven't specified the DATABASE_ENGINE setting.\n" +
 40             "Edit your settings file and change DATABASE_ENGINE to something like 'postgresql' or 'mysql'.")
 41 
 42     app_models = models.get_models(app)
 43     final_output = []
 44 
 45     for model in app_models:
 46         if not model._meta.parents:
 47             continue # Not a multi-table-inheritance class
 48         final_output.append(connection.creation.sql_create_model_view(model, style))
 49     return final_output
 50 
 51 # Patch django.core.management.sql to know sql_create_views
 52 import django.core.management.sql
 53 django.core.management.sql.sql_create_views = sql_create_views
 54 
 55 def sql_create_model_view(self, model, style):
 56     import re
 57     qn = self.connection.ops.quote_name
 58     view = style.SQL_KEYWORD('CREATE VIEW') + ' ' + \
 59            style.SQL_TABLE(qn(model._meta.db_table + '_view')) + ' ' + \
 60            style.SQL_KEYWORD('AS') + '\n' + style.SQL_KEYWORD('SELECT') + '\n'
 61 
 62     fields_seen = []
 63     def hl(m,filter=True):
 64         table = style.SQL_TABLE(qn(m.group(1)))
 65         field = m.group(2)
 66         if field:
 67             if filter and (field in fields_seen or field.endswith('_ptr_id')):
 68                 return ''
 69             fields_seen.append(field)
 70             table += '.' + qn(style.SQL_FIELD(field))
 71         if filter:
 72             return '    %s,\n' % table
 73         return table
 74 
 75     # Use the query internals to create the SELECT query
 76     # Since that outputs quoted text, unquote it and mangle formatting
 77     # Slightly hackish but works
 78     query = model.objects.order_by().query
 79     query.pre_sql_setup()
 80     for col in query.get_columns():
 81         view += re.sub(r'%s\.%s' % (qn(r'(\S+?)'), qn(r'(\S+?)')), hl, col)
 82 
 83     view = view[:-2] + '\n' + style.SQL_KEYWORD('FROM')
 84     for clause in query.get_from_clause()[0]:
 85         clause = ' ' + re.sub(r'%s(?:\.%s)?' % (qn(r'(\S+?)'), qn(r'(\S+?)')), lambda m: hl(m, False), clause) + '\n'
 86         clause = clause.replace(' ON ', ' ' + style.SQL_KEYWORD('ON') + ' ')
 87         clause = clause.replace(' INNER JOIN ', '    ' + style.SQL_KEYWORD('INNER JOIN') + ' ')
 88         view += clause
 89     return view[:-1] + ';'
 90 
 91 # Patch django.db.backends.creation to know sql_create_model_view
 92 import django.db.backends.creation
 93 django.db.backends.creation.BaseDatabaseCreation.sql_create_model_view = sql_create_model_view
 94 
 95 class Command(AppCommand):
 96     help = "Print CREATE VIEW statements for multi-table inheritance models"
 97 
 98     output_transaction = True
 99 
100     def handle_app(self, app, **options):
101         from django.core.management.sql import sql_create_views
102         return u'\n'.join(sql_create_views(app, self.style)).encode('utf-8')

Show all