parent
327df551e8
commit
11662022be
|
@ -173,6 +173,7 @@ class DatabaseFeatures(BaseDatabaseFeatures):
|
||||||
supports_binary_field = six.PY2
|
supports_binary_field = six.PY2
|
||||||
supports_regex_backreferencing = False
|
supports_regex_backreferencing = False
|
||||||
supports_date_lookup_using_string = False
|
supports_date_lookup_using_string = False
|
||||||
|
can_introspect_autofield = True
|
||||||
can_introspect_binary_field = False
|
can_introspect_binary_field = False
|
||||||
can_introspect_small_integer_field = True
|
can_introspect_small_integer_field = True
|
||||||
supports_timezones = False
|
supports_timezones = False
|
||||||
|
|
|
@ -1,9 +1,11 @@
|
||||||
|
from collections import namedtuple
|
||||||
import re
|
import re
|
||||||
from .base import FIELD_TYPE
|
from .base import FIELD_TYPE
|
||||||
from django.utils.datastructures import OrderedSet
|
from django.utils.datastructures import OrderedSet
|
||||||
from django.db.backends import BaseDatabaseIntrospection, FieldInfo, TableInfo
|
from django.db.backends import BaseDatabaseIntrospection, FieldInfo, TableInfo
|
||||||
from django.utils.encoding import force_text
|
from django.utils.encoding import force_text
|
||||||
|
|
||||||
|
FieldInfo = namedtuple('FieldInfo', FieldInfo._fields + ('extra',))
|
||||||
|
|
||||||
foreign_key_re = re.compile(r"\sCONSTRAINT `[^`]*` FOREIGN KEY \(`([^`]*)`\) REFERENCES `([^`]*)` \(`([^`]*)`\)")
|
foreign_key_re = re.compile(r"\sCONSTRAINT `[^`]*` FOREIGN KEY \(`([^`]*)`\) REFERENCES `([^`]*)` \(`([^`]*)`\)")
|
||||||
|
|
||||||
|
@ -32,6 +34,12 @@ class DatabaseIntrospection(BaseDatabaseIntrospection):
|
||||||
FIELD_TYPE.VAR_STRING: 'CharField',
|
FIELD_TYPE.VAR_STRING: 'CharField',
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def get_field_type(self, data_type, description):
|
||||||
|
field_type = super(DatabaseIntrospection, self).get_field_type(data_type, description)
|
||||||
|
if field_type == 'IntegerField' and 'auto_increment' in description.extra:
|
||||||
|
return 'AutoField'
|
||||||
|
return field_type
|
||||||
|
|
||||||
def get_table_list(self, cursor):
|
def get_table_list(self, cursor):
|
||||||
"""
|
"""
|
||||||
Returns a list of table and view names in the current database.
|
Returns a list of table and view names in the current database.
|
||||||
|
@ -44,28 +52,33 @@ class DatabaseIntrospection(BaseDatabaseIntrospection):
|
||||||
"""
|
"""
|
||||||
Returns a description of the table, with the DB-API cursor.description interface."
|
Returns a description of the table, with the DB-API cursor.description interface."
|
||||||
"""
|
"""
|
||||||
# varchar length returned by cursor.description is an internal length,
|
# information_schema database gives more accurate results for some figures:
|
||||||
# not visible length (#5725), use information_schema database to fix this
|
# - varchar length returned by cursor.description is an internal length,
|
||||||
|
# not visible length (#5725)
|
||||||
|
# - precision and scale (for decimal fields) (#5014)
|
||||||
|
# - auto_increment is not available in cursor.description
|
||||||
|
InfoLine = namedtuple('InfoLine', 'col_name data_type max_len num_prec num_scale extra')
|
||||||
cursor.execute("""
|
cursor.execute("""
|
||||||
SELECT column_name, character_maximum_length FROM information_schema.columns
|
SELECT column_name, data_type, character_maximum_length, numeric_precision, numeric_scale, extra
|
||||||
WHERE table_name = %s AND table_schema = DATABASE()
|
FROM information_schema.columns
|
||||||
AND character_maximum_length IS NOT NULL""", [table_name])
|
WHERE table_name = %s AND table_schema = DATABASE()""", [table_name])
|
||||||
length_map = dict(cursor.fetchall())
|
field_info = dict((line[0], InfoLine(*line)) for line in cursor.fetchall())
|
||||||
|
|
||||||
# Also getting precision and scale from information_schema (see #5014)
|
|
||||||
cursor.execute("""
|
|
||||||
SELECT column_name, numeric_precision, numeric_scale FROM information_schema.columns
|
|
||||||
WHERE table_name = %s AND table_schema = DATABASE()
|
|
||||||
AND data_type='decimal'""", [table_name])
|
|
||||||
numeric_map = dict((line[0], tuple(int(n) for n in line[1:])) for line in cursor.fetchall())
|
|
||||||
|
|
||||||
cursor.execute("SELECT * FROM %s LIMIT 1" % self.connection.ops.quote_name(table_name))
|
cursor.execute("SELECT * FROM %s LIMIT 1" % self.connection.ops.quote_name(table_name))
|
||||||
return [FieldInfo(*((force_text(line[0]),)
|
to_int = lambda i: int(i) if i is not None else i
|
||||||
|
fields = []
|
||||||
|
for line in cursor.description:
|
||||||
|
col_name = force_text(line[0])
|
||||||
|
fields.append(
|
||||||
|
FieldInfo(*((col_name,)
|
||||||
+ line[1:3]
|
+ line[1:3]
|
||||||
+ (length_map.get(line[0], line[3]),)
|
+ (to_int(field_info[col_name].max_len) or line[3],
|
||||||
+ numeric_map.get(line[0], line[4:6])
|
to_int(field_info[col_name].num_prec) or line[4],
|
||||||
+ (line[6],)))
|
to_int(field_info[col_name].num_scale) or line[5])
|
||||||
for line in cursor.description]
|
+ (line[6],)
|
||||||
|
+ (field_info[col_name].extra,)))
|
||||||
|
)
|
||||||
|
return fields
|
||||||
|
|
||||||
def _name_to_index(self, cursor, table_name):
|
def _name_to_index(self, cursor, table_name):
|
||||||
"""
|
"""
|
||||||
|
|
Loading…
Reference in New Issue