def rename_column(self, model, old_field, new_field): if old_field.column == new_field.column: # No Operation return [] qn = self.connection.ops.quote_name max_name_length = self.connection.ops.max_name_length() opts = model._meta refs = {} models = [] return AlterTableSQLResult( self, model, pre_sql=self.remove_field_constraints(old_field, opts, models, refs), alter_table=[ { 'independent': True, 'sql': 'RENAME COLUMN %s TO %s' % (truncate_name(qn(old_field.column), max_name_length), truncate_name(qn(new_field.column), max_name_length)), }, ], post_sql=self.add_primary_key_field_constraints( old_field, new_field, models, refs) )
def sql_indexes_for_field(self, model, f, style): """ Create a CREATE INDEX sentence for custom fields. """ from django_orm.fields import standard as stdfields kwargs = VERSION[:2] >= (1, 3) and {'connection': self.connection} or {} if f.db_type(**kwargs) in ('hstore', 'tsvector'): if not f.db_index: return [] # create GIST index for hstore column qn = self.connection.ops.quote_name index_name = '%s_%s_gist' % (model._meta.db_table, f.column) clauses = [style.SQL_KEYWORD('CREATE INDEX'), style.SQL_TABLE(qn(truncate_name(index_name, self.connection.ops.max_name_length()))), style.SQL_KEYWORD('ON'), style.SQL_TABLE(qn(model._meta.db_table)), style.SQL_KEYWORD('USING GIST'), '(%s)' % style.SQL_FIELD(qn(f.column))] # add tablespace clause tablespace = f.db_tablespace or model._meta.db_tablespace if tablespace: sql = self.connection.ops.tablespace_sql(tablespace) if sql: clauses.append(sql) clauses.append(';') return [' '.join(clauses)] elif isinstance(f, stdfields.CharField): if not f.db_index: return [] output = super(DatabaseCreation, self).sql_indexes_for_field(model, f, style) qn = self.connection.ops.quote_name index_name0 = '%s_%s_idx%s_btree' % (model._meta.db_table, f.column, 0) index_name1 = '%s_%s_idx%s_btree' % (model._meta.db_table, f.column, 1) clauses0 = [style.SQL_KEYWORD('CREATE INDEX'), style.SQL_TABLE(qn(truncate_name(index_name0, self.connection.ops.max_name_length()))), style.SQL_KEYWORD('ON'), style.SQL_TABLE(qn(model._meta.db_table)), style.SQL_KEYWORD('USING BTREE'), '(unaccent(%s))' % style.SQL_FIELD(qn(f.column))] clauses1 = [style.SQL_KEYWORD('CREATE INDEX'), style.SQL_TABLE(qn(truncate_name(index_name1, self.connection.ops.max_name_length()))), style.SQL_KEYWORD('ON'), style.SQL_TABLE(qn(model._meta.db_table)), style.SQL_KEYWORD('USING BTREE'), '(lower(unaccent(%s)))' % style.SQL_FIELD(qn(f.column))] return output + [' '.join(clauses0) + ';'] + [' '.join(clauses1) + ';'] return super(DatabaseCreation, self).sql_indexes_for_field(model, f, style)
def sql_indexes_for_field(self, model, f, style): """Return the CREATE INDEX SQL statements for a single model field""" output = [] qn = self.connection.ops.quote_name max_name_length = self.connection.ops.max_name_length() # ignore tablespace information tablespace_sql = '' i = 0 if getattr(self.connection.connection, dbms_name) != 'DB2': if len(model._meta.unique_together_index) != 0: for unique_together_index in model._meta.unique_together_index: i += 1 column_list = [] for column in unique_together_index: for local_field in model._meta.local_fields: if column == local_field.name: column_list.extend([local_field.column]) self.__add_psudokey_column(style, self.connection.cursor(), model._meta.db_table, model._meta.pk.attname, column_list) column_list.extend( [truncate_name("%s%s" % ( self.psudo_column_prefix, "_".join(column_list) ), max_name_length)]) output.extend([style.SQL_KEYWORD('CREATE UNIQUE INDEX') + ' ' + \ style.SQL_TABLE(qn('db2_%s_%s' % ( model._meta.db_table, i ))) + ' ' + \ style.SQL_KEYWORD('ON') + ' ' + \ style.SQL_TABLE(qn(model._meta.db_table)) + ' ' + \ '( %s )' % ", ".join(column_list) + ' ' + \ '%s;' % tablespace_sql]) model._meta.unique_together_index = [] if f.unique_index: column_list = [] column_list.extend([f.column]) self.__add_psudokey_column(style, self.connection.cursor(), model._meta.db_table, model._meta.pk.attname, column_list) cisql = 'CREATE UNIQUE INDEX' output.extend([style.SQL_KEYWORD(cisql) + ' ' + style.SQL_TABLE(qn('%s_%s' % ( model._meta.db_table, f.column ))) + ' ' + style.SQL_KEYWORD('ON') + ' ' + style.SQL_TABLE(qn(model._meta.db_table)) + ' ' + "(%s, %s )" % (style.SQL_FIELD(qn(f.column)), style.SQL_FIELD( qn(truncate_name(( self.psudo_column_prefix + f.column ), max_name_length))) ) + "%s;" % tablespace_sql]) return output if f.db_index and not f.unique: cisql = 'CREATE INDEX' output.extend([style.SQL_KEYWORD(cisql) + ' ' + style.SQL_TABLE(qn('%s_%s' % ( model._meta.db_table, f.column ))) + ' ' + style.SQL_KEYWORD('ON') + ' ' + style.SQL_TABLE(qn(model._meta.db_table)) + ' ' + "(%s)" % style.SQL_FIELD(qn(f.column)) + "%s;" % tablespace_sql]) return output
def sql_for_pending_references(self, model, style, pending_references): "Returns any ALTER TABLE statements to add constraints after the fact." from django.db.backends.util import truncate_name if not model._meta.managed or model._meta.proxy: return [] qn = self.connection.ops.quote_name final_output = [] opts = model._meta if model in pending_references: for rel_class, f in pending_references[model]: rel_opts = rel_class._meta r_table = rel_opts.db_table r_col = f.column table = opts.db_table col = opts.get_field(f.rel.field_name).column if not hasattr(col, "columns"): # For MySQL, r_name must be unique in the first 64 characters. # So we are careful with character usage here. r_name = "%s_refs_%s_%s" % (r_col, col, self._digest(r_table, table)) final_output.append( style.SQL_KEYWORD("ALTER TABLE") + " %s ADD CONSTRAINT %s FOREIGN KEY (%s) REFERENCES %s (%s)%s;" % ( qn(r_table), qn(truncate_name(r_name, self.connection.ops.max_name_length())), qn(r_col), qn(table), qn(col), self.connection.ops.deferrable_sql(), ) ) else: try: r_col = "_".join(cf.column for cf in f.fields) col = "_".join(cf.column for cf in opts.pk.fields) r_name = "%s_refs_%s_%s" % (r_col, col, self._digest(r_table, table)) final_output.append( style.SQL_KEYWORD("ALTER TABLE") + " %s ADD CONSTRAINT %s FOREIGN KEY (%s) REFERENCES %s (%s)%s;" % ( qn(r_table), qn(truncate_name(r_name, self.connection.ops.max_name_length())), ", ".join([style.SQL_FIELD(qn(cf.column)) for cf in f.fields]), qn(table), ", ".join([style.SQL_FIELD(qn(cf.column)) for cf in opts.pk.fields]), self.connection.ops.deferrable_sql(), ) ) except: print "Skip constraint: TODO", rel_class, model del pending_references[model] return final_output
def rename_column(self, opts, old_field, new_field): if old_field.column == new_field.column: # No Operation return [] style = color.no_style() qn = self.connection.ops.quote_name max_name_length = self.connection.ops.max_name_length() creation = self.connection.creation sql = [] refs = {} models = [] if old_field.primary_key: for field in opts.local_many_to_many: if field.rel and field.rel.through: through = field.rel.through for m2m_f in through._meta.local_fields: if (m2m_f.rel and m2m_f.rel.to._meta.db_table == opts.db_table and m2m_f.rel.field_name == old_field.column): models.append(m2m_f.rel.to) refs.setdefault(m2m_f.rel.to, []).append( (through, m2m_f)) remove_refs = refs.copy() for relto in models: sql.extend(creation.sql_remove_table_constraints( relto, remove_refs, style)) params = (qn(opts.db_table), truncate_name(qn(old_field.column), max_name_length), truncate_name(qn(new_field.column), max_name_length)) sql.append('ALTER TABLE %s RENAME COLUMN %s TO %s;' % params) if old_field.primary_key: for relto in models: for rel_class, f in refs[relto]: f.rel.field_name = new_field.column del relto._meta._fields[old_field.name] relto._meta._fields[new_field.name] = new_field sql.extend(creation.sql_for_pending_references( relto, style, refs)) return sql
def sql_for_pending_references(self, model, style, pending_references): """ Returns any ALTER TABLE statements to add constraints after the fact. """ # Code copied from django.db.backends.creation.BaseDatabaseCreation in Django 1.6.0. # We always need to create every ForeignKey reference, # so no need to check _create_for_schema() opts = model._meta if not opts.managed or opts.swapped: return [] qn = self.connection.ops.quote_name final_output = [] if model in pending_references: for rel_class, f in pending_references[model]: rel_opts = rel_class._meta r_table = rel_opts.db_table r_col = f.column table = opts.db_table col = opts.get_field(f.rel.field_name).column # For MySQL, r_name must be unique in the first 64 characters. # So we are careful with character usage here. r_name = '%s_refs_%s_%s' % ( r_col, col, self._digest(r_table, table)) final_output.append(style.SQL_KEYWORD('ALTER TABLE') + ' %s%s ADD CONSTRAINT %s FOREIGN KEY (%s) REFERENCES %s%s (%s)%s;' % (self._table_prefix(rel_class), qn(r_table), qn(truncate_name( r_name, self.connection.ops.max_name_length())), qn(r_col), self._table_prefix(model), qn(table), qn(col), self.connection.ops.deferrable_sql())) del pending_references[model] return final_output
def sql_for_pending_references(self, model, style, pending_references): from django.db.backends.util import truncate_name opts = model._meta if not opts.managed or opts.proxy or opts.swapped: return [] qn = self.connection.ops.quote_name final_output = [] if model in pending_references: for rel_class, f in pending_references[model]: rel_opts = rel_class._meta r_table = rel_opts.db_table r_col = f.column table = opts.db_table col = opts.get_field(f.rel.field_name).column r_name = '%s_refs_%s_%s' % ( r_col, col, self._digest(r_table, table)) final_output.append(style.SQL_KEYWORD('ALTER TABLE') + ' %s ADD CONSTRAINT FOREIGN KEY (%s) REFERENCES %s (%s)%s CONSTRAINT %s;' % (qn(r_table), qn(r_col), qn(table), qn(col), self.connection.ops.deferrable_sql(), qn(truncate_name( r_name, self.connection.ops.max_name_length())))) del pending_references[model] return final_output
def get_default_index_name(self, table_name, field): """Returns a default index name for the database. This will return an index name for the given field that matches what the database or Django database backend would automatically generate when marking a field as indexed or unique. This can be overridden by subclasses if the database or Django database backend provides different values. """ assert field.unique or field.db_index if field.unique: index_name = field.column elif field.db_index: # This whole block of logic comes from sql_indexes_for_field # in django.db.backends.creation, and is designed to match # the logic for the past few versions of Django. if supports_index_together: # Starting in Django 1.5, the _digest is passed a raw # list. While this is probably a bug (digest should # expect a string), we still need to retain # compatibility. We know this behavior hasn't changed # as of Django 1.6.1. # # It also uses the field name, and not the column name. column = [field.name] else: column = field.column column = self.connection.creation._digest(column) index_name = '%s_%s' % (table_name, column) return truncate_name(index_name, self.connection.ops.max_name_length())
def deferred_class_factory(model, attrs, bulk_attrs): """ Returns a class object that is a copy of "model" with the specified "attrs" being replaced with BulkDeferredAttribute objects. The "pk_value" ties the deferred attributes to a particular instance of the model. """ class Meta: proxy = True app_label = model._meta.app_label # The app_cache wants a unique name for each model, otherwise the new class # won't be created (we get an old one back). Therefore, we generate the # name using the passed in attrs. It's OK to reuse an existing class # object if the attrs are identical. name = "%s_Deferred_%s" % (model.__name__, '_'.join(sorted(list(attrs | bulk_attrs)))) name = util.truncate_name(name, 80, 32) overrides = dict([(attr, BulkDeferredAttribute(attr, model)) for attr in bulk_attrs - attrs]) overrides.update(dict([(attr, DeferredAttribute(attr, model)) for attr in attrs])) overrides["Meta"] = Meta overrides["__module__"] = model.__module__ overrides["_deferred"] = True return type(name, (model,), overrides)
def sql_for_pending_references(model, style, pending_references): """ Returns any ALTER TABLE statements to add constraints after the fact. """ from django.db import connection from django.db.backends.util import truncate_name qn = connection.ops.quote_name final_output = [] if connection.features.supports_constraints: opts = model._meta if model in pending_references: for rel_class, f in pending_references[model]: rel_opts = rel_class._meta r_table = rel_opts.db_table r_col = f.column table = opts.db_table col = opts.get_field(f.rel.field_name).column # For MySQL, r_name must be unique in the first 64 characters. # So we are careful with character usage here. r_name = "%s_refs_%s_%x" % (r_col, col, abs(hash((r_table, table)))) final_output.append( style.SQL_KEYWORD("ALTER TABLE") + " %s ADD CONSTRAINT %s FOREIGN KEY (%s) REFERENCES %s (%s)%s;" % ( qn(r_table), truncate_name(r_name, connection.ops.max_name_length()), qn(r_col), qn(table), qn(col), connection.ops.deferrable_sql(), ) ) del pending_references[model] return final_output
def sql_indexes_for_field(self, model, f, style): kwargs = VERSION[:2] >= (1, 3) and {"connection": self.connection} or {} if f.db_type(**kwargs) == "hstore": if not f.db_index: return [] # create GIST index for hstore column qn = self.connection.ops.quote_name index_name = "%s_%s_gist" % (model._meta.db_table, f.column) clauses = [ style.SQL_KEYWORD("CREATE INDEX"), style.SQL_TABLE(qn(truncate_name(index_name, self.connection.ops.max_name_length()))), style.SQL_KEYWORD("ON"), style.SQL_TABLE(qn(model._meta.db_table)), style.SQL_KEYWORD("USING GIST"), "(%s)" % style.SQL_FIELD(qn(f.column)), ] # add tablespace clause tablespace = f.db_tablespace or model._meta.db_tablespace if tablespace: sql = self.connection.ops.tablespace_sql(tablespace) if sql: clauses.append(sql) clauses.append(";") return [" ".join(clauses)] return super(DatabaseCreation, self).sql_indexes_for_field(model, f, style)
def sql_indexes_for_field(self, model, f, style): kwargs = VERSION[:2] >= (1, 3) and {'connection': self.connection} or {} if f.db_type(**kwargs) == 'hstore': if not f.db_index: return [] # create GIST index for hstore column qn = self.connection.ops.quote_name index_name = '%s_%s_gist' % (model._meta.db_table, f.column) clauses = [style.SQL_KEYWORD('CREATE INDEX'), style.SQL_TABLE(qn(truncate_name(index_name, self.connection.ops.max_name_length()))), style.SQL_KEYWORD('ON'), style.SQL_TABLE(qn(model._meta.db_table)), style.SQL_KEYWORD('USING GIST'), '(%s)' % style.SQL_FIELD(qn(f.column))] # add tablespace clause tablespace = f.db_tablespace or model._meta.db_tablespace if tablespace: sql = self.connection.ops.tablespace_sql(tablespace) if sql: clauses.append(sql) clauses.append(';') return [ ' '.join(clauses) ] return super(DatabaseCreation, self).sql_indexes_for_field(model, f, style)
def sql_destroy_indexes_for_fields(self, model, fields, style): if len(fields) == 1 and fields[0].db_tablespace: tablespace_sql = self.connection.ops.tablespace_sql( fields[0].db_tablespace) elif model._meta.db_tablespace: tablespace_sql = self.connection.ops.tablespace_sql( model._meta.db_tablespace) else: tablespace_sql = "" if tablespace_sql: tablespace_sql = " " + tablespace_sql field_names = [] qn = self.connection.ops.quote_name for f in fields: field_names.append(style.SQL_FIELD(qn(f.column))) index_name = "%s_%s" % (model._meta.db_table, self._digest([f.name for f in fields])) from django.db.backends.util import truncate_name return [ style.SQL_KEYWORD("DROP INDEX") + " " + style.SQL_TABLE( qn( truncate_name(index_name, self.connection.ops.max_name_length()))) + " " + style.SQL_KEYWORD("ON") + " " + style.SQL_TABLE(qn(model._meta.db_table)) + ";", ]
def sql_destroy_indexes_for_fields(self, model, fields, style): # Django 1.6 if len(fields) == 1 and fields[0].db_tablespace: tablespace_sql = self.connection.ops.tablespace_sql( fields[0].db_tablespace) elif model._meta.db_tablespace: tablespace_sql = self.connection.ops.tablespace_sql( model._meta.db_tablespace) else: tablespace_sql = "" if tablespace_sql: tablespace_sql = " " + tablespace_sql field_names = [] qn = self.connection.ops.quote_name for f in fields: field_names.append(style.SQL_FIELD(qn(f.column))) index_name = "{0}_{1}".format(model._meta.db_table, self._digest([f.name for f in fields])) return [ style.SQL_KEYWORD("DROP INDEX") + " " + style.SQL_TABLE(qn(truncate_name(index_name, self.connection.ops.max_name_length()))) + " " + style.SQL_KEYWORD("ON") + " " + style.SQL_TABLE(qn(model._meta.db_table)) + ";", ]
def get_index_sql(index_name, opclass=''): return (style.SQL_KEYWORD('CREATE INDEX') + ' ' + style.SQL_TABLE(qn(truncate_name(index_name,self.connection.ops.max_name_length()))) + ' ' + style.SQL_KEYWORD('ON') + ' ' + style.SQL_TABLE(qn(db_table)) + ' ' + "(%s%s)" % (style.SQL_FIELD(qn(f.column)), opclass) + "%s;" % tablespace_sql)
def sql_for_pending_references(self, model, style, pending_references): """ Returns any ALTER TABLE statements to add constraints after the fact. """ opts = model._meta if not opts.managed or opts.proxy or opts.swapped: return [] qn = self.connection.ops.quote_name final_output = [] if model in pending_references: for rel_class, f in pending_references[model]: rel_opts = rel_class._meta r_table = rel_opts.db_table r_col = f.column table = opts.db_table col = opts.get_field(f.rel.field_name).column # For MySQL, r_name must be unique in the first 64 characters. # So we are careful with character usage here. r_name = '%s_refs_%s_%s' % ( r_col, col, self._digest(r_table, table)) if f.rel.on_delete == models.CASCADE: cascade = ' ON DELETE CASCADE ' else: cascade = '' final_output.append(style.SQL_KEYWORD('ALTER TABLE') + ' %s ADD CONSTRAINT %s FOREIGN KEY (%s) REFERENCES %s (%s)%s%s;' % (qn(r_table), qn(truncate_name( r_name, self.connection.ops.max_name_length())), qn(r_col), qn(table), qn(col), cascade, self.connection.ops.deferrable_sql())) del pending_references[model] return final_output
def sql_for_pending_references(self, model, style, pending_references): "Returns any ALTER TABLE statements to add constraints after the fact." from django.db.backends.util import truncate_name if not model._meta.managed or model._meta.proxy: return [] qn = self.connection.ops.quote_name final_output = [] opts = model._meta if model in pending_references: for rel_class, f in pending_references[model]: rel_opts = rel_class._meta r_table = rel_opts.db_table r_col = f.column table = opts.db_table col = opts.get_field(f.rel.field_name).column # For MySQL, r_name must be unique in the first 64 characters. # So we are careful with character usage here. r_name = '%s_refs_%s_%s' % (r_col, col, self._digest(r_table, table)) final_output.append(style.SQL_KEYWORD('ALTER TABLE') + ' %s ADD CONSTRAINT %s FOREIGN KEY (%s) REFERENCES %s (%s)%s;' % \ (qn(r_table), qn(truncate_name(r_name, self.connection.ops.max_name_length())), qn(r_col), qn(table), qn(col), self.connection.ops.deferrable_sql())) del pending_references[model] return final_output
def sql_indexes_for_field(self, model, f, style): "Return the CREATE INDEX SQL statements for a single model field" from django.db.backends.util import truncate_name if f.db_index and not f.unique: qn = self.connection.ops.quote_name tablespace = f.db_tablespace or model._meta.db_tablespace if tablespace: sql = self.connection.ops.tablespace_sql(tablespace) if sql: tablespace_sql = ' ' + sql else: tablespace_sql = '' else: tablespace_sql = '' i_name = '%s_%s' % (model._meta.db_table, self._digest(f.column)) output = [ style.SQL_KEYWORD('CREATE INDEX') + ' ' + style.SQL_TABLE( qn( truncate_name( i_name, self.connection.ops.max_name_length()))) + ' ' + style.SQL_KEYWORD('ON') + ' ' + style.SQL_TABLE(qn(model._meta.db_table)) + ' ' + "(%s)" % style.SQL_FIELD(qn(f.column)) + "%s;" % tablespace_sql ] else: output = [] return output
def sql_remove_table_constraints(self, model, references_to_delete, style): from django.db.backends.util import truncate_name if not model._meta.managed or model._meta.proxy or model._meta.swapped: return [] output = [] qn = self.connection.ops.quote_name '' for rel_class, f in references_to_delete[model]: table = rel_class._meta.db_table col = f.column r_table = model._meta.db_table r_col = model._meta.get_field(f.rel.field_name).column r_name = '%s_refs_%s_%s' % ( col, r_col, self._digest(table, r_table)) output.append('%s %s %s %s;' % \ (style.SQL_KEYWORD('ALTER TABLE'), style.SQL_TABLE(qn(table)), style.SQL_KEYWORD(self.connection.ops.drop_foreignkey_sql()), style.SQL_FIELD(qn(truncate_name( r_name, self.connection.ops.max_name_length()))))) del references_to_delete[model] 在引用列表中删除 return output
def sql_indexes_for_field(self, model, f, style): kwargs = VERSION[:2] >= (1, 3) and { 'connection': self.connection } or {} if f.db_type(**kwargs) == 'hstore': if not f.db_index: return [] # create GIST index for hstore column qn = self.connection.ops.quote_name index_name = '%s_%s_gist' % (model._meta.db_table, f.column) clauses = [ style.SQL_KEYWORD('CREATE INDEX'), style.SQL_TABLE( qn( truncate_name(index_name, self.connection.ops.max_name_length()))), style.SQL_KEYWORD('ON'), style.SQL_TABLE(qn(model._meta.db_table)), style.SQL_KEYWORD('USING GIST'), '(%s)' % style.SQL_FIELD(qn(f.column)) ] # add tablespace clause tablespace = f.db_tablespace or model._meta.db_tablespace if tablespace: sql = self.connection.ops.tablespace_sql(tablespace) if sql: clauses.append(sql) clauses.append(';') return [' '.join(clauses)] return super(DatabaseCreation, self).sql_indexes_for_field(model, f, style)
def sql_for_pending_references(self, model, style, pending_references): """ Returns any ALTER TABLE statements to add constraints after the fact. pg_django adds ON DELETE CASCADE if settings.DELETE_CASCADE is True """ from django.db.backends.util import truncate_name from django.db.models import CASCADE if not model._meta.managed or model._meta.proxy: return [] qn = self.connection.ops.quote_name final_output = [] opts = model._meta if model in pending_references: for rel_class, f in pending_references[model]: if getattr(settings, 'DB_CASCADE', False )and f.rel.on_delete == CASCADE: cascade = ' ON DELETE CASCADE' else: cascade = '' rel_opts = rel_class._meta r_table = rel_opts.db_table r_col = f.column table = opts.db_table col = opts.get_field(f.rel.field_name).column r_name = '%s_refs_%s_%s' % ( r_col, col, self._digest(r_table, table)) final_output.append(style.SQL_KEYWORD('ALTER TABLE') + ' %s ADD CONSTRAINT %s FOREIGN KEY (%s) REFERENCES %s (%s)%s%s;' % (qn(r_table), qn(truncate_name( r_name, self.connection.ops.max_name_length())), qn(r_col), qn(table), qn(col), cascade, self.connection.ops.deferrable_sql())) del pending_references[model] return final_output
def sql_indexes_for_field(self, model, f, style): "Return the CREATE INDEX SQL statements for a single model field" from django.db.backends.util import truncate_name if f.db_index and not f.unique: qn = self.connection.ops.quote_name tablespace = f.db_tablespace or model._meta.db_tablespace if tablespace: sql = self.connection.ops.tablespace_sql(tablespace) if sql: tablespace_sql = " " + sql else: tablespace_sql = "" else: tablespace_sql = "" i_name = "%s_%s" % (model._meta.db_table, self._digest(f.column)) output = [ style.SQL_KEYWORD("CREATE INDEX") + " " + style.SQL_TABLE(qn(truncate_name(i_name, self.connection.ops.max_name_length()))) + " " + style.SQL_KEYWORD("ON") + " " + style.SQL_TABLE(qn(model._meta.db_table)) + " " + "(%s)" % style.SQL_FIELD(qn(f.column)) + "%s;" % tablespace_sql ] else: output = [] return output
def _create_index_name(self, model, column_names, suffix=""): """ Generates a unique name for an index/unique constraint. """ # If there is just one column in the index, use a default algorithm from Django if len(column_names) == 1 and not suffix: return truncate_name( '%s_%s' % (model._meta.db_table, BaseDatabaseCreation._digest(column_names[0])), self.connection.ops.max_name_length()) # Else generate the name for the index using a different algorithm table_name = model._meta.db_table.replace('"', '').replace('.', '_') index_unique_name = '_%x' % abs( hash((table_name, ','.join(column_names)))) # If the index name is too long, truncate it index_name = ( '%s_%s%s%s' % (table_name, column_names[0], index_unique_name, suffix)).replace( '"', '').replace('.', '_') if len(index_name) > self.connection.features.max_index_name_length: part = ('_%s%s%s' % (column_names[0], index_unique_name, suffix)) index_name = '%s%s' % (table_name[:( self.connection.features.max_index_name_length - len(part))], part) # It shouldn't start with an underscore (Oracle hates this) if index_name[0] == "_": index_name = index_name[1:] # If it's STILL too long, just hash it down if len(index_name) > self.connection.features.max_index_name_length: index_name = hashlib.md5(index_name).hexdigest( )[:self.connection.features.max_index_name_length] # It can't start with a number on Oracle, so prepend D if we need to if index_name[0].isdigit(): index_name = "D%s" % index_name[:-1] return index_name
def _create_index_name(self, model, column_names, suffix=""): """ Generates a unique name for an index/unique constraint. """ # If there is just one column in the index, use a default algorithm from Django if len(column_names) == 1 and not suffix: return truncate_name( '%s_%s' % (model._meta.db_table, BaseDatabaseCreation._digest(column_names[0])), self.connection.ops.max_name_length() ) # Else generate the name for the index using a different algorithm table_name = model._meta.db_table.replace('"', '').replace('.', '_') index_unique_name = '_%x' % abs(hash((table_name, ','.join(column_names)))) # If the index name is too long, truncate it index_name = ('%s_%s%s%s' % (table_name, column_names[0], index_unique_name, suffix)).replace('"', '').replace('.', '_') if len(index_name) > self.connection.features.max_index_name_length: part = ('_%s%s%s' % (column_names[0], index_unique_name, suffix)) index_name = '%s%s' % (table_name[:(self.connection.features.max_index_name_length - len(part))], part) # It shouldn't start with an underscore (Oracle hates this) if index_name[0] == "_": index_name = index_name[1:] # If it's STILL too long, just hash it down if len(index_name) > self.connection.features.max_index_name_length: index_name = hashlib.md5(index_name).hexdigest()[:self.connection.features.max_index_name_length] # It can't start with a number on Oracle, so prepend D if we need to if index_name[0].isdigit(): index_name = "D%s" % index_name[:-1] return index_name
def _prepare(self, model): from django.db import connection from django.db.backends.util import truncate_name if self.order_with_respect_to: self.order_with_respect_to = self.get_field(self.order_with_respect_to) self.ordering = ('_order',) else: self.order_with_respect_to = None if self.pk is None: if self.parents: # Promote the first parent link in lieu of adding yet another # field. field = self.parents.value_for_index(0) field.primary_key = True self.pk = field else: auto = AutoField(verbose_name='ID', primary_key=True, auto_created=True) model.add_to_class('id', auto) # If the db_table wasn't provided, use the app_label + module_name. if not self.db_table: self.db_table = "%s_%s" % (self.app_label, self.module_name) self.db_table = truncate_name(self.db_table, connection.ops.max_name_length())
def _prepare(self, model): from django.db import connection from django.db.backends.util import truncate_name if self.order_with_respect_to: self.order_with_respect_to = self.get_field( self.order_with_respect_to) self.ordering = ('_order', ) else: self.order_with_respect_to = None if self.pk is None: if self.parents: # Promote the first parent link in lieu of adding yet another # field. field = self.parents.value_for_index(0) field.primary_key = True self.setup_pk(field) else: auto = AutoField(verbose_name='ID', primary_key=True, auto_created=True) model.add_to_class('id', auto) # If the db_table wasn't provided, use the app_label + module_name. if not self.db_table: self.db_table = "%s_%s" % (self.app_label, self.module_name) self.db_table = truncate_name(self.db_table, connection.ops.max_name_length())
def sql_indexes_for_fields(self, model, fields, style): if len(fields) == 1 and fields[0].db_tablespace: tablespace_sql = self.connection.ops.tablespace_sql(fields[0].db_tablespace) elif model._meta.db_tablespace: tablespace_sql = self.connection.ops.tablespace_sql(model._meta.db_tablespace) else: tablespace_sql = "" if tablespace_sql: tablespace_sql = " " + tablespace_sql field_names = [] qn = self.connection.ops.quote_name for f in fields: field_names.append(style.SQL_FIELD(qn(f.column))) index_name = "%s_%s" % (model._meta.db_table, self._digest([f.name for f in fields])) return [ style.SQL_KEYWORD("CREATE INDEX") + " " + style.SQL_TABLE(qn(truncate_name(index_name, self.connection.ops.max_name_length()))) + " " + style.SQL_KEYWORD("ON") + " " + style.SQL_TABLE(qn(model._meta.db_table)) + " " + "(%s)" % style.SQL_FIELD(", ".join(field_names)) + "%s;" % tablespace_sql, ]
def sql_indexes_for_field(self, model, f, style): """ Return the CREATE INDEX SQL statements for a single model field. """ from django.db.backends.util import truncate_name if f.db_index and not f.unique and not f.rel and not f.primary_key: qn = self.connection.ops.quote_name tablespace = f.db_tablespace or model._meta.db_tablespace if tablespace: tablespace_sql = self.connection.ops.tablespace_sql(tablespace) if tablespace_sql: tablespace_sql = ' ' + tablespace_sql else: tablespace_sql = '' i_name = '%s_%s' % (model._meta.db_table, self._digest(f.column)) output = [style.SQL_KEYWORD('CREATE INDEX') + ' ' + style.SQL_TABLE(qn(truncate_name( i_name, self.connection.ops.max_name_length()))) + ' ' + style.SQL_KEYWORD('ON') + ' ' + style.SQL_TABLE(qn(model._meta.db_table)) + ' ' + "(%s)" % style.SQL_FIELD(qn(f.column)) + "%s;" % tablespace_sql] else: output = [] return output
def contribute_to_class(self, cls, name): from django.db import connection from django.db.backends.util import truncate_name cls._meta = self self.installed = re.sub('\.models$', '', cls.__module__) in settings.INSTALLED_APPS # First, construct the default values for these options. self.object_name = cls.__name__ self.module_name = self.object_name.lower() self.verbose_name = get_verbose_name(self.object_name) self.pk = CompositePrimaryKey() # Next, apply any overridden values from 'class Meta'. if self.meta: meta_attrs = self.meta.__dict__.copy() # We have to delay setup of this because self.fields isn't populated yet self._primary_key = meta_attrs.pop('primary_key', []) for name in self.meta.__dict__: # Ignore any private attributes that Django doesn't care about. # NOTE: We can't modify a dictionary's contents while looping # over it, so we loop over the *original* dictionary instead. if name.startswith('_'): del meta_attrs[name] for attr_name in DEFAULT_NAMES: if attr_name in meta_attrs: setattr(self, attr_name, meta_attrs.pop(attr_name)) elif hasattr(self.meta, attr_name): setattr(self, attr_name, getattr(self.meta, attr_name)) # unique_together can be either a tuple of tuples, or a single # tuple of two strings. Normalize it to a tuple of tuples, so that # calling code can uniformly expect that. ut = meta_attrs.pop('unique_together', getattr(self, 'unique_together')) if ut and not isinstance(ut[0], (tuple, list)): ut = (ut, ) setattr(self, 'unique_together', ut) # verbose_name_plural is a special case because it uses a 's' # by default. setattr( self, 'verbose_name_plural', meta_attrs.pop('verbose_name_plural', string_concat(self.verbose_name, 's'))) # Any leftover attributes must be invalid. if meta_attrs != {}: raise TypeError, "'class Meta' got invalid attribute(s): %s" % ','.join( meta_attrs.keys()) else: self.verbose_name_plural = string_concat(self.verbose_name, 's') del self.meta # If the db_table wasn't provided, use the app_label + module_name. if not self.db_table: self.db_table = "%s_%s" % (self.app_label, self.module_name) self.db_table = truncate_name(self.db_table, connection.ops.max_name_length())
def contribute_to_class(self, cls, name): from django.db import connection from django.db.backends.util import truncate_name self.cls = cls cls._meta = self self.installed = re.sub('\.models$', '', cls.__module__) in settings.INSTALLED_APPS # First, construct the default values for these options. self.object_name = cls.__name__ self.module_name = self.object_name.lower() self._verbose_name = CAMEL_CASE_RE.sub(' \\1', self.object_name).lower().strip() # Next, apply any overridden values from 'class Meta'. if self.meta: meta_attrs = self.meta.__dict__.copy() for name in self.meta.__dict__: # Ignore any private attributes that Django doesn't care about. # NOTE: We can't modify a dictionary's contents while looping # over it, so we loop over the *original* dictionary instead. if name.startswith('_'): del meta_attrs[name] for attr_name in DEFAULT_NAMES: if attr_name in meta_attrs: setattr(self, attr_name, meta_attrs.pop(attr_name)) elif hasattr(self.meta, attr_name): setattr(self, attr_name, getattr(self.meta, attr_name)) for attr_name in DEPRECATED_NAMES: if attr_name in meta_attrs: warnings.warn("%(cls)s: Meta.%(attr_name)s is deprecated. Use a " "verbose_names() classmethod in the model " "instead." % {'cls': cls, 'attr_name': attr_name}, PendingDeprecationWarning) setattr(self, '_%s' % attr_name, meta_attrs.pop(attr_name)) # unique_together can be either a tuple of tuples, or a single # tuple of two strings. Normalize it to a tuple of tuples, so that # calling code can uniformly expect that. ut = meta_attrs.pop('unique_together', self.unique_together) if ut and not isinstance(ut[0], (tuple, list)): ut = (ut,) self.unique_together = ut # verbose_name_plural is a special case because it uses a 's' # by default. if self._verbose_name_plural is None: self._verbose_name_plural = string_concat(self._verbose_name, 's') # Any leftover attributes must be invalid. if meta_attrs != {}: raise TypeError("'class Meta' got invalid attribute(s): %s" % ','.join(meta_attrs.keys())) else: self._verbose_name_plural = string_concat(self._verbose_name, 's') del self.meta # If the db_table wasn't provided, use the app_label + module_name. if not self.db_table: self.db_table = "%s_%s" % (self.app_label, self.module_name) self.db_table = truncate_name(self.db_table, connection.ops.max_name_length())
def quote_name(self, name): # SQL92 requires delimited (quoted) names to be case-sensitive. When # not quoted, Oracle has case-insensitive behavior for identifiers, but # always defaults to uppercase. # We simplify things by making Oracle identifiers always uppercase. if not name.startswith('"') and not name.endswith('"'): name = '"%s"' % util.truncate_name(name.upper(), self.max_name_length()) return name.upper()
def configure(self): data = self.configured_data if not data['INVITER_DB_TABLE']: # from: django/db/models/options.py#L112 (django 1.4) app, module = data['INVITER_CLASS'].lower().split('.') db_table_long = '{}_{}'.format(app, module) data['INVITER_DB_TABLE'] = truncate_name( db_table_long, connection.ops.max_name_length()) return data
def sql_for_many_to_many_field(self, model, f, style): "Return the CREATE TABLE statements for a single m2m field" from django.db import models from django.db.backends.util import truncate_name output = [] if f.creates_table: opts = model._meta qn = self.connection.ops.quote_name tablespace = f.db_tablespace or opts.db_tablespace if tablespace: sql = self.connection.ops.tablespace_sql(tablespace, inline=True) if sql: tablespace_sql = ' ' + sql else: tablespace_sql = '' else: tablespace_sql = '' table_output = [style.SQL_KEYWORD('CREATE TABLE') + ' ' + \ style.SQL_TABLE(qn(f.m2m_db_table())) + ' ('] table_output.append(' %s %s %s%s,' % (style.SQL_FIELD(qn('id')), style.SQL_COLTYPE(models.AutoField(primary_key=True).db_type()), style.SQL_KEYWORD('NOT NULL PRIMARY KEY'), tablespace_sql)) deferred = [] inline_output, deferred = self.sql_for_inline_many_to_many_references(model, f, style) table_output.extend(inline_output) table_output.append(' %s (%s, %s)%s' % (style.SQL_KEYWORD('UNIQUE'), style.SQL_FIELD(qn(f.m2m_column_name())), style.SQL_FIELD(qn(f.m2m_reverse_name())), tablespace_sql)) table_output.append(')') if opts.db_tablespace: # f.db_tablespace is only for indices, so ignore its value here. table_output.append(self.connection.ops.tablespace_sql(opts.db_tablespace)) table_output.append(';') output.append('\n'.join(table_output)) for r_table, r_col, table, col in deferred: r_name = '%s_refs_%s_%x' % (r_col, col, abs(hash((r_table, table)))) output.append(style.SQL_KEYWORD('ALTER TABLE') + ' %s ADD CONSTRAINT %s FOREIGN KEY (%s) REFERENCES %s (%s)%s;' % (qn(r_table), qn(truncate_name(r_name, self.connection.ops.max_name_length())), qn(r_col), qn(table), qn(col), self.connection.ops.deferrable_sql())) # Add any extra SQL needed to support auto-incrementing PKs autoinc_sql = self.connection.ops.autoinc_sql(f.m2m_db_table(), 'id') if autoinc_sql: for stmt in autoinc_sql: output.append(stmt) return output
def _get_m2m_db_table(self, opts): "Function that can be curried to provide the m2m table name for this relation" if self.rel.through is not None: return self.rel.through_model._meta.db_table elif self.db_table: return self.db_table else: return util.truncate_name('%s_%s' % (opts.db_table, self.name), connection.ops.max_name_length())
def get_default_index_name(self, table_name, field): assert field.unique or field.db_index if field.unique: index_name = '%s_%s_key' % (table_name, field.column) elif field.db_index: index_name = '%s_%s' % (table_name, field.column) return truncate_name(index_name, self.connection.ops.max_name_length())
def quote_name(self, name, upper=True, column = False, check_m2m = True): if not column: if check_m2m: name = self.check_m2m(name) if self.check_meta(name): #replication of Django flow for models where Meta.db_table is set by user name = name.upper() tn = truncate_name(name, connection.ops.max_name_length()) return upper and tn.upper() or tn.lower()
def sql_for_many_to_many_field(self, model, f, style): "Return the CREATE TABLE statements for a single m2m field" from django.db import models from django.db.backends.util import truncate_name output = [] if f.creates_table: opts = model._meta qn = self.connection.ops.quote_name tablespace = f.db_tablespace or opts.db_tablespace if tablespace: sql = self.connection.ops.tablespace_sql(tablespace, inline=True) if sql: tablespace_sql = ' ' + sql else: tablespace_sql = '' else: tablespace_sql = '' table_output = [style.SQL_KEYWORD('CREATE TABLE') + ' ' + \ style.SQL_TABLE(qn(f.m2m_db_table())) + ' ('] table_output.append(' %s %s %s%s,' % (style.SQL_FIELD(qn('id')), style.SQL_COLTYPE(models.AutoField(primary_key=True).db_type()), style.SQL_KEYWORD('NOT NULL PRIMARY KEY'), tablespace_sql)) deferred = [] inline_output, deferred = self.sql_for_inline_many_to_many_references(model, f, style) table_output.extend(inline_output) table_output.append(' %s (%s, %s)%s' % (style.SQL_KEYWORD('UNIQUE'), style.SQL_FIELD(qn(f.m2m_column_name())), style.SQL_FIELD(qn(f.m2m_reverse_name())), tablespace_sql)) table_output.append(')') if opts.db_tablespace: # f.db_tablespace is only for indices, so ignore its value here. table_output.append(self.connection.ops.tablespace_sql(opts.db_tablespace)) table_output.append(';') output.append('\n'.join(table_output)) for r_table, r_col, table, col in deferred: r_name = '%s_refs_%s_%x' % (r_col, col, abs(hash((r_table, table)))) output.append(style.SQL_KEYWORD('ALTER TABLE') + ' %s ADD CONSTRAINT %s FOREIGN KEY (%s) REFERENCES %s (%s)%s;' % (qn(r_table), truncate_name(r_name, self.connection.ops.max_name_length()), qn(r_col), qn(table), qn(col), self.connection.ops.deferrable_sql())) # Add any extra SQL needed to support auto-incrementing PKs autoinc_sql = self.connection.ops.autoinc_sql(f.m2m_db_table(), 'id') if autoinc_sql: for stmt in autoinc_sql: output.append(stmt) return output
def foreign_key_sql(self, from_table_name, from_column_name, to_table_name, to_column_name): """ Generates a full SQL statement to add a foreign key constraint """ constraint_name = '%s_refs_%s_%x' % (from_column_name, to_column_name, abs(hash((from_table_name, to_table_name)))) return 'ALTER TABLE %s ADD CONSTRAINT %s FOREIGN KEY (%s) REFERENCES %s (%s)%s;' % ( self.quote_name(from_table_name), self.quote_name(truncate_name(constraint_name, self._get_connection().ops.max_name_length())), self.quote_name(from_column_name), self.quote_name(to_table_name), self.quote_name(to_column_name), self._get_connection().ops.deferrable_sql() # Django knows this )
def _geom_index(self, style, db_table): "Creates an Oracle Geometry index (R-tree) for this geometry field." # Getting the index name, Oracle doesn't allow object # names > 30 characters. idx_name = truncate_name('%s_%s_id' % (db_table, self.column), 30) sql = (style.SQL_KEYWORD('CREATE INDEX ') + style.SQL_TABLE(qn(idx_name)) + style.SQL_KEYWORD(' ON ') + style.SQL_TABLE(qn(db_table)) + '(' + style.SQL_FIELD(qn(self.column)) + ') ' + style.SQL_KEYWORD('INDEXTYPE IS ') + style.SQL_TABLE('MDSYS.SPATIAL_INDEX') + ';') return sql
def makeAutoCreateIndexName(cls, column): """Syncdbで自動的に作られるインデクス名を偽造. """ if BaseModel._style is None: from django.core.management.color import no_style BaseModel._style = no_style() from django.db import connections connection = connections[settings.DB_DEFAULT] qn = connection.ops.quote_name index_name = '%s_%s' % (cls.get_tablename(), ('%x' % (abs(hash((column, ))) % 4294967296L))) return BaseModel._style.SQL_TABLE( qn(truncate_name(index_name, connection.ops.max_name_length())))
def alterFieldDataTypeByRemaking(self, model, old_field, new_field, strict): tmp_new_field = copy.deepcopy(new_field) tmp_new_field.column = truncate_name( "%s%s" % (self.psudo_column_prefix, tmp_new_field.column), self.connection.ops.max_name_length()) self.add_field(model, tmp_new_field) #Transfer data from old field to new tmp field self.execute("UPDATE %s set %s=%s" % (self.quote_name( model._meta.db_table), self.quote_name( tmp_new_field.column), self.quote_name(old_field.column))) self.remove_field(model, old_field) return tmp_new_field, new_field
def create_index_name(self, table_name, column_names, suffix=""): """ Generate a unique name for the index Django's logic for naming field indexes is different in the postgresql_psycopg2 backend, so we follow that for single-column indexes. """ if len(column_names) == 1: return truncate_name( '%s_%s%s' % (table_name, column_names[0], suffix), self._get_connection().ops.max_name_length() ) return super(DatabaseOperations, self).create_index_name(table_name, column_names, suffix)
def sql_for_pending_references(self, model, style, pending_references): """ Returns any ALTER TABLE statements to add constraints after the fact. """ from django.db.backends.util import truncate_name opts = model._meta if not opts.managed or opts.swapped: return [] qn = self.connection.ops.quote_name final_output = [] if model in pending_references: for rel_class, f in pending_references[model]: rel_opts = rel_class._meta r_table = rel_opts.db_table r_col = f.column table = opts.db_table col = opts.get_field(f.rel.field_name).column if not hasattr(col, "columns"): # For MySQL, r_name must be unique in the first 64 characters. # So we are careful with character usage here. r_name = '%s_refs_%s_%s' % (r_col, col, self._digest(r_table, table)) final_output.append( style.SQL_KEYWORD('ALTER TABLE') + ' %s ADD CONSTRAINT %s FOREIGN KEY (%s) REFERENCES %s (%s)%s;' % (qn(r_table), qn( truncate_name( r_name, self.connection.ops.max_name_length())), qn(r_col), qn(table), qn(col), self.connection.ops.deferrable_sql())) else: try: r_col = "_".join(cf.column for cf in f.fields) col = "_".join(cf.column for cf in opts.pk.fields) r_name = '%s_refs_%s_%s' % (r_col, col, self._digest(r_table, table)) final_output.append(style.SQL_KEYWORD('ALTER TABLE') + ' %s ADD CONSTRAINT %s FOREIGN KEY (%s) REFERENCES %s (%s)%s;' %\ (qn(r_table), qn(truncate_name(r_name, self.connection.ops.max_name_length())), ", ".join([style.SQL_FIELD(qn(cf.column)) for cf in f.fields]), qn(table), ", ".join([style.SQL_FIELD(qn(cf.column)) for cf in opts.pk.fields]), self.connection.ops.deferrable_sql())) except: print "Skip constraint: TODO", rel_class, model del pending_references[model] return final_output
def rename_table(self, model, old_db_tablename, db_tablename): if old_db_tablename == db_tablename: # No Operation return [] style = color.no_style() qn = self.connection.ops.quote_name max_name_length = self.connection.ops.max_name_length() creation = self.connection.creation sql = [] refs = {} models = [] for field in model._meta.local_many_to_many: if (field.rel and field.rel.through and field.rel.through._meta.db_table == old_db_tablename): through = field.rel.through for m2m_field in through._meta.local_fields: if m2m_field.rel and m2m_field.rel.to == model: models.append(m2m_field.rel.to) refs.setdefault(m2m_field.rel.to, []).append( (through, m2m_field)) remove_refs = refs.copy() for relto in models: sql.extend( creation.sql_remove_table_constraints(relto, remove_refs, style)) params = (qn(old_db_tablename), qn(db_tablename)) sql.append('ALTER TABLE %s RENAME TO %s;' % params) for relto in models: for rel_class, f in refs[relto]: if rel_class._meta.db_table == old_db_tablename: rel_class._meta.db_table = db_tablename rel_class._meta.db_table = \ truncate_name(rel_class._meta.db_table, max_name_length) sql.extend(creation.sql_for_pending_references(relto, style, refs)) return sql
def __add_psudokey_column(self, style, cursor, table_name, pk_name, column_list): qn = self.connection.ops.quote_name max_name_length = self.connection.ops.max_name_length() sql = style.SQL_KEYWORD( 'ALTER TABLE ' ) + \ style.SQL_TABLE( qn( table_name ) ) + \ style.SQL_KEYWORD( ' ADD COLUMN ' ) + \ style.SQL_FIELD( qn( truncate_name( "%s%s" % ( self.psudo_column_prefix, "_".join( column_list ) ), max_name_length ) ) ) + \ style.SQL_KEYWORD( ' GENERATED ALWAYS AS( CASE WHEN ' ) + \ style.SQL_FIELD( "%s %s" % ( " IS NULL OR ".join( column_list ), 'IS NULL THEN ' ) ) + \ style.SQL_FIELD( qn( pk_name ) ) + \ style.SQL_KEYWORD( ' END ) ;' ) cursor.execute('SET INTEGRITY FOR ' + style.SQL_TABLE(qn(table_name)) + ' OFF CASCADE DEFERRED;') cursor.execute(sql) cursor.execute('SET INTEGRITY FOR ' + style.SQL_TABLE(table_name) + ' IMMEDIATE CHECKED;') cursor.close()
def sql_indexes_for_field(self, model, f, style): "Return any spatial index creation SQL for the field." from django.contrib.gis.db.models.fields import GeometryField output = super(OracleCreation, self).sql_indexes_for_field(model, f, style) if isinstance(f, GeometryField): gqn = self.connection.ops.geo_quote_name qn = self.connection.ops.quote_name db_table = model._meta.db_table output.append( style.SQL_KEYWORD('INSERT INTO ') + style.SQL_TABLE('USER_SDO_GEOM_METADATA') + ' (%s, %s, %s, %s)\n ' % tuple(map(qn, ['TABLE_NAME', 'COLUMN_NAME', 'DIMINFO', 'SRID']) ) + style.SQL_KEYWORD(' VALUES ') + '(\n ' + style.SQL_TABLE(gqn(db_table)) + ',\n ' + style.SQL_FIELD(gqn(f.column)) + ',\n ' + style.SQL_KEYWORD("MDSYS.SDO_DIM_ARRAY") + '(\n ' + style.SQL_KEYWORD("MDSYS.SDO_DIM_ELEMENT") + ("('LONG', %s, %s, %s),\n " % (f._extent[0], f._extent[2], f._tolerance)) + style.SQL_KEYWORD("MDSYS.SDO_DIM_ELEMENT") + ("('LAT', %s, %s, %s)\n ),\n" % (f._extent[1], f._extent[3], f._tolerance)) + ' %s\n );' % f.srid) if f.spatial_index: # Getting the index name, Oracle doesn't allow object # names > 30 characters. idx_name = truncate_name('%s_%s_id' % (db_table, f.column), 30) output.append( style.SQL_KEYWORD('CREATE INDEX ') + style.SQL_TABLE(qn(idx_name)) + style.SQL_KEYWORD(' ON ') + style.SQL_TABLE(qn(db_table)) + '(' + style.SQL_FIELD(qn(f.column)) + ') ' + style.SQL_KEYWORD('INDEXTYPE IS ') + style.SQL_TABLE('MDSYS.SPATIAL_INDEX') + ';') return output
def _prepare(self, model): from django.db import connection from django.db.backends.util import truncate_name if self.order_with_respect_to: self.order_with_respect_to = self.get_field( self.order_with_respect_to) self.ordering = ('_order', ) else: self.order_with_respect_to = None if self.pk is None: auto = AutoField(verbose_name='ID', primary_key=True) auto.creation_counter = -1 model.add_to_class('id', auto) # If the db_table wasn't provided, use the app_label + module_name. if not self.db_table: self.db_table = "%s_%s" % (self.app_label, self.module_name) self.db_table = truncate_name(self.db_table, connection.ops.max_name_length())
def change_unique(self, model, field_name, new_unique_value, initial=None): qn = self.connection.ops.quote_name opts = model._meta f = opts.get_field(field_name) constraint_name = truncate_name( '%s_%s_key' % (opts.db_table, f.column), self.connection.ops.max_name_length()) if new_unique_value: params = ( qn(opts.db_table), constraint_name, qn(f.column), ) return ['ALTER TABLE %s ADD CONSTRAINT %s UNIQUE(%s);' % params] else: params = ( qn(opts.db_table), constraint_name, ) return ['ALTER TABLE %s DROP CONSTRAINT %s;' % params]
def sql_indexes_for_field(self, connection, model, f, style): # create GIST index for hstore column qn = connection.ops.quote_name index_name = '%s_%s_gist' % (model._meta.db_table, f.column) clauses = [ style.SQL_KEYWORD('CREATE INDEX'), style.SQL_TABLE( qn(truncate_name(index_name, connection.ops.max_name_length()))), style.SQL_KEYWORD('ON'), style.SQL_TABLE(qn(model._meta.db_table)), style.SQL_KEYWORD('USING GIST'), '(%s)' % style.SQL_FIELD(qn(f.column)) ] # add tablespace clause tablespace = f.db_tablespace or model._meta.db_tablespace if tablespace: sql = connection.ops.tablespace_sql(tablespace) if sql: clauses.append(sql) clauses.append(';') return [' '.join(clauses)]
def deferred_class_factory(model, attrs): """ Returns a class object that is a copy of "model" with the specified "attrs" being replaced with DeferredAttribute objects. The "pk_value" ties the deferred attributes to a particular instance of the model. """ class Meta: proxy = True app_label = model._meta.app_label # The app_cache wants a unique name for each model, otherwise the new class # won't be created (we get an old one back). Therefore, we generate the # name using the passed in attrs. It's OK to reuse an existing class # object if the attrs are identical. name = "%s_Deferred_%s" % (model.__name__, '_'.join(sorted(list(attrs)))) name = util.truncate_name(name, 80, 32) overrides = dict((attr, DeferredAttribute(attr, model)) for attr in attrs) overrides["Meta"] = Meta overrides["__module__"] = model.__module__ overrides["_deferred"] = True return type(str(name), (model, ), overrides)
def shorten_name(self, name): return truncate_name(name, self._get_connection().ops.max_name_length())