Beispiel #1
0
    def sql_indexes_for_field(self, model, f, style):
        """
        Return the CREATE INDEX SQL statements for a single model field.
        """
        from djangocg.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:
                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
Beispiel #2
0
 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)
Beispiel #3
0
    def sql_for_pending_references(self, model, style, pending_references):
        """
        Returns any ALTER TABLE statements to add constraints after the fact.
        """
        from djangocg.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
Beispiel #4
0
    def contribute_to_class(self, cls, name):
        from djangocg.db import connection
        from djangocg.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)

        # 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))

            # 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())
Beispiel #5
0
 def sql_remove_table_constraints(self, model, references_to_delete, style):
     from djangocg.db.backends.util import truncate_name
     if not model._meta.managed or model._meta.proxy:
         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
Beispiel #6
0
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)
Beispiel #7
0
    def sql_indexes_for_field(self, model, f, style):
        "Return any spatial index creation SQL for the field."
        from djangocg.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
Beispiel #8
0
    def get_columns(self, with_aliases=False):
        """
        Returns the list of columns to use in the select statement. If no
        columns have been specified, returns all columns relating to fields in
        the model.

        If 'with_aliases' is true, any column names that are duplicated
        (without the table names) are given unique aliases. This is needed in
        some cases to avoid ambiguity with nested queries.
        """
        qn = self.quote_name_unless_alias
        qn2 = self.connection.ops.quote_name
        result = ['(%s) AS %s' % (col[0], qn2(alias)) for alias, col in six.iteritems(self.query.extra_select)]
        aliases = set(self.query.extra_select.keys())
        if with_aliases:
            col_aliases = aliases.copy()
        else:
            col_aliases = set()
        if self.query.select:
            only_load = self.deferred_to_columns()
            for col in self.query.select:
                if isinstance(col, (list, tuple)):
                    alias, column = col
                    table = self.query.alias_map[alias].table_name
                    if table in only_load and column not in only_load[table]:
                        continue
                    r = '%s.%s' % (qn(alias), qn(column))
                    if with_aliases:
                        if col[1] in col_aliases:
                            c_alias = 'Col%d' % len(col_aliases)
                            result.append('%s AS %s' % (r, c_alias))
                            aliases.add(c_alias)
                            col_aliases.add(c_alias)
                        else:
                            result.append('%s AS %s' % (r, qn2(col[1])))
                            aliases.add(r)
                            col_aliases.add(col[1])
                    else:
                        result.append(r)
                        aliases.add(r)
                        col_aliases.add(col[1])
                else:
                    result.append(col.as_sql(qn, self.connection))

                    if hasattr(col, 'alias'):
                        aliases.add(col.alias)
                        col_aliases.add(col.alias)

        elif self.query.default_cols:
            cols, new_aliases = self.get_default_columns(with_aliases,
                    col_aliases)
            result.extend(cols)
            aliases.update(new_aliases)

        max_name_length = self.connection.ops.max_name_length()
        result.extend([
            '%s%s' % (
                aggregate.as_sql(qn, self.connection),
                alias is not None
                    and ' AS %s' % qn(truncate_name(alias, max_name_length))
                    or ''
            )
            for alias, aggregate in self.query.aggregate_select.items()
        ])

        for table, col in self.query.related_select_cols:
            r = '%s.%s' % (qn(table), qn(col))
            if with_aliases and col in col_aliases:
                c_alias = 'Col%d' % len(col_aliases)
                result.append('%s AS %s' % (r, c_alias))
                aliases.add(c_alias)
                col_aliases.add(c_alias)
            else:
                result.append(r)
                aliases.add(r)
                col_aliases.add(col)

        self._select_aliases = aliases
        return result