backported django postgres backend fixes

This commit is contained in:
Guillaume Andreu Sabater 2017-12-06 16:30:14 +01:00
parent 20c72782ce
commit 7239b91a47
3 changed files with 86 additions and 31 deletions

View File

@ -0,0 +1,20 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models, migrations
from django.conf import settings
class Migration(migrations.Migration):
dependencies = [
('dts_test_app', '0002_test_drop_unique'),
]
operations = [
migrations.AddField(
model_name='DummyModel',
name='indexed_value',
field=models.CharField(max_length=255, db_index=True),
),
]

View File

@ -0,0 +1,25 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models, migrations
from django.conf import settings
class Migration(migrations.Migration):
dependencies = [
('dts_test_app', '0003_test_add_db_index'),
]
operations = [
migrations.AlterField(
model_name='DummyModel',
name='indexed_value',
field=models.CharField(max_length=255, unique=True),
),
migrations.RemoveField(
model_name='DummyModel',
name='indexed_value',
),
]

View File

@ -5,6 +5,11 @@ from collections import namedtuple
from django.db.backends.base.introspection import (
BaseDatabaseIntrospection, FieldInfo, TableInfo,
)
try:
# Django >= 1.11
from django.db.models.indexes import Index
except ImportError:
Index = None
from django.utils.encoding import force_text
fields = FieldInfo._fields
@ -113,7 +118,8 @@ class DatabaseSchemaIntrospection(BaseDatabaseIntrospection):
FROM pg_attribute AS fka
JOIN pg_class AS fkc ON fka.attrelid = fkc.oid
WHERE fka.attrelid = c.confrelid
AND fka.attnum = c.confkey[1])
AND fka.attnum = c.confkey[1]),
cl.reloptions
FROM pg_constraint AS c
JOIN pg_class AS cl ON c.conrelid = cl.oid
JOIN pg_namespace AS ns ON cl.relnamespace = ns.oid
@ -135,35 +141,37 @@ class DatabaseSchemaIntrospection(BaseDatabaseIntrospection):
_get_index_constraints_query = """
SELECT
indexname, array_agg(attname), indisunique, indisprimary,
array_agg(ordering), amname, exprdef
indexname, array_agg(attname ORDER BY rnum), indisunique, indisprimary,
array_agg(ordering ORDER BY rnum), amname, exprdef, s2.attoptions
FROM (
SELECT
row_number() OVER () as rnum, c2.relname as indexname,
idx.*, attr.attname, am.amname,
CASE
WHEN idx.indexprs IS NOT NULL THEN
pg_get_indexdef(idx.indexrelid)
END AS exprdef,
CASE am.amname
WHEN 'btree' THEN
CASE (option & 1)
WHEN 1 THEN 'DESC' ELSE 'ASC'
END
END as ordering,
c2.reloptions as attoptions
FROM (
SELECT
c2.relname as indexname, idx.*, attr.attname, am.amname,
CASE
WHEN idx.indexprs IS NOT NULL THEN
pg_get_indexdef(idx.indexrelid)
END AS exprdef,
CASE am.amname
WHEN 'btree' THEN
CASE (option & 1)
WHEN 1 THEN 'DESC' ELSE 'ASC'
END
END as ordering
FROM (
SELECT
*, unnest(i.indkey) as key, unnest(i.indoption) as option
FROM pg_index i
) idx
LEFT JOIN pg_class c ON idx.indrelid = c.oid
LEFT JOIN pg_class c2 ON idx.indexrelid = c2.oid
LEFT JOIN pg_am am ON c2.relam = am.oid
LEFT JOIN pg_attribute attr ON attr.attrelid = c.oid AND attr.attnum = idx.key
LEFT JOIN pg_namespace n ON c.relnamespace = n.oid
WHERE c.relname = %(table)s
AND n.nspname = %(schema)s
) s2
GROUP BY indexname, indisunique, indisprimary, amname, exprdef;
*, unnest(i.indkey) as key, unnest(i.indoption) as option
FROM pg_index i
) idx
LEFT JOIN pg_class c ON idx.indrelid = c.oid
LEFT JOIN pg_class c2 ON idx.indexrelid = c2.oid
LEFT JOIN pg_am am ON c2.relam = am.oid
LEFT JOIN pg_attribute attr ON attr.attrelid = c.oid AND attr.attnum = idx.key
LEFT JOIN pg_namespace n ON c.relnamespace = n.oid
WHERE c.relname = %(table)s
AND n.nspname = %(schema)s
) s2
GROUP BY indexname, indisunique, indisprimary, amname, exprdef, attoptions;
"""
def get_field_type(self, data_type, description):
@ -274,7 +282,7 @@ class DatabaseSchemaIntrospection(BaseDatabaseIntrospection):
'table': table_name,
})
for constraint, columns, kind, used_cols in cursor.fetchall():
for constraint, columns, kind, used_cols, options in cursor.fetchall():
constraints[constraint] = {
"columns": columns,
"primary_key": kind == "p",
@ -283,6 +291,7 @@ class DatabaseSchemaIntrospection(BaseDatabaseIntrospection):
"check": kind == "c",
"index": False,
"definition": None,
"options": options,
}
# Now get indexes
@ -291,7 +300,7 @@ class DatabaseSchemaIntrospection(BaseDatabaseIntrospection):
'table': table_name,
})
for index, columns, unique, primary, orders, type_, definition in cursor.fetchall():
for index, columns, unique, primary, orders, type_, definition, options in cursor.fetchall():
if index not in constraints:
constraints[index] = {
"columns": columns if columns != [None] else [],
@ -301,7 +310,8 @@ class DatabaseSchemaIntrospection(BaseDatabaseIntrospection):
"foreign_key": None,
"check": False,
"index": True,
"type": type_,
"type": Index.suffix if type_ == 'btree' and Index else type_,
"definition": definition,
"options": options,
}
return constraints