Commit 60d94c2a authored by Erik Romijn's avatar Erik Romijn
Browse files

Fixed #11442 -- Postgresql backend casts all inet types to text

parent 56d6fdbb
Loading
Loading
Loading
Loading
+5 −5
Original line number Diff line number Diff line
@@ -765,12 +765,12 @@ class BaseDatabaseOperations(object):
        """
        return cursor.fetchone()[0]

    def field_cast_sql(self, db_type):
    def field_cast_sql(self, db_type, internal_type):
        """
        Given a column type (e.g. 'BLOB', 'VARCHAR'), returns the SQL necessary
        to cast it before using it in a WHERE statement. Note that the
        resulting string should contain a '%s' placeholder for the column being
        searched against.
        Given a column type (e.g. 'BLOB', 'VARCHAR'), and an internal type
        (e.g. 'GenericIPAddressField'), returns the SQL necessary to cast it
        before using it in a WHERE statement. Note that the resulting string
        should contain a '%s' placeholder for the column being searched against.
        """
        return '%s'

+1 −1
Original line number Diff line number Diff line
@@ -254,7 +254,7 @@ WHEN (new.%(col_name)s IS NULL)
    def fetch_returned_insert_id(self, cursor):
        return int(cursor._insert_id_var.getvalue())

    def field_cast_sql(self, db_type):
    def field_cast_sql(self, db_type, internal_type):
        if db_type and db_type.endswith('LOB'):
            return "DBMS_LOB.SUBSTR(%s)"
        else:
+2 −2
Original line number Diff line number Diff line
@@ -78,8 +78,8 @@ class DatabaseOperations(BaseDatabaseOperations):

        return lookup

    def field_cast_sql(self, db_type):
        if db_type == 'inet':
    def field_cast_sql(self, db_type, internal_type):
        if internal_type == "GenericIPAddressField" or internal_type == "IPAddressField":
            return 'HOST(%s)'
        return '%s'

+5 −3
Original line number Diff line number Diff line
@@ -174,6 +174,8 @@ class WhereNode(tree.Node):
        it.
        """
        lvalue, lookup_type, value_annotation, params_or_value = child
        field_internal_type = lvalue.field.get_internal_type() if lvalue.field else None
        
        if isinstance(lvalue, Constraint):
            try:
                lvalue, params = lvalue.process(lookup_type, params_or_value, connection)
@@ -187,7 +189,7 @@ class WhereNode(tree.Node):

        if isinstance(lvalue, tuple):
            # A direct database column lookup.
            field_sql, field_params = self.sql_for_columns(lvalue, qn, connection), []
            field_sql, field_params = self.sql_for_columns(lvalue, qn, connection, field_internal_type), []
        else:
            # A smart object with an as_sql() method.
            field_sql, field_params = lvalue.as_sql(qn, connection)
@@ -257,7 +259,7 @@ class WhereNode(tree.Node):

        raise TypeError('Invalid lookup_type: %r' % lookup_type)

    def sql_for_columns(self, data, qn, connection):
    def sql_for_columns(self, data, qn, connection, internal_type=None):
        """
        Returns the SQL fragment used for the left-hand side of a column
        constraint (for example, the "T1.foo" portion in the clause
@@ -268,7 +270,7 @@ class WhereNode(tree.Node):
            lhs = '%s.%s' % (qn(table_alias), qn(name))
        else:
            lhs = qn(name)
        return connection.ops.field_cast_sql(db_type) % lhs
        return connection.ops.field_cast_sql(db_type, internal_type) % lhs

    def relabel_aliases(self, change_map):
        """
+3 −1
Original line number Diff line number Diff line
@@ -73,9 +73,11 @@ class StringLookupTests(TestCase):
        """
        Regression test for #708

        "like" queries on IP address fields require casting to text (on PostgreSQL).
        "like" queries on IP address fields require casting with HOST() (on PostgreSQL).
        """
        a = Article(name='IP test', text='The body', submitted_from='192.0.2.100')
        a.save()
        self.assertEqual(repr(Article.objects.filter(submitted_from__contains='192.0.2')),
            repr([a]))
        # Test that the searches do not match the subnet mask (/32 in this case)
        self.assertEqual(Article.objects.filter(submitted_from__contains='32').count(), 0)
 No newline at end of file